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