xref: /aosp_15_r20/external/pdfium/core/fxge/freetype/fx_freetype.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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