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-2018 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; 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 292 { 293 error = FT_Err_Ok; 294 goto Exit; 295 } 296 else 297 { 298 FT_TRACE2(( "check_table_dir:" )); 299 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 300 FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" )); 301 #else 302 FT_TRACE2(( " neither `head' nor `sing' table found\n" )); 303 #endif 304 error = FT_THROW( Table_Missing ); 305 } 306 307 Exit: 308 return error; 309 } 310 311 312 /*************************************************************************/ 313 /* */ 314 /* <Function> */ 315 /* tt_face_load_font_dir */ 316 /* */ 317 /* <Description> */ 318 /* Loads the header of a SFNT font file. */ 319 /* */ 320 /* <Input> */ 321 /* face :: A handle to the target face object. */ 322 /* */ 323 /* stream :: The input stream. */ 324 /* */ 325 /* <Output> */ 326 /* sfnt :: The SFNT header. */ 327 /* */ 328 /* <Return> */ 329 /* FreeType error code. 0 means success. */ 330 /* */ 331 /* <Note> */ 332 /* The stream cursor must be at the beginning of the font directory. */ 333 /* */ 334 FT_LOCAL_DEF( FT_Error ) 335 tt_face_load_font_dir( TT_Face face, 336 FT_Stream stream ) 337 { 338 SFNT_HeaderRec sfnt; 339 FT_Error error; 340 FT_Memory memory = stream->memory; 341 FT_UShort nn, valid_entries = 0; 342 343 static const FT_Frame_Field offset_table_fields[] = 344 { 345 #undef FT_STRUCTURE 346 #define FT_STRUCTURE SFNT_HeaderRec 347 348 FT_FRAME_START( 8 ), 349 FT_FRAME_USHORT( num_tables ), 350 FT_FRAME_USHORT( search_range ), 351 FT_FRAME_USHORT( entry_selector ), 352 FT_FRAME_USHORT( range_shift ), 353 FT_FRAME_END 479 { 480 FT_TRACE2(( "\n" )); 481 482 /* we finally have a valid entry */ 483 face->dir_tables[valid_entries++] = entry; 484 } 485 } 486 487 /* final adjustment to number of tables */ 488 face->num_tables = valid_entries; 489 490 FT_FRAME_EXIT(); 491 492 FT_TRACE2(( "table directory loaded\n\n" )); 493 494 Exit: 495 return error; 496 } 497 498 499 /*************************************************************************/ 500 /* */ 501 /* <Function> */ 502 /* tt_face_load_any */ 503 /* */ 504 /* <Description> */ 505 /* Loads any font table into client memory. */ 506 /* */ 507 /* <Input> */ 508 /* face :: The face object to look for. */ 509 /* */ 510 /* tag :: The tag of table to load. Use the value 0 if you want */ 511 /* to access the whole font file, else set this parameter */ 512 /* to a valid TrueType table tag that you can forge with */ 513 /* the MAKE_TT_TAG macro. */ 514 /* */ 515 /* offset :: The starting offset in the table (or the file if */ 516 /* tag == 0). */ 517 /* */ 518 /* length :: The address of the decision variable: */ 519 /* */ 520 /* If length == NULL: */ 521 /* Loads the whole table. Returns an error if */ 522 /* `offset' == 0! */ 523 /* */ 524 /* If *length == 0: */ 525 /* Exits immediately; returning the length of the given */ 526 /* table or of the font file, depending on the value of */ 527 /* `tag'. */ 528 /* */ 529 /* If *length != 0: */ 530 /* Loads the next `length' bytes of table or font, */ 531 /* starting at offset `offset' (in table or font too). */ 532 /* */ 533 /* <Output> */ 534 /* buffer :: The address of target buffer. */ 535 /* */ 536 /* <Return> */ 537 /* FreeType error code. 0 means success. */ 538 /* */ 539 FT_LOCAL_DEF( FT_Error ) 540 tt_face_load_any( TT_Face face, 541 FT_ULong tag, 542 FT_Long offset, 543 FT_Byte* buffer, 544 FT_ULong* length ) 545 { 546 FT_Error error; 547 FT_Stream stream; 548 TT_Table table; 549 FT_ULong size; 550 551 552 if ( tag != 0 ) 553 { 554 /* look for tag in font directory */ 555 table = tt_face_lookup_table( face, tag ); 556 if ( !table ) 557 { 558 error = FT_THROW( Table_Missing ); 569 if ( length && *length == 0 ) 570 { 571 *length = size; 572 573 return FT_Err_Ok; 574 } 575 576 if ( length ) 577 size = *length; 578 579 stream = face->root.stream; 580 /* the `if' is syntactic sugar for picky compilers */ 581 if ( FT_STREAM_READ_AT( offset, buffer, size ) ) 582 goto Exit; 583 584 Exit: 585 return error; 586 } 587 588 589 /*************************************************************************/ 590 /* */ 591 /* <Function> */ 592 /* tt_face_load_generic_header */ 593 /* */ 594 /* <Description> */ 595 /* Loads the TrueType table `head' or `bhed'. */ 596 /* */ 597 /* <Input> */ 598 /* face :: A handle to the target face object. */ 599 /* */ 600 /* stream :: The input stream. */ 601 /* */ 602 /* <Return> */ 603 /* FreeType error code. 0 means success. */ 604 /* */ 605 static FT_Error 606 tt_face_load_generic_header( TT_Face face, 607 FT_Stream stream, 608 FT_ULong tag ) 609 { 610 FT_Error error; 611 TT_Header* header; 612 613 static const FT_Frame_Field header_fields[] = 614 { 615 #undef FT_STRUCTURE 616 #define FT_STRUCTURE TT_Header 617 618 FT_FRAME_START( 54 ), 619 FT_FRAME_ULONG ( Table_Version ), 620 FT_FRAME_ULONG ( Font_Revision ), 621 FT_FRAME_LONG ( CheckSum_Adjust ), 622 FT_FRAME_LONG ( Magic_Number ), 623 FT_FRAME_USHORT( Flags ), 624 FT_FRAME_USHORT( Units_Per_EM ), 625 FT_FRAME_LONG ( Created[0] ), 626 FT_FRAME_LONG ( Created[1] ), 627 FT_FRAME_LONG ( Modified[0] ), 628 FT_FRAME_LONG ( Modified[1] ), 629 FT_FRAME_SHORT ( xMin ), 630 FT_FRAME_SHORT ( yMin ), 631 FT_FRAME_SHORT ( xMax ), 632 FT_FRAME_SHORT ( yMax ), 633 FT_FRAME_USHORT( Mac_Style ), 634 FT_FRAME_USHORT( Lowest_Rec_PPEM ), 635 FT_FRAME_SHORT ( Font_Direction ), 636 FT_FRAME_SHORT ( Index_To_Loc_Format ), 637 FT_FRAME_SHORT ( Glyph_Data_Format ), 638 FT_FRAME_END 639 }; 640 641 642 error = face->goto_table( face, tag, stream, 0 ); 643 if ( error ) 644 goto Exit; 645 646 header = &face->header; 647 648 if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) 659 FT_LOCAL_DEF( FT_Error ) 660 tt_face_load_head( TT_Face face, 661 FT_Stream stream ) 662 { 663 return tt_face_load_generic_header( face, stream, TTAG_head ); 664 } 665 666 667 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 668 669 FT_LOCAL_DEF( FT_Error ) 670 tt_face_load_bhed( TT_Face face, 671 FT_Stream stream ) 672 { 673 return tt_face_load_generic_header( face, stream, TTAG_bhed ); 674 } 675 676 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 677 678 679 /*************************************************************************/ 680 /* */ 681 /* <Function> */ 682 /* tt_face_load_maxp */ 683 /* */ 684 /* <Description> */ 685 /* Loads the maximum profile into a face object. */ 686 /* */ 687 /* <Input> */ 688 /* face :: A handle to the target face object. */ 689 /* */ 690 /* stream :: The input stream. */ 691 /* */ 692 /* <Return> */ 693 /* FreeType error code. 0 means success. */ 694 /* */ 695 FT_LOCAL_DEF( FT_Error ) 696 tt_face_load_maxp( TT_Face face, 697 FT_Stream stream ) 698 { 699 FT_Error error; 700 TT_MaxProfile* maxProfile = &face->max_profile; 701 702 static const FT_Frame_Field maxp_fields[] = 703 { 704 #undef FT_STRUCTURE 705 #define FT_STRUCTURE TT_MaxProfile 706 707 FT_FRAME_START( 6 ), 708 FT_FRAME_LONG ( version ), 709 FT_FRAME_USHORT( numGlyphs ), 710 FT_FRAME_END 711 }; 712 713 static const FT_Frame_Field maxp_fields_extra[] = 714 { 767 768 /* we add 4 phantom points later */ 769 if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) ) 770 { 771 FT_TRACE0(( "tt_face_load_maxp:" 772 " too much twilight points in `maxp' table;\n" 773 " " 774 " some glyphs might be rendered incorrectly\n" )); 775 776 maxProfile->maxTwilightPoints = 0xFFFFU - 4; 777 } 778 } 779 780 FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); 781 782 Exit: 783 return error; 784 } 785 786 787 /*************************************************************************/ 788 /* */ 789 /* <Function> */ 790 /* tt_face_load_name */ 791 /* */ 792 /* <Description> */ 793 /* Loads the name records. */ 794 /* */ 795 /* <Input> */ 796 /* face :: A handle to the target face object. */ 797 /* */ 798 /* stream :: The input stream. */ 799 /* */ 800 /* <Return> */ 801 /* FreeType error code. 0 means success. */ 802 /* */ 803 FT_LOCAL_DEF( FT_Error ) 804 tt_face_load_name( TT_Face face, 805 FT_Stream stream ) 806 { 807 FT_Error error; 808 FT_Memory memory = stream->memory; 809 FT_ULong table_pos, table_len; 810 FT_ULong storage_start, storage_limit; 811 TT_NameTable table; 812 813 static const FT_Frame_Field name_table_fields[] = 814 { 815 #undef FT_STRUCTURE 816 #define FT_STRUCTURE TT_NameTableRec 817 818 FT_FRAME_START( 6 ), 819 FT_FRAME_USHORT( format ), 820 FT_FRAME_USHORT( numNameRecords ), 821 FT_FRAME_USHORT( storageOffset ), 822 FT_FRAME_END 964 } 965 966 /* reduce array size to the actually used elements */ 967 count = (FT_UInt)( entry - table->names ); 968 (void)FT_RENEW_ARRAY( table->names, 969 table->numNameRecords, 970 count ); 971 table->numNameRecords = count; 972 } 973 974 FT_FRAME_EXIT(); 975 976 /* everything went well, update face->num_names */ 977 face->num_names = (FT_UShort)table->numNameRecords; 978 979 Exit: 980 return error; 981 } 982 983 984 /*************************************************************************/ 985 /* */ 986 /* <Function> */ 987 /* tt_face_free_name */ 988 /* */ 989 /* <Description> */ 990 /* Frees the name records. */ 991 /* */ 992 /* <Input> */ 993 /* face :: A handle to the target face object. */ 994 /* */ 995 FT_LOCAL_DEF( void ) 996 tt_face_free_name( TT_Face face ) 997 { 998 FT_Memory memory = face->root.driver->root.memory; 999 TT_NameTable table = &face->name_table; 1000 1001 1002 if ( table->names ) 1003 { 1004 TT_Name entry = table->names; 1005 TT_Name limit = entry + table->numNameRecords; 1006 1007 1008 for ( ; entry < limit; entry++ ) 1009 FT_FREE( entry->string ); 1010 1011 FT_FREE( table->names ); 1012 } 1013 1014 if ( table->langTags ) 1015 { 1016 TT_LangTag entry = table->langTags; 1017 TT_LangTag limit = entry + table->numLangTagRecords; 1018 1019 1020 for ( ; entry < limit; entry++ ) 1021 FT_FREE( entry->string ); 1022 1023 FT_FREE( table->langTags ); 1024 } 1025 1026 table->numNameRecords = 0; 1027 table->numLangTagRecords = 0; 1028 table->format = 0; 1029 table->storageOffset = 0; 1030 } 1031 1032 1033 /*************************************************************************/ 1034 /* */ 1035 /* <Function> */ 1036 /* tt_face_load_cmap */ 1037 /* */ 1038 /* <Description> */ 1039 /* Loads the cmap directory in a face object. The cmaps themselves */ 1040 /* are loaded on demand in the `ttcmap.c' module. */ 1041 /* */ 1042 /* <Input> */ 1043 /* face :: A handle to the target face object. */ 1044 /* */ 1045 /* stream :: A handle to the input stream. */ 1046 /* */ 1047 /* <Return> */ 1048 /* FreeType error code. 0 means success. */ 1049 /* */ 1050 1051 FT_LOCAL_DEF( FT_Error ) 1052 tt_face_load_cmap( TT_Face face, 1053 FT_Stream stream ) 1054 { 1055 FT_Error error; 1056 1057 1058 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); 1059 if ( error ) 1060 goto Exit; 1061 1062 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) 1063 face->cmap_size = 0; 1064 1065 Exit: 1066 return error; 1067 } 1068 1069 1070 1071 /*************************************************************************/ 1072 /* */ 1073 /* <Function> */ 1074 /* tt_face_load_os2 */ 1075 /* */ 1076 /* <Description> */ 1077 /* Loads the OS2 table. */ 1078 /* */ 1079 /* <Input> */ 1080 /* face :: A handle to the target face object. */ 1081 /* */ 1082 /* stream :: A handle to the input stream. */ 1083 /* */ 1084 /* <Return> */ 1085 /* FreeType error code. 0 means success. */ 1086 /* */ 1087 FT_LOCAL_DEF( FT_Error ) 1088 tt_face_load_os2( TT_Face face, 1089 FT_Stream stream ) 1090 { 1091 FT_Error error; 1092 TT_OS2* os2; 1093 1094 static const FT_Frame_Field os2_fields[] = 1095 { 1096 #undef FT_STRUCTURE 1097 #define FT_STRUCTURE TT_OS2 1098 1099 FT_FRAME_START( 78 ), 1100 FT_FRAME_USHORT( version ), 1101 FT_FRAME_SHORT ( xAvgCharWidth ), 1102 FT_FRAME_USHORT( usWeightClass ), 1103 FT_FRAME_USHORT( usWidthClass ), 1104 FT_FRAME_SHORT ( fsType ), 1105 FT_FRAME_SHORT ( ySubscriptXSize ), 1106 FT_FRAME_SHORT ( ySubscriptYSize ), 1211 if ( os2->version >= 0x0005 ) 1212 { 1213 /* only version 5 tables */ 1214 if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) ) 1215 goto Exit; 1216 } 1217 } 1218 } 1219 1220 FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); 1221 FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); 1222 FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); 1223 FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); 1224 FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); 1225 1226 Exit: 1227 return error; 1228 } 1229 1230 1231 /*************************************************************************/ 1232 /* */ 1233 /* <Function> */ 1234 /* tt_face_load_postscript */ 1235 /* */ 1236 /* <Description> */ 1237 /* Loads the Postscript table. */ 1238 /* */ 1239 /* <Input> */ 1240 /* face :: A handle to the target face object. */ 1241 /* */ 1242 /* stream :: A handle to the input stream. */ 1243 /* */ 1244 /* <Return> */ 1245 /* FreeType error code. 0 means success. */ 1246 /* */ 1247 FT_LOCAL_DEF( FT_Error ) 1248 tt_face_load_post( TT_Face face, 1249 FT_Stream stream ) 1250 { 1251 FT_Error error; 1252 TT_Postscript* post = &face->postscript; 1253 1254 static const FT_Frame_Field post_fields[] = 1255 { 1256 #undef FT_STRUCTURE 1257 #define FT_STRUCTURE TT_Postscript 1258 1259 FT_FRAME_START( 32 ), 1260 FT_FRAME_LONG ( FormatType ), 1261 FT_FRAME_LONG ( italicAngle ), 1262 FT_FRAME_SHORT( underlinePosition ), 1263 FT_FRAME_SHORT( underlineThickness ), 1264 FT_FRAME_ULONG( isFixedPitch ), 1265 FT_FRAME_ULONG( minMemType42 ), 1266 FT_FRAME_ULONG( maxMemType42 ), 1271 1272 1273 error = face->goto_table( face, TTAG_post, stream, 0 ); 1274 if ( error ) 1275 return error; 1276 1277 if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) 1278 return error; 1279 1280 /* we don't load the glyph names, we do that in another */ 1281 /* module (ttpost). */ 1282 1283 FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType )); 1284 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch 1285 ? " yes" : " no" )); 1286 1287 return FT_Err_Ok; 1288 } 1289 1290 1291 /*************************************************************************/ 1292 /* */ 1293 /* <Function> */ 1294 /* tt_face_load_pclt */ 1295 /* */ 1296 /* <Description> */ 1297 /* Loads the PCL 5 Table. */ 1298 /* */ 1299 /* <Input> */ 1300 /* face :: A handle to the target face object. */ 1301 /* */ 1302 /* stream :: A handle to the input stream. */ 1303 /* */ 1304 /* <Return> */ 1305 /* FreeType error code. 0 means success. */ 1306 /* */ 1307 FT_LOCAL_DEF( FT_Error ) 1308 tt_face_load_pclt( TT_Face face, 1309 FT_Stream stream ) 1310 { 1311 static const FT_Frame_Field pclt_fields[] = 1312 { 1313 #undef FT_STRUCTURE 1314 #define FT_STRUCTURE TT_PCLT 1315 1316 FT_FRAME_START( 54 ), 1317 FT_FRAME_ULONG ( Version ), 1318 FT_FRAME_ULONG ( FontNumber ), 1319 FT_FRAME_USHORT( Pitch ), 1320 FT_FRAME_USHORT( xHeight ), 1321 FT_FRAME_USHORT( Style ), 1322 FT_FRAME_USHORT( TypeFamily ), 1323 FT_FRAME_USHORT( CapHeight ), 1324 FT_FRAME_USHORT( SymbolSet ), 1325 FT_FRAME_BYTES ( TypeFace, 16 ), 1326 FT_FRAME_BYTES ( CharacterComplement, 8 ), 1332 FT_FRAME_END 1333 }; 1334 1335 FT_Error error; 1336 TT_PCLT* pclt = &face->pclt; 1337 1338 1339 /* optional table */ 1340 error = face->goto_table( face, TTAG_PCLT, stream, 0 ); 1341 if ( error ) 1342 goto Exit; 1343 1344 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) 1345 goto Exit; 1346 1347 Exit: 1348 return error; 1349 } 1350 1351 1352 /*************************************************************************/ 1353 /* */ 1354 /* <Function> */ 1355 /* tt_face_load_gasp */ 1356 /* */ 1357 /* <Description> */ 1358 /* Loads the `gasp' table into a face object. */ 1359 /* */ 1360 /* <Input> */ 1361 /* face :: A handle to the target face object. */ 1362 /* */ 1363 /* stream :: The input stream. */ 1364 /* */ 1365 /* <Return> */ 1366 /* FreeType error code. 0 means success. */ 1367 /* */ 1368 FT_LOCAL_DEF( FT_Error ) 1369 tt_face_load_gasp( TT_Face face, 1370 FT_Stream stream ) 1371 { 1372 FT_Error error; 1373 FT_Memory memory = stream->memory; 1374 1375 FT_UInt j,num_ranges; 1376 TT_GaspRange gaspranges = NULL; 1377 1378 1379 /* the gasp table is optional */ 1380 error = face->goto_table( face, TTAG_gasp, stream, 0 ); 1381 if ( error ) 1382 goto Exit; 1383 1384 if ( FT_FRAME_ENTER( 4L ) ) 1385 goto Exit; 1386 1387 face->gasp.version = FT_GET_USHORT(); | 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 (C) 1996-2019 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 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 :: 49 * A face object handle. 50 * 51 * tag :: 52 * The searched tag. 53 * 54 * @Return: 55 * A pointer to the table directory entry. 0 if not found. 56 */ 57 FT_LOCAL_DEF( TT_Table ) 58 tt_face_lookup_table( TT_Face face, 59 FT_ULong tag ) 60 { 61 TT_Table entry; 62 TT_Table limit; 63 #ifdef FT_DEBUG_LEVEL_TRACE 64 FT_Bool zero_length = FALSE; 65 #endif 66 67 68 FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ", 69 face, 70 (FT_Char)( tag >> 24 ), 71 (FT_Char)( tag >> 16 ), 72 (FT_Char)( tag >> 8 ), 73 (FT_Char)( tag ) )); 74 75 entry = face->dir_tables; 76 limit = entry + face->num_tables; 86 FT_TRACE4(( "found table.\n" )); 87 return entry; 88 } 89 #ifdef FT_DEBUG_LEVEL_TRACE 90 zero_length = TRUE; 91 #endif 92 } 93 } 94 95 #ifdef FT_DEBUG_LEVEL_TRACE 96 if ( zero_length ) 97 FT_TRACE4(( "ignoring empty table\n" )); 98 else 99 FT_TRACE4(( "could not find table\n" )); 100 #endif 101 102 return NULL; 103 } 104 105 106 /************************************************************************** 107 * 108 * @Function: 109 * tt_face_goto_table 110 * 111 * @Description: 112 * Looks for a TrueType table by name, then seek a stream to it. 113 * 114 * @Input: 115 * face :: 116 * A face object handle. 117 * 118 * tag :: 119 * The searched tag. 120 * 121 * stream :: 122 * The stream to seek when the table is found. 123 * 124 * @Output: 125 * length :: 126 * The length of the table if found, undefined otherwise. 127 * 128 * @Return: 129 * FreeType error code. 0 means success. 130 */ 131 FT_LOCAL_DEF( FT_Error ) 132 tt_face_goto_table( TT_Face face, 133 FT_ULong tag, 134 FT_Stream stream, 135 FT_ULong* length ) 136 { 137 TT_Table table; 138 FT_Error error; 139 140 141 table = tt_face_lookup_table( face, tag ); 142 if ( table ) 143 { 144 if ( length ) 145 *length = table->Length; 146 147 if ( FT_STREAM_SEEK( table->Offset ) ) 148 goto Exit; 149 } 150 else 298 { 299 error = FT_Err_Ok; 300 goto Exit; 301 } 302 else 303 { 304 FT_TRACE2(( "check_table_dir:" )); 305 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 306 FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" )); 307 #else 308 FT_TRACE2(( " neither `head' nor `sing' table found\n" )); 309 #endif 310 error = FT_THROW( Table_Missing ); 311 } 312 313 Exit: 314 return error; 315 } 316 317 318 /************************************************************************** 319 * 320 * @Function: 321 * tt_face_load_font_dir 322 * 323 * @Description: 324 * Loads the header of a SFNT font file. 325 * 326 * @Input: 327 * face :: 328 * A handle to the target face object. 329 * 330 * stream :: 331 * The input stream. 332 * 333 * @Output: 334 * sfnt :: 335 * The SFNT header. 336 * 337 * @Return: 338 * FreeType error code. 0 means success. 339 * 340 * @Note: 341 * The stream cursor must be at the beginning of the font directory. 342 */ 343 FT_LOCAL_DEF( FT_Error ) 344 tt_face_load_font_dir( TT_Face face, 345 FT_Stream stream ) 346 { 347 SFNT_HeaderRec sfnt; 348 FT_Error error; 349 FT_Memory memory = stream->memory; 350 FT_UShort nn, valid_entries = 0; 351 352 static const FT_Frame_Field offset_table_fields[] = 353 { 354 #undef FT_STRUCTURE 355 #define FT_STRUCTURE SFNT_HeaderRec 356 357 FT_FRAME_START( 8 ), 358 FT_FRAME_USHORT( num_tables ), 359 FT_FRAME_USHORT( search_range ), 360 FT_FRAME_USHORT( entry_selector ), 361 FT_FRAME_USHORT( range_shift ), 362 FT_FRAME_END 488 { 489 FT_TRACE2(( "\n" )); 490 491 /* we finally have a valid entry */ 492 face->dir_tables[valid_entries++] = entry; 493 } 494 } 495 496 /* final adjustment to number of tables */ 497 face->num_tables = valid_entries; 498 499 FT_FRAME_EXIT(); 500 501 FT_TRACE2(( "table directory loaded\n\n" )); 502 503 Exit: 504 return error; 505 } 506 507 508 /************************************************************************** 509 * 510 * @Function: 511 * tt_face_load_any 512 * 513 * @Description: 514 * Loads any font table into client memory. 515 * 516 * @Input: 517 * face :: 518 * The face object to look for. 519 * 520 * tag :: 521 * The tag of table to load. Use the value 0 if you want 522 * to access the whole font file, else set this parameter 523 * to a valid TrueType table tag that you can forge with 524 * the MAKE_TT_TAG macro. 525 * 526 * offset :: 527 * The starting offset in the table (or the file if 528 * tag == 0). 529 * 530 * length :: 531 * The address of the decision variable: 532 * 533 * If length == NULL: 534 * Loads the whole table. Returns an error if 535 * `offset' == 0! 536 * 537 * If *length == 0: 538 * Exits immediately; returning the length of the given 539 * table or of the font file, depending on the value of 540 * `tag'. 541 * 542 * If *length != 0: 543 * Loads the next `length' bytes of table or font, 544 * starting at offset `offset' (in table or font too). 545 * 546 * @Output: 547 * buffer :: 548 * The address of target buffer. 549 * 550 * @Return: 551 * FreeType error code. 0 means success. 552 */ 553 FT_LOCAL_DEF( FT_Error ) 554 tt_face_load_any( TT_Face face, 555 FT_ULong tag, 556 FT_Long offset, 557 FT_Byte* buffer, 558 FT_ULong* length ) 559 { 560 FT_Error error; 561 FT_Stream stream; 562 TT_Table table; 563 FT_ULong size; 564 565 566 if ( tag != 0 ) 567 { 568 /* look for tag in font directory */ 569 table = tt_face_lookup_table( face, tag ); 570 if ( !table ) 571 { 572 error = FT_THROW( Table_Missing ); 583 if ( length && *length == 0 ) 584 { 585 *length = size; 586 587 return FT_Err_Ok; 588 } 589 590 if ( length ) 591 size = *length; 592 593 stream = face->root.stream; 594 /* the `if' is syntactic sugar for picky compilers */ 595 if ( FT_STREAM_READ_AT( offset, buffer, size ) ) 596 goto Exit; 597 598 Exit: 599 return error; 600 } 601 602 603 /************************************************************************** 604 * 605 * @Function: 606 * tt_face_load_generic_header 607 * 608 * @Description: 609 * Loads the TrueType table `head' or `bhed'. 610 * 611 * @Input: 612 * face :: 613 * A handle to the target face object. 614 * 615 * stream :: 616 * The input stream. 617 * 618 * @Return: 619 * FreeType error code. 0 means success. 620 */ 621 static FT_Error 622 tt_face_load_generic_header( TT_Face face, 623 FT_Stream stream, 624 FT_ULong tag ) 625 { 626 FT_Error error; 627 TT_Header* header; 628 629 static const FT_Frame_Field header_fields[] = 630 { 631 #undef FT_STRUCTURE 632 #define FT_STRUCTURE TT_Header 633 634 FT_FRAME_START( 54 ), 635 FT_FRAME_ULONG ( Table_Version ), 636 FT_FRAME_ULONG ( Font_Revision ), 637 FT_FRAME_LONG ( CheckSum_Adjust ), 638 FT_FRAME_LONG ( Magic_Number ), 639 FT_FRAME_USHORT( Flags ), 640 FT_FRAME_USHORT( Units_Per_EM ), 641 FT_FRAME_ULONG ( Created[0] ), 642 FT_FRAME_ULONG ( Created[1] ), 643 FT_FRAME_ULONG ( Modified[0] ), 644 FT_FRAME_ULONG ( Modified[1] ), 645 FT_FRAME_SHORT ( xMin ), 646 FT_FRAME_SHORT ( yMin ), 647 FT_FRAME_SHORT ( xMax ), 648 FT_FRAME_SHORT ( yMax ), 649 FT_FRAME_USHORT( Mac_Style ), 650 FT_FRAME_USHORT( Lowest_Rec_PPEM ), 651 FT_FRAME_SHORT ( Font_Direction ), 652 FT_FRAME_SHORT ( Index_To_Loc_Format ), 653 FT_FRAME_SHORT ( Glyph_Data_Format ), 654 FT_FRAME_END 655 }; 656 657 658 error = face->goto_table( face, tag, stream, 0 ); 659 if ( error ) 660 goto Exit; 661 662 header = &face->header; 663 664 if ( FT_STREAM_READ_FIELDS( header_fields, header ) ) 675 FT_LOCAL_DEF( FT_Error ) 676 tt_face_load_head( TT_Face face, 677 FT_Stream stream ) 678 { 679 return tt_face_load_generic_header( face, stream, TTAG_head ); 680 } 681 682 683 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 684 685 FT_LOCAL_DEF( FT_Error ) 686 tt_face_load_bhed( TT_Face face, 687 FT_Stream stream ) 688 { 689 return tt_face_load_generic_header( face, stream, TTAG_bhed ); 690 } 691 692 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 693 694 695 /************************************************************************** 696 * 697 * @Function: 698 * tt_face_load_maxp 699 * 700 * @Description: 701 * Loads the maximum profile into a face object. 702 * 703 * @Input: 704 * face :: 705 * A handle to the target face object. 706 * 707 * stream :: 708 * The input stream. 709 * 710 * @Return: 711 * FreeType error code. 0 means success. 712 */ 713 FT_LOCAL_DEF( FT_Error ) 714 tt_face_load_maxp( TT_Face face, 715 FT_Stream stream ) 716 { 717 FT_Error error; 718 TT_MaxProfile* maxProfile = &face->max_profile; 719 720 static const FT_Frame_Field maxp_fields[] = 721 { 722 #undef FT_STRUCTURE 723 #define FT_STRUCTURE TT_MaxProfile 724 725 FT_FRAME_START( 6 ), 726 FT_FRAME_LONG ( version ), 727 FT_FRAME_USHORT( numGlyphs ), 728 FT_FRAME_END 729 }; 730 731 static const FT_Frame_Field maxp_fields_extra[] = 732 { 785 786 /* we add 4 phantom points later */ 787 if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) ) 788 { 789 FT_TRACE0(( "tt_face_load_maxp:" 790 " too much twilight points in `maxp' table;\n" 791 " " 792 " some glyphs might be rendered incorrectly\n" )); 793 794 maxProfile->maxTwilightPoints = 0xFFFFU - 4; 795 } 796 } 797 798 FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs )); 799 800 Exit: 801 return error; 802 } 803 804 805 /************************************************************************** 806 * 807 * @Function: 808 * tt_face_load_name 809 * 810 * @Description: 811 * Loads the name records. 812 * 813 * @Input: 814 * face :: 815 * A handle to the target face object. 816 * 817 * stream :: 818 * The input stream. 819 * 820 * @Return: 821 * FreeType error code. 0 means success. 822 */ 823 FT_LOCAL_DEF( FT_Error ) 824 tt_face_load_name( TT_Face face, 825 FT_Stream stream ) 826 { 827 FT_Error error; 828 FT_Memory memory = stream->memory; 829 FT_ULong table_pos, table_len; 830 FT_ULong storage_start, storage_limit; 831 TT_NameTable table; 832 833 static const FT_Frame_Field name_table_fields[] = 834 { 835 #undef FT_STRUCTURE 836 #define FT_STRUCTURE TT_NameTableRec 837 838 FT_FRAME_START( 6 ), 839 FT_FRAME_USHORT( format ), 840 FT_FRAME_USHORT( numNameRecords ), 841 FT_FRAME_USHORT( storageOffset ), 842 FT_FRAME_END 984 } 985 986 /* reduce array size to the actually used elements */ 987 count = (FT_UInt)( entry - table->names ); 988 (void)FT_RENEW_ARRAY( table->names, 989 table->numNameRecords, 990 count ); 991 table->numNameRecords = count; 992 } 993 994 FT_FRAME_EXIT(); 995 996 /* everything went well, update face->num_names */ 997 face->num_names = (FT_UShort)table->numNameRecords; 998 999 Exit: 1000 return error; 1001 } 1002 1003 1004 /************************************************************************** 1005 * 1006 * @Function: 1007 * tt_face_free_name 1008 * 1009 * @Description: 1010 * Frees the name records. 1011 * 1012 * @Input: 1013 * face :: 1014 * A handle to the target face object. 1015 */ 1016 FT_LOCAL_DEF( void ) 1017 tt_face_free_name( TT_Face face ) 1018 { 1019 FT_Memory memory = face->root.driver->root.memory; 1020 TT_NameTable table = &face->name_table; 1021 1022 1023 if ( table->names ) 1024 { 1025 TT_Name entry = table->names; 1026 TT_Name limit = entry + table->numNameRecords; 1027 1028 1029 for ( ; entry < limit; entry++ ) 1030 FT_FREE( entry->string ); 1031 1032 FT_FREE( table->names ); 1033 } 1034 1035 if ( table->langTags ) 1036 { 1037 TT_LangTag entry = table->langTags; 1038 TT_LangTag limit = entry + table->numLangTagRecords; 1039 1040 1041 for ( ; entry < limit; entry++ ) 1042 FT_FREE( entry->string ); 1043 1044 FT_FREE( table->langTags ); 1045 } 1046 1047 table->numNameRecords = 0; 1048 table->numLangTagRecords = 0; 1049 table->format = 0; 1050 table->storageOffset = 0; 1051 } 1052 1053 1054 /************************************************************************** 1055 * 1056 * @Function: 1057 * tt_face_load_cmap 1058 * 1059 * @Description: 1060 * Loads the cmap directory in a face object. The cmaps themselves 1061 * are loaded on demand in the `ttcmap.c' module. 1062 * 1063 * @Input: 1064 * face :: 1065 * A handle to the target face object. 1066 * 1067 * stream :: 1068 * A handle to the input stream. 1069 * 1070 * @Return: 1071 * FreeType error code. 0 means success. 1072 */ 1073 1074 FT_LOCAL_DEF( FT_Error ) 1075 tt_face_load_cmap( TT_Face face, 1076 FT_Stream stream ) 1077 { 1078 FT_Error error; 1079 1080 1081 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size ); 1082 if ( error ) 1083 goto Exit; 1084 1085 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) ) 1086 face->cmap_size = 0; 1087 1088 Exit: 1089 return error; 1090 } 1091 1092 1093 1094 /************************************************************************** 1095 * 1096 * @Function: 1097 * tt_face_load_os2 1098 * 1099 * @Description: 1100 * Loads the OS2 table. 1101 * 1102 * @Input: 1103 * face :: 1104 * A handle to the target face object. 1105 * 1106 * stream :: 1107 * A handle to the input stream. 1108 * 1109 * @Return: 1110 * FreeType error code. 0 means success. 1111 */ 1112 FT_LOCAL_DEF( FT_Error ) 1113 tt_face_load_os2( TT_Face face, 1114 FT_Stream stream ) 1115 { 1116 FT_Error error; 1117 TT_OS2* os2; 1118 1119 static const FT_Frame_Field os2_fields[] = 1120 { 1121 #undef FT_STRUCTURE 1122 #define FT_STRUCTURE TT_OS2 1123 1124 FT_FRAME_START( 78 ), 1125 FT_FRAME_USHORT( version ), 1126 FT_FRAME_SHORT ( xAvgCharWidth ), 1127 FT_FRAME_USHORT( usWeightClass ), 1128 FT_FRAME_USHORT( usWidthClass ), 1129 FT_FRAME_SHORT ( fsType ), 1130 FT_FRAME_SHORT ( ySubscriptXSize ), 1131 FT_FRAME_SHORT ( ySubscriptYSize ), 1236 if ( os2->version >= 0x0005 ) 1237 { 1238 /* only version 5 tables */ 1239 if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) ) 1240 goto Exit; 1241 } 1242 } 1243 } 1244 1245 FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender )); 1246 FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender )); 1247 FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent )); 1248 FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent )); 1249 FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection )); 1250 1251 Exit: 1252 return error; 1253 } 1254 1255 1256 /************************************************************************** 1257 * 1258 * @Function: 1259 * tt_face_load_postscript 1260 * 1261 * @Description: 1262 * Loads the Postscript table. 1263 * 1264 * @Input: 1265 * face :: 1266 * A handle to the target face object. 1267 * 1268 * stream :: 1269 * A handle to the input stream. 1270 * 1271 * @Return: 1272 * FreeType error code. 0 means success. 1273 */ 1274 FT_LOCAL_DEF( FT_Error ) 1275 tt_face_load_post( TT_Face face, 1276 FT_Stream stream ) 1277 { 1278 FT_Error error; 1279 TT_Postscript* post = &face->postscript; 1280 1281 static const FT_Frame_Field post_fields[] = 1282 { 1283 #undef FT_STRUCTURE 1284 #define FT_STRUCTURE TT_Postscript 1285 1286 FT_FRAME_START( 32 ), 1287 FT_FRAME_LONG ( FormatType ), 1288 FT_FRAME_LONG ( italicAngle ), 1289 FT_FRAME_SHORT( underlinePosition ), 1290 FT_FRAME_SHORT( underlineThickness ), 1291 FT_FRAME_ULONG( isFixedPitch ), 1292 FT_FRAME_ULONG( minMemType42 ), 1293 FT_FRAME_ULONG( maxMemType42 ), 1298 1299 1300 error = face->goto_table( face, TTAG_post, stream, 0 ); 1301 if ( error ) 1302 return error; 1303 1304 if ( FT_STREAM_READ_FIELDS( post_fields, post ) ) 1305 return error; 1306 1307 /* we don't load the glyph names, we do that in another */ 1308 /* module (ttpost). */ 1309 1310 FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType )); 1311 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch 1312 ? " yes" : " no" )); 1313 1314 return FT_Err_Ok; 1315 } 1316 1317 1318 /************************************************************************** 1319 * 1320 * @Function: 1321 * tt_face_load_pclt 1322 * 1323 * @Description: 1324 * Loads the PCL 5 Table. 1325 * 1326 * @Input: 1327 * face :: 1328 * A handle to the target face object. 1329 * 1330 * stream :: 1331 * A handle to the input stream. 1332 * 1333 * @Return: 1334 * FreeType error code. 0 means success. 1335 */ 1336 FT_LOCAL_DEF( FT_Error ) 1337 tt_face_load_pclt( TT_Face face, 1338 FT_Stream stream ) 1339 { 1340 static const FT_Frame_Field pclt_fields[] = 1341 { 1342 #undef FT_STRUCTURE 1343 #define FT_STRUCTURE TT_PCLT 1344 1345 FT_FRAME_START( 54 ), 1346 FT_FRAME_ULONG ( Version ), 1347 FT_FRAME_ULONG ( FontNumber ), 1348 FT_FRAME_USHORT( Pitch ), 1349 FT_FRAME_USHORT( xHeight ), 1350 FT_FRAME_USHORT( Style ), 1351 FT_FRAME_USHORT( TypeFamily ), 1352 FT_FRAME_USHORT( CapHeight ), 1353 FT_FRAME_USHORT( SymbolSet ), 1354 FT_FRAME_BYTES ( TypeFace, 16 ), 1355 FT_FRAME_BYTES ( CharacterComplement, 8 ), 1361 FT_FRAME_END 1362 }; 1363 1364 FT_Error error; 1365 TT_PCLT* pclt = &face->pclt; 1366 1367 1368 /* optional table */ 1369 error = face->goto_table( face, TTAG_PCLT, stream, 0 ); 1370 if ( error ) 1371 goto Exit; 1372 1373 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) ) 1374 goto Exit; 1375 1376 Exit: 1377 return error; 1378 } 1379 1380 1381 /************************************************************************** 1382 * 1383 * @Function: 1384 * tt_face_load_gasp 1385 * 1386 * @Description: 1387 * Loads the `gasp' table into a face object. 1388 * 1389 * @Input: 1390 * face :: 1391 * A handle to the target face object. 1392 * 1393 * stream :: 1394 * The input stream. 1395 * 1396 * @Return: 1397 * FreeType error code. 0 means success. 1398 */ 1399 FT_LOCAL_DEF( FT_Error ) 1400 tt_face_load_gasp( TT_Face face, 1401 FT_Stream stream ) 1402 { 1403 FT_Error error; 1404 FT_Memory memory = stream->memory; 1405 1406 FT_UInt j,num_ranges; 1407 TT_GaspRange gaspranges = NULL; 1408 1409 1410 /* the gasp table is optional */ 1411 error = face->goto_table( face, TTAG_gasp, stream, 0 ); 1412 if ( error ) 1413 goto Exit; 1414 1415 if ( FT_FRAME_ENTER( 4L ) ) 1416 goto Exit; 1417 1418 face->gasp.version = FT_GET_USHORT(); |