142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501 242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/***************************************************************************/ 342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* */ 442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* psmodule.c */ 542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* */ 642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* PSNames module implementation (body). */ 742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* */ 842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* Copyright 1996-2003, 2005-2008, 2012, 2013 by */ 942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 1042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* */ 1124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org/* This file is part of the FreeType project, and may only be used, */ 1242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* modified, and distributed under the terms of the FreeType project */ 1342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 1442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* this file you indicate that you have read the license and */ 1542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* understand and accept it fully. */ 1642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/* */ 1742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org/***************************************************************************/ 1842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 1942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#define FT2_BUILD_LIBRARY 2042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/ft2build.h" 2142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/ftdebug.h" 2242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/ftobjs.h" 2342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "../../include/freetype/internal/services/svpscmap.h" 2442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 2542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "psmodule.h" 2642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "pstables.h" 2742dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 2842dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "psnamerr.h" 2942dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#include "pspic.h" 3042dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 3142dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 3242dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 3342dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 3442dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 3542dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 3642dacab4e7366d9f53989558cc8d045c3d065bcdcommit-bot@chromium.org 3724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 3824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#define VARIANT_BIT 0x80000000UL 3924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) ) 4024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 4124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#ifdef __cplusplus 4224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgextern "C" { 4324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org#endif 4424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* Return the Unicode value corresponding to a given glyph. Note that */ 4524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* we do deal with glyph variants by detecting a non-initial dot in */ 4624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* the name, as in `A.swash' or `e.final'; in this case, the */ 4724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* VARIANT_BIT is set in the return value. */ 4824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* */ 4924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgint FXFT_unicode_from_adobe_name( const char* glyph_name ) 5024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 5124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* If the name begins with `uni', then the glyph name may be a */ 5224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* hard-coded unicode character code. */ 5324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( glyph_name[0] == 'u' && 5424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org glyph_name[1] == 'n' && 5524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org glyph_name[2] == 'i' ) 5624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 5724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* determine whether the next four characters following are */ 5824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* hexadecimal. */ 5924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 6024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* XXX: Add code to deal with ligatures, i.e. glyph names like */ 6124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* `uniXXXXYYYYZZZZ'... */ 6224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 6324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org FT_Int count; 6424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org FT_UInt32 value = 0; 6524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org const char* p = glyph_name + 3; 6624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 6724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 6824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org for ( count = 4; count > 0; count--, p++ ) 6924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 7024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org char c = *p; 7124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org unsigned int d; 7224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 7324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 7424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d = (unsigned char)c - '0'; 7524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( d >= 10 ) 76f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org { 7724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d = (unsigned char)c - 'A'; 7824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( d >= 6 ) 7924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d = 16; 8024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org else 8124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d += 10; 8224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org } 8324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 8424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* Exit if a non-uppercase hexadecimal character was found */ 8524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* -- this also catches character codes below `0' since such */ 8624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* negative numbers cast to `unsigned int' are far too big. */ 8724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( d >= 16 ) 8824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org break; 8924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 9024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org value = ( value << 4 ) + d; 9124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org } 9224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 9324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* there must be exactly four hex digits */ 9424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( count == 0 ) 9524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 9624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( *p == '\0' ) 9724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org return value; 9824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( *p == '.' ) 9924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org return (FT_UInt32)( value | VARIANT_BIT ); 10024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org } 10124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org } 10224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 10324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* If the name begins with `u', followed by four to six uppercase */ 10424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org /* hexadecimal digits, it is a hard-coded unicode character code. */ 10524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( glyph_name[0] == 'u' ) 10624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 10788cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org FT_Int count; 10824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org FT_UInt32 value = 0; 10924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org const char* p = glyph_name + 1; 11024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 11124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 11224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org for ( count = 6; count > 0; count--, p++ ) 11324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 11424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org char c = *p; 11524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org unsigned int d; 11624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 11724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 11824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d = (unsigned char)c - '0'; 11924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( d >= 10 ) 12024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org { 12124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org d = (unsigned char)c - 'A'; 12224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org if ( d >= 6 ) 12324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org 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 #ifdef __cplusplus 168} 169#endif 170 171#if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 172static int xyq_search_node(char* glyph_name, int name_offset, int table_offset, FT_UInt32 unicode) 173{ 174 int i, count; 175 176 // copy letters 177 while (1) { 178 glyph_name[name_offset] = ft_adobe_glyph_list[table_offset] & 0x7f; 179 name_offset ++; 180 table_offset ++; 181 if (!(ft_adobe_glyph_list[table_offset-1] & 0x80)) break; 182 } 183 glyph_name[name_offset] = 0; 184 185 // get child count 186 count = ft_adobe_glyph_list[table_offset] & 0x7f; 187 188 // check if we have value for this node 189 if (ft_adobe_glyph_list[table_offset] & 0x80) { 190 unsigned short thiscode = ft_adobe_glyph_list[table_offset+1] * 256 + ft_adobe_glyph_list[table_offset+2]; 191 if (thiscode == unicode) // found it! 192 return 1; 193 table_offset += 3; 194 } else 195 table_offset ++; 196 197 // now search in sub-nodes 198 if (count == 0) return 0; 199 for (i = 0; i < count; i ++) { 200 int child_offset = ft_adobe_glyph_list[table_offset+i*2] * 256 + ft_adobe_glyph_list[table_offset+i*2+1]; 201 if (xyq_search_node(glyph_name, name_offset, child_offset, unicode)) 202 // found in child 203 return 1; 204 } 205 return 0; 206} 207 208// XYQ: function for searching Unicode in the glyph list 209void FXFT_adobe_name_from_unicode(char* glyph_name, FT_UInt32 unicode) 210{ 211 int i, count; 212 213 // start from top level node 214 count = ft_adobe_glyph_list[1]; 215 for (i = 0; i < count; i ++) { 216 int child_offset = ft_adobe_glyph_list[i*2+2] * 256 + ft_adobe_glyph_list[i*2+3]; 217 if (xyq_search_node(glyph_name, 0, child_offset, unicode)) 218 return; 219 } 220 221 // failed, clear the buffer 222 glyph_name[0] = 0; 223} 224#endif 225 226 /* ft_qsort callback to sort the unicode map */ 227 FT_CALLBACK_DEF( int ) 228 compare_uni_maps( const void* a, 229 const void* b ) 230 { 231 PS_UniMap* map1 = (PS_UniMap*)a; 232 PS_UniMap* map2 = (PS_UniMap*)b; 233 FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode ); 234 FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode ); 235 236 237 /* sort base glyphs before glyph variants */ 238 if ( unicode1 == unicode2 ) 239 { 240 if ( map1->unicode > map2->unicode ) 241 return 1; 242 else if ( map1->unicode < map2->unicode ) 243 return -1; 244 else 245 return 0; 246 } 247 else 248 { 249 if ( unicode1 > unicode2 ) 250 return 1; 251 else if ( unicode1 < unicode2 ) 252 return -1; 253 else 254 return 0; 255 } 256 } 257 258 259 /* support for extra glyphs not handled (well) in AGL; */ 260 /* we add extra mappings for them if necessary */ 261 262#define EXTRA_GLYPH_LIST_SIZE 10 263 264 static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] = 265 { 266 /* WGL 4 */ 267 0x0394, 268 0x03A9, 269 0x2215, 270 0x00AD, 271 0x02C9, 272 0x03BC, 273 0x2219, 274 0x00A0, 275 /* Romanian */ 276 0x021A, 277 0x021B 278 }; 279 280 static const char ft_extra_glyph_names[] = 281 { 282 'D','e','l','t','a',0, 283 'O','m','e','g','a',0, 284 'f','r','a','c','t','i','o','n',0, 285 'h','y','p','h','e','n',0, 286 'm','a','c','r','o','n',0, 287 'm','u',0, 288 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0, 289 's','p','a','c','e',0, 290 'T','c','o','m','m','a','a','c','c','e','n','t',0, 291 't','c','o','m','m','a','a','c','c','e','n','t',0 292 }; 293 294 static const FT_Int 295 ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] = 296 { 297 0, 298 6, 299 12, 300 21, 301 28, 302 35, 303 38, 304 53, 305 59, 306 72 307 }; 308 309 310 static void 311 ps_check_extra_glyph_name( const char* gname, 312 FT_UInt glyph, 313 FT_UInt* extra_glyphs, 314 FT_UInt *states ) 315 { 316 FT_UInt n; 317 318 319 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 320 { 321 if ( ft_strcmp( ft_extra_glyph_names + 322 ft_extra_glyph_name_offsets[n], gname ) == 0 ) 323 { 324 if ( states[n] == 0 ) 325 { 326 /* mark this extra glyph as a candidate for the cmap */ 327 states[n] = 1; 328 extra_glyphs[n] = glyph; 329 } 330 331 return; 332 } 333 } 334 } 335 336 337 static void 338 ps_check_extra_glyph_unicode( FT_UInt32 uni_char, 339 FT_UInt *states ) 340 { 341 FT_UInt n; 342 343 344 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 345 { 346 if ( uni_char == ft_extra_glyph_unicodes[n] ) 347 { 348 /* disable this extra glyph from being added to the cmap */ 349 states[n] = 2; 350 351 return; 352 } 353 } 354 } 355 356 357 /* Build a table that maps Unicode values to glyph indices. */ 358 static FT_Error 359 ps_unicodes_init( FT_Memory memory, 360 PS_Unicodes table, 361 FT_UInt num_glyphs, 362 PS_GetGlyphNameFunc get_glyph_name, 363 PS_FreeGlyphNameFunc free_glyph_name, 364 FT_Pointer glyph_data ) 365 { 366 FT_Error error; 367 368 FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 369 FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE]; 370 371 372 /* we first allocate the table */ 373 table->num_maps = 0; 374 table->maps = 0; 375 376 if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) 377 { 378 FT_UInt n; 379 FT_UInt count; 380 PS_UniMap* map; 381 FT_UInt32 uni_char; 382 383 384 map = table->maps; 385 386 for ( n = 0; n < num_glyphs; n++ ) 387 { 388 const char* gname = get_glyph_name( glyph_data, n ); 389 390 391 if ( gname ) 392 { 393 ps_check_extra_glyph_name( gname, n, 394 extra_glyphs, extra_glyph_list_states ); 395 uni_char = FXFT_unicode_from_adobe_name( gname ); 396 397 if ( BASE_GLYPH( uni_char ) != 0 ) 398 { 399 ps_check_extra_glyph_unicode( uni_char, 400 extra_glyph_list_states ); 401 map->unicode = uni_char; 402 map->glyph_index = n; 403 map++; 404 } 405 406 if ( free_glyph_name ) 407 free_glyph_name( glyph_data, gname ); 408 } 409 } 410 411 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 412 { 413 if ( extra_glyph_list_states[n] == 1 ) 414 { 415 /* This glyph name has an additional representation. */ 416 /* Add it to the cmap. */ 417 418 map->unicode = ft_extra_glyph_unicodes[n]; 419 map->glyph_index = extra_glyphs[n]; 420 map++; 421 } 422 } 423 424 /* now compress the table a bit */ 425 count = (FT_UInt)( map - table->maps ); 426 427 if ( count == 0 ) 428 { 429 /* No unicode chars here! */ 430 FT_FREE( table->maps ); 431 if ( !error ) 432 error = FT_THROW( No_Unicode_Glyph_Name ); 433 } 434 else 435 { 436 /* Reallocate if the number of used entries is much smaller. */ 437 if ( count < num_glyphs / 2 ) 438 { 439 (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count ); 440 error = FT_Err_Ok; 441 } 442 443 /* Sort the table in increasing order of unicode values, */ 444 /* taking care of glyph variants. */ 445 ft_qsort( table->maps, count, sizeof ( PS_UniMap ), 446 compare_uni_maps ); 447 } 448 449 table->num_maps = count; 450 } 451 452 return error; 453 } 454 455 456 static FT_UInt 457 ps_unicodes_char_index( PS_Unicodes table, 458 FT_UInt32 unicode ) 459 { 460 PS_UniMap *min, *max, *mid, *result = NULL; 461 462 463 /* Perform a binary search on the table. */ 464 465 min = table->maps; 466 max = min + table->num_maps - 1; 467 468 while ( min <= max ) 469 { 470 FT_UInt32 base_glyph; 471 472 473 mid = min + ( ( max - min ) >> 1 ); 474 475 if ( mid->unicode == unicode ) 476 { 477 result = mid; 478 break; 479 } 480 481 base_glyph = BASE_GLYPH( mid->unicode ); 482 483 if ( base_glyph == unicode ) 484 result = mid; /* remember match but continue search for base glyph */ 485 486 if ( min == max ) 487 break; 488 489 if ( base_glyph < unicode ) 490 min = mid + 1; 491 else 492 max = mid - 1; 493 } 494 495 if ( result ) 496 return result->glyph_index; 497 else 498 return 0; 499 } 500 501 502 static FT_UInt32 503 ps_unicodes_char_next( PS_Unicodes table, 504 FT_UInt32 *unicode ) 505 { 506 FT_UInt result = 0; 507 FT_UInt32 char_code = *unicode + 1; 508 509 510 { 511 FT_UInt min = 0; 512 FT_UInt max = table->num_maps; 513 FT_UInt mid; 514 PS_UniMap* map; 515 FT_UInt32 base_glyph; 516 517 518 while ( min < max ) 519 { 520 mid = min + ( ( max - min ) >> 1 ); 521 map = table->maps + mid; 522 523 if ( map->unicode == char_code ) 524 { 525 result = map->glyph_index; 526 goto Exit; 527 } 528 529 base_glyph = BASE_GLYPH( map->unicode ); 530 531 if ( base_glyph == char_code ) 532 result = map->glyph_index; 533 534 if ( base_glyph < char_code ) 535 min = mid + 1; 536 else 537 max = mid; 538 } 539 540 if ( result ) 541 goto Exit; /* we have a variant glyph */ 542 543 /* we didn't find it; check whether we have a map just above it */ 544 char_code = 0; 545 546 if ( min < table->num_maps ) 547 { 548 map = table->maps + min; 549 result = map->glyph_index; 550 char_code = BASE_GLYPH( map->unicode ); 551 } 552 } 553 554 Exit: 555 *unicode = char_code; 556 return result; 557 } 558 559 560#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 561 562 563 static const char* 564 ps_get_macintosh_name( FT_UInt name_index ) 565 { 566 if ( name_index >= FT_NUM_MAC_NAMES ) 567 name_index = 0; 568 569 return ft_standard_glyph_names + ft_mac_names[name_index]; 570 } 571 572 573 static const char* 574 ps_get_standard_strings( FT_UInt sid ) 575 { 576 if ( sid >= FT_NUM_SID_NAMES ) 577 return 0; 578 579 return ft_standard_glyph_names + ft_sid_names[sid]; 580 } 581 582 583#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 584 585 FT_DEFINE_SERVICE_PSCMAPSREC( 586 pscmaps_interface, 587 (PS_Unicode_ValueFunc) FXFT_unicode_from_adobe_name, 588 (PS_Unicodes_InitFunc) ps_unicodes_init, 589 (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, 590 (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, 591 592 (PS_Macintosh_NameFunc) ps_get_macintosh_name, 593 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, 594 595 t1_standard_encoding, 596 t1_expert_encoding ) 597 598#else 599 600 FT_DEFINE_SERVICE_PSCMAPSREC( 601 pscmaps_interface, 602 NULL, 603 NULL, 604 NULL, 605 NULL, 606 607 (PS_Macintosh_NameFunc) ps_get_macintosh_name, 608 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, 609 610 t1_standard_encoding, 611 t1_expert_encoding ) 612 613#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 614 615 616 FT_DEFINE_SERVICEDESCREC1( 617 pscmaps_services, 618 FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET ) 619 620 621 static FT_Pointer 622 psnames_get_service( FT_Module module, 623 const char* service_id ) 624 { 625 /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */ 626#ifdef FT_CONFIG_OPTION_PIC 627 FT_Library library; 628 629 630 if ( !module ) 631 return NULL; 632 library = module->library; 633 if ( !library ) 634 return NULL; 635#else 636 FT_UNUSED( module ); 637#endif 638 639 return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id ); 640 } 641 642#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 643 644 645#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 646#define PUT_PS_NAMES_SERVICE( a ) NULL 647#else 648#define PUT_PS_NAMES_SERVICE( a ) a 649#endif 650 651 FT_DEFINE_MODULE( 652 psnames_module_class, 653 654 0, /* this is not a font driver, nor a renderer */ 655 sizeof ( FT_ModuleRec ), 656 657 "psnames", /* driver name */ 658 0x10000L, /* driver version */ 659 0x20000L, /* driver requires FreeType 2 or above */ 660 661 PUT_PS_NAMES_SERVICE( 662 (void*)&PSCMAPS_INTERFACE_GET ), /* module specific interface */ 663 (FT_Module_Constructor)NULL, 664 (FT_Module_Destructor) NULL, 665 (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) ) 666 667 668/* END */ 669#endif 670 671