带有肤色的表情符号如何在内部表示? [关闭]

Posted

技术标签:

【中文标题】带有肤色的表情符号如何在内部表示? [关闭]【英文标题】:How are emojis with skin tones internally represented? [closed] 【发布时间】:2020-05-26 19:00:37 【问题描述】:

我正在编写一个处理表情符号的计算机程序。我对表情符号变体的内部表示方式很感兴趣。

诸如这些竖起大拇指的表情符号??????????????????????????????????????? ?,看起来是相同的角色,但具有不同的特征,例如肤色。此外,这些字符似乎占用了相对大量的内存:

console.log('a'.length) // 1
console.log('????????'.length) // 4

这些字符在内部是如何表示的?

【问题讨论】:

contentful.com/blog/2016/12/06/… 有 2 个代码点和 1 个字素(有争议,这取决于您在语言上如何对待表情符号)。如果不先修复编码,则无法回答其他问题。在 UTF-16 中,有 4 个代码单元、8 个字节和 2 个代理对。 “正确”的答案还包括解释每个术语。 这个问题是题外话,因为它不是help center 中描述的范围内的实际编程问题。 编辑后,现在是一个完全不同的问题,使答案无效。那么,鉴于您是写下答案的人,您真正追求的是什么? @Cody Gray 我不同意这是题外话。在右侧,我看到一个问题,上面写着“字符、代码点、字形和字形之间有什么区别?”这不是一个编程问题,但它有 128 个赞成票。还有一个“Zalgo 文本是如何工作的?”有 683 票赞成的问题。 【参考方案1】:

TLDR

在 Unicode 中,带有肤色的表情符号是一种变体形式,对 base character 呈现不同的描述 (glyph)。

中深肤色(??)等表情符号由 grapheme cluster 组成,该grapheme cluster 包含一个基本字符(竖起大拇指符号 ?),紧随其后的是 variation selector non-spacing mark(中深肤色)。

详情

“??”一共有多少个字符?

一个。

character 的 Unicode 定义是:

(1) 书面语言中具有语义的最小组成部分 价值;指抽象的意义和/或形状,而不是 特定的形状(另见字形),虽然在代码表中的某种形式 视觉表示对于读者的理解至关重要。 (2) 抽象字符的同义词。 (3) 编码的基本单位 Unicode 字符编码。 (4)表意文字的英文名称 来自中国的书面元素。

“??”具有单一的、不可分割的抽象含义(“竖起大拇指”),因此符合单个字符的定义。


“??”一共有多少个字素?

一个。

grapheme 的 Unicode 定义是:

(1) 在一个上下文中的最小区别的写作单位 特殊的书写系统。例如,‹b›和‹d›是不同的 英文书写系统中的字形,因为存在不同的 大和挖之类的词。相反,小写的斜体字母 a 和 小写罗马字母 a 不是不同的字素,因为没有单词 是根据这两种不同的形式来区分的。 (2) 什么 用户认为是一个角色。

存在一个字素:竖起大拇指符号 (U+1F44D),然后是 non-spacing mark:中深肤色 variation selector (U+1F3FE)。变体选择器指示应使用不同的字形来描述base character。

基本字符(grapheme base)和变体选择器的组合称为grapheme cluster。请注意,变体选择器是 not 组合符号,如重音符号。

来自 Unicode 规范section on combination:

字素簇通常以字素基开头,然后 跨越任何后续的非间距标记序列。一个字形 集群与文本渲染和处理最直接相关 作为编辑中的光标位置和文本选择,但也可能是 与比较和搜索相关。

和,

对于许多进程,一个字形集群的行为就像它是一个单独的 字符具有与其字素基相同的属性。有效, 非间距标记以图形方式应用于基础,但不要更改其 属性。

因此,在本例中,我们将一个字形和一个非空格标记组合成一个grapheme cluster,从而形成一个glyph(对特定字符的描述):

? + ? makes ??

“??”中有多少个代码点?

两个。

code point 的 Unicode 定义是:

(1) Unicode 代码空间中的任何值;也就是整数的范围 从 0 到 10FFFF16。 (参见第 3.4 节中的定义 D10,字符和 编码。)并非所有代码点都分配给编码字符。看 码点类型。 (2) 任何字符的值或位置 编码字符集。

这里我们有两个来自 Unicode 代码空间的值,所以我们有两个代码点。

javascript 中,String#[Symbol.Iterator] 迭代代码点,使我们能够“看到”代码点:

console.log([...'??'])

“??”中有多少个代码单元?

四个(UTF-16 格式)。

代码单元是编码代码点的一部分的存储单元。

这个字符中的两个码位都需要超过十六位来表示,因此在 UTF-16 中,每个码位有两个码位,一共有四个码位。

\ud83d\udc4d\ud83c\udffe

"??".length // 4
console.log('\ud83d\udc4d\ud83c\udffe')

“??”有多少字节?

八。

在 UTF-16 中,有四个 16 位代码单元,在这个字符中构成 8 个字节。


“??”中有多少个代理对?

两个。

代理对 are 仅用于 UTF-16。该术语指的是由 2 个代码单元组成的序列,它们共同构成一个代码点。

UTF-16 是一种可变宽度的 2 字节或 4 字节字符编码。代码点(字符)编码为 2 字节或 4 字节,具体取决于代码点编号。

对于 0x0 和 0xFFFF 之间的代码点(即 0 到 65,536),代码点可以在单个代码单元(16 位)中编码。 对于 0x10000 和 0x10FFFF 之间的代码点,代码点需要 2 个代码单元(一个 16 位高字和一个 16 位低字)。

在 UTF-16 中,两个代码单元一起形成所谓的代理对。

有two surrogate pairs 的 16 位代码单元,形成两个代码点。

【讨论】:

链接的文章不是 Unicode 标准的一部分,但是,该标准将代理对定义为“由两个 16 位代码单元序列组成的单个抽象字符的表示,其中该对的第一个值是高代理代码单元,第二个值是低代理代码单元”。你在这里有两对这样的代码单元,唯一美中不足的是,这似乎暗示这个序列必须由两个抽象字符组成,而表情符号似乎只有一个——但这并没有真正改变代理计数。 我认为您从链接的答案中获得了“字形”的定义,但该答案暗示此定义在 Unicode 标准中——如果是,我找不到它(并且答案未能引用章节)。 glossary 包含一些完全不同的东西。 “grapheme cluster”和“grapheme base”之类的东西在标准中有技术定义,但“grapheme”没有(无论如何我都能找到)。我会认为这个表情符号是一个字形。

以上是关于带有肤色的表情符号如何在内部表示? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

带有动画表情符号的 Discord 机器人

跟随其他大公司步伐 Microsoft放弃手枪表情符

带有自定义表情符号的反应角色

如何使用css无限期翻转两个表情符号

请问微信😱表情符号还有其它99个表情符号各是啥意思?

在 Flutter 上显示带有表情符号的文本