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