Skip to main content

字符编码与字体简介

·1005 words·3 mins· loading · loading · ·
Sans
Author
Sans
wanna know everything
Table of Contents

为什么要了解
#

编码确保了信息被准确的传输
字体确保了(文字)信息被准确的表达
某种角度上,我们也在做类似的,抽象纬度更高的工作

字符编码
#

​https://baidu.com
可以将上述链接复制到地址栏打开测试

编码集
#

定义字符和数字(码点)之间的映射关系

ASCII
#

最早的标准, 定义 128 个字符, 仅支持英文

Unicode
#

支持多种语言(CJKV..), 特殊符号, emoji, … 上例的零宽空格符的 Unicode 值为 U+200B, 可通过 String.fromCodePoint(0x200B) 观察

Others
#

这期间还有我国推出的 GB(K), 早期标准 ISO-8859-1, 早期事实标准 windows-1252 等… 网页编码标准 Tip: 标准是标准,实现看各家..可以试验下修改网页编码后的表现(通过 document.charset 获取)

字符编码 UTF - Unicode Transformation Format
#

至今 Unicode 15.1 含 149813 个字符, UTF 对其进行二进制编码

UTF-8
#

普适, 事实上的标准(尤其是Web领域)

UTF-16(BE / LE)
#

适合 CJKV 场景

UTF-32
#

适合随机读取字符场景

字体
#

首先介绍一些基础概念:

字形 glyph, 字的形体
字型 font, 某套具有同样样式、尺寸的字形. 如“12号常规宋体字"
字体 typeface, 也称 font family, 一个或多个字型组成的集合,每个字型具有共同设计特征,如“宋体”

字体的发展历史
#

这里暂时不讨论排版印刷(typography)时期的概念,直接讨论计算机字体

计算机字体
#

  • 点阵字体:位图,适合小字体场景
  • 矢量字体:
    • PostScript 字体(特别指代 Adoble 最早使用 PostScript 格式(3次贝塞尔曲线)私有封装的字体)
    • TrueType(TTF, 主要使用 2次贝塞尔曲线)
    • OpenType(TTF/OTF)
    • Web font(Woff)

一些不那么常用的字体特性
#

Hinting - 渲染提示 思考一下为什么浏览器默认不允许设置 12px 以下的字体大小? rn m Ligature - 连字

Alt text
Alt text

Kerning - (连字)间距

Alt text

Bidi

Alt text
严格来说这里并不属于字体特性而是语言特性,但 bidi 经常需要和 ligature 等场景一起处理
在国际化场景中,有时候我们会通过 logic direction 进行 RTL 适配(虽然一般不这么做)
语言实际上也存在 logical order 和 visual order, 两者不一致的时候就是 Bidirectional 文本

如何准确显示字体
#

以上场景在在 HTML 中浏览器都会处理好(大部分也支持我们通过 CSS 设置) 如果在 Canvas 中,就需要我们自己处理,这里简单介绍下:

  • 解析字体的 PostScript 信息(hhea/vhea/(os/2)..), 拿到 font-Mertrics (注意是 font 不是字体)
  • 排版: line-breaking, Bidi 等
  • 字形选择(Shaping/reShaping): harfbuzz (处理 hinting, ligature, kerning…)
  • 渲染: fillText (一切都交给 chromium 了) 实际上 chrome 大概也是这么做的, 只不过它使用了 skia 作为底层渲染器 这也一定程度上解释了为什么 google 推出了 flutter

了解这些后,可以做些什么
#

做一款字体
#

为了不干扰其他字符的正常展示,这里使用的 Unicode 中的私有区
直接/安装字体后 点击测试
实际上企业发展到一定体量后,为了保障用户体验,自研字体是必经之路(然后就是自研浏览器)