在使用 cairo  绘制文本时,发现它不能绘制多行文本,搜索到官网 [cairo] automatic multi-line text?,它说需要使用 Pango库,这就痛苦了。

于是研究了一下cairo源码,自己实现了一下。附上函数:

#define HAVE_STDINT_H 1
#define HAVE_CONFIG_H 1
#include "cairo/cairo-private.h"
#include "cairo/cairo-compiler-private.h"
#include "cairo/cairo-error-private.h"
#include "cairo/cairo-fontconfig-private.h"
#include "cairo/cairo-scaled-font-private.h"
#include "cairo/cairoint.h"
#include "cairo/cairo-backend-private.h"void CCairo::show_multiline_utf8(const char* utf8, int utf8_len, LPRECT lprc, const char* szFontname, int nFontSize, DWORD dtFormat, bool bold)
{cairo_text_extents_t extents;cairo_status_t status;cairo_glyph_t* glyphs = NULL, * last_glyph = NULL;cairo_text_cluster_t* clusters = NULL;int num_glyphs, num_clusters;cairo_text_cluster_flags_t cluster_flags;cairo_bool_t has_show_text_glyphs;cairo_glyph_t stack_glyphs[CAIRO_STACK_ARRAY_LENGTH(cairo_glyph_t)];cairo_text_cluster_t stack_clusters[CAIRO_STACK_ARRAY_LENGTH(cairo_text_cluster_t)];cairo_scaled_font_t* scaled_font;cairo_glyph_text_info_t info, * i;cairo_select_font_face(cr, szFontname, CAIRO_FONT_SLANT_NORMAL,bold? CAIRO_FONT_WEIGHT_BOLD : CAIRO_FONT_WEIGHT_NORMAL);cairo_set_font_size(cr, nFontSize);RECT rc;CopyRect(&rc, lprc);double y = rc.top;double x = rc.left;if (unlikely(cr->status))return;if (utf8 == NULL)return;if (utf8_len <= 0){utf8_len = strlen(utf8);}if (utf8_len <= 0)return;double x1, x2, y1, y2, font_height, x_offset;    x1 = rc.left;y1 = rc.top;x2 = rc.right;y2 = rc.bottom;scaled_font = cairo_get_scaled_font(cr);if (unlikely(scaled_font->status)) {      return;}cairo_scaled_font_text_extents(scaled_font, utf8, &extents);y += extents.height;cairo_move_to(cr, x, y);font_height = extents.height;has_show_text_glyphs =cairo_surface_has_show_text_glyphs(cairo_get_target(cr));glyphs = stack_glyphs;num_glyphs = ARRAY_LENGTH(stack_glyphs);if (has_show_text_glyphs) {clusters = stack_clusters;num_clusters = ARRAY_LENGTH(stack_clusters);}else {clusters = NULL;num_clusters = 0;}cairo_get_current_point(cr, &x, &y);status = cairo_scaled_font_text_to_glyphs(scaled_font,x, y,utf8, utf8_len,&glyphs, &num_glyphs,has_show_text_glyphs ? &clusters : NULL, &num_clusters,&cluster_flags);if (unlikely(status)){if (glyphs && glyphs != stack_glyphs)cairo_glyph_free(glyphs);if (clusters && clusters != stack_clusters)cairo_text_cluster_free(clusters);if (unlikely(status))_cairo_status_set_error(&cr->status, _cairo_error(status));return;}if (num_glyphs == 0)return;i = NULL;if (has_show_text_glyphs) {info.utf8 = utf8;info.utf8_len = utf8_len;info.clusters = clusters;info.num_clusters = num_clusters;info.cluster_flags = cluster_flags;i = &info;}int line_head = 0;int line_no = 0;for (int n = 0; n < num_glyphs; n++){last_glyph = &glyphs[n];status = cr->backend->glyph_extents(cr, last_glyph, 1, &extents);if (unlikely(status)){if (glyphs && glyphs != stack_glyphs)cairo_glyph_free(glyphs);if (clusters && clusters != stack_clusters)cairo_text_cluster_free(clusters);if (unlikely(status))_cairo_status_set_error(&cr->status, _cairo_error(status));return;}if (last_glyph->x + extents.x_advance >= x2){//本行需要计算右对齐double dj = 0.0;if (n > line_head) //2个字以上,分散对齐{cairo_text_extents_t exts;cr->backend->glyph_extents(cr, &glyphs[n - 1], 1, &exts);dj = (x2 - (glyphs[n - 1].x + exts.width)) / (n - line_head);cr->backend->glyph_extents(cr, &glyphs[line_head], n - line_head, &exts);double dj2 = ((x2 - x1) - exts.width) / (n - line_head);for (int m = line_head; m < n; m++){glyphs[m].x += dj * (m - line_head);}}//换行,并调整后续行位置x_offset = last_glyph->x - x;y += font_height + 2;for (int m = n; m < num_glyphs; m++){glyphs[m].x -= x_offset;glyphs[m].y = y;}if (y - extents.height >= y2){num_glyphs = n;break;}line_no++;line_head = n;}}//cairo_show_glyphsstatus = cr->backend->glyphs(cr, glyphs, num_glyphs, i);if (unlikely(status)){if (glyphs && glyphs != stack_glyphs)cairo_glyph_free(glyphs);if (clusters && clusters != stack_clusters)cairo_text_cluster_free(clusters);if (unlikely(status))_cairo_status_set_error(&cr->status, _cairo_error(status));return;}last_glyph = &glyphs[num_glyphs - 1];//cairo_glyph_extentsstatus = cr->backend->glyph_extents(cr, last_glyph, 1, &extents);if (unlikely(status)){if (glyphs && glyphs != stack_glyphs)cairo_glyph_free(glyphs);if (clusters && clusters != stack_clusters)cairo_text_cluster_free(clusters);if (unlikely(status))_cairo_status_set_error(&cr->status, _cairo_error(status));return;}x = last_glyph->x + extents.x_advance;y = last_glyph->y + extents.y_advance;cr->backend->move_to(cr, x, y);if (glyphs && glyphs != stack_glyphs)cairo_glyph_free(glyphs);if (clusters && clusters != stack_clusters)cairo_text_cluster_free(clusters);if (unlikely(status))_cairo_status_set_error(&cr->status, _cairo_error(status));
}

cairo显示多行文本相关推荐

  1. outlook可以显示多少行文本_Linux学习从处理文本开始

    在Linux世界一切皆文件,而且绝大多数都是文本文件.Shell是强大的用户界面,其强大之处在于Shell中自带了大量的文本处理工具,而且这些工具可以通过通道串联起来形成流式处理线.这些命令使执行文本 ...

  2. QLabel显示多行文本

    问题: QLabel显示文本过长时会被截断. 解决办法: 在设计器里找不到设置的地方,可以直接用代码设置 ui->label2.setWordWrap(true);

  3. python之Text 多行文本框

    Text 多行文本框 Text(多行文本框)的主要用于显示多行文本,还可以显示网页链接, 图片, HTML 页面, 甚至 CSS 样式表,添加组件等. 因此,也常被当做简单的文本处理器.文本编辑器或者 ...

  4. html 多行文本显示,html多行文本显示 html中文本怎么显示省略号和多行

    html里的input文本框怎样单行变多行 多行的就不能使用Input了.需要使用textarea标签属性: textarea代表html的单多行输入域 html多行输入框 tyle="OV ...

  5. js文本内容显示6行,超出6行出现显示更多按钮,css样式超出行数只能使用...去替代

    js处理文本内容显示6行,超出6行出现显示更多按钮,对于网上说的css样式处理,基本上都是超出6行使用-去处理,不符合需求,先看结果,再看需求:如下 先看实现结果,如下图所示: 需求:产品经理提出详情 ...

  6. UILabel中的多行文本

    是否可以像在UITextView那样在UILabel具有多行文本,还是应该改用第二行? #1楼 您可以使用\\r转到下一行,同时使用NSString填充UILabel . UILabel * labe ...

  7. iOS 9应用开发教程之显示编辑文本标签文本框

    iOS 9应用开发教程之显示编辑文本标签文本框 ios9显示.编辑文本 在iOS,经常会看到一些文本的显示.文字就是这些不会说话的设备的嘴巴.通过这些文字,可以很清楚的指定这些设备要表达的信息.本节将 ...

  8. Xamarin iOS教程之显示和编辑文本

    Xamarin iOS教程之显示和编辑文本 Xamarin iOS显示和编辑文本 在一个应用程序中,文字是非常重要的.它就是这些不会说话的设备的嘴巴.通过这些文字,可以很清楚的指定这些应用程序要表达的 ...

  9. NGUI 3.5教程(二)Label 标签 (Hello world)、多行文本

    写在前面:     本文将创建NGUI的第一个样例.依照编程传统,第一个样例,就是做一个Hello world 显示出来.NGUI.我们用Label来实现 . 欢迎大家纠错.拍砖!原创非常辛苦,如有转 ...

最新文章

  1. 解题报告:luoguP2868 Sightseeing Cows G(最优比率环,负环判定,二分答案)
  2. 程序员的灯下黑:能认识自己吗?
  3. 组件化实践详解(二)
  4. Xcode8 消除部分警告
  5. 关于activiti中的三类网关
  6. 如何通过 C# 判断某个 IP 是否属于某IP段?
  7. 语音识别插件_2D动画唇动合成,根据语音自动生成动画人物口型
  8. Redis高可用架构 (redis主从+sentinel)
  9. c c 语言编程项目实例,实例分享cmake编译一个简单c++项目(demo)
  10. Django中文无法转换成latin-1编码的解决方案
  11. dev c 编程语言,devc如何自定义头文件并使用
  12. JVM 字节码 栈图(Stack Map Table) 学习笔记
  13. 毕业设计记录(二):基于VUE框架与ECharts和Axios技术结合的Web移动高校实验室管理系统设计与实现
  14. 对OMAP-L138的PSC模块的理解
  15. Angular CLI简介
  16. 【MySQL】根据数据表中日期字段查询某个月每一天的数据量?查询数据表中所有日期每天的数据量?近三天每天数据量?
  17. 我的世界Faithful Java_我的世界:原来我们都被骗了,这才Minecraft真实的样貌
  18. 计算机考研转专业,申请美国研究生转专业有什么要求?
  19. 递归算法实例应用(四)
  20. Cookie是什么及用法详解

热门文章

  1. php图形验证码验证,php图片验证码代码
  2. 电商卖家们必须关注的几个数据
  3. 广东工业大学计算机专业课程,广东工业大学在职研究生计算机专业课程安排
  4. java中的字符串常量池_java字符串常量池
  5. 《Linux命令行与Shell脚本编程大全第2版.布卢姆》pdf
  6. C语言自学笔记,第一天
  7. vscode运行命令是报错:标记“”不是此版本中的有效语句分隔符。
  8. 为什么说每个软件工程师,都该懂大数据技术?
  9. SDP最佳实践丨为室内亲子动物园注入新零售基因
  10. VMX(2) -- VMCS理解