~ubuntu-branches/ubuntu/saucy/emscripten/saucy-proposed

« back to all changes in this revision

Viewing changes to tests/freetype/src/sfnt/sfobjs.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

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