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