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