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