数字世界中的 CJK 字体

AI Assisted

CJK 字体封面图

字符编码和字体是计算机文字处理的基础设施。特别是对于汉字而言,由于其字符数量是西文的数十倍,相关的编码方案和字体设计都更为复杂。以下我会介绍主流书写系统的编码方案演变历史,并重点探讨 CJK(中日韩)字符在计算机世界中的表现。

主流书写系统的编码方案

ASCII 编码:数字化文字的起点

ASCII(American Standard Code for Information Interchange)由美国国家标准协会于1963年发布,是最早的广泛使用的字符编码标准

它使用7位二进制编码,能表示128个字符,包括英文字母、数字、标点符号和控制字符。这一标准满足了早期英文文本处理的基本需求,为后续的编码发展奠定了基础。

Unicode 编码:统一全球文字的宏大工程

Unicode 是为了解决不同语言字符编码不兼容的问题而设计的统一编码标准。它为每个字符分配了一个唯一的编码点,支持全球大部分现存书写系统的字符。

核心特点:

  • 全球覆盖:Unicode标准包含了超过一百万个字符,涵盖了几乎所有已知的书写系统,也包括emoji
  • 唯一性:每个字符拥有唯一码点,确保跨平台一致性
  • 扩展性:Unicode标准不断更新和扩展,以包括新的字符和符号,满足不断变化的全球化需求

UTF-8:高效的 Unicode 实现方式

UTF-8 是 Unicode 最成功的实现方式,使用可变长度编码(1 到 4 个字节)来表示字符。

GB 2312的字符集被整合到了 Unicode 中,这意味着 GB 2312 编码的文本可以无损转换为 Unicode 编码。

核心特点:

  • 可变长度:根据字符需求分配适当字节数,节省存储空间
  • 向下兼容ASCII:前128个字符与ASCII完全相同,现有的ASCII文本可直接在UTF-8环境中使用,无需转换
  • 广泛应用:已成为网络传输和存储的主流编码方式

需要明确区分:Unicode 是字符集(规定了哪些字符及其编码值),而 UTF-8 是编码方式(规定了如何将这些编码值转换为二进制数据)。

汉字编码方案的演变历史

GB2312:中国大陆的首个标准化方案

中国国家标准的简体中文字符集编码,于1980年发布,早期简体中文环境下最重要的编码标准之一。 共收录6763个汉字和682个外文字符,覆盖了中国大陆99.75%的使用频率,基本满足了汉字的计算机处理需要。

但无法处理人名、古汉语等方面出现的罕用字和繁体字,须借由一系列的国标辅助集负责编码和显示。

Big5:台湾地区的汉字编码标准

由台湾财团法人信息产业策进会于1983年设计推出,收录13060个汉字。Big5对于台湾地区以及香港、澳门等使用繁体中文的地区产生了深远影响,成为这些地区计算机系统的核心编码标准。

GBK:GB2312 的扩展

GBK 是 GB2312 的扩展版本,增加了对更多汉字和符号的支持,同时保持向下兼容GB2312,解决了简体中文环境中对更多汉字的需求。

Unicode 中的汉字

Unicode 为汉字分配了专门的编码范围(U+4E00 到 U+9FFF),包含约2万个基本汉字。随着需求增长,Unicode 通过扩展区(扩展 A、B、C 等)容纳了更多罕用汉字,目前收录的汉字总数接近10万个,占整个 Unicode 字符空间的63.7%。

字体文件与编码的关系:身份与外观的分离

在计算机文字处理系统中,编码和字体分别负责不同但相互关联的功能:

编码:确定字符的身份

字符编码(如 Unicode)为每个字符分配唯一码点,告诉计算机"这是哪个字符"。例如,Unicode 中大写字母 'A' 的码点是 U+0041,汉字 '字' 的码点是 U+5B57。编码解决的是字符的唯一识别问题。

字体:定义字符的外观

字体文件(如 .ttf, .otf, .woff)包含字形数据,决定每个字符的具体视觉表现。字体提供从"码点"到"形状"的映射,告诉计算机"这个字符应该长什么样"。

文字渲染的基本流程

当应用程序显示文字时:

  1. 通过字符编码确定每个字符的 Unicode 码点
  2. 对于每一个码点,渲染引擎会去当前选定的字体文件(可能为系统提供)中查找与之对应的字形
  3. 渲染引擎使用字体文件中包含的字形数据(通常是矢量或位图信息),将字符绘制到屏幕上

常见的与文本渲染有关的现象

锟斤拷(编码冲突)

在不同的编码系统中,可能会有相同的码点对应不同的字符。例如,Unicode 中的 U+00E9 代表拉丁字母 'é',而在某些其他编码中,它可能代表其他字符。这种情况通常会导致显示错误或乱码。我们常见的「锟斤拷」乱码问题就是由 GBK 和 UTF-8 之间的编码冲突所导致。延伸阅读延伸阅读

口现象(字形缺失)

如果当前字体文件不包含某个特定 Unicode 码点所需的字形(例如,一个英文字体不包含汉字字形,或者一个旧字体不包含新的 Emoji 字形),系统就无法直接渲染它。

这时可能会显示一个"占位符"(如方框 或其它符号)或者尝试从系统指定的其他"后备字体 (Fallback Font)"中寻找该字形。

CJK 统一表意文字:挑战与妥协

统一编码的背景

中文、日文、韩文书写系统与字符数有限的西文书写系统不一样,其字符数量过于庞大,所以编码工作有其独特的挑战性。

由于中日韩文字系统中存在大量相同或相似的汉字,Unicode 采用"CJK 统一表意文字"(CJK Unified Ideographs)策略,为形义基本相同的字符分配单一码点,而不考虑各地区书写风格的差异。

经过以上的整合,汉字依旧在Unicode中占据了相当大的空间。Unicode 16.0 版本中,汉字的数量已经接近 10 万个,占 63.7%:

Unicode V16 字符分布图Unicode V16 字符数量统计

数据来源:https://www.unicode.org/versions/stats/charcountv16_0.html

中日韩汉字的区别

每个地区都有其文字的变更历史,目前中日韩所正使用的汉字表不同,其官方规范的书写风格也有所差异,常见的差别比较大的汉字可以在此页面 Examples of language-dependent glyphs 看到,这些汉字在编码时都被认为是同一个汉字,因此拥有相同的 Unicode 编码。

不同语言中字形差异的示例

Unicode 官方对统一编码的解释:

The Unicode Standard is designed to encode scripts and their characters, not their specific shapes, or glyphs. Even where there are substantial variations in the standard way of writing a character from region to region, if the fundamental identity of the character is not in question, then a single character is encoded in the standard.

Unicode标准旨在编码书写系统及其字符,而不是它们的具体形状或字形。即使在不同地区对字符的书写方式存在显著差异,只要字符的基本身份没有问题,就只会在标准中编码一个字符。

Q: How can I determine whether a Unicode character is Chinese, Japanese, or Korean?

A: It's largely impossible and the attempt basically meaningless. It's the equivalent of asking if "a" is an English letter or a French one.

Q: 如何判断一个Unicode字符是中文、日文还是韩文?

A: 这在很大程度上是不可能的,尝试这样做基本上是毫无意义的。这相当于问"a"是英文字母还是法文字母。

以上提到的有相同 Unicode 编码的汉字,其书写风格只能通过对应语言的字体来控制。这意味着在不同语言环境下,字体的选择会直接影响这些汉字的显示效果。

另外,实际实践中还是存在标准不一致的情况,或许因为汉字数量过于庞大,在多方协调的过程中有各种妥协,导致并非所有的汉字都依照了完全同样的标准进行编码,在这个页面 Examples of some non-unified Han ideographs 所展示的,即是书写差异不明显却被独立编码的汉字。

Fallback Font:字体回退机制

Fallback Font 是指在当前字体文件中找不到所需字形时,系统会自动选择的备用字体。它的作用是确保即使在主字体中缺少某些字符时,文本仍然能够正确显示。

直观的看到字体回退

在网页中,我们有更多的控制汉字渲染样式的方法,例如声明font-familylang 属性。

此时我设置了 font-family: "Hiragino Sans", "PingFang SC",此时日文字体 Hiragino Sans 中缺少的汉字会回退到 PingFang SC, 由于两种字体都属于无衬线黑体,所以区别并不明显。

网页中Hiragino Sans到PingFang SC的回退效果

若换成 font-family: "Hiragino Sans", "SongTi SC",则可以清晰的见到字体的后退机制,日文字体中不存在的简体中文汉字,被使用宋体渲染了。

网页中Hiragino Sans到SongTi SC的回退效果

系统字体栈的工作原理

主流操作系统均支持设置「语言优先级」,大多数情况下其决定了用于渲染文字的字体栈,
以 macOS 为例,如截图中的设置页,其字体栈可能是 SF Pro (English) => PingFang TC (繁體中文) => PingFang HK (繁體中文(香港)) => PingFang SC (简体中文)。

macOS语言设置界面

所以在遇到并未声明语言的汉字时,因为 SF Pro 字体不包含该汉字的编码,其会后退到使用 PingFang TC 来渲染该字体,若 PingFang TC 也不包含该汉字,则可能最终回退到 PingFang SC。

因为不同地区的标准写法有不同程度的差异,所以对应的不同地区的字体(例如 PingFang SC、PingFang TC 和 PingFang HK)的字形也存在差异,以下截图展示了部分汉字的写法差异:

PingFang HK 与 PingFang SC 字体的差异

所以,若要以正确的地区对应的写法渲染汉字,必须用正确的地区字体渲染,而对字体的选择,在不同操作系统中有不同的处理,以 Apple 系统来看,字体选择会受以下因素影响:

  • 系统语言设置
  • 当前应用程序的语言设置
  • 当前文本的语言设置(如 HTML 中的 lang 属性)
  • 当前文本的字体设置(如 CSS 中的 font-family 属性)

而不同地区所使用的标准汉字字库也不一样,所以若使用不符合目标语言的字体,一定会出现不同程度的缺字的情况,例如,日文字体中就缺少诸多中文汉字, 如下图所示,Noto Sans Japanese 中就缺少「谐」、「盘」、「墙」、「纸」、「设」、「计」、「针」等汉字:

Noto Sans日文与简体中文对比

此时操作系统通常会回退到其他字体来渲染这些缺失的汉字。

主流操作系统如何处理不同语言的汉字混排

目前,Apple 使用了 Hiragino Sans TC 为日文环境下用于渲染中文汉字的回退字体,因此汉字样式统一,仅有写法区别:

macOS中的Hiragino Sans TC

Android 也一样,日文和中文都使用了 Noto Sans 字体族,所以汉字样式也保持了统一:

Pixel 上的备忘录中,也因此获得字体样式较为统一的中日混排显示效果(不考虑书写风格差异):

Pixel备忘录中的中日混排效果

总结

  • 字符编码(如 Unicode)为每个字符分配了一个唯一的码点,确保了字符在不同系统和平台之间的一致性。
  • 字体文件(如 TTF、OTF)包含了字符的具体视觉表现形式(字形),决定了字符的外观。
  • Unicode 通过 CJK Unified Ideographs 将中日韩汉字进行统一编码,避免重复和混乱,但也为多语言融合的文本处理带来了挑战。
  • Fallback Font 是在当前字体文件中找不到所需字形时,系统会自动选择的备用字体,确保文本能够正确显示。
  • 汉字存在不同地区的书写风格差异,Unicode 通过 CJK Unified Ideographs 将不同地区存在的同一汉字进行统一编码,但也有例外。
  • macOS 和 Android 都提供了相同字体族的中日字体,提升混排文字的阅读体验。

附录

你可以在此页面的 Code Charts 找到 Unicode 所包含的所有字符:https://www.unicode.org/versions/Unicode16.0.0/

常见的在不同语言中字形差异较大的汉字:https://en.wikipedia.org/wiki/Han_unification#Examples_of_language-dependent_glyphs

Unicode Version 16.0 的字符统计表格:https://www.unicode.org/versions/stats/charcountv16_0.html

Related Articles

Topics to be Written

  • How Android tackles CJK font rendering (highlighting comparison of keyboard input candidate differences between Apple and Android)
  • What to do to ensure proper CJK characters rendering correctly on CJK multi-language websites
  • In what ways Apple excels CJK rendering among competitors