本篇教程由作者设定使用 CC BY-NC-SA 协议。

有人会问:“如何使用mc原版字体?”作为作者,我给大家回答一下。

首先大家应该清楚文字渲染不是一个简单的事情。

注:这里指的文字只包括字符(含控制字符),不含文字装饰物(下划线,删除线)、内嵌图片之类的富文本样式。


所有文字使用Unicode规范以满足国际化需要。以下所有库均使用Unicode规范。

文字渲染的基本单位为字形(Glyph),而文字在内存中格式视为char(uint16_t)数组。

字符(Character)的基本单位为码点(Code Point),大体包含两类:BMP(Basic Multilingual Plane),SMP(Supplementary Multilingual Plane)。

绝大部分字符都在BMP平面上,因此可以用一个16位无符号型整数表示,而SMP平面的上的,需要两个16位无符号型整数表示。高16位称为High Surrogate,低16位称为Low Surrogate。


文字的输入顺序称为视觉顺序(Visual Order),意思是理解该文字的顺序。对于阿拉伯语等从右往左书写的文字,其顺序为从右往左(简称RTL),而在内存中则为正序输入。

渲染文字使用的顺序为逻辑顺序(Logical Order),意思是在不同的BiDi Run中,文字递进(Advancement)方向,通常按照行进LTR方向。

BiDi为Bi-Directional的简写,意为双向文字。渲染文字前必须先进行文字方向分析,这被称为BiDi分析,其中需要的BiDi算法一般由ICU库提供。

Run为一次行进,指文字方向、字体、样式都不发生变化的最小区间。一般分为BiDi Run、Style Run、Font Run、Text Run。


接下来需要进行字体样式分析,这里的字体样式指粗/斜体的组合,由字体文件提供。

注:在某些情况下,字体不支持原生粗斜体,那么此时会由软件提供合成粗斜体(或称假粗斜体)来满足渲染需求。一般来讲,对于同一个字体中的不同样式的字体,称为Font。而所有样式的合称为Typeface(也译作字体),亦有时与字体家族(Font Family)通用。

在Minecraft中,字体样式可由Minecraft自己规定的格式控制码或样式标记对象(Style)表示。前者可从语言文件输入,后者只能通过编写程序控制。

Modern UI会根据这些标识符来判断当前的字体样式进行衍生字体,每一个过渡区间成为Style Run。


接下来需要根据字体评分算法判断使用哪个字体来进行渲染,每一个过渡区间为Font Run。字体评分主要由当前的Typeface是否能够渲染该字符/码点决定。

Modern UI使用标准字体格式为TrueType,扩展类型包括TTC、OTF等。为矢量图(直线和二次贝塞尔曲线),支持无限清晰度。


接下来需要进行文字布局。这其中包括字体塑性,主要由HarfBuzz库提供。之前说过文字渲染的基本单位为字形(Glyph),而我们此时只提供了一堆按逻辑顺序排序的、不含BiDi控制符的字符(Character)。每个字符/码点并不能唯一映射为字形,这必须要通过字体塑性来完成,其算法规范为Unicode。例如对于每个阿拉伯字母,它在单词的开头、中间、结尾都有不同的写法,因此他们的字形也不一样,而递进量也不同。在文字整形之后,才能最终通过Modern UI的渲染管线完成渲染。


以上的这些算法运算量不小,如果每帧每行文字都要进行这么多分析的话,一定会使帧数大幅下降。为了保证性能,我花了一年多时间专门为Minecraft的文字系统做了大量优化,在不改动原版动态UI布局下架构,又能保证很好的性能。至于这其中运用到了什么技术,有能力的人可以看我的源码。


总之说了这么多,主要是想告诉大家文字渲染十分烦琐,并且需要依赖TrueType字体文件。而原版字体为位图文件,一堆图片怎么能满足以上这些分析所需要的信息呢?所以Modern UI不支持位图字体的原因就在这。虽然位图字体渲染起来非常非常简单,但其完全不具备良好的文字兼容性,扩展性,各种排版功能以及非常重要的国际化支持。


那么我们怎么使用像原版一样的像素字体呢?那就用TTF格式的像素字体呗,鉴于支持语言较多的像素字体较少,并且不免费,Modern UI不自带这些字体,你可以自行下载方正像素16。

找到/config/ModernUI/client.toml,将像素字体加入到fontFamily中(按照配置文件中的注释添加,有三种方式)。注意像素字体的标准大小必须是16x16。

虽然TTF矢量图是带抗锯齿的,但Modern UI可以将其关闭。找到/config/ModernUI/text.toml,开启fixedResolution;找到/config/ModernUI/client.toml,开启bitmapLike;此外可按需关闭linearSampling。修改完配置后必须重启游戏才能生效。

这样做是有负面效果的,这会导致Modern UI原生提供的UI动画中的文字渲染不雅(不具备像素边缘),所以看自己取舍。


在Modern UI 3.3中,用文本编辑器打开/config/ModernUI/bootstrap,将其值视为int1(或运算,空视为0),保存为UTF8格式后重启游戏即可禁用整个Modern UI为Minecraft专门设计的字体引擎,这会使所有使用原版字体渲染器的行为继续保持原版,不影响Modern UI原生UI系统。