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