1 /***************************************************************************/
5 /* Load the basic TrueType tables, i.e., tables that can be either in */
6 /* TTF or OTF fonts (body). */
8 /* Copyright 1996-2001, 2002 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. */
17 /***************************************************************************/
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_TRUETYPE_TAGS_H
30 /*************************************************************************/
32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
34 /* messages during execution. */
37 #define FT_COMPONENT trace_ttload
40 /*************************************************************************/
43 /* tt_face_lookup_table */
46 /* Looks for a TrueType table by name. */
49 /* face :: A face object handle. */
51 /* tag :: The searched tag. */
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,
64 FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
66 (FT_Char)( tag >> 24 ),
67 (FT_Char)( tag >> 16 ),
68 (FT_Char)( tag >> 8 ),
71 entry = face->dir_tables;
72 limit = entry + face->num_tables;
74 for ( ; entry < limit; entry++ )
76 /* For compatibility with Windows, we consider 0-length */
77 /* tables the same as missing tables. */
78 if ( entry->Tag == tag && entry->Length != 0 )
80 FT_TRACE3(( "found table.\n" ));
85 FT_TRACE3(( "could not find table!\n" ));
90 /*************************************************************************/
93 /* tt_face_goto_table */
96 /* Looks for a TrueType table by name, then seek a stream to it. */
99 /* face :: A face object handle. */
101 /* tag :: The searched tag. */
103 /* stream :: The stream to seek when the table is found. */
106 /* length :: The length of the table if found, undefined otherwise. */
109 /* FreeType error code. 0 means success. */
111 FT_LOCAL_DEF( FT_Error )
112 tt_face_goto_table( TT_Face face,
121 table = tt_face_lookup_table( face, tag );
125 *length = table->Length;
127 if ( FT_STREAM_SEEK( table->Offset ) )
131 error = SFNT_Err_Table_Missing;
138 /* In theory, we should check the values of `search_range', */
139 /* `entry_selector', and `range_shift' to detect non-SFNT based files */
140 /* whose header might also start with 0x100000L (yes, these exist). */
142 /* Very unfortunately, many TrueType fonts don't have these fields */
143 /* set correctly and we must ignore them to support them. An alternative */
144 /* way to check the font file is thus to: */
146 /* - check that `num_tables' is valid */
147 /* - look for a "head" table, check its size, and parse it to */
148 /* see if its "magic" field is correctly set */
150 /* When checking directory entries, ignore the tables `glyx' and `locx' */
151 /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
152 /* Type 42 fonts, and will generally be invalid. */
155 sfnt_dir_check( FT_Stream stream,
160 FT_UInt nn, has_head = 0;
162 const FT_ULong glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
163 const FT_ULong locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
165 static const FT_Frame_Field sfnt_dir_entry_fields[] =
168 #define FT_STRUCTURE TT_TableRec
170 FT_FRAME_START( 16 ),
171 FT_FRAME_ULONG( Tag ),
172 FT_FRAME_ULONG( CheckSum ),
173 FT_FRAME_ULONG( Offset ),
174 FT_FRAME_ULONG( Length ),
179 /* if 'num_tables' is 0, read the table count from the file */
180 if ( num_tables == 0 )
185 if ( FT_STREAM_SEEK( offset ) ||
186 FT_READ_ULONG ( format_tag ) ||
187 FT_READ_USHORT( num_tables ) ||
188 FT_STREAM_SKIP( 6 ) )
191 if ( offset + 12 + num_tables*16 > stream->size )
194 else if ( FT_STREAM_SEEK( offset + 12 ) )
197 for ( nn = 0; nn < num_tables; nn++ )
202 if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
205 if ( table.Offset + table.Length > stream->size &&
206 table.Tag != glyx_tag && table.Tag != locx_tag )
209 if ( table.Tag == TTAG_head )
216 /* the table length should be 0x36, but certain font tools
217 * make it 0x38, so we will just check that it is greater.
219 * note that according to the specification,
220 * the table must be padded to 32-bit lengths, but this doesn't
221 * apply to the value of its "Length" field !!
223 if ( table.Length < 0x36 ||
224 FT_STREAM_SEEK( table.Offset + 12 ) ||
225 FT_READ_ULONG( magic ) ||
226 magic != 0x5F0F3CF5UL )
229 if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
241 error = FT_Err_Unknown_File_Format;
246 /*************************************************************************/
249 /* tt_face_load_sfnt_header */
252 /* Loads the header of a SFNT font file. Supports collections. */
255 /* face :: A handle to the target face object. */
257 /* stream :: The input stream. */
259 /* face_index :: If the font is a collection, the number of the font */
260 /* in the collection, ignored otherwise. */
263 /* sfnt :: The SFNT header. */
266 /* FreeType error code. 0 means success. */
269 /* The stream cursor must be at the font file's origin. */
271 /* This function recognizes fonts embedded in a `TrueType collection' */
273 /* The header will be checked whether it is valid by looking at the */
274 /* values of `search_range', `entry_selector', and `range_shift'. */
276 FT_LOCAL_DEF( FT_Error )
277 tt_face_load_sfnt_header( TT_Face face,
283 FT_ULong format_tag, offset;
284 FT_Memory memory = stream->memory;
286 static const FT_Frame_Field sfnt_header_fields[] =
289 #define FT_STRUCTURE SFNT_HeaderRec
292 FT_FRAME_USHORT( num_tables ),
293 FT_FRAME_USHORT( search_range ),
294 FT_FRAME_USHORT( entry_selector ),
295 FT_FRAME_USHORT( range_shift ),
299 static const FT_Frame_Field ttc_header_fields[] =
302 #define FT_STRUCTURE TTC_HeaderRec
305 FT_FRAME_LONG( version ),
306 FT_FRAME_LONG( count ),
311 FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
314 face->ttc_header.tag = 0;
315 face->ttc_header.version = 0;
316 face->ttc_header.count = 0;
318 face->num_tables = 0;
320 /* first of all, read the first 4 bytes. If it is `ttcf', then the */
321 /* file is a TrueType collection, otherwise it can be any other */
324 offset = FT_STREAM_POS();
326 if ( FT_READ_ULONG( format_tag ) )
329 if ( format_tag == TTAG_ttcf )
334 FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" ));
336 /* It is a TrueType collection, i.e. a file containing several */
337 /* font files. Read the font directory now */
338 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
341 /* now read the offsets of each font in the file */
342 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ||
343 FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
346 for ( n = 0; n < face->ttc_header.count; n++ )
347 face->ttc_header.offsets[n] = FT_GET_ULONG();
351 /* check face index */
352 if ( face_index >= face->ttc_header.count )
354 error = SFNT_Err_Bad_Argument;
358 /* seek to the appropriate TrueType file, then read tag */
359 offset = face->ttc_header.offsets[face_index];
361 if ( FT_STREAM_SEEK( offset ) ||
362 FT_READ_LONG( format_tag ) )
366 /* the format tag was read, now check the rest of the header */
367 sfnt->format_tag = format_tag;
368 sfnt->offset = offset;
370 if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
373 /* now check the sfnt directory */
374 error = sfnt_dir_check( stream, offset, sfnt->num_tables );
377 FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" ));
378 error = SFNT_Err_Unknown_File_Format;
386 /*************************************************************************/
389 /* tt_face_load_directory */
392 /* Loads the table directory into a face object. */
395 /* face :: A handle to the target face object. */
398 /* stream :: The input stream. */
400 /* sfnt :: The SFNT directory header. */
403 /* FreeType error code. 0 means success. */
406 /* The stream cursor must be at the font file's origin. */
408 FT_LOCAL_DEF( FT_Error )
409 tt_face_load_directory( TT_Face face,
414 FT_Memory memory = stream->memory;
416 TT_TableRec *entry, *limit;
419 FT_TRACE2(( "tt_face_load_directory: %08p\n", face ));
421 FT_TRACE2(( "-- Tables count: %12u\n", sfnt->num_tables ));
422 FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
424 face->num_tables = sfnt->num_tables;
426 if ( FT_NEW_ARRAY( face->dir_tables, face->num_tables ) )
429 if ( FT_STREAM_SEEK( sfnt->offset + 12 ) ||
430 FT_FRAME_ENTER( face->num_tables * 16L ) )
433 entry = face->dir_tables;
434 limit = entry + face->num_tables;
436 for ( ; entry < limit; entry++ )
437 { /* loop through the tables and get all entries */
438 entry->Tag = FT_GET_TAG4();
439 entry->CheckSum = FT_GET_ULONG();
440 entry->Offset = FT_GET_LONG();
441 entry->Length = FT_GET_LONG();
443 FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
444 (FT_Char)( entry->Tag >> 24 ),
445 (FT_Char)( entry->Tag >> 16 ),
446 (FT_Char)( entry->Tag >> 8 ),
447 (FT_Char)( entry->Tag ),
454 FT_TRACE2(( "Directory loaded\n\n" ));
461 /*************************************************************************/
464 /* tt_face_load_any */
467 /* Loads any font table into client memory. */
470 /* face :: The face object to look for. */
472 /* tag :: The tag of table to load. Use the value 0 if you want */
473 /* to access the whole font file, else set this parameter */
474 /* to a valid TrueType table tag that you can forge with */
475 /* the MAKE_TT_TAG macro. */
477 /* offset :: The starting offset in the table (or the file if */
480 /* length :: The address of the decision variable: */
482 /* If length == NULL: */
483 /* Loads the whole table. Returns an error if */
486 /* If *length == 0: */
487 /* Exits immediately; returning the length of the given */
488 /* table or of the font file, depending on the value of */
491 /* If *length != 0: */
492 /* Loads the next `length' bytes of table or font, */
493 /* starting at offset `offset' (in table or font too). */
496 /* buffer :: The address of target buffer. */
499 /* FreeType error code. 0 means success. */
501 FT_LOCAL_DEF( FT_Error )
502 tt_face_load_any( TT_Face face,
516 /* look for tag in font directory */
517 table = tt_face_lookup_table( face, tag );
520 error = SFNT_Err_Table_Missing;
524 offset += table->Offset;
525 size = table->Length;
528 /* tag == 0 -- the user wants to access the font file directly */
529 size = face->root.stream->size;
531 if ( length && *length == 0 )
541 stream = face->root.stream;
542 /* the `if' is syntactic sugar for picky compilers */
543 if ( FT_STREAM_READ_AT( offset, buffer, size ) )
551 /*************************************************************************/
554 /* tt_face_load_generic_header */
557 /* Loads the TrueType table `head' or `bhed'. */
560 /* face :: A handle to the target face object. */
562 /* stream :: The input stream. */
565 /* FreeType error code. 0 means success. */
568 tt_face_load_generic_header( TT_Face face,
575 static const FT_Frame_Field header_fields[] =
578 #define FT_STRUCTURE TT_Header
580 FT_FRAME_START( 54 ),
581 FT_FRAME_ULONG ( Table_Version ),
582 FT_FRAME_ULONG ( Font_Revision ),
583 FT_FRAME_LONG ( CheckSum_Adjust ),
584 FT_FRAME_LONG ( Magic_Number ),
585 FT_FRAME_USHORT( Flags ),
586 FT_FRAME_USHORT( Units_Per_EM ),
587 FT_FRAME_LONG ( Created[0] ),
588 FT_FRAME_LONG ( Created[1] ),
589 FT_FRAME_LONG ( Modified[0] ),
590 FT_FRAME_LONG ( Modified[1] ),
591 FT_FRAME_SHORT ( xMin ),
592 FT_FRAME_SHORT ( yMin ),
593 FT_FRAME_SHORT ( xMax ),
594 FT_FRAME_SHORT ( yMax ),
595 FT_FRAME_USHORT( Mac_Style ),
596 FT_FRAME_USHORT( Lowest_Rec_PPEM ),
597 FT_FRAME_SHORT ( Font_Direction ),
598 FT_FRAME_SHORT ( Index_To_Loc_Format ),
599 FT_FRAME_SHORT ( Glyph_Data_Format ),
604 FT_TRACE2(( "tt_face_load_generic_header: "
605 "%08p, looking up font table `%c%c%c%c'.\n",
607 (FT_Char)( tag >> 24 ),
608 (FT_Char)( tag >> 16 ),
609 (FT_Char)( tag >> 8 ),
612 error = face->goto_table( face, tag, stream, 0 );
615 FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" ));
619 header = &face->header;
621 if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
624 FT_TRACE2(( " Units per EM: %8u\n", header->Units_Per_EM ));
625 FT_TRACE2(( " IndexToLoc: %8d\n", header->Index_To_Loc_Format ));
626 FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" ));
633 FT_LOCAL_DEF( FT_Error )
634 tt_face_load_header( TT_Face face,
637 return tt_face_load_generic_header( face, stream, TTAG_head );
641 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
643 FT_LOCAL_DEF( FT_Error )
644 tt_face_load_bitmap_header( TT_Face face,
647 return tt_face_load_generic_header( face, stream, TTAG_bhed );
650 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
653 /*************************************************************************/
656 /* tt_face_load_max_profile */
659 /* Loads the maximum profile into a face object. */
662 /* face :: A handle to the target face object. */
664 /* stream :: The input stream. */
667 /* FreeType error code. 0 means success. */
669 FT_LOCAL_DEF( FT_Error )
670 tt_face_load_max_profile( TT_Face face,
674 TT_MaxProfile* maxProfile = &face->max_profile;
676 const FT_Frame_Field maxp_fields[] =
679 #define FT_STRUCTURE TT_MaxProfile
682 FT_FRAME_LONG ( version ),
683 FT_FRAME_USHORT( numGlyphs ),
687 const FT_Frame_Field maxp_fields_extra[] =
689 FT_FRAME_START( 26 ),
690 FT_FRAME_USHORT( maxPoints ),
691 FT_FRAME_USHORT( maxContours ),
692 FT_FRAME_USHORT( maxCompositePoints ),
693 FT_FRAME_USHORT( maxCompositeContours ),
694 FT_FRAME_USHORT( maxZones ),
695 FT_FRAME_USHORT( maxTwilightPoints ),
696 FT_FRAME_USHORT( maxStorage ),
697 FT_FRAME_USHORT( maxFunctionDefs ),
698 FT_FRAME_USHORT( maxInstructionDefs ),
699 FT_FRAME_USHORT( maxStackElements ),
700 FT_FRAME_USHORT( maxSizeOfInstructions ),
701 FT_FRAME_USHORT( maxComponentElements ),
702 FT_FRAME_USHORT( maxComponentDepth ),
707 FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
709 error = face->goto_table( face, TTAG_maxp, stream, 0 );
713 if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
716 maxProfile->maxPoints = 0;
717 maxProfile->maxContours = 0;
718 maxProfile->maxCompositePoints = 0;
719 maxProfile->maxCompositeContours = 0;
720 maxProfile->maxZones = 0;
721 maxProfile->maxTwilightPoints = 0;
722 maxProfile->maxStorage = 0;
723 maxProfile->maxFunctionDefs = 0;
724 maxProfile->maxInstructionDefs = 0;
725 maxProfile->maxStackElements = 0;
726 maxProfile->maxSizeOfInstructions = 0;
727 maxProfile->maxComponentElements = 0;
728 maxProfile->maxComponentDepth = 0;
730 if ( maxProfile->version >= 0x10000L )
732 if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
735 /* XXX: an adjustment that is necessary to load certain */
736 /* broken fonts like `Keystrokes MT' :-( */
738 /* We allocate 64 function entries by default when */
739 /* the maxFunctionDefs field is null. */
741 if ( maxProfile->maxFunctionDefs == 0 )
742 maxProfile->maxFunctionDefs = 64;
744 face->root.num_glyphs = maxProfile->numGlyphs;
746 face->root.internal->max_points =
747 (FT_UShort)MAX( maxProfile->maxCompositePoints,
748 maxProfile->maxPoints );
750 face->root.internal->max_contours =
751 (FT_Short)MAX( maxProfile->maxCompositeContours,
752 maxProfile->maxContours );
754 face->max_components = (FT_ULong)maxProfile->maxComponentElements +
755 maxProfile->maxComponentDepth;
757 /* XXX: some fonts have maxComponents set to 0; we will */
758 /* then use 16 of them by default. */
759 if ( face->max_components == 0 )
760 face->max_components = 16;
762 /* We also increase maxPoints and maxContours in order to support */
763 /* some broken fonts. */
764 face->root.internal->max_points += (FT_UShort)8;
765 face->root.internal->max_contours += (FT_Short) 4;
768 FT_TRACE2(( "MAXP loaded.\n" ));
775 /*************************************************************************/
778 /* tt_face_load_metrics */
781 /* Loads the horizontal or vertical metrics table into a face object. */
784 /* face :: A handle to the target face object. */
786 /* stream :: The input stream. */
788 /* vertical :: A boolean flag. If set, load vertical metrics. */
791 /* FreeType error code. 0 means success. */
794 tt_face_load_metrics( TT_Face face,
799 FT_Memory memory = stream->memory;
802 FT_Long num_shorts, num_longs, num_shorts_checked;
804 TT_LongMetrics * longs;
805 TT_ShortMetrics** shorts;
808 FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
814 /* The table is optional, quit silently if it wasn't found */
816 /* XXX: Some fonts have a valid vertical header with a non-null */
817 /* `number_of_VMetrics' fields, but no corresponding `vmtx' */
818 /* table to get the metrics from (e.g. mingliu). */
820 /* For safety, we set the field to 0! */
822 error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
825 /* Set number_Of_VMetrics to 0! */
826 FT_TRACE2(( " no vertical header in file.\n" ));
827 face->vertical.number_Of_VMetrics = 0;
832 num_longs = face->vertical.number_Of_VMetrics;
833 longs = (TT_LongMetrics *)&face->vertical.long_metrics;
834 shorts = (TT_ShortMetrics**)&face->vertical.short_metrics;
838 error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
842 #ifdef FT_CONFIG_OPTION_INCREMENTAL
843 /* If this is an incrementally loaded font and there are */
844 /* overriding metrics tolerate a missing 'hmtx' table. */
845 if ( face->root.internal->incremental_interface &&
846 face->root.internal->incremental_interface->funcs->
849 face->horizontal.number_Of_HMetrics = 0;
855 FT_ERROR(( " no horizontal metrics in file!\n" ));
856 error = SFNT_Err_Hmtx_Table_Missing;
860 num_longs = face->horizontal.number_Of_HMetrics;
861 longs = (TT_LongMetrics *)&face->horizontal.long_metrics;
862 shorts = (TT_ShortMetrics**)&face->horizontal.short_metrics;
865 /* never trust derived values */
867 num_shorts = face->max_profile.numGlyphs - num_longs;
868 num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
870 if ( num_shorts < 0 )
872 FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
873 vertical ? "Vertical"
876 error = vertical ? SFNT_Err_Invalid_Vert_Metrics
877 : SFNT_Err_Invalid_Horiz_Metrics;
881 if ( FT_NEW_ARRAY( *longs, num_longs ) ||
882 FT_NEW_ARRAY( *shorts, num_shorts ) )
885 if ( FT_FRAME_ENTER( table_len ) )
889 TT_LongMetrics cur = *longs;
890 TT_LongMetrics limit = cur + num_longs;
893 for ( ; cur < limit; cur++ )
895 cur->advance = FT_GET_USHORT();
896 cur->bearing = FT_GET_SHORT();
900 /* do we have an inconsistent number of metric values? */
902 TT_ShortMetrics* cur = *shorts;
903 TT_ShortMetrics* limit = cur + MIN( num_shorts, num_shorts_checked );
906 for ( ; cur < limit; cur++ )
907 *cur = FT_GET_SHORT();
909 /* we fill up the missing left side bearings with the */
910 /* last valid value. Since this will occur for buggy CJK */
911 /* fonts usually only, nothing serious will happen */
912 if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
914 FT_Short val = (*shorts)[num_shorts_checked - 1];
917 limit = *shorts + num_shorts;
918 for ( ; cur < limit; cur++ )
925 FT_TRACE2(( "loaded\n" ));
932 /*************************************************************************/
935 /* tt_face_load_metrics_header */
938 /* Loads the horizontal or vertical header in a face object. */
941 /* face :: A handle to the target face object. */
943 /* stream :: The input stream. */
945 /* vertical :: A boolean flag. If set, load vertical metrics. */
948 /* FreeType error code. 0 means success. */
950 FT_LOCAL_DEF( FT_Error )
951 tt_face_load_metrics_header( TT_Face face,
956 TT_HoriHeader* header;
958 const FT_Frame_Field metrics_header_fields[] =
961 #define FT_STRUCTURE TT_HoriHeader
963 FT_FRAME_START( 36 ),
964 FT_FRAME_ULONG ( Version ),
965 FT_FRAME_SHORT ( Ascender ),
966 FT_FRAME_SHORT ( Descender ),
967 FT_FRAME_SHORT ( Line_Gap ),
968 FT_FRAME_USHORT( advance_Width_Max ),
969 FT_FRAME_SHORT ( min_Left_Side_Bearing ),
970 FT_FRAME_SHORT ( min_Right_Side_Bearing ),
971 FT_FRAME_SHORT ( xMax_Extent ),
972 FT_FRAME_SHORT ( caret_Slope_Rise ),
973 FT_FRAME_SHORT ( caret_Slope_Run ),
974 FT_FRAME_SHORT ( caret_Offset ),
975 FT_FRAME_SHORT ( Reserved[0] ),
976 FT_FRAME_SHORT ( Reserved[1] ),
977 FT_FRAME_SHORT ( Reserved[2] ),
978 FT_FRAME_SHORT ( Reserved[3] ),
979 FT_FRAME_SHORT ( metric_Data_Format ),
980 FT_FRAME_USHORT( number_Of_HMetrics ),
985 FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
989 face->vertical_info = 0;
991 /* The vertical header table is optional, so return quietly if */
992 /* we don't find it. */
993 error = face->goto_table( face, TTAG_vhea, stream, 0 );
1000 face->vertical_info = 1;
1001 header = (TT_HoriHeader*)&face->vertical;
1005 /* The horizontal header is mandatory; return an error if we */
1006 /* don't find it. */
1007 error = face->goto_table( face, TTAG_hhea, stream, 0 );
1010 error = SFNT_Err_Horiz_Header_Missing;
1014 header = &face->horizontal;
1017 if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
1020 header->long_metrics = NULL;
1021 header->short_metrics = NULL;
1023 FT_TRACE2(( "loaded\n" ));
1025 /* Now try to load the corresponding metrics */
1027 error = tt_face_load_metrics( face, stream, vertical );
1034 /*************************************************************************/
1037 /* tt_face_load_names */
1040 /* Loads the name records. */
1043 /* face :: A handle to the target face object. */
1045 /* stream :: The input stream. */
1048 /* FreeType error code. 0 means success. */
1050 FT_LOCAL_DEF( FT_Error )
1051 tt_face_load_names( TT_Face face,
1055 FT_Memory memory = stream->memory;
1056 FT_ULong table_pos, table_len;
1057 FT_ULong storage_start, storage_limit;
1061 static const FT_Frame_Field name_table_fields[] =
1064 #define FT_STRUCTURE TT_NameTableRec
1066 FT_FRAME_START( 6 ),
1067 FT_FRAME_USHORT( format ),
1068 FT_FRAME_USHORT( numNameRecords ),
1069 FT_FRAME_USHORT( storageOffset ),
1073 static const FT_Frame_Field name_record_fields[] =
1076 #define FT_STRUCTURE TT_NameEntryRec
1078 /* no FT_FRAME_START */
1079 FT_FRAME_USHORT( platformID ),
1080 FT_FRAME_USHORT( encodingID ),
1081 FT_FRAME_USHORT( languageID ),
1082 FT_FRAME_USHORT( nameID ),
1083 FT_FRAME_USHORT( stringLength ),
1084 FT_FRAME_USHORT( stringOffset ),
1089 table = &face->name_table;
1090 table->stream = stream;
1092 FT_TRACE2(( "Names " ));
1094 error = face->goto_table( face, TTAG_name, stream, &table_len );
1097 /* The name table is required so indicate failure. */
1098 FT_TRACE2(( "is missing!\n" ));
1099 error = SFNT_Err_Name_Table_Missing;
1103 table_pos = FT_STREAM_POS();
1106 if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
1109 /* Some popular Asian fonts have an invalid `storageOffset' value */
1110 /* (it should be at least "6 + 12*num_names"). However, the string */
1111 /* offsets, computed as "storageOffset + entry->stringOffset", are */
1112 /* valid pointers within the name table... */
1114 /* We thus can't check `storageOffset' right now. */
1116 storage_start = table_pos + 6 + 12*table->numNameRecords;
1117 storage_limit = table_pos + table_len;
1119 if ( storage_start > storage_limit )
1121 FT_ERROR(( "tt_face_load_names: invalid `name' table\n" ));
1122 error = SFNT_Err_Name_Table_Missing;
1126 /* Allocate the array of name records. */
1127 count = table->numNameRecords;
1128 table->numNameRecords = 0;
1130 if ( FT_NEW_ARRAY( table->names, count ) ||
1131 FT_FRAME_ENTER( count * 12 ) )
1134 /* Load the name records and determine how much storage is needed */
1135 /* to hold the strings themselves. */
1137 TT_NameEntryRec* entry = table->names;
1140 for ( ; count > 0; count-- )
1142 if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
1145 /* check that the name is not empty */
1146 if ( entry->stringLength == 0 )
1149 /* check that the name string is within the table */
1150 entry->stringOffset += table_pos + table->storageOffset;
1151 if ( entry->stringOffset < storage_start ||
1152 entry->stringOffset + entry->stringLength > storage_limit )
1154 /* invalid entry - ignore it */
1155 entry->stringOffset = 0;
1156 entry->stringLength = 0;
1163 table->numNameRecords = (FT_UInt)( entry - table->names );
1168 FT_TRACE2(( "loaded\n" ));
1170 /* everything went well, update face->num_names */
1171 face->num_names = (FT_UShort) table->numNameRecords;
1178 /*************************************************************************/
1181 /* tt_face_free_names */
1184 /* Frees the name records. */
1187 /* face :: A handle to the target face object. */
1189 FT_LOCAL_DEF( void )
1190 tt_face_free_names( TT_Face face )
1192 FT_Memory memory = face->root.driver->root.memory;
1193 TT_NameTable table = &face->name_table;
1194 TT_NameEntry entry = table->names;
1195 FT_UInt count = table->numNameRecords;
1198 for ( ; count > 0; count--, entry++ )
1200 FT_FREE( entry->string );
1201 entry->stringLength = 0;
1204 /* free strings table */
1205 FT_FREE( table->names );
1207 table->numNameRecords = 0;
1209 table->storageOffset = 0;
1213 /*************************************************************************/
1216 /* tt_face_load_cmap */
1219 /* Loads the cmap directory in a face object. The cmaps itselves are */
1220 /* loaded on demand in the `ttcmap.c' module. */
1223 /* face :: A handle to the target face object. */
1225 /* stream :: A handle to the input stream. */
1228 /* FreeType error code. 0 means success. */
1231 FT_LOCAL_DEF( FT_Error )
1232 tt_face_load_cmap( TT_Face face,
1238 error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
1241 FT_TRACE2(( "No `cmap' table in font !\n" ));
1242 error = SFNT_Err_CMap_Table_Missing;
1246 if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
1247 FT_TRACE2(( "`cmap' table loaded\n" ));
1250 FT_ERROR(( "`cmap' table is too short!\n" ));
1251 face->cmap_size = 0;
1260 /*************************************************************************/
1263 /* tt_face_load_os2 */
1266 /* Loads the OS2 table. */
1269 /* face :: A handle to the target face object. */
1271 /* stream :: A handle to the input stream. */
1274 /* FreeType error code. 0 means success. */
1276 FT_LOCAL_DEF( FT_Error )
1277 tt_face_load_os2( TT_Face face,
1283 const FT_Frame_Field os2_fields[] =
1286 #define FT_STRUCTURE TT_OS2
1288 FT_FRAME_START( 78 ),
1289 FT_FRAME_USHORT( version ),
1290 FT_FRAME_SHORT ( xAvgCharWidth ),
1291 FT_FRAME_USHORT( usWeightClass ),
1292 FT_FRAME_USHORT( usWidthClass ),
1293 FT_FRAME_SHORT ( fsType ),
1294 FT_FRAME_SHORT ( ySubscriptXSize ),
1295 FT_FRAME_SHORT ( ySubscriptYSize ),
1296 FT_FRAME_SHORT ( ySubscriptXOffset ),
1297 FT_FRAME_SHORT ( ySubscriptYOffset ),
1298 FT_FRAME_SHORT ( ySuperscriptXSize ),
1299 FT_FRAME_SHORT ( ySuperscriptYSize ),
1300 FT_FRAME_SHORT ( ySuperscriptXOffset ),
1301 FT_FRAME_SHORT ( ySuperscriptYOffset ),
1302 FT_FRAME_SHORT ( yStrikeoutSize ),
1303 FT_FRAME_SHORT ( yStrikeoutPosition ),
1304 FT_FRAME_SHORT ( sFamilyClass ),
1305 FT_FRAME_BYTE ( panose[0] ),
1306 FT_FRAME_BYTE ( panose[1] ),
1307 FT_FRAME_BYTE ( panose[2] ),
1308 FT_FRAME_BYTE ( panose[3] ),
1309 FT_FRAME_BYTE ( panose[4] ),
1310 FT_FRAME_BYTE ( panose[5] ),
1311 FT_FRAME_BYTE ( panose[6] ),
1312 FT_FRAME_BYTE ( panose[7] ),
1313 FT_FRAME_BYTE ( panose[8] ),
1314 FT_FRAME_BYTE ( panose[9] ),
1315 FT_FRAME_ULONG ( ulUnicodeRange1 ),
1316 FT_FRAME_ULONG ( ulUnicodeRange2 ),
1317 FT_FRAME_ULONG ( ulUnicodeRange3 ),
1318 FT_FRAME_ULONG ( ulUnicodeRange4 ),
1319 FT_FRAME_BYTE ( achVendID[0] ),
1320 FT_FRAME_BYTE ( achVendID[1] ),
1321 FT_FRAME_BYTE ( achVendID[2] ),
1322 FT_FRAME_BYTE ( achVendID[3] ),
1324 FT_FRAME_USHORT( fsSelection ),
1325 FT_FRAME_USHORT( usFirstCharIndex ),
1326 FT_FRAME_USHORT( usLastCharIndex ),
1327 FT_FRAME_SHORT ( sTypoAscender ),
1328 FT_FRAME_SHORT ( sTypoDescender ),
1329 FT_FRAME_SHORT ( sTypoLineGap ),
1330 FT_FRAME_USHORT( usWinAscent ),
1331 FT_FRAME_USHORT( usWinDescent ),
1335 const FT_Frame_Field os2_fields_extra[] =
1337 FT_FRAME_START( 8 ),
1338 FT_FRAME_ULONG( ulCodePageRange1 ),
1339 FT_FRAME_ULONG( ulCodePageRange2 ),
1343 const FT_Frame_Field os2_fields_extra2[] =
1345 FT_FRAME_START( 10 ),
1346 FT_FRAME_SHORT ( sxHeight ),
1347 FT_FRAME_SHORT ( sCapHeight ),
1348 FT_FRAME_USHORT( usDefaultChar ),
1349 FT_FRAME_USHORT( usBreakChar ),
1350 FT_FRAME_USHORT( usMaxContext ),
1355 FT_TRACE2(( "OS/2 Table " ));
1357 /* We now support old Mac fonts where the OS/2 table doesn't */
1358 /* exist. Simply put, we set the `version' field to 0xFFFF */
1359 /* and test this value each time we need to access the table. */
1360 error = face->goto_table( face, TTAG_OS2, stream, 0 );
1363 FT_TRACE2(( "is missing!\n" ));
1364 face->os2.version = 0xFFFFU;
1365 error = SFNT_Err_Ok;
1371 if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
1374 os2->ulCodePageRange1 = 0;
1375 os2->ulCodePageRange2 = 0;
1377 os2->sCapHeight = 0;
1378 os2->usDefaultChar = 0;
1379 os2->usBreakChar = 0;
1380 os2->usMaxContext = 0;
1382 if ( os2->version >= 0x0001 )
1384 /* only version 1 tables */
1385 if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
1388 if ( os2->version >= 0x0002 )
1390 /* only version 2 tables */
1391 if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
1396 FT_TRACE2(( "loaded\n" ));
1403 /*************************************************************************/
1406 /* tt_face_load_postscript */
1409 /* Loads the Postscript table. */
1412 /* face :: A handle to the target face object. */
1414 /* stream :: A handle to the input stream. */
1417 /* FreeType error code. 0 means success. */
1419 FT_LOCAL_DEF( FT_Error )
1420 tt_face_load_postscript( TT_Face face,
1424 TT_Postscript* post = &face->postscript;
1426 static const FT_Frame_Field post_fields[] =
1429 #define FT_STRUCTURE TT_Postscript
1431 FT_FRAME_START( 32 ),
1432 FT_FRAME_ULONG( FormatType ),
1433 FT_FRAME_ULONG( italicAngle ),
1434 FT_FRAME_SHORT( underlinePosition ),
1435 FT_FRAME_SHORT( underlineThickness ),
1436 FT_FRAME_ULONG( isFixedPitch ),
1437 FT_FRAME_ULONG( minMemType42 ),
1438 FT_FRAME_ULONG( maxMemType42 ),
1439 FT_FRAME_ULONG( minMemType1 ),
1440 FT_FRAME_ULONG( maxMemType1 ),
1445 FT_TRACE2(( "PostScript " ));
1447 error = face->goto_table( face, TTAG_post, stream, 0 );
1449 return SFNT_Err_Post_Table_Missing;
1451 if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
1454 /* we don't load the glyph names, we do that in another */
1455 /* module (ttpost). */
1456 FT_TRACE2(( "loaded\n" ));
1462 /*************************************************************************/
1465 /* tt_face_load_pclt */
1468 /* Loads the PCL 5 Table. */
1471 /* face :: A handle to the target face object. */
1473 /* stream :: A handle to the input stream. */
1476 /* FreeType error code. 0 means success. */
1478 FT_LOCAL_DEF( FT_Error )
1479 tt_face_load_pclt( TT_Face face,
1482 static const FT_Frame_Field pclt_fields[] =
1485 #define FT_STRUCTURE TT_PCLT
1487 FT_FRAME_START( 54 ),
1488 FT_FRAME_ULONG ( Version ),
1489 FT_FRAME_ULONG ( FontNumber ),
1490 FT_FRAME_USHORT( Pitch ),
1491 FT_FRAME_USHORT( xHeight ),
1492 FT_FRAME_USHORT( Style ),
1493 FT_FRAME_USHORT( TypeFamily ),
1494 FT_FRAME_USHORT( CapHeight ),
1495 FT_FRAME_BYTES ( TypeFace, 16 ),
1496 FT_FRAME_BYTES ( CharacterComplement, 8 ),
1497 FT_FRAME_BYTES ( FileName, 6 ),
1498 FT_FRAME_CHAR ( StrokeWeight ),
1499 FT_FRAME_CHAR ( WidthType ),
1500 FT_FRAME_BYTE ( SerifStyle ),
1501 FT_FRAME_BYTE ( Reserved ),
1506 TT_PCLT* pclt = &face->pclt;
1509 FT_TRACE2(( "PCLT " ));
1511 /* optional table */
1512 error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1515 FT_TRACE2(( "missing (optional)\n" ));
1520 if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
1523 FT_TRACE2(( "loaded\n" ));
1530 /*************************************************************************/
1533 /* tt_face_load_gasp */
1536 /* Loads the `gasp' table into a face object. */
1539 /* face :: A handle to the target face object. */
1541 /* stream :: The input stream. */
1544 /* FreeType error code. 0 means success. */
1546 FT_LOCAL_DEF( FT_Error )
1547 tt_face_load_gasp( TT_Face face,
1551 FT_Memory memory = stream->memory;
1553 FT_UInt j,num_ranges;
1554 TT_GaspRange gaspranges;
1557 FT_TRACE2(( "tt_face_load_gasp: %08p\n", face ));
1559 /* the gasp table is optional */
1560 error = face->goto_table( face, TTAG_gasp, stream, 0 );
1564 if ( FT_FRAME_ENTER( 4L ) )
1567 face->gasp.version = FT_GET_USHORT();
1568 face->gasp.numRanges = FT_GET_USHORT();
1572 num_ranges = face->gasp.numRanges;
1573 FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
1575 if ( FT_NEW_ARRAY( gaspranges, num_ranges ) ||
1576 FT_FRAME_ENTER( num_ranges * 4L ) )
1579 face->gasp.gaspRanges = gaspranges;
1581 for ( j = 0; j < num_ranges; j++ )
1583 gaspranges[j].maxPPEM = FT_GET_USHORT();
1584 gaspranges[j].gaspFlag = FT_GET_USHORT();
1586 FT_TRACE3(( " [max:%d flag:%d]",
1587 gaspranges[j].maxPPEM,
1588 gaspranges[j].gaspFlag ));
1590 FT_TRACE3(( "\n" ));
1593 FT_TRACE2(( "GASP loaded\n" ));
1600 FT_CALLBACK_DEF( int )
1601 tt_kern_pair_compare( const void* a,
1605 /*************************************************************************/
1608 /* tt_face_load_kern */
1611 /* Loads the first kerning table with format 0 in the font. Only */
1612 /* accepts the first horizontal kerning table. Developers should use */
1613 /* the `ftxkern' extension to access other kerning tables in the font */
1614 /* file, if they really want to. */
1617 /* face :: A handle to the target face object. */
1619 /* stream :: The input stream. */
1622 /* FreeType error code. 0 means success. */
1624 FT_LOCAL_DEF( FT_Error )
1625 tt_face_load_kern( TT_Face face,
1629 FT_Memory memory = stream->memory;
1631 FT_UInt n, num_tables;
1634 /* the kern table is optional; exit silently if it is missing */
1635 error = face->goto_table( face, TTAG_kern, stream, 0 );
1639 if ( FT_FRAME_ENTER( 4L ) )
1642 (void)FT_GET_USHORT(); /* version */
1643 num_tables = FT_GET_USHORT();
1647 for ( n = 0; n < num_tables; n++ )
1653 if ( FT_FRAME_ENTER( 6L ) )
1656 (void)FT_GET_USHORT(); /* version */
1657 length = FT_GET_USHORT() - 6; /* substract header length */
1658 coverage = FT_GET_USHORT();
1662 if ( coverage == 0x0001 )
1666 TT_Kern0_Pair limit;
1669 /* found a horizontal format 0 kerning table! */
1670 if ( FT_FRAME_ENTER( 8L ) )
1673 num_pairs = FT_GET_USHORT();
1679 /* allocate array of kerning pairs */
1680 if ( FT_NEW_ARRAY( face->kern_pairs, num_pairs ) ||
1681 FT_FRAME_ENTER( 6L * num_pairs ) )
1684 pair = face->kern_pairs;
1685 limit = pair + num_pairs;
1686 for ( ; pair < limit; pair++ )
1688 pair->left = FT_GET_USHORT();
1689 pair->right = FT_GET_USHORT();
1690 pair->value = FT_GET_USHORT();
1695 face->num_kern_pairs = num_pairs;
1696 face->kern_table_index = n;
1698 /* ensure that the kerning pair table is sorted (yes, some */
1699 /* fonts have unsorted tables!) */
1702 TT_Kern0_Pair pair0;
1705 pair0 = face->kern_pairs;
1707 for ( i = 1; i < num_pairs; i++, pair0++ )
1709 if ( tt_kern_pair_compare( pair0, pair0 + 1 ) != -1 )
1711 ft_qsort( (void*)face->kern_pairs, (int)num_pairs,
1712 sizeof ( TT_Kern0_PairRec ), tt_kern_pair_compare );
1721 if ( FT_STREAM_SKIP( length ) )
1725 /* no kern table found -- doesn't matter */
1726 face->kern_table_index = -1;
1727 face->num_kern_pairs = 0;
1728 face->kern_pairs = NULL;
1735 #undef TT_KERN_INDEX
1736 #define TT_KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 )
1739 FT_CALLBACK_DEF( int )
1740 tt_kern_pair_compare( const void* a,
1743 TT_Kern0_Pair pair1 = (TT_Kern0_Pair)a;
1744 TT_Kern0_Pair pair2 = (TT_Kern0_Pair)b;
1746 FT_ULong index1 = TT_KERN_INDEX( pair1->left, pair1->right );
1747 FT_ULong index2 = TT_KERN_INDEX( pair2->left, pair2->right );
1750 return ( index1 < index2 ? -1 :
1751 ( index1 > index2 ? 1 : 0 ));
1755 #undef TT_KERN_INDEX
1758 /*************************************************************************/
1761 /* tt_face_load_hdmx */
1764 /* Loads the horizontal device metrics table. */
1767 /* face :: A handle to the target face object. */
1769 /* stream :: A handle to the input stream. */
1772 /* FreeType error code. 0 means success. */
1774 FT_LOCAL_DEF( FT_Error )
1775 tt_face_load_hdmx( TT_Face face,
1779 FT_Memory memory = stream->memory;
1781 TT_Hdmx hdmx = &face->hdmx;
1783 FT_Long record_size;
1787 hdmx->num_records = 0;
1790 /* this table is optional */
1791 error = face->goto_table( face, TTAG_hdmx, stream, 0 );
1795 if ( FT_FRAME_ENTER( 8L ) )
1798 hdmx->version = FT_GET_USHORT();
1799 hdmx->num_records = FT_GET_SHORT();
1800 record_size = FT_GET_LONG();
1804 /* Only recognize format 0 */
1805 if ( hdmx->version != 0 )
1808 if ( FT_NEW_ARRAY( hdmx->records, hdmx->num_records ) )
1811 num_glyphs = face->root.num_glyphs;
1812 record_size -= num_glyphs + 2;
1815 TT_HdmxEntry cur = hdmx->records;
1816 TT_HdmxEntry limit = cur + hdmx->num_records;
1819 for ( ; cur < limit; cur++ )
1822 if ( FT_READ_BYTE( cur->ppem ) ||
1823 FT_READ_BYTE( cur->max_width ) )
1826 if ( FT_ALLOC( cur->widths, num_glyphs ) ||
1827 FT_STREAM_READ( cur->widths, num_glyphs ) )
1830 /* skip padding bytes */
1831 if ( record_size > 0 && FT_STREAM_SKIP( record_size ) )
1841 /*************************************************************************/
1844 /* tt_face_free_hdmx */
1847 /* Frees the horizontal device metrics table. */
1850 /* face :: A handle to the target face object. */
1852 FT_LOCAL_DEF( void )
1853 tt_face_free_hdmx( TT_Face face )
1858 FT_Memory memory = face->root.driver->root.memory;
1861 for ( n = 0; n < face->hdmx.num_records; n++ )
1862 FT_FREE( face->hdmx.records[n].widths );
1864 FT_FREE( face->hdmx.records );
1865 face->hdmx.num_records = 0;