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