1 /***************************************************************************/ 2 /* */ 3 /* psmodule.c */ 4 /* */ 5 /* PSNames module implementation (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include <ft2build.h> 20 #include FT_INTERNAL_POSTSCRIPT_NAMES_H 21 #include FT_INTERNAL_OBJECTS_H 22 23 #include "psmodule.h" 24 #include "pstables.h" 25 26 #include "psnamerr.h" 27 28 29 #ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES 30 31 32 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 33 34 35 /* return the Unicode value corresponding to a given glyph. Note that */ 36 /* we do deal with glyph variants by detecting a non-initial dot in */ 37 /* the name, as in `A.swash' or `e.final', etc. */ 38 /* */ 39 static FT_UInt32 ps_unicode_value(const char * glyph_name)40 ps_unicode_value( const char* glyph_name ) 41 { 42 FT_Int n; 43 char first = glyph_name[0]; 44 char temp[64]; 45 46 47 /* if the name begins with `uni', then the glyph name may be a */ 48 /* hard-coded unicode character code. */ 49 if ( glyph_name[0] == 'u' && 50 glyph_name[1] == 'n' && 51 glyph_name[2] == 'i' ) 52 { 53 /* determine whether the next four characters following are */ 54 /* hexadecimal. */ 55 56 /* XXX: Add code to deal with ligatures, i.e. glyph names like */ 57 /* `uniXXXXYYYYZZZZ'... */ 58 59 FT_Int count; 60 FT_ULong value = 0; 61 const char* p = glyph_name + 3; 62 63 64 for ( count = 4; count > 0; count--, p++ ) 65 { 66 char c = *p; 67 unsigned int d; 68 69 70 d = (unsigned char)c - '0'; 71 if ( d >= 10 ) 72 { 73 d = (unsigned char)c - 'A'; 74 if ( d >= 6 ) 75 d = 16; 76 else 77 d += 10; 78 } 79 80 /* exit if a non-uppercase hexadecimal character was found */ 81 if ( d >= 16 ) 82 break; 83 84 value = ( value << 4 ) + d; 85 } 86 if ( count == 0 ) 87 return value; 88 } 89 90 /* look for a non-initial dot in the glyph name in order to */ 91 /* sort-out variants like `A.swash', `e.final', etc. */ 92 { 93 const char* p; 94 int len; 95 96 97 p = glyph_name; 98 99 while ( *p && *p != '.' ) 100 p++; 101 102 len = (int)( p - glyph_name ); 103 104 if ( *p && len < 64 ) 105 { 106 ft_strncpy( temp, glyph_name, len ); 107 temp[len] = 0; 108 glyph_name = temp; 109 } 110 } 111 112 /* now, look up the glyph in the Adobe Glyph List */ 113 for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ ) 114 { 115 const char* name = sid_standard_names[n]; 116 117 118 if ( first == name[0] && ft_strcmp( glyph_name, name ) == 0 ) 119 return ps_names_to_unicode[n]; 120 } 121 122 /* not found, there is probably no Unicode value for this glyph name */ 123 return 0; 124 } 125 126 127 /* ft_qsort callback to sort the unicode map */ 128 FT_CALLBACK_DEF( int ) compare_uni_maps(const void * a,const void * b)129 compare_uni_maps( const void* a, 130 const void* b ) 131 { 132 PS_UniMap* map1 = (PS_UniMap*)a; 133 PS_UniMap* map2 = (PS_UniMap*)b; 134 135 136 return ( map1->unicode - map2->unicode ); 137 } 138 139 140 /* Builds a table that maps Unicode values to glyph indices */ 141 static FT_Error ps_build_unicode_table(FT_Memory memory,FT_UInt num_glyphs,const char ** glyph_names,PS_Unicodes * table)142 ps_build_unicode_table( FT_Memory memory, 143 FT_UInt num_glyphs, 144 const char** glyph_names, 145 PS_Unicodes* table ) 146 { 147 FT_Error error; 148 149 150 /* we first allocate the table */ 151 table->num_maps = 0; 152 table->maps = 0; 153 154 if ( !FT_NEW_ARRAY( table->maps, num_glyphs ) ) 155 { 156 FT_UInt n; 157 FT_UInt count; 158 PS_UniMap* map; 159 FT_UInt32 uni_char; 160 161 162 map = table->maps; 163 164 for ( n = 0; n < num_glyphs; n++ ) 165 { 166 const char* gname = glyph_names[n]; 167 168 169 if ( gname ) 170 { 171 uni_char = ps_unicode_value( gname ); 172 173 if ( uni_char != 0 && uni_char != 0xFFFF ) 174 { 175 map->unicode = uni_char; 176 map->glyph_index = n; 177 map++; 178 } 179 } 180 } 181 182 /* now, compress the table a bit */ 183 count = (FT_UInt)( map - table->maps ); 184 185 if ( count > 0 && FT_REALLOC( table->maps, 186 num_glyphs * sizeof ( PS_UniMap ), 187 count * sizeof ( PS_UniMap ) ) ) 188 count = 0; 189 190 if ( count == 0 ) 191 { 192 FT_FREE( table->maps ); 193 if ( !error ) 194 error = PSnames_Err_Invalid_Argument; /* no unicode chars here! */ 195 } 196 else 197 /* sort the table in increasing order of unicode values */ 198 ft_qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps ); 199 200 table->num_maps = count; 201 } 202 203 return error; 204 } 205 206 207 static FT_UInt ps_lookup_unicode(PS_Unicodes * table,FT_ULong unicode)208 ps_lookup_unicode( PS_Unicodes* table, 209 FT_ULong unicode ) 210 { 211 PS_UniMap *min, *max, *mid; 212 213 214 /* perform a binary search on the table */ 215 216 min = table->maps; 217 max = min + table->num_maps - 1; 218 219 while ( min <= max ) 220 { 221 mid = min + ( max - min ) / 2; 222 if ( mid->unicode == unicode ) 223 return mid->glyph_index; 224 225 if ( min == max ) 226 break; 227 228 if ( mid->unicode < unicode ) 229 min = mid + 1; 230 else 231 max = mid - 1; 232 } 233 234 return 0xFFFF; 235 } 236 237 238 static FT_ULong ps_next_unicode(PS_Unicodes * table,FT_ULong unicode)239 ps_next_unicode( PS_Unicodes* table, 240 FT_ULong unicode ) 241 { 242 PS_UniMap *min, *max, *mid; 243 244 245 unicode++; 246 /* perform a binary search on the table */ 247 248 min = table->maps; 249 max = min + table->num_maps - 1; 250 251 while ( min <= max ) 252 { 253 mid = min + ( max - min ) / 2; 254 if ( mid->unicode == unicode ) 255 return unicode; 256 257 if ( min == max ) 258 break; 259 260 if ( mid->unicode < unicode ) 261 min = mid + 1; 262 else 263 max = mid - 1; 264 } 265 266 if ( max < table->maps ) 267 max = table->maps; 268 269 while ( max < table->maps + table->num_maps ) 270 { 271 if ( unicode < max->unicode ) 272 return max->unicode; 273 max++; 274 } 275 276 return 0; 277 } 278 279 280 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 281 282 283 static const char* ps_get_macintosh_name(FT_UInt name_index)284 ps_get_macintosh_name( FT_UInt name_index ) 285 { 286 if ( name_index >= 258 ) 287 name_index = 0; 288 289 return ps_glyph_names[mac_standard_names[name_index]]; 290 } 291 292 293 static const char* ps_get_standard_strings(FT_UInt sid)294 ps_get_standard_strings( FT_UInt sid ) 295 { 296 return ( sid < NUM_SID_GLYPHS ? sid_standard_names[sid] : 0 ); 297 } 298 299 300 static 301 const PSNames_Interface psnames_interface = 302 { 303 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 304 305 (PS_Unicode_Value_Func) ps_unicode_value, 306 (PS_Build_Unicodes_Func) ps_build_unicode_table, 307 (PS_Lookup_Unicode_Func) ps_lookup_unicode, 308 309 #else 310 311 0, 312 0, 313 0, 314 315 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 316 317 (PS_Macintosh_Name_Func) ps_get_macintosh_name, 318 (PS_Adobe_Std_Strings_Func) ps_get_standard_strings, 319 320 t1_standard_encoding, 321 t1_expert_encoding, 322 323 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 324 (PS_Next_Unicode_Func) ps_next_unicode 325 #else 326 0 327 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 328 329 }; 330 331 332 #endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */ 333 334 335 FT_CALLBACK_TABLE_DEF 336 const FT_Module_Class psnames_module_class = 337 { 338 0, /* this is not a font driver, nor a renderer */ 339 sizeof ( FT_ModuleRec ), 340 341 "psnames", /* driver name */ 342 0x10000L, /* driver version */ 343 0x20000L, /* driver requires FreeType 2 or above */ 344 345 #ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES 346 0, 347 #else 348 (void*)&psnames_interface, /* module specific interface */ 349 #endif 350 351 (FT_Module_Constructor)0, 352 (FT_Module_Destructor) 0, 353 (FT_Module_Requester) 0 354 }; 355 356 357 /* END */ 358