~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/sfnt/sfobjs.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

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