1 /****************************************************************************
5 * Load the basic TrueType tables, i.e., tables that can be either in
6 * TTF or OTF fonts (body).
8 * Copyright (C) 1996-2023 by
9 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/tttags.h>
28 /**************************************************************************
30 * The macro FT_COMPONENT is used in trace mode. It is an implicit
31 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
32 * messages during execution.
35 #define FT_COMPONENT ttload
38 /**************************************************************************
41 * tt_face_lookup_table
44 * Looks for a TrueType table by name.
48 * A face object handle.
54 * A pointer to the table directory entry. 0 if not found.
56 FT_LOCAL_DEF( TT_Table )
57 tt_face_lookup_table( TT_Face face,
62 #ifdef FT_DEBUG_LEVEL_TRACE
63 FT_Bool zero_length = FALSE;
67 FT_TRACE4(( "tt_face_lookup_table: %p, `%c%c%c%c' -- ",
69 (FT_Char)( tag >> 24 ),
70 (FT_Char)( tag >> 16 ),
71 (FT_Char)( tag >> 8 ),
74 entry = face->dir_tables;
75 limit = entry + face->num_tables;
77 for ( ; entry < limit; entry++ )
79 /* For compatibility with Windows, we consider */
80 /* zero-length tables the same as missing tables. */
81 if ( entry->Tag == tag )
83 if ( entry->Length != 0 )
85 FT_TRACE4(( "found table.\n" ));
88 #ifdef FT_DEBUG_LEVEL_TRACE
94 #ifdef FT_DEBUG_LEVEL_TRACE
96 FT_TRACE4(( "ignoring empty table\n" ));
98 FT_TRACE4(( "could not find table\n" ));
105 /**************************************************************************
111 * Looks for a TrueType table by name, then seek a stream to it.
115 * A face object handle.
121 * The stream to seek when the table is found.
125 * The length of the table if found, undefined otherwise.
128 * FreeType error code. 0 means success.
130 FT_LOCAL_DEF( FT_Error )
131 tt_face_goto_table( TT_Face face,
140 table = tt_face_lookup_table( face, tag );
144 *length = table->Length;
146 if ( FT_STREAM_SEEK( table->Offset ) )
150 error = FT_THROW( Table_Missing );
159 /* - check that `num_tables' is valid (and adjust it if necessary); */
160 /* also return the number of valid table entries */
162 /* - look for a `head' table, check its size, and parse it to check */
163 /* whether its `magic' field is correctly set */
165 /* - errors (except errors returned by stream handling) */
167 /* SFNT_Err_Unknown_File_Format: */
168 /* no table is defined in directory, it is not sfnt-wrapped */
170 /* SFNT_Err_Table_Missing: */
171 /* table directory is valid, but essential tables */
172 /* (head/bhed/SING) are missing */
175 check_table_dir( SFNT_Header sfnt,
180 FT_UShort nn, valid_entries = 0;
181 FT_UInt has_head = 0, has_sing = 0, has_meta = 0;
182 FT_ULong offset = sfnt->offset + 12;
184 static const FT_Frame_Field table_dir_entry_fields[] =
187 #define FT_STRUCTURE TT_TableRec
189 FT_FRAME_START( 16 ),
190 FT_FRAME_ULONG( Tag ),
191 FT_FRAME_ULONG( CheckSum ),
192 FT_FRAME_ULONG( Offset ),
193 FT_FRAME_ULONG( Length ),
198 if ( FT_STREAM_SEEK( offset ) )
201 for ( nn = 0; nn < sfnt->num_tables; nn++ )
206 if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
208 FT_TRACE2(( "check_table_dir:"
209 " can read only %hu table%s in font (instead of %hu)\n",
210 nn, nn == 1 ? "" : "s", sfnt->num_tables ));
211 sfnt->num_tables = nn;
215 /* we ignore invalid tables */
217 if ( table.Offset > stream->size )
219 FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn ));
222 else if ( table.Length > stream->size - table.Offset )
224 /* Some tables have such a simple structure that clipping its */
225 /* contents is harmless. This also makes FreeType less sensitive */
226 /* to invalid table lengths (which programs like Acroread seem to */
227 /* ignore in general). */
229 if ( table.Tag == TTAG_hmtx ||
230 table.Tag == TTAG_vmtx )
234 FT_TRACE2(( "check_table_dir: table entry %hu invalid\n", nn ));
241 if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
246 #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
247 if ( table.Tag == TTAG_head )
252 * The table length should be 0x36, but certain font tools make it
253 * 0x38, so we will just check that it is greater.
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!
260 if ( table.Length < 0x36 )
262 FT_TRACE2(( "check_table_dir:"
263 " `head' or `bhed' table too small\n" ));
264 error = FT_THROW( Table_Missing );
268 if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
269 FT_READ_ULONG( magic ) )
272 if ( magic != 0x5F0F3CF5UL )
273 FT_TRACE2(( "check_table_dir:"
274 " invalid magic number in `head' or `bhed' table\n"));
276 if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
279 else if ( table.Tag == TTAG_SING )
281 else if ( table.Tag == TTAG_META )
285 *valid = valid_entries;
287 if ( !valid_entries )
289 FT_TRACE2(( "check_table_dir: no valid tables found\n" ));
290 error = FT_THROW( Unknown_File_Format );
294 /* if `sing' and `meta' tables are present, there is no `head' table */
295 if ( has_head || ( has_sing && has_meta ) )
302 FT_TRACE2(( "check_table_dir:" ));
303 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
304 FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
306 FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
308 error = FT_THROW( Table_Missing );
316 /**************************************************************************
319 * tt_face_load_font_dir
322 * Loads the header of a SFNT font file.
326 * A handle to the target face object.
336 * FreeType error code. 0 means success.
339 * The stream cursor must be at the beginning of the font directory.
341 FT_LOCAL_DEF( FT_Error )
342 tt_face_load_font_dir( TT_Face face,
347 FT_Memory memory = stream->memory;
348 FT_UShort nn, valid_entries = 0;
350 static const FT_Frame_Field offset_table_fields[] =
353 #define FT_STRUCTURE SFNT_HeaderRec
356 FT_FRAME_USHORT( num_tables ),
357 FT_FRAME_USHORT( search_range ),
358 FT_FRAME_USHORT( entry_selector ),
359 FT_FRAME_USHORT( range_shift ),
364 FT_TRACE2(( "tt_face_load_font_dir: %p\n", (void *)face ));
366 /* read the offset table */
368 sfnt.offset = FT_STREAM_POS();
370 if ( FT_READ_ULONG( sfnt.format_tag ) ||
371 FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
374 /* many fonts don't have these fields set correctly */
376 if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) ||
377 sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
378 return FT_THROW( Unknown_File_Format );
381 /* load the table directory */
383 FT_TRACE2(( "-- Number of tables: %10hu\n", sfnt.num_tables ));
384 FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag ));
386 if ( sfnt.format_tag != TTAG_OTTO )
389 error = check_table_dir( &sfnt, stream, &valid_entries );
392 FT_TRACE2(( "tt_face_load_font_dir:"
393 " invalid table directory for TrueType\n" ));
399 valid_entries = sfnt.num_tables;
400 if ( !valid_entries )
402 FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" ));
403 error = FT_THROW( Unknown_File_Format );
408 face->num_tables = valid_entries;
409 face->format_tag = sfnt.format_tag;
411 if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
414 if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
415 FT_FRAME_ENTER( sfnt.num_tables * 16L ) )
419 FT_TRACE2(( " tag offset length checksum\n" ));
420 FT_TRACE2(( " ----------------------------------\n" ));
423 for ( nn = 0; nn < sfnt.num_tables; nn++ )
430 entry.Tag = FT_GET_TAG4();
431 entry.CheckSum = FT_GET_ULONG();
432 entry.Offset = FT_GET_ULONG();
433 entry.Length = FT_GET_ULONG();
435 /* ignore invalid tables that can't be sanitized */
437 if ( entry.Offset > stream->size )
439 else if ( entry.Length > stream->size - entry.Offset )
441 if ( entry.Tag == TTAG_hmtx ||
442 entry.Tag == TTAG_vmtx )
444 #ifdef FT_DEBUG_LEVEL_TRACE
445 FT_ULong old_length = entry.Length;
449 /* make metrics table length a multiple of 4 */
450 entry.Length = ( stream->size - entry.Offset ) & ~3U;
452 FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx"
453 " (sanitized; original length %08lx)",
454 (FT_Char)( entry.Tag >> 24 ),
455 (FT_Char)( entry.Tag >> 16 ),
456 (FT_Char)( entry.Tag >> 8 ),
457 (FT_Char)( entry.Tag ),
466 #ifdef FT_DEBUG_LEVEL_TRACE
468 FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx",
469 (FT_Char)( entry.Tag >> 24 ),
470 (FT_Char)( entry.Tag >> 16 ),
471 (FT_Char)( entry.Tag >> 8 ),
472 (FT_Char)( entry.Tag ),
478 /* ignore duplicate tables – the first one wins */
480 for ( i = 0; i < valid_entries; i++ )
482 if ( face->dir_tables[i].Tag == entry.Tag )
490 FT_TRACE2(( " (duplicate, ignored)\n" ));
497 /* we finally have a valid entry */
498 face->dir_tables[valid_entries++] = entry;
502 /* final adjustment to number of tables */
503 face->num_tables = valid_entries;
507 if ( !valid_entries )
509 FT_TRACE2(( "tt_face_load_font_dir: no valid tables found\n" ));
510 error = FT_THROW( Unknown_File_Format );
514 FT_TRACE2(( "table directory loaded\n" ));
522 /**************************************************************************
528 * Loads any font table into client memory.
532 * The face object to look for.
535 * The tag of table to load. Use the value 0 if you want
536 * to access the whole font file, else set this parameter
537 * to a valid TrueType table tag that you can forge with
538 * the MAKE_TT_TAG macro.
541 * The starting offset in the table (or the file if
545 * The address of the decision variable:
548 * Loads the whole table. Returns an error if
552 * Exits immediately; returning the length of the given
553 * table or of the font file, depending on the value of
557 * Loads the next `length' bytes of table or font,
558 * starting at offset `offset' (in table or font too).
562 * The address of target buffer.
565 * FreeType error code. 0 means success.
567 FT_LOCAL_DEF( FT_Error )
568 tt_face_load_any( TT_Face face,
582 /* look for tag in font directory */
583 table = tt_face_lookup_table( face, tag );
586 error = FT_THROW( Table_Missing );
590 offset += table->Offset;
591 size = table->Length;
594 /* tag == 0 -- the user wants to access the font file directly */
595 size = face->root.stream->size;
597 if ( length && *length == 0 )
607 stream = face->root.stream;
608 /* the `if' is syntactic sugar for picky compilers */
609 if ( FT_STREAM_READ_AT( offset, buffer, size ) )
617 /**************************************************************************
620 * tt_face_load_generic_header
623 * Loads the TrueType table `head' or `bhed'.
627 * A handle to the target face object.
633 * FreeType error code. 0 means success.
636 tt_face_load_generic_header( TT_Face face,
643 static const FT_Frame_Field header_fields[] =
646 #define FT_STRUCTURE TT_Header
648 FT_FRAME_START( 54 ),
649 FT_FRAME_ULONG ( Table_Version ),
650 FT_FRAME_ULONG ( Font_Revision ),
651 FT_FRAME_LONG ( CheckSum_Adjust ),
652 FT_FRAME_LONG ( Magic_Number ),
653 FT_FRAME_USHORT( Flags ),
654 FT_FRAME_USHORT( Units_Per_EM ),
655 FT_FRAME_ULONG ( Created[0] ),
656 FT_FRAME_ULONG ( Created[1] ),
657 FT_FRAME_ULONG ( Modified[0] ),
658 FT_FRAME_ULONG ( Modified[1] ),
659 FT_FRAME_SHORT ( xMin ),
660 FT_FRAME_SHORT ( yMin ),
661 FT_FRAME_SHORT ( xMax ),
662 FT_FRAME_SHORT ( yMax ),
663 FT_FRAME_USHORT( Mac_Style ),
664 FT_FRAME_USHORT( Lowest_Rec_PPEM ),
665 FT_FRAME_SHORT ( Font_Direction ),
666 FT_FRAME_SHORT ( Index_To_Loc_Format ),
667 FT_FRAME_SHORT ( Glyph_Data_Format ),
672 error = face->goto_table( face, tag, stream, 0 );
676 header = &face->header;
678 if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
681 FT_TRACE3(( "Units per EM: %4hu\n", header->Units_Per_EM ));
682 FT_TRACE3(( "IndexToLoc: %4hd\n", header->Index_To_Loc_Format ));
689 FT_LOCAL_DEF( FT_Error )
690 tt_face_load_head( TT_Face face,
693 return tt_face_load_generic_header( face, stream, TTAG_head );
697 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
699 FT_LOCAL_DEF( FT_Error )
700 tt_face_load_bhed( TT_Face face,
703 return tt_face_load_generic_header( face, stream, TTAG_bhed );
706 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
709 /**************************************************************************
715 * Loads the maximum profile into a face object.
719 * A handle to the target face object.
725 * FreeType error code. 0 means success.
727 FT_LOCAL_DEF( FT_Error )
728 tt_face_load_maxp( TT_Face face,
732 TT_MaxProfile* maxProfile = &face->max_profile;
734 static const FT_Frame_Field maxp_fields[] =
737 #define FT_STRUCTURE TT_MaxProfile
740 FT_FRAME_LONG ( version ),
741 FT_FRAME_USHORT( numGlyphs ),
745 static const FT_Frame_Field maxp_fields_extra[] =
747 FT_FRAME_START( 26 ),
748 FT_FRAME_USHORT( maxPoints ),
749 FT_FRAME_USHORT( maxContours ),
750 FT_FRAME_USHORT( maxCompositePoints ),
751 FT_FRAME_USHORT( maxCompositeContours ),
752 FT_FRAME_USHORT( maxZones ),
753 FT_FRAME_USHORT( maxTwilightPoints ),
754 FT_FRAME_USHORT( maxStorage ),
755 FT_FRAME_USHORT( maxFunctionDefs ),
756 FT_FRAME_USHORT( maxInstructionDefs ),
757 FT_FRAME_USHORT( maxStackElements ),
758 FT_FRAME_USHORT( maxSizeOfInstructions ),
759 FT_FRAME_USHORT( maxComponentElements ),
760 FT_FRAME_USHORT( maxComponentDepth ),
765 error = face->goto_table( face, TTAG_maxp, stream, 0 );
769 if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
772 maxProfile->maxPoints = 0;
773 maxProfile->maxContours = 0;
774 maxProfile->maxCompositePoints = 0;
775 maxProfile->maxCompositeContours = 0;
776 maxProfile->maxZones = 0;
777 maxProfile->maxTwilightPoints = 0;
778 maxProfile->maxStorage = 0;
779 maxProfile->maxFunctionDefs = 0;
780 maxProfile->maxInstructionDefs = 0;
781 maxProfile->maxStackElements = 0;
782 maxProfile->maxSizeOfInstructions = 0;
783 maxProfile->maxComponentElements = 0;
784 maxProfile->maxComponentDepth = 0;
786 if ( maxProfile->version >= 0x10000L )
788 if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
791 /* XXX: an adjustment that is necessary to load certain */
792 /* broken fonts like `Keystrokes MT' :-( */
794 /* We allocate 64 function entries by default when */
795 /* the maxFunctionDefs value is smaller. */
797 if ( maxProfile->maxFunctionDefs < 64 )
798 maxProfile->maxFunctionDefs = 64;
800 /* we add 4 phantom points later */
801 if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
803 FT_TRACE0(( "tt_face_load_maxp:"
804 " too much twilight points in `maxp' table;\n" ));
806 " some glyphs might be rendered incorrectly\n" ));
808 maxProfile->maxTwilightPoints = 0xFFFFU - 4;
812 FT_TRACE3(( "numGlyphs: %hu\n", maxProfile->numGlyphs ));
819 /**************************************************************************
825 * Loads the name records.
829 * A handle to the target face object.
835 * FreeType error code. 0 means success.
837 FT_LOCAL_DEF( FT_Error )
838 tt_face_load_name( TT_Face face,
842 FT_Memory memory = stream->memory;
843 FT_ULong table_pos, table_len;
844 FT_ULong storage_start, storage_limit;
846 TT_Name names = NULL;
847 TT_LangTag langTags = NULL;
849 static const FT_Frame_Field name_table_fields[] =
852 #define FT_STRUCTURE TT_NameTableRec
855 FT_FRAME_USHORT( format ),
856 FT_FRAME_USHORT( numNameRecords ),
857 FT_FRAME_USHORT( storageOffset ),
861 static const FT_Frame_Field name_record_fields[] =
864 #define FT_STRUCTURE TT_NameRec
866 /* no FT_FRAME_START */
867 FT_FRAME_USHORT( platformID ),
868 FT_FRAME_USHORT( encodingID ),
869 FT_FRAME_USHORT( languageID ),
870 FT_FRAME_USHORT( nameID ),
871 FT_FRAME_USHORT( stringLength ),
872 FT_FRAME_USHORT( stringOffset ),
876 static const FT_Frame_Field langTag_record_fields[] =
879 #define FT_STRUCTURE TT_LangTagRec
881 /* no FT_FRAME_START */
882 FT_FRAME_USHORT( stringLength ),
883 FT_FRAME_USHORT( stringOffset ),
888 table = &face->name_table;
889 table->stream = stream;
891 error = face->goto_table( face, TTAG_name, stream, &table_len );
895 table_pos = FT_STREAM_POS();
897 if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
900 /* Some popular Asian fonts have an invalid `storageOffset' value (it */
901 /* should be at least `6 + 12*numNameRecords'). However, the string */
902 /* offsets, computed as `storageOffset + entry->stringOffset', are */
903 /* valid pointers within the name table... */
905 /* We thus can't check `storageOffset' right now. */
907 storage_start = table_pos + 6 + 12 * table->numNameRecords;
908 storage_limit = table_pos + table_len;
910 if ( storage_start > storage_limit )
912 FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
913 error = FT_THROW( Name_Table_Missing );
917 /* `name' format 1 contains additional language tag records, */
918 /* which we load first */
919 if ( table->format == 1 )
921 if ( FT_STREAM_SEEK( storage_start ) ||
922 FT_READ_USHORT( table->numLangTagRecords ) )
925 storage_start += 2 + 4 * table->numLangTagRecords;
927 /* allocate language tag records array */
928 if ( FT_QNEW_ARRAY( langTags, table->numLangTagRecords ) ||
929 FT_FRAME_ENTER( table->numLangTagRecords * 4 ) )
932 /* load language tags */
934 TT_LangTag entry = langTags;
935 TT_LangTag limit = FT_OFFSET( entry, table->numLangTagRecords );
938 for ( ; entry < limit; entry++ )
940 (void)FT_STREAM_READ_FIELDS( langTag_record_fields, entry );
942 /* check that the langTag string is within the table */
943 entry->stringOffset += table_pos + table->storageOffset;
944 if ( entry->stringOffset < storage_start ||
945 entry->stringOffset + entry->stringLength > storage_limit )
947 /* invalid entry; ignore it */
948 entry->stringLength = 0;
951 /* mark the string as not yet loaded */
952 entry->string = NULL;
955 table->langTags = langTags;
961 (void)FT_STREAM_SEEK( table_pos + 6 );
964 /* allocate name records array */
965 if ( FT_QNEW_ARRAY( names, table->numNameRecords ) ||
966 FT_FRAME_ENTER( table->numNameRecords * 12 ) )
969 /* load name records */
971 TT_Name entry = names;
972 FT_UInt count = table->numNameRecords;
976 for ( ; count > 0; count-- )
978 if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
981 /* check that the name is not empty */
982 if ( entry->stringLength == 0 )
985 /* check that the name string is within the table */
986 entry->stringOffset += table_pos + table->storageOffset;
987 if ( entry->stringOffset < storage_start ||
988 entry->stringOffset + entry->stringLength > storage_limit )
990 /* invalid entry; ignore it */
994 /* assure that we have a valid language tag ID, and */
995 /* that the corresponding langTag entry is valid, too */
996 if ( table->format == 1 && entry->languageID >= 0x8000U )
998 if ( entry->languageID - 0x8000U >= table->numLangTagRecords ||
999 !table->langTags[entry->languageID - 0x8000U].stringLength )
1001 /* invalid entry; ignore it */
1006 /* mark the string as not yet converted */
1007 entry->string = NULL;
1013 /* reduce array size to the actually used elements */
1014 FT_MEM_QRENEW_ARRAY( names,
1015 table->numNameRecords,
1017 table->names = names;
1019 table->numNameRecords = valid;
1024 /* everything went well, update face->num_names */
1025 face->num_names = (FT_UShort)table->numNameRecords;
1029 FT_FREE( langTags );
1034 /**************************************************************************
1040 * Frees the name records.
1044 * A handle to the target face object.
1046 FT_LOCAL_DEF( void )
1047 tt_face_free_name( TT_Face face )
1049 FT_Memory memory = face->root.driver->root.memory;
1050 TT_NameTable table = &face->name_table;
1055 TT_Name entry = table->names;
1056 TT_Name limit = entry + table->numNameRecords;
1059 for ( ; entry < limit; entry++ )
1060 FT_FREE( entry->string );
1062 FT_FREE( table->names );
1065 if ( table->langTags )
1067 TT_LangTag entry = table->langTags;
1068 TT_LangTag limit = entry + table->numLangTagRecords;
1071 for ( ; entry < limit; entry++ )
1072 FT_FREE( entry->string );
1074 FT_FREE( table->langTags );
1077 table->numNameRecords = 0;
1078 table->numLangTagRecords = 0;
1080 table->storageOffset = 0;
1084 /**************************************************************************
1090 * Loads the cmap directory in a face object. The cmaps themselves
1091 * are loaded on demand in the `ttcmap.c' module.
1095 * A handle to the target face object.
1098 * A handle to the input stream.
1101 * FreeType error code. 0 means success.
1104 FT_LOCAL_DEF( FT_Error )
1105 tt_face_load_cmap( TT_Face face,
1111 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
1115 if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
1116 face->cmap_size = 0;
1124 /**************************************************************************
1130 * Loads the OS2 table.
1134 * A handle to the target face object.
1137 * A handle to the input stream.
1140 * FreeType error code. 0 means success.
1142 FT_LOCAL_DEF( FT_Error )
1143 tt_face_load_os2( TT_Face face,
1149 static const FT_Frame_Field os2_fields[] =
1152 #define FT_STRUCTURE TT_OS2
1154 FT_FRAME_START( 78 ),
1155 FT_FRAME_USHORT( version ),
1156 FT_FRAME_SHORT ( xAvgCharWidth ),
1157 FT_FRAME_USHORT( usWeightClass ),
1158 FT_FRAME_USHORT( usWidthClass ),
1159 FT_FRAME_SHORT ( fsType ),
1160 FT_FRAME_SHORT ( ySubscriptXSize ),
1161 FT_FRAME_SHORT ( ySubscriptYSize ),
1162 FT_FRAME_SHORT ( ySubscriptXOffset ),
1163 FT_FRAME_SHORT ( ySubscriptYOffset ),
1164 FT_FRAME_SHORT ( ySuperscriptXSize ),
1165 FT_FRAME_SHORT ( ySuperscriptYSize ),
1166 FT_FRAME_SHORT ( ySuperscriptXOffset ),
1167 FT_FRAME_SHORT ( ySuperscriptYOffset ),
1168 FT_FRAME_SHORT ( yStrikeoutSize ),
1169 FT_FRAME_SHORT ( yStrikeoutPosition ),
1170 FT_FRAME_SHORT ( sFamilyClass ),
1171 FT_FRAME_BYTE ( panose[0] ),
1172 FT_FRAME_BYTE ( panose[1] ),
1173 FT_FRAME_BYTE ( panose[2] ),
1174 FT_FRAME_BYTE ( panose[3] ),
1175 FT_FRAME_BYTE ( panose[4] ),
1176 FT_FRAME_BYTE ( panose[5] ),
1177 FT_FRAME_BYTE ( panose[6] ),
1178 FT_FRAME_BYTE ( panose[7] ),
1179 FT_FRAME_BYTE ( panose[8] ),
1180 FT_FRAME_BYTE ( panose[9] ),
1181 FT_FRAME_ULONG ( ulUnicodeRange1 ),
1182 FT_FRAME_ULONG ( ulUnicodeRange2 ),
1183 FT_FRAME_ULONG ( ulUnicodeRange3 ),
1184 FT_FRAME_ULONG ( ulUnicodeRange4 ),
1185 FT_FRAME_BYTE ( achVendID[0] ),
1186 FT_FRAME_BYTE ( achVendID[1] ),
1187 FT_FRAME_BYTE ( achVendID[2] ),
1188 FT_FRAME_BYTE ( achVendID[3] ),
1190 FT_FRAME_USHORT( fsSelection ),
1191 FT_FRAME_USHORT( usFirstCharIndex ),
1192 FT_FRAME_USHORT( usLastCharIndex ),
1193 FT_FRAME_SHORT ( sTypoAscender ),
1194 FT_FRAME_SHORT ( sTypoDescender ),
1195 FT_FRAME_SHORT ( sTypoLineGap ),
1196 FT_FRAME_USHORT( usWinAscent ),
1197 FT_FRAME_USHORT( usWinDescent ),
1201 /* `OS/2' version 1 and newer */
1202 static const FT_Frame_Field os2_fields_extra1[] =
1204 FT_FRAME_START( 8 ),
1205 FT_FRAME_ULONG( ulCodePageRange1 ),
1206 FT_FRAME_ULONG( ulCodePageRange2 ),
1210 /* `OS/2' version 2 and newer */
1211 static const FT_Frame_Field os2_fields_extra2[] =
1213 FT_FRAME_START( 10 ),
1214 FT_FRAME_SHORT ( sxHeight ),
1215 FT_FRAME_SHORT ( sCapHeight ),
1216 FT_FRAME_USHORT( usDefaultChar ),
1217 FT_FRAME_USHORT( usBreakChar ),
1218 FT_FRAME_USHORT( usMaxContext ),
1222 /* `OS/2' version 5 and newer */
1223 static const FT_Frame_Field os2_fields_extra5[] =
1225 FT_FRAME_START( 4 ),
1226 FT_FRAME_USHORT( usLowerOpticalPointSize ),
1227 FT_FRAME_USHORT( usUpperOpticalPointSize ),
1232 /* We now support old Mac fonts where the OS/2 table doesn't */
1233 /* exist. Simply put, we set the `version' field to 0xFFFF */
1234 /* and test this value each time we need to access the table. */
1235 error = face->goto_table( face, TTAG_OS2, stream, 0 );
1241 if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
1244 os2->ulCodePageRange1 = 0;
1245 os2->ulCodePageRange2 = 0;
1247 os2->sCapHeight = 0;
1248 os2->usDefaultChar = 0;
1249 os2->usBreakChar = 0;
1250 os2->usMaxContext = 0;
1251 os2->usLowerOpticalPointSize = 0;
1252 os2->usUpperOpticalPointSize = 0xFFFF;
1254 if ( os2->version >= 0x0001 )
1256 /* only version 1 tables */
1257 if ( FT_STREAM_READ_FIELDS( os2_fields_extra1, os2 ) )
1260 if ( os2->version >= 0x0002 )
1262 /* only version 2 tables */
1263 if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
1266 if ( os2->version >= 0x0005 )
1268 /* only version 5 tables */
1269 if ( FT_STREAM_READ_FIELDS( os2_fields_extra5, os2 ) )
1275 FT_TRACE3(( "sTypoAscender: %4hd\n", os2->sTypoAscender ));
1276 FT_TRACE3(( "sTypoDescender: %4hd\n", os2->sTypoDescender ));
1277 FT_TRACE3(( "usWinAscent: %4hu\n", os2->usWinAscent ));
1278 FT_TRACE3(( "usWinDescent: %4hu\n", os2->usWinDescent ));
1279 FT_TRACE3(( "fsSelection: 0x%2hx\n", os2->fsSelection ));
1286 /**************************************************************************
1289 * tt_face_load_postscript
1292 * Loads the Postscript table.
1296 * A handle to the target face object.
1299 * A handle to the input stream.
1302 * FreeType error code. 0 means success.
1304 FT_LOCAL_DEF( FT_Error )
1305 tt_face_load_post( TT_Face face,
1309 TT_Postscript* post = &face->postscript;
1311 static const FT_Frame_Field post_fields[] =
1314 #define FT_STRUCTURE TT_Postscript
1316 FT_FRAME_START( 32 ),
1317 FT_FRAME_LONG ( FormatType ),
1318 FT_FRAME_LONG ( italicAngle ),
1319 FT_FRAME_SHORT( underlinePosition ),
1320 FT_FRAME_SHORT( underlineThickness ),
1321 FT_FRAME_ULONG( isFixedPitch ),
1322 FT_FRAME_ULONG( minMemType42 ),
1323 FT_FRAME_ULONG( maxMemType42 ),
1324 FT_FRAME_ULONG( minMemType1 ),
1325 FT_FRAME_ULONG( maxMemType1 ),
1330 error = face->goto_table( face, TTAG_post, stream, 0 );
1334 if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
1337 if ( post->FormatType != 0x00030000L &&
1338 post->FormatType != 0x00025000L &&
1339 post->FormatType != 0x00020000L &&
1340 post->FormatType != 0x00010000L )
1341 return FT_THROW( Invalid_Post_Table_Format );
1343 /* we don't load the glyph names, we do that in another */
1344 /* module (ttpost). */
1346 FT_TRACE3(( "FormatType: 0x%lx\n", post->FormatType ));
1347 FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch
1348 ? " yes" : " no" ));
1354 /**************************************************************************
1360 * Loads the PCL 5 Table.
1364 * A handle to the target face object.
1367 * A handle to the input stream.
1370 * FreeType error code. 0 means success.
1372 FT_LOCAL_DEF( FT_Error )
1373 tt_face_load_pclt( TT_Face face,
1376 static const FT_Frame_Field pclt_fields[] =
1379 #define FT_STRUCTURE TT_PCLT
1381 FT_FRAME_START( 54 ),
1382 FT_FRAME_ULONG ( Version ),
1383 FT_FRAME_ULONG ( FontNumber ),
1384 FT_FRAME_USHORT( Pitch ),
1385 FT_FRAME_USHORT( xHeight ),
1386 FT_FRAME_USHORT( Style ),
1387 FT_FRAME_USHORT( TypeFamily ),
1388 FT_FRAME_USHORT( CapHeight ),
1389 FT_FRAME_USHORT( SymbolSet ),
1390 FT_FRAME_BYTES ( TypeFace, 16 ),
1391 FT_FRAME_BYTES ( CharacterComplement, 8 ),
1392 FT_FRAME_BYTES ( FileName, 6 ),
1393 FT_FRAME_CHAR ( StrokeWeight ),
1394 FT_FRAME_CHAR ( WidthType ),
1395 FT_FRAME_BYTE ( SerifStyle ),
1396 FT_FRAME_BYTE ( Reserved ),
1401 TT_PCLT* pclt = &face->pclt;
1404 /* optional table */
1405 error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1409 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
1417 /**************************************************************************
1423 * Loads the `gasp' table into a face object.
1427 * A handle to the target face object.
1433 * FreeType error code. 0 means success.
1435 FT_LOCAL_DEF( FT_Error )
1436 tt_face_load_gasp( TT_Face face,
1440 FT_Memory memory = stream->memory;
1442 FT_UShort j, num_ranges;
1443 TT_GaspRange gasp_ranges = NULL;
1446 /* the gasp table is optional */
1447 error = face->goto_table( face, TTAG_gasp, stream, 0 );
1451 if ( FT_FRAME_ENTER( 4L ) )
1454 face->gasp.version = FT_GET_USHORT();
1455 num_ranges = FT_GET_USHORT();
1459 /* only support versions 0 and 1 of the table */
1460 if ( face->gasp.version >= 2 )
1462 face->gasp.numRanges = 0;
1463 error = FT_THROW( Invalid_Table );
1467 FT_TRACE3(( "numRanges: %hu\n", num_ranges ));
1469 if ( FT_QNEW_ARRAY( gasp_ranges, num_ranges ) ||
1470 FT_FRAME_ENTER( num_ranges * 4L ) )
1473 for ( j = 0; j < num_ranges; j++ )
1475 gasp_ranges[j].maxPPEM = FT_GET_USHORT();
1476 gasp_ranges[j].gaspFlag = FT_GET_USHORT();
1478 FT_TRACE3(( "gaspRange %hu: rangeMaxPPEM %5hu, rangeGaspBehavior 0x%hx\n",
1480 gasp_ranges[j].maxPPEM,
1481 gasp_ranges[j].gaspFlag ));
1484 face->gasp.gaspRanges = gasp_ranges;
1486 face->gasp.numRanges = num_ranges;
1491 FT_FREE( gasp_ranges );