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