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