• 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 #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