S1.03.4Grapheme and rendered-width mismatch设计
字符计数与显示宽度不成正比
别名: 字符数不等于字宽 · 字素簇 · rendered text width
概念解释
字符计数与渲染宽度错配(grapheme and rendered-width mismatch)指程序得到的字符串长度、用户感知的字符数和文字最终占用的像素宽度是三种不同量。一个可见符号可能由多个 Unicode 码位组成,一个码位也可能通过字体塑形与相邻字符形成连字;相同数量的可见字符还会因字形宽窄而占据完全不同的空间。
机制
字符串 API 可能按字节、UTF 编码单元或 Unicode 标量计数,而用户编辑的最小单位通常更接近扩展字素簇。组合附加符、肤色修饰符、零宽连接符序列和旗帜都能让多个码位形成一个感知字符。排版阶段又把字符序列塑形成带有 advance width、字距调整和连字的字形序列,因此计数不会线性映射为宽度。比例字体中的窄字与宽字差异,足以让等长标签产生不同换行。
边界
等宽字体只能让其覆盖范围内的常规字形占据近似固定单元,不能保证 emoji、全角字符、组合标记或后备字体仍等宽。按字素簇限制输入比按编码单元更接近用户预期,但字素簇数量仍不能预测屏幕宽度。像素测量也只对当前字体、字号、语言、塑形设置和设备缩放有效,不能作为跨平台常量。
怎么落地
- 输入上限按业务含义选择计量单位;面向用户说明“字符数”时优先采用平台的字素簇分段,而非 UTF 编码单元。
- 布局是否容纳文字应调用实际排版测量或直接让布局引擎排版,不用字符数乘平均字宽。
- 截断、删除和光标移动不得拆开组合标记、emoji 修饰符或零宽连接符序列。
- 用宽窄字形、组合字符、CJK、emoji、混合字体和文字放大构造测试;核验计数提示、一次删除行为、换行和可见内容都符合用户感知。