ttload.c revision f463818dd9146e11105c0572fb119e757eb47768
1/***************************************************************************/ 2/* */ 3/* ttload.c */ 4/* */ 5/* Load the basic TrueType tables, i.e., tables that can be either in */ 6/* TTF or OTF fonts (body). */ 7/* */ 8/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by */ 9/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 10/* */ 11/* This file is part of the FreeType project, and may only be used, */ 12/* modified, and distributed under the terms of the FreeType project */ 13/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 14/* this file you indicate that you have read the license and */ 15/* understand and accept it fully. */ 16/* */ 17/***************************************************************************/ 18 19 20#include <ft2build.h> 21#include FT_INTERNAL_DEBUG_H 22#include FT_INTERNAL_STREAM_H 23#include FT_TRUETYPE_TAGS_H 24#include "ttload.h" 25 26#include "sferrors.h" 27 28 29 /*************************************************************************/ 30 /* */ 31 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 32 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 33 /* messages during execution. */ 34 /* */ 35#undef FT_COMPONENT 36#define FT_COMPONENT trace_ttload 37 38 39 /*************************************************************************/ 40 /* */ 41 /* <Function> */ 42 /* tt_face_lookup_table */ 43 /* */ 44 /* <Description> */ 45 /* Looks for a TrueType table by name. */ 46 /* */ 47 /* <Input> */ 48 /* face :: A face object handle. */ 49 /* */ 50 /* tag :: The searched tag. */ 51 /* */ 52 /* <Return> */ 53 /* A pointer to the table directory entry. 0 if not found. */ 54 /* */ 55 FT_LOCAL_DEF( TT_Table ) 56 tt_face_lookup_table( TT_Face face, 57 FT_ULong tag ) 58 { 59 TT_Table entry; 60 TT_Table limit; 61 62 63 FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", 64 face, 65 (FT_Char)( tag >> 24 ), 66 (FT_Char)( tag >> 16 ), 67 (FT_Char)( tag >> 8 ), 68 (FT_Char)( tag ) )); 69 70 entry = face->dir_tables; 71 limit = entry + face->num_tables; 72 73 for ( ; entry < limit; entry++ ) 74 { 75 /* For compatibility with Windows, we consider 0-length */ 76 /* tables the same as missing tables. */ 77 if ( entry->Tag == tag && entry->Length != 0 ) 78 { 79 FT_TRACE4(( "found table.\n" )); 80 return entry; 81 } 82 } 83 84 FT_TRACE4(( "could not find table!\n" )); 85 return 0; 86 } 87 88 89 /*************************************************************************/ 90 /* */ 91 /* <Function> */ 92 /* tt_face_goto_table */ 93 /* */ 94 /* <Description> */ 95 /* Looks for a TrueType table by name, then seek a stream to it. */ 96 /* */ 97 /* <Input> */ 98 /* face :: A face object handle. */ 99 /* */ 100 /* tag :: The searched tag. */ 101 /* */ 102 /* stream :: The stream to seek when the table is found. */ 103 /* */ 104 /* <Output> */ 105 /* length :: The length of the table if found, undefined otherwise. */ 106 /* */ 107 /* <Return> */ 108 /* FreeType error code. 0 means success. */ 109 /* */ 110 FT_LOCAL_DEF( FT_Error ) 111 tt_face_goto_table( TT_Face face, 112 FT_ULong tag, 113 FT_Stream stream, 114 FT_ULong* length ) 115 { 116 TT_Table table; 117 FT_Error error; 118 119 120 table = tt_face_lookup_table( face, tag ); 121 if ( table ) 122 { 123 if ( length ) 124 *length = table->Length; 125 126 if ( FT_STREAM_SEEK( table->Offset ) ) 127 goto Exit; 128 } 129 else 130 error = SFNT_Err_Table_Missing; 131 132 Exit: 133 return error; 134 } 135 136 137 /* Here, we */ 138 /* */ 139 /* - check that `num_tables' is valid */ 140 /* - look for a `head' table, check its size, and parse it to check */ 141 /* whether its `magic' field is correctly set */ 142 /* */ 143 /* When checking directory entries, ignore the tables `glyx' and `locx' */ 144 /* which are hacked-out versions of `glyf' and `loca' in some PostScript */ 145 /* Type 42 fonts, and which are generally invalid. */ 146 /* */ 147 static FT_Error 148 check_table_dir( SFNT_Header sfnt, 149 FT_Stream stream ) 150 { 151 FT_Error error; 152 FT_UInt nn; 153 FT_UInt has_head = 0, has_sing = 0, has_meta = 0; 154 FT_ULong offset = sfnt->offset + 12; 155 156 const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' ); 157 const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' ); 158 159 static const FT_Frame_Field table_dir_entry_fields[] = 160 { 161#undef FT_STRUCTURE 162#define FT_STRUCTURE TT_TableRec 163 164 FT_FRAME_START( 16 ), 165 FT_FRAME_ULONG( Tag ), 166 FT_FRAME_ULONG( CheckSum ), 167 FT_FRAME_ULONG( Offset ), 168 FT_FRAME_ULONG( Length ), 169 FT_FRAME_END 170 }; 171 172 173 if ( sfnt->num_tables == 0 || 174 offset + sfnt->num_tables * 16 > stream->size ) 175 return SFNT_Err_Unknown_File_Format; 176 177 if ( FT_STREAM_SEEK( offset ) ) 178 return error; 179 180 for ( nn = 0; nn < sfnt->num_tables; nn++ ) 181 { 182 TT_TableRec table; 183 184 185 if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) ) 186 return error; 187 188 if ( table.Offset + table.Length > stream->size && 189 table.Tag != glyx_tag && 190 table.Tag != locx_tag ) 191 return SFNT_Err_Unknown_File_Format; 192 193 if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed ) 194 { 195 FT_UInt32 magic; 196 197 198#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 199 if ( table.Tag == TTAG_head ) 200#endif 201 has_head = 1; 202 203 /* 204 * The table length should be 0x36, but certain font tools make it 205 * 0x38, so we will just check that it is greater. 206 * 207 * Note that according to the specification, the table must be 208 * padded to 32-bit lengths, but this doesn't apply to the value of 209 * its `Length' field! 210 * 211 */ 212 if ( table.Length < 0x36 ) 213 return SFNT_Err_Unknown_File_Format; 214 215 if ( FT_STREAM_SEEK( table.Offset + 12 ) || 216 FT_READ_ULONG( magic ) ) 217 return error; 218 219 if ( magic != 0x5F0F3CF5UL ) 220 return SFNT_Err_Unknown_File_Format; 221 222 if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) ) 223 return error; 224 } 225 else if ( table.Tag == TTAG_SING ) 226 has_sing = 1; 227 else if ( table.Tag == TTAG_META ) 228 has_meta = 1; 229 } 230 231 /* if `sing' and `meta' tables are present, there is no `head' table */ 232 if ( has_head || ( has_sing && has_meta ) ) 233 return SFNT_Err_Ok; 234 else 235 return SFNT_Err_Unknown_File_Format; 236 } 237 238 239 /*************************************************************************/ 240 /* */ 241 /* <Function> */ 242 /* tt_face_load_font_dir */ 243 /* */ 244 /* <Description> */ 245 /* Loads the header of a SFNT font file. */ 246 /* */ 247 /* <Input> */ 248 /* face :: A handle to the target face object. */ 249 /* */ 250 /* stream :: The input stream. */ 251 /* */ 252 /* <Output> */ 253 /* sfnt :: The SFNT header. */ 254 /* */ 255 /* <Return> */ 256 /* FreeType error code. 0 means success. */ 257 /* */ 258 /* <Note> */ 259 /* The stream cursor must be at the beginning of the font directory. */ 260 /* */ 261 FT_LOCAL_DEF( FT_Error ) 262 tt_face_load_font_dir( TT_Face face, 263 FT_Stream stream ) 264 { 265 SFNT_HeaderRec sfnt; 266 FT_Error error; 267 FT_Memory memory = stream->memory; 268 TT_TableRec* entry; 269 TT_TableRec* limit; 270 271 static const FT_Frame_Field offset_table_fields[] = 272 { 273#undef FT_STRUCTURE 274#define FT_STRUCTURE SFNT_HeaderRec 275 276 FT_FRAME_START( 8 ), 277 FT_FRAME_USHORT( num_tables ), 278 FT_FRAME_USHORT( search_range ), 279 FT_FRAME_USHORT( entry_selector ), 280 FT_FRAME_USHORT( range_shift ), 281 FT_FRAME_END 282 }; 283 284 285 FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face )); 286 287 /* read the offset table */ 288 289 sfnt.offset = FT_STREAM_POS(); 290 291 if ( FT_READ_ULONG( sfnt.format_tag ) || 292 FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) ) 293 return error; 294 295 /* many fonts don't have these fields set correctly */ 296#if 0 297 if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) || 298 sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 ) 299 return SFNT_Err_Unknown_File_Format; 300#endif 301 302 /* load the table directory */ 303 304 FT_TRACE2(( "-- Tables count: %12u\n", sfnt.num_tables )); 305 FT_TRACE2(( "-- Format version: %08lx\n", sfnt.format_tag )); 306 307 /* check first */ 308 error = check_table_dir( &sfnt, stream ); 309 if ( error ) 310 { 311 FT_TRACE2(( "tt_face_load_font_dir: invalid table directory!\n" )); 312 313 return error; 314 } 315 316 face->num_tables = sfnt.num_tables; 317 face->format_tag = sfnt.format_tag; 318 319 if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) ) 320 return error; 321 322 if ( FT_STREAM_SEEK( sfnt.offset + 12 ) || 323 FT_FRAME_ENTER( face->num_tables * 16L ) ) 324 return error; 325 326 entry = face->dir_tables; 327 limit = entry + face->num_tables; 328 329 for ( ; entry < limit; entry++ ) 330 { 331 entry->Tag = FT_GET_TAG4(); 332 entry->CheckSum = FT_GET_ULONG(); 333 entry->Offset = FT_GET_LONG(); 334 entry->Length = FT_GET_LONG(); 335 336 FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n", 337 (FT_Char)( entry->Tag >> 24 ), 338 (FT_Char)( entry->Tag >> 16 ), 339 (FT_Char)( entry->Tag >> 8 ), 340 (FT_Char)( entry->Tag ), 341 entry->Offset, 342 entry->Length )); 343 } 344 345 FT_FRAME_EXIT(); 346 347 FT_TRACE2(( "table directory loaded\n\n" )); 348 349 return error; 350 } 351 352 353 /*************************************************************************/ 354 /* */ 355 /* <Function> */ 356 /* tt_face_load_any */ 357 /* */ 358 /* <Description> */ 359 /* Loads any font table into client memory. */ 360 /* */ 361 /* <Input> */ 362 /* face :: The face object to look for. */ 363 /* */ 364 /* tag :: The tag of table to load. Use the value 0 if you want */ 365 /* to access the whole font file, else set this parameter */ 366 /* to a valid TrueType table tag that you can forge with */ 367 /* the MAKE_TT_TAG macro. */ 368 /* */ 369 /* offset :: The starting offset in the table (or the file if */ 370 /* tag == 0). */ 371 /* */ 372 /* length :: The address of the decision variable: */ 373 /* */ 374 /* If length == NULL: */ 375 /* Loads the whole table. Returns an error if */ 376 /* `offset' == 0! */ 377 /* */ 378 /* If *length == 0: */ 379 /* Exits immediately; returning the length of the given */ 380 /* table or of the font file, depending on the value of */ 381 /* `tag'. */ 382 /* */ 383 /* If *length != 0: */ 384 /* Loads the next `length' bytes of table or font, */ 385 /* starting at offset `offset' (in table or font too). */ 386 /* */ 387 /* <Output> */ 388 /* buffer :: The address of target buffer. */ 389 /* */ 390 /* <Return> */ 391 /* FreeType error code. 0 means success. */ 392 /* */ 393 FT_LOCAL_DEF( FT_Error ) 394 tt_face_load_any( TT_Face face, 395 FT_ULong tag, 396 FT_Long offset, 397 FT_Byte* buffer, 398 FT_ULong* length ) 399 { 400 FT_Error error; 401 FT_Stream stream; 402 TT_Table table; 403 FT_ULong size; 404 405 406 if ( tag != 0 ) 407 { 408 /* look for tag in font directory */ 409 table = tt_face_lookup_table( face, tag ); 410 if ( !table ) 411 { 412 error = SFNT_Err_Table_Missing; 413 goto Exit; 414 } 415 416 offset += table->Offset; 417 size = table->Length; 418 } 419 else 420 /* tag == 0 -- the user wants to access the font file directly */ 421 size = face->root.stream->size; 422 423 if ( length && *length == 0 ) 424 { 425 *length = size; 426 427 return SFNT_Err_Ok; 428 } 429 430 if ( length ) 431 size = *length; 432 433 stream = face->root.stream; 434 /* the `if' is syntactic sugar for picky compilers */ 435 if ( FT_STREAM_READ_AT( offset, buffer, size ) ) 436 goto Exit; 437 438 Exit: 439 return error; 440 } 441 442 443 /*************************************************************************/ 444 /* */ 445 /* <Function> */ 446 /* tt_face_load_generic_header */ 447 /* */ 448 /* <Description> */ 449 /* Loads the TrueType table `head' or `bhed'. */ 450 /* */ 451 /* <Input> */ 452 /* face :: A handle to the target face object. */ 453 /* */ 454 /* stream :: The input stream. */ 455 /* */ 456 /* <Return> */ 457 /* FreeType error code. 0 means success. */ 458 /* */ 459 static FT_Error 460 tt_face_load_generic_header( TT_Face face, 461 FT_Stream stream, 462 FT_ULong tag ) 463 { 464 FT_Error error; 465 TT_Header* header; 466 467 static const FT_Frame_Field header_fields[] = 468 { 469#undef FT_STRUCTURE 470#define FT_STRUCTURE TT_Header 471 472 FT_FRAME_START( 54 ), 473 FT_FRAME_ULONG ( Table_Version ), 474 FT_FRAME_ULONG ( Font_Revision ), 475 FT_FRAME_LONG ( CheckSum_Adjust ), 476 FT_FRAME_LONG ( Magic_Number ), 477 FT_FRAME_USHORT( Flags ), 478 FT_FRAME_USHORT( Units_Per_EM ), 479 FT_FRAME_LONG ( Created[0] ), 480 FT_FRAME_LONG ( Created[1] ), 481 FT_FRAME_LONG ( Modified[0] ), 482 FT_FRAME_LONG ( Modified[1] ), 483 FT_FRAME_SHORT ( xMin ), 484 FT_FRAME_SHORT ( yMin ), 485 FT_FRAME_SHORT ( xMax ), 486 FT_FRAME_SHORT ( yMax ), 487 FT_FRAME_USHORT( Mac_Style ), 488 FT_FRAME_USHORT( Lowest_Rec_PPEM ), 489 FT_FRAME_SHORT ( Font_Direction ), 490 FT_FRAME_SHORT ( Index_To_Loc_Format ), 491 FT_FRAME_SHORT ( Glyph_Data_Format ), 492 FT_FRAME_END 493 }; 494 495 496 error = face->goto_table( face, tag, stream, 0 ); 497 if ( error ) 498 goto Exit; 499 500 header = &face->header; 501 502 if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) 503 goto Exit; 504 505 FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM )); 506 FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format )); 507 508 Exit: 509 return error; 510 } 511 512 513 FT_LOCAL_DEF( FT_Error ) 514 tt_face_load_head( TT_Face face, 515 FT_Stream stream ) 516 { 517 return tt_face_load_generic_header( face, stream, TTAG_head ); 518 } 519 520 521#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 522 523 FT_LOCAL_DEF( FT_Error ) 524 tt_face_load_bhed( TT_Face face, 525 FT_Stream stream ) 526 { 527 return tt_face_load_generic_header( face, stream, TTAG_bhed ); 528 } 529 530#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 531 532 533 /*************************************************************************/ 534 /* */ 535 /* <Function> */ 536 /* tt_face_load_max_profile */ 537 /* */ 538 /* <Description> */ 539 /* Loads the maximum profile into a face object. */ 540 /* */ 541 /* <Input> */ 542 /* face :: A handle to the target face object. */ 543 /* */ 544 /* stream :: The input stream. */ 545 /* */ 546 /* <Return> */ 547 /* FreeType error code. 0 means success. */ 548 /* */ 549 FT_LOCAL_DEF( FT_Error ) 550 tt_face_load_maxp( TT_Face face, 551 FT_Stream stream ) 552 { 553 FT_Error error; 554 TT_MaxProfile* maxProfile = &face->max_profile; 555 556 const FT_Frame_Field maxp_fields[] = 557 { 558#undef FT_STRUCTURE 559#define FT_STRUCTURE TT_MaxProfile 560 561 FT_FRAME_START( 6 ), 562 FT_FRAME_LONG ( version ), 563 FT_FRAME_USHORT( numGlyphs ), 564 FT_FRAME_END 565 }; 566 567 const FT_Frame_Field maxp_fields_extra[] = 568 { 569 FT_FRAME_START( 26 ), 570 FT_FRAME_USHORT( maxPoints ), 571 FT_FRAME_USHORT( maxContours ), 572 FT_FRAME_USHORT( maxCompositePoints ), 573 FT_FRAME_USHORT( maxCompositeContours ), 574 FT_FRAME_USHORT( maxZones ), 575 FT_FRAME_USHORT( maxTwilightPoints ), 576 FT_FRAME_USHORT( maxStorage ), 577 FT_FRAME_USHORT( maxFunctionDefs ), 578 FT_FRAME_USHORT( maxInstructionDefs ), 579 FT_FRAME_USHORT( maxStackElements ), 580 FT_FRAME_USHORT( maxSizeOfInstructions ), 581 FT_FRAME_USHORT( maxComponentElements ), 582 FT_FRAME_USHORT( maxComponentDepth ), 583 FT_FRAME_END 584 }; 585 586 587 error = face->goto_table( face, TTAG_maxp, stream, 0 ); 588 if ( error ) 589 goto Exit; 590 591 if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) ) 592 goto Exit; 593 594 maxProfile->maxPoints = 0; 595 maxProfile->maxContours = 0; 596 maxProfile->maxCompositePoints = 0; 597 maxProfile->maxCompositeContours = 0; 598 maxProfile->maxZones = 0; 599 maxProfile->maxTwilightPoints = 0; 600 maxProfile->maxStorage = 0; 601 maxProfile->maxFunctionDefs = 0; 602 maxProfile->maxInstructionDefs = 0; 603 maxProfile->maxStackElements = 0; 604 maxProfile->maxSizeOfInstructions = 0; 605 maxProfile->maxComponentElements = 0; 606 maxProfile->maxComponentDepth = 0; 607 608 if ( maxProfile->version >= 0x10000L ) 609 { 610 if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) ) 611 goto Exit; 612 613 /* XXX: an adjustment that is necessary to load certain */ 614 /* broken fonts like `Keystrokes MT' :-( */ 615 /* */ 616 /* We allocate 64 function entries by default when */ 617 /* the maxFunctionDefs field is null. */ 618 619 if ( maxProfile->maxFunctionDefs == 0 ) 620 maxProfile->maxFunctionDefs = 64; 621 } 622 623 FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); 624 625 Exit: 626 return error; 627 } 628 629 630 /*************************************************************************/ 631 /* */ 632 /* <Function> */ 633 /* tt_face_load_names */ 634 /* */ 635 /* <Description> */ 636 /* Loads the name records. */ 637 /* */ 638 /* <Input> */ 639 /* face :: A handle to the target face object. */ 640 /* */ 641 /* stream :: The input stream. */ 642 /* */ 643 /* <Return> */ 644 /* FreeType error code. 0 means success. */ 645 /* */ 646 FT_LOCAL_DEF( FT_Error ) 647 tt_face_load_name( TT_Face face, 648 FT_Stream stream ) 649 { 650 FT_Error error; 651 FT_Memory memory = stream->memory; 652 FT_ULong table_pos, table_len; 653 FT_ULong storage_start, storage_limit; 654 FT_UInt count; 655 TT_NameTable table; 656 657 static const FT_Frame_Field name_table_fields[] = 658 { 659#undef FT_STRUCTURE 660#define FT_STRUCTURE TT_NameTableRec 661 662 FT_FRAME_START( 6 ), 663 FT_FRAME_USHORT( format ), 664 FT_FRAME_USHORT( numNameRecords ), 665 FT_FRAME_USHORT( storageOffset ), 666 FT_FRAME_END 667 }; 668 669 static const FT_Frame_Field name_record_fields[] = 670 { 671#undef FT_STRUCTURE 672#define FT_STRUCTURE TT_NameEntryRec 673 674 /* no FT_FRAME_START */ 675 FT_FRAME_USHORT( platformID ), 676 FT_FRAME_USHORT( encodingID ), 677 FT_FRAME_USHORT( languageID ), 678 FT_FRAME_USHORT( nameID ), 679 FT_FRAME_USHORT( stringLength ), 680 FT_FRAME_USHORT( stringOffset ), 681 FT_FRAME_END 682 }; 683 684 685 table = &face->name_table; 686 table->stream = stream; 687 688 error = face->goto_table( face, TTAG_name, stream, &table_len ); 689 if ( error ) 690 goto Exit; 691 692 table_pos = FT_STREAM_POS(); 693 694 695 if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) ) 696 goto Exit; 697 698 /* Some popular Asian fonts have an invalid `storageOffset' value */ 699 /* (it should be at least "6 + 12*num_names"). However, the string */ 700 /* offsets, computed as "storageOffset + entry->stringOffset", are */ 701 /* valid pointers within the name table... */ 702 /* */ 703 /* We thus can't check `storageOffset' right now. */ 704 /* */ 705 storage_start = table_pos + 6 + 12*table->numNameRecords; 706 storage_limit = table_pos + table_len; 707 708 if ( storage_start > storage_limit ) 709 { 710 FT_ERROR(( "invalid `name' table\n" )); 711 error = SFNT_Err_Name_Table_Missing; 712 goto Exit; 713 } 714 715 /* Allocate the array of name records. */ 716 count = table->numNameRecords; 717 table->numNameRecords = 0; 718 719 if ( FT_NEW_ARRAY( table->names, count ) || 720 FT_FRAME_ENTER( count * 12 ) ) 721 goto Exit; 722 723 /* Load the name records and determine how much storage is needed */ 724 /* to hold the strings themselves. */ 725 { 726 TT_NameEntryRec* entry = table->names; 727 728 729 for ( ; count > 0; count-- ) 730 { 731 if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) ) 732 continue; 733 734 /* check that the name is not empty */ 735 if ( entry->stringLength == 0 ) 736 continue; 737 738 /* check that the name string is within the table */ 739 entry->stringOffset += table_pos + table->storageOffset; 740 if ( entry->stringOffset < storage_start || 741 entry->stringOffset + entry->stringLength > storage_limit ) 742 { 743 /* invalid entry - ignore it */ 744 entry->stringOffset = 0; 745 entry->stringLength = 0; 746 continue; 747 } 748 749 entry++; 750 } 751 752 table->numNameRecords = (FT_UInt)( entry - table->names ); 753 } 754 755 FT_FRAME_EXIT(); 756 757 /* everything went well, update face->num_names */ 758 face->num_names = (FT_UShort) table->numNameRecords; 759 760 Exit: 761 return error; 762 } 763 764 765 /*************************************************************************/ 766 /* */ 767 /* <Function> */ 768 /* tt_face_free_names */ 769 /* */ 770 /* <Description> */ 771 /* Frees the name records. */ 772 /* */ 773 /* <Input> */ 774 /* face :: A handle to the target face object. */ 775 /* */ 776 FT_LOCAL_DEF( void ) 777 tt_face_free_name( TT_Face face ) 778 { 779 FT_Memory memory = face->root.driver->root.memory; 780 TT_NameTable table = &face->name_table; 781 TT_NameEntry entry = table->names; 782 FT_UInt count = table->numNameRecords; 783 784 785 if ( table->names ) 786 { 787 for ( ; count > 0; count--, entry++ ) 788 { 789 FT_FREE( entry->string ); 790 entry->stringLength = 0; 791 } 792 793 /* free strings table */ 794 FT_FREE( table->names ); 795 } 796 797 table->numNameRecords = 0; 798 table->format = 0; 799 table->storageOffset = 0; 800 } 801 802 803 /*************************************************************************/ 804 /* */ 805 /* <Function> */ 806 /* tt_face_load_cmap */ 807 /* */ 808 /* <Description> */ 809 /* Loads the cmap directory in a face object. The cmaps themselves */ 810 /* are loaded on demand in the `ttcmap.c' module. */ 811 /* */ 812 /* <Input> */ 813 /* face :: A handle to the target face object. */ 814 /* */ 815 /* stream :: A handle to the input stream. */ 816 /* */ 817 /* <Return> */ 818 /* FreeType error code. 0 means success. */ 819 /* */ 820 821 FT_LOCAL_DEF( FT_Error ) 822 tt_face_load_cmap( TT_Face face, 823 FT_Stream stream ) 824 { 825 FT_Error error; 826 827 828 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); 829 if ( error ) 830 goto Exit; 831 832 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) 833 face->cmap_size = 0; 834 835 Exit: 836 return error; 837 } 838 839 840 841 /*************************************************************************/ 842 /* */ 843 /* <Function> */ 844 /* tt_face_load_os2 */ 845 /* */ 846 /* <Description> */ 847 /* Loads the OS2 table. */ 848 /* */ 849 /* <Input> */ 850 /* face :: A handle to the target face object. */ 851 /* */ 852 /* stream :: A handle to the input stream. */ 853 /* */ 854 /* <Return> */ 855 /* FreeType error code. 0 means success. */ 856 /* */ 857 FT_LOCAL_DEF( FT_Error ) 858 tt_face_load_os2( TT_Face face, 859 FT_Stream stream ) 860 { 861 FT_Error error; 862 TT_OS2* os2; 863 864 const FT_Frame_Field os2_fields[] = 865 { 866#undef FT_STRUCTURE 867#define FT_STRUCTURE TT_OS2 868 869 FT_FRAME_START( 78 ), 870 FT_FRAME_USHORT( version ), 871 FT_FRAME_SHORT ( xAvgCharWidth ), 872 FT_FRAME_USHORT( usWeightClass ), 873 FT_FRAME_USHORT( usWidthClass ), 874 FT_FRAME_SHORT ( fsType ), 875 FT_FRAME_SHORT ( ySubscriptXSize ), 876 FT_FRAME_SHORT ( ySubscriptYSize ), 877 FT_FRAME_SHORT ( ySubscriptXOffset ), 878 FT_FRAME_SHORT ( ySubscriptYOffset ), 879 FT_FRAME_SHORT ( ySuperscriptXSize ), 880 FT_FRAME_SHORT ( ySuperscriptYSize ), 881 FT_FRAME_SHORT ( ySuperscriptXOffset ), 882 FT_FRAME_SHORT ( ySuperscriptYOffset ), 883 FT_FRAME_SHORT ( yStrikeoutSize ), 884 FT_FRAME_SHORT ( yStrikeoutPosition ), 885 FT_FRAME_SHORT ( sFamilyClass ), 886 FT_FRAME_BYTE ( panose[0] ), 887 FT_FRAME_BYTE ( panose[1] ), 888 FT_FRAME_BYTE ( panose[2] ), 889 FT_FRAME_BYTE ( panose[3] ), 890 FT_FRAME_BYTE ( panose[4] ), 891 FT_FRAME_BYTE ( panose[5] ), 892 FT_FRAME_BYTE ( panose[6] ), 893 FT_FRAME_BYTE ( panose[7] ), 894 FT_FRAME_BYTE ( panose[8] ), 895 FT_FRAME_BYTE ( panose[9] ), 896 FT_FRAME_ULONG ( ulUnicodeRange1 ), 897 FT_FRAME_ULONG ( ulUnicodeRange2 ), 898 FT_FRAME_ULONG ( ulUnicodeRange3 ), 899 FT_FRAME_ULONG ( ulUnicodeRange4 ), 900 FT_FRAME_BYTE ( achVendID[0] ), 901 FT_FRAME_BYTE ( achVendID[1] ), 902 FT_FRAME_BYTE ( achVendID[2] ), 903 FT_FRAME_BYTE ( achVendID[3] ), 904 905 FT_FRAME_USHORT( fsSelection ), 906 FT_FRAME_USHORT( usFirstCharIndex ), 907 FT_FRAME_USHORT( usLastCharIndex ), 908 FT_FRAME_SHORT ( sTypoAscender ), 909 FT_FRAME_SHORT ( sTypoDescender ), 910 FT_FRAME_SHORT ( sTypoLineGap ), 911 FT_FRAME_USHORT( usWinAscent ), 912 FT_FRAME_USHORT( usWinDescent ), 913 FT_FRAME_END 914 }; 915 916 const FT_Frame_Field os2_fields_extra[] = 917 { 918 FT_FRAME_START( 8 ), 919 FT_FRAME_ULONG( ulCodePageRange1 ), 920 FT_FRAME_ULONG( ulCodePageRange2 ), 921 FT_FRAME_END 922 }; 923 924 const FT_Frame_Field os2_fields_extra2[] = 925 { 926 FT_FRAME_START( 10 ), 927 FT_FRAME_SHORT ( sxHeight ), 928 FT_FRAME_SHORT ( sCapHeight ), 929 FT_FRAME_USHORT( usDefaultChar ), 930 FT_FRAME_USHORT( usBreakChar ), 931 FT_FRAME_USHORT( usMaxContext ), 932 FT_FRAME_END 933 }; 934 935 936 /* We now support old Mac fonts where the OS/2 table doesn't */ 937 /* exist. Simply put, we set the `version' field to 0xFFFF */ 938 /* and test this value each time we need to access the table. */ 939 error = face->goto_table( face, TTAG_OS2, stream, 0 ); 940 if ( error ) 941 goto Exit; 942 943 os2 = &face->os2; 944 945 if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) ) 946 goto Exit; 947 948 os2->ulCodePageRange1 = 0; 949 os2->ulCodePageRange2 = 0; 950 os2->sxHeight = 0; 951 os2->sCapHeight = 0; 952 os2->usDefaultChar = 0; 953 os2->usBreakChar = 0; 954 os2->usMaxContext = 0; 955 956 if ( os2->version >= 0x0001 ) 957 { 958 /* only version 1 tables */ 959 if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) ) 960 goto Exit; 961 962 if ( os2->version >= 0x0002 ) 963 { 964 /* only version 2 tables */ 965 if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) ) 966 goto Exit; 967 } 968 } 969 970 FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); 971 FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); 972 FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); 973 FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); 974 FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); 975 976 Exit: 977 return error; 978 } 979 980 981 /*************************************************************************/ 982 /* */ 983 /* <Function> */ 984 /* tt_face_load_postscript */ 985 /* */ 986 /* <Description> */ 987 /* Loads the Postscript table. */ 988 /* */ 989 /* <Input> */ 990 /* face :: A handle to the target face object. */ 991 /* */ 992 /* stream :: A handle to the input stream. */ 993 /* */ 994 /* <Return> */ 995 /* FreeType error code. 0 means success. */ 996 /* */ 997 FT_LOCAL_DEF( FT_Error ) 998 tt_face_load_post( TT_Face face, 999 FT_Stream stream ) 1000 { 1001 FT_Error error; 1002 TT_Postscript* post = &face->postscript; 1003 1004 static const FT_Frame_Field post_fields[] = 1005 { 1006#undef FT_STRUCTURE 1007#define FT_STRUCTURE TT_Postscript 1008 1009 FT_FRAME_START( 32 ), 1010 FT_FRAME_ULONG( FormatType ), 1011 FT_FRAME_ULONG( italicAngle ), 1012 FT_FRAME_SHORT( underlinePosition ), 1013 FT_FRAME_SHORT( underlineThickness ), 1014 FT_FRAME_ULONG( isFixedPitch ), 1015 FT_FRAME_ULONG( minMemType42 ), 1016 FT_FRAME_ULONG( maxMemType42 ), 1017 FT_FRAME_ULONG( minMemType1 ), 1018 FT_FRAME_ULONG( maxMemType1 ), 1019 FT_FRAME_END 1020 }; 1021 1022 1023 error = face->goto_table( face, TTAG_post, stream, 0 ); 1024 if ( error ) 1025 return error; 1026 1027 if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) 1028 return error; 1029 1030 /* we don't load the glyph names, we do that in another */ 1031 /* module (ttpost). */ 1032 1033 FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType )); 1034 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch 1035 ? " yes" : " no" )); 1036 1037 return SFNT_Err_Ok; 1038 } 1039 1040 1041 /*************************************************************************/ 1042 /* */ 1043 /* <Function> */ 1044 /* tt_face_load_pclt */ 1045 /* */ 1046 /* <Description> */ 1047 /* Loads the PCL 5 Table. */ 1048 /* */ 1049 /* <Input> */ 1050 /* face :: A handle to the target face object. */ 1051 /* */ 1052 /* stream :: A handle to the input stream. */ 1053 /* */ 1054 /* <Return> */ 1055 /* FreeType error code. 0 means success. */ 1056 /* */ 1057 FT_LOCAL_DEF( FT_Error ) 1058 tt_face_load_pclt( TT_Face face, 1059 FT_Stream stream ) 1060 { 1061 static const FT_Frame_Field pclt_fields[] = 1062 { 1063#undef FT_STRUCTURE 1064#define FT_STRUCTURE TT_PCLT 1065 1066 FT_FRAME_START( 54 ), 1067 FT_FRAME_ULONG ( Version ), 1068 FT_FRAME_ULONG ( FontNumber ), 1069 FT_FRAME_USHORT( Pitch ), 1070 FT_FRAME_USHORT( xHeight ), 1071 FT_FRAME_USHORT( Style ), 1072 FT_FRAME_USHORT( TypeFamily ), 1073 FT_FRAME_USHORT( CapHeight ), 1074 FT_FRAME_BYTES ( TypeFace, 16 ), 1075 FT_FRAME_BYTES ( CharacterComplement, 8 ), 1076 FT_FRAME_BYTES ( FileName, 6 ), 1077 FT_FRAME_CHAR ( StrokeWeight ), 1078 FT_FRAME_CHAR ( WidthType ), 1079 FT_FRAME_BYTE ( SerifStyle ), 1080 FT_FRAME_BYTE ( Reserved ), 1081 FT_FRAME_END 1082 }; 1083 1084 FT_Error error; 1085 TT_PCLT* pclt = &face->pclt; 1086 1087 1088 /* optional table */ 1089 error = face->goto_table( face, TTAG_PCLT, stream, 0 ); 1090 if ( error ) 1091 goto Exit; 1092 1093 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) 1094 goto Exit; 1095 1096 Exit: 1097 return error; 1098 } 1099 1100 1101 /*************************************************************************/ 1102 /* */ 1103 /* <Function> */ 1104 /* tt_face_load_gasp */ 1105 /* */ 1106 /* <Description> */ 1107 /* Loads the `gasp' table into a face object. */ 1108 /* */ 1109 /* <Input> */ 1110 /* face :: A handle to the target face object. */ 1111 /* */ 1112 /* stream :: The input stream. */ 1113 /* */ 1114 /* <Return> */ 1115 /* FreeType error code. 0 means success. */ 1116 /* */ 1117 FT_LOCAL_DEF( FT_Error ) 1118 tt_face_load_gasp( TT_Face face, 1119 FT_Stream stream ) 1120 { 1121 FT_Error error; 1122 FT_Memory memory = stream->memory; 1123 1124 FT_UInt j,num_ranges; 1125 TT_GaspRange gaspranges; 1126 1127 1128 /* the gasp table is optional */ 1129 error = face->goto_table( face, TTAG_gasp, stream, 0 ); 1130 if ( error ) 1131 goto Exit; 1132 1133 if ( FT_FRAME_ENTER( 4L ) ) 1134 goto Exit; 1135 1136 face->gasp.version = FT_GET_USHORT(); 1137 face->gasp.numRanges = FT_GET_USHORT(); 1138 1139 FT_FRAME_EXIT(); 1140 1141 /* only support versions 0 and 1 of the table */ 1142 if ( face->gasp.version >= 2 ) 1143 { 1144 face->gasp.numRanges = 0; 1145 error = SFNT_Err_Invalid_Table; 1146 goto Exit; 1147 } 1148 1149 num_ranges = face->gasp.numRanges; 1150 FT_TRACE3(( "numRanges: %u\n", num_ranges )); 1151 1152 if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) || 1153 FT_FRAME_ENTER( num_ranges * 4L ) ) 1154 goto Exit; 1155 1156 face->gasp.gaspRanges = gaspranges; 1157 1158 for ( j = 0; j < num_ranges; j++ ) 1159 { 1160 gaspranges[j].maxPPEM = FT_GET_USHORT(); 1161 gaspranges[j].gaspFlag = FT_GET_USHORT(); 1162 1163 FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n", 1164 j, 1165 gaspranges[j].maxPPEM, 1166 gaspranges[j].gaspFlag )); 1167 } 1168 1169 FT_FRAME_EXIT(); 1170 1171 Exit: 1172 return error; 1173 } 1174 1175 1176/* END */ 1177