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
29 #include FT_SFNT_NAMES_H
32 #ifdef TT_CONFIG_OPTION_BDF
37 /*************************************************************************/
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
44 #define FT_COMPONENT trace_sfobjs
48 /* convert a UTF-16 name entry to ASCII */
50 tt_name_entry_ascii_from_utf16( TT_NameEntry entry
,
55 FT_Byte
* read
= (FT_Byte
*)entry
->string
;
59 len
= (FT_UInt
)entry
->stringLength
/ 2;
61 if ( FT_NEW_ARRAY( string
, len
+ 1 ) )
64 for ( n
= 0; n
< len
; n
++ )
66 code
= FT_NEXT_USHORT( read
);
67 if ( code
< 32 || code
> 127 )
70 string
[n
] = (char)code
;
79 /* convert an Apple Roman or symbol name entry to ASCII */
81 tt_name_entry_ascii_from_other( TT_NameEntry entry
,
86 FT_Byte
* read
= (FT_Byte
*)entry
->string
;
90 len
= (FT_UInt
)entry
->stringLength
;
92 if ( FT_NEW_ARRAY( string
, len
+ 1 ) )
95 for ( n
= 0; n
< len
; n
++ )
98 if ( code
< 32 || code
> 127 )
101 string
[n
] = (char)code
;
110 typedef FT_String
* (*TT_NameEntry_ConvertFunc
)( TT_NameEntry entry
,
114 /*************************************************************************/
117 /* tt_face_get_name */
120 /* Returns a given ENGLISH name record in ASCII. */
123 /* face :: A handle to the source face object. */
125 /* nameid :: The name id of the name record to return. */
128 /* name :: The address of a string pointer. NULL if no name is */
132 /* FreeType error code. 0 means success. */
135 tt_face_get_name( TT_Face face
,
139 FT_Memory memory
= face
->root
.memory
;
140 FT_Error error
= SFNT_Err_Ok
;
141 FT_String
* result
= NULL
;
143 TT_NameEntryRec
* rec
;
144 FT_Int found_apple
= -1;
145 FT_Int found_apple_roman
= -1;
146 FT_Int found_apple_english
= -1;
147 FT_Int found_win
= -1;
148 FT_Int found_unicode
= -1;
150 FT_Bool is_english
= 0;
152 TT_NameEntry_ConvertFunc convert
;
157 rec
= face
->name_table
.names
;
158 for ( n
= 0; n
< face
->num_names
; n
++, rec
++ )
160 /* According to the OpenType 1.3 specification, only Microsoft or */
161 /* Apple platform IDs might be used in the `name' table. The */
162 /* `Unicode' platform is reserved for the `cmap' table, and the */
163 /* `Iso' one is deprecated. */
165 /* However, the Apple TrueType specification doesn't say the same */
166 /* thing and goes to suggest that all Unicode `name' table entries */
167 /* should be coded in UTF-16 (in big-endian format I suppose). */
169 if ( rec
->nameID
== nameid
&& rec
->stringLength
> 0 )
171 switch ( rec
->platformID
)
173 case TT_PLATFORM_APPLE_UNICODE
:
174 case TT_PLATFORM_ISO
:
175 /* there is `languageID' to check there. We should use this */
176 /* field only as a last solution when nothing else is */
182 case TT_PLATFORM_MACINTOSH
:
183 /* This is a bit special because some fonts will use either */
184 /* an English language id, or a Roman encoding id, to indicate */
185 /* the English version of its font name. */
187 if ( rec
->languageID
== TT_MAC_LANGID_ENGLISH
)
188 found_apple_english
= n
;
189 else if ( rec
->encodingID
== TT_MAC_ID_ROMAN
)
190 found_apple_roman
= n
;
193 case TT_PLATFORM_MICROSOFT
:
194 /* we only take a non-English name when there is nothing */
195 /* else available in the font */
197 if ( found_win
== -1 || ( rec
->languageID
& 0x3FF ) == 0x009 )
199 switch ( rec
->encodingID
)
201 case TT_MS_ID_SYMBOL_CS
:
202 case TT_MS_ID_UNICODE_CS
:
204 is_english
= FT_BOOL( ( rec
->languageID
& 0x3FF ) == 0x009 );
220 found_apple
= found_apple_roman
;
221 if ( found_apple_english
>= 0 )
222 found_apple
= found_apple_english
;
224 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
225 /* we will thus favor names encoded in Windows formats if available */
226 /* (provided it is an English name) */
229 if ( found_win
>= 0 && !( found_apple
>= 0 && !is_english
) )
231 rec
= face
->name_table
.names
+ found_win
;
232 switch ( rec
->encodingID
)
234 /* all Unicode strings are encoded using UTF-16BE */
235 case TT_MS_ID_UNICODE_CS
:
236 case TT_MS_ID_SYMBOL_CS
:
237 convert
= tt_name_entry_ascii_from_utf16
;
241 /* Apparently, if this value is found in a name table entry, it is */
242 /* documented as `full Unicode repertoire'. Experience with the */
243 /* MsGothic font shipped with Windows Vista shows that this really */
244 /* means UTF-16 encoded names (UCS-4 values are only used within */
246 convert
= tt_name_entry_ascii_from_utf16
;
253 else if ( found_apple
>= 0 )
255 rec
= face
->name_table
.names
+ found_apple
;
256 convert
= tt_name_entry_ascii_from_other
;
258 else if ( found_unicode
>= 0 )
260 rec
= face
->name_table
.names
+ found_unicode
;
261 convert
= tt_name_entry_ascii_from_utf16
;
264 if ( rec
&& convert
)
266 if ( rec
->string
== NULL
)
268 FT_Stream stream
= face
->name_table
.stream
;
271 if ( FT_QNEW_ARRAY ( rec
->string
, rec
->stringLength
) ||
272 FT_STREAM_SEEK( rec
->stringOffset
) ||
273 FT_STREAM_READ( rec
->string
, rec
->stringLength
) )
275 FT_FREE( rec
->string
);
276 rec
->stringLength
= 0;
282 result
= convert( rec
, memory
);
292 sfnt_find_encoding( int platform_id
,
295 typedef struct TEncoding_
299 FT_Encoding encoding
;
304 const TEncoding tt_encodings
[] =
306 { TT_PLATFORM_ISO
, -1, FT_ENCODING_UNICODE
},
308 { TT_PLATFORM_APPLE_UNICODE
, -1, FT_ENCODING_UNICODE
},
310 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, FT_ENCODING_APPLE_ROMAN
},
312 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SYMBOL_CS
, FT_ENCODING_MS_SYMBOL
},
313 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, FT_ENCODING_UNICODE
},
314 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, FT_ENCODING_UNICODE
},
315 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, FT_ENCODING_SJIS
},
316 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, FT_ENCODING_GB2312
},
317 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, FT_ENCODING_BIG5
},
318 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, FT_ENCODING_WANSUNG
},
319 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, FT_ENCODING_JOHAB
}
322 const TEncoding
*cur
, *limit
;
326 limit
= cur
+ sizeof ( tt_encodings
) / sizeof ( tt_encodings
[0] );
328 for ( ; cur
< limit
; cur
++ )
330 if ( cur
->platform_id
== platform_id
)
332 if ( cur
->encoding_id
== encoding_id
||
333 cur
->encoding_id
== -1 )
334 return cur
->encoding
;
338 return FT_ENCODING_NONE
;
342 /* Fill in face->ttc_header. If the font is not a TTC, it is */
343 /* synthesized into a TTC with one offset table. */
345 sfnt_open_font( FT_Stream stream
,
348 FT_Memory memory
= stream
->memory
;
350 FT_ULong tag
, offset
;
352 static const FT_Frame_Field ttc_header_fields
[] =
355 #define FT_STRUCTURE TTC_HeaderRec
358 FT_FRAME_LONG( version
),
359 FT_FRAME_LONG( count
),
364 face
->ttc_header
.tag
= 0;
365 face
->ttc_header
.version
= 0;
366 face
->ttc_header
.count
= 0;
368 offset
= FT_STREAM_POS();
370 if ( FT_READ_ULONG( tag
) )
373 if ( tag
!= 0x00010000UL
&&
378 tag
!= 0x00020000UL
)
379 return SFNT_Err_Unknown_File_Format
;
381 face
->ttc_header
.tag
= TTAG_ttcf
;
383 if ( tag
== TTAG_ttcf
)
388 FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
390 if ( FT_STREAM_READ_FIELDS( ttc_header_fields
, &face
->ttc_header
) )
393 /* now read the offsets of each font in the file */
394 if ( FT_NEW_ARRAY( face
->ttc_header
.offsets
, face
->ttc_header
.count
) )
397 if ( FT_FRAME_ENTER( face
->ttc_header
.count
* 4L ) )
400 for ( n
= 0; n
< face
->ttc_header
.count
; n
++ )
401 face
->ttc_header
.offsets
[n
] = FT_GET_ULONG();
407 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
409 face
->ttc_header
.version
= 1 << 16;
410 face
->ttc_header
.count
= 1;
412 if ( FT_NEW( face
->ttc_header
.offsets
) )
415 face
->ttc_header
.offsets
[0] = offset
;
422 FT_LOCAL_DEF( FT_Error
)
423 sfnt_init_face( FT_Stream stream
,
427 FT_Parameter
* params
)
430 FT_Library library
= face
->root
.driver
->root
.library
;
434 /* for now, parameters are unused */
435 FT_UNUSED( num_params
);
439 sfnt
= (SFNT_Service
)face
->sfnt
;
442 sfnt
= (SFNT_Service
)FT_Get_Module_Interface( library
, "sfnt" );
444 return SFNT_Err_Invalid_File_Format
;
447 face
->goto_table
= sfnt
->goto_table
;
450 FT_FACE_FIND_GLOBAL_SERVICE( face
, face
->psnames
, POSTSCRIPT_CMAPS
);
452 error
= sfnt_open_font( stream
, face
);
456 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face
, face_index
));
458 if ( face_index
< 0 )
461 if ( face_index
>= face
->ttc_header
.count
)
462 return SFNT_Err_Invalid_Argument
;
464 if ( FT_STREAM_SEEK( face
->ttc_header
.offsets
[face_index
] ) )
467 /* check that we have a valid TrueType file */
468 error
= sfnt
->load_font_dir( face
, stream
);
472 face
->root
.num_faces
= face
->ttc_header
.count
;
473 face
->root
.face_index
= face_index
;
481 FT_TRACE2(( "`" #x "' " )); \
482 FT_TRACE3(( "-->\n" )); \
484 error = sfnt->load_##x( face, stream ); \
486 FT_TRACE2(( "%s\n", ( !error ) \
488 : ( error == SFNT_Err_Table_Missing ) \
490 : "failed to load" )); \
491 FT_TRACE3(( "\n" )); \
494 #define LOADM_( x, vertical ) \
496 FT_TRACE2(( "`%s" #x "' ", \
497 vertical ? "vertical " : "" )); \
498 FT_TRACE3(( "-->\n" )); \
500 error = sfnt->load_##x( face, stream, vertical ); \
502 FT_TRACE2(( "%s\n", ( !error ) \
504 : ( error == SFNT_Err_Table_Missing ) \
506 : "failed to load" )); \
507 FT_TRACE3(( "\n" )); \
510 #define GET_NAME( id, field ) \
512 error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
518 FT_LOCAL_DEF( FT_Error
)
519 sfnt_load_face( FT_Stream stream
,
523 FT_Parameter
* params
)
526 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
527 FT_Error psnames_error
;
530 FT_Bool is_apple_sbit
;
531 FT_Bool ignore_preferred_family
= FALSE
;
532 FT_Bool ignore_preferred_subfamily
= FALSE
;
534 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
536 FT_UNUSED( face_index
);
538 /* Check parameters */
544 for ( i
= 0; i
< num_params
; i
++ )
546 if ( params
[i
].tag
== FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY
)
547 ignore_preferred_family
= TRUE
;
548 else if ( params
[i
].tag
== FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY
)
549 ignore_preferred_subfamily
= TRUE
;
555 /* We now support two SFNT-based bitmapped font formats. They */
556 /* are recognized easily as they do not include a `glyf' */
559 /* The first format comes from Apple, and uses a table named */
560 /* `bhed' instead of `head' to store the font header (using */
561 /* the same format). It also doesn't include horizontal and */
562 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
565 /* The other format comes from Microsoft, and is used with */
566 /* WinCE/PocketPC. It looks like a standard TTF, except that */
567 /* it doesn't contain outlines. */
570 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face
));
572 /* do we have outlines in there? */
573 #ifdef FT_CONFIG_OPTION_INCREMENTAL
574 has_outline
= FT_BOOL( face
->root
.internal
->incremental_interface
!= 0 ||
575 tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
576 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
578 has_outline
= FT_BOOL( tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
579 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
584 /* if this font doesn't contain outlines, we try to load */
586 if ( !has_outline
&& sfnt
->load_bhed
)
589 is_apple_sbit
= FT_BOOL( !error
);
592 /* load the font header (`head' table) if this isn't an Apple */
594 if ( !is_apple_sbit
)
601 if ( face
->header
.Units_Per_EM
== 0 )
603 error
= SFNT_Err_Invalid_Table
;
608 /* the following tables are often not present in embedded TrueType */
609 /* fonts within PDF documents, so don't check for them. */
613 /* the following tables are optional in PCL fonts -- */
614 /* don't check for errors */
618 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
619 psnames_error
= error
;
622 /* do not load the metrics headers and tables if this is an Apple */
624 if ( !is_apple_sbit
)
626 /* load the `hhea' and `hmtx' tables */
631 if ( error
== SFNT_Err_Table_Missing
)
633 error
= SFNT_Err_Hmtx_Table_Missing
;
635 #ifdef FT_CONFIG_OPTION_INCREMENTAL
636 /* If this is an incrementally loaded font and there are */
637 /* overriding metrics, tolerate a missing `hmtx' table. */
638 if ( face
->root
.internal
->incremental_interface
&&
639 face
->root
.internal
->incremental_interface
->funcs
->
642 face
->horizontal
.number_Of_HMetrics
= 0;
648 else if ( error
== SFNT_Err_Table_Missing
)
650 /* No `hhea' table necessary for SFNT Mac fonts. */
651 if ( face
->format_tag
== TTAG_true
)
653 FT_TRACE2(( "This is an SFNT Mac font.\n" ));
659 error
= SFNT_Err_Horiz_Header_Missing
;
661 #ifdef FT_CONFIG_OPTION_INCREMENTAL
662 /* If this is an incrementally loaded font and there are */
663 /* overriding metrics, tolerate a missing `hhea' table. */
664 if ( face
->root
.internal
->incremental_interface
&&
665 face
->root
.internal
->incremental_interface
->funcs
->
668 face
->horizontal
.number_Of_HMetrics
= 0;
679 /* try to load the `vhea' and `vmtx' tables */
685 face
->vertical_info
= 1;
688 if ( error
&& error
!= SFNT_Err_Table_Missing
)
694 if ( error
!= SFNT_Err_Table_Missing
)
697 face
->os2
.version
= 0xFFFFU
;
701 /* the optional tables */
703 /* embedded bitmap support */
704 if ( sfnt
->load_eblc
)
709 /* a font which contains neither bitmaps nor outlines is */
710 /* still valid (although rather useless in most cases); */
711 /* however, you can find such stripped fonts in PDFs */
712 if ( error
== SFNT_Err_Table_Missing
)
722 if ( error
!= SFNT_Err_Table_Missing
)
725 face
->pclt
.Version
= 0;
728 /* consider the kerning and gasp tables as optional */
732 face
->root
.num_glyphs
= face
->max_profile
.numGlyphs
;
734 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */
735 /* a WWS-only font face. `WWS' stands for `weight', width', and */
736 /* `slope', a term used by Microsoft's Windows Presentation */
737 /* Foundation (WPF). This flag has been introduced in version */
738 /* 1.5 of the OpenType specification (May 2008). */
740 face
->root
.family_name
= NULL
;
741 face
->root
.style_name
= NULL
;
742 if ( face
->os2
.version
!= 0xFFFFU
&& face
->os2
.fsSelection
& 256 )
744 if ( !ignore_preferred_family
)
745 GET_NAME( PREFERRED_FAMILY
, &face
->root
.family_name
);
746 if ( !face
->root
.family_name
)
747 GET_NAME( FONT_FAMILY
, &face
->root
.family_name
);
749 if ( !ignore_preferred_subfamily
)
750 GET_NAME( PREFERRED_SUBFAMILY
, &face
->root
.style_name
);
751 if ( !face
->root
.style_name
)
752 GET_NAME( FONT_SUBFAMILY
, &face
->root
.style_name
);
756 GET_NAME( WWS_FAMILY
, &face
->root
.family_name
);
757 if ( !face
->root
.family_name
&& !ignore_preferred_family
)
758 GET_NAME( PREFERRED_FAMILY
, &face
->root
.family_name
);
759 if ( !face
->root
.family_name
)
760 GET_NAME( FONT_FAMILY
, &face
->root
.family_name
);
762 GET_NAME( WWS_SUBFAMILY
, &face
->root
.style_name
);
763 if ( !face
->root
.style_name
&& !ignore_preferred_subfamily
)
764 GET_NAME( PREFERRED_SUBFAMILY
, &face
->root
.style_name
);
765 if ( !face
->root
.style_name
)
766 GET_NAME( FONT_SUBFAMILY
, &face
->root
.style_name
);
769 /* now set up root fields */
771 FT_Face root
= &face
->root
;
772 FT_Long flags
= root
->face_flags
;
775 /*********************************************************************/
777 /* Compute face flags. */
779 if ( has_outline
== TRUE
)
780 flags
|= FT_FACE_FLAG_SCALABLE
; /* scalable outlines */
782 /* The sfnt driver only supports bitmap fonts natively, thus we */
783 /* don't set FT_FACE_FLAG_HINTER. */
784 flags
|= FT_FACE_FLAG_SFNT
| /* SFNT file format */
785 FT_FACE_FLAG_HORIZONTAL
; /* horizontal data */
787 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
788 if ( psnames_error
== SFNT_Err_Ok
&&
789 face
->postscript
.FormatType
!= 0x00030000L
)
790 flags
|= FT_FACE_FLAG_GLYPH_NAMES
;
793 /* fixed width font? */
794 if ( face
->postscript
.isFixedPitch
)
795 flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
797 /* vertical information? */
798 if ( face
->vertical_info
)
799 flags
|= FT_FACE_FLAG_VERTICAL
;
801 /* kerning available ? */
802 if ( TT_FACE_HAS_KERNING( face
) )
803 flags
|= FT_FACE_FLAG_KERNING
;
805 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
806 /* Don't bother to load the tables unless somebody asks for them. */
807 /* No need to do work which will (probably) not be used. */
808 if ( tt_face_lookup_table( face
, TTAG_glyf
) != 0 &&
809 tt_face_lookup_table( face
, TTAG_fvar
) != 0 &&
810 tt_face_lookup_table( face
, TTAG_gvar
) != 0 )
811 flags
|= FT_FACE_FLAG_MULTIPLE_MASTERS
;
814 root
->face_flags
= flags
;
816 /*********************************************************************/
818 /* Compute style flags. */
822 if ( has_outline
== TRUE
&& face
->os2
.version
!= 0xFFFFU
)
824 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */
825 /* indicates an oblique font face. This flag has been */
826 /* introduced in version 1.5 of the OpenType specification. */
828 if ( face
->os2
.fsSelection
& 512 ) /* bit 9 */
829 flags
|= FT_STYLE_FLAG_ITALIC
;
830 else if ( face
->os2
.fsSelection
& 1 ) /* bit 0 */
831 flags
|= FT_STYLE_FLAG_ITALIC
;
833 if ( face
->os2
.fsSelection
& 32 ) /* bit 5 */
834 flags
|= FT_STYLE_FLAG_BOLD
;
838 /* this is an old Mac font, use the header field */
840 if ( face
->header
.Mac_Style
& 1 )
841 flags
|= FT_STYLE_FLAG_BOLD
;
843 if ( face
->header
.Mac_Style
& 2 )
844 flags
|= FT_STYLE_FLAG_ITALIC
;
847 root
->style_flags
= flags
;
849 /*********************************************************************/
851 /* Polish the charmaps. */
853 /* Try to set the charmap encoding according to the platform & */
854 /* encoding ID of each charmap. */
857 tt_face_build_cmaps( face
); /* ignore errors */
860 /* set the encoding fields */
865 for ( m
= 0; m
< root
->num_charmaps
; m
++ )
867 FT_CharMap charmap
= root
->charmaps
[m
];
870 charmap
->encoding
= sfnt_find_encoding( charmap
->platform_id
,
871 charmap
->encoding_id
);
874 if ( root
->charmap
== NULL
&&
875 charmap
->encoding
== FT_ENCODING_UNICODE
)
877 /* set 'root->charmap' to the first Unicode encoding we find */
878 root
->charmap
= charmap
;
884 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
887 * Now allocate the root array of FT_Bitmap_Size records and
888 * populate them. Unfortunately, it isn't possible to indicate bit
889 * depths in the FT_Bitmap_Size record. This is a design error.
895 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
896 count
= face
->sbit_num_strikes
;
898 count
= (FT_UInt
)face
->num_sbit_strikes
;
903 FT_Memory memory
= face
->root
.stream
->memory
;
904 FT_UShort em_size
= face
->header
.Units_Per_EM
;
905 FT_Short avgwidth
= face
->os2
.xAvgCharWidth
;
906 FT_Size_Metrics metrics
;
909 if ( em_size
== 0 || face
->os2
.version
== 0xFFFFU
)
915 if ( FT_NEW_ARRAY( root
->available_sizes
, count
) )
918 for ( i
= 0; i
< count
; i
++ )
920 FT_Bitmap_Size
* bsize
= root
->available_sizes
+ i
;
923 error
= sfnt
->load_strike_metrics( face
, i
, &metrics
);
927 bsize
->height
= (FT_Short
)( metrics
.height
>> 6 );
928 bsize
->width
= (FT_Short
)(
929 ( avgwidth
* metrics
.x_ppem
+ em_size
/ 2 ) / em_size
);
931 bsize
->x_ppem
= metrics
.x_ppem
<< 6;
932 bsize
->y_ppem
= metrics
.y_ppem
<< 6;
935 bsize
->size
= metrics
.y_ppem
<< 6;
938 root
->face_flags
|= FT_FACE_FLAG_FIXED_SIZES
;
939 root
->num_fixed_sizes
= (FT_Int
)count
;
943 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
945 /* a font with no bitmaps and no outlines is scalable; */
946 /* it has only empty glyphs then */
947 if ( !FT_HAS_FIXED_SIZES( root
) && !FT_IS_SCALABLE( root
) )
948 root
->face_flags
|= FT_FACE_FLAG_SCALABLE
;
951 /*********************************************************************/
953 /* Set up metrics. */
955 if ( FT_IS_SCALABLE( root
) )
957 /* XXX What about if outline header is missing */
958 /* (e.g. sfnt wrapped bitmap)? */
959 root
->bbox
.xMin
= face
->header
.xMin
;
960 root
->bbox
.yMin
= face
->header
.yMin
;
961 root
->bbox
.xMax
= face
->header
.xMax
;
962 root
->bbox
.yMax
= face
->header
.yMax
;
963 root
->units_per_EM
= face
->header
.Units_Per_EM
;
966 /* XXX: Computing the ascender/descender/height is very different */
967 /* from what the specification tells you. Apparently, we */
968 /* must be careful because */
970 /* - not all fonts have an OS/2 table; in this case, we take */
971 /* the values in the horizontal header. However, these */
972 /* values very often are not reliable. */
974 /* - otherwise, the correct typographic values are in the */
975 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
977 /* However, certain fonts have these fields set to 0. */
978 /* Rather, they have usWinAscent & usWinDescent correctly */
979 /* set (but with different values). */
981 /* As an example, Arial Narrow is implemented through four */
982 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
984 /* Strangely, all fonts have the same values in their */
985 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
987 /* On the other hand, they all have different */
988 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
989 /* table cannot be used to compute the text height reliably! */
992 /* The ascender/descender/height are computed from the OS/2 table */
993 /* when found. Otherwise, they're taken from the horizontal */
997 root
->ascender
= face
->horizontal
.Ascender
;
998 root
->descender
= face
->horizontal
.Descender
;
1000 root
->height
= (FT_Short
)( root
->ascender
- root
->descender
+
1001 face
->horizontal
.Line_Gap
);
1004 /* if the line_gap is 0, we add an extra 15% to the text height -- */
1005 /* this computation is based on various versions of Times New Roman */
1006 if ( face
->horizontal
.Line_Gap
== 0 )
1007 root
->height
= (FT_Short
)( ( root
->height
* 115 + 50 ) / 100 );
1011 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
1012 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
1013 if ( face
->os2
.version
!= 0xFFFFU
&& root
->ascender
)
1018 root
->ascender
= face
->os2
.sTypoAscender
;
1019 root
->descender
= -face
->os2
.sTypoDescender
;
1021 height
= root
->ascender
+ root
->descender
+ face
->os2
.sTypoLineGap
;
1022 if ( height
> root
->height
)
1023 root
->height
= height
;
1027 root
->max_advance_width
= face
->horizontal
.advance_Width_Max
;
1028 root
->max_advance_height
= (FT_Short
)( face
->vertical_info
1029 ? face
->vertical
.advance_Height_Max
1032 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */
1033 /* Adjust underline position from top edge to centre of */
1034 /* stroke to convert TrueType meaning to FreeType meaning. */
1035 root
->underline_position
= face
->postscript
.underlinePosition
-
1036 face
->postscript
.underlineThickness
/ 2;
1037 root
->underline_thickness
= face
->postscript
.underlineThickness
;
1043 FT_TRACE2(( "sfnt_load_face: done\n" ));
1054 FT_LOCAL_DEF( void )
1055 sfnt_done_face( TT_Face face
)
1064 memory
= face
->root
.memory
;
1065 sfnt
= (SFNT_Service
)face
->sfnt
;
1069 /* destroy the postscript names table if it is loaded */
1070 if ( sfnt
->free_psnames
)
1071 sfnt
->free_psnames( face
);
1073 /* destroy the embedded bitmaps table if it is loaded */
1074 if ( sfnt
->free_eblc
)
1075 sfnt
->free_eblc( face
);
1078 #ifdef TT_CONFIG_OPTION_BDF
1079 /* freeing the embedded BDF properties */
1080 tt_face_free_bdf_props( face
);
1083 /* freeing the kerning table */
1084 tt_face_done_kern( face
);
1086 /* freeing the collection table */
1087 FT_FREE( face
->ttc_header
.offsets
);
1088 face
->ttc_header
.count
= 0;
1090 /* freeing table directory */
1091 FT_FREE( face
->dir_tables
);
1092 face
->num_tables
= 0;
1095 FT_Stream stream
= FT_FACE_STREAM( face
);
1098 /* simply release the 'cmap' table frame */
1099 FT_FRAME_RELEASE( face
->cmap_table
);
1100 face
->cmap_size
= 0;
1103 /* freeing the horizontal metrics */
1104 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
1106 FT_Stream stream
= FT_FACE_STREAM( face
);
1109 FT_FRAME_RELEASE( face
->horz_metrics
);
1110 FT_FRAME_RELEASE( face
->vert_metrics
);
1111 face
->horz_metrics_size
= 0;
1112 face
->vert_metrics_size
= 0;
1115 FT_FREE( face
->horizontal
.long_metrics
);
1116 FT_FREE( face
->horizontal
.short_metrics
);
1119 /* freeing the vertical ones, if any */
1120 if ( face
->vertical_info
)
1122 FT_FREE( face
->vertical
.long_metrics
);
1123 FT_FREE( face
->vertical
.short_metrics
);
1124 face
->vertical_info
= 0;
1127 /* freeing the gasp table */
1128 FT_FREE( face
->gasp
.gaspRanges
);
1129 face
->gasp
.numRanges
= 0;
1131 /* freeing the name table */
1133 sfnt
->free_name( face
);
1135 /* freeing family and style name */
1136 FT_FREE( face
->root
.family_name
);
1137 FT_FREE( face
->root
.style_name
);
1139 /* freeing sbit size table */
1140 FT_FREE( face
->root
.available_sizes
);
1141 face
->root
.num_fixed_sizes
= 0;
1143 FT_FREE( face
->postscript_name
);