1 /***************************************************************************/
5 /* Load the basic TrueType tables, i.e., tables that can be either in */
6 /* TTF or OTF fonts (body). */
8 /* Copyright 1996-2000 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 /***************************************************************************/
20 #include <freetype/internal/ftdebug.h>
21 #include <freetype/internal/tterrors.h>
22 #include <freetype/tttags.h>
25 #ifdef FT_FLAT_COMPILE
32 #include <sfnt/ttload.h>
33 #include <sfnt/ttcmap.h>
38 /*************************************************************************/
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
45 #define FT_COMPONENT trace_ttload
48 /*************************************************************************/
54 /* Looks for a TrueType table by name. */
57 /* face :: A face object handle. */
58 /* tag :: The searched tag. */
61 /* A pointer to the table directory entry. 0 if not found. */
64 TT_Table
* TT_LookUp_Table( TT_Face face
,
71 FT_TRACE3(( "TT_LookUp_Table: %08p, `%c%c%c%c'\n",
73 (FT_Char
)( tag
>> 24 ),
74 (FT_Char
)( tag
>> 16 ),
75 (FT_Char
)( tag
>> 8 ),
78 entry
= face
->dir_tables
;
79 limit
= entry
+ face
->num_tables
;
81 for ( ; entry
< limit
; entry
++ )
83 if ( entry
->Tag
== tag
)
87 FT_TRACE3(( " Could not find table!\n" ));
92 /*************************************************************************/
98 /* Looks for a TrueType table by name, then seek a stream to it. */
101 /* face :: A face object handle. */
102 /* 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. */
112 FT_Error
TT_Goto_Table( TT_Face face
,
121 table
= TT_LookUp_Table( face
, tag
);
125 *length
= table
->Length
;
127 (void)FILE_Seek( table
->Offset
);
130 error
= TT_Err_Table_Missing
;
136 /*************************************************************************/
139 /* TT_Load_SFNT_Header */
142 /* Loads the header of a SFNT font file. Supports collections. */
145 /* face :: A handle to the target face object. */
146 /* stream :: The input stream. */
147 /* face_index :: If the font is a collection, the number of the font */
148 /* in the collection, ignored otherwise. */
151 /* sfnt :: The SFNT header. */
154 /* FreeType error code. 0 means success. */
157 /* The stream cursor must be at the font file's origin. */
159 /* This function recognizes fonts embedded in a `TrueType collection' */
161 /* The header will be checked whether it is valid by looking at the */
162 /* values of `search_range', `entry_selector', and `range_shift'. */
165 FT_Error
TT_Load_SFNT_Header( TT_Face face
,
172 FT_Memory memory
= stream
->memory
;
174 const FT_Frame_Field sfnt_header_fields
[] =
177 FT_FRAME_USHORT( SFNT_Header
, num_tables
),
178 FT_FRAME_USHORT( SFNT_Header
, search_range
),
179 FT_FRAME_USHORT( SFNT_Header
, entry_selector
),
180 FT_FRAME_USHORT( SFNT_Header
, range_shift
),
184 const FT_Frame_Field ttc_header_fields
[] =
187 FT_FRAME_LONG( TTC_Header
, version
),
188 FT_FRAME_LONG( TTC_Header
, count
),
192 FT_TRACE2(( "TT_Load_SFNT_Header: %08p, %ld\n",
195 face
->ttc_header
.tag
= 0;
196 face
->ttc_header
.version
= 0;
197 face
->ttc_header
.count
= 0;
199 face
->num_tables
= 0;
201 /* first of all, read the first 4 bytes. If it is `ttcf', then the */
202 /* file is a TrueType collection, otherwise it can be any other */
204 if ( READ_ULong( format_tag
) )
207 if ( format_tag
== TTAG_ttcf
)
212 FT_TRACE3(( "TT_Load_SFNT_Header: file is a collection\n" ));
214 /* it's a TrueType collection, i.e. a file containing several */
215 /* font files. Read the font directory now */
216 if ( READ_Fields( ttc_header_fields
, &face
->ttc_header
) )
219 /* now read the offsets of each font in the file */
220 if ( ALLOC_ARRAY( face
->ttc_header
.offsets
,
221 face
->ttc_header
.count
,
223 ACCESS_Frame( face
->ttc_header
.count
* 4L ) )
226 for ( n
= 0; n
< face
->ttc_header
.count
; n
++ )
227 face
->ttc_header
.offsets
[n
] = GET_ULong();
231 /* check face index */
232 if ( face_index
>= face
->ttc_header
.count
)
234 error
= TT_Err_Bad_Argument
;
238 /* seek to the appropriate TrueType file, then read tag */
239 if ( FILE_Seek( face
->ttc_header
.offsets
[face_index
] ) ||
240 READ_Long( format_tag
) )
244 /* the format tag was read, now check the rest of the header */
245 sfnt
->format_tag
= format_tag
;
246 if ( READ_Fields( sfnt_header_fields
, sfnt
) )
249 /* now, check the values of `num_tables', `seach_range', etc. */
251 FT_UInt num_tables
= sfnt
->num_tables
;
252 FT_ULong entry_selector
= 1L << sfnt
->entry_selector
;
255 /* IMPORTANT: Many fonts have an incorrect `search_range' value, so */
256 /* we only check the `entry_selector' correctness here. */
258 if ( num_tables
== 0 ||
259 entry_selector
> num_tables
||
260 entry_selector
* 2 <= num_tables
)
262 FT_TRACE2(( "TT_Load_SFNT_Header: file is not SFNT!\n" ));
263 error
= FT_Err_Unknown_File_Format
;
272 /*************************************************************************/
275 /* TT_Load_Directory */
278 /* Loads the table directory into a face object. */
281 /* face :: A handle to the target face object. */
284 /* stream :: The input stream. */
285 /* sfnt :: The SFNT directory header. */
288 /* FreeType error code. 0 means success. */
291 /* The stream cursor must be at the font file's origin. */
294 FT_Error
TT_Load_Directory( TT_Face face
,
299 FT_Memory memory
= stream
->memory
;
301 TT_Table
*entry
, *limit
;
304 FT_TRACE2(( "TT_Load_Directory: %08p\n", face
));
306 FT_TRACE2(( "-- Tables count: %12u\n", sfnt
->num_tables
));
307 FT_TRACE2(( "-- Format version: %08lx\n", sfnt
->format_tag
));
309 face
->num_tables
= sfnt
->num_tables
;
311 if ( ALLOC_ARRAY( face
->dir_tables
,
316 if ( ACCESS_Frame( face
->num_tables
* 16L ) )
319 entry
= face
->dir_tables
;
320 limit
= entry
+ face
->num_tables
;
322 for ( ; entry
< limit
; entry
++ )
323 { /* loop through the tables and get all entries */
324 entry
->Tag
= GET_Tag4();
325 entry
->CheckSum
= GET_ULong();
326 entry
->Offset
= GET_Long();
327 entry
->Length
= GET_Long();
329 FT_TRACE2(( " %c%c%c%c - %08lx - %08lx\n",
330 (FT_Char
)( entry
->Tag
>> 24 ),
331 (FT_Char
)( entry
->Tag
>> 16 ),
332 (FT_Char
)( entry
->Tag
>> 8 ),
333 (FT_Char
)( entry
->Tag
),
340 FT_TRACE2(( "Directory loaded\n\n" ));
347 /*************************************************************************/
353 /* Loads any font table into client memory. */
356 /* face :: The face object to look for. */
358 /* tag :: The tag of table to load. Use the value 0 if you want */
359 /* to access the whole font file, else set this parameter */
360 /* to a valid TrueType table tag that you can forge with */
361 /* the MAKE_TT_TAG macro. */
363 /* offset :: The starting offset in the table (or the file if */
366 /* length :: The address of the decision variable: */
368 /* If length == NULL: */
369 /* Loads the whole table. Returns an error if */
372 /* If *length == 0: */
373 /* Exits immediately; returning the length of the given */
374 /* table or of the font file, depending on the value of */
377 /* If *length != 0: */
378 /* Loads the next `length' bytes of table or font, */
379 /* starting at offset `offset' (in table or font too). */
382 /* buffer :: The address of target buffer. */
385 /* FreeType error code. 0 means success. */
388 FT_Error
TT_Load_Any( TT_Face face
,
402 /* look for tag in font directory */
403 table
= TT_LookUp_Table( face
, tag
);
406 error
= TT_Err_Table_Missing
;
410 offset
+= table
->Offset
;
411 size
= table
->Length
;
414 /* tag == 0 -- the user wants to access the font file directly */
415 size
= face
->root
.stream
->size
;
417 if ( length
&& *length
== 0 )
427 stream
= face
->root
.stream
;
428 (void)FILE_Read_At( offset
, buffer
, size
);
435 /*************************************************************************/
441 /* Loads the TrueType font header. */
444 /* face :: A handle to the target face object. */
445 /* stream :: The input stream. */
448 /* FreeType error code. 0 means success. */
451 FT_Error
TT_Load_Header( TT_Face face
,
457 static const FT_Frame_Field header_fields
[] =
459 FT_FRAME_START( 54 ),
460 FT_FRAME_ULONG( TT_Header
, Table_Version
),
461 FT_FRAME_ULONG( TT_Header
, Font_Revision
),
462 FT_FRAME_LONG( TT_Header
, CheckSum_Adjust
),
463 FT_FRAME_LONG( TT_Header
, Magic_Number
),
464 FT_FRAME_USHORT( TT_Header
, Flags
),
465 FT_FRAME_USHORT( TT_Header
, Units_Per_EM
),
466 FT_FRAME_LONG( TT_Header
, Created
[0] ),
467 FT_FRAME_LONG( TT_Header
, Created
[1] ),
468 FT_FRAME_LONG( TT_Header
, Modified
[0] ),
469 FT_FRAME_LONG( TT_Header
, Modified
[1] ),
470 FT_FRAME_SHORT( TT_Header
, xMin
),
471 FT_FRAME_SHORT( TT_Header
, yMin
),
472 FT_FRAME_SHORT( TT_Header
, xMax
),
473 FT_FRAME_SHORT( TT_Header
, yMax
),
474 FT_FRAME_USHORT( TT_Header
, Mac_Style
),
475 FT_FRAME_USHORT( TT_Header
, Lowest_Rec_PPEM
),
476 FT_FRAME_SHORT( TT_Header
, Font_Direction
),
477 FT_FRAME_SHORT( TT_Header
, Index_To_Loc_Format
),
478 FT_FRAME_SHORT( TT_Header
, Glyph_Data_Format
),
483 FT_TRACE2(( "Load_TT_Header: %08p\n", face
));
485 error
= face
->goto_table( face
, TTAG_head
, stream
, 0 );
488 FT_TRACE0(( "Font Header is missing!\n" ));
492 header
= &face
->header
;
494 if ( READ_Fields( header_fields
, header
) )
497 FT_TRACE2(( " Units per EM: %8u\n", header
->Units_Per_EM
));
498 FT_TRACE2(( " IndexToLoc: %8d\n", header
->Index_To_Loc_Format
));
499 FT_TRACE2(( "Font Header Loaded.\n" ));
506 /*************************************************************************/
509 /* TT_Load_MaxProfile */
512 /* Loads the maximum profile into a face object. */
515 /* face :: A handle to the target face object. */
516 /* stream :: The input stream. */
519 /* FreeType error code. 0 means success. */
522 FT_Error
TT_Load_MaxProfile( TT_Face face
,
526 TT_MaxProfile
* maxProfile
= &face
->max_profile
;
528 const FT_Frame_Field maxp_fields
[] =
530 FT_FRAME_START( 32 ),
531 FT_FRAME_ULONG( TT_MaxProfile
, version
),
532 FT_FRAME_USHORT( TT_MaxProfile
, numGlyphs
),
533 FT_FRAME_USHORT( TT_MaxProfile
, maxPoints
),
534 FT_FRAME_USHORT( TT_MaxProfile
, maxContours
),
535 FT_FRAME_USHORT( TT_MaxProfile
, maxCompositePoints
),
536 FT_FRAME_USHORT( TT_MaxProfile
, maxCompositeContours
),
537 FT_FRAME_USHORT( TT_MaxProfile
, maxZones
),
538 FT_FRAME_USHORT( TT_MaxProfile
, maxTwilightPoints
),
539 FT_FRAME_USHORT( TT_MaxProfile
, maxStorage
),
540 FT_FRAME_USHORT( TT_MaxProfile
, maxFunctionDefs
),
541 FT_FRAME_USHORT( TT_MaxProfile
, maxInstructionDefs
),
542 FT_FRAME_USHORT( TT_MaxProfile
, maxStackElements
),
543 FT_FRAME_USHORT( TT_MaxProfile
, maxSizeOfInstructions
),
544 FT_FRAME_USHORT( TT_MaxProfile
, maxComponentElements
),
545 FT_FRAME_USHORT( TT_MaxProfile
, maxComponentDepth
),
549 FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face
));
551 error
= face
->goto_table( face
, TTAG_maxp
, stream
, 0 );
555 if ( READ_Fields( maxp_fields
, maxProfile
) )
558 /* XXX: an adjustment that is necessary to load certain */
559 /* broken fonts like `Keystrokes MT' :-( */
561 /* We allocate 64 function entries by default when */
562 /* the maxFunctionDefs field is null. */
564 if ( maxProfile
->maxFunctionDefs
== 0 )
565 maxProfile
->maxFunctionDefs
= 64;
567 face
->root
.num_glyphs
= maxProfile
->numGlyphs
;
569 face
->root
.max_points
= MAX( maxProfile
->maxCompositePoints
,
570 maxProfile
->maxPoints
);
572 face
->root
.max_contours
= MAX( maxProfile
->maxCompositeContours
,
573 maxProfile
->maxContours
);
575 face
->max_components
= (FT_ULong
)maxProfile
->maxComponentElements
+
576 maxProfile
->maxComponentDepth
;
578 /* XXX: some fonts have maxComponents set to 0; we will */
579 /* then use 16 of them by default. */
580 if ( face
->max_components
== 0 )
581 face
->max_components
= 16;
583 /* We also increase maxPoints and maxContours in order to support */
584 /* some broken fonts. */
585 face
->root
.max_points
+= 8;
586 face
->root
.max_contours
+= 4;
588 FT_TRACE2(( "MAXP loaded.\n" ));
595 /*************************************************************************/
598 /* TT_Load_Metrics */
601 /* Loads the horizontal or vertical metrics table into a face object. */
604 /* face :: A handle to the target face object. */
605 /* stream :: The input stream. */
606 /* vertical :: A boolean flag. If set, load vertical metrics. */
609 /* FreeType error code. 0 means success. */
612 FT_Error
TT_Load_Metrics( TT_Face face
,
617 FT_Memory memory
= stream
->memory
;
620 FT_Long num_shorts
, num_longs
, num_shorts_checked
;
622 TT_LongMetrics
** longs
;
623 TT_ShortMetrics
** shorts
;
626 FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical
? "Vertical"
632 /* The table is optional, quit silently if it wasn't found */
633 /* XXX: Some fonts have a valid vertical header with a non-null */
634 /* `number_of_VMetrics' fields, but no corresponding `vmtx' */
635 /* table to get the metrics from (e.g. mingliu). */
637 /* For safety, we set the field to 0! */
639 error
= face
->goto_table( face
, TTAG_vmtx
, stream
, &table_len
);
642 /* Set number_Of_VMetrics to 0! */
643 FT_TRACE2(( " no vertical header in file.\n" ));
644 face
->vertical
.number_Of_VMetrics
= 0;
649 num_longs
= face
->vertical
.number_Of_VMetrics
;
650 longs
= (TT_LongMetrics
**)&face
->vertical
.long_metrics
;
651 shorts
= (TT_ShortMetrics
**)&face
->vertical
.short_metrics
;
655 error
= face
->goto_table( face
, TTAG_hmtx
, stream
, &table_len
);
658 FT_ERROR(( " no horizontal metrics in file!\n" ));
659 error
= TT_Err_Hmtx_Table_Missing
;
663 num_longs
= face
->horizontal
.number_Of_HMetrics
;
664 longs
= (TT_LongMetrics
**)&face
->horizontal
.long_metrics
;
665 shorts
= (TT_ShortMetrics
**)&face
->horizontal
.short_metrics
;
668 /* never trust derived values */
670 num_shorts
= face
->max_profile
.numGlyphs
- num_longs
;
671 num_shorts_checked
= ( table_len
- num_longs
* 4L ) / 2;
673 if ( num_shorts
< 0 )
675 FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
676 vertical
? "Vertical"
679 error
= vertical
? TT_Err_Invalid_Vert_Metrics
680 : TT_Err_Invalid_Horiz_Metrics
;
684 if ( ALLOC_ARRAY( *longs
, num_longs
, TT_LongMetrics
) ||
685 ALLOC_ARRAY( *shorts
, num_shorts
, TT_ShortMetrics
) )
688 if ( ACCESS_Frame( table_len
) )
692 TT_LongMetrics
* cur
= *longs
;
693 TT_LongMetrics
* limit
= cur
+ num_longs
;
696 for ( ; cur
< limit
; cur
++ )
698 cur
->advance
= GET_UShort();
699 cur
->bearing
= GET_Short();
703 /* do we have an inconsistent number of metric values? */
705 TT_ShortMetrics
* cur
= *shorts
;
706 TT_ShortMetrics
* limit
= cur
+ MIN( num_shorts
, num_shorts_checked
);
709 for ( ; cur
< limit
; cur
++ )
712 /* we fill up the missing left side bearings with the */
713 /* last valid value. Since this will occur for buggy CJK */
714 /* fonts usually only, nothing serious will happen */
715 if ( num_shorts
> num_shorts_checked
&& num_shorts_checked
> 0 )
717 FT_Short val
= *(shorts
)[num_shorts_checked
- 1];
720 limit
= *shorts
+ num_shorts
;
721 for ( ; cur
< limit
; cur
++ )
728 FT_TRACE2(( "loaded\n" ));
735 /*************************************************************************/
738 /* TT_Load_Metrics_Header */
741 /* Loads the horizontal or vertical header in a face object. */
744 /* face :: A handle to the target face object. */
745 /* stream :: The input stream. */
746 /* vertical :: A boolean flag. If set, load vertical metrics. */
749 /* FreeType error code. 0 means success. */
752 FT_Error
TT_Load_Metrics_Header( TT_Face face
,
757 TT_HoriHeader
* header
;
759 const FT_Frame_Field metrics_header_fields
[] =
761 FT_FRAME_START( 36 ),
762 FT_FRAME_ULONG( TT_HoriHeader
, Version
),
763 FT_FRAME_SHORT( TT_HoriHeader
, Ascender
),
764 FT_FRAME_SHORT( TT_HoriHeader
, Descender
),
765 FT_FRAME_SHORT( TT_HoriHeader
, Line_Gap
),
766 FT_FRAME_USHORT( TT_HoriHeader
, advance_Width_Max
),
767 FT_FRAME_SHORT( TT_HoriHeader
, min_Left_Side_Bearing
),
768 FT_FRAME_SHORT( TT_HoriHeader
, min_Right_Side_Bearing
),
769 FT_FRAME_SHORT( TT_HoriHeader
, xMax_Extent
),
770 FT_FRAME_SHORT( TT_HoriHeader
, caret_Slope_Rise
),
771 FT_FRAME_SHORT( TT_HoriHeader
, caret_Slope_Run
),
772 FT_FRAME_SHORT( TT_HoriHeader
, Reserved
[0] ),
773 FT_FRAME_SHORT( TT_HoriHeader
, Reserved
[1] ),
774 FT_FRAME_SHORT( TT_HoriHeader
, Reserved
[2] ),
775 FT_FRAME_SHORT( TT_HoriHeader
, Reserved
[3] ),
776 FT_FRAME_SHORT( TT_HoriHeader
, Reserved
[4] ),
777 FT_FRAME_SHORT( TT_HoriHeader
, metric_Data_Format
),
778 FT_FRAME_USHORT( TT_HoriHeader
, number_Of_HMetrics
),
783 FT_TRACE2(( vertical
? "Vertical header " : "Horizontal header " ));
787 face
->vertical_info
= 0;
789 /* The vertical header table is optional, so return quietly if */
790 /* we don't find it. */
791 error
= face
->goto_table( face
, TTAG_vhea
, stream
, 0 );
798 face
->vertical_info
= 1;
799 header
= (TT_HoriHeader
*)&face
->vertical
;
803 /* The horizontal header is mandatory; return an error if we */
805 error
= face
->goto_table( face
, TTAG_hhea
, stream
, 0 );
808 error
= TT_Err_Horiz_Header_Missing
;
812 header
= &face
->horizontal
;
815 if ( READ_Fields( metrics_header_fields
, header
) )
818 header
->long_metrics
= NULL
;
819 header
->short_metrics
= NULL
;
821 FT_TRACE2(( "loaded\n" ));
823 /* Now try to load the corresponding metrics */
825 error
= TT_Load_Metrics( face
, stream
, vertical
);
832 /*************************************************************************/
838 /* Loads the name records. */
841 /* face :: A handle to the target face object. */
842 /* stream :: The input stream. */
845 /* FreeType error code. 0 means success. */
848 FT_Error
TT_Load_Names( TT_Face face
,
852 FT_Memory memory
= stream
->memory
;
854 FT_ULong table_pos
, table_len
;
855 FT_ULong storageSize
;
859 const FT_Frame_Field name_table_fields
[] =
862 FT_FRAME_USHORT( TT_NameTable
, format
),
863 FT_FRAME_USHORT( TT_NameTable
, numNameRecords
),
864 FT_FRAME_USHORT( TT_NameTable
, storageOffset
),
868 const FT_Frame_Field name_record_fields
[] =
870 /* no FT_FRAME_START */
871 FT_FRAME_USHORT( TT_NameRec
, platformID
),
872 FT_FRAME_USHORT( TT_NameRec
, encodingID
),
873 FT_FRAME_USHORT( TT_NameRec
, languageID
),
874 FT_FRAME_USHORT( TT_NameRec
, nameID
),
875 FT_FRAME_USHORT( TT_NameRec
, stringLength
),
876 FT_FRAME_USHORT( TT_NameRec
, stringOffset
),
881 FT_TRACE2(( "Names " ));
883 error
= face
->goto_table( face
, TTAG_name
, stream
, &table_len
);
886 /* The name table is required so indicate failure. */
887 FT_TRACE2(( "is missing!\n" ));
888 error
= TT_Err_Name_Table_Missing
;
892 table_pos
= FILE_Pos();
894 names
= &face
->name_table
;
896 if ( READ_Fields( name_table_fields
, names
) )
899 /* Allocate the array of name records. */
900 if ( ALLOC_ARRAY( names
->names
,
901 names
->numNameRecords
,
903 ACCESS_Frame( names
->numNameRecords
* 12L ) )
906 /* Load the name records and determine how much storage is needed */
907 /* to hold the strings themselves. */
909 TT_NameRec
* cur
= names
->names
;
910 TT_NameRec
* limit
= cur
+ names
->numNameRecords
;
915 for ( ; cur
< limit
; cur
++ )
920 (void)READ_Fields( name_record_fields
, cur
);
922 upper
= (FT_ULong
)( cur
->stringOffset
+ cur
->stringLength
);
923 if ( upper
> storageSize
)
930 if ( storageSize
> 0 )
932 /* allocate the name storage area in memory, then read it */
933 if ( ALLOC( names
->storage
, storageSize
) ||
934 FILE_Read_At( table_pos
+ names
->storageOffset
,
935 names
->storage
, storageSize
) )
938 /* Go through and assign the string pointers to the name records. */
940 TT_NameRec
* cur
= names
->names
;
941 TT_NameRec
* limit
= cur
+ names
->numNameRecords
;
944 for ( ; cur
< limit
; cur
++ )
945 cur
->string
= names
->storage
+ cur
->stringOffset
;
948 #ifdef FT_DEBUG_LEVEL_TRACE
950 /* Print Name Record Table in case of debugging */
952 TT_NameRec
* cur
= names
->names
;
953 TT_NameRec
* limit
= cur
+ names
->numNameRecords
;
956 for ( ; cur
< limit
; cur
++ )
961 FT_TRACE3(( "%d %d %x %d\n ",
967 /* I know that M$ encoded strings are Unicode, */
968 /* but this works reasonable well for debugging purposes. */
970 for ( j
= 0; j
< cur
->stringLength
; j
++ )
972 FT_Char c
= *( cur
->string
+ j
);
975 if ( (FT_Byte
)c
< 128 )
976 FT_TRACE3(( "%c", c
));
982 #endif /* FT_DEBUG_LEVEL_TRACE */
985 FT_TRACE2(( "loaded\n" ));
987 /* everything went well, update face->num_names */
988 face
->num_names
= names
->numNameRecords
;
995 /*************************************************************************/
1001 /* Frees the name records. */
1004 /* face :: A handle to the target face object. */
1007 void TT_Free_Names( TT_Face face
)
1009 FT_Memory memory
= face
->root
.driver
->root
.memory
;
1010 TT_NameTable
* names
= &face
->name_table
;
1013 /* free strings table */
1014 FREE( names
->names
);
1016 /* free strings storage */
1017 FREE( names
->storage
);
1019 names
->numNameRecords
= 0;
1021 names
->storageOffset
= 0;
1025 /*************************************************************************/
1031 /* Loads the cmap directory in a face object. The cmaps itselves are */
1032 /* loaded on demand in the `ttcmap.c' module. */
1035 /* face :: A handle to the target face object. */
1036 /* stream :: A handle to the input stream. */
1039 /* FreeType error code. 0 means success. */
1042 FT_Error
TT_Load_CMap( TT_Face face
,
1046 FT_Memory memory
= stream
->memory
;
1047 FT_Long table_start
;
1048 TT_CMapDir cmap_dir
;
1050 const FT_Frame_Field cmap_fields
[] =
1052 FT_FRAME_START( 4 ),
1053 FT_FRAME_USHORT( TT_CMapDir
, tableVersionNumber
),
1054 FT_FRAME_USHORT( TT_CMapDir
, numCMaps
),
1058 const FT_Frame_Field cmap_rec_fields
[] =
1060 FT_FRAME_START( 6 ),
1061 FT_FRAME_USHORT( TT_CMapTable
, format
),
1062 FT_FRAME_USHORT( TT_CMapTable
, length
),
1063 FT_FRAME_USHORT( TT_CMapTable
, version
),
1068 FT_TRACE2(( "CMaps " ));
1070 error
= face
->goto_table( face
, TTAG_cmap
, stream
, 0 );
1073 error
= TT_Err_CMap_Table_Missing
;
1077 table_start
= FILE_Pos();
1079 if ( READ_Fields( cmap_fields
, &cmap_dir
) )
1082 /* reserve space in face table for cmap tables */
1083 if ( ALLOC_ARRAY( face
->charmaps
,
1088 face
->num_charmaps
= cmap_dir
.numCMaps
;
1090 TT_CharMap charmap
= face
->charmaps
;
1091 TT_CharMap limit
= charmap
+ face
->num_charmaps
;
1094 /* read the header of each charmap first */
1095 if ( ACCESS_Frame( face
->num_charmaps
* 8L ) )
1098 for ( ; charmap
< limit
; charmap
++ )
1103 charmap
->root
.face
= (FT_Face
)face
;
1104 cmap
= &charmap
->cmap
;
1106 cmap
->loaded
= FALSE
;
1107 cmap
->platformID
= GET_UShort();
1108 cmap
->platformEncodingID
= GET_UShort();
1109 cmap
->offset
= (FT_ULong
)GET_Long();
1114 /* now read the rest of each table */
1115 for ( charmap
= face
->charmaps
; charmap
< limit
; charmap
++ )
1117 TT_CMapTable
* cmap
= &charmap
->cmap
;
1120 if ( FILE_Seek( table_start
+ (FT_Long
)cmap
->offset
) ||
1121 READ_Fields( cmap_rec_fields
, cmap
) )
1124 cmap
->offset
= FILE_Pos();
1128 FT_TRACE2(( "loaded\n" ));
1135 /*************************************************************************/
1141 /* Loads the OS2 table. */
1144 /* face :: A handle to the target face object. */
1145 /* stream :: A handle to the input stream. */
1148 /* FreeType error code. 0 means success. */
1151 FT_Error
TT_Load_OS2( TT_Face face
,
1157 const FT_Frame_Field os2_fields
[] =
1159 FT_FRAME_START( 78 ),
1160 FT_FRAME_USHORT( TT_OS2
, version
),
1161 FT_FRAME_SHORT( TT_OS2
, xAvgCharWidth
),
1162 FT_FRAME_USHORT( TT_OS2
, usWeightClass
),
1163 FT_FRAME_USHORT( TT_OS2
, usWidthClass
),
1164 FT_FRAME_SHORT( TT_OS2
, fsType
),
1165 FT_FRAME_SHORT( TT_OS2
, ySubscriptXSize
),
1166 FT_FRAME_SHORT( TT_OS2
, ySubscriptYSize
),
1167 FT_FRAME_SHORT( TT_OS2
, ySubscriptXOffset
),
1168 FT_FRAME_SHORT( TT_OS2
, ySubscriptYOffset
),
1169 FT_FRAME_SHORT( TT_OS2
, ySuperscriptXSize
),
1170 FT_FRAME_SHORT( TT_OS2
, ySuperscriptYSize
),
1171 FT_FRAME_SHORT( TT_OS2
, ySuperscriptXOffset
),
1172 FT_FRAME_SHORT( TT_OS2
, ySuperscriptYOffset
),
1173 FT_FRAME_SHORT( TT_OS2
, yStrikeoutSize
),
1174 FT_FRAME_SHORT( TT_OS2
, yStrikeoutPosition
),
1175 FT_FRAME_SHORT( TT_OS2
, sFamilyClass
),
1176 FT_FRAME_BYTE( TT_OS2
, panose
[0] ),
1177 FT_FRAME_BYTE( TT_OS2
, panose
[1] ),
1178 FT_FRAME_BYTE( TT_OS2
, panose
[2] ),
1179 FT_FRAME_BYTE( TT_OS2
, panose
[3] ),
1180 FT_FRAME_BYTE( TT_OS2
, panose
[4] ),
1181 FT_FRAME_BYTE( TT_OS2
, panose
[5] ),
1182 FT_FRAME_BYTE( TT_OS2
, panose
[6] ),
1183 FT_FRAME_BYTE( TT_OS2
, panose
[7] ),
1184 FT_FRAME_BYTE( TT_OS2
, panose
[8] ),
1185 FT_FRAME_BYTE( TT_OS2
, panose
[9] ),
1186 FT_FRAME_ULONG( TT_OS2
, ulUnicodeRange1
),
1187 FT_FRAME_ULONG( TT_OS2
, ulUnicodeRange2
),
1188 FT_FRAME_ULONG( TT_OS2
, ulUnicodeRange3
),
1189 FT_FRAME_ULONG( TT_OS2
, ulUnicodeRange4
),
1190 FT_FRAME_BYTE( TT_OS2
, achVendID
[0] ),
1191 FT_FRAME_BYTE( TT_OS2
, achVendID
[1] ),
1192 FT_FRAME_BYTE( TT_OS2
, achVendID
[2] ),
1193 FT_FRAME_BYTE( TT_OS2
, achVendID
[3] ),
1195 FT_FRAME_USHORT( TT_OS2
, fsSelection
),
1196 FT_FRAME_USHORT( TT_OS2
, usFirstCharIndex
),
1197 FT_FRAME_USHORT( TT_OS2
, usLastCharIndex
),
1198 FT_FRAME_SHORT( TT_OS2
, sTypoAscender
),
1199 FT_FRAME_SHORT( TT_OS2
, sTypoDescender
),
1200 FT_FRAME_SHORT( TT_OS2
, sTypoLineGap
),
1201 FT_FRAME_USHORT( TT_OS2
, usWinAscent
),
1202 FT_FRAME_USHORT( TT_OS2
, usWinDescent
),
1206 const FT_Frame_Field os2_fields_extra
[] =
1208 FT_FRAME_START( 8 ),
1209 FT_FRAME_ULONG( TT_OS2
, ulCodePageRange1
),
1210 FT_FRAME_ULONG( TT_OS2
, ulCodePageRange2
),
1214 const FT_Frame_Field os2_fields_extra2
[] =
1216 FT_FRAME_START( 10 ),
1217 FT_FRAME_SHORT( TT_OS2
, sxHeight
),
1218 FT_FRAME_SHORT( TT_OS2
, sCapHeight
),
1219 FT_FRAME_USHORT( TT_OS2
, usDefaultChar
),
1220 FT_FRAME_USHORT( TT_OS2
, usBreakChar
),
1221 FT_FRAME_USHORT( TT_OS2
, usMaxContext
),
1226 FT_TRACE2(( "OS/2 Table " ));
1228 /* We now support old Mac fonts where the OS/2 table doesn't */
1229 /* exist. Simply put, we set the `version' field to 0xFFFF */
1230 /* and test this value each time we need to access the table. */
1231 error
= face
->goto_table( face
, TTAG_OS2
, stream
, 0 );
1234 FT_TRACE2(( "is missing!\n" ));
1235 face
->os2
.version
= 0xFFFF;
1242 if ( READ_Fields( os2_fields
, os2
) )
1245 os2
->ulCodePageRange1
= 0;
1246 os2
->ulCodePageRange2
= 0;
1248 if ( os2
->version
>= 0x0001 )
1250 /* only version 1 tables */
1251 if ( READ_Fields( os2_fields_extra
, os2
) )
1254 if ( os2
->version
>= 0x0002 )
1256 /* only version 2 tables */
1257 if ( READ_Fields( os2_fields_extra2
, os2
) )
1262 FT_TRACE2(( "loaded\n" ));
1269 /*************************************************************************/
1272 /* TT_Load_Postscript */
1275 /* Loads the Postscript table. */
1278 /* face :: A handle to the target face object. */
1279 /* stream :: A handle to the input stream. */
1282 /* FreeType error code. 0 means success. */
1285 FT_Error
TT_Load_PostScript( TT_Face face
,
1289 TT_Postscript
* post
= &face
->postscript
;
1291 static const FT_Frame_Field post_fields
[] =
1293 FT_FRAME_START( 32 ),
1294 FT_FRAME_ULONG( TT_Postscript
, FormatType
),
1295 FT_FRAME_ULONG( TT_Postscript
, italicAngle
),
1296 FT_FRAME_SHORT( TT_Postscript
, underlinePosition
),
1297 FT_FRAME_SHORT( TT_Postscript
, underlineThickness
),
1298 FT_FRAME_ULONG( TT_Postscript
, isFixedPitch
),
1299 FT_FRAME_ULONG( TT_Postscript
, minMemType42
),
1300 FT_FRAME_ULONG( TT_Postscript
, maxMemType42
),
1301 FT_FRAME_ULONG( TT_Postscript
, minMemType1
),
1302 FT_FRAME_ULONG( TT_Postscript
, maxMemType1
),
1307 FT_TRACE2(( "PostScript " ));
1309 error
= face
->goto_table( face
, TTAG_post
, stream
, 0 );
1311 return TT_Err_Post_Table_Missing
;
1313 if ( READ_Fields( post_fields
, post
) )
1316 /* we don't load the glyph names, we do that in another */
1317 /* module (ttpost). */
1318 FT_TRACE2(( "loaded\n" ));
1324 /*************************************************************************/
1330 /* Loads the PCL 5 Table. */
1333 /* face :: A handle to the target face object. */
1334 /* stream :: A handle to the input stream. */
1337 /* FreeType error code. 0 means success. */
1340 FT_Error
TT_Load_PCLT( TT_Face face
,
1343 static const FT_Frame_Field pclt_fields
[] =
1345 FT_FRAME_START( 54 ),
1346 FT_FRAME_ULONG ( TT_PCLT
, Version
),
1347 FT_FRAME_ULONG ( TT_PCLT
, FontNumber
),
1348 FT_FRAME_USHORT( TT_PCLT
, Pitch
),
1349 FT_FRAME_USHORT( TT_PCLT
, xHeight
),
1350 FT_FRAME_USHORT( TT_PCLT
, Style
),
1351 FT_FRAME_USHORT( TT_PCLT
, TypeFamily
),
1352 FT_FRAME_USHORT( TT_PCLT
, CapHeight
),
1353 FT_FRAME_BYTES ( TT_PCLT
, TypeFace
, 16 ),
1354 FT_FRAME_BYTES ( TT_PCLT
, CharacterComplement
, 8 ),
1355 FT_FRAME_BYTES ( TT_PCLT
, FileName
, 6 ),
1356 FT_FRAME_CHAR ( TT_PCLT
, StrokeWeight
),
1357 FT_FRAME_CHAR ( TT_PCLT
, WidthType
),
1358 FT_FRAME_BYTE ( TT_PCLT
, SerifStyle
),
1359 FT_FRAME_BYTE ( TT_PCLT
, Reserved
),
1364 TT_PCLT
* pclt
= &face
->pclt
;
1367 FT_TRACE2(( "PCLT " ));
1369 /* optional table */
1370 error
= face
->goto_table( face
, TTAG_PCLT
, stream
, 0 );
1373 FT_TRACE2(( "missing (optional)\n" ));
1378 if ( READ_Fields( pclt_fields
, pclt
) )
1381 FT_TRACE2(( "loaded\n" ));
1388 /*************************************************************************/
1394 /* Loads the `gasp' table into a face object. */
1397 /* face :: A handle to the target face object. */
1398 /* stream :: The input stream. */
1401 /* FreeType error code. 0 means success. */
1404 FT_Error
TT_Load_Gasp( TT_Face face
,
1408 FT_Memory memory
= stream
->memory
;
1410 FT_UInt j
,num_ranges
;
1411 TT_GaspRange
* gaspranges
;
1414 FT_TRACE2(( "TT_Load_Gasp: %08p\n", face
));
1416 /* the gasp table is optional */
1417 error
= face
->goto_table( face
, TTAG_gasp
, stream
, 0 );
1421 if ( ACCESS_Frame( 4L ) )
1424 face
->gasp
.version
= GET_UShort();
1425 face
->gasp
.numRanges
= GET_UShort();
1429 num_ranges
= face
->gasp
.numRanges
;
1430 FT_TRACE3(( "number of ranges = %d\n", num_ranges
));
1432 if ( ALLOC_ARRAY( gaspranges
, num_ranges
, TT_GaspRange
) ||
1433 ACCESS_Frame( num_ranges
* 4L ) )
1436 face
->gasp
.gaspRanges
= gaspranges
;
1438 for ( j
= 0; j
< num_ranges
; j
++ )
1440 gaspranges
[j
].maxPPEM
= GET_UShort();
1441 gaspranges
[j
].gaspFlag
= GET_UShort();
1443 FT_TRACE3(( " [max:%d flag:%d]",
1444 gaspranges
[j
].maxPPEM
,
1445 gaspranges
[j
].gaspFlag
));
1447 FT_TRACE3(( "\n" ));
1450 FT_TRACE2(( "GASP loaded\n" ));
1457 /*************************************************************************/
1463 /* Loads the first kerning table with format 0 in the font. Only */
1464 /* accepts the first horizontal kerning table. Developers should use */
1465 /* the `ftxkern' extension to access other kerning tables in the font */
1466 /* file, if they really want to. */
1469 /* face :: A handle to the target face object. */
1470 /* stream :: The input stream. */
1473 /* FreeType error code. 0 means success. */
1476 FT_Error
TT_Load_Kern( TT_Face face
,
1480 FT_Memory memory
= stream
->memory
;
1482 FT_UInt n
, num_tables
, version
;
1485 /* the kern table is optional; exit silently if it is missing */
1486 error
= face
->goto_table( face
, TTAG_kern
, stream
, 0 );
1490 if ( ACCESS_Frame( 4L ) )
1493 version
= GET_UShort();
1494 num_tables
= GET_UShort();
1498 for ( n
= 0; n
< num_tables
; n
++ )
1504 if ( ACCESS_Frame( 6L ) )
1507 version
= GET_UShort(); /* version */
1508 length
= GET_UShort() - 6; /* substract header length */
1509 coverage
= GET_UShort();
1513 if ( coverage
== 0x0001 )
1516 TT_Kern_0_Pair
* pair
;
1517 TT_Kern_0_Pair
* limit
;
1520 /* found a horizontal format 0 kerning table! */
1521 if ( ACCESS_Frame( 8L ) )
1524 num_pairs
= GET_UShort();
1530 /* allocate array of kerning pairs */
1531 if ( ALLOC_ARRAY( face
->kern_pairs
, num_pairs
, TT_Kern_0_Pair
) ||
1532 ACCESS_Frame( 6L * num_pairs
) )
1535 pair
= face
->kern_pairs
;
1536 limit
= pair
+ num_pairs
;
1537 for ( ; pair
< limit
; pair
++ )
1539 pair
->left
= GET_UShort();
1540 pair
->right
= GET_UShort();
1541 pair
->value
= GET_UShort();
1546 face
->num_kern_pairs
= num_pairs
;
1547 face
->kern_table_index
= n
;
1551 if ( FILE_Skip( length
) )
1555 /* no kern table found -- doesn't matter */
1556 face
->kern_table_index
= -1;
1557 face
->num_kern_pairs
= 0;
1558 face
->kern_pairs
= NULL
;
1565 /*************************************************************************/
1571 /* Loads the horizontal device metrics table. */
1574 /* face :: A handle to the target face object. */
1575 /* stream :: A handle to the input stream. */
1578 /* FreeType error code. 0 means success. */
1581 FT_Error
TT_Load_Hdmx( TT_Face face
,
1585 FT_Memory memory
= stream
->memory
;
1587 TT_Hdmx
* hdmx
= &face
->hdmx
;
1589 FT_Long record_size
;
1593 hdmx
->num_records
= 0;
1596 /* this table is optional */
1597 error
= face
->goto_table( face
, TTAG_hdmx
, stream
, 0 );
1601 if ( ACCESS_Frame( 8L ) )
1604 hdmx
->version
= GET_UShort();
1605 hdmx
->num_records
= GET_Short();
1606 record_size
= GET_Long();
1610 /* Only recognize format 0 */
1611 if ( hdmx
->version
!= 0 )
1614 if ( ALLOC_ARRAY( hdmx
->records
, hdmx
->num_records
, TT_HdmxRec
) )
1617 num_glyphs
= face
->root
.num_glyphs
;
1618 record_size
-= num_glyphs
+ 2;
1621 TT_HdmxRec
* cur
= hdmx
->records
;
1622 TT_HdmxRec
* limit
= cur
+ hdmx
->num_records
;
1625 for ( ; cur
< limit
; cur
++ )
1628 if ( READ_Byte( cur
->ppem
) ||
1629 READ_Byte( cur
->max_width
) )
1632 if ( ALLOC( cur
->widths
, num_glyphs
) ||
1633 FILE_Read( cur
->widths
, num_glyphs
) )
1636 /* skip padding bytes */
1637 if ( record_size
> 0 && FILE_Skip( record_size
) )
1647 /*************************************************************************/
1653 /* Frees the horizontal device metrics table. */
1656 /* face :: A handle to the target face object. */
1659 void TT_Free_Hdmx( TT_Face face
)
1664 FT_Memory memory
= face
->root
.driver
->root
.memory
;
1667 for ( n
= 0; n
< face
->hdmx
.num_records
; n
++ )
1668 FREE( face
->hdmx
.records
[n
].widths
);
1670 FREE( face
->hdmx
.records
);
1671 face
->hdmx
.num_records
= 0;