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