Caxton

Caxton

一个为游戏添加改进的TrueType/OpenType字体支持的模组

Caxton

Caxton,以威廉·卡克斯顿的名字命名,是一个为 Minecraft 添加 TrueType 和 OpenType 字体支持的模组。

可在 Modrinth 和 CurseForge 上获取!

特性

  • 得益于 MSDF 技术,任何尺寸下文字都清晰锐利
  • 真正的粗体和斜体字体
  • 复杂文本渲染
  • 不使用 AWT

当前限制

  • 旧版字体目前不支持阿拉伯语整形。 在存在样式和正确的双向文本处理的情况下实现这一点很复杂,因为我们无法为此使用 ICU4J 的 API。如果你希望阿拉伯语文本正确渲染,则必须在 Caxton 下使用支持阿拉伯语的字体。
  • 从字体生成 MTSDF 开销很大。因此,Caxton 会并行化此过程,并在首次完成后缓存结果。
  • 无论是 Minecraft 还是模组中的许多 UI 元素,都对文本渲染做出了错误的假设。让它们支持双向文本——更不用说连字等问题了——将是一项艰巨的任务,我们欢迎这方面的补丁。
    • GUI 元素已打补丁以解决此问题,但显示的文本无论其基本方向如何都向左对齐。
  • 字体微调(Font hinting)可能永远不会被支持。

模组和资源包兼容性

兼容但有一些注意事项

模组 版本 备注
Sodium 除 Caxton <0.6.0 + Sodium 0.5.5 之外的任何版本 使用 Sodium 0.5.5 和 pre-0.6.0 版本的 Caxton 时,描边文字渲染错误
ImmediatelyFast ≥1.2.0 禁用 Caxton 的 sortTextRenderLayers 选项(Caxton <0.6.0 还需禁用 reuseTextRendererDrawer)(自动完成)。确保 ImmediatelyFast 的 experimental_sign_text_buffering 选项已禁用。
Exordium 任何版本 禁用 Exordium 的告示牌缓冲

不兼容

模组 版本 备注
Iris Shaders 任何版本 自定义核心着色器 不被 Iris 支持;使用 MSDF 字体的世界内文本无法渲染
Emojiful 任何版本 直接替换了 Minecraft 的默认文本渲染器
MemoryLeakFix ≤1.1.1
VanillaIcecreamFix ≤1.2.1-beta+1.20.4 启动时与 Caxton 的 Fabric ASM 依赖冲突 – 已在 1.2.2-beta+1.21 中修复
Porting Lib <1.2.1451-beta+1.18.2/2.1.1453+1.19.2 与 Fabric API 的核心着色器注册 API 冲突
Advent of Ascension 1.20.4-3.7.7 不会崩溃,但 AoA 的描边文字不使用 MSDF 字体,且 AoA 的滚动面板组件无法裁剪 MSDF 字体文本(计划推出兼容性附加组件)

布局处理不正确

已知以下模组不能正确处理文本布局。它们应该不会导致游戏崩溃,但来自这些模组的 GUI 元素可能表现出意外行为,并可能导致日志中显示关于不支持的文本处理方法的警告。

模组 版本 备注
IBE Editor 任何版本 使用自定义文本字段组件,该组件 复制了大部分原版 Minecraft 的渲染代码
Roughly Enough Items 任何版本 在其某些组件中使用 不支持的方法

带有自定义文本相关核心着色器的资源包

修改与文本相关的核心着色器的资源包,例如来自 Vanilla Tweaks 的 “Dark UI” 和 “Transparent UI” 包,将需要修改才能与 Caxton 字体配合使用。

操作系统支持

Caxton 使用一个原生库来协助文本整形和 MSDF 生成。该模组的预构建副本捆绑了适用于 x86_64 Windows 和 Linux 平台的此库版本。如果你在其他平台上游戏,则必须自己构建一份模组副本。

如果模组仍然无法识别你的平台,请将 config/caxton.json 中的 rustTarget 设置更改为与你平台对应的 Rust 平台名称之一,并在此处报告问题。

请注意,由于我家里没有一台 Mac,由于许可问题,我无法为 macOS 构建二进制文件。

如何使用 Caxton

Caxton 目前自带两个内置字体资源包。第一个内置字体是 Inter,第二个是 Open Sans。

如果这两种字体都不符合你的需求,你可以通过资源包使用自己的字体。在分发包含字体文件的资源包之前,请阅读字体许可证,以确保你有权分发该字体。

通过资源包添加字体

Caxton 添加了一种类型为 caxton 的字体提供程序,它支持 regular、bold、italic 和 bold_italic 键。每个键都可以设置为一个标识符,其中 <命名空间>:<路径> 解析为字体文件 assets/<命名空间>/textures/font/<路径>。要指定其他选项,请使用一个对象,其中 file 键指定路径:

{
  // 唯一必需的元素。
  "file": "<命名空间>:<路径>",
  // 字体从默认尺寸缩放的倍数。
  // 如果为 1.0,则字体缩放使得上升部(ascent)缩放到默认位图字体的 7 像素。
  // 在 Caxton 0.3.0 中添加。
  "scale_factor": 1.0,
  // 阴影偏移,作为 memefont 像素大小的倍数。
  "shadow_offset": 1.0,
  // 渲染文本在 X 和 Y 轴上的偏移量,单位为 memefont 像素。
  // 在 Caxton 0.4.4 中添加。
  "shift": [
    0.0,
    0.0
  ],
  // 一个 32 位整数,其位被解释为一个描述字符倾斜度的 32 位浮点数。
  // 这可用于在没有斜体变体的字体中模拟斜体,
  // 但如果存在专用的斜体变体,始终优先使用它。
  // 在 Caxton 0.5.6 中添加。
  // 在 Caxton 0.7.0 中不支持。
  "the_font_designer_couldnt_be_assed_to_make_an_italic_variant_so_slant_the_text": 0,
  // 一个 OpenType 功能标签列表。语法见下文:
  // https://docs.rs/rustybuzz/0.6.0/rustybuzz/struct.Feature.html#method.from_str
  "features": [],
  // 仅对光栅化技术有效。对于 MSDF 字体,插值始终启用。
  // 如果为 true,则字形位图中的纹素将被插值。
  // 在 Caxton 0.4.0 中添加。在 Caxton 0.7.0 中被字体元数据设置替换。
  "blur": false
}

如果在字体 JSON 文件中的 caxton_providers 键处存在一个对象,并且安装了 Caxton,则将使用它代替 providers。这可以用于在安装 Caxton 时加载 Caxton 字体,同时在没有安装 Caxton 时有回退方案。如果未指定 caxton_providers,则将改用 providers。

你还可以添加文件 assets/<命名空间>/textures/font/<路径>.json,其中包含光栅化字体的设置:

{
  // 指定字体文件的实际路径,如同在 Caxton 字体提供程序中显示的那样。
  // 通常应省略,但如果你使用的是可变字体,这可能会很有用。
  "path": "<字体文件的路径>",
  // 所有这些选项都是可选的,并将默认为提供的值。
  // 纹理图集中每个像素对应的字体单位数量。
  // 如果使用 "msdf" 字体渲染技术,可以设置为较高的值。
  // 如果你使用 "raster",则应将其设置为较低的值。
  "shrinkage": 32.0,
  // 围绕字形边界框每侧留下的像素数。
  // 这应该大于 `range`,如果留空则默认为 `range`。
  "margin": 4,
  // 字形周围最小和最大可表示有符号距离之间的范围宽度。这是一个不大于 255 的正整数。
  // 这也决定了发光告示牌文本绘制的边框宽度。
  "range": 4,
  // 是否反转有符号距离场(true 或 false)。
  // 如果为 null,则 Caxton 将尝试自动确定,
  // 但如果它猜错了,你可以覆盖此设置。
  "invert": null,
  // 此选项用于设置可变字体中的可变轴坐标。
  // 每个元素的格式如下:
  // { "axis": <轴类型>, "value": <轴值> }
  "variations": [],
  // 要在字体集合中使用的字体面索引。
  // 如果不确定,请将其保留为 0。
  // 在 Caxton 0.3.0 中添加。
  "face_index": 0,
  // 指定使用基于 MSDF 的渲染方法("msdf")还是使用字形位图("raster" – 实验性)。
  // 对于大多数字体,推荐使用 "msdf",但 "raster" 更适合像素字体。
  // 此外,只有 "raster" 与 Iris Shaders 完全兼容 – 如果加载了着色器,
  // MSDF 字体中的文本将不会在世界中显示。
  // 在 Caxton 0.4.0 中添加。
  "tech": "msdf",
  // 最大 mipmap 级别(0 – 4)。
  // 如果你使用 MSDF 渲染技术,设置此值没有意义。
  // 但是,当你使用光栅化渲染技术时,它对于非像素字体可能很有用。
  // 在 Caxton 0.4.0 中添加。
  "max_mipmap": 0,
  // 仅对光栅化技术有效。对于 MSDF 字体,插值始终启用。
  // 如果为 true,则字形位图中的纹素将被插值。
  // 在 Caxton 0.7.0 中取代字体提供程序设置。
  "blur": false
}

确保包含字体文件的扩展名。 因此,如果你的字体位于 assets/example/textures/font/example.otf,那么你的 JSON 文件应位于 assets/example/textures/font/example.otf.json(而不是 example.json)。

全局配置

config/caxton.json 中提供以下选项:

{
  // 与你平台对应的 Rust 平台名称之一
  // (https://doc.rust-lang.org/nightly/rustc/platform-support.html)。
  // 如果为 null,则 Caxton 将为你的平台确定正确的值,
  // 因此建议仅在必要时更改。
  // 在 Caxton 0.2.1 中添加。
  "rustTarget": null,
  // 在经验条上使用不同的绘制等级文本的方法:
  // 对于 Caxton 字体,这将使用轮廓着色器绘制文本,而不是先绘制四个偏移的轮廓色副本
  // 然后再绘制填充色的主要文本。
  // 此选项主要是为了让经验等级文本在轮廓字体中看起来更好。
  // 它曾用作 ImmediatelyFast 渲染错误问题的变通方法,但在该模组的某些后续版本中带来了问题。
  // 从 Caxton 0.5.0 开始,Caxton 将检测是否安装了 ImmediatelyFast 1.2.0 或更高版本,并使用其 API 来缓解启用此设置时的问题。
  // 参见:
  // * https://gitlab.com/Kyarei/caxton/-/issues/31
  // * https://github.com/RaphiMC/ImmediatelyFast/issues/49
  // 非 Caxton 字体不受影响。
  // 在 Caxton 0.4.0 中添加。
  "tweakExpText": true,
  // 从后到前对 Caxton 文本渲染层上的图元进行排序。
  // 禁用此设置理论上可能导致文本渲染错误;然而,ImmediatelyFast 期望禁用此设置,
  // 并且 ImmediatelyFast 的开发人员尚未收到任何关于禁用此功能时出现渲染问题的报告。
  // 如果你遇到某些文本似乎以错误的 z 顺序绘制的问题,请尝试启用此选项(并在 ImmediatelyFast 中禁用 HUD 批处理)。
  // 参见:https://github.com/RaphiMC/ImmediatelyFast/issues/49
  // 在 Caxton 0.4.0 中添加。
  "sortTextRenderLayers": false,
  // 在 0.6.0 之前,Caxton 重用了原版的 `TextRenderer.Drawer` 类,
  // 但强制设置其 `x` 和 `y` 字段,而不是为每个操作创建新实例。
  // 这导致了与 ImmediatelyFast 的一个 mixin 不兼容,
  // 因此引入了此选项来解决此问题。
  // 从 0.6.0-alpha.4 开始,这不再需要,因为 Caxton 不再使用 `TextRenderer.Drawer`。
  // 参见:https://gitlab.com/Kyarei/caxton/-/issues/50
  // 在 Caxton 0.4.7 中添加。
  // 在 Caxton 0.6.0 中移除。
  "reuseTextRendererDrawer": true,
  // 某些文本处理方法本身就存在缺陷且不受 Caxton 支持。
  // 每当这些方法被调用时,Caxton 都会记录一条警告。如果此选项设置为 true,
  // 则 Caxton 将改为抛出异常。
  // 此选项主要用于调试。如有疑问,请将其设置为 false。
  // 在 Caxton 0.2.1 中添加。
  "fatalOnBrokenMethodCall": false,
  // 跟踪有关 Caxton 字体对象的引用何时被添加或移除的信息,用于调试目的。
  // 如有疑问,请将其设置为 false。
  // 在 Caxton 0.3.0 中添加。
  "debugRefcountChanges": false,
  // 在特定日期禁用闪烁文本(splash text)彩蛋。
  // 在 Caxton 0.5.6 中添加。
  "disableEasterEggs": false
}

从源代码构建

如果你想从源代码构建 Caxton,除了 Gradle 之外,你还需要安装 Rust 工具链 和 Clang。

默认情况下,原生库仅为主机平台构建。要为其他平台构建,请在 xyz.flirora.caxton.additionalTargets 属性中通过其目标三元组(以逗号分隔)指定额外的目标。例如,如果你想为 x86_64 Windows 构建该库,则可以调用:

gradle build -Dxyz.flirora.caxton.additionalTargets=x86_64-pc-windows-gnu

如果你收到关于未知目标的错误,请修改 caxton-impl/build.gradle 中的 cargoCrossBuildTasks 变量。

与其他模组的比较

BetterFonts / TrueType Font Replacement

最初由 thvortex 创建至 1.4.4 版本,由 bechill 更新至 1.4.7,然后由 The_MiningCrafter 更新至 1.5.2,随后由 secretdataz 更新至 1.6.x 和 1.7.x,再由 cubex2 从 1.8.9 更新至 1.12.2。然后由 secretdataz 再次更新至 1.13。

此模组使用 Java AWT 的文本布局功能进行文本布局。为了渲染字形,它会将它们光栅化为位图。分辨率相当有限。然而,与下面列出的许多其他模组不同,它正确地实现了粗体和斜体样式,以及复杂脚本(complex scripts)。

Smooth Font

由 bre2el 为 1.7 至 1.12 版本创建。此模组还改进了不同缩放比例下文本的渲染,并实现了文本渲染的一些优化。

至于它如何工作,谁知道 RenderType 呢?这个模组是 ARR(保留所有权利)。

ThaiFixes

由 lion328 为最高 1.12.2 版本的 Forge 和 1.13 版本的 Rift 创建,并由 secretdataz 在 Fabric 上更新至 1.18.2 版本。

此模组专门为泰语实现了自己的整形例程。因此,它对于需要复杂渲染的其他语言没有用处。

Modern UI

由 BloCamLimb 为 Forge 上的 1.15 至 1.19 版本创建。

从截图来看,此模组似乎支持复杂文本渲染和真正的粗体与斜体样式。它还修复了原版文本布局的许多问题,例如 MC-117311。

从代码来看,Modern UI 有一个非常复杂的布局算法。不过,我还没有太多时间研究它。

然而,此模组无法渲染具有清晰边框的文本。它还使用 AWT 来执行文本布局。

Minecraft 1.13 及更高版本

自 1.13 起,Minecraft 支持 TrueType 和 OpenType 字体。然而,此实现与位图字体的实现没有本质区别——游戏将字形转换为位图并天真地进行文本布局。此外,它错误地处理了字形度量,导致 TTF 文本看起来歪斜。

致谢

没有以下项目,Caxton 是不可能实现的:

以下人员对翻译工作做出了贡献:

  • 中文翻译: IcedDog
  • 波兰语翻译: JustFoxxo