source: trunk/poppler/freetype-2.1.10/src/sfnt/sfobjs.c @ 2

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

First import

File size: 27.2 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  sfobjs.c                                                               */
4/*                                                                         */
5/*    SFNT object management (base).                                       */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005 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_TRUETYPE_IDS_H
26#include FT_TRUETYPE_TAGS_H
27#include FT_SERVICE_POSTSCRIPT_CMAPS_H
28#include "sferrors.h"
29
30
31  /*************************************************************************/
32  /*                                                                       */
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.                                            */
36  /*                                                                       */
37#undef  FT_COMPONENT
38#define FT_COMPONENT  trace_sfobjs
39
40
41
42  /* convert a UTF-16 name entry to ASCII */
43  static FT_String*
44  tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
45                                  FT_Memory     memory )
46  {
47    FT_String*  string;
48    FT_UInt     len, code, n;
49    FT_Byte*    read = (FT_Byte*)entry->string;
50
51
52    len = (FT_UInt)entry->stringLength / 2;
53
54    if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
55      return NULL;
56
57    for ( n = 0; n < len; n++ )
58    {
59      code = FT_NEXT_USHORT( read );
60      if ( code < 32 || code > 127 )
61        code = '?';
62
63      string[n] = (char)code;
64    }
65
66    string[len] = 0;
67
68    return string;
69  }
70
71
72  /* convert a UCS-4 name entry to ASCII */
73  static FT_String*
74  tt_name_entry_ascii_from_ucs4( TT_NameEntry  entry,
75                                 FT_Memory     memory )
76  {
77    FT_String*  string;
78    FT_UInt     len, code, n;
79    FT_Byte*    read = (FT_Byte*)entry->string;
80
81
82    len = (FT_UInt)entry->stringLength / 4;
83
84    if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
85      return NULL;
86
87    for ( n = 0; n < len; n++ )
88    {
89      code = (FT_UInt)FT_NEXT_ULONG( read );
90      if ( code < 32 || code > 127 )
91        code = '?';
92
93      string[n] = (char)code;
94    }
95
96    string[len] = 0;
97
98    return string;
99  }
100
101
102  /* convert an Apple Roman or symbol name entry to ASCII */
103  static FT_String*
104  tt_name_entry_ascii_from_other( TT_NameEntry  entry,
105                                  FT_Memory     memory )
106  {
107    FT_String*  string;
108    FT_UInt     len, code, n;
109    FT_Byte*    read = (FT_Byte*)entry->string;
110
111
112    len = (FT_UInt)entry->stringLength;
113
114    if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
115      return NULL;
116
117    for ( n = 0; n < len; n++ )
118    {
119      code = *read++;
120      if ( code < 32 || code > 127 )
121        code = '?';
122
123      string[n] = (char)code;
124    }
125
126    string[len] = 0;
127
128    return string;
129  }
130
131
132  typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
133                                                   FT_Memory     memory );
134
135
136  /*************************************************************************/
137  /*                                                                       */
138  /* <Function>                                                            */
139  /*    tt_face_get_name                                                   */
140  /*                                                                       */
141  /* <Description>                                                         */
142  /*    Returns a given ENGLISH name record in ASCII.                      */
143  /*                                                                       */
144  /* <Input>                                                               */
145  /*    face   :: A handle to the source face object.                      */
146  /*                                                                       */
147  /*    nameid :: The name id of the name record to return.                */
148  /*                                                                       */
149  /* <Return>                                                              */
150  /*    Character string.  NULL if no name is present.                     */
151  /*                                                                       */
152  static FT_String*
153  tt_face_get_name( TT_Face    face,
154                    FT_UShort  nameid )
155  {
156    FT_Memory         memory = face->root.memory;
157    FT_String*        result = NULL;
158    FT_UShort         n;
159    TT_NameEntryRec*  rec;
160    FT_Int            found_apple   = -1;
161    FT_Int            found_win     = -1;
162    FT_Int            found_unicode = -1;
163
164    FT_Bool           is_english = 0;
165
166    TT_NameEntry_ConvertFunc  convert;
167
168
169    rec = face->name_table.names;
170    for ( n = 0; n < face->num_names; n++, rec++ )
171    {
172      /* According to the OpenType 1.3 specification, only Microsoft or  */
173      /* Apple platform IDs might be used in the `name' table.  The      */
174      /* `Unicode' platform is reserved for the `cmap' table, and the    */
175      /* `Iso' one is deprecated.                                        */
176      /*                                                                 */
177      /* However, the Apple TrueType specification doesn't say the same  */
178      /* thing and goes to suggest that all Unicode `name' table entries */
179      /* should be coded in UTF-16 (in big-endian format I suppose).     */
180      /*                                                                 */
181      if ( rec->nameID == nameid && rec->stringLength > 0 )
182      {
183        switch ( rec->platformID )
184        {
185        case TT_PLATFORM_APPLE_UNICODE:
186        case TT_PLATFORM_ISO:
187          /* there is `languageID' to check there.  We should use this */
188          /* field only as a last solution when nothing else is        */
189          /* available.                                                */
190          /*                                                           */
191          found_unicode = n;
192          break;
193
194        case TT_PLATFORM_MACINTOSH:
195          if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
196            found_apple = n;
197
198          break;
199
200        case TT_PLATFORM_MICROSOFT:
201          /* we only take a non-English name when there is nothing */
202          /* else available in the font                            */
203          /*                                                       */
204          if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
205          {
206            switch ( rec->encodingID )
207            {
208            case TT_MS_ID_SYMBOL_CS:
209            case TT_MS_ID_UNICODE_CS:
210            case TT_MS_ID_UCS_4:
211              is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 );
212              found_win  = n;
213              break;
214
215            default:
216              ;
217            }
218          }
219          break;
220
221        default:
222          ;
223        }
224      }
225    }
226
227    /* some fonts contain invalid Unicode or Macintosh formatted entries; */
228    /* we will thus favor names encoded in Windows formats if available   */
229    /* (provided it is an English name)                                   */
230    /*                                                                    */
231    convert = NULL;
232    if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) )
233    {
234      rec = face->name_table.names + found_win;
235      switch ( rec->encodingID )
236      {
237      case TT_MS_ID_UNICODE_CS:
238      case TT_MS_ID_SYMBOL_CS:
239        convert = tt_name_entry_ascii_from_utf16;
240        break;
241
242      case TT_MS_ID_UCS_4:
243        convert = tt_name_entry_ascii_from_ucs4;
244        break;
245
246      default:
247        ;
248      }
249    }
250    else if ( found_apple >= 0 )
251    {
252      rec     = face->name_table.names + found_apple;
253      convert = tt_name_entry_ascii_from_other;
254    }
255    else if ( found_unicode >= 0 )
256    {
257      rec     = face->name_table.names + found_unicode;
258      convert = tt_name_entry_ascii_from_utf16;
259    }
260
261    if ( rec && convert )
262    {
263      if ( rec->string == NULL )
264      {
265        FT_Error   error  = SFNT_Err_Ok;
266        FT_Stream  stream = face->name_table.stream;
267
268        FT_UNUSED( error );
269
270
271        if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) ||
272             FT_STREAM_SEEK( rec->stringOffset )              ||
273             FT_STREAM_READ( rec->string, rec->stringLength ) )
274        {
275          FT_FREE( rec->string );
276          rec->stringLength = 0;
277          result            = NULL;
278          goto Exit;
279        }
280      }
281
282      result = convert( rec, memory );
283    }
284
285  Exit:
286    return result;
287  }
288
289
290  static FT_Encoding
291  sfnt_find_encoding( int  platform_id,
292                      int  encoding_id )
293  {
294    typedef struct  TEncoding
295    {
296      int          platform_id;
297      int          encoding_id;
298      FT_Encoding  encoding;
299
300    } TEncoding;
301
302    static
303    const TEncoding  tt_encodings[] =
304    {
305      { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
306
307      { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
308
309      { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
310
311      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
312      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
313      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
314      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_SJIS },
315      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     FT_ENCODING_GB2312 },
316      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_BIG5 },
317      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_WANSUNG },
318      { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_JOHAB }
319    };
320
321    const TEncoding  *cur, *limit;
322
323
324    cur   = tt_encodings;
325    limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
326
327    for ( ; cur < limit; cur++ )
328    {
329      if ( cur->platform_id == platform_id )
330      {
331        if ( cur->encoding_id == encoding_id ||
332             cur->encoding_id == -1          )
333          return cur->encoding;
334      }
335    }
336
337    return FT_ENCODING_NONE;
338  }
339
340
341  FT_LOCAL_DEF( FT_Error )
342  sfnt_init_face( FT_Stream      stream,
343                  TT_Face        face,
344                  FT_Int         face_index,
345                  FT_Int         num_params,
346                  FT_Parameter*  params )
347  {
348    FT_Error         error;
349    FT_Library       library = face->root.driver->root.library;
350    SFNT_Service     sfnt;
351    SFNT_HeaderRec   sfnt_header;
352
353    /* for now, parameters are unused */
354    FT_UNUSED( num_params );
355    FT_UNUSED( params );
356
357
358    sfnt = (SFNT_Service)face->sfnt;
359    if ( !sfnt )
360    {
361      sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
362      if ( !sfnt )
363      {
364        error = SFNT_Err_Invalid_File_Format;
365        goto Exit;
366      }
367
368      face->sfnt       = sfnt;
369      face->goto_table = sfnt->goto_table;
370    }
371
372    FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS );
373
374    /* check that we have a valid TrueType file */
375    error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
376    if ( error )
377      goto Exit;
378
379    face->format_tag = sfnt_header.format_tag;
380    face->num_tables = sfnt_header.num_tables;
381
382    /* Load font directory */
383    error = sfnt->load_directory( face, stream, &sfnt_header );
384    if ( error )
385      goto Exit;
386
387    face->root.num_faces = face->ttc_header.count;
388    if ( face->root.num_faces < 1 )
389      face->root.num_faces = 1;
390
391  Exit:
392    return error;
393  }
394
395
396#undef  LOAD_
397#define LOAD_( x )  ( ( error = sfnt->load_##x( face, stream ) ) \
398                      != SFNT_Err_Ok )
399
400
401  FT_LOCAL_DEF( FT_Error )
402  sfnt_load_face( FT_Stream      stream,
403                  TT_Face        face,
404                  FT_Int         face_index,
405                  FT_Int         num_params,
406                  FT_Parameter*  params )
407  {
408    FT_Error      error, psnames_error;
409    FT_Bool       has_outline;
410    FT_Bool       is_apple_sbit;
411
412    SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
413
414    FT_UNUSED( face_index );
415    FT_UNUSED( num_params );
416    FT_UNUSED( params );
417
418
419    /* Load tables */
420
421    /* We now support two SFNT-based bitmapped font formats.  They */
422    /* are recognized easily as they do not include a `glyf'       */
423    /* table.                                                      */
424    /*                                                             */
425    /* The first format comes from Apple, and uses a table named   */
426    /* `bhed' instead of `head' to store the font header (using    */
427    /* the same format).  It also doesn't include horizontal and   */
428    /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
429    /* missing).                                                   */
430    /*                                                             */
431    /* The other format comes from Microsoft, and is used with     */
432    /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
433    /* it doesn't contain outlines.                                */
434    /*                                                             */
435
436    /* do we have outlines in there? */
437#ifdef FT_CONFIG_OPTION_INCREMENTAL
438    has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
439                             tt_face_lookup_table( face, TTAG_glyf )    != 0 ||
440                             tt_face_lookup_table( face, TTAG_CFF )     != 0 );
441#else
442    has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
443                             tt_face_lookup_table( face, TTAG_CFF )  != 0 );
444#endif
445
446    is_apple_sbit = 0;
447
448#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
449
450    /* if this font doesn't contain outlines, we try to load */
451    /* a `bhed' table                                        */
452    if ( !has_outline )
453      is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) );
454
455#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
456
457    /* load the font header (`head' table) if this isn't an Apple */
458    /* sbit font file                                             */
459    if ( !is_apple_sbit && LOAD_( header ) )
460      goto Exit;
461
462    /* the following tables are often not present in embedded TrueType */
463    /* fonts within PDF documents, so don't check for them.            */
464    (void)LOAD_( max_profile );
465    (void)LOAD_( charmaps );
466
467    /* the following tables are optional in PCL fonts -- */
468    /* don't check for errors                            */
469    (void)LOAD_( names );
470    psnames_error = LOAD_( psnames );
471
472    /* do not load the metrics headers and tables if this is an Apple */
473    /* sbit font file                                                 */
474    if ( !is_apple_sbit )
475    {
476      /* load the `hhea' and `hmtx' tables at once */
477      error = sfnt->load_metrics( face, stream, 0 );
478      if ( error )
479        goto Exit;
480
481      /* try to load the `vhea' and `vmtx' tables at once */
482      error = sfnt->load_metrics( face, stream, 1 );
483      if ( error )
484        goto Exit;
485
486      if ( LOAD_( os2 ) )
487        goto Exit;
488    }
489
490    /* the optional tables */
491
492#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
493
494    /* embedded bitmap support. */
495    if ( sfnt->load_sbits && LOAD_( sbits ) )
496    {
497      /* return an error if this font file has no outlines */
498      if ( error == SFNT_Err_Table_Missing && has_outline )
499        error = SFNT_Err_Ok;
500      else
501        goto Exit;
502    }
503
504#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
505
506    if ( LOAD_( hdmx )    ||
507         LOAD_( pclt )    )
508      goto Exit;
509
510    /* consider the kerning and gasp tables as optional */
511    (void)LOAD_( gasp );
512    (void)LOAD_( kerning );
513
514    error = SFNT_Err_Ok;
515
516    face->root.family_name = tt_face_get_name( face,
517                                               TT_NAME_ID_PREFERRED_FAMILY );
518    if ( !face->root.family_name )
519      face->root.family_name = tt_face_get_name( face,
520                                                 TT_NAME_ID_FONT_FAMILY );
521
522    face->root.style_name = tt_face_get_name( face,
523                                              TT_NAME_ID_PREFERRED_SUBFAMILY );
524    if ( !face->root.style_name )
525      face->root.style_name  = tt_face_get_name( face,
526                                                 TT_NAME_ID_FONT_SUBFAMILY );
527
528    /* now set up root fields */
529    {
530      FT_Face    root = &face->root;
531      FT_Int32   flags = root->face_flags;
532
533
534      /*********************************************************************/
535      /*                                                                   */
536      /* Compute face flags.                                               */
537      /*                                                                   */
538      if ( has_outline == TRUE )
539        flags |= FT_FACE_FLAG_SCALABLE;    /* scalable outlines */
540
541      flags |= FT_FACE_FLAG_SFNT      |   /* SFNT file format  */
542               FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
543
544#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
545      if ( psnames_error == SFNT_Err_Ok &&
546           face->postscript.FormatType != 0x00030000L )
547        flags |= FT_FACE_FLAG_GLYPH_NAMES;
548#endif
549
550      /* fixed width font? */
551      if ( face->postscript.isFixedPitch )
552        flags |= FT_FACE_FLAG_FIXED_WIDTH;
553
554      /* vertical information? */
555      if ( face->vertical_info )
556        flags |= FT_FACE_FLAG_VERTICAL;
557
558#if 0
559      /* kerning available ? */
560      if ( TT_FACE_HAS_KERNING( face ) )
561        flags |= FT_FACE_FLAG_KERNING;
562#endif
563
564#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
565      /* Don't bother to load the tables unless somebody asks for them. */
566      /* No need to do work which will (probably) not be used.          */
567      if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 &&
568           tt_face_lookup_table( face, TTAG_fvar ) != 0 &&
569           tt_face_lookup_table( face, TTAG_gvar ) != 0 )
570        flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
571#endif
572
573      root->face_flags = flags;
574
575      /*********************************************************************/
576      /*                                                                   */
577      /* Compute style flags.                                              */
578      /*                                                                   */
579      flags = 0;
580      if ( has_outline == TRUE && face->os2.version != 0xFFFFU )
581      {
582        /* we have an OS/2 table; use the `fsSelection' field */
583        if ( face->os2.fsSelection & 1 )
584          flags |= FT_STYLE_FLAG_ITALIC;
585
586        if ( face->os2.fsSelection & 32 )
587          flags |= FT_STYLE_FLAG_BOLD;
588      }
589      else
590      {
591        /* this is an old Mac font, use the header field */
592        if ( face->header.Mac_Style & 1 )
593          flags |= FT_STYLE_FLAG_BOLD;
594
595        if ( face->header.Mac_Style & 2 )
596          flags |= FT_STYLE_FLAG_ITALIC;
597      }
598
599      root->style_flags = flags;
600
601      /*********************************************************************/
602      /*                                                                   */
603      /* Polish the charmaps.                                              */
604      /*                                                                   */
605      /*   Try to set the charmap encoding according to the platform &     */
606      /*   encoding ID of each charmap.                                    */
607      /*                                                                   */
608
609      tt_face_build_cmaps( face );  /* ignore errors */
610
611
612      /* set the encoding fields */
613      {
614        FT_Int  m;
615
616
617        for ( m = 0; m < root->num_charmaps; m++ )
618        {
619          FT_CharMap  charmap = root->charmaps[m];
620
621
622          charmap->encoding = sfnt_find_encoding( charmap->platform_id,
623                                                  charmap->encoding_id );
624
625#if 0
626          if ( root->charmap     == NULL &&
627               charmap->encoding == FT_ENCODING_UNICODE )
628          {
629            /* set 'root->charmap' to the first Unicode encoding we find */
630            root->charmap = charmap;
631          }
632#endif
633        }
634      }
635
636
637      /*********************************************************************/
638      /*                                                                   */
639      /*  Set up metrics.                                                  */
640      /*                                                                   */
641      if ( has_outline == TRUE )
642      {
643        /* XXX What about if outline header is missing */
644        /*     (e.g. sfnt wrapped bitmap)?             */
645        root->bbox.xMin    = face->header.xMin;
646        root->bbox.yMin    = face->header.yMin;
647        root->bbox.xMax    = face->header.xMax;
648        root->bbox.yMax    = face->header.yMax;
649        root->units_per_EM = face->header.Units_Per_EM;
650
651
652        /* XXX: Computing the ascender/descender/height is very different */
653        /*      from what the specification tells you.  Apparently, we    */
654        /*      must be careful because                                   */
655        /*                                                                */
656        /*      - not all fonts have an OS/2 table; in this case, we take */
657        /*        the values in the horizontal header.  However, these    */
658        /*        values very often are not reliable.                     */
659        /*                                                                */
660        /*      - otherwise, the correct typographic values are in the    */
661        /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
662        /*                                                                */
663        /*        However, certains fonts have these fields set to 0.     */
664        /*        Rather, they have usWinAscent & usWinDescent correctly  */
665        /*        set (but with different values).                        */
666        /*                                                                */
667        /*      As an example, Arial Narrow is implemented through four   */
668        /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
669        /*                                                                */
670        /*      Strangely, all fonts have the same values in their        */
671        /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
672        /*                                                                */
673        /*      On the other hand, they all have different                */
674        /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
675        /*      table cannot be used to compute the text height reliably! */
676        /*                                                                */
677
678        /* The ascender/descender/height are computed from the OS/2 table */
679        /* when found.  Otherwise, they're taken from the horizontal      */
680        /* header.                                                        */
681        /*                                                                */
682
683        root->ascender  = face->horizontal.Ascender;
684        root->descender = face->horizontal.Descender;
685
686        root->height    = (FT_Short)( root->ascender - root->descender +
687                                      face->horizontal.Line_Gap );
688
689#if 0
690        /* if the line_gap is 0, we add an extra 15% to the text height --  */
691        /* this computation is based on various versions of Times New Roman */
692        if ( face->horizontal.Line_Gap == 0 )
693          root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
694#endif
695
696#if 0
697
698        /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
699        /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
700        if ( face->os2.version != 0xFFFFU && root->ascender )
701        {
702          FT_Int  height;
703
704
705          root->ascender  =  face->os2.sTypoAscender;
706          root->descender = -face->os2.sTypoDescender;
707
708          height = root->ascender + root->descender + face->os2.sTypoLineGap;
709          if ( height > root->height )
710            root->height = height;
711        }
712
713#endif /* 0 */
714
715        root->max_advance_width   = face->horizontal.advance_Width_Max;
716
717        root->max_advance_height  = (FT_Short)( face->vertical_info
718                                      ? face->vertical.advance_Height_Max
719                                      : root->height );
720
721        root->underline_position  = face->postscript.underlinePosition;
722        root->underline_thickness = face->postscript.underlineThickness;
723
724        /* root->max_points   -- already set up */
725        /* root->max_contours -- already set up */
726      }
727    }
728
729  Exit:
730    return error;
731  }
732
733
734#undef LOAD_
735
736
737  FT_LOCAL_DEF( void )
738  sfnt_done_face( TT_Face  face )
739  {
740    FT_Memory     memory = face->root.memory;
741    SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
742
743
744    if ( sfnt )
745    {
746      /* destroy the postscript names table if it is loaded */
747      if ( sfnt->free_psnames )
748        sfnt->free_psnames( face );
749
750      /* destroy the embedded bitmaps table if it is loaded */
751      if ( sfnt->free_sbits )
752        sfnt->free_sbits( face );
753    }
754
755    /* freeing the kerning table */
756    tt_face_done_kern( face );
757
758    /* freeing the collection table */
759    FT_FREE( face->ttc_header.offsets );
760    face->ttc_header.count = 0;
761
762    /* freeing table directory */
763    FT_FREE( face->dir_tables );
764    face->num_tables = 0;
765
766    {
767      FT_Stream  stream = FT_FACE_STREAM( face );
768
769
770      /* simply release the 'cmap' table frame */
771      FT_FRAME_RELEASE( face->cmap_table );
772      face->cmap_size = 0;
773    }
774
775    /* freeing the horizontal metrics */
776#ifdef FT_OPTIMIZE_MEMORY
777    {
778      FT_Stream  stream = FT_FACE_STREAM( face );
779
780
781      FT_FRAME_RELEASE( face->horz_metrics );
782      FT_FRAME_RELEASE( face->vert_metrics );
783      face->horz_metrics_size = 0;
784      face->vert_metrics_size = 0;
785    }
786#else
787    FT_FREE( face->horizontal.long_metrics );
788    FT_FREE( face->horizontal.short_metrics );
789#endif
790
791    /* freeing the vertical ones, if any */
792    if ( face->vertical_info )
793    {
794      FT_FREE( face->vertical.long_metrics  );
795      FT_FREE( face->vertical.short_metrics );
796      face->vertical_info = 0;
797    }
798
799    /* freeing the gasp table */
800    FT_FREE( face->gasp.gaspRanges );
801    face->gasp.numRanges = 0;
802
803    /* freeing the name table */
804    sfnt->free_names( face );
805
806    /* freeing the hdmx table */
807    sfnt->free_hdmx( face );
808
809    /* freeing family and style name */
810    FT_FREE( face->root.family_name );
811    FT_FREE( face->root.style_name );
812
813    /* freeing sbit size table */
814    FT_FREE( face->root.available_sizes );
815    face->root.num_fixed_sizes = 0;
816
817    FT_FREE( face->postscript_name );
818
819    face->sfnt = 0;
820  }
821
822
823/* END */
Note: See TracBrowser for help on using the repository browser.