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

Last change on this file since 182 was 182, checked in by Eugene Romanenko, 15 years ago

freetype update to version 2.3.0

File size: 35.5 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  sfobjs.c                                                               */
4/*                                                                         */
5/*    SFNT object management (base).                                       */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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          error = SFNT_Err_Horiz_Header_Missing;
623      }
624
625      if ( error )
626        goto Exit;
627
628      /* try to load the `vhea' and `vmtx' tables */
629      LOADM_( hhea, 1 );
630      if ( !error )
631      {
632        LOADM_( hmtx, 1 );
633        if ( !error )
634          face->vertical_info = 1;
635      }
636
637      if ( error && error != SFNT_Err_Table_Missing )
638        goto Exit;
639
640      LOAD_( os2 );
641      if ( error )
642      {
643        if ( error != SFNT_Err_Table_Missing )
644          goto Exit;
645
646        face->os2.version = 0xFFFFU;
647      }
648
649    }
650
651    /* the optional tables */
652
653    /* embedded bitmap support. */
654    if ( sfnt->load_eblc )
655    {
656      LOAD_( eblc );
657      if ( error )
658      {
659        /* return an error if this font file has no outlines */
660        if ( error == SFNT_Err_Table_Missing && has_outline )
661          error = SFNT_Err_Ok;
662        else
663          goto Exit;
664      }
665    }
666
667    LOAD_( pclt );
668    if ( error )
669    {
670      if ( error != SFNT_Err_Table_Missing )
671        goto Exit;
672
673      face->pclt.Version = 0;
674    }
675
676    /* consider the kerning and gasp tables as optional */
677    LOAD_( gasp );
678    LOAD_( kern );
679
680    error = SFNT_Err_Ok;
681
682    face->root.num_glyphs = face->max_profile.numGlyphs;
683
684    face->root.family_name = tt_face_get_name( face,
685                                               TT_NAME_ID_PREFERRED_FAMILY );
686    if ( !face->root.family_name )
687      face->root.family_name = tt_face_get_name( face,
688                                                 TT_NAME_ID_FONT_FAMILY );
689
690    face->root.style_name = tt_face_get_name( face,
691                                              TT_NAME_ID_PREFERRED_SUBFAMILY );
692    if ( !face->root.style_name )
693      face->root.style_name  = tt_face_get_name( face,
694                                                 TT_NAME_ID_FONT_SUBFAMILY );
695
696    /* now set up root fields */
697    {
698      FT_Face    root = &face->root;
699      FT_Int32   flags = root->face_flags;
700
701
702      /*********************************************************************/
703      /*                                                                   */
704      /* Compute face flags.                                               */
705      /*                                                                   */
706      if ( has_outline == TRUE )
707        flags |= FT_FACE_FLAG_SCALABLE;   /* scalable outlines */
708
709      /* The sfnt driver only supports bitmap fonts natively, thus we */
710      /* don't set FT_FACE_FLAG_HINTER.                               */
711      flags |= FT_FACE_FLAG_SFNT       |  /* SFNT file format  */
712               FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
713
714#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
715      if ( psnames_error == SFNT_Err_Ok &&
716           face->postscript.FormatType != 0x00030000L )
717        flags |= FT_FACE_FLAG_GLYPH_NAMES;
718#endif
719
720      /* fixed width font? */
721      if ( face->postscript.isFixedPitch )
722        flags |= FT_FACE_FLAG_FIXED_WIDTH;
723
724      /* vertical information? */
725      if ( face->vertical_info )
726        flags |= FT_FACE_FLAG_VERTICAL;
727
728      /* kerning available ? */
729      if ( TT_FACE_HAS_KERNING( face ) )
730        flags |= FT_FACE_FLAG_KERNING;
731
732#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
733      /* Don't bother to load the tables unless somebody asks for them. */
734      /* No need to do work which will (probably) not be used.          */
735      if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
736           tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
737           tt_face_lookup_table( face, TTAG_gvar ) != 0 )
738        flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
739#endif
740
741      root->face_flags = flags;
742
743      /*********************************************************************/
744      /*                                                                   */
745      /* Compute style flags.                                              */
746      /*                                                                   */
747      flags = 0;
748      if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
749      {
750        /* we have an OS/2 table; use the `fsSelection' field */
751        if ( face->os2.fsSelection & 1 )
752          flags |= FT_STYLE_FLAG_ITALIC;
753
754        if ( face->os2.fsSelection & 32 )
755          flags |= FT_STYLE_FLAG_BOLD;
756      }
757      else
758      {
759        /* this is an old Mac font, use the header field */
760        if ( face->header.Mac_Style & 1 )
761          flags |= FT_STYLE_FLAG_BOLD;
762
763        if ( face->header.Mac_Style & 2 )
764          flags |= FT_STYLE_FLAG_ITALIC;
765      }
766
767      root->style_flags = flags;
768
769      /*********************************************************************/
770      /*                                                                   */
771      /* Polish the charmaps.                                              */
772      /*                                                                   */
773      /*   Try to set the charmap encoding according to the platform &     */
774      /*   encoding ID of each charmap.                                    */
775      /*                                                                   */
776
777      tt_face_build_cmaps( face );  /* ignore errors */
778
779
780      /* set the encoding fields */
781      {
782        FT_Int  m;
783
784
785        for ( m = 0; m < root->num_charmaps; m++ )
786        {
787          FT_CharMap  charmap = root->charmaps[m];
788
789
790          charmap->encoding = sfnt_find_encoding( charmap->platform_id,
791                                                  charmap->encoding_id );
792
793#if 0
794          if ( root->charmap     == NULL &&
795               charmap->encoding == FT_ENCODING_UNICODE )
796          {
797            /* set 'root->charmap' to the first Unicode encoding we find */
798            root->charmap = charmap;
799          }
800#endif
801        }
802      }
803
804
805      /*********************************************************************/
806      /*                                                                   */
807      /*  Set up metrics.                                                  */
808      /*                                                                   */
809      if ( has_outline == TRUE )
810      {
811        /* XXX What about if outline header is missing */
812        /*     (e.g. sfnt wrapped bitmap)?             */
813        root->bbox.xMin    = face->header.xMin;
814        root->bbox.yMin    = face->header.yMin;
815        root->bbox.xMax    = face->header.xMax;
816        root->bbox.yMax    = face->header.yMax;
817        root->units_per_EM = face->header.Units_Per_EM;
818
819
820        /* XXX: Computing the ascender/descender/height is very different */
821        /*      from what the specification tells you.  Apparently, we    */
822        /*      must be careful because                                   */
823        /*                                                                */
824        /*      - not all fonts have an OS/2 table; in this case, we take */
825        /*        the values in the horizontal header.  However, these    */
826        /*        values very often are not reliable.                     */
827        /*                                                                */
828        /*      - otherwise, the correct typographic values are in the    */
829        /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
830        /*                                                                */
831        /*        However, certains fonts have these fields set to 0.     */
832        /*        Rather, they have usWinAscent & usWinDescent correctly  */
833        /*        set (but with different values).                        */
834        /*                                                                */
835        /*      As an example, Arial Narrow is implemented through four   */
836        /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
837        /*                                                                */
838        /*      Strangely, all fonts have the same values in their        */
839        /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
840        /*                                                                */
841        /*      On the other hand, they all have different                */
842        /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
843        /*      table cannot be used to compute the text height reliably! */
844        /*                                                                */
845
846        /* The ascender/descender/height are computed from the OS/2 table */
847        /* when found.  Otherwise, they're taken from the horizontal      */
848        /* header.                                                        */
849        /*                                                                */
850
851        root->ascender  = face->horizontal.Ascender;
852        root->descender = face->horizontal.Descender;
853
854        root->height    = (FT_Short)( root->ascender - root->descender +
855                                      face->horizontal.Line_Gap );
856
857#if 0
858        /* if the line_gap is 0, we add an extra 15% to the text height --  */
859        /* this computation is based on various versions of Times New Roman */
860        if ( face->horizontal.Line_Gap == 0 )
861          root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
862#endif
863
864#if 0
865
866        /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
867        /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
868        if ( face->os2.version != 0xFFFFU && root->ascender )
869        {
870          FT_Int  height;
871
872
873          root->ascender  =  face->os2.sTypoAscender;
874          root->descender = -face->os2.sTypoDescender;
875
876          height = root->ascender + root->descender + face->os2.sTypoLineGap;
877          if ( height > root->height )
878            root->height = height;
879        }
880
881#endif /* 0 */
882
883        root->max_advance_width   = face->horizontal.advance_Width_Max;
884
885        root->max_advance_height  = (FT_Short)( face->vertical_info
886                                      ? face->vertical.advance_Height_Max
887                                      : root->height );
888
889        root->underline_position  = face->postscript.underlinePosition;
890        root->underline_thickness = face->postscript.underlineThickness;
891      }
892
893#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
894
895      /*
896       *  Now allocate the root array of FT_Bitmap_Size records and
897       *  populate them.  Unfortunately, it isn't possible to indicate bit
898       *  depths in the FT_Bitmap_Size record.  This is a design error.
899       */
900      {
901        FT_UInt  i, count;
902
903
904#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
905        count = face->sbit_num_strikes;
906#else
907        count = (FT_UInt)face->num_sbit_strikes;
908#endif
909
910        if ( count > 0 )
911        {
912          FT_Memory        memory   = face->root.stream->memory;
913          FT_UShort        em_size  = face->header.Units_Per_EM;
914          FT_Short         avgwidth = face->os2.xAvgCharWidth;
915          FT_Size_Metrics  metrics;
916
917
918          if ( em_size == 0 || face->os2.version == 0xFFFFU )
919          {
920            avgwidth = 0;
921            em_size = 1;
922          }
923
924          if ( FT_NEW_ARRAY( root->available_sizes, count ) )
925            goto Exit;
926
927          for ( i = 0; i < count; i++ )
928          {
929            FT_Bitmap_Size*  bsize = root->available_sizes + i;
930
931
932            error = sfnt->load_strike_metrics( face, i, &metrics );
933            if ( error )
934              goto Exit;
935
936            bsize->height = (FT_Short)( metrics.height >> 6 );
937            bsize->width = (FT_Short)(
938                ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size );
939
940            bsize->x_ppem = metrics.x_ppem << 6;
941            bsize->y_ppem = metrics.y_ppem << 6;
942
943            /* assume 72dpi */
944            bsize->size   = metrics.y_ppem << 6;
945          }
946
947          root->face_flags     |= FT_FACE_FLAG_FIXED_SIZES;
948          root->num_fixed_sizes = (FT_Int)count;
949        }
950      }
951
952#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
953
954    }
955
956  Exit:
957    FT_TRACE2(( "sfnt_load_face: done\n" ));
958
959    return error;
960  }
961
962
963#undef LOAD_
964#undef LOADM_
965
966
967  FT_LOCAL_DEF( void )
968  sfnt_done_face( TT_Face  face )
969  {
970    FT_Memory     memory = face->root.memory;
971    SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
972
973
974    if ( sfnt )
975    {
976      /* destroy the postscript names table if it is loaded */
977      if ( sfnt->free_psnames )
978        sfnt->free_psnames( face );
979
980      /* destroy the embedded bitmaps table if it is loaded */
981      if ( sfnt->free_eblc )
982        sfnt->free_eblc( face );
983    }
984
985#ifdef TT_CONFIG_OPTION_BDF
986    /* freeing the embedded BDF properties */
987    tt_face_free_bdf_props( face );
988#endif
989
990    /* freeing the kerning table */
991    tt_face_done_kern( face );
992
993    /* freeing the collection table */
994    FT_FREE( face->ttc_header.offsets );
995    face->ttc_header.count = 0;
996
997    /* freeing table directory */
998    FT_FREE( face->dir_tables );
999    face->num_tables = 0;
1000
1001    {
1002      FT_Stream  stream = FT_FACE_STREAM( face );
1003
1004
1005      /* simply release the 'cmap' table frame */
1006      FT_FRAME_RELEASE( face->cmap_table );
1007      face->cmap_size = 0;
1008    }
1009
1010    /* freeing the horizontal metrics */
1011#if !defined FT_CONFIG_OPTION_OLD_INTERNALS
1012    {
1013      FT_Stream  stream = FT_FACE_STREAM( face );
1014
1015
1016      FT_FRAME_RELEASE( face->horz_metrics );
1017      FT_FRAME_RELEASE( face->vert_metrics );
1018      face->horz_metrics_size = 0;
1019      face->vert_metrics_size = 0;
1020    }
1021#else
1022    FT_FREE( face->horizontal.long_metrics );
1023    FT_FREE( face->horizontal.short_metrics );
1024#endif
1025
1026    /* freeing the vertical ones, if any */
1027    if ( face->vertical_info )
1028    {
1029      FT_FREE( face->vertical.long_metrics  );
1030      FT_FREE( face->vertical.short_metrics );
1031      face->vertical_info = 0;
1032    }
1033
1034    /* freeing the gasp table */
1035    FT_FREE( face->gasp.gaspRanges );
1036    face->gasp.numRanges = 0;
1037
1038    /* freeing the name table */
1039    sfnt->free_name( face );
1040
1041    /* freeing family and style name */
1042    FT_FREE( face->root.family_name );
1043    FT_FREE( face->root.style_name );
1044
1045    /* freeing sbit size table */
1046    FT_FREE( face->root.available_sizes );
1047    face->root.num_fixed_sizes = 0;
1048
1049    FT_FREE( face->postscript_name );
1050
1051    face->sfnt = 0;
1052  }
1053
1054
1055/* END */
Note: See TracBrowser for help on using the repository browser.