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