1 /***************************************************************************/
5 /* SFNT object management (base). */
7 /* Copyright 1996-2001, 2002 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 /***************************************************************************/
23 #include FT_INTERNAL_SFNT_H
24 #include FT_INTERNAL_POSTSCRIPT_NAMES_H
25 #include FT_TRUETYPE_IDS_H
26 #include FT_TRUETYPE_TAGS_H
31 /*************************************************************************/
33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35 /* messages during execution. */
38 #define FT_COMPONENT trace_sfobjs
42 /* convert a UTF-16 name entry to ASCII */
44 tt_name_entry_ascii_from_utf16( TT_NameEntry entry,
49 FT_Byte* read = (FT_Byte*)entry->string;
52 len = (FT_UInt)entry->stringLength / 2;
54 if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
57 for ( n = 0; n < len; n++ )
59 code = FT_NEXT_USHORT( read );
60 if ( code < 32 || code > 127 )
63 string[n] = (char)code;
72 /* convert a UCS-4 name entry to ASCII */
74 tt_name_entry_ascii_from_ucs4( TT_NameEntry entry,
79 FT_Byte* read = (FT_Byte*)entry->string;
82 len = (FT_UInt)entry->stringLength / 4;
84 if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
87 for ( n = 0; n < len; n++ )
89 code = (FT_UInt)FT_NEXT_ULONG( read );
90 if ( code < 32 || code > 127 )
93 string[n] = (char)code;
102 /* convert an Apple Roman or symbol name entry to ASCII */
104 tt_name_entry_ascii_from_other( TT_NameEntry entry,
108 FT_UInt len, code, n;
109 FT_Byte* read = (FT_Byte*)entry->string;
112 len = (FT_UInt)entry->stringLength;
114 if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
117 for ( n = 0; n < len; n++ )
120 if ( code < 32 || code > 127 )
123 string[n] = (char)code;
132 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry,
136 /*************************************************************************/
139 /* tt_face_get_name */
142 /* Returns a given ENGLISH name record in ASCII. */
145 /* face :: A handle to the source face object. */
147 /* nameid :: The name id of the name record to return. */
150 /* Character string. NULL if no name is present. */
153 tt_face_get_name( TT_Face face,
156 FT_Memory memory = face->root.memory;
157 FT_String* result = NULL;
159 TT_NameEntryRec* rec;
160 FT_Int found_apple = -1;
161 FT_Int found_win = -1;
162 FT_Int found_unicode = -1;
164 TT_NameEntry_ConvertFunc convert;
167 rec = face->name_table.names;
168 for ( n = 0; n < face->num_names; n++, rec++ )
170 /* According to the OpenType 1.3 specification, only Microsoft or */
171 /* Apple platform IDs might be used in the `name' table. The */
172 /* `Unicode' platform is reserved for the `cmap' table, and the */
173 /* `Iso' one is deprecated. */
175 /* However, the Apple TrueType specification doesn't say the same */
176 /* thing and goes to suggest that all Unicode `name' table entries */
177 /* should be coded in UTF-16 (in big-endian format I suppose). */
179 if ( rec->nameID == nameid && rec->stringLength > 0 )
181 switch ( rec->platformID )
183 case TT_PLATFORM_APPLE_UNICODE:
184 case TT_PLATFORM_ISO:
185 /* there is `languageID' to check there. We should use this */
186 /* field only as a last solution when nothing else is */
192 case TT_PLATFORM_MACINTOSH:
193 if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
198 case TT_PLATFORM_MICROSOFT:
199 /* we only take a non-English name when there is nothing */
200 /* else available in the font */
202 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
204 switch ( rec->encodingID )
206 case TT_MS_ID_SYMBOL_CS:
207 case TT_MS_ID_UNICODE_CS:
224 /* some fonts contain invalid Unicode or Macintosh formatted entries; */
225 /* we will thus favor names encoded in Windows formats if available */
228 if ( found_win >= 0 )
230 rec = face->name_table.names + found_win;
231 switch ( rec->encodingID )
233 case TT_MS_ID_UNICODE_CS:
234 case TT_MS_ID_SYMBOL_CS:
235 convert = tt_name_entry_ascii_from_utf16;
239 convert = tt_name_entry_ascii_from_ucs4;
246 else if ( found_apple >= 0 )
248 rec = face->name_table.names + found_apple;
249 convert = tt_name_entry_ascii_from_other;
251 else if ( found_unicode >= 0 )
253 rec = face->name_table.names + found_unicode;
254 convert = tt_name_entry_ascii_from_utf16;
257 if ( rec && convert )
259 if ( rec->string == NULL )
262 FT_Stream stream = face->name_table.stream;
265 if ( FT_NEW_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_MS_SJIS },
309 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_MS_GB2312 },
310 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_MS_BIG5 },
311 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_MS_WANSUNG },
312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_MS_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 FT_LOCAL_DEF( FT_Error )
336 sfnt_init_face( FT_Stream stream,
340 FT_Parameter* params )
343 FT_Library library = face->root.driver->root.library;
345 SFNT_HeaderRec sfnt_header;
347 /* for now, parameters are unused */
348 FT_UNUSED( num_params );
352 sfnt = (SFNT_Service)face->sfnt;
355 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
358 error = SFNT_Err_Invalid_File_Format;
363 face->goto_table = sfnt->goto_table;
366 if ( !face->psnames )
368 face->psnames = (PSNames_Service)
369 FT_Get_Module_Interface( library, "psnames" );
372 /* check that we have a valid TrueType file */
373 error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
377 face->format_tag = sfnt_header.format_tag;
378 face->num_tables = sfnt_header.num_tables;
380 /* Load font directory */
381 error = sfnt->load_directory( face, stream, &sfnt_header );
385 face->root.num_faces = face->ttc_header.count;
386 if ( face->root.num_faces < 1 )
387 face->root.num_faces = 1;
395 #define LOAD_( x ) ( ( error = sfnt->load_##x( face, stream ) ) \
399 FT_LOCAL_DEF( FT_Error )
400 sfnt_load_face( FT_Stream stream,
404 FT_Parameter* params )
408 FT_Bool is_apple_sbit;
410 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
412 FT_UNUSED( face_index );
413 FT_UNUSED( num_params );
419 /* We now support two SFNT-based bitmapped font formats. They */
420 /* are recognized easily as they do not include a `glyf' */
423 /* The first format comes from Apple, and uses a table named */
424 /* `bhed' instead of `head' to store the font header (using */
425 /* the same format). It also doesn't include horizontal and */
426 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */
429 /* The other format comes from Microsoft, and is used with */
430 /* WinCE/PocketPC. It looks like a standard TTF, except that */
431 /* it doesn't contain outlines. */
434 /* do we have outlines in there? */
435 #ifdef FT_CONFIG_OPTION_INCREMENTAL
436 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 ||
437 tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
438 tt_face_lookup_table( face, TTAG_CFF ) != 0 );
440 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
441 tt_face_lookup_table( face, TTAG_CFF ) != 0 );
446 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
448 /* if this font doesn't contain outlines, we try to load */
451 is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) );
453 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
455 /* load the font header (`head' table) if this isn't an Apple */
457 if ( !is_apple_sbit && LOAD_( header ) )
460 /* the following tables are often not present in embedded TrueType */
461 /* fonts within PDF documents, so don't check for them. */
462 (void)LOAD_( max_profile );
463 (void)LOAD_( charmaps );
465 /* the following tables are optional in PCL fonts -- */
466 /* don't check for errors */
467 (void)LOAD_( names );
468 (void)LOAD_( psnames );
470 /* do not load the metrics headers and tables if this is an Apple */
472 if ( !is_apple_sbit )
474 /* load the `hhea' and `hmtx' tables at once */
475 error = sfnt->load_metrics( face, stream, 0 );
479 /* try to load the `vhea' and `vmtx' tables at once */
480 error = sfnt->load_metrics( face, stream, 1 );
488 /* the optional tables */
490 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
492 /* embedded bitmap support. */
493 if ( sfnt->load_sbits && LOAD_( sbits ) )
495 /* return an error if this font file has no outlines */
496 if ( error == SFNT_Err_Table_Missing && has_outline )
502 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
504 if ( LOAD_( hdmx ) ||
510 face->root.family_name = tt_face_get_name( face,
511 TT_NAME_ID_FONT_FAMILY );
512 face->root.style_name = tt_face_get_name( face,
513 TT_NAME_ID_FONT_SUBFAMILY );
515 /* now set up root fields */
517 FT_Face root = &face->root;
522 memory = root->memory;
524 /*********************************************************************/
526 /* Compute face flags. */
528 if ( has_outline == TRUE )
529 flags = FT_FACE_FLAG_SCALABLE; /* scalable outlines */
531 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */
532 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */
534 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
535 /* might need more polish to detect the presence of a Postscript */
536 /* name table in the font */
537 flags |= FT_FACE_FLAG_GLYPH_NAMES;
540 /* fixed width font? */
541 if ( face->postscript.isFixedPitch )
542 flags |= FT_FACE_FLAG_FIXED_WIDTH;
544 /* vertical information? */
545 if ( face->vertical_info )
546 flags |= FT_FACE_FLAG_VERTICAL;
548 /* kerning available ? */
549 if ( face->kern_pairs )
550 flags |= FT_FACE_FLAG_KERNING;
552 root->face_flags = flags;
554 /*********************************************************************/
556 /* Compute style flags. */
559 if ( has_outline == TRUE && face->os2.version != 0xFFFF )
561 /* we have an OS/2 table; use the `fsSelection' field */
562 if ( face->os2.fsSelection & 1 )
563 flags |= FT_STYLE_FLAG_ITALIC;
565 if ( face->os2.fsSelection & 32 )
566 flags |= FT_STYLE_FLAG_BOLD;
570 /* this is an old Mac font, use the header field */
571 if ( face->header.Mac_Style & 1 )
572 flags |= FT_STYLE_FLAG_BOLD;
574 if ( face->header.Mac_Style & 2 )
575 flags |= FT_STYLE_FLAG_ITALIC;
578 root->style_flags = flags;
580 /*********************************************************************/
582 /* Polish the charmaps. */
584 /* Try to set the charmap encoding according to the platform & */
585 /* encoding ID of each charmap. */
588 tt_face_build_cmaps( face ); /* ignore errors */
591 /* set the encoding fields */
596 for ( m = 0; m < root->num_charmaps; m++ )
598 FT_CharMap charmap = root->charmaps[m];
601 charmap->encoding = sfnt_find_encoding( charmap->platform_id,
602 charmap->encoding_id );
605 if ( root->charmap == NULL &&
606 charmap->encoding == FT_ENCODING_UNICODE )
608 /* set 'root->charmap' to the first Unicode encoding we find */
609 root->charmap = charmap;
616 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
618 if ( face->num_sbit_strikes )
623 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
626 /* XXX: I don't know criteria whether layout is horizontal */
628 if ( has_outline.... )
631 root->face_flags |= FT_FACE_FLAG_VERTICAL;
634 root->num_fixed_sizes = face->num_sbit_strikes;
636 if ( FT_NEW_ARRAY( root->available_sizes, face->num_sbit_strikes ) )
639 for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
641 root->available_sizes[n].width =
642 face->sbit_strikes[n].x_ppem;
644 root->available_sizes[n].height =
645 face->sbit_strikes[n].y_ppem;
650 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
653 root->num_fixed_sizes = 0;
654 root->available_sizes = 0;
657 /*********************************************************************/
659 /* Set up metrics. */
661 if ( has_outline == TRUE )
663 /* XXX What about if outline header is missing */
664 /* (e.g. sfnt wrapped outline)? */
665 root->bbox.xMin = face->header.xMin;
666 root->bbox.yMin = face->header.yMin;
667 root->bbox.xMax = face->header.xMax;
668 root->bbox.yMax = face->header.yMax;
669 root->units_per_EM = face->header.Units_Per_EM;
672 /* XXX: Computing the ascender/descender/height is very different */
673 /* from what the specification tells you. Apparently, we */
674 /* must be careful because */
676 /* - not all fonts have an OS/2 table; in this case, we take */
677 /* the values in the horizontal header. However, these */
678 /* values very often are not reliable. */
680 /* - otherwise, the correct typographic values are in the */
681 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */
683 /* However, certains fonts have these fields set to 0. */
684 /* Rather, they have usWinAscent & usWinDescent correctly */
685 /* set (but with different values). */
687 /* As an example, Arial Narrow is implemented through four */
688 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
690 /* Strangely, all fonts have the same values in their */
691 /* sTypoXXX fields, except ARIALNB which sets them to 0. */
693 /* On the other hand, they all have different */
694 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */
695 /* table cannot be used to compute the text height reliably! */
698 /* The ascender/descender/height are computed from the OS/2 table */
699 /* when found. Otherwise, they're taken from the horizontal */
703 root->ascender = face->horizontal.Ascender;
704 root->descender = face->horizontal.Descender;
706 root->height = (FT_Short)( root->ascender - root->descender +
707 face->horizontal.Line_Gap );
709 /* if the line_gap is 0, we add an extra 15% to the text height -- */
710 /* this computation is based on various versions of Times New Roman */
711 if ( face->horizontal.Line_Gap == 0 )
712 root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
716 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
717 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */
718 if ( face->os2.version != 0xFFFF && root->ascender )
723 root->ascender = face->os2.sTypoAscender;
724 root->descender = -face->os2.sTypoDescender;
726 height = root->ascender + root->descender + face->os2.sTypoLineGap;
727 if ( height > root->height )
728 root->height = height;
733 root->max_advance_width = face->horizontal.advance_Width_Max;
735 root->max_advance_height = (FT_Short)( face->vertical_info
736 ? face->vertical.advance_Height_Max
739 root->underline_position = face->postscript.underlinePosition;
740 root->underline_thickness = face->postscript.underlineThickness;
742 /* root->max_points -- already set up */
743 /* root->max_contours -- already set up */
756 sfnt_done_face( TT_Face face )
758 FT_Memory memory = face->root.memory;
759 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
764 /* destroy the postscript names table if it is loaded */
765 if ( sfnt->free_psnames )
766 sfnt->free_psnames( face );
768 /* destroy the embedded bitmaps table if it is loaded */
769 if ( sfnt->free_sbits )
770 sfnt->free_sbits( face );
773 /* freeing the kerning table */
774 FT_FREE( face->kern_pairs );
775 face->num_kern_pairs = 0;
777 /* freeing the collection table */
778 FT_FREE( face->ttc_header.offsets );
779 face->ttc_header.count = 0;
781 /* freeing table directory */
782 FT_FREE( face->dir_tables );
783 face->num_tables = 0;
786 FT_Stream stream = FT_FACE_STREAM( face );
789 /* simply release the 'cmap' table frame */
790 FT_FRAME_RELEASE( face->cmap_table );
794 /* freeing the horizontal metrics */
795 FT_FREE( face->horizontal.long_metrics );
796 FT_FREE( face->horizontal.short_metrics );
798 /* freeing the vertical ones, if any */
799 if ( face->vertical_info )
801 FT_FREE( face->vertical.long_metrics );
802 FT_FREE( face->vertical.short_metrics );
803 face->vertical_info = 0;
806 /* freeing the gasp table */
807 FT_FREE( face->gasp.gaspRanges );
808 face->gasp.numRanges = 0;
810 /* freeing the name table */
811 sfnt->free_names( face );
813 /* freeing the hdmx table */
814 sfnt->free_hdmx( face );
816 /* freeing family and style name */
817 FT_FREE( face->root.family_name );
818 FT_FREE( face->root.style_name );
820 /* freeing sbit size table */
821 face->root.num_fixed_sizes = 0;
822 if ( face->root.available_sizes )
823 FT_FREE( face->root.available_sizes );