Como obter o Unicode de um caractere chinês em Latex

Como obter o Unicode de um caractere chinês em Latex

Como posso obter o código UTF-16 de um caractere chinês em Latex? Por exemplo, se eu quiser imprimir o Unicode de `你' em Latex, como isso pode ser feito pedindo ao Latex para pesquisar o código para mim?

Responder1

Aqui está uma implementação que permite imprimir o ponto de código Unicode, a representação UTF8 e a representação UTF16.

\documentclass{article}

\usepackage{xparse}
\usepackage{fontspec}

\setmainfont{Heiti SC}

\ExplSyntaxOn

\NewDocumentCommand{\codepoint}{m}
 {
  U+\xiang_codepoint:n { #1 }
 }
\NewDocumentCommand{\codepointutfviii}{m}
 {
  UTF8:\nobreakspace
  \xiang_codepoint_utfviii:f { \char_codepoint_to_bytes:n { `#1 } }
 }
\NewDocumentCommand{\codepointutfxvi}{m}
 {
  UTF16:\nobreakspace
  \xiang_codepoint_utfxvi:n { #1 }
 }

\NewDocumentCommand{\chardetails}{m}
 {
  #1~\texttt
   {
    \codepoint{#1},~
    \codepointutfviii{#1},~
    \codepointutfxvi{#1}
   }
 }


\cs_new:Nn \xiang_codepoint:n
 {
  \int_compare:nT { `#1 < 4096 } { 0 }
  \int_compare:nT { `#1 < 256 } { 0 }
  \int_to_Hex:n { `#1 }
 }

\cs_new:Nn \xiang_codepoint_utfviii:n
 {
  \tl_map_function:nN { #1 } \__xiang_codepoint_utfviii_aux:n
 }
\cs_generate_variant:Nn \xiang_codepoint_utfviii:n { f }

\cs_new:Nn \__xiang_codepoint_utfviii_aux:n
 {
  \tl_if_empty:nF { #1 }
   {
    <\int_to_Hex:n { #1 }>
   }
 }

\cs_new:Nn \xiang_codepoint_utfxvi:n
 {
  \int_compare:nTF { `#1 < 65536 }
   {
    <\xiang_codepoint:n { #1 }>
   }
   {
    \__xiang_codepoint_utfxvi:n { #1 }
   }
 }

\cs_new:Nn \__xiang_codepoint_utfxvi:n
 {
  <
  \int_to_Hex:n
   {
    \int_div_truncate:nn { `#1 - "10000 } { "400 } + "D800
   }
  >
  <
  \int_to_Hex:n
   {
    \int_mod:nn { `#1 - "10000 } { "400 } + "DC00
   }
  >
 }

\ExplSyntaxOff

\begin{document}

\chardetails{a}

\chardetails{à}

\chardetails{。}

\chardetails{豈}

\chardetails{你}

\chardetails{

Responder2

Aqui está uma implementação em expl3. Veja os comentários para saber como funciona.

Atualizarpara funcionar com todos os motores TeX. (Os próprios caracteres são impressos apenas com os mecanismos Unicode.)

Não tenho ideia se esta é a melhor maneira de fazer isso…

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\int_new:N \l__xiang_high_int
\int_new:N \l__xiang_low_int
\int_new:N \g__xiang_codepoint_int
\int_new:N \g__xiang_utfviii_byte_int
\intarray_new:Nn \g__xiang_utfviii_bytes_intarray { 4 }
\tl_new:N \l__xiang_bin_tl
\tl_new:N \l__xiang_high_tl
\tl_new:N \l__xiang_low_tl
\tl_new:N \l__xiang_byte_i_str
\tl_new:N \l__xiang_byte_ii_str
\tl_new:N \l__xiang_byte_iii_str
\tl_new:N \l__xiang_byte_iv_str

\cs_new:Nn \__xiang_utf_viii_char_to_codepoint:n
  {
    \int_set:Nn \g__xiang_codepoint_int { 0 }
    \int_set:Nn \g__xiang_utfviii_byte_int { 0 }
    \exp_args:NNx \str_set:Nn \l_tmpa_str { \tl_to_str:n { #1 } }
    % add each byte from UTF-8 character to array
    \str_map_inline:Nn \l_tmpa_str
      {
        \int_incr:N \g__xiang_utfviii_byte_int
        \intarray_gset:Nnn \g__xiang_utfviii_bytes_intarray
          { \g__xiang_utfviii_byte_int } { `##1 }
      }
    % calculate code point from UTF-8 bytes
    \int_case:nn { \g__xiang_utfviii_byte_int }
      {
        { 1 }
        {
          \int_set:Nn \g__xiang_codepoint_int
            { \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 1 } }
        }
        { 2 }
        {
          \int_set:Nn \g__xiang_codepoint_int
            {
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 1 } - "C0 )
              * "40 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 2 } - "80 )
            }
        }
        { 3 }
        {
          \int_set:Nn \g__xiang_codepoint_int
            {
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 1 } - "E0 )
              * "1000 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 2 } - "80 )
              * "40 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 3 } - "80 )
            }
        }
        { 4 }
        {
          \int_set:Nn \g__xiang_codepoint_int
            {
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 1 } - "F0 )
              * "40000 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 2 } - "80 )
              * "1000 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 3 } - "80 )
              * "40 +
              ( \intarray_item:Nn \g__xiang_utfviii_bytes_intarray { 4 } - "80 )
            }
        }
      }
  }

\cs_new:Nn \__xiang_codepoint_to_utf_xvi:n
  {
    \int_compare:nTF
      { #1 < 55296 }
      {
        % code point between U+0000 and U+D7FF
        % convert to hex
        \exp_args:NNx \tl_set:Nn \l_tmpa_tl { \int_to_Hex:n {#1} }
        % pad to 4 places
        \int_while_do:nn
          { \tl_count:N \l_tmpa_tl < 4 }
          { \tl_put_left:Nn \l_tmpa_tl { 0 } }
        % output UTF-16 in hex
        0x \tl_use:N \l_tmpa_tl
      }
      {
        \int_compare:nTF
          { 57344 <= #1 <= 65535 }
          {
            % code point between U+E000 and U+FFFF
            % output UTF-16 in hex
            0x \int_to_Hex:n {#1}
          }
          {
            \int_compare:nTF
              { #1 > 65535 }
              {
                % code point between U+010000 and U+10FFFF
                % subtract 0x10000
                \int_set:Nn \l_tmpb_int { #1 - 65536 }
                % convert to binary
                \exp_args:NNx \tl_set:Nn \l__xiang_bin_tl
                  { 
                    \int_to_bin:n { \l_tmpb_int }
                  }
                % pad to 20 bits
                \int_while_do:nn
                  { \tl_count:N \l__xiang_bin_tl < 20 }
                  {
                    \tl_put_left:Nn \l__xiang_bin_tl { 0 }
                  }
                % get high 10 bits
                \tl_set:Nn \l__xiang_high_tl
                  {
                    \tl_range:Nnn \l__xiang_bin_tl { 1 } { 10 }
                  }
                % get low 10 bits
                \tl_set:Nn \l__xiang_low_tl
                  {
                    \tl_range:Nnn \l__xiang_bin_tl { 11 } { 20 }
                  }
                % convert high 10 bits back to integer and add 0xD800
                \int_set:Nn \l__xiang_high_int
                  {
                    55296 + \exp_args:Ne \int_from_bin:n { \l__xiang_high_tl }
                  }
                % convert low 10 bits back to integer and add 0xDC00
                \int_set:Nn \l__xiang_low_int
                  {
                    56320 + \exp_args:Ne \int_from_bin:n { \l__xiang_low_tl }
                  }
                % output UTF-16 in hex
                0x \int_to_Hex:n { \l__xiang_high_int }
                \space
                0x \int_to_Hex:n { \l__xiang_low_int }
              }
              {
                % code point between U+D800 and U+DFFF
                Invalid~code~point.
              }
          }
      }
  }

\NewDocumentCommand \chardetails { m }
  {
    \sys_if_engine_pdftex:TF
      {
        \__xiang_utf_viii_char_to_codepoint:n { #1 }
      }
      {
        { \Large #1 \par }
        \int_set:Nn \g__xiang_codepoint_int { `#1 }
      }
    Code~point:~ \int_use:N \g__xiang_codepoint_int \par
    UTF-16:~ \__xiang_codepoint_to_utf_xvi:n { \g__xiang_codepoint_int }
  }

\sys_if_engine_pdftex:F
  {
    \usepackage{fontspec}
    \setmainfont{Noto~Sans~CJK~SC}
  }

\ExplSyntaxOff

\begin{document}
\chardetails{a}

\chardetails{à}

\chardetails{。}

\chardetails{豈}

\chardetails{你}

\chardetails{

informação relacionada