Home | History | Annotate | Download | only in freetype
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/include/fxge/fx_freetype.h"
      8 
      9 #include "third_party/freetype/src/psnames/pstables.h"
     10 
     11 static int xyq_search_node(char* glyph_name, int name_offset, int table_offset, wchar_t unicode)
     12 {
     13     int i, count;
     14 
     15     // copy letters
     16     while (1) {
     17         glyph_name[name_offset] = ft_adobe_glyph_list[table_offset] & 0x7f;
     18         name_offset++;
     19         table_offset++;
     20         if (!(ft_adobe_glyph_list[table_offset - 1] & 0x80)) break;
     21     }
     22     glyph_name[name_offset] = 0;
     23 
     24     // get child count
     25     count = ft_adobe_glyph_list[table_offset] & 0x7f;
     26 
     27     // check if we have value for this node
     28     if (ft_adobe_glyph_list[table_offset] & 0x80) {
     29         unsigned short thiscode = ft_adobe_glyph_list[table_offset + 1] * 256 + ft_adobe_glyph_list[table_offset + 2];
     30         if (thiscode == (unsigned short)unicode)	// found it!
     31             return 1;
     32         table_offset += 3;
     33     }
     34     else
     35         table_offset++;
     36 
     37     // now search in sub-nodes
     38     if (count == 0) return 0;
     39     for (i = 0; i < count; i++) {
     40         int child_offset = ft_adobe_glyph_list[table_offset + i * 2] * 256 + ft_adobe_glyph_list[table_offset + i * 2 + 1];
     41         if (xyq_search_node(glyph_name, name_offset, child_offset, unicode))
     42             // found in child
     43             return 1;
     44     }
     45     return 0;
     46 }
     47 
     48 #define VARIANT_BIT         0x80000000UL
     49 
     50 int FXFT_unicode_from_adobe_name(const char*  glyph_name)
     51 {
     52     /* If the name begins with `uni', then the glyph name may be a */
     53     /* hard-coded unicode character code.                          */
     54     if (glyph_name[0] == 'u' &&
     55         glyph_name[1] == 'n' &&
     56         glyph_name[2] == 'i')
     57     {
     58         /* determine whether the next four characters following are */
     59         /* hexadecimal.                                             */
     60 
     61         /* XXX: Add code to deal with ligatures, i.e. glyph names like */
     62         /*      `uniXXXXYYYYZZZZ'...                                   */
     63 
     64         FT_Int       count;
     65         FT_UInt32    value = 0;
     66         const char*  p = glyph_name + 3;
     67 
     68 
     69         for (count = 4; count > 0; count--, p++)
     70         {
     71             char          c = *p;
     72             unsigned int  d;
     73 
     74 
     75             d = (unsigned char)c - '0';
     76             if (d >= 10)
     77             {
     78                 d = (unsigned char)c - 'A';
     79                 if (d >= 6)
     80                     d = 16;
     81                 else
     82                     d += 10;
     83             }
     84 
     85             /* Exit if a non-uppercase hexadecimal character was found   */
     86             /* -- this also catches character codes below `0' since such */
     87             /* negative numbers cast to `unsigned int' are far too big.  */
     88             if (d >= 16)
     89                 break;
     90 
     91             value = (value << 4) + d;
     92         }
     93 
     94         /* there must be exactly four hex digits */
     95         if (count == 0)
     96         {
     97             if (*p == '\0')
     98                 return value;
     99             if (*p == '.')
    100                 return (FT_UInt32)(value | VARIANT_BIT);
    101         }
    102     }
    103 
    104     /* If the name begins with `u', followed by four to six uppercase */
    105     /* hexadecimal digits, it is a hard-coded unicode character code. */
    106     if (glyph_name[0] == 'u')
    107     {
    108         FT_Int       count;
    109         FT_UInt32    value = 0;
    110         const char*  p = glyph_name + 1;
    111 
    112 
    113         for (count = 6; count > 0; count--, p++)
    114         {
    115             char          c = *p;
    116             unsigned int  d;
    117 
    118 
    119             d = (unsigned char)c - '0';
    120             if (d >= 10)
    121             {
    122                 d = (unsigned char)c - 'A';
    123                 if (d >= 6)
    124                     d = 16;
    125                 else
    126                     d += 10;
    127             }
    128 
    129             if (d >= 16)
    130                 break;
    131 
    132             value = (value << 4) + d;
    133         }
    134 
    135         if (count <= 2)
    136         {
    137             if (*p == '\0')
    138                 return value;
    139             if (*p == '.')
    140                 return (FT_UInt32)(value | VARIANT_BIT);
    141         }
    142     }
    143 
    144     /* Look for a non-initial dot in the glyph name in order to */
    145     /* find variants like `A.swash', `e.final', etc.            */
    146     {
    147         const char*  p = glyph_name;
    148         const char*  dot = NULL;
    149 
    150 
    151         for (; *p; p++)
    152         {
    153             if (*p == '.' && p > glyph_name)
    154             {
    155                 dot = p;
    156                 break;
    157             }
    158         }
    159 
    160         /* now look up the glyph in the Adobe Glyph List */
    161         if (!dot)
    162             return (FT_UInt32)ft_get_adobe_glyph_index(glyph_name, p);
    163         else
    164             return (FT_UInt32)(ft_get_adobe_glyph_index(glyph_name, dot) |
    165             VARIANT_BIT);
    166     }
    167 }
    168 
    169 void FXFT_adobe_name_from_unicode(char* glyph_name, wchar_t unicode)
    170 {
    171     int i, count;
    172 
    173     // start from top level node
    174     count = ft_adobe_glyph_list[1];
    175     for (i = 0; i < count; i++) {
    176         int child_offset = ft_adobe_glyph_list[i * 2 + 2] * 256 + ft_adobe_glyph_list[i * 2 + 3];
    177         if (xyq_search_node(glyph_name, 0, child_offset, unicode))
    178             return;
    179     }
    180 
    181     // failed, clear the buffer
    182     glyph_name[0] = 0;
    183 }
    184