1 /***************************************************************************/ 2 /* */ 3 /* sfdriver.c */ 4 /* */ 5 /* High-level SFNT driver interface (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009 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_SFNT_H 21 #include FT_INTERNAL_OBJECTS_H 22 23 #include "sfdriver.h" 24 #include "ttload.h" 25 #include "sfobjs.h" 26 27 #include "sferrors.h" 28 29 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 30 #include "ttsbit.h" 31 #endif 32 33 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 34 #include "ttpost.h" 35 #endif 36 37 #ifdef TT_CONFIG_OPTION_BDF 38 #include "ttbdf.h" 39 #include FT_SERVICE_BDF_H 40 #endif 41 42 #include "ttcmap.h" 43 #include "ttkern.h" 44 #include "ttmtx.h" 45 46 #include FT_SERVICE_GLYPH_DICT_H 47 #include FT_SERVICE_POSTSCRIPT_NAME_H 48 #include FT_SERVICE_SFNT_H 49 #include FT_SERVICE_TT_CMAP_H 50 51 52 /* 53 * SFNT TABLE SERVICE 54 * 55 */ 56 57 static void* get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)58 get_sfnt_table( TT_Face face, 59 FT_Sfnt_Tag tag ) 60 { 61 void* table; 62 63 64 switch ( tag ) 65 { 66 case ft_sfnt_head: 67 table = &face->header; 68 break; 69 70 case ft_sfnt_hhea: 71 table = &face->horizontal; 72 break; 73 74 case ft_sfnt_vhea: 75 table = face->vertical_info ? &face->vertical : 0; 76 break; 77 78 case ft_sfnt_os2: 79 table = face->os2.version == 0xFFFFU ? 0 : &face->os2; 80 break; 81 82 case ft_sfnt_post: 83 table = &face->postscript; 84 break; 85 86 case ft_sfnt_maxp: 87 table = &face->max_profile; 88 break; 89 90 case ft_sfnt_pclt: 91 table = face->pclt.Version ? &face->pclt : 0; 92 break; 93 94 default: 95 table = 0; 96 } 97 98 return table; 99 } 100 101 102 static FT_Error sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * length)103 sfnt_table_info( TT_Face face, 104 FT_UInt idx, 105 FT_ULong *tag, 106 FT_ULong *length ) 107 { 108 if ( !tag || !length ) 109 return SFNT_Err_Invalid_Argument; 110 111 if ( idx >= face->num_tables ) 112 return SFNT_Err_Table_Missing; 113 114 *tag = face->dir_tables[idx].Tag; 115 *length = face->dir_tables[idx].Length; 116 117 return SFNT_Err_Ok; 118 } 119 120 121 static const FT_Service_SFNT_TableRec sfnt_service_sfnt_table = 122 { 123 (FT_SFNT_TableLoadFunc)tt_face_load_any, 124 (FT_SFNT_TableGetFunc) get_sfnt_table, 125 (FT_SFNT_TableInfoFunc)sfnt_table_info 126 }; 127 128 129 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 130 131 /* 132 * GLYPH DICT SERVICE 133 * 134 */ 135 136 static FT_Error sfnt_get_glyph_name(TT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)137 sfnt_get_glyph_name( TT_Face face, 138 FT_UInt glyph_index, 139 FT_Pointer buffer, 140 FT_UInt buffer_max ) 141 { 142 FT_String* gname; 143 FT_Error error; 144 145 146 error = tt_face_get_ps_name( face, glyph_index, &gname ); 147 if ( !error ) 148 FT_STRCPYN( buffer, gname, buffer_max ); 149 150 return error; 151 } 152 153 154 static FT_UInt sfnt_get_name_index(TT_Face face,FT_String * glyph_name)155 sfnt_get_name_index( TT_Face face, 156 FT_String* glyph_name ) 157 { 158 FT_Face root = &face->root; 159 FT_Long i; 160 161 162 for ( i = 0; i < root->num_glyphs; i++ ) 163 { 164 FT_String* gname; 165 FT_Error error = tt_face_get_ps_name( face, i, &gname ); 166 167 168 if ( error ) 169 continue; 170 171 if ( !ft_strcmp( glyph_name, gname ) ) 172 return (FT_UInt)i; 173 } 174 175 return 0; 176 } 177 178 179 static const FT_Service_GlyphDictRec sfnt_service_glyph_dict = 180 { 181 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, 182 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index 183 }; 184 185 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 186 187 188 /* 189 * POSTSCRIPT NAME SERVICE 190 * 191 */ 192 193 static const char* sfnt_get_ps_name(TT_Face face)194 sfnt_get_ps_name( TT_Face face ) 195 { 196 FT_Int n, found_win, found_apple; 197 const char* result = NULL; 198 199 200 /* shouldn't happen, but just in case to avoid memory leaks */ 201 if ( face->postscript_name ) 202 return face->postscript_name; 203 204 /* scan the name table to see whether we have a Postscript name here, */ 205 /* either in Macintosh or Windows platform encodings */ 206 found_win = -1; 207 found_apple = -1; 208 209 for ( n = 0; n < face->num_names; n++ ) 210 { 211 TT_NameEntryRec* name = face->name_table.names + n; 212 213 214 if ( name->nameID == 6 && name->stringLength > 0 ) 215 { 216 if ( name->platformID == 3 && 217 name->encodingID == 1 && 218 name->languageID == 0x409 ) 219 found_win = n; 220 221 if ( name->platformID == 1 && 222 name->encodingID == 0 && 223 name->languageID == 0 ) 224 found_apple = n; 225 } 226 } 227 228 if ( found_win != -1 ) 229 { 230 FT_Memory memory = face->root.memory; 231 TT_NameEntryRec* name = face->name_table.names + found_win; 232 FT_UInt len = name->stringLength / 2; 233 FT_Error error = SFNT_Err_Ok; 234 235 FT_UNUSED( error ); 236 237 238 if ( !FT_ALLOC( result, name->stringLength + 1 ) ) 239 { 240 FT_Stream stream = face->name_table.stream; 241 FT_String* r = (FT_String*)result; 242 FT_Byte* p = (FT_Byte*)name->string; 243 244 245 if ( FT_STREAM_SEEK( name->stringOffset ) || 246 FT_FRAME_ENTER( name->stringLength ) ) 247 { 248 FT_FREE( result ); 249 name->stringLength = 0; 250 name->stringOffset = 0; 251 FT_FREE( name->string ); 252 253 goto Exit; 254 } 255 256 p = (FT_Byte*)stream->cursor; 257 258 for ( ; len > 0; len--, p += 2 ) 259 { 260 if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 ) 261 *r++ = p[1]; 262 } 263 *r = '\0'; 264 265 FT_FRAME_EXIT(); 266 } 267 goto Exit; 268 } 269 270 if ( found_apple != -1 ) 271 { 272 FT_Memory memory = face->root.memory; 273 TT_NameEntryRec* name = face->name_table.names + found_apple; 274 FT_UInt len = name->stringLength; 275 FT_Error error = SFNT_Err_Ok; 276 277 FT_UNUSED( error ); 278 279 280 if ( !FT_ALLOC( result, len + 1 ) ) 281 { 282 FT_Stream stream = face->name_table.stream; 283 284 285 if ( FT_STREAM_SEEK( name->stringOffset ) || 286 FT_STREAM_READ( result, len ) ) 287 { 288 name->stringOffset = 0; 289 name->stringLength = 0; 290 FT_FREE( name->string ); 291 FT_FREE( result ); 292 goto Exit; 293 } 294 ((char*)result)[len] = '\0'; 295 } 296 } 297 298 Exit: 299 face->postscript_name = result; 300 return result; 301 } 302 303 static const FT_Service_PsFontNameRec sfnt_service_ps_name = 304 { 305 (FT_PsName_GetFunc)sfnt_get_ps_name 306 }; 307 308 309 /* 310 * TT CMAP INFO 311 */ 312 static const FT_Service_TTCMapsRec tt_service_get_cmap_info = 313 { 314 (TT_CMap_Info_GetFunc)tt_get_cmap_info 315 }; 316 317 318 #ifdef TT_CONFIG_OPTION_BDF 319 320 static FT_Error sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)321 sfnt_get_charset_id( TT_Face face, 322 const char* *acharset_encoding, 323 const char* *acharset_registry ) 324 { 325 BDF_PropertyRec encoding, registry; 326 FT_Error error; 327 328 329 /* XXX: I don't know whether this is correct, since 330 * tt_face_find_bdf_prop only returns something correct if we have 331 * previously selected a size that is listed in the BDF table. 332 * Should we change the BDF table format to include single offsets 333 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? 334 */ 335 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); 336 if ( !error ) 337 { 338 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding ); 339 if ( !error ) 340 { 341 if ( registry.type == BDF_PROPERTY_TYPE_ATOM && 342 encoding.type == BDF_PROPERTY_TYPE_ATOM ) 343 { 344 *acharset_encoding = encoding.u.atom; 345 *acharset_registry = registry.u.atom; 346 } 347 else 348 error = FT_Err_Invalid_Argument; 349 } 350 } 351 352 return error; 353 } 354 355 356 static const FT_Service_BDFRec sfnt_service_bdf = 357 { 358 (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id, 359 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop, 360 }; 361 362 #endif /* TT_CONFIG_OPTION_BDF */ 363 364 365 /* 366 * SERVICE LIST 367 */ 368 369 static const FT_ServiceDescRec sfnt_services[] = 370 { 371 { FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table }, 372 { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name }, 373 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 374 { FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict }, 375 #endif 376 #ifdef TT_CONFIG_OPTION_BDF 377 { FT_SERVICE_ID_BDF, &sfnt_service_bdf }, 378 #endif 379 { FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info }, 380 381 { NULL, NULL } 382 }; 383 384 385 FT_CALLBACK_DEF( FT_Module_Interface ) sfnt_get_interface(FT_Module module,const char * module_interface)386 sfnt_get_interface( FT_Module module, 387 const char* module_interface ) 388 { 389 FT_UNUSED( module ); 390 391 return ft_service_list_lookup( sfnt_services, module_interface ); 392 } 393 394 395 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 396 397 FT_CALLBACK_DEF( FT_Error ) tt_face_load_sfnt_header_stub(TT_Face face,FT_Stream stream,FT_Long face_index,SFNT_Header header)398 tt_face_load_sfnt_header_stub( TT_Face face, 399 FT_Stream stream, 400 FT_Long face_index, 401 SFNT_Header header ) 402 { 403 FT_UNUSED( face ); 404 FT_UNUSED( stream ); 405 FT_UNUSED( face_index ); 406 FT_UNUSED( header ); 407 408 return FT_Err_Unimplemented_Feature; 409 } 410 411 412 FT_CALLBACK_DEF( FT_Error ) tt_face_load_directory_stub(TT_Face face,FT_Stream stream,SFNT_Header header)413 tt_face_load_directory_stub( TT_Face face, 414 FT_Stream stream, 415 SFNT_Header header ) 416 { 417 FT_UNUSED( face ); 418 FT_UNUSED( stream ); 419 FT_UNUSED( header ); 420 421 return FT_Err_Unimplemented_Feature; 422 } 423 424 425 FT_CALLBACK_DEF( FT_Error ) tt_face_load_hdmx_stub(TT_Face face,FT_Stream stream)426 tt_face_load_hdmx_stub( TT_Face face, 427 FT_Stream stream ) 428 { 429 FT_UNUSED( face ); 430 FT_UNUSED( stream ); 431 432 return FT_Err_Unimplemented_Feature; 433 } 434 435 436 FT_CALLBACK_DEF( void ) tt_face_free_hdmx_stub(TT_Face face)437 tt_face_free_hdmx_stub( TT_Face face ) 438 { 439 FT_UNUSED( face ); 440 } 441 442 443 FT_CALLBACK_DEF( FT_Error ) tt_face_set_sbit_strike_stub(TT_Face face,FT_UInt x_ppem,FT_UInt y_ppem,FT_ULong * astrike_index)444 tt_face_set_sbit_strike_stub( TT_Face face, 445 FT_UInt x_ppem, 446 FT_UInt y_ppem, 447 FT_ULong* astrike_index ) 448 { 449 /* 450 * We simply forge a FT_Size_Request and call the real function 451 * that does all the work. 452 * 453 * This stub might be called by libXfont in the X.Org Xserver, 454 * compiled against version 2.1.8 or newer. 455 */ 456 457 FT_Size_RequestRec req; 458 459 460 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; 461 req.width = (FT_F26Dot6)x_ppem; 462 req.height = (FT_F26Dot6)y_ppem; 463 req.horiResolution = 0; 464 req.vertResolution = 0; 465 466 *astrike_index = 0x7FFFFFFFUL; 467 468 return tt_face_set_sbit_strike( face, &req, astrike_index ); 469 } 470 471 472 FT_CALLBACK_DEF( FT_Error ) tt_face_load_sbit_stub(TT_Face face,FT_Stream stream)473 tt_face_load_sbit_stub( TT_Face face, 474 FT_Stream stream ) 475 { 476 FT_UNUSED( face ); 477 FT_UNUSED( stream ); 478 479 /* 480 * This function was originally implemented to load the sbit table. 481 * However, it has been replaced by `tt_face_load_eblc', and this stub 482 * is only there for some rogue clients which would want to call it 483 * directly (which doesn't make much sense). 484 */ 485 return FT_Err_Unimplemented_Feature; 486 } 487 488 489 FT_CALLBACK_DEF( void ) tt_face_free_sbit_stub(TT_Face face)490 tt_face_free_sbit_stub( TT_Face face ) 491 { 492 /* nothing to do in this stub */ 493 FT_UNUSED( face ); 494 } 495 496 497 FT_CALLBACK_DEF( FT_Error ) tt_face_load_charmap_stub(TT_Face face,void * cmap,FT_Stream input)498 tt_face_load_charmap_stub( TT_Face face, 499 void* cmap, 500 FT_Stream input ) 501 { 502 FT_UNUSED( face ); 503 FT_UNUSED( cmap ); 504 FT_UNUSED( input ); 505 506 return FT_Err_Unimplemented_Feature; 507 } 508 509 510 FT_CALLBACK_DEF( FT_Error ) tt_face_free_charmap_stub(TT_Face face,void * cmap)511 tt_face_free_charmap_stub( TT_Face face, 512 void* cmap ) 513 { 514 FT_UNUSED( face ); 515 FT_UNUSED( cmap ); 516 517 return 0; 518 } 519 520 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */ 521 522 523 static 524 const SFNT_Interface sfnt_interface = 525 { 526 tt_face_goto_table, 527 528 sfnt_init_face, 529 sfnt_load_face, 530 sfnt_done_face, 531 sfnt_get_interface, 532 533 tt_face_load_any, 534 535 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 536 tt_face_load_sfnt_header_stub, 537 tt_face_load_directory_stub, 538 #endif 539 540 tt_face_load_head, 541 tt_face_load_hhea, 542 tt_face_load_cmap, 543 tt_face_load_maxp, 544 tt_face_load_os2, 545 tt_face_load_post, 546 547 tt_face_load_name, 548 tt_face_free_name, 549 550 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 551 tt_face_load_hdmx_stub, 552 tt_face_free_hdmx_stub, 553 #endif 554 555 tt_face_load_kern, 556 tt_face_load_gasp, 557 tt_face_load_pclt, 558 559 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 560 /* see `ttload.h' */ 561 tt_face_load_bhed, 562 #else 563 0, 564 #endif 565 566 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 567 tt_face_set_sbit_strike_stub, 568 tt_face_load_sbit_stub, 569 570 tt_find_sbit_image, 571 tt_load_sbit_metrics, 572 #endif 573 574 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 575 tt_face_load_sbit_image, 576 #else 577 0, 578 #endif 579 580 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 581 tt_face_free_sbit_stub, 582 #endif 583 584 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 585 /* see `ttpost.h' */ 586 tt_face_get_ps_name, 587 tt_face_free_ps_names, 588 #else 589 0, 590 0, 591 #endif 592 593 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 594 tt_face_load_charmap_stub, 595 tt_face_free_charmap_stub, 596 #endif 597 598 /* since version 2.1.8 */ 599 600 tt_face_get_kerning, 601 602 /* since version 2.2 */ 603 604 tt_face_load_font_dir, 605 tt_face_load_hmtx, 606 607 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 608 /* see `ttsbit.h' and `sfnt.h' */ 609 tt_face_load_eblc, 610 tt_face_free_eblc, 611 612 tt_face_set_sbit_strike, 613 tt_face_load_strike_metrics, 614 #else 615 0, 616 0, 617 0, 618 0, 619 #endif 620 621 tt_face_get_metrics 622 }; 623 624 625 FT_CALLBACK_TABLE_DEF 626 const FT_Module_Class sfnt_module_class = 627 { 628 0, /* not a font driver or renderer */ 629 sizeof( FT_ModuleRec ), 630 631 "sfnt", /* driver name */ 632 0x10000L, /* driver version 1.0 */ 633 0x20000L, /* driver requires FreeType 2.0 or higher */ 634 635 (const void*)&sfnt_interface, /* module specific interface */ 636 637 (FT_Module_Constructor)0, 638 (FT_Module_Destructor) 0, 639 (FT_Module_Requester) sfnt_get_interface 640 }; 641 642 643 /* END */ 644