• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
xyq_search_node(char * glyph_name,int name_offset,int table_offset,wchar_t unicode)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 
FXFT_unicode_from_adobe_name(const char * glyph_name)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 
FXFT_adobe_name_from_unicode(char * glyph_name,wchar_t unicode)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