Windows 添加 flag emoji 支持
Windows 默认的 “Segoe UI Emoji” 字体中没有相应的字形,因此无法显示 emoji 旗帜。通过添加这些缺失的字形,就可以让 Windows 支持国旗显示。
fontTools
fontTools 是一个基于 Python 的字体编辑工具,可以通过 pip install fonttools
安装。安装完成后就可以在命令行里使用 pyfttools 提供的一些工具:
ttx
该命令可以将 TrueType / OpenType 字体“反编译”成可以直接用文本编辑器打开的 XML 文档,其后缀名为 ttx。也可以把修改后的 ttx 文件重新“编译”回 ttf。
pyftmerge
该命令用于合并字体。但是这里我们无法使用这个命令把其他字体的字形合并到 “Segoe UI Emoji” 中,因为 pyftmerge 不支持对 CPAL/COLR 表进行合并。
OpenType
关于 OpenType 规范的详细介绍,可以参考微软的文档 https://docs.microsoft.com/en-us/typography/opentype/spec/
OpenType 字体中有多种不同类型的表格,我们主要关注下面几张表:
cmap
指定某个码位对应的字形。不是所有的字形都会对应一个码位,但是每个在 cmap 表中声明的码位都需要对应一个字形(可以重复)。如果我们需要添加字形的 Unicode 码在原字体中不存在,就需要手动添加。某些字体可能会存在多张对应不同区域和语言的映射表,需要在所有映射表都加上相应的码位。一些防复制方案就是通过混淆 cmap 来实现的,可以实现选中复制后的文本和原始显示完全不同。
hmtx
指定每个字形的垂直度量。如果修改之后的字体的宽度和间距过宽或过窄,就说明这个表中的数值存在问题。
glyf
包含字形数据,每个字形都由一系列 XY 座标点组成的轮廓构成。
GSUB
定义了字形的替换规则。一类比较常见的字形替换是连字:当多个字形按照指定的顺序依次出现时,将其替换成另一个字形。国旗 emoji 没有单独的 Unicode 码位,就是通过连字实现。比如 “🇹” 和 “🇼” ,连在一起就会变成 “🇹🇼”。
彩色字形
Apple, Google, Microsoft 和 Mozilla 都提出了自己的彩色字形标准。通常情况下,相应平台对自己格式的支持是最好的,对于其他格式的支持则极为有限。有部分软件自己实现了字体渲染,导致它们可以支持一些原本平台不支持的格式,比如 Adobe 和 Mozilla 的软件就会支持 SVG 。
CBDT/CBLC
由 Google 提出,允许在字体中嵌入彩色位图。可以看作是 EBDT/EBLC 的升级版。
sbix
由 Apple 提出,也是一个基于位图的方案,原理和 Google 几乎没有区别。
CPAL/COLR
由 Microsoft 提出,彩色字形中的单个颜色作为一个“图层”存储于 glyf 中。CPAL 包含了各个颜色索引值所对应的颜色。COLR 则指定了某个字形由那些“图层”构成,以及各“图层”的颜色索引值。
SVG
由 Adobe 和 Mozilla 提出,通过直接在文件中嵌入 svg 来显示彩色字形。相比其他方案,SVG 的功能最为齐全,甚至可以实现动画等特殊效果。
修改要点
为了可以在 Windows 中使用,我们需要一个使用 CPAL/COLR,并且包含国旗 emoji 的字体。TwemojiMozilla 是一个使用 CPAL/COLR 的 Twitter emoji 字体,我们将其中的国旗 emoji 提取出来,添加到 “Segoe UI Emoji” 字体中。
使用 DirectDraw 的程序可以显示彩色 emoji,如果程序不支持 DirectDraw,只能显示黑白的 emoji。因此为了支持这些应用,我们还需要一份黑白的 emoji 字形,可以从 TwitterColorEmoji-SVGinOT 中提取。TwitterColorEmoji-SVGinOT 是一个使用 svg 的 Twitter emoji 字体,除了彩色字形之外,还包含了使用程序转换生成的黑白字形。黑白字形的辨识度相对较低,但总比完全无法显示要好得多。
TwemojiMozilla 的 units per em 是 512,而另外两个字体是 2048,因此在合并之前需要对 TwemojiMozilla 中的所有 XY 座标值乘 4。下面是一个简单的 Python 脚本,来实现 hmtx 和 glyf 中的座标值乘 4:
1 | import re |
每在 glyf 表里添加一个字形,都需要在 hmtx 、GlyphOrder 和 GDEF 里面添加对应的项,即这四个表的元素数目需要保持一致。
在合并 COLR 之前,需要先合并 CPAL ,然后对 colorID 作相应的映射。原始微软字体中有一些 CPAL 项没有被使用,在合并时可以回收利用这些 colorID。下面是一个简单的 Python 脚本,来实现 CPAL 的合并和 COLR 的 colorID 映射:
1 | import re |
原字体 CPAL 中有两张调色板,都需要作相应修改。fontTools 可以自动计算大多数的统计值,但是不支持自动计算 CPAL 里面的 numPaletteEntries,因此需要手动更新这一项。
原字体有数字签名,修改后重新编译的字体数字签名会失效,因此可以删掉最后的 DSIG 表。
安装修改后的字体
下载
1.31 版适用于 Win10 和 Server 2019/2022,1.33 版适用于 Win11。这两个版本的不同之处在 emojipedia (Archive) 上有比较详细的说明。
替换系统字体
使用 copy 命令将字体复制到 %windir%\Fonts 中。为了更好的兼容性,新字体文件名的 ASCII 排序应当在原字体 “seguiemj.ttf” 之前,同时使用 8.3 格式。
1 | copy seguiemj_mod.ttf %windir%\Fonts\segoeemj.ttf |
修改下列注册表项,重启系统即可生效。
1 | reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" /v "Segoe UI Emoji (TrueType)" /d segoeemj.ttf /f |