1 /***************************************************************************/
5 /* SFNT object management (base). */
7 /* Copyright 1996-2000 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 /***************************************************************************/
19 #ifdef FT_FLAT_COMPILE
25 #include <sfnt/sfobjs.h>
30 #include <freetype/internal/sfnt.h>
31 #include <freetype/internal/psnames.h>
32 #include <freetype/ttnameid.h>
33 #include <freetype/internal/tterrors.h>
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
46 /*************************************************************************/
52 /* Returns a given ENGLISH name record in ASCII. */
55 /* face :: A handle to the source face object. */
57 /* nameid :: The name id of the name record to return. */
60 /* Character string. NULL if no name is present. */
63 FT_String
* Get_Name( TT_Face face
,
66 FT_Memory memory
= face
->root
.memory
;
69 FT_Bool wide_chars
= 1;
72 rec
= face
->name_table
.names
;
73 for ( n
= 0; n
< face
->name_table
.numNameRecords
; n
++, rec
++ )
75 if ( rec
->nameID
== nameid
)
77 /* found the name -- now create an ASCII string from it */
81 /* test for Microsoft English language */
82 if ( rec
->platformID
== TT_PLATFORM_MICROSOFT
&&
83 rec
->encodingID
<= TT_MS_ID_UNICODE_CS
&&
84 ( rec
->languageID
& 0x3FF ) == 0x009 )
87 /* test for Apple Unicode encoding */
88 else if ( rec
->platformID
== TT_PLATFORM_APPLE_UNICODE
)
91 /* test for Apple Roman */
92 else if ( rec
->platformID
== TT_PLATFORM_MACINTOSH
&&
93 rec
->languageID
== TT_MAC_ID_ROMAN
)
99 /* found a Unicode name */
111 len
= (FT_UInt
)rec
->stringLength
/ 2;
112 if ( MEM_Alloc( string
, len
+ 1 ) )
115 for ( m
= 0; m
< len
; m
++ )
116 string
[m
] = rec
->string
[2 * m
+ 1];
120 len
= rec
->stringLength
;
121 if ( MEM_Alloc( string
, len
+ 1 ) )
124 MEM_Copy( string
, rec
->string
, len
);
138 FT_Encoding
find_encoding( int platform_id
,
141 typedef struct TEncoding
145 FT_Encoding encoding
;
150 const TEncoding tt_encodings
[] =
152 { TT_PLATFORM_ISO
, -1, ft_encoding_unicode
},
154 { TT_PLATFORM_APPLE_UNICODE
, -1, ft_encoding_unicode
},
156 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, ft_encoding_apple_roman
},
158 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, ft_encoding_unicode
},
159 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, ft_encoding_sjis
},
160 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, ft_encoding_gb2312
},
161 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, ft_encoding_big5
},
162 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, ft_encoding_wansung
},
163 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, ft_encoding_johab
}
166 const TEncoding
*cur
, *limit
;
170 limit
= cur
+ sizeof ( tt_encodings
) / sizeof ( tt_encodings
[0] );
172 for ( ; cur
< limit
; cur
++ )
174 if ( cur
->platform_id
== platform_id
)
176 if ( cur
->encoding_id
== encoding_id
||
177 cur
->encoding_id
== -1 )
178 return cur
->encoding
;
182 return ft_encoding_none
;
187 FT_Error
SFNT_Init_Face( FT_Stream stream
,
191 FT_Parameter
* params
)
194 FT_Library library
= face
->root
.driver
->root
.library
;
195 SFNT_Interface
* sfnt
;
196 SFNT_Header sfnt_header
;
198 /* for now, parameters are unused */
199 FT_UNUSED( num_params
);
202 sfnt
= (SFNT_Interface
*)face
->sfnt
;
205 sfnt
= (SFNT_Interface
*)FT_Get_Module_Interface( library
, "sfnt" );
208 error
= FT_Err_Invalid_File_Format
;
213 face
->goto_table
= sfnt
->goto_table
;
216 if ( !face
->psnames
)
218 face
->psnames
= (PSNames_Interface
*)
219 FT_Get_Module_Interface( library
, "psnames" );
222 /* check that we have a valid TrueType file */
223 error
= sfnt
->load_sfnt_header( face
, stream
, face_index
, &sfnt_header
);
227 face
->format_tag
= sfnt_header
.format_tag
;
228 face
->num_tables
= sfnt_header
.num_tables
;
230 /* Load font directory */
231 error
= sfnt
->load_directory( face
, stream
, &sfnt_header
);
235 face
->root
.num_faces
= face
->ttc_header
.count
;
236 if ( face
->root
.num_faces
< 1 )
237 face
->root
.num_faces
= 1;
245 #define LOAD_( x ) ( ( error = sfnt->load_##x( face, stream ) ) \
250 FT_Error
SFNT_Load_Face( FT_Stream stream
,
254 FT_Parameter
* params
)
257 SFNT_Interface
* sfnt
= (SFNT_Interface
*)face
->sfnt
;
259 FT_UNUSED( face_index
);
260 FT_UNUSED( num_params
);
265 if ( LOAD_( header
) ||
266 LOAD_( max_profile
) ||
268 /* load the `hhea' & `hmtx' tables at once */
269 ( error
= sfnt
->load_metrics( face
, stream
, 0 ) ) != TT_Err_Ok
||
271 /* try to load the `vhea' & `vmtx' at once if present */
272 ( error
= sfnt
->load_metrics( face
, stream
, 1 ) ) != TT_Err_Ok
||
280 /* the optional tables */
282 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
283 /* embedded bitmap support. */
284 if ( sfnt
->load_sbits
&& LOAD_( sbits
) )
286 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
288 if ( LOAD_( hdmx
) ||
294 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
295 if ( ( error
= TT_Extension_Create( face
) ) != TT_Err_Ok
)
299 face
->root
.family_name
= Get_Name( face
, TT_NAME_ID_FONT_FAMILY
);
300 face
->root
.style_name
= Get_Name( face
, TT_NAME_ID_FONT_SUBFAMILY
);
302 /* now set up root fields */
304 FT_Face root
= &face
->root
;
311 memory
= root
->memory
;
313 /*********************************************************************/
315 /* Compute face flags. */
317 flags
= FT_FACE_FLAG_SCALABLE
| /* scalable outlines */
318 FT_FACE_FLAG_SFNT
| /* SFNT file format */
319 FT_FACE_FLAG_HORIZONTAL
; /* horizontal data */
321 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
322 /* might need more polish to detect the presence of a Postscript */
323 /* name table in the font */
324 flags
|= FT_FACE_FLAG_GLYPH_NAMES
;
327 /* fixed width font? */
328 if ( face
->postscript
.isFixedPitch
)
329 flags
|= FT_FACE_FLAG_FIXED_WIDTH
;
331 /* vertical information? */
332 if ( face
->vertical_info
)
333 flags
|= FT_FACE_FLAG_VERTICAL
;
335 /* kerning available ? */
336 if ( face
->kern_pairs
)
337 flags
|= FT_FACE_FLAG_KERNING
;
339 root
->face_flags
= flags
;
341 /*********************************************************************/
343 /* Compute style flags. */
347 if ( face
->os2
.version
!= 0xFFFF )
349 /* we have an OS/2 table; use the `fsSelection' field */
350 if ( face
->os2
.fsSelection
& 1 )
351 flags
|= FT_STYLE_FLAG_ITALIC
;
353 if ( face
->os2
.fsSelection
& 32 )
354 flags
|= FT_STYLE_FLAG_BOLD
;
358 /* this is an old Mac font, use the header field */
359 if ( face
->header
.Mac_Style
& 1 )
360 flags
|= FT_STYLE_FLAG_BOLD
;
362 if ( face
->header
.Mac_Style
& 2 )
363 flags
|= FT_STYLE_FLAG_ITALIC
;
366 root
->style_flags
= flags
;
368 /*********************************************************************/
370 /* Polish the charmaps. */
372 /* Try to set the charmap encoding according to the platform & */
373 /* encoding ID of each charmap. */
375 charmap
= face
->charmaps
;
376 root
->num_charmaps
= face
->num_charmaps
;
378 /* allocate table of pointers */
379 if ( ALLOC_ARRAY( root
->charmaps
, root
->num_charmaps
, FT_CharMap
) )
382 for ( n
= 0; n
< root
->num_charmaps
; n
++, charmap
++ )
384 FT_Int platform
= charmap
->cmap
.platformID
;
385 FT_Int encoding
= charmap
->cmap
.platformEncodingID
;
388 charmap
->root
.face
= (FT_Face
)face
;
389 charmap
->root
.platform_id
= platform
;
390 charmap
->root
.encoding_id
= encoding
;
391 charmap
->root
.encoding
= find_encoding( platform
, encoding
);
393 /* now, set root->charmap with a unicode charmap */
394 /* wherever available */
395 if ( !root
->charmap
&&
396 charmap
->root
.encoding
== ft_encoding_unicode
)
397 root
->charmap
= (FT_CharMap
)charmap
;
399 root
->charmaps
[n
] = (FT_CharMap
)charmap
;
402 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
404 if ( face
->num_sbit_strikes
)
406 root
->num_fixed_sizes
= face
->num_sbit_strikes
;
407 if ( ALLOC_ARRAY( root
->available_sizes
,
408 face
->num_sbit_strikes
,
412 for ( n
= 0 ; n
< face
->num_sbit_strikes
; n
++ )
414 root
->available_sizes
[n
].width
=
415 face
->sbit_strikes
[n
].x_ppem
;
416 root
->available_sizes
[n
].height
=
417 face
->sbit_strikes
[n
].y_ppem
;
422 #else /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
425 root
->num_fixed_sizes
= 0;
426 root
->available_sizes
= 0;
429 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
431 /*********************************************************************/
433 /* Set up metrics. */
435 root
->bbox
.xMin
= face
->header
.xMin
;
436 root
->bbox
.yMin
= face
->header
.yMin
;
437 root
->bbox
.xMax
= face
->header
.xMax
;
438 root
->bbox
.yMax
= face
->header
.yMax
;
439 root
->units_per_EM
= face
->header
.Units_Per_EM
;
441 /* The ascender/descender/height are computed from the OS/2 table */
442 /* when found. Otherwise, they're taken from the horizontal header. */
443 if ( face
->os2
.version
!= 0xFFFF )
445 root
->ascender
= face
->os2
.sTypoAscender
;
446 root
->descender
= -face
->os2
.sTypoDescender
;
447 root
->height
= root
->ascender
+ root
->descender
+
448 face
->os2
.sTypoLineGap
;
452 root
->ascender
= face
->horizontal
.Ascender
;
453 root
->descender
= face
->horizontal
.Descender
;
454 root
->height
= root
->ascender
+ root
->descender
+
455 face
->horizontal
.Line_Gap
;
458 root
->max_advance_width
= face
->horizontal
.advance_Width_Max
;
460 root
->max_advance_height
= face
->vertical_info
461 ? face
->vertical
.advance_Height_Max
464 root
->underline_position
= face
->postscript
.underlinePosition
;
465 root
->underline_thickness
= face
->postscript
.underlineThickness
;
467 /* root->max_points -- already set up */
468 /* root->max_contours -- already set up */
480 void SFNT_Done_Face( TT_Face face
)
482 FT_Memory memory
= face
->root
.memory
;
483 SFNT_Interface
* sfnt
= (SFNT_Interface
*)face
->sfnt
;
488 /* destroy the postscript names table if it is loaded */
489 if ( sfnt
->free_psnames
)
490 sfnt
->free_psnames( face
);
492 /* destroy the embedded bitmaps table if it is loaded */
493 if ( sfnt
->free_sbits
)
494 sfnt
->free_sbits( face
);
497 /* freeing the kerning table */
498 FREE( face
->kern_pairs
);
499 face
->num_kern_pairs
= 0;
501 /* freeing the collection table */
502 FREE( face
->ttc_header
.offsets
);
503 face
->ttc_header
.count
= 0;
505 /* freeing table directory */
506 FREE( face
->dir_tables
);
507 face
->num_tables
= 0;
509 /* freeing the character mapping tables */
510 if ( sfnt
&& sfnt
->load_charmaps
)
515 for ( n
= 0; n
< face
->num_charmaps
; n
++ )
516 sfnt
->free_charmap( face
, &face
->charmaps
[n
].cmap
);
519 FREE( face
->charmaps
);
520 face
->num_charmaps
= 0;
522 FREE( face
->root
.charmaps
);
523 face
->root
.num_charmaps
= 0;
524 face
->root
.charmap
= 0;
526 /* freeing the horizontal metrics */
527 FREE( face
->horizontal
.long_metrics
);
528 FREE( face
->horizontal
.short_metrics
);
530 /* freeing the vertical ones, if any */
531 if ( face
->vertical_info
)
533 FREE( face
->vertical
.long_metrics
);
534 FREE( face
->vertical
.short_metrics
);
535 face
->vertical_info
= 0;
538 /* freeing the gasp table */
539 FREE( face
->gasp
.gaspRanges
);
540 face
->gasp
.numRanges
= 0;
542 /* freeing the name table */
543 sfnt
->free_names( face
);
545 /* freeing the hdmx table */
546 sfnt
->free_hdmx( face
);
548 /* freeing family and style name */
549 FREE( face
->root
.family_name
);
550 FREE( face
->root
.style_name
);
552 /* freeing sbit size table */
553 face
->root
.num_fixed_sizes
= 0;
554 if ( face
->root
.available_sizes
)
555 FREE( face
->root
.available_sizes
);