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