1 /***************************************************************************/
5 /* SFNT object management (base). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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 /* Character string. NULL if no name is present. */
130 tt_face_get_name( TT_Face face
,
133 FT_Memory memory
= face
->root
.memory
;
134 FT_String
* result
= NULL
;
136 TT_NameEntryRec
* rec
;
137 FT_Int found_apple
= -1;
138 FT_Int found_apple_roman
= -1;
139 FT_Int found_apple_english
= -1;
140 FT_Int found_win
= -1;
141 FT_Int found_unicode
= -1;
143 FT_Bool is_english
= 0;
145 TT_NameEntry_ConvertFunc convert
;
148 rec
= face
->name_table
.names
;
149 for ( n
= 0; n
< face
->num_names
; n
++, rec
++ )
151 /* According to the OpenType 1.3 specification, only Microsoft or */
152 /* Apple platform IDs might be used in the `name' table. The */
153 /* `Unicode' platform is reserved for the `cmap' table, and the */
154 /* `Iso' one is deprecated. */
156 /* However, the Apple TrueType specification doesn't say the same */
157 /* thing and goes to suggest that all Unicode `name' table entries */
158 /* should be coded in UTF-16 (in big-endian format I suppose). */
160 if ( rec
->nameID
== nameid
&& rec
->stringLength
> 0 )
162 switch ( rec
->platformID
)
164 case TT_PLATFORM_APPLE_UNICODE
:
165 case TT_PLATFORM_ISO
:
166 /* there is `languageID' to check there. We should use this */
167 /* field only as a last solution when nothing else is */
173 case TT_PLATFORM_MACINTOSH
:
174 /* This is a bit special because some fonts will use either */
175 /* an English language id, or a Roman encoding id, to indicate */
176 /* the English version of its font name. */
178 if ( rec
->languageID
== TT_MAC_LANGID_ENGLISH
)
179 found_apple_english
= n
;
180 else if ( rec
->encodingID
== TT_MAC_ID_ROMAN
)
181 found_apple_roman
= n
;
184 case TT_PLATFORM_MICROSOFT
:
185 /* we only take a non-English name when there is nothing */
186 /* else available in the font */
188 if ( found_win
== -1 || ( rec
->languageID
& 0x3FF ) == 0x009 )
190 switch ( rec
->encodingID
)
192 case TT_MS_ID_SYMBOL_CS
:
193 case TT_MS_ID_UNICODE_CS
:
195 is_english
= FT_BOOL( ( rec
->languageID
& 0x3FF ) == 0x009 );
211 found_apple
= found_apple_roman
;
212 if ( found_apple_english
>= 0 )
213 found_apple
= found_apple_english
;
215 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
216 /* we will thus favor names encoded in Windows formats if available */
217 /* (provided it is an English name) */
220 if ( found_win
>= 0 && !( found_apple
>= 0 && !is_english
) )
222 rec
= face
->name_table
.names
+ found_win
;
223 switch ( rec
->encodingID
)
225 /* all Unicode strings are encoded using UTF-16BE */
226 case TT_MS_ID_UNICODE_CS
:
227 case TT_MS_ID_SYMBOL_CS
:
228 convert
= tt_name_entry_ascii_from_utf16
;
232 /* Apparently, if this value is found in a name table entry, it is */
233 /* documented as `full Unicode repertoire'. Experience with the */
234 /* MsGothic font shipped with Windows Vista shows that this really */
235 /* means UTF-16 encoded names (UCS-4 values are only used within */
237 convert
= tt_name_entry_ascii_from_utf16
;
244 else if ( found_apple
>= 0 )
246 rec
= face
->name_table
.names
+ found_apple
;
247 convert
= tt_name_entry_ascii_from_other
;
249 else if ( found_unicode
>= 0 )
251 rec
= face
->name_table
.names
+ found_unicode
;
252 convert
= tt_name_entry_ascii_from_utf16
;
255 if ( rec
&& convert
)
257 if ( rec
->string
== NULL
)
259 FT_Error error
= SFNT_Err_Ok
;
260 FT_Stream stream
= face
->name_table
.stream
;
265 if ( FT_QNEW_ARRAY ( rec
->string
, rec
->stringLength
) ||
266 FT_STREAM_SEEK( rec
->stringOffset
) ||
267 FT_STREAM_READ( rec
->string
, rec
->stringLength
) )
269 FT_FREE( rec
->string
);
270 rec
->stringLength
= 0;
276 result
= convert( rec
, memory
);
285 sfnt_find_encoding( int platform_id
,
288 typedef struct TEncoding
292 FT_Encoding encoding
;
297 const TEncoding tt_encodings
[] =
299 { TT_PLATFORM_ISO
, -1, FT_ENCODING_UNICODE
},
301 { TT_PLATFORM_APPLE_UNICODE
, -1, FT_ENCODING_UNICODE
},
303 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, FT_ENCODING_APPLE_ROMAN
},
305 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SYMBOL_CS
, FT_ENCODING_MS_SYMBOL
},
306 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, FT_ENCODING_UNICODE
},
307 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, FT_ENCODING_UNICODE
},
308 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, FT_ENCODING_SJIS
},
309 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, FT_ENCODING_GB2312
},
310 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, FT_ENCODING_BIG5
},
311 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, FT_ENCODING_WANSUNG
},
312 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, FT_ENCODING_JOHAB
}
315 const TEncoding
*cur
, *limit
;
319 limit
= cur
+ sizeof ( tt_encodings
) / sizeof ( tt_encodings
[0] );
321 for ( ; cur
< limit
; cur
++ )
323 if ( cur
->platform_id
== platform_id
)
325 if ( cur
->encoding_id
== encoding_id
||
326 cur
->encoding_id
== -1 )
327 return cur
->encoding
;
331 return FT_ENCODING_NONE
;
335 /* Fill in face->ttc_header. If the font is not a TTC, it is */
336 /* synthesized into a TTC with one offset table. */
338 sfnt_open_font( FT_Stream stream
,
341 FT_Memory memory
= stream
->memory
;
343 FT_ULong tag
, offset
;
345 static const FT_Frame_Field ttc_header_fields
[] =
348 #define FT_STRUCTURE TTC_HeaderRec
351 FT_FRAME_LONG( version
),
352 FT_FRAME_LONG( count
),
357 face
->ttc_header
.tag
= 0;
358 face
->ttc_header
.version
= 0;
359 face
->ttc_header
.count
= 0;
361 offset
= FT_STREAM_POS();
363 if ( FT_READ_ULONG( tag
) )
366 if ( tag
!= 0x00010000UL
&&
368 tag
!= FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) &&
370 tag
!= 0x00020000UL
)
371 return SFNT_Err_Unknown_File_Format
;
373 face
->ttc_header
.tag
= TTAG_ttcf
;
375 if ( tag
== TTAG_ttcf
)
380 FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
382 if ( FT_STREAM_READ_FIELDS( ttc_header_fields
, &face
->ttc_header
) )
385 /* now read the offsets of each font in the file */
386 if ( FT_NEW_ARRAY( face
->ttc_header
.offsets
, face
->ttc_header
.count
) )
389 if ( FT_FRAME_ENTER( face
->ttc_header
.count
* 4L ) )
392 for ( n
= 0; n
< face
->ttc_header
.count
; n
++ )
393 face
->ttc_header
.offsets
[n
] = FT_GET_ULONG();
399 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
401 face
->ttc_header
.version
= 1 << 16;
402 face
->ttc_header
.count
= 1;
404 if ( FT_NEW( face
->ttc_header
.offsets
) )
407 face
->ttc_header
.offsets
[0] = offset
;
414 FT_LOCAL_DEF( FT_Error
)
415 sfnt_init_face( FT_Stream stream
,
419 FT_Parameter
* params
)
422 FT_Library library
= face
->root
.driver
->root
.library
;
426 /* for now, parameters are unused */
427 FT_UNUSED( num_params
);
431 sfnt
= (SFNT_Service
)face
->sfnt
;
434 sfnt
= (SFNT_Service
)FT_Get_Module_Interface( library
, "sfnt" );
436 return SFNT_Err_Invalid_File_Format
;
439 face
->goto_table
= sfnt
->goto_table
;
442 FT_FACE_FIND_GLOBAL_SERVICE( face
, face
->psnames
, POSTSCRIPT_CMAPS
);
444 error
= sfnt_open_font( stream
, face
);
448 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face
, face_index
));
450 if ( face_index
< 0 )
453 if ( face_index
>= face
->ttc_header
.count
)
454 return SFNT_Err_Bad_Argument
;
456 if ( FT_STREAM_SEEK( face
->ttc_header
.offsets
[face_index
] ) )
459 /* check that we have a valid TrueType file */
460 error
= sfnt
->load_font_dir( face
, stream
);
464 face
->root
.num_faces
= face
->ttc_header
.count
;
472 FT_TRACE2(( "`" #x "' " )); \
473 FT_TRACE3(( "-->\n" )); \
475 error = sfnt->load_##x( face, stream ); \
477 FT_TRACE2(( "%s\n", ( !error ) \
479 : ( error == SFNT_Err_Table_Missing ) \
481 : "failed to load" )); \
482 FT_TRACE3(( "\n" )); \
485 #define LOADM_( x, vertical ) \
487 FT_TRACE2(( "`%s" #x "' ", \
488 vertical ? "vertical " : "" )); \
489 FT_TRACE3(( "-->\n" )); \
491 error = sfnt->load_##x( face, stream, vertical ); \
493 FT_TRACE2(( "%s\n", ( !error ) \
495 : ( error == SFNT_Err_Table_Missing ) \
497 : "failed to load" )); \
498 FT_TRACE3(( "\n" )); \
502 FT_LOCAL_DEF( FT_Error
)
503 sfnt_load_face( FT_Stream stream
,
507 FT_Parameter
* params
)
509 FT_Error error
, psnames_error
;
511 FT_Bool is_apple_sbit
;
513 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
515 FT_UNUSED( face_index
);
516 FT_UNUSED( num_params
);
522 /* We now support two SFNT-based bitmapped font formats. They */
523 /* are recognized easily as they do not include a `glyf' */
526 /* The first format comes from Apple, and uses a table named */
527 /* `bhed' instead of `head' to store the font header (using */
528 /* the same format). It also doesn't include horizontal and */
529 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
532 /* The other format comes from Microsoft, and is used with */
533 /* WinCE/PocketPC. It looks like a standard TTF, except that */
534 /* it doesn't contain outlines. */
537 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face
));
539 /* do we have outlines in there? */
540 #ifdef FT_CONFIG_OPTION_INCREMENTAL
541 has_outline
= FT_BOOL( face
->root
.internal
->incremental_interface
!= 0 ||
542 tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
543 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
545 has_outline
= FT_BOOL( tt_face_lookup_table( face
, TTAG_glyf
) != 0 ||
546 tt_face_lookup_table( face
, TTAG_CFF
) != 0 );
551 /* if this font doesn't contain outlines, we try to load */
553 if ( !has_outline
&& sfnt
->load_bhed
)
556 is_apple_sbit
= FT_BOOL( !error
);
559 /* load the font header (`head' table) if this isn't an Apple */
561 if ( !is_apple_sbit
)
568 if ( face
->header
.Units_Per_EM
== 0 )
570 error
= SFNT_Err_Invalid_Table
;
575 /* the following tables are often not present in embedded TrueType */
576 /* fonts within PDF documents, so don't check for them. */
580 /* the following tables are optional in PCL fonts -- */
581 /* don't check for errors */
584 psnames_error
= error
;
586 /* do not load the metrics headers and tables if this is an Apple */
588 if ( !is_apple_sbit
)
590 /* load the `hhea' and `hmtx' tables */
595 if ( error
== SFNT_Err_Table_Missing
)
597 error
= SFNT_Err_Hmtx_Table_Missing
;
599 #ifdef FT_CONFIG_OPTION_INCREMENTAL
600 /* If this is an incrementally loaded font and there are */
601 /* overriding metrics, tolerate a missing `hmtx' table. */
602 if ( face
->root
.internal
->incremental_interface
&&
603 face
->root
.internal
->incremental_interface
->funcs
->
606 face
->horizontal
.number_Of_HMetrics
= 0;
612 else if ( error
== SFNT_Err_Table_Missing
)
614 /* No `hhea' table necessary for SFNT Mac fonts. */
615 if ( face
->format_tag
== TTAG_true
)
617 FT_TRACE2(( "This is an SFNT Mac font.\n" ));
623 error
= SFNT_Err_Horiz_Header_Missing
;
625 #ifdef FT_CONFIG_OPTION_INCREMENTAL
626 /* If this is an incrementally loaded font and there are */
627 /* overriding metrics, tolerate a missing `hhea' table. */
628 if ( face
->root
.internal
->incremental_interface
&&
629 face
->root
.internal
->incremental_interface
->funcs
->
632 face
->horizontal
.number_Of_HMetrics
= 0;
643 /* try to load the `vhea' and `vmtx' tables */
649 face
->vertical_info
= 1;
652 if ( error
&& error
!= SFNT_Err_Table_Missing
)
658 if ( error
!= SFNT_Err_Table_Missing
)
661 face
->os2
.version
= 0xFFFFU
;
666 /* the optional tables */
668 /* embedded bitmap support. */
669 if ( sfnt
->load_eblc
)
674 /* return an error if this font file has no outlines */
675 if ( error
== SFNT_Err_Table_Missing
&& has_outline
)
685 if ( error
!= SFNT_Err_Table_Missing
)
688 face
->pclt
.Version
= 0;
691 /* consider the kerning and gasp tables as optional */
697 face
->root
.num_glyphs
= face
->max_profile
.numGlyphs
;
699 face
->root
.family_name
= tt_face_get_name( face
,
700 TT_NAME_ID_PREFERRED_FAMILY
);
701 if ( !face
->root
.family_name
)
702 face
->root
.family_name
= tt_face_get_name( face
,
703 TT_NAME_ID_FONT_FAMILY
);
705 face
->root
.style_name
= tt_face_get_name( face
,
706 TT_NAME_ID_PREFERRED_SUBFAMILY
);
707 if ( !face
->root
.style_name
)
708 face
->root
.style_name
= tt_face_get_name( face
,
709 TT_NAME_ID_FONT_SUBFAMILY
);
711 /* now set up root fields */
713 FT_Face root
= &face
->root
;
714 FT_Int32 flags
= root
->face_flags
;
717 /*********************************************************************/
719 /* Compute face flags. */
721 if ( has_outline
== TRUE
)
722 flags
|= FT_FACE_FLAG_SCALABLE
; /* scalable outlines */
724 /* The sfnt driver only supports bitmap fonts natively, thus we */
725 /* don't set FT_FACE_FLAG_HINTER. */
726 flags
|= FT_FACE_FLAG_SFNT
| /* SFNT file format */
727 FT_FACE_FLAG_HORIZONTAL
; /* horizontal data */
729 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
730 if ( psnames_error
== SFNT_Err_Ok
&&
731 face
->postscript
.FormatType
!= 0x00030000L
)
732 flags
|= FT_FACE_FLAG_GLYPH_NAMES
;
735 /* fixed width font? */
736 if ( face
->postscript
.isFixedPitch
)
737 flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
739 /* vertical information? */
740 if ( face
->vertical_info
)
741 flags
|= FT_FACE_FLAG_VERTICAL
;
743 /* kerning available ? */
744 if ( TT_FACE_HAS_KERNING( face
) )
745 flags
|= FT_FACE_FLAG_KERNING
;
747 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
748 /* Don't bother to load the tables unless somebody asks for them. */
749 /* No need to do work which will (probably) not be used. */
750 if ( tt_face_lookup_table( face
, TTAG_glyf
) != 0 &&
751 tt_face_lookup_table( face
, TTAG_fvar
) != 0 &&
752 tt_face_lookup_table( face
, TTAG_gvar
) != 0 )
753 flags
|= FT_FACE_FLAG_MULTIPLE_MASTERS
;
756 root
->face_flags
= flags
;
758 /*********************************************************************/
760 /* Compute style flags. */
763 if ( has_outline
== TRUE
&& face
->os2
.version
!= 0xFFFFU
)
765 /* we have an OS/2 table; use the `fsSelection' field */
766 if ( face
->os2
.fsSelection
& 1 )
767 flags
|= FT_STYLE_FLAG_ITALIC
;
769 if ( face
->os2
.fsSelection
& 32 )
770 flags
|= FT_STYLE_FLAG_BOLD
;
774 /* this is an old Mac font, use the header field */
775 if ( face
->header
.Mac_Style
& 1 )
776 flags
|= FT_STYLE_FLAG_BOLD
;
778 if ( face
->header
.Mac_Style
& 2 )
779 flags
|= FT_STYLE_FLAG_ITALIC
;
782 root
->style_flags
= flags
;
784 /*********************************************************************/
786 /* Polish the charmaps. */
788 /* Try to set the charmap encoding according to the platform & */
789 /* encoding ID of each charmap. */
792 tt_face_build_cmaps( face
); /* ignore errors */
795 /* set the encoding fields */
800 for ( m
= 0; m
< root
->num_charmaps
; m
++ )
802 FT_CharMap charmap
= root
->charmaps
[m
];
805 charmap
->encoding
= sfnt_find_encoding( charmap
->platform_id
,
806 charmap
->encoding_id
);
809 if ( root
->charmap
== NULL
&&
810 charmap
->encoding
== FT_ENCODING_UNICODE
)
812 /* set 'root->charmap' to the first Unicode encoding we find */
813 root
->charmap
= charmap
;
820 /*********************************************************************/
822 /* Set up metrics. */
824 if ( has_outline
== TRUE
)
826 /* XXX What about if outline header is missing */
827 /* (e.g. sfnt wrapped bitmap)? */
828 root
->bbox
.xMin
= face
->header
.xMin
;
829 root
->bbox
.yMin
= face
->header
.yMin
;
830 root
->bbox
.xMax
= face
->header
.xMax
;
831 root
->bbox
.yMax
= face
->header
.yMax
;
832 root
->units_per_EM
= face
->header
.Units_Per_EM
;
835 /* XXX: Computing the ascender/descender/height is very different */
836 /* from what the specification tells you. Apparently, we */
837 /* must be careful because */
839 /* - not all fonts have an OS/2 table; in this case, we take */
840 /* the values in the horizontal header. However, these */
841 /* values very often are not reliable. */
843 /* - otherwise, the correct typographic values are in the */
844 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
846 /* However, certain fonts have these fields set to 0. */
847 /* Rather, they have usWinAscent & usWinDescent correctly */
848 /* set (but with different values). */
850 /* As an example, Arial Narrow is implemented through four */
851 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
853 /* Strangely, all fonts have the same values in their */
854 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
856 /* On the other hand, they all have different */
857 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
858 /* table cannot be used to compute the text height reliably! */
861 /* The ascender/descender/height are computed from the OS/2 table */
862 /* when found. Otherwise, they're taken from the horizontal */
866 root
->ascender
= face
->horizontal
.Ascender
;
867 root
->descender
= face
->horizontal
.Descender
;
869 root
->height
= (FT_Short
)( root
->ascender
- root
->descender
+
870 face
->horizontal
.Line_Gap
);
873 /* if the line_gap is 0, we add an extra 15% to the text height -- */
874 /* this computation is based on various versions of Times New Roman */
875 if ( face
->horizontal
.Line_Gap
== 0 )
876 root
->height
= (FT_Short
)( ( root
->height
* 115 + 50 ) / 100 );
881 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
882 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
883 if ( face
->os2
.version
!= 0xFFFFU
&& root
->ascender
)
888 root
->ascender
= face
->os2
.sTypoAscender
;
889 root
->descender
= -face
->os2
.sTypoDescender
;
891 height
= root
->ascender
+ root
->descender
+ face
->os2
.sTypoLineGap
;
892 if ( height
> root
->height
)
893 root
->height
= height
;
898 root
->max_advance_width
= face
->horizontal
.advance_Width_Max
;
900 root
->max_advance_height
= (FT_Short
)( face
->vertical_info
901 ? face
->vertical
.advance_Height_Max
904 root
->underline_position
= face
->postscript
.underlinePosition
;
905 root
->underline_thickness
= face
->postscript
.underlineThickness
;
908 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
911 * Now allocate the root array of FT_Bitmap_Size records and
912 * populate them. Unfortunately, it isn't possible to indicate bit
913 * depths in the FT_Bitmap_Size record. This is a design error.
919 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
920 count
= face
->sbit_num_strikes
;
922 count
= (FT_UInt
)face
->num_sbit_strikes
;
927 FT_Memory memory
= face
->root
.stream
->memory
;
928 FT_UShort em_size
= face
->header
.Units_Per_EM
;
929 FT_Short avgwidth
= face
->os2
.xAvgCharWidth
;
930 FT_Size_Metrics metrics
;
933 if ( em_size
== 0 || face
->os2
.version
== 0xFFFFU
)
939 if ( FT_NEW_ARRAY( root
->available_sizes
, count
) )
942 for ( i
= 0; i
< count
; i
++ )
944 FT_Bitmap_Size
* bsize
= root
->available_sizes
+ i
;
947 error
= sfnt
->load_strike_metrics( face
, i
, &metrics
);
951 bsize
->height
= (FT_Short
)( metrics
.height
>> 6 );
952 bsize
->width
= (FT_Short
)(
953 ( avgwidth
* metrics
.x_ppem
+ em_size
/ 2 ) / em_size
);
955 bsize
->x_ppem
= metrics
.x_ppem
<< 6;
956 bsize
->y_ppem
= metrics
.y_ppem
<< 6;
959 bsize
->size
= metrics
.y_ppem
<< 6;
962 root
->face_flags
|= FT_FACE_FLAG_FIXED_SIZES
;
963 root
->num_fixed_sizes
= (FT_Int
)count
;
967 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
972 FT_TRACE2(( "sfnt_load_face: done\n" ));
983 sfnt_done_face( TT_Face face
)
985 FT_Memory memory
= face
->root
.memory
;
986 SFNT_Service sfnt
= (SFNT_Service
)face
->sfnt
;
991 /* destroy the postscript names table if it is loaded */
992 if ( sfnt
->free_psnames
)
993 sfnt
->free_psnames( face
);
995 /* destroy the embedded bitmaps table if it is loaded */
996 if ( sfnt
->free_eblc
)
997 sfnt
->free_eblc( face
);
1000 #ifdef TT_CONFIG_OPTION_BDF
1001 /* freeing the embedded BDF properties */
1002 tt_face_free_bdf_props( face
);
1005 /* freeing the kerning table */
1006 tt_face_done_kern( face
);
1008 /* freeing the collection table */
1009 FT_FREE( face
->ttc_header
.offsets
);
1010 face
->ttc_header
.count
= 0;
1012 /* freeing table directory */
1013 FT_FREE( face
->dir_tables
);
1014 face
->num_tables
= 0;
1017 FT_Stream stream
= FT_FACE_STREAM( face
);
1020 /* simply release the 'cmap' table frame */
1021 FT_FRAME_RELEASE( face
->cmap_table
);
1022 face
->cmap_size
= 0;
1025 /* freeing the horizontal metrics */
1026 #if !defined FT_CONFIG_OPTION_OLD_INTERNALS
1028 FT_Stream stream
= FT_FACE_STREAM( face
);
1031 FT_FRAME_RELEASE( face
->horz_metrics
);
1032 FT_FRAME_RELEASE( face
->vert_metrics
);
1033 face
->horz_metrics_size
= 0;
1034 face
->vert_metrics_size
= 0;
1037 FT_FREE( face
->horizontal
.long_metrics
);
1038 FT_FREE( face
->horizontal
.short_metrics
);
1041 /* freeing the vertical ones, if any */
1042 if ( face
->vertical_info
)
1044 FT_FREE( face
->vertical
.long_metrics
);
1045 FT_FREE( face
->vertical
.short_metrics
);
1046 face
->vertical_info
= 0;
1049 /* freeing the gasp table */
1050 FT_FREE( face
->gasp
.gaspRanges
);
1051 face
->gasp
.numRanges
= 0;
1053 /* freeing the name table */
1054 sfnt
->free_name( face
);
1056 /* freeing family and style name */
1057 FT_FREE( face
->root
.family_name
);
1058 FT_FREE( face
->root
.style_name
);
1060 /* freeing sbit size table */
1061 FT_FREE( face
->root
.available_sizes
);
1062 face
->root
.num_fixed_sizes
= 0;
1064 FT_FREE( face
->postscript_name
);