Emoji 中的组合字符与零宽字符

问题背景的产生:iOS - NSString 与 Emoji

在解决这个问题的过程中,发现一个 Emoji 字符的 UTF-16 编码长度经常会有超过 2 的情况,而 Unicode 一个码点用两个 UTF-16 编码长度已经足够表示了。而一个字符编码长度超过 2 的情况就涉及到了 Unicode 的组合字符。

组合字符

Unicode 中有一类字符称为组合字符,它可以附加在前一个非组合字符上,从而使整体看起来像是一个字符。组合字符原来目的是为了解决一些地区语言、文字特殊的需要,比如说泰文声调符号与母音符号。

通过组合字符可以实现一些比较有趣的效果,比如:

Unicode 中码点为 U+0311 的 ”组合用竖翻短音符“
Unicode 中码点为 U+032E 的 ”组合用下短音符“

利用这两个字符和中文字符 ”啊“ 结合,可以得到 ”啊̮̮̮̮̮̮̮̮̮̮̮̑̑̑̑̑̑̑̑̑̑̑“ 这个神奇的字符,这个字符的编码用 OC 表示为:

@"啊\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E\u0311\u032E"

只是在 "啊" 这个字符后面不断的重复这两个组合字符。而 U+0311 和 U+032E 这两个字符也可以单独显示为:

Emoji 与组合字符

其实在 Emoji 中,也可以看到组合字符的大量应用,比如:

 + ✋ = ✋ (由于编辑器原因皮肤写在最前面才能正常显示)
 - U+1F3FB
✋ - U+270B
✋ - U+270B U+1F3FB

作为组合字符和上一个字符组合 ✋ 形成了新的字符 ✋。在 Emoji 中,组合字符被用作调整 Emoji 颜色,使 Emoji 可以表示不同的人种和肤色。

零宽字符

Unicode 中除了组合字符之外,还有一种特殊的字符可以实现组合字的效果,这种字符不可见,不可打印,主要作用于调整字符的显示格式,我们将其称为零宽字符。

零宽字符主要有以下几类:

  • 零宽度空格符 (zero-width space) U+200B : 用于较长单词的换行分隔
  • 零宽度非断空格符 (zero width no-break space) U+FEFF : 用于阻止特定位置的换行分隔
  • 零宽度连字符 (zero-width joiner) U+200D : 用于阿拉伯文与印度语系等文字中,使不会发生连字的字符间产生连字效果
  • 零宽度断字符 (zero-width non-joiner) U+200C : 用于阿拉伯文,德文,印度语系等文字中,阻止会发生连字的字符间的连字效果
  • 左至右符 (left-to-right mark) U+200E : 用于在混合文字方向的多种语言文本中(例:混合左至右书写的英语与右至左书写的希伯来语),规定排版文字书写方向为左至右
  • 右至左符 (right-to-left mark) U+200F : 用于在混合文字方向的多种语言文本中,规定排版文字书写方向为右至左

零宽字符在实际应用中也有很多有趣的用法,在本文中我们只探究 Emoji 中的零宽字符

Emoji 与零宽字符

在 Emoji 中除了组合字符之外,零宽字符对于 Emoji 也是非常重要的。比如对于 Emoji 字符:

有毒,显示不正常,直接放图
它由四个不同的码点组合而成:
 - U+1F468 - 基础字符
 - U+1F3FB - 组合字符,表示肤色
   - U+200D  - 零宽度连字符,表示上下相连
 - U+1F9B3 - 基础字符,表示发型

如果去掉其中的连字符,则会得到两个分离的字符:
♀ - U+1F468 U+1F3FB U+1F9B3

可以发现,连字符在这个 Emoji 中的作用是使用 的发型修饰上一个字符 。

除了发型,连字符的作用还包括了,修饰性别:


有毒,显示不正常,直接放图
它由四个不同的码点组合而成:
 - U+1F468 - 基础字符
 - U+1F3FB - 组合字符,表示肤色
   - U+200D  - 零宽度连字符,表示上下相连
♀ - U+2640  - 基础字符,表示性别

组合图形:

有毒,显示不正常,直接放图
它由五个不同的码点组合而成:
 - U+1F469 - 基础字符
   - U+200D  - 零宽度连字符,表示上下相连
❤  - U+2764   - 基础字符
   - U+200D  - 零宽度连字符,表示上下相连
 - U+1F468 - 基础字符

以及更多的组合图形:

有毒,显示不正常,直接放图
它由七个不同的码点组合而成:
 - U+1F469 - 基础字符
   - U+200D  - 零宽度连字符,表示上下相连
 - U+1F469 - 基础字符
   - U+200D  - 零宽度连字符,表示上下相连
 - U+1F466   - 基础字符
   - U+200D  - 零宽度连字符,表示上下相连
 - U+1F466 - 基础字符

可能还有其他的情景没有提及的,有兴趣的同学可以自己探究一下

你可能感兴趣的:(Emoji 中的组合字符与零宽字符)