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