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