psmodule.c revision fbeb41d93d84b6f6dfa2ec8a8b43bafe0fe7696c
1/***************************************************************************/ 2/* */ 3/* psmodule.c */ 4/* */ 5/* PSNames module implementation (body). */ 6/* */ 7/* Copyright 1996-2000 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 <freetype/internal/psnames.h> 20#include <freetype/internal/ftobjs.h> 21#include <psmodule.h> 22 23#include <stdlib.h> /* for qsort() */ 24#include <string.h> /* for strcmp(), strncpy() */ 25 26 27#ifndef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES 28 29 30 /* see the Python script `freetype2/docs/glnames.py' which is used */ 31 /* to generate the following file */ 32#include <pstables.h> 33 34 35#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 36 37 38 /* return the Unicode value corresponding to a given glyph. Note that */ 39 /* we do deal with glyph variants by detecting a non-initial dot in */ 40 /* the name, as in `A.swash' or `e.final', etc. */ 41 /* */ 42 static 43 FT_ULong PS_Unicode_Value( const char* glyph_name ) 44 { 45 FT_Int n; 46 char first = glyph_name[0]; 47 char temp[64]; 48 49 50 /* if the name begins with `uni', then the glyph name may be a */ 51 /* hard-coded unicode character code. */ 52 if ( glyph_name[0] == 'u' && 53 glyph_name[1] == 'n' && 54 glyph_name[2] == 'i' ) 55 { 56 /* determine whether the next four characters following are */ 57 /* hexadecimal. */ 58 59 /* XXX: Add code to deal with ligatures, i.e. glyph names like */ 60 /* `uniXXXXYYYYZZZZ'... */ 61 62 FT_Int count; 63 FT_ULong value = 0; 64 const char* p = glyph_name + 4; 65 66 67 for ( count = 4; count > 0; count--, p++ ) 68 { 69 char c = *p; 70 unsigned char d; 71 72 73 d = (unsigned char)c - '0'; 74 if ( d >= 10 ) 75 { 76 d = (unsigned char)c - 'A'; 77 if ( d >= 6 ) 78 d = 16; 79 else 80 d += 10; 81 } 82 83 /* exit if a non-uppercase hexadecimal character was found */ 84 if ( d >= 16 ) 85 break; 86 87 value = ( value << 4 ) + d; 88 89 if ( count == 0 ) 90 return value; 91 } 92 } 93 94 /* look for a non-initial dot in the glyph name in order to */ 95 /* sort-out variants like `A.swash', `e.final', etc. */ 96 { 97 const char* p; 98 int len; 99 100 101 p = glyph_name; 102 103 while ( *p && *p != '.' ) 104 p++; 105 106 len = p - glyph_name; 107 108 if ( *p && len < 64 ) 109 { 110 strncpy( temp, glyph_name, len ); 111 temp[len] = 0; 112 glyph_name = temp; 113 } 114 } 115 116 /* now, look up the glyph in the Adobe Glyph List */ 117 for ( n = 0; n < NUM_ADOBE_GLYPHS; n++ ) 118 { 119 const char* name = t1_standard_glyphs[n]; 120 121 122 if ( first == name[0] && strcmp( glyph_name, name ) == 0 ) 123 return names_to_unicode[n]; 124 } 125 126 /* not found, there is probably no Unicode value for this glyph name */ 127 return 0; 128 } 129 130 131 /* qsort callback to sort the unicode map */ 132 static 133 int compare_uni_maps( const void* a, 134 const void* b ) 135 { 136 PS_UniMap* map1 = (PS_UniMap*)a; 137 PS_UniMap* map2 = (PS_UniMap*)b; 138 139 140 return ( map1->unicode - map2->unicode ); 141 } 142 143 144 /* Builds a table that maps Unicode values to glyph indices */ 145 static 146 FT_Error PS_Build_Unicode_Table( FT_Memory memory, 147 FT_UInt num_glyphs, 148 const char** glyph_names, 149 PS_Unicodes* table ) 150 { 151 FT_Error error; 152 153 154 /* we first allocate the table */ 155 table->num_maps = 0; 156 table->maps = 0; 157 158 if ( !ALLOC_ARRAY( table->maps, num_glyphs, PS_UniMap ) ) 159 { 160 FT_UInt n; 161 FT_UInt count; 162 PS_UniMap* map; 163 FT_ULong uni_char; 164 165 166 map = table->maps; 167 168 for ( n = 0; n < num_glyphs; n++ ) 169 { 170 const char* gname = glyph_names[n]; 171 172 173 if ( gname ) 174 { 175 uni_char = PS_Unicode_Value( gname ); 176 177 if ( uni_char && uni_char != 0xFFFF ) 178 { 179 map->unicode = uni_char; 180 map->glyph_index = n; 181 map++; 182 } 183 } 184 } 185 186 /* now, compress the table a bit */ 187 count = map - table->maps; 188 189 if ( count > 0 && REALLOC( table->maps, 190 num_glyphs * sizeof ( PS_UniMap ), 191 count * sizeof ( PS_UniMap ) ) ) 192 count = 0; 193 194 if ( count == 0 ) 195 { 196 FREE( table->maps ); 197 if ( !error ) 198 error = FT_Err_Invalid_Argument; /* no unicode chars here! */ 199 } 200 else 201 /* sort the table in increasing order of unicode values */ 202 qsort( table->maps, count, sizeof ( PS_UniMap ), compare_uni_maps ); 203 204 table->num_maps = count; 205 } 206 207 return error; 208 } 209 210 211 static 212 FT_UInt PS_Lookup_Unicode( PS_Unicodes* table, 213 FT_ULong unicode ) 214 { 215 PS_UniMap *min, *max, *mid; 216 217 218 /* perform a binary search on the table */ 219 220 min = table->maps; 221 max = min + table->num_maps - 1; 222 223 while ( min <= max ) 224 { 225 mid = min + ( max - min ) / 2; 226 if ( mid->unicode == unicode ) 227 return mid->glyph_index; 228 229 if ( min == max ) 230 break; 231 232 if ( mid->unicode < unicode ) 233 min = mid + 1; 234 else 235 max = mid - 1; 236 } 237 238 return 0xFFFF; 239 } 240 241 242#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 243 244 245 static 246 const char* PS_Macintosh_Name( FT_UInt name_index ) 247 { 248 if ( name_index >= 258 ) 249 name_index = 0; 250 251 return standard_glyph_names[mac_standard_names[name_index]]; 252 } 253 254 255 static 256 const char* PS_Standard_Strings( FT_UInt sid ) 257 { 258 return ( sid < NUM_STD_GLYPHS ? t1_standard_glyphs[sid] : 0 ); 259 } 260 261 262 static const PSNames_Interface psnames_interface = 263 { 264#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 265 266 (PS_Unicode_Value_Func) PS_Unicode_Value, 267 (PS_Build_Unicodes_Func) PS_Build_Unicode_Table, 268 (PS_Lookup_Unicode_Func) PS_Lookup_Unicode, 269 270#else 271 272 0, 273 0, 274 0, 275 276#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 277 278 (PS_Macintosh_Name_Func) PS_Macintosh_Name, 279 (PS_Adobe_Std_Strings_Func)PS_Standard_Strings, 280 281 t1_standard_encoding, 282 t1_expert_encoding 283 }; 284 285 286#endif /* !FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES */ 287 288 289 const FT_Module_Class psnames_module_class = 290 { 291 0, /* this is not a font driver, nor a renderer */ 292 sizeof( FT_ModuleRec ), 293 294 "psnames", /* driver name */ 295 0x10000L, /* driver version */ 296 0x20000L, /* driver requires FreeType 2 or above */ 297 298#ifdef FT_CONFIG_OPTION_NO_POSTSCRIPT_NAMES 299 0, 300#else 301 (void*)&psnames_interface, /* module specific interface */ 302#endif 303 304 (FT_Module_Constructor)0, 305 (FT_Module_Destructor) 0, 306 (FT_Module_Requester) 0 307 }; 308 309 310/* END */ 311