Преобразование между различными числами, идентифицирующими символ Unicode - PullRequest
1 голос
/ 20 февраля 2020

Символы Unicode могут быть идентифицированы с помощью различных чисел .

Например, смайлики "Face with Medical Mask" могут быть идентифицированы дескриптором U+1F637 или U+E40C.

Я предполагаю, что эти дескрипторы идентифицируют индекс символа в полной таблице символов Unicode: но почему их два?

В UTF-16 эта кодовая точка Unicode может быть представлена ​​как четыре байта, образующие две 16-битные единицы кода (я думаю):

D83D followed by DE37

console.log('\uD83D\uDE37') // prints ?

Как перейти от дескриптора Unicode к двоичному представлению символа, а затем к представлению UTF-16?

Ответы [ 2 ]

1 голос
/ 20 февраля 2020

Область личного пользования в Юникоде

Вы спросили:

но почему их два?

Их не два. Существует один официально обозначенный символ (U+1F637), другой (U+E40C) - это номер «личного пользования», который любой может неофициально назначить любому персонажу.

Кодовые точки Unicode используют диапазон более миллиона чисел.

  • Только десятая часть, более 113 000 из которых были официально назначены на определенный c символ.
  • Широкие диапазоны зарезервированы для Частные области использования (PUA) . Подобно тому, как природный заповедник откладывает свойство с намерением, что оно никогда не будет разработано, эти частные диапазоны чисел никогда не будут официально назначены персонажу.
  • Остальные миллионные числа просто не назначены, ожидая когда-нибудь быть официально назначенным персонажем консорциумом Unicode .

Числа в частных зонах могут использоваться любыми сторонами, которые согласны с их семантикой. Любой человек может назначить любой символ, который он хочет, любому номеру в приватном диапазоне. После заключения собственного частного соглашения эти стороны могут безопасно обмениваться данными, используя эти кодовые точки, зная, что они никогда не будут внезапно переосмыслены будущим программным обеспечением в качестве официальных символов.

Зачем кому-то это делать? Сторонами могут быть ученые, занимающиеся исследованием и документированием неясного языка, еще не признанного консорциумом Unicode. Или они могут быть фанатами вымышленного языка, например Klingon , который не соответствует требованиям для официального включения в Unicode. Или это могут быть люди, которые хотят изобрести новый emoji неофициально. Во всех этих случаях сторонам, использующим частные области, необходимо реализовать шрифт с глифами для их неофициальных символов.

Некоторые люди, не входящие в Консорциум Unicode, координируют свои усилия по публичному назначению персонажей, не охватываемых Unicode, в различных диапазонах в зонах частного использования. Они могут опубликовать sh реестр, чтобы другие знали об этом. Но такие назначения, конечно, не являются официальными, и соответствие необязательно.

Ваш номер U+E40C (десятичный 58,380) относится к диапазону номеров Private Use . Этот персонаж, возможно, часто использовался разными людьми в качестве смайлика для лица в старину. Но этот номер никогда не назначался официально Консорциумом Unicode. И при этом это никогда не будет назначено, потому что это отведено для частного использования.

U+1F637 = FACE WITH MEDICAL MASK = ?

U + 1F637 (десятичное число 128 567) было официально назначено Консорциумом Unicode в Unicode 6.0 в 2010 году как ЛИЦО С МЕДИЦИНСКОЙ МАСКОЙ .

Кодировка

Вы спросили:

Как перейти от дескриптора Unicode к двоичному представлению символа, а затем к представлению UTF-16?

Чтобы кодировать это число, см. Answer by Ben .

1 голос
/ 20 февраля 2020

Символ «Лицо с медицинской маской» ? является кодовой точкой U+1F637.

В двоичном виде это: 1 1111 0110 0011 0111.

Для кодирования этого в UTF-16 вам необходимо do следующее :

  1. 0x10000 вычитается из кодовой точки
  2. Старшие десять бит добавляются к 0xD800, чтобы получить первые 16- единица битового кода
  3. Младшие десять бит добавляются к 0xDC00, чтобы дать вторую единицу 16-битного кода

const codepoint = 0b11111011000110111 // ?
const tmp = codepoint - 0x10000
const padded = tmp.toString(2).padStart(20, '0')
const unit1 = Number.parseInt(padded.substr(0, 10), 2) + 0xD800;
const unit2 = Number.parseInt(padded.substr(10), 2) + 0xDC00;

const ch = String.fromCharCode(unit1) + String.fromCharCode(unit2);

console.log(ch);
...