source: trunk/poppler/freetype2/src/sfnt/sfobjs.c @ 251

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 37.7 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  sfobjs.c                                                               */
4/*                                                                         */
5/*    SFNT object management (base).                                       */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
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.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18
19#include <ft2build.h>
20#include "sfobjs.h"
21#include "ttload.h"
22#include "ttcmap.h"
23#include "ttkern.h"
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 "sferrors.h"
30
31#ifdef TT_CONFIG_OPTION_BDF
32#include "ttbdf.h"
33#endif
34
35
36  /*************************************************************************/
37  /*                                                                       */
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.                                            */
41  /*                                                                       */
42#undef  FT_COMPONENT
43#define FT_COMPONENT  trace_sfobjs
44
45
46
47  /* convert a UTF-16 name entry to ASCII */
48  static FT_String*
49  tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
50                                  FT_Memory     memory )
51  {
52    FT_String*  string;
53    FT_UInt     len, code, n;
54    FT_Byte*    read = (FT_Byte*)entry->string;
55    FT_Error    error;
56
57
58    len = (FT_UInt)entry->stringLength / 2;
59
60    if ( FT_NEW_ARRAY( string, len + 1 ) )
61      return NULL;
62
63    for ( n = 0; n < len; n++ )
64    {
65      code = FT_NEXT_USHORT( read );
66      if ( code < 32 || code > 127 )
67        code = '?';
68
69      string[n] = (char)code;
70    }
71
72    string[len] = 0;
73
74    return string;
75  }
76
77
78  /* convert an Apple Roman or symbol name entry to ASCII */
79  static FT_String*
80  tt_name_entry_ascii_from_other( TT_NameEntry  entry,
81                                  FT_Memory     memory )
82  {
83    FT_String*  string;
84    FT_UInt     len, code, n;
85    FT_Byte*    read = (FT_Byte*)entry->string;
86    FT_Error    error;
87
88
89    len = (FT_UInt)entry->stringLength;
90
91    if ( FT_NEW_ARRAY( string, len + 1 ) )
92      return NULL;
93
94    for ( n = 0; n < len; n++ )
95    {
96      code = *read++;
97      if ( code < 32 || code > 127 )
98        code = '?';
99
100      string[n] = (char)code;
101    }
102
103    string[len] = 0;
104
105    return string;
106  }
107
108
109  typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
110                                                   FT_Memory     memory );
111
112
113  /*************************************************************************/
114  /*                                                                       */
115  /* <Function>                                                            */
116  /*    tt_face_get_name                                                   */
117  /*                                                                       */
118  /* <Description>                                                         */
119  /*    Returns a given ENGLISH name record in ASCII.                      */
120  /*                                                                       */
121  /* <Input>                                                               */
122  /*    face   :: A handle to the source face object.                      */
123  /*                                                                       */
124  /*    nameid :: The name id of the name record to return.                */
125  /*                                                                       */
126  /* <Return>                                                              */
127  /*    Character string.  NULL if no name is present.                     */
128  /*                                                                       */
129  static FT_String*
130  tt_face_get_name( TT_Face    face,
131                    FT_UShort  nameid )
132  {
133    FT_Memory         memory = face->root.memory;
134    FT_String*        result = NULL;
135    FT_UShort         n;
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;
142
143    FT_Bool           is_english = 0;
144
145    TT_NameEntry_ConvertFunc  convert;
146
147
148    rec = face->name_table.names;
149    for ( n = 0; n < face->num_names; n++, rec++ )
150    {
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.                                        */
155      /*                                                                 */
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).     */
159      /*                                                                 */
160      if ( rec->nameID == nameid && rec->stringLength > 0 )
161      {
162        switch ( rec->platformID )
163        {
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        */
168          /* available.                                                */
169          /*                                                           */
170          found_unicode = n;
171          break;
172
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.                       */
177          /*                                                             */
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;
182          break;
183
184        case TT_PLATFORM_MICROSOFT:
185          /* we only take a non-English name when there is nothing */
186          /* else available in the font                            */
187          /*                                                       */
188          if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
189          {
190            switch ( rec->encodingID )
191            {
192            case TT_MS_ID_SYMBOL_CS:
193            case TT_MS_ID_UNICODE_CS:
194            case TT_MS_ID_UCS_4:
195              is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
196              found_win  = n;
197              break;
198
199            default:
200              ;
201            }
202          }
203          break;
204
205        default:
206          ;
207        }
208      }
209    }
210
211    found_apple = found_apple_roman;
212    if ( found_apple_english >= 0 )
213      found_apple = found_apple_english;
214
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)                                   */
218    /*                                                                    */
219    convert = NULL;
220    if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
221    {
222      rec = face->name_table.names + found_win;
223      switch ( rec->encodingID )
224      {
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;
229        break;
230
231      case TT_MS_ID_UCS_4:
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   */
236        /* charmaps).                                                      */
237        convert = tt_name_entry_ascii_from_utf16;
238        break;
239
240      default:
241        ;
242      }
243    }
244    else if ( found_apple >= 0 )
245    {
246      rec     = face->name_table.names + found_apple;
247      convert = tt_name_entry_ascii_from_other;
248    }
249    else if ( found_unicode >= 0 )
250    {
251      rec     = face->name_table.names + found_unicode;
252      convert = tt_name_entry_ascii_from_utf16;
253    }
254
255    if ( rec && convert )
256    {
257      if ( rec->string == NULL )
258      {
259        FT_Error   error  = SFNT_Err_Ok;
260        FT_Stream  stream = face->name_table.stream;
261
262        FT_UNUSED( error );
263
264
265        if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
266             FT_STREAM_SEEK( rec->stringOffset )              ||
267             FT_STREAM_READ( rec->string, rec->stringLength ) )
268        {
269          FT_FREE( rec->string );
270          rec->stringLength = 0;
271          result            = NULL;
272          goto Exit;
273        }
274      }
275
276      result = convert( rec, memory );
277    }
278
279  Exit:
280    return result;
281  }
282
283
284  static FT_Encoding
285  sfnt_find_encoding( int  platform_id,
286                      int  encoding_id )
287  {
288    typedef struct  TEncoding_
289    {
290      int          platform_id;
291      int          encoding_id;
292      FT_Encoding  encoding;
293
294    } TEncoding;
295
296    static
297    const TEncoding  tt_encodings[] =
298    {
299      { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
300
301      { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
302
303      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
304
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 }
313    };
314
315    const TEncoding  *cur, *limit;
316
317
318    cur   = tt_encodings;
319    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
320
321    for ( ; cur < limit; cur++ )
322    {
323      if ( cur->platform_id == platform_id )
324      {
325        if ( cur->encoding_id == encoding_id ||
326             cur->encoding_id == -1          )
327          return cur->encoding;
328      }
329    }
330
331    return FT_ENCODING_NONE;
332  }
333
334
335  /* Fill in face->ttc_header.  If the font is not a TTC, it is */
336  /* synthesized into a TTC with one offset table.              */
337  static FT_Error
338  sfnt_open_font( FT_Stream  stream,
339                  TT_Face    face )
340  {
341    FT_Memory  memory = stream->memory;
342    FT_Error   error;
343    FT_ULong   tag, offset;
344
345    static const FT_Frame_Field  ttc_header_fields[] =
346    {
347#undef  FT_STRUCTURE
348#define FT_STRUCTURE  TTC_HeaderRec
349
350      FT_FRAME_START( 8 ),
351        FT_FRAME_LONG( version ),
352        FT_FRAME_LONG( count   ),
353      FT_FRAME_END
354    };
355
356
357    face->ttc_header.tag     = 0;
358    face->ttc_header.version = 0;
359    face->ttc_header.count   = 0;
360
361    offset = FT_STREAM_POS();
362
363    if ( FT_READ_ULONG( tag ) )
364      return error;
365
366    if ( tag != 0x00010000UL                      &&
367         tag != TTAG_ttcf                         &&
368         tag != FT_MAKE_TAG( 'O', 'T', 'T', 'O' ) &&
369         tag != TTAG_true                         &&
370         tag != 0x00020000UL                      )
371      return SFNT_Err_Unknown_File_Format;
372
373    face->ttc_header.tag = TTAG_ttcf;
374
375    if ( tag == TTAG_ttcf )
376    {
377      FT_Int  n;
378
379
380      FT_TRACE3(( "sfnt_open_font: file is a collection\n" ));
381
382      if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
383        return error;
384
385      /* now read the offsets of each font in the file */
386      if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
387        return error;
388
389      if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) )
390        return error;
391
392      for ( n = 0; n < face->ttc_header.count; n++ )
393        face->ttc_header.offsets[n] = FT_GET_ULONG();
394
395      FT_FRAME_EXIT();
396    }
397    else
398    {
399      FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" ));
400
401      face->ttc_header.version = 1 << 16;
402      face->ttc_header.count   = 1;
403
404      if ( FT_NEW( face->ttc_header.offsets) )
405        return error;
406
407      face->ttc_header.offsets[0] = offset;
408    }
409
410    return error;
411  }
412
413
414  FT_LOCAL_DEF( FT_Error )
415  sfnt_init_face( FT_Stream      stream,
416                  TT_Face        face,
417                  FT_Int         face_index,
418                  FT_Int         num_params,
419                  FT_Parameter*  params )
420  {
421    FT_Error        error;
422    FT_Library      library = face->root.driver->root.library;
423    SFNT_Service    sfnt;
424
425
426    /* for now, parameters are unused */
427    FT_UNUSED( num_params );
428    FT_UNUSED( params );
429
430
431    sfnt = (SFNT_Service)face->sfnt;
432    if ( !sfnt )
433    {
434      sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
435      if ( !sfnt )
436        return SFNT_Err_Invalid_File_Format;
437
438      face->sfnt       = sfnt;
439      face->goto_table = sfnt->goto_table;
440    }
441
442    FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
443
444    error = sfnt_open_font( stream, face );
445    if ( error )
446      return error;
447
448    FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index ));
449
450    if ( face_index < 0 )
451      face_index = 0;
452
453    if ( face_index >= face->ttc_header.count )
454        return SFNT_Err_Bad_Argument;
455
456    if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
457      return error;
458
459    /* check that we have a valid TrueType file */
460    error = sfnt->load_font_dir( face, stream );
461    if ( error )
462      return error;
463
464    face->root.num_faces = face->ttc_header.count;
465
466    return error;
467  }
468
469
470#define LOAD_( x )                                            \
471  do {                                                        \
472    FT_TRACE2(( "`" #x "' " ));                               \
473    FT_TRACE3(( "-->\n" ));                                   \
474                                                              \
475    error = sfnt->load_##x( face, stream );                   \
476                                                              \
477    FT_TRACE2(( "%s\n", ( !error )                            \
478                        ? "loaded"                            \
479                        : ( error == SFNT_Err_Table_Missing ) \
480                          ? "missing"                         \
481                          : "failed to load" ));              \
482    FT_TRACE3(( "\n" ));                                      \
483  } while ( 0 )
484
485#define LOADM_( x, vertical )                                 \
486  do {                                                        \
487    FT_TRACE2(( "`%s" #x "' ",                                \
488                vertical ? "vertical " : "" ));               \
489    FT_TRACE3(( "-->\n" ));                                   \
490                                                              \
491    error = sfnt->load_##x( face, stream, vertical );         \
492                                                              \
493    FT_TRACE2(( "%s\n", ( !error )                            \
494                        ? "loaded"                            \
495                        : ( error == SFNT_Err_Table_Missing ) \
496                          ? "missing"                         \
497                          : "failed to load" ));              \
498    FT_TRACE3(( "\n" ));                                      \
499  } while ( 0 )
500
501
502  FT_LOCAL_DEF( FT_Error )
503  sfnt_load_face( FT_Stream      stream,
504                  TT_Face        face,
505                  FT_Int         face_index,
506                  FT_Int         num_params,
507                  FT_Parameter*  params )
508  {
509    FT_Error      error, psnames_error;
510    FT_Bool       has_outline;
511    FT_Bool       is_apple_sbit;
512
513    SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
514
515    FT_UNUSED( face_index );
516    FT_UNUSED( num_params );
517    FT_UNUSED( params );
518
519
520    /* Load tables */
521
522    /* We now support two SFNT-based bitmapped font formats.  They */
523    /* are recognized easily as they do not include a `glyf'       */
524    /* table.                                                      */
525    /*                                                             */
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  */
530    /* missing).                                                   */
531    /*                                                             */
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.                                */
535    /*                                                             */
536
537    FT_TRACE2(( "sfnt_load_face: %08p\n\n", face ));
538
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 );
544#else
545    has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
546                             tt_face_lookup_table( face, TTAG_CFF )  != 0 );
547#endif
548
549    is_apple_sbit = 0;
550
551    /* if this font doesn't contain outlines, we try to load */
552    /* a `bhed' table                                        */
553    if ( !has_outline && sfnt->load_bhed )
554    {
555      LOAD_( bhed );
556      is_apple_sbit = FT_BOOL( !error );
557    }
558
559    /* load the font header (`head' table) if this isn't an Apple */
560    /* sbit font file                                             */
561    if ( !is_apple_sbit )
562    {
563      LOAD_( head );
564      if ( error )
565        goto Exit;
566    }
567
568    if ( face->header.Units_Per_EM == 0 )
569    {
570      error = SFNT_Err_Invalid_Table;
571
572      goto Exit;
573    }
574
575    /* the following tables are often not present in embedded TrueType */
576    /* fonts within PDF documents, so don't check for them.            */
577    LOAD_( maxp );
578    LOAD_( cmap );
579
580    /* the following tables are optional in PCL fonts -- */
581    /* don't check for errors                            */
582    LOAD_( name );
583    LOAD_( post );
584    psnames_error = error;
585
586    /* do not load the metrics headers and tables if this is an Apple */
587    /* sbit font file                                                 */
588    if ( !is_apple_sbit )
589    {
590      /* load the `hhea' and `hmtx' tables */
591      LOADM_( hhea, 0 );
592      if ( !error )
593      {
594        LOADM_( hmtx, 0 );
595        if ( error == SFNT_Err_Table_Missing )
596        {
597          error = SFNT_Err_Hmtx_Table_Missing;
598
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->
604                 get_glyph_metrics                                 )
605          {
606            face->horizontal.number_Of_HMetrics = 0;
607            error = SFNT_Err_Ok;
608          }
609#endif
610        }
611      }
612      else if ( error == SFNT_Err_Table_Missing )
613      {
614        /* No `hhea' table necessary for SFNT Mac fonts. */
615        if ( face->format_tag == TTAG_true )
616        {
617          FT_TRACE2(( "This is an SFNT Mac font.\n" ));
618          has_outline = 0;
619          error = SFNT_Err_Ok;
620        }
621        else
622        {
623          error = SFNT_Err_Horiz_Header_Missing;
624
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->
630                 get_glyph_metrics                                 )
631          {
632            face->horizontal.number_Of_HMetrics = 0;
633            error = SFNT_Err_Ok;
634          }
635#endif
636
637        }
638      }
639
640      if ( error )
641        goto Exit;
642
643      /* try to load the `vhea' and `vmtx' tables */
644      LOADM_( hhea, 1 );
645      if ( !error )
646      {
647        LOADM_( hmtx, 1 );
648        if ( !error )
649          face->vertical_info = 1;
650      }
651
652      if ( error && error != SFNT_Err_Table_Missing )
653        goto Exit;
654
655      LOAD_( os2 );
656      if ( error )
657      {
658        if ( error != SFNT_Err_Table_Missing )
659          goto Exit;
660
661        face->os2.version = 0xFFFFU;
662      }
663
664    }
665
666    /* the optional tables */
667
668    /* embedded bitmap support. */
669    if ( sfnt->load_eblc )
670    {
671      LOAD_( eblc );
672      if ( error )
673      {
674        /* return an error if this font file has no outlines */
675        if ( error == SFNT_Err_Table_Missing && has_outline )
676          error = SFNT_Err_Ok;
677        else
678          goto Exit;
679      }
680    }
681
682    LOAD_( pclt );
683    if ( error )
684    {
685      if ( error != SFNT_Err_Table_Missing )
686        goto Exit;
687
688      face->pclt.Version = 0;
689    }
690
691    /* consider the kerning and gasp tables as optional */
692    LOAD_( gasp );
693    LOAD_( kern );
694
695    error = SFNT_Err_Ok;
696
697    face->root.num_glyphs = face->max_profile.numGlyphs;
698
699#if 0
700    /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes  */
701    /* a WWS-only font face.  `WWS' stands for `weight', width', and */
702    /* `slope', a term used by Microsoft's Windows Presentation      */
703    /* Foundation (WPF).  This flag will be introduced in version    */
704    /* 1.5 of the OpenType specification (but is already in use).    */
705
706    if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 )
707#endif
708    {
709      face->root.family_name =
710        tt_face_get_name( face, TT_NAME_ID_PREFERRED_FAMILY );
711      if ( !face->root.family_name )
712        face->root.family_name =
713          tt_face_get_name( face, TT_NAME_ID_FONT_FAMILY );
714
715      face->root.style_name =
716        tt_face_get_name( face, TT_NAME_ID_PREFERRED_SUBFAMILY );
717      if ( !face->root.style_name )
718        face->root.style_name =
719          tt_face_get_name( face, TT_NAME_ID_FONT_SUBFAMILY );
720    }
721#if 0
722    else
723    {
724      /* Support for `name' table ID 21 (WWS family) and 22 (WWS  */
725      /* subfamily) is still under consideration by Microsoft and */
726      /* not implemented in the current version of WPF.           */
727
728      face->root.family_name =
729        tt_face_get_name( face, TT_NAME_ID_WWS_FAMILY );
730      if ( !face->root.family_name )
731        face->root.family_name =
732          tt_face_get_name( face, TT_NAME_ID_PREFERRED_FAMILY );
733      if ( !face->root.family_name )
734        face->root.family_name =
735          tt_face_get_name( face, TT_NAME_ID_FONT_FAMILY );
736
737      face->root.style_name =
738        tt_face_get_name( face, TT_NAME_ID_WWS_SUBFAMILY );
739      if ( !face->root.style_name )
740        face->root.style_name =
741          tt_face_get_name( face, TT_NAME_ID_PREFERRED_SUBFAMILY );
742      if ( !face->root.style_name )
743        face->root.style_name =
744          tt_face_get_name( face, TT_NAME_ID_FONT_SUBFAMILY );
745    }
746#endif
747
748
749    /* now set up root fields */
750    {
751      FT_Face   root  = &face->root;
752      FT_Int32  flags = root->face_flags;
753
754
755      /*********************************************************************/
756      /*                                                                   */
757      /* Compute face flags.                                               */
758      /*                                                                   */
759      if ( has_outline == TRUE )
760        flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
761
762      /* The sfnt driver only supports bitmap fonts natively, thus we */
763      /* don't set FT_FACE_FLAG_HINTER.                               */
764      flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
765               FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
766
767#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
768      if ( psnames_error == SFNT_Err_Ok               &&
769           face->postscript.FormatType != 0x00030000L )
770        flags |= FT_FACE_FLAG_GLYPH_NAMES;
771#endif
772
773      /* fixed width font? */
774      if ( face->postscript.isFixedPitch )
775        flags |= FT_FACE_FLAG_FIXED_WIDTH;
776
777      /* vertical information? */
778      if ( face->vertical_info )
779        flags |= FT_FACE_FLAG_VERTICAL;
780
781      /* kerning available ? */
782      if ( TT_FACE_HAS_KERNING( face ) )
783        flags |= FT_FACE_FLAG_KERNING;
784
785#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
786      /* Don't bother to load the tables unless somebody asks for them. */
787      /* No need to do work which will (probably) not be used.          */
788      if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
789           tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
790           tt_face_lookup_table( face, TTAG_gvar ) != 0 )
791        flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
792#endif
793
794      root->face_flags = flags;
795
796      /*********************************************************************/
797      /*                                                                   */
798      /* Compute style flags.                                              */
799      /*                                                                   */
800
801      flags = 0;
802      if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
803      {
804        /* We have an OS/2 table; use the `fsSelection' field.  Bit 9   */
805        /* indicates an oblique font face.  This flag will be           */
806        /* introduced in version 1.5 of the OpenType specification (but */
807        /* is already in use).                                          */
808
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;
813
814        if ( face->os2.fsSelection & 32 )        /* bit 5 */
815          flags |= FT_STYLE_FLAG_BOLD;
816      }
817      else
818      {
819        /* this is an old Mac font, use the header field */
820        if ( face->header.Mac_Style & 1 )
821          flags |= FT_STYLE_FLAG_BOLD;
822
823        if ( face->header.Mac_Style & 2 )
824          flags |= FT_STYLE_FLAG_ITALIC;
825      }
826
827      root->style_flags = flags;
828
829      /*********************************************************************/
830      /*                                                                   */
831      /* Polish the charmaps.                                              */
832      /*                                                                   */
833      /*   Try to set the charmap encoding according to the platform &     */
834      /*   encoding ID of each charmap.                                    */
835      /*                                                                   */
836
837      tt_face_build_cmaps( face );  /* ignore errors */
838
839
840      /* set the encoding fields */
841      {
842        FT_Int  m;
843
844
845        for ( m = 0; m < root->num_charmaps; m++ )
846        {
847          FT_CharMap  charmap = root->charmaps[m];
848
849
850          charmap->encoding = sfnt_find_encoding( charmap->platform_id,
851                                                  charmap->encoding_id );
852
853#if 0
854          if ( root->charmap     == NULL &&
855               charmap->encoding == FT_ENCODING_UNICODE )
856          {
857            /* set 'root->charmap' to the first Unicode encoding we find */
858            root->charmap = charmap;
859          }
860#endif
861        }
862      }
863
864
865      /*********************************************************************/
866      /*                                                                   */
867      /*  Set up metrics.                                                  */
868      /*                                                                   */
869      if ( has_outline == TRUE )
870      {
871        /* XXX What about if outline header is missing */
872        /*     (e.g. sfnt wrapped bitmap)?             */
873        root->bbox.xMin    = face->header.xMin;
874        root->bbox.yMin    = face->header.yMin;
875        root->bbox.xMax    = face->header.xMax;
876        root->bbox.yMax    = face->header.yMax;
877        root->units_per_EM = face->header.Units_Per_EM;
878
879
880        /* XXX: Computing the ascender/descender/height is very different */
881        /*      from what the specification tells you.  Apparently, we    */
882        /*      must be careful because                                   */
883        /*                                                                */
884        /*      - not all fonts have an OS/2 table; in this case, we take */
885        /*        the values in the horizontal header.  However, these    */
886        /*        values very often are not reliable.                     */
887        /*                                                                */
888        /*      - otherwise, the correct typographic values are in the    */
889        /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
890        /*                                                                */
891        /*        However, certain fonts have these fields set to 0.      */
892        /*        Rather, they have usWinAscent & usWinDescent correctly  */
893        /*        set (but with different values).                        */
894        /*                                                                */
895        /*      As an example, Arial Narrow is implemented through four   */
896        /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
897        /*                                                                */
898        /*      Strangely, all fonts have the same values in their        */
899        /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
900        /*                                                                */
901        /*      On the other hand, they all have different                */
902        /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
903        /*      table cannot be used to compute the text height reliably! */
904        /*                                                                */
905
906        /* The ascender/descender/height are computed from the OS/2 table */
907        /* when found.  Otherwise, they're taken from the horizontal      */
908        /* header.                                                        */
909        /*                                                                */
910
911        root->ascender  = face->horizontal.Ascender;
912        root->descender = face->horizontal.Descender;
913
914        root->height    = (FT_Short)( root->ascender - root->descender +
915                                      face->horizontal.Line_Gap );
916
917#if 0
918        /* if the line_gap is 0, we add an extra 15% to the text height --  */
919        /* this computation is based on various versions of Times New Roman */
920        if ( face->horizontal.Line_Gap == 0 )
921          root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
922#endif
923
924#if 0
925
926        /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
927        /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
928        if ( face->os2.version != 0xFFFFU && root->ascender )
929        {
930          FT_Int  height;
931
932
933          root->ascender  =  face->os2.sTypoAscender;
934          root->descender = -face->os2.sTypoDescender;
935
936          height = root->ascender + root->descender + face->os2.sTypoLineGap;
937          if ( height > root->height )
938            root->height = height;
939        }
940
941#endif /* 0 */
942
943        root->max_advance_width   = face->horizontal.advance_Width_Max;
944
945        root->max_advance_height  = (FT_Short)( face->vertical_info
946                                      ? face->vertical.advance_Height_Max
947                                      : root->height );
948
949        root->underline_position  = face->postscript.underlinePosition;
950        root->underline_thickness = face->postscript.underlineThickness;
951      }
952
953#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
954
955      /*
956       *  Now allocate the root array of FT_Bitmap_Size records and
957       *  populate them.  Unfortunately, it isn't possible to indicate bit
958       *  depths in the FT_Bitmap_Size record.  This is a design error.
959       */
960      {
961        FT_UInt  i, count;
962
963
964#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
965        count = face->sbit_num_strikes;
966#else
967        count = (FT_UInt)face->num_sbit_strikes;
968#endif
969
970        if ( count > 0 )
971        {
972          FT_Memory        memory   = face->root.stream->memory;
973          FT_UShort        em_size  = face->header.Units_Per_EM;
974          FT_Short         avgwidth = face->os2.xAvgCharWidth;
975          FT_Size_Metrics  metrics;
976
977
978          if ( em_size == 0 || face->os2.version == 0xFFFFU )
979          {
980            avgwidth = 0;
981            em_size = 1;
982          }
983
984          if ( FT_NEW_ARRAY( root->available_sizes, count ) )
985            goto Exit;
986
987          for ( i = 0; i < count; i++ )
988          {
989            FT_Bitmap_Size*  bsize = root->available_sizes + i;
990
991
992            error = sfnt->load_strike_metrics( face, i, &metrics );
993            if ( error )
994              goto Exit;
995
996            bsize->height = (FT_Short)( metrics.height >> 6 );
997            bsize->width = (FT_Short)(
998                ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
999
1000            bsize->x_ppem = metrics.x_ppem << 6;
1001            bsize->y_ppem = metrics.y_ppem << 6;
1002
1003            /* assume 72dpi */
1004            bsize->size   = metrics.y_ppem << 6;
1005          }
1006
1007          root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
1008          root->num_fixed_sizes = (FT_Int)count;
1009        }
1010      }
1011
1012#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1013
1014    }
1015
1016  Exit:
1017    FT_TRACE2(( "sfnt_load_face: done\n" ));
1018
1019    return error;
1020  }
1021
1022
1023#undef LOAD_
1024#undef LOADM_
1025
1026
1027  FT_LOCAL_DEF( void )
1028  sfnt_done_face( TT_Face  face )
1029  {
1030    FT_Memory     memory = face->root.memory;
1031    SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
1032
1033
1034    if ( sfnt )
1035    {
1036      /* destroy the postscript names table if it is loaded */
1037      if ( sfnt->free_psnames )
1038        sfnt->free_psnames( face );
1039
1040      /* destroy the embedded bitmaps table if it is loaded */
1041      if ( sfnt->free_eblc )
1042        sfnt->free_eblc( face );
1043    }
1044
1045#ifdef TT_CONFIG_OPTION_BDF
1046    /* freeing the embedded BDF properties */
1047    tt_face_free_bdf_props( face );
1048#endif
1049
1050    /* freeing the kerning table */
1051    tt_face_done_kern( face );
1052
1053    /* freeing the collection table */
1054    FT_FREE( face->ttc_header.offsets );
1055    face->ttc_header.count = 0;
1056
1057    /* freeing table directory */
1058    FT_FREE( face->dir_tables );
1059    face->num_tables = 0;
1060
1061    {
1062      FT_Stream  stream = FT_FACE_STREAM( face );
1063
1064
1065      /* simply release the 'cmap' table frame */
1066      FT_FRAME_RELEASE( face->cmap_table );
1067      face->cmap_size = 0;
1068    }
1069
1070    /* freeing the horizontal metrics */
1071#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
1072    {
1073      FT_Stream  stream = FT_FACE_STREAM( face );
1074
1075
1076      FT_FRAME_RELEASE( face->horz_metrics );
1077      FT_FRAME_RELEASE( face->vert_metrics );
1078      face->horz_metrics_size = 0;
1079      face->vert_metrics_size = 0;
1080    }
1081#else
1082    FT_FREE( face->horizontal.long_metrics );
1083    FT_FREE( face->horizontal.short_metrics );
1084#endif
1085
1086    /* freeing the vertical ones, if any */
1087    if ( face->vertical_info )
1088    {
1089      FT_FREE( face->vertical.long_metrics  );
1090      FT_FREE( face->vertical.short_metrics );
1091      face->vertical_info = 0;
1092    }
1093
1094    /* freeing the gasp table */
1095    FT_FREE( face->gasp.gaspRanges );
1096    face->gasp.numRanges = 0;
1097
1098    /* freeing the name table */
1099    if ( sfnt )
1100      sfnt->free_name( face );
1101
1102    /* freeing family and style name */
1103    FT_FREE( face->root.family_name );
1104    FT_FREE( face->root.style_name );
1105
1106    /* freeing sbit size table */
1107    FT_FREE( face->root.available_sizes );
1108    face->root.num_fixed_sizes = 0;
1109
1110    FT_FREE( face->postscript_name );
1111
1112    face->sfnt = 0;
1113  }
1114
1115
1116/* END */
Note: See TracBrowser for help on using the repository browser.