Chapter 211 · 文本扩展专题

Emoji:SVG 表情与字素序列

让 Emoji 进入与普通文字相同的整形、测量、基线、命中测试和绘制路径,而不是在布局完成后额外贴一张图片。

211

本章目标

完成本章后,你可以加载内建 Emoji 包、把 Emoji 交给 xgeTextShape 整形,并理解肤色修饰符、变体选择符和 ZWJ 家庭序列为什么都必须作为一个逻辑文本项目处理。

关键概念

  • Emoji pack:内建包由 xgeEmojiPackLoadBuiltin 提供 SVG 图形及度量;也可以用 xgeEmojiPackAddSvgMemory 加入应用自己的序列。
  • 整形开关:XGE_TEXT_SHAPE_EMOJI 启用 Emoji 识别,XGE_TEXT_SHAPE_DEFAULT 同时启用 kerning 和 Emoji。
  • 呈现策略:AUTO 遵循 VS15/VS16 与文本默认条目;COLOR 强制彩色 Emoji;TEXT 和 DISABLED 分别优先文本呈现或关闭 Emoji 替换。
  • 行高策略:STABLE 把 SVG 艺术字放入现有字体的 ascent/descent 框,不改变普通文本行高;EXPAND 允许更大的 Emoji 扩张行盒。

API 速查

API / 常量用途
xgeEmojiPackLoadBuiltin加载内建 SVG Emoji 资源包。
xgeEmojiPackMatch检查 UTF-8 字节位置是否匹配完整 Emoji 序列。
xgeTextShape将文字与 Emoji 统一为 xge_glyph_run_t。
XGE_EMOJI_LINE_STABLE保持常规文字行高,适合编辑器和列表。

构建与验证本章示例

examples\xge_emoji\build.bat
build\xge_emoji.exe --capture tutorial\img\ch211_1.png

# 教程镜像入口:包含同一份已验证实现
gcc -O2 -I. -o build\ch211_main1.exe examples\tutorial_capture\ch211_main1.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
build\ch211_main1.exe --capture tutorial\img\ch211_1.png

核心代码:把 Emoji 放进 GlyphRun

xge_text_shape_desc_t desc = { 0 };
xge_glyph_run_t run = { 0 };
desc.iSize = sizeof(desc); desc.pFont = font;
desc.sText = "Hello 😀  Rocket 🚀"; desc.iTextSize = -1;
desc.iFlags = XGE_TEXT_SHAPE_DEFAULT;
desc.iEmojiPresentation = XGE_EMOJI_PRESENTATION_AUTO;
desc.iEmojiLinePolicy = XGE_EMOJI_LINE_STABLE;
if (xgeTextShape(&desc, &run) == XGE_OK) {
    xgeGlyphRunDraw(&run, x, y, color, XGE_DRAW_SCREEN_SPACE);
    xgeGlyphRunFree(&run); // 释放整形结果
}

完整代码

权威实现是 examples/xge_emoji/main.c;教程的 examples/tutorial_capture/ch211_main1.c 直接包含它,因此网页、教程构建入口和示例库始终使用同一份已验证代码。示例以 16、24、40 与 72 px 同时渲染普通文字、单码点 Emoji、肤色修饰符、变体选择符、国旗和 ZWJ 家庭序列,并画出测量框与基线。

代码讲解

  • 不要按码点切分:👍🏽、❤️、国旗和 ZWJ 家庭都由多个码点组成;编辑、选择和光标移动应依赖 GlyphRun 的 cluster 映射。
  • 度量与绘制须配对:先用同一个描述整形和测量,再绘制同一个 GlyphRun,才能保证基线、选区和命中测试一致。
  • 字体仍然重要:非 Emoji 文本由 pFont 与 fallback 链处理;Emoji artwork 来自 pack。
  • 资源生命周期:示例在退出时释放字体和 render target;应用自建的 Emoji pack 同样需要 xgeEmojiPackFree。

要点与练习

  1. 将呈现策略改为 XGE_EMOJI_PRESENTATION_TEXT,比较 VS15/VS16 序列。
  2. 把行高策略改为 XGE_EMOJI_LINE_EXPAND,观察大号 Emoji 对行盒的影响。
  3. 用 xgeEmojiPackMatch 扫描聊天消息,统计完整 Emoji 数而非 UTF-8 字节数。
XGE SVG Emoji 的多字号、基线和测量框示例
图:同一个 GlyphRun 管线在多字号下渲染 Emoji。蓝框是测量结果,橙线是基线;截图由本章权威示例离屏生成。