1 /***************************************************************************/
5 /* SFNT object management (base). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
16 /***************************************************************************/
24 #include FT_INTERNAL_SFNT_H
25 #include FT_INTERNAL_DEBUG_H
26 #include FT_TRUETYPE_IDS_H
27 #include FT_TRUETYPE_TAGS_H
28 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
31 #ifdef TT_CONFIG_OPTION_BDF
36 /*************************************************************************/
38 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
39 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
40 /* messages during execution. */
43 #define FT_COMPONENT trace_sfobjs
47 /* convert a UTF-16 name entry to ASCII */
49 tt_name_entry_ascii_from_utf16( TT_NameEntry entry
,
54 FT_Byte
* read
= (FT_Byte
*)entry
->string
;
58 len
= (FT_UInt
)entry
->stringLength
/ 2;
60 if ( FT_NEW_ARRAY( string
, len
+ 1 ) )
63 for ( n
= 0; n
< len
; n
++ )
65 code
= FT_NEXT_USHORT( read
);
66 if ( code
< 32 || code
> 127 )
69 string
[n
] = (char)code
;
78 /* convert an Apple Roman or symbol name entry to ASCII */
80 tt_name_entry_ascii_from_other( TT_NameEntry entry
,
85 FT_Byte
* read
= (FT_Byte
*)entry
->string
;
89 len
= (FT_UInt
)entry
->stringLength
;
91 if ( FT_NEW_ARRAY( string
, len
+ 1 ) )
94 for ( n
= 0; n
< len
; n
++ )
97 if ( code
< 32 || code
> 127 )
100 string
[n
] = (char)code
;
109 typedef FT_String
* (*TT_NameEntry_ConvertFunc
)( TT_NameEntry entry
,
113 /*************************************************************************/
116 /* tt_face_get_name */
119 /* Returns a given ENGLISH name record in ASCII. */
122 /* face :: A handle to the source face object. */
124 /* nameid :: The name id of the name record to return. */
127 /* name :: The address of a string pointer. NULL if no name is */
131 /* FreeType error code. 0 means success. */
134 tt_face_get_name( TT_Face face
,
138 FT_Memory memory
= face
->root
.memory
;
139 FT_Error error
= SFNT_Err_Ok
;
140 FT_String
* result
= NULL
;
142 TT_NameEntryRec
* rec
;
143 FT_Int found_apple
= -1;
144 FT_Int found_apple_roman
= -1;
145 FT_Int found_apple_english
= -1;
146 FT_Int found_win
= -1;
147 FT_Int found_unicode
= -1;
149 FT_Bool is_english
= 0;
151 TT_NameEntry_ConvertFunc convert
;
156 rec
= face
->name_table
.names
;
157 for ( n
= 0; n
< face
->num_names
; n
++, rec
++ )
159 /* According to the OpenType 1.3 specification, only Microsoft or */
160 /* Apple platform IDs might be used in the `name' table. The */
161 /* `Unicode' platform is reserved for the `cmap' table, and the */
162 /* `Iso' one is deprecated. */
164 /* However, the Apple TrueType specification doesn't say the same */
165 /* thing and goes to suggest that all Unicode `name' table entries */
166 /* should be coded in UTF-16 (in big-endian format I suppose). */
168 if ( rec
->nameID
== nameid
&& rec
->stringLength
> 0 )
170 switch ( rec
->platformID
)
172 case TT_PLATFORM_APPLE_UNICODE
:
173 case TT_PLATFORM_ISO
:
174 /* there is `languageID' to check there. We should use this */
175 /* field only as a last solution when nothing else is */
181 case TT_PLATFORM_MACINTOSH
:
182 /* This is a bit special because some fonts will use either */
183 /* an English language id, or a Roman encoding id, to indicate */
184 /* the English version of its font name. */
186 if ( rec
->languageID
== TT_MAC_LANGID_ENGLISH
)
187 found_apple_english
= n
;
188 else if ( rec
->encodingID
== TT_MAC_ID_ROMAN
)
189 found_apple_roman
= n
;
192 case TT_PLATFORM_MICROSOFT
:
193 /* we only take a non-English name when there is nothing */
194 /* else available in the font */
196 if ( found_win
== -1 || ( rec
->languageID
& 0x3FF ) == 0x009 )
198 switch ( rec
->encodingID
)
200 case TT_MS_ID_SYMBOL_CS
:
201 case TT_MS_ID_UNICODE_CS
:
203 is_english
= FT_BOOL( ( rec
->languageID
& 0x3FF ) == 0x009 );
219 found_apple
= found_apple_roman
;
220 if ( found_apple_english
>= 0 )
221 found_apple
= found_apple_english
;
223 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
224 /* we will thus favor names encoded in Windows formats if available */
225 /* (provided it is an English name) */
228 if ( found_win
>= 0 && !( found_apple
>= 0 && !is_english
) )
230 rec
= face
->name_table
.names
+ found_win
;
231 switch ( rec
->encodingID
)
233 /* all Unicode strings are encoded using UTF-16BE */
234 case TT_MS_ID_UNICODE_CS
:
235 case TT_MS_ID_SYMBOL_CS
:
236 convert
= tt_name_entry_ascii_from_utf16
;
240 /* Apparently, if this value is found in a name table entry, it is */
241 /* documented as `full Unicode repertoire'. Experience with the */
242 /* MsGothic font shipped with Windows Vista shows that this really */
243 /* means UTF-16 encoded names (UCS-4 values are only used within */
245 convert
= tt_name_entry_ascii_from_utf16
;
252 else if ( found_apple
>= 0 )
254 rec
= face
->name_table
.names
+ found_apple
;
255 convert
= tt_name_entry_ascii_from_other
;
257 else if ( found_unicode
>= 0 )
259 rec
= face
->name_table
.names
+ found_unicode
;
260 convert
= tt_name_entry_ascii_from_utf16
;
263 if ( rec
&& convert
)
265 if ( rec
->string
== NULL
)
267 FT_Stream stream
= face
->name_table
.stream
;
270 if ( FT_QNEW_ARRAY ( rec
->string
, rec
->stringLength
) ||
271 FT_STREAM_SEEK( rec
->stringOffset
) ||
272 FT_STREAM_READ( rec
->string
, rec
->stringLength
) )
274 FT_FREE( rec
->string
);
275 rec
->stringLength
= 0;
281 result
= convert( rec
, memory
);
291 sfnt_find_encoding( int platform_id
,
294 typedef struct TEncoding_
298 FT_Encoding encoding
;
303 const TEncoding tt_encodings
[] =
305 { TT_PLATFORM_ISO
, -1, FT_ENCODING_UNICODE
},
307 { TT_PLATFORM_APPLE_UNICODE
, -1, FT_ENCODING_UNICODE
},
309 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, FT_ENCODING_APPLE_ROMAN
},
311 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SYMBOL_CS
, FT_ENCODING_MS_SYMBOL
},
312 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, FT_ENCODING_UNICODE
},
313 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, FT_ENCODING_UNICODE
},
314 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, FT_ENCODING_SJIS
},
315 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, FT_ENCODING_GB2312
},
316 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, FT_ENCODING_BIG5
},
317 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, FT_ENCODING_WANSUNG
},
318 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, FT_ENCODING_JOHAB
}
321 const TEncoding
*cur
, *limit
;
325 limit
= cur
+ sizeof ( tt_encodings
) / sizeof ( tt_encodings
[0] );
327 for ( ; cur
< limit
; cur
++ )
329 if ( cur
->platform_id
== platform_id
)
331 if ( cur
->encoding_id
== encoding_id
||
332 cur
->encoding_id
== -1 )
333 return cur
->encoding
;
337 return FT_ENCODING_NONE
;
341 /* Fill in face->ttc_header. If the font is not a TTC, it is */
342 /* synthesized into a TTC with one offset table. */
344 sfnt_open_font( FT_Stream stream
,
347 FT_Memory memory
= stream
->memory
;
349 FT_ULong tag
, offset
;
351 static const FT_Frame_Field ttc_header_fields
[] =
354 #define FT_STRUCTURE TTC_HeaderRec
357 FT_FRAME_LONG( version
),
358 FT_FRAME_LONG( count
),
363 face
->ttc_header
.tag
= 0;
364 face
->ttc_header
.version
= 0;
365 face
->ttc_header
.count
= 0;
367 offset
= FT_STREAM_POS();
369 if ( FT_READ_ULONG( tag
) )
372 if ( tag
!= 0x00010000UL
&&
377 tag
!= 0x00020000UL
)
378 return SFNT_Err_Unknown_File_Format
;
380 face
->ttc_header
.tag
= TTAG_ttcf
;
382 if ( tag
== TTAG_ttcf
)
387 FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
389 if ( FT_STREAM_READ_FIELDS( ttc_header_fields
, &face
->ttc_header
) )
392 /* now read the offsets of each font in the file */
393 if ( FT_NEW_ARRAY( face
->ttc_header
.offsets
, face
->ttc_header
.count
) )
396 if ( FT_FRAME_ENTER( face
->ttc_header
.count
* 4L ) )
399 for ( n
= 0; n
< face
->ttc_header
.count
; n
++ )
400 face
->ttc_header
.offsets
[n
] = FT_GET_ULONG();
406 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
408 face
->ttc_header
.version
= 1 << 16;
409 face
->ttc_header
.count
= 1;
411 if ( FT_NEW( face
->ttc_header
.offsets
) )
414 face
->ttc_header
.offsets
[0] = offset
;
421 FT_LOCAL_DEF( FT_Error
)
422 sfnt_init_face( FT_Stream stream
,
426 FT_Parameter
* params
)
429 FT_Library library
= face
->root
.driver
->root
.library
;
433 /* for now, parameters are unused */
434 FT_UNUSED( num_params
);
438 sfnt
= (SFNT_Service
)face
->sfnt
;
441 sfnt
= (SFNT_Service
)FT_Get_Module_Interface( library
, "sfnt" );
443 return SFNT_Err_Invalid_File_Format
;
446 face
->goto_table
= sfnt
->goto_table
;
449 FT_FACE_FIND_GLOBAL_SERVICE( face
, face
->psnames
, POSTSCRIPT_CMAPS
);
451 error
= sfnt_open_font( stream
, face
);
455 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face
, face_index
));
457 if ( face_index
< 0 )
460 if ( face_index
>= face
->ttc_header
.count
)
461 return SFNT_Err_Invalid_Argument
;
463 if ( FT_STREAM_SEEK( face
->ttc_header
.offsets
[face_index
] ) )
466 /* check that we have a valid TrueType file */
467 error
= sfnt
->load_font_dir( face
, stream
);
471 face
->root
.num_faces
= face
->ttc_header
.count
;
472 face
->root
.face_index
= face_index
;
480 FT_TRACE2(( "`" #x "' " )); \
481 FT_TRACE3(( "-->\n" )); \
483 error = sfnt->load_##x( face, stream ); \
485 FT_TRACE2(( "%s\n", ( !error ) \
487 : ( error == SFNT_Err_Table_Missing ) \
489 : "failed to load" )); \
490 FT_TRACE3(( "\n" )); \
493 #define LOADM_( x, vertical ) \
495 FT_TRACE2(( "`%s" #x "' ", \
496 vertical ? "vertical " : "" )); \
497 FT_TRACE3(( "-->\n" )); \
499 error = sfnt->load_##x( face, stream, vertical ); \
501 FT_TRACE2(( "%s\n", ( !error ) \
503 : ( error == SFNT_Err_Table_Missing ) \
505 : "failed to load" )); \
506 FT_TRACE3(( "\n" )); \
509 #define GET_NAME( id, field ) \
511 error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
517 FT_LOCAL_DEF( FT_Error
)
518 sfnt_load_face( FT_Stream stream
,
522 FT_Parameter
* params
)
525 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
526 FT_Error psnames_error
;
529 FT_Bool is_apple_sbit
;
531 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
533 FT_UNUSED( face_index
);
534 FT_UNUSED( num_params
);
540 /* We now support two SFNT-based bitmapped font formats. They */
541 /* are recognized easily as they do not include a `glyf' */
544 /* The first format comes from Apple, and uses a table named */
545 /* `bhed' instead of `head' to store the font header (using */
546 /* the same format). It also doesn't include horizontal and */
547 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
550 /* The other format comes from Microsoft, and is used with */
551 /* WinCE/PocketPC. It looks like a standard TTF, except that */
552 /* it doesn't contain outlines. */
555 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face
));
557 /* do we have outlines in there? */
558 #ifdef FT_CONFIG_OPTION_INCREMENTAL
559 has_outline
= FT_BOOL( face
->root
.internal
->incremental_interface
!= 0 ||
560 tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
561 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
563 has_outline
= FT_BOOL( tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
564 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
569 /* if this font doesn't contain outlines, we try to load */
571 if ( !has_outline
&& sfnt
->load_bhed
)
574 is_apple_sbit
= FT_BOOL( !error
);
577 /* load the font header (`head' table) if this isn't an Apple */
579 if ( !is_apple_sbit
)
586 if ( face
->header
.Units_Per_EM
== 0 )
588 error
= SFNT_Err_Invalid_Table
;
593 /* the following tables are often not present in embedded TrueType */
594 /* fonts within PDF documents, so don't check for them. */
598 /* the following tables are optional in PCL fonts -- */
599 /* don't check for errors */
603 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
604 psnames_error
= error
;
607 /* do not load the metrics headers and tables if this is an Apple */
609 if ( !is_apple_sbit
)
611 /* load the `hhea' and `hmtx' tables */
616 if ( error
== SFNT_Err_Table_Missing
)
618 error
= SFNT_Err_Hmtx_Table_Missing
;
620 #ifdef FT_CONFIG_OPTION_INCREMENTAL
621 /* If this is an incrementally loaded font and there are */
622 /* overriding metrics, tolerate a missing `hmtx' table. */
623 if ( face
->root
.internal
->incremental_interface
&&
624 face
->root
.internal
->incremental_interface
->funcs
->
627 face
->horizontal
.number_Of_HMetrics
= 0;
633 else if ( error
== SFNT_Err_Table_Missing
)
635 /* No `hhea' table necessary for SFNT Mac fonts. */
636 if ( face
->format_tag
== TTAG_true
)
638 FT_TRACE2(( "This is an SFNT Mac font.\n" ));
644 error
= SFNT_Err_Horiz_Header_Missing
;
646 #ifdef FT_CONFIG_OPTION_INCREMENTAL
647 /* If this is an incrementally loaded font and there are */
648 /* overriding metrics, tolerate a missing `hhea' table. */
649 if ( face
->root
.internal
->incremental_interface
&&
650 face
->root
.internal
->incremental_interface
->funcs
->
653 face
->horizontal
.number_Of_HMetrics
= 0;
664 /* try to load the `vhea' and `vmtx' tables */
670 face
->vertical_info
= 1;
673 if ( error
&& error
!= SFNT_Err_Table_Missing
)
679 if ( error
!= SFNT_Err_Table_Missing
)
682 face
->os2
.version
= 0xFFFFU
;
686 /* the optional tables */
688 /* embedded bitmap support */
689 if ( sfnt
->load_eblc
)
694 /* a font which contains neither bitmaps nor outlines is */
695 /* still valid (although rather useless in most cases); */
696 /* however, you can find such stripped fonts in PDFs */
697 if ( error
== SFNT_Err_Table_Missing
)
707 if ( error
!= SFNT_Err_Table_Missing
)
710 face
->pclt
.Version
= 0;
713 /* consider the kerning and gasp tables as optional */
717 face
->root
.num_glyphs
= face
->max_profile
.numGlyphs
;
719 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */
720 /* a WWS-only font face. `WWS' stands for `weight', width', and */
721 /* `slope', a term used by Microsoft's Windows Presentation */
722 /* Foundation (WPF). This flag has been introduced in version */
723 /* 1.5 of the OpenType specification (May 2008). */
725 if ( face
->os2
.version
!= 0xFFFFU
&& face
->os2
.fsSelection
& 256 )
727 GET_NAME( PREFERRED_FAMILY
, &face
->root
.family_name
);
728 if ( !face
->root
.family_name
)
729 GET_NAME( FONT_FAMILY
, &face
->root
.family_name
);
731 GET_NAME( PREFERRED_SUBFAMILY
, &face
->root
.style_name
);
732 if ( !face
->root
.style_name
)
733 GET_NAME( FONT_SUBFAMILY
, &face
->root
.style_name
);
737 GET_NAME( WWS_FAMILY
, &face
->root
.family_name
);
738 if ( !face
->root
.family_name
)
739 GET_NAME( PREFERRED_FAMILY
, &face
->root
.family_name
);
740 if ( !face
->root
.family_name
)
741 GET_NAME( FONT_FAMILY
, &face
->root
.family_name
);
743 GET_NAME( WWS_SUBFAMILY
, &face
->root
.style_name
);
744 if ( !face
->root
.style_name
)
745 GET_NAME( PREFERRED_SUBFAMILY
, &face
->root
.style_name
);
746 if ( !face
->root
.style_name
)
747 GET_NAME( FONT_SUBFAMILY
, &face
->root
.style_name
);
750 /* now set up root fields */
752 FT_Face root
= &face
->root
;
753 FT_Long flags
= root
->face_flags
;
756 /*********************************************************************/
758 /* Compute face flags. */
760 if ( has_outline
== TRUE
)
761 flags
|= FT_FACE_FLAG_SCALABLE
; /* scalable outlines */
763 /* The sfnt driver only supports bitmap fonts natively, thus we */
764 /* don't set FT_FACE_FLAG_HINTER. */
765 flags
|= FT_FACE_FLAG_SFNT
| /* SFNT file format */
766 FT_FACE_FLAG_HORIZONTAL
; /* horizontal data */
768 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
769 if ( psnames_error
== SFNT_Err_Ok
&&
770 face
->postscript
.FormatType
!= 0x00030000L
)
771 flags
|= FT_FACE_FLAG_GLYPH_NAMES
;
774 /* fixed width font? */
775 if ( face
->postscript
.isFixedPitch
)
776 flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
778 /* vertical information? */
779 if ( face
->vertical_info
)
780 flags
|= FT_FACE_FLAG_VERTICAL
;
782 /* kerning available ? */
783 if ( TT_FACE_HAS_KERNING( face
) )
784 flags
|= FT_FACE_FLAG_KERNING
;
786 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
787 /* Don't bother to load the tables unless somebody asks for them. */
788 /* No need to do work which will (probably) not be used. */
789 if ( tt_face_lookup_table( face
, TTAG_glyf
) != 0 &&
790 tt_face_lookup_table( face
, TTAG_fvar
) != 0 &&
791 tt_face_lookup_table( face
, TTAG_gvar
) != 0 )
792 flags
|= FT_FACE_FLAG_MULTIPLE_MASTERS
;
795 root
->face_flags
= flags
;
797 /*********************************************************************/
799 /* Compute style flags. */
803 if ( has_outline
== TRUE
&& face
->os2
.version
!= 0xFFFFU
)
805 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */
806 /* indicates an oblique font face. This flag has been */
807 /* introduced in version 1.5 of the OpenType specification. */
809 if ( face
->os2
.fsSelection
& 512 ) /* bit 9 */
810 flags
|= FT_STYLE_FLAG_ITALIC
;
811 else if ( face
->os2
.fsSelection
& 1 ) /* bit 0 */
812 flags
|= FT_STYLE_FLAG_ITALIC
;
814 if ( face
->os2
.fsSelection
& 32 ) /* bit 5 */
815 flags
|= FT_STYLE_FLAG_BOLD
;
819 /* this is an old Mac font, use the header field */
821 if ( face
->header
.Mac_Style
& 1 )
822 flags
|= FT_STYLE_FLAG_BOLD
;
824 if ( face
->header
.Mac_Style
& 2 )
825 flags
|= FT_STYLE_FLAG_ITALIC
;
828 root
->style_flags
= flags
;
830 /*********************************************************************/
832 /* Polish the charmaps. */
834 /* Try to set the charmap encoding according to the platform & */
835 /* encoding ID of each charmap. */
838 tt_face_build_cmaps( face
); /* ignore errors */
841 /* set the encoding fields */
846 for ( m
= 0; m
< root
->num_charmaps
; m
++ )
848 FT_CharMap charmap
= root
->charmaps
[m
];
851 charmap
->encoding
= sfnt_find_encoding( charmap
->platform_id
,
852 charmap
->encoding_id
);
855 if ( root
->charmap
== NULL
&&
856 charmap
->encoding
== FT_ENCODING_UNICODE
)
858 /* set 'root->charmap' to the first Unicode encoding we find */
859 root
->charmap
= charmap
;
865 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
868 * Now allocate the root array of FT_Bitmap_Size records and
869 * populate them. Unfortunately, it isn't possible to indicate bit
870 * depths in the FT_Bitmap_Size record. This is a design error.
876 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
877 count
= face
->sbit_num_strikes
;
879 count
= (FT_UInt
)face
->num_sbit_strikes
;
884 FT_Memory memory
= face
->root
.stream
->memory
;
885 FT_UShort em_size
= face
->header
.Units_Per_EM
;
886 FT_Short avgwidth
= face
->os2
.xAvgCharWidth
;
887 FT_Size_Metrics metrics
;
890 if ( em_size
== 0 || face
->os2
.version
== 0xFFFFU
)
896 if ( FT_NEW_ARRAY( root
->available_sizes
, count
) )
899 for ( i
= 0; i
< count
; i
++ )
901 FT_Bitmap_Size
* bsize
= root
->available_sizes
+ i
;
904 error
= sfnt
->load_strike_metrics( face
, i
, &metrics
);
908 bsize
->height
= (FT_Short
)( metrics
.height
>> 6 );
909 bsize
->width
= (FT_Short
)(
910 ( avgwidth
* metrics
.x_ppem
+ em_size
/ 2 ) / em_size
);
912 bsize
->x_ppem
= metrics
.x_ppem
<< 6;
913 bsize
->y_ppem
= metrics
.y_ppem
<< 6;
916 bsize
->size
= metrics
.y_ppem
<< 6;
919 root
->face_flags
|= FT_FACE_FLAG_FIXED_SIZES
;
920 root
->num_fixed_sizes
= (FT_Int
)count
;
924 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
926 /* a font with no bitmaps and no outlines is scalable; */
927 /* it has only empty glyphs then */
928 if ( !FT_HAS_FIXED_SIZES( root
) && !FT_IS_SCALABLE( root
) )
929 root
->face_flags
|= FT_FACE_FLAG_SCALABLE
;
932 /*********************************************************************/
934 /* Set up metrics. */
936 if ( FT_IS_SCALABLE( root
) )
938 /* XXX What about if outline header is missing */
939 /* (e.g. sfnt wrapped bitmap)? */
940 root
->bbox
.xMin
= face
->header
.xMin
;
941 root
->bbox
.yMin
= face
->header
.yMin
;
942 root
->bbox
.xMax
= face
->header
.xMax
;
943 root
->bbox
.yMax
= face
->header
.yMax
;
944 root
->units_per_EM
= face
->header
.Units_Per_EM
;
947 /* XXX: Computing the ascender/descender/height is very different */
948 /* from what the specification tells you. Apparently, we */
949 /* must be careful because */
951 /* - not all fonts have an OS/2 table; in this case, we take */
952 /* the values in the horizontal header. However, these */
953 /* values very often are not reliable. */
955 /* - otherwise, the correct typographic values are in the */
956 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
958 /* However, certain fonts have these fields set to 0. */
959 /* Rather, they have usWinAscent & usWinDescent correctly */
960 /* set (but with different values). */
962 /* As an example, Arial Narrow is implemented through four */
963 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
965 /* Strangely, all fonts have the same values in their */
966 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
968 /* On the other hand, they all have different */
969 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
970 /* table cannot be used to compute the text height reliably! */
973 /* The ascender/descender/height are computed from the OS/2 table */
974 /* when found. Otherwise, they're taken from the horizontal */
978 root
->ascender
= face
->horizontal
.Ascender
;
979 root
->descender
= face
->horizontal
.Descender
;
981 root
->height
= (FT_Short
)( root
->ascender
- root
->descender
+
982 face
->horizontal
.Line_Gap
);
985 /* if the line_gap is 0, we add an extra 15% to the text height -- */
986 /* this computation is based on various versions of Times New Roman */
987 if ( face
->horizontal
.Line_Gap
== 0 )
988 root
->height
= (FT_Short
)( ( root
->height
* 115 + 50 ) / 100 );
992 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
993 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
994 if ( face
->os2
.version
!= 0xFFFFU
&& root
->ascender
)
999 root
->ascender
= face
->os2
.sTypoAscender
;
1000 root
->descender
= -face
->os2
.sTypoDescender
;
1002 height
= root
->ascender
+ root
->descender
+ face
->os2
.sTypoLineGap
;
1003 if ( height
> root
->height
)
1004 root
->height
= height
;
1008 root
->max_advance_width
= face
->horizontal
.advance_Width_Max
;
1009 root
->max_advance_height
= (FT_Short
)( face
->vertical_info
1010 ? face
->vertical
.advance_Height_Max
1013 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
1014 /* Adjust underline position from top edge to centre of */
1015 /* stroke to convert TrueType meaning to FreeType meaning. */
1016 root
->underline_position
= face
->postscript
.underlinePosition
-
1017 face
->postscript
.underlineThickness
/ 2;
1018 root
->underline_thickness
= face
->postscript
.underlineThickness
;
1024 FT_TRACE2(( "sfnt_load_face: done\n" ));
1035 FT_LOCAL_DEF( void )
1036 sfnt_done_face( TT_Face face
)
1045 memory
= face
->root
.memory
;
1046 sfnt
= (SFNT_Service
)face
->sfnt
;
1050 /* destroy the postscript names table if it is loaded */
1051 if ( sfnt
->free_psnames
)
1052 sfnt
->free_psnames( face
);
1054 /* destroy the embedded bitmaps table if it is loaded */
1055 if ( sfnt
->free_eblc
)
1056 sfnt
->free_eblc( face
);
1059 #ifdef TT_CONFIG_OPTION_BDF
1060 /* freeing the embedded BDF properties */
1061 tt_face_free_bdf_props( face
);
1064 /* freeing the kerning table */
1065 tt_face_done_kern( face
);
1067 /* freeing the collection table */
1068 FT_FREE( face
->ttc_header
.offsets
);
1069 face
->ttc_header
.count
= 0;
1071 /* freeing table directory */
1072 FT_FREE( face
->dir_tables
);
1073 face
->num_tables
= 0;
1076 FT_Stream stream
= FT_FACE_STREAM( face
);
1079 /* simply release the 'cmap' table frame */
1080 FT_FRAME_RELEASE( face
->cmap_table
);
1081 face
->cmap_size
= 0;
1084 /* freeing the horizontal metrics */
1085 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
1087 FT_Stream stream
= FT_FACE_STREAM( face
);
1090 FT_FRAME_RELEASE( face
->horz_metrics
);
1091 FT_FRAME_RELEASE( face
->vert_metrics
);
1092 face
->horz_metrics_size
= 0;
1093 face
->vert_metrics_size
= 0;
1096 FT_FREE( face
->horizontal
.long_metrics
);
1097 FT_FREE( face
->horizontal
.short_metrics
);
1100 /* freeing the vertical ones, if any */
1101 if ( face
->vertical_info
)
1103 FT_FREE( face
->vertical
.long_metrics
);
1104 FT_FREE( face
->vertical
.short_metrics
);
1105 face
->vertical_info
= 0;
1108 /* freeing the gasp table */
1109 FT_FREE( face
->gasp
.gaspRanges
);
1110 face
->gasp
.numRanges
= 0;
1112 /* freeing the name table */
1114 sfnt
->free_name( face
);
1116 /* freeing family and style name */
1117 FT_FREE( face
->root
.family_name
);
1118 FT_FREE( face
->root
.style_name
);
1120 /* freeing sbit size table */
1121 FT_FREE( face
->root
.available_sizes
);
1122 face
->root
.num_fixed_sizes
= 0;
1124 FT_FREE( face
->postscript_name
);