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