~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/sfnt/ttload.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
/*  ttload.c                                                               */
 
4
/*                                                                         */
 
5
/*    Load the basic TrueType tables, i.e., tables that can be either in   */
 
6
/*    TTF or OTF fonts (body).                                             */
 
7
/*                                                                         */
 
8
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
 
9
/*            2010 by                                                      */
 
10
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 
11
/*                                                                         */
 
12
/*  This file is part of the FreeType project, and may only be used,       */
 
13
/*  modified, and distributed under the terms of the FreeType project      */
 
14
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
 
15
/*  this file you indicate that you have read the license and              */
 
16
/*  understand and accept it fully.                                        */
 
17
/*                                                                         */
 
18
/***************************************************************************/
 
19
 
 
20
 
 
21
#include <ft2build.h>
 
22
#include FT_INTERNAL_DEBUG_H
 
23
#include FT_INTERNAL_STREAM_H
 
24
#include FT_TRUETYPE_TAGS_H
 
25
#include "ttload.h"
 
26
 
 
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_ttload
 
38
 
 
39
 
 
40
  /*************************************************************************/
 
41
  /*                                                                       */
 
42
  /* <Function>                                                            */
 
43
  /*    tt_face_lookup_table                                               */
 
44
  /*                                                                       */
 
45
  /* <Description>                                                         */
 
46
  /*    Looks for a TrueType table by name.                                */
 
47
  /*                                                                       */
 
48
  /* <Input>                                                               */
 
49
  /*    face :: A face object handle.                                      */
 
50
  /*                                                                       */
 
51
  /*    tag  :: The searched tag.                                          */
 
52
  /*                                                                       */
 
53
  /* <Return>                                                              */
 
54
  /*    A pointer to the table directory entry.  0 if not found.           */
 
55
  /*                                                                       */
 
56
  FT_LOCAL_DEF( TT_Table  )
 
57
  tt_face_lookup_table( TT_Face   face,
 
58
                        FT_ULong  tag  )
 
59
  {
 
60
    TT_Table  entry;
 
61
    TT_Table  limit;
 
62
#ifdef FT_DEBUG_LEVEL_TRACE
 
63
    FT_Bool   zero_length = FALSE;
 
64
#endif
 
65
 
 
66
 
 
67
    FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
 
68
                face,
 
69
                (FT_Char)( tag >> 24 ),
 
70
                (FT_Char)( tag >> 16 ),
 
71
                (FT_Char)( tag >> 8  ),
 
72
                (FT_Char)( tag       ) ));
 
73
 
 
74
    entry = face->dir_tables;
 
75
    limit = entry + face->num_tables;
 
76
 
 
77
    for ( ; entry < limit; entry++ )
 
78
    {
 
79
      /* For compatibility with Windows, we consider    */
 
80
      /* zero-length tables the same as missing tables. */
 
81
      if ( entry->Tag == tag )
 
82
      {
 
83
        if ( entry->Length != 0 )
 
84
        {
 
85
          FT_TRACE4(( "found table.\n" ));
 
86
          return entry;
 
87
        }
 
88
#ifdef FT_DEBUG_LEVEL_TRACE
 
89
        zero_length = TRUE;
 
90
#endif
 
91
      }
 
92
    }
 
93
 
 
94
#ifdef FT_DEBUG_LEVEL_TRACE
 
95
    if ( zero_length )
 
96
      FT_TRACE4(( "ignoring empty table\n" ));
 
97
    else
 
98
      FT_TRACE4(( "could not find table\n" ));
 
99
#endif
 
100
 
 
101
    return NULL;
 
102
  }
 
103
 
 
104
 
 
105
  /*************************************************************************/
 
106
  /*                                                                       */
 
107
  /* <Function>                                                            */
 
108
  /*    tt_face_goto_table                                                 */
 
109
  /*                                                                       */
 
110
  /* <Description>                                                         */
 
111
  /*    Looks for a TrueType table by name, then seek a stream to it.      */
 
112
  /*                                                                       */
 
113
  /* <Input>                                                               */
 
114
  /*    face   :: A face object handle.                                    */
 
115
  /*                                                                       */
 
116
  /*    tag    :: The searched tag.                                        */
 
117
  /*                                                                       */
 
118
  /*    stream :: The stream to seek when the table is found.              */
 
119
  /*                                                                       */
 
120
  /* <Output>                                                              */
 
121
  /*    length :: The length of the table if found, undefined otherwise.   */
 
122
  /*                                                                       */
 
123
  /* <Return>                                                              */
 
124
  /*    FreeType error code.  0 means success.                             */
 
125
  /*                                                                       */
 
126
  FT_LOCAL_DEF( FT_Error )
 
127
  tt_face_goto_table( TT_Face    face,
 
128
                      FT_ULong   tag,
 
129
                      FT_Stream  stream,
 
130
                      FT_ULong*  length )
 
131
  {
 
132
    TT_Table  table;
 
133
    FT_Error  error;
 
134
 
 
135
 
 
136
    table = tt_face_lookup_table( face, tag );
 
137
    if ( table )
 
138
    {
 
139
      if ( length )
 
140
        *length = table->Length;
 
141
 
 
142
      if ( FT_STREAM_SEEK( table->Offset ) )
 
143
        goto Exit;
 
144
    }
 
145
    else
 
146
      error = SFNT_Err_Table_Missing;
 
147
 
 
148
  Exit:
 
149
    return error;
 
150
  }
 
151
 
 
152
 
 
153
  /* Here, we                                                         */
 
154
  /*                                                                  */
 
155
  /* - check that `num_tables' is valid (and adjust it if necessary)  */
 
156
  /*                                                                  */
 
157
  /* - look for a `head' table, check its size, and parse it to check */
 
158
  /*   whether its `magic' field is correctly set                     */
 
159
  /*                                                                  */
 
160
  /* - errors (except errors returned by stream handling)             */
 
161
  /*                                                                  */
 
162
  /*     SFNT_Err_Unknown_File_Format:                                */
 
163
  /*       no table is defined in directory, it is not sfnt-wrapped   */
 
164
  /*       data                                                       */
 
165
  /*     SFNT_Err_Table_Missing:                                      */
 
166
  /*       table directory is valid, but essential tables             */
 
167
  /*       (head/bhed/SING) are missing                               */
 
168
  /*                                                                  */
 
169
  static FT_Error
 
170
  check_table_dir( SFNT_Header  sfnt,
 
171
                   FT_Stream    stream )
 
172
  {
 
173
    FT_Error   error;
 
174
    FT_UShort  nn, valid_entries = 0;
 
175
    FT_UInt    has_head = 0, has_sing = 0, has_meta = 0;
 
176
    FT_ULong   offset = sfnt->offset + 12;
 
177
 
 
178
    static const FT_Frame_Field  table_dir_entry_fields[] =
 
179
    {
 
180
#undef  FT_STRUCTURE
 
181
#define FT_STRUCTURE  TT_TableRec
 
182
 
 
183
      FT_FRAME_START( 16 ),
 
184
        FT_FRAME_ULONG( Tag ),
 
185
        FT_FRAME_ULONG( CheckSum ),
 
186
        FT_FRAME_ULONG( Offset ),
 
187
        FT_FRAME_ULONG( Length ),
 
188
      FT_FRAME_END
 
189
    };
 
190
 
 
191
 
 
192
    if ( FT_STREAM_SEEK( offset ) )
 
193
      goto Exit;
 
194
 
 
195
    for ( nn = 0; nn < sfnt->num_tables; nn++ )
 
196
    {
 
197
      TT_TableRec  table;
 
198
 
 
199
 
 
200
      if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
 
201
      {
 
202
        nn--;
 
203
        FT_TRACE2(( "check_table_dir:"
 
204
                    " can read only %d table%s in font (instead of %d)\n",
 
205
                    nn, nn == 1 ? "" : "s", sfnt->num_tables ));
 
206
        sfnt->num_tables = nn;
 
207
        break;
 
208
      }
 
209
 
 
210
      /* we ignore invalid tables */
 
211
      if ( table.Offset + table.Length > stream->size )
 
212
      {
 
213
        FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
 
214
        continue;
 
215
      }
 
216
      else
 
217
        valid_entries++;
 
218
 
 
219
      if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
 
220
      {
 
221
        FT_UInt32  magic;
 
222
 
 
223
 
 
224
#ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
225
        if ( table.Tag == TTAG_head )
 
226
#endif
 
227
          has_head = 1;
 
228
 
 
229
        /*
 
230
         * The table length should be 0x36, but certain font tools make it
 
231
         * 0x38, so we will just check that it is greater.
 
232
         *
 
233
         * Note that according to the specification, the table must be
 
234
         * padded to 32-bit lengths, but this doesn't apply to the value of
 
235
         * its `Length' field!
 
236
         *
 
237
         */
 
238
        if ( table.Length < 0x36 )
 
239
        {
 
240
          FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
 
241
          error = SFNT_Err_Table_Missing;
 
242
          goto Exit;
 
243
        }
 
244
 
 
245
        if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
 
246
             FT_READ_ULONG( magic )              )
 
247
          goto Exit;
 
248
 
 
249
        if ( magic != 0x5F0F3CF5UL )
 
250
        {
 
251
          FT_TRACE2(( "check_table_dir:"
 
252
                      " no magic number found in `head' table\n"));
 
253
          error = SFNT_Err_Table_Missing;
 
254
          goto Exit;
 
255
        }
 
256
 
 
257
        if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
 
258
          goto Exit;
 
259
      }
 
260
      else if ( table.Tag == TTAG_SING )
 
261
        has_sing = 1;
 
262
      else if ( table.Tag == TTAG_META )
 
263
        has_meta = 1;
 
264
    }
 
265
 
 
266
    sfnt->num_tables = valid_entries;
 
267
 
 
268
    if ( sfnt->num_tables == 0 )
 
269
    {
 
270
      FT_TRACE2(( "check_table_dir: no tables found\n" ));
 
271
      error = SFNT_Err_Unknown_File_Format;
 
272
      goto Exit;
 
273
    }
 
274
 
 
275
    /* if `sing' and `meta' tables are present, there is no `head' table */
 
276
    if ( has_head || ( has_sing && has_meta ) )
 
277
    {
 
278
      error = SFNT_Err_Ok;
 
279
      goto Exit;
 
280
    }
 
281
    else
 
282
    {
 
283
      FT_TRACE2(( "check_table_dir:" ));
 
284
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
285
      FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
 
286
#else
 
287
      FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
 
288
#endif
 
289
      error = SFNT_Err_Table_Missing;
 
290
    }
 
291
 
 
292
  Exit:
 
293
    return error;
 
294
  }
 
295
 
 
296
 
 
297
  /*************************************************************************/
 
298
  /*                                                                       */
 
299
  /* <Function>                                                            */
 
300
  /*    tt_face_load_font_dir                                              */
 
301
  /*                                                                       */
 
302
  /* <Description>                                                         */
 
303
  /*    Loads the header of a SFNT font file.                              */
 
304
  /*                                                                       */
 
305
  /* <Input>                                                               */
 
306
  /*    face       :: A handle to the target face object.                  */
 
307
  /*                                                                       */
 
308
  /*    stream     :: The input stream.                                    */
 
309
  /*                                                                       */
 
310
  /* <Output>                                                              */
 
311
  /*    sfnt       :: The SFNT header.                                     */
 
312
  /*                                                                       */
 
313
  /* <Return>                                                              */
 
314
  /*    FreeType error code.  0 means success.                             */
 
315
  /*                                                                       */
 
316
  /* <Note>                                                                */
 
317
  /*    The stream cursor must be at the beginning of the font directory.  */
 
318
  /*                                                                       */
 
319
  FT_LOCAL_DEF( FT_Error )
 
320
  tt_face_load_font_dir( TT_Face    face,
 
321
                         FT_Stream  stream )
 
322
  {
 
323
    SFNT_HeaderRec  sfnt;
 
324
    FT_Error        error;
 
325
    FT_Memory       memory = stream->memory;
 
326
    TT_TableRec*    entry;
 
327
    FT_Int          nn;
 
328
 
 
329
    static const FT_Frame_Field  offset_table_fields[] =
 
330
    {
 
331
#undef  FT_STRUCTURE
 
332
#define FT_STRUCTURE  SFNT_HeaderRec
 
333
 
 
334
      FT_FRAME_START( 8 ),
 
335
        FT_FRAME_USHORT( num_tables ),
 
336
        FT_FRAME_USHORT( search_range ),
 
337
        FT_FRAME_USHORT( entry_selector ),
 
338
        FT_FRAME_USHORT( range_shift ),
 
339
      FT_FRAME_END
 
340
    };
 
341
 
 
342
 
 
343
    FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
 
344
 
 
345
    /* read the offset table */
 
346
 
 
347
    sfnt.offset = FT_STREAM_POS();
 
348
 
 
349
    if ( FT_READ_ULONG( sfnt.format_tag )                    ||
 
350
         FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
 
351
      goto Exit;
 
352
 
 
353
    /* many fonts don't have these fields set correctly */
 
354
#if 0
 
355
    if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 )        ||
 
356
         sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
 
357
      return SFNT_Err_Unknown_File_Format;
 
358
#endif
 
359
 
 
360
    /* load the table directory */
 
361
 
 
362
    FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
 
363
    FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
 
364
 
 
365
    /* check first */
 
366
    error = check_table_dir( &sfnt, stream );
 
367
    if ( error )
 
368
    {
 
369
      FT_TRACE2(( "tt_face_load_font_dir:"
 
370
                  " invalid table directory for TrueType\n" ));
 
371
 
 
372
      goto Exit;
 
373
    }
 
374
 
 
375
    face->num_tables = sfnt.num_tables;
 
376
    face->format_tag = sfnt.format_tag;
 
377
 
 
378
    if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
 
379
      goto Exit;
 
380
 
 
381
    if ( FT_STREAM_SEEK( sfnt.offset + 12 )       ||
 
382
         FT_FRAME_ENTER( face->num_tables * 16L ) )
 
383
      goto Exit;
 
384
 
 
385
    entry = face->dir_tables;
 
386
 
 
387
    FT_TRACE2(( "\n"
 
388
                "  tag    offset    length   checksum\n"
 
389
                "  ----------------------------------\n" ));
 
390
 
 
391
    for ( nn = 0; nn < sfnt.num_tables; nn++ )
 
392
    {
 
393
      entry->Tag      = FT_GET_TAG4();
 
394
      entry->CheckSum = FT_GET_ULONG();
 
395
      entry->Offset   = FT_GET_LONG();
 
396
      entry->Length   = FT_GET_LONG();
 
397
 
 
398
      /* ignore invalid tables */
 
399
      if ( entry->Offset + entry->Length > stream->size )
 
400
        continue;
 
401
      else
 
402
      {
 
403
        FT_TRACE2(( "  %c%c%c%c  %08lx  %08lx  %08lx\n",
 
404
                    (FT_Char)( entry->Tag >> 24 ),
 
405
                    (FT_Char)( entry->Tag >> 16 ),
 
406
                    (FT_Char)( entry->Tag >> 8  ),
 
407
                    (FT_Char)( entry->Tag       ),
 
408
                    entry->Offset,
 
409
                    entry->Length,
 
410
                    entry->CheckSum ));
 
411
        entry++;
 
412
      }
 
413
    }
 
414
 
 
415
    FT_FRAME_EXIT();
 
416
 
 
417
    FT_TRACE2(( "table directory loaded\n\n" ));
 
418
 
 
419
  Exit:
 
420
    return error;
 
421
  }
 
422
 
 
423
 
 
424
  /*************************************************************************/
 
425
  /*                                                                       */
 
426
  /* <Function>                                                            */
 
427
  /*    tt_face_load_any                                                   */
 
428
  /*                                                                       */
 
429
  /* <Description>                                                         */
 
430
  /*    Loads any font table into client memory.                           */
 
431
  /*                                                                       */
 
432
  /* <Input>                                                               */
 
433
  /*    face   :: The face object to look for.                             */
 
434
  /*                                                                       */
 
435
  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
 
436
  /*              to access the whole font file, else set this parameter   */
 
437
  /*              to a valid TrueType table tag that you can forge with    */
 
438
  /*              the MAKE_TT_TAG macro.                                   */
 
439
  /*                                                                       */
 
440
  /*    offset :: The starting offset in the table (or the file if         */
 
441
  /*              tag == 0).                                               */
 
442
  /*                                                                       */
 
443
  /*    length :: The address of the decision variable:                    */
 
444
  /*                                                                       */
 
445
  /*                If length == NULL:                                     */
 
446
  /*                  Loads the whole table.  Returns an error if          */
 
447
  /*                  `offset' == 0!                                       */
 
448
  /*                                                                       */
 
449
  /*                If *length == 0:                                       */
 
450
  /*                  Exits immediately; returning the length of the given */
 
451
  /*                  table or of the font file, depending on the value of */
 
452
  /*                  `tag'.                                               */
 
453
  /*                                                                       */
 
454
  /*                If *length != 0:                                       */
 
455
  /*                  Loads the next `length' bytes of table or font,      */
 
456
  /*                  starting at offset `offset' (in table or font too).  */
 
457
  /*                                                                       */
 
458
  /* <Output>                                                              */
 
459
  /*    buffer :: The address of target buffer.                            */
 
460
  /*                                                                       */
 
461
  /* <Return>                                                              */
 
462
  /*    FreeType error code.  0 means success.                             */
 
463
  /*                                                                       */
 
464
  FT_LOCAL_DEF( FT_Error )
 
465
  tt_face_load_any( TT_Face    face,
 
466
                    FT_ULong   tag,
 
467
                    FT_Long    offset,
 
468
                    FT_Byte*   buffer,
 
469
                    FT_ULong*  length )
 
470
  {
 
471
    FT_Error   error;
 
472
    FT_Stream  stream;
 
473
    TT_Table   table;
 
474
    FT_ULong   size;
 
475
 
 
476
 
 
477
    if ( tag != 0 )
 
478
    {
 
479
      /* look for tag in font directory */
 
480
      table = tt_face_lookup_table( face, tag );
 
481
      if ( !table )
 
482
      {
 
483
        error = SFNT_Err_Table_Missing;
 
484
        goto Exit;
 
485
      }
 
486
 
 
487
      offset += table->Offset;
 
488
      size    = table->Length;
 
489
    }
 
490
    else
 
491
      /* tag == 0 -- the user wants to access the font file directly */
 
492
      size = face->root.stream->size;
 
493
 
 
494
    if ( length && *length == 0 )
 
495
    {
 
496
      *length = size;
 
497
 
 
498
      return SFNT_Err_Ok;
 
499
    }
 
500
 
 
501
    if ( length )
 
502
      size = *length;
 
503
 
 
504
    stream = face->root.stream;
 
505
    /* the `if' is syntactic sugar for picky compilers */
 
506
    if ( FT_STREAM_READ_AT( offset, buffer, size ) )
 
507
      goto Exit;
 
508
 
 
509
  Exit:
 
510
    return error;
 
511
  }
 
512
 
 
513
 
 
514
  /*************************************************************************/
 
515
  /*                                                                       */
 
516
  /* <Function>                                                            */
 
517
  /*    tt_face_load_generic_header                                        */
 
518
  /*                                                                       */
 
519
  /* <Description>                                                         */
 
520
  /*    Loads the TrueType table `head' or `bhed'.                         */
 
521
  /*                                                                       */
 
522
  /* <Input>                                                               */
 
523
  /*    face   :: A handle to the target face object.                      */
 
524
  /*                                                                       */
 
525
  /*    stream :: The input stream.                                        */
 
526
  /*                                                                       */
 
527
  /* <Return>                                                              */
 
528
  /*    FreeType error code.  0 means success.                             */
 
529
  /*                                                                       */
 
530
  static FT_Error
 
531
  tt_face_load_generic_header( TT_Face    face,
 
532
                               FT_Stream  stream,
 
533
                               FT_ULong   tag )
 
534
  {
 
535
    FT_Error    error;
 
536
    TT_Header*  header;
 
537
 
 
538
    static const FT_Frame_Field  header_fields[] =
 
539
    {
 
540
#undef  FT_STRUCTURE
 
541
#define FT_STRUCTURE  TT_Header
 
542
 
 
543
      FT_FRAME_START( 54 ),
 
544
        FT_FRAME_ULONG ( Table_Version ),
 
545
        FT_FRAME_ULONG ( Font_Revision ),
 
546
        FT_FRAME_LONG  ( CheckSum_Adjust ),
 
547
        FT_FRAME_LONG  ( Magic_Number ),
 
548
        FT_FRAME_USHORT( Flags ),
 
549
        FT_FRAME_USHORT( Units_Per_EM ),
 
550
        FT_FRAME_LONG  ( Created[0] ),
 
551
        FT_FRAME_LONG  ( Created[1] ),
 
552
        FT_FRAME_LONG  ( Modified[0] ),
 
553
        FT_FRAME_LONG  ( Modified[1] ),
 
554
        FT_FRAME_SHORT ( xMin ),
 
555
        FT_FRAME_SHORT ( yMin ),
 
556
        FT_FRAME_SHORT ( xMax ),
 
557
        FT_FRAME_SHORT ( yMax ),
 
558
        FT_FRAME_USHORT( Mac_Style ),
 
559
        FT_FRAME_USHORT( Lowest_Rec_PPEM ),
 
560
        FT_FRAME_SHORT ( Font_Direction ),
 
561
        FT_FRAME_SHORT ( Index_To_Loc_Format ),
 
562
        FT_FRAME_SHORT ( Glyph_Data_Format ),
 
563
      FT_FRAME_END
 
564
    };
 
565
 
 
566
 
 
567
    error = face->goto_table( face, tag, stream, 0 );
 
568
    if ( error )
 
569
      goto Exit;
 
570
 
 
571
    header = &face->header;
 
572
 
 
573
    if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
 
574
      goto Exit;
 
575
 
 
576
    FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
 
577
    FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
 
578
 
 
579
  Exit:
 
580
    return error;
 
581
  }
 
582
 
 
583
 
 
584
  FT_LOCAL_DEF( FT_Error )
 
585
  tt_face_load_head( TT_Face    face,
 
586
                     FT_Stream  stream )
 
587
  {
 
588
    return tt_face_load_generic_header( face, stream, TTAG_head );
 
589
  }
 
590
 
 
591
 
 
592
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
593
 
 
594
  FT_LOCAL_DEF( FT_Error )
 
595
  tt_face_load_bhed( TT_Face    face,
 
596
                     FT_Stream  stream )
 
597
  {
 
598
    return tt_face_load_generic_header( face, stream, TTAG_bhed );
 
599
  }
 
600
 
 
601
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
 
602
 
 
603
 
 
604
  /*************************************************************************/
 
605
  /*                                                                       */
 
606
  /* <Function>                                                            */
 
607
  /*    tt_face_load_max_profile                                           */
 
608
  /*                                                                       */
 
609
  /* <Description>                                                         */
 
610
  /*    Loads the maximum profile into a face object.                      */
 
611
  /*                                                                       */
 
612
  /* <Input>                                                               */
 
613
  /*    face   :: A handle to the target face object.                      */
 
614
  /*                                                                       */
 
615
  /*    stream :: The input stream.                                        */
 
616
  /*                                                                       */
 
617
  /* <Return>                                                              */
 
618
  /*    FreeType error code.  0 means success.                             */
 
619
  /*                                                                       */
 
620
  FT_LOCAL_DEF( FT_Error )
 
621
  tt_face_load_maxp( TT_Face    face,
 
622
                     FT_Stream  stream )
 
623
  {
 
624
    FT_Error        error;
 
625
    TT_MaxProfile*  maxProfile = &face->max_profile;
 
626
 
 
627
    const FT_Frame_Field  maxp_fields[] =
 
628
    {
 
629
#undef  FT_STRUCTURE
 
630
#define FT_STRUCTURE  TT_MaxProfile
 
631
 
 
632
      FT_FRAME_START( 6 ),
 
633
        FT_FRAME_LONG  ( version ),
 
634
        FT_FRAME_USHORT( numGlyphs ),
 
635
      FT_FRAME_END
 
636
    };
 
637
 
 
638
    const FT_Frame_Field  maxp_fields_extra[] =
 
639
    {
 
640
      FT_FRAME_START( 26 ),
 
641
        FT_FRAME_USHORT( maxPoints ),
 
642
        FT_FRAME_USHORT( maxContours ),
 
643
        FT_FRAME_USHORT( maxCompositePoints ),
 
644
        FT_FRAME_USHORT( maxCompositeContours ),
 
645
        FT_FRAME_USHORT( maxZones ),
 
646
        FT_FRAME_USHORT( maxTwilightPoints ),
 
647
        FT_FRAME_USHORT( maxStorage ),
 
648
        FT_FRAME_USHORT( maxFunctionDefs ),
 
649
        FT_FRAME_USHORT( maxInstructionDefs ),
 
650
        FT_FRAME_USHORT( maxStackElements ),
 
651
        FT_FRAME_USHORT( maxSizeOfInstructions ),
 
652
        FT_FRAME_USHORT( maxComponentElements ),
 
653
        FT_FRAME_USHORT( maxComponentDepth ),
 
654
      FT_FRAME_END
 
655
    };
 
656
 
 
657
 
 
658
    error = face->goto_table( face, TTAG_maxp, stream, 0 );
 
659
    if ( error )
 
660
      goto Exit;
 
661
 
 
662
    if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
 
663
      goto Exit;
 
664
 
 
665
    maxProfile->maxPoints             = 0;
 
666
    maxProfile->maxContours           = 0;
 
667
    maxProfile->maxCompositePoints    = 0;
 
668
    maxProfile->maxCompositeContours  = 0;
 
669
    maxProfile->maxZones              = 0;
 
670
    maxProfile->maxTwilightPoints     = 0;
 
671
    maxProfile->maxStorage            = 0;
 
672
    maxProfile->maxFunctionDefs       = 0;
 
673
    maxProfile->maxInstructionDefs    = 0;
 
674
    maxProfile->maxStackElements      = 0;
 
675
    maxProfile->maxSizeOfInstructions = 0;
 
676
    maxProfile->maxComponentElements  = 0;
 
677
    maxProfile->maxComponentDepth     = 0;
 
678
 
 
679
    if ( maxProfile->version >= 0x10000L )
 
680
    {
 
681
      if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
 
682
        goto Exit;
 
683
 
 
684
      /* XXX: an adjustment that is necessary to load certain */
 
685
      /*      broken fonts like `Keystrokes MT' :-(           */
 
686
      /*                                                      */
 
687
      /*   We allocate 64 function entries by default when    */
 
688
      /*   the maxFunctionDefs value is smaller.              */
 
689
 
 
690
      if ( maxProfile->maxFunctionDefs < 64 )
 
691
        maxProfile->maxFunctionDefs = 64;
 
692
 
 
693
      /* we add 4 phantom points later */
 
694
      if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
 
695
      {
 
696
        FT_TRACE0(( "tt_face_load_maxp:"
 
697
                    " too much twilight points in `maxp' table;\n"
 
698
                    "                  "
 
699
                    " some glyphs might be rendered incorrectly\n" ));
 
700
 
 
701
        maxProfile->maxTwilightPoints = 0xFFFFU - 4;
 
702
      }
 
703
 
 
704
      /* we arbitrarily limit recursion to avoid stack exhaustion */
 
705
      if ( maxProfile->maxComponentDepth > 100 )
 
706
      {
 
707
        FT_TRACE0(( "tt_face_load_maxp:"
 
708
                    " abnormally large component depth (%d) set to 100\n",
 
709
                    maxProfile->maxComponentDepth ));
 
710
        maxProfile->maxComponentDepth = 100;
 
711
      }
 
712
    }
 
713
 
 
714
    FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
 
715
 
 
716
  Exit:
 
717
    return error;
 
718
  }
 
719
 
 
720
 
 
721
  /*************************************************************************/
 
722
  /*                                                                       */
 
723
  /* <Function>                                                            */
 
724
  /*    tt_face_load_names                                                 */
 
725
  /*                                                                       */
 
726
  /* <Description>                                                         */
 
727
  /*    Loads the name records.                                            */
 
728
  /*                                                                       */
 
729
  /* <Input>                                                               */
 
730
  /*    face   :: A handle to the target face object.                      */
 
731
  /*                                                                       */
 
732
  /*    stream :: The input stream.                                        */
 
733
  /*                                                                       */
 
734
  /* <Return>                                                              */
 
735
  /*    FreeType error code.  0 means success.                             */
 
736
  /*                                                                       */
 
737
  FT_LOCAL_DEF( FT_Error )
 
738
  tt_face_load_name( TT_Face    face,
 
739
                     FT_Stream  stream )
 
740
  {
 
741
    FT_Error      error;
 
742
    FT_Memory     memory = stream->memory;
 
743
    FT_ULong      table_pos, table_len;
 
744
    FT_ULong      storage_start, storage_limit;
 
745
    FT_UInt       count;
 
746
    TT_NameTable  table;
 
747
 
 
748
    static const FT_Frame_Field  name_table_fields[] =
 
749
    {
 
750
#undef  FT_STRUCTURE
 
751
#define FT_STRUCTURE  TT_NameTableRec
 
752
 
 
753
      FT_FRAME_START( 6 ),
 
754
        FT_FRAME_USHORT( format ),
 
755
        FT_FRAME_USHORT( numNameRecords ),
 
756
        FT_FRAME_USHORT( storageOffset ),
 
757
      FT_FRAME_END
 
758
    };
 
759
 
 
760
    static const FT_Frame_Field  name_record_fields[] =
 
761
    {
 
762
#undef  FT_STRUCTURE
 
763
#define FT_STRUCTURE  TT_NameEntryRec
 
764
 
 
765
      /* no FT_FRAME_START */
 
766
        FT_FRAME_USHORT( platformID ),
 
767
        FT_FRAME_USHORT( encodingID ),
 
768
        FT_FRAME_USHORT( languageID ),
 
769
        FT_FRAME_USHORT( nameID ),
 
770
        FT_FRAME_USHORT( stringLength ),
 
771
        FT_FRAME_USHORT( stringOffset ),
 
772
      FT_FRAME_END
 
773
    };
 
774
 
 
775
 
 
776
    table         = &face->name_table;
 
777
    table->stream = stream;
 
778
 
 
779
    error = face->goto_table( face, TTAG_name, stream, &table_len );
 
780
    if ( error )
 
781
      goto Exit;
 
782
 
 
783
    table_pos = FT_STREAM_POS();
 
784
 
 
785
 
 
786
    if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
 
787
      goto Exit;
 
788
 
 
789
    /* Some popular Asian fonts have an invalid `storageOffset' value   */
 
790
    /* (it should be at least "6 + 12*num_names").  However, the string */
 
791
    /* offsets, computed as "storageOffset + entry->stringOffset", are  */
 
792
    /* valid pointers within the name table...                          */
 
793
    /*                                                                  */
 
794
    /* We thus can't check `storageOffset' right now.                   */
 
795
    /*                                                                  */
 
796
    storage_start = table_pos + 6 + 12*table->numNameRecords;
 
797
    storage_limit = table_pos + table_len;
 
798
 
 
799
    if ( storage_start > storage_limit )
 
800
    {
 
801
      FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
 
802
      error = SFNT_Err_Name_Table_Missing;
 
803
      goto Exit;
 
804
    }
 
805
 
 
806
    /* Allocate the array of name records. */
 
807
    count                 = table->numNameRecords;
 
808
    table->numNameRecords = 0;
 
809
 
 
810
    if ( FT_NEW_ARRAY( table->names, count ) ||
 
811
         FT_FRAME_ENTER( count * 12 )        )
 
812
      goto Exit;
 
813
 
 
814
    /* Load the name records and determine how much storage is needed */
 
815
    /* to hold the strings themselves.                                */
 
816
    {
 
817
      TT_NameEntryRec*  entry = table->names;
 
818
 
 
819
 
 
820
      for ( ; count > 0; count-- )
 
821
      {
 
822
        if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
 
823
          continue;
 
824
 
 
825
        /* check that the name is not empty */
 
826
        if ( entry->stringLength == 0 )
 
827
          continue;
 
828
 
 
829
        /* check that the name string is within the table */
 
830
        entry->stringOffset += table_pos + table->storageOffset;
 
831
        if ( entry->stringOffset                       < storage_start ||
 
832
             entry->stringOffset + entry->stringLength > storage_limit )
 
833
        {
 
834
          /* invalid entry - ignore it */
 
835
          entry->stringOffset = 0;
 
836
          entry->stringLength = 0;
 
837
          continue;
 
838
        }
 
839
 
 
840
        entry++;
 
841
      }
 
842
 
 
843
      table->numNameRecords = (FT_UInt)( entry - table->names );
 
844
    }
 
845
 
 
846
    FT_FRAME_EXIT();
 
847
 
 
848
    /* everything went well, update face->num_names */
 
849
    face->num_names = (FT_UShort) table->numNameRecords;
 
850
 
 
851
  Exit:
 
852
    return error;
 
853
  }
 
854
 
 
855
 
 
856
  /*************************************************************************/
 
857
  /*                                                                       */
 
858
  /* <Function>                                                            */
 
859
  /*    tt_face_free_names                                                 */
 
860
  /*                                                                       */
 
861
  /* <Description>                                                         */
 
862
  /*    Frees the name records.                                            */
 
863
  /*                                                                       */
 
864
  /* <Input>                                                               */
 
865
  /*    face :: A handle to the target face object.                        */
 
866
  /*                                                                       */
 
867
  FT_LOCAL_DEF( void )
 
868
  tt_face_free_name( TT_Face  face )
 
869
  {
 
870
    FT_Memory     memory = face->root.driver->root.memory;
 
871
    TT_NameTable  table  = &face->name_table;
 
872
    TT_NameEntry  entry  = table->names;
 
873
    FT_UInt       count  = table->numNameRecords;
 
874
 
 
875
 
 
876
    if ( table->names )
 
877
    {
 
878
      for ( ; count > 0; count--, entry++ )
 
879
      {
 
880
        FT_FREE( entry->string );
 
881
        entry->stringLength = 0;
 
882
      }
 
883
 
 
884
      /* free strings table */
 
885
      FT_FREE( table->names );
 
886
    }
 
887
 
 
888
    table->numNameRecords = 0;
 
889
    table->format         = 0;
 
890
    table->storageOffset  = 0;
 
891
  }
 
892
 
 
893
 
 
894
  /*************************************************************************/
 
895
  /*                                                                       */
 
896
  /* <Function>                                                            */
 
897
  /*    tt_face_load_cmap                                                  */
 
898
  /*                                                                       */
 
899
  /* <Description>                                                         */
 
900
  /*    Loads the cmap directory in a face object.  The cmaps themselves   */
 
901
  /*    are loaded on demand in the `ttcmap.c' module.                     */
 
902
  /*                                                                       */
 
903
  /* <Input>                                                               */
 
904
  /*    face   :: A handle to the target face object.                      */
 
905
  /*                                                                       */
 
906
  /*    stream :: A handle to the input stream.                            */
 
907
  /*                                                                       */
 
908
  /* <Return>                                                              */
 
909
  /*    FreeType error code.  0 means success.                             */
 
910
  /*                                                                       */
 
911
 
 
912
  FT_LOCAL_DEF( FT_Error )
 
913
  tt_face_load_cmap( TT_Face    face,
 
914
                     FT_Stream  stream )
 
915
  {
 
916
    FT_Error  error;
 
917
 
 
918
 
 
919
    error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
 
920
    if ( error )
 
921
      goto Exit;
 
922
 
 
923
    if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
 
924
      face->cmap_size = 0;
 
925
 
 
926
  Exit:
 
927
    return error;
 
928
  }
 
929
 
 
930
 
 
931
 
 
932
  /*************************************************************************/
 
933
  /*                                                                       */
 
934
  /* <Function>                                                            */
 
935
  /*    tt_face_load_os2                                                   */
 
936
  /*                                                                       */
 
937
  /* <Description>                                                         */
 
938
  /*    Loads the OS2 table.                                               */
 
939
  /*                                                                       */
 
940
  /* <Input>                                                               */
 
941
  /*    face   :: A handle to the target face object.                      */
 
942
  /*                                                                       */
 
943
  /*    stream :: A handle to the input stream.                            */
 
944
  /*                                                                       */
 
945
  /* <Return>                                                              */
 
946
  /*    FreeType error code.  0 means success.                             */
 
947
  /*                                                                       */
 
948
  FT_LOCAL_DEF( FT_Error )
 
949
  tt_face_load_os2( TT_Face    face,
 
950
                    FT_Stream  stream )
 
951
  {
 
952
    FT_Error  error;
 
953
    TT_OS2*   os2;
 
954
 
 
955
    const FT_Frame_Field  os2_fields[] =
 
956
    {
 
957
#undef  FT_STRUCTURE
 
958
#define FT_STRUCTURE  TT_OS2
 
959
 
 
960
      FT_FRAME_START( 78 ),
 
961
        FT_FRAME_USHORT( version ),
 
962
        FT_FRAME_SHORT ( xAvgCharWidth ),
 
963
        FT_FRAME_USHORT( usWeightClass ),
 
964
        FT_FRAME_USHORT( usWidthClass ),
 
965
        FT_FRAME_SHORT ( fsType ),
 
966
        FT_FRAME_SHORT ( ySubscriptXSize ),
 
967
        FT_FRAME_SHORT ( ySubscriptYSize ),
 
968
        FT_FRAME_SHORT ( ySubscriptXOffset ),
 
969
        FT_FRAME_SHORT ( ySubscriptYOffset ),
 
970
        FT_FRAME_SHORT ( ySuperscriptXSize ),
 
971
        FT_FRAME_SHORT ( ySuperscriptYSize ),
 
972
        FT_FRAME_SHORT ( ySuperscriptXOffset ),
 
973
        FT_FRAME_SHORT ( ySuperscriptYOffset ),
 
974
        FT_FRAME_SHORT ( yStrikeoutSize ),
 
975
        FT_FRAME_SHORT ( yStrikeoutPosition ),
 
976
        FT_FRAME_SHORT ( sFamilyClass ),
 
977
        FT_FRAME_BYTE  ( panose[0] ),
 
978
        FT_FRAME_BYTE  ( panose[1] ),
 
979
        FT_FRAME_BYTE  ( panose[2] ),
 
980
        FT_FRAME_BYTE  ( panose[3] ),
 
981
        FT_FRAME_BYTE  ( panose[4] ),
 
982
        FT_FRAME_BYTE  ( panose[5] ),
 
983
        FT_FRAME_BYTE  ( panose[6] ),
 
984
        FT_FRAME_BYTE  ( panose[7] ),
 
985
        FT_FRAME_BYTE  ( panose[8] ),
 
986
        FT_FRAME_BYTE  ( panose[9] ),
 
987
        FT_FRAME_ULONG ( ulUnicodeRange1 ),
 
988
        FT_FRAME_ULONG ( ulUnicodeRange2 ),
 
989
        FT_FRAME_ULONG ( ulUnicodeRange3 ),
 
990
        FT_FRAME_ULONG ( ulUnicodeRange4 ),
 
991
        FT_FRAME_BYTE  ( achVendID[0] ),
 
992
        FT_FRAME_BYTE  ( achVendID[1] ),
 
993
        FT_FRAME_BYTE  ( achVendID[2] ),
 
994
        FT_FRAME_BYTE  ( achVendID[3] ),
 
995
 
 
996
        FT_FRAME_USHORT( fsSelection ),
 
997
        FT_FRAME_USHORT( usFirstCharIndex ),
 
998
        FT_FRAME_USHORT( usLastCharIndex ),
 
999
        FT_FRAME_SHORT ( sTypoAscender ),
 
1000
        FT_FRAME_SHORT ( sTypoDescender ),
 
1001
        FT_FRAME_SHORT ( sTypoLineGap ),
 
1002
        FT_FRAME_USHORT( usWinAscent ),
 
1003
        FT_FRAME_USHORT( usWinDescent ),
 
1004
      FT_FRAME_END
 
1005
    };
 
1006
 
 
1007
    const FT_Frame_Field  os2_fields_extra[] =
 
1008
    {
 
1009
      FT_FRAME_START( 8 ),
 
1010
        FT_FRAME_ULONG( ulCodePageRange1 ),
 
1011
        FT_FRAME_ULONG( ulCodePageRange2 ),
 
1012
      FT_FRAME_END
 
1013
    };
 
1014
 
 
1015
    const FT_Frame_Field  os2_fields_extra2[] =
 
1016
    {
 
1017
      FT_FRAME_START( 10 ),
 
1018
        FT_FRAME_SHORT ( sxHeight ),
 
1019
        FT_FRAME_SHORT ( sCapHeight ),
 
1020
        FT_FRAME_USHORT( usDefaultChar ),
 
1021
        FT_FRAME_USHORT( usBreakChar ),
 
1022
        FT_FRAME_USHORT( usMaxContext ),
 
1023
      FT_FRAME_END
 
1024
    };
 
1025
 
 
1026
 
 
1027
    /* We now support old Mac fonts where the OS/2 table doesn't  */
 
1028
    /* exist.  Simply put, we set the `version' field to 0xFFFF   */
 
1029
    /* and test this value each time we need to access the table. */
 
1030
    error = face->goto_table( face, TTAG_OS2, stream, 0 );
 
1031
    if ( error )
 
1032
      goto Exit;
 
1033
 
 
1034
    os2 = &face->os2;
 
1035
 
 
1036
    if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
 
1037
      goto Exit;
 
1038
 
 
1039
    os2->ulCodePageRange1 = 0;
 
1040
    os2->ulCodePageRange2 = 0;
 
1041
    os2->sxHeight         = 0;
 
1042
    os2->sCapHeight       = 0;
 
1043
    os2->usDefaultChar    = 0;
 
1044
    os2->usBreakChar      = 0;
 
1045
    os2->usMaxContext     = 0;
 
1046
 
 
1047
    if ( os2->version >= 0x0001 )
 
1048
    {
 
1049
      /* only version 1 tables */
 
1050
      if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
 
1051
        goto Exit;
 
1052
 
 
1053
      if ( os2->version >= 0x0002 )
 
1054
      {
 
1055
        /* only version 2 tables */
 
1056
        if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
 
1057
          goto Exit;
 
1058
      }
 
1059
    }
 
1060
 
 
1061
    FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
 
1062
    FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
 
1063
    FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
 
1064
    FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
 
1065
    FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
 
1066
 
 
1067
  Exit:
 
1068
    return error;
 
1069
  }
 
1070
 
 
1071
 
 
1072
  /*************************************************************************/
 
1073
  /*                                                                       */
 
1074
  /* <Function>                                                            */
 
1075
  /*    tt_face_load_postscript                                            */
 
1076
  /*                                                                       */
 
1077
  /* <Description>                                                         */
 
1078
  /*    Loads the Postscript table.                                        */
 
1079
  /*                                                                       */
 
1080
  /* <Input>                                                               */
 
1081
  /*    face   :: A handle to the target face object.                      */
 
1082
  /*                                                                       */
 
1083
  /*    stream :: A handle to the input stream.                            */
 
1084
  /*                                                                       */
 
1085
  /* <Return>                                                              */
 
1086
  /*    FreeType error code.  0 means success.                             */
 
1087
  /*                                                                       */
 
1088
  FT_LOCAL_DEF( FT_Error )
 
1089
  tt_face_load_post( TT_Face    face,
 
1090
                     FT_Stream  stream )
 
1091
  {
 
1092
    FT_Error        error;
 
1093
    TT_Postscript*  post = &face->postscript;
 
1094
 
 
1095
    static const FT_Frame_Field  post_fields[] =
 
1096
    {
 
1097
#undef  FT_STRUCTURE
 
1098
#define FT_STRUCTURE  TT_Postscript
 
1099
 
 
1100
      FT_FRAME_START( 32 ),
 
1101
        FT_FRAME_ULONG( FormatType ),
 
1102
        FT_FRAME_ULONG( italicAngle ),
 
1103
        FT_FRAME_SHORT( underlinePosition ),
 
1104
        FT_FRAME_SHORT( underlineThickness ),
 
1105
        FT_FRAME_ULONG( isFixedPitch ),
 
1106
        FT_FRAME_ULONG( minMemType42 ),
 
1107
        FT_FRAME_ULONG( maxMemType42 ),
 
1108
        FT_FRAME_ULONG( minMemType1 ),
 
1109
        FT_FRAME_ULONG( maxMemType1 ),
 
1110
      FT_FRAME_END
 
1111
    };
 
1112
 
 
1113
 
 
1114
    error = face->goto_table( face, TTAG_post, stream, 0 );
 
1115
    if ( error )
 
1116
      return error;
 
1117
 
 
1118
    if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
 
1119
      return error;
 
1120
 
 
1121
    /* we don't load the glyph names, we do that in another */
 
1122
    /* module (ttpost).                                     */
 
1123
 
 
1124
    FT_TRACE3(( "FormatType:   0x%x\n", post->FormatType ));
 
1125
    FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
 
1126
                                        ? "  yes" : "   no" ));
 
1127
 
 
1128
    return SFNT_Err_Ok;
 
1129
  }
 
1130
 
 
1131
 
 
1132
  /*************************************************************************/
 
1133
  /*                                                                       */
 
1134
  /* <Function>                                                            */
 
1135
  /*    tt_face_load_pclt                                                  */
 
1136
  /*                                                                       */
 
1137
  /* <Description>                                                         */
 
1138
  /*    Loads the PCL 5 Table.                                             */
 
1139
  /*                                                                       */
 
1140
  /* <Input>                                                               */
 
1141
  /*    face   :: A handle to the target face object.                      */
 
1142
  /*                                                                       */
 
1143
  /*    stream :: A handle to the input stream.                            */
 
1144
  /*                                                                       */
 
1145
  /* <Return>                                                              */
 
1146
  /*    FreeType error code.  0 means success.                             */
 
1147
  /*                                                                       */
 
1148
  FT_LOCAL_DEF( FT_Error )
 
1149
  tt_face_load_pclt( TT_Face    face,
 
1150
                     FT_Stream  stream )
 
1151
  {
 
1152
    static const FT_Frame_Field  pclt_fields[] =
 
1153
    {
 
1154
#undef  FT_STRUCTURE
 
1155
#define FT_STRUCTURE  TT_PCLT
 
1156
 
 
1157
      FT_FRAME_START( 54 ),
 
1158
        FT_FRAME_ULONG ( Version ),
 
1159
        FT_FRAME_ULONG ( FontNumber ),
 
1160
        FT_FRAME_USHORT( Pitch ),
 
1161
        FT_FRAME_USHORT( xHeight ),
 
1162
        FT_FRAME_USHORT( Style ),
 
1163
        FT_FRAME_USHORT( TypeFamily ),
 
1164
        FT_FRAME_USHORT( CapHeight ),
 
1165
        FT_FRAME_BYTES ( TypeFace, 16 ),
 
1166
        FT_FRAME_BYTES ( CharacterComplement, 8 ),
 
1167
        FT_FRAME_BYTES ( FileName, 6 ),
 
1168
        FT_FRAME_CHAR  ( StrokeWeight ),
 
1169
        FT_FRAME_CHAR  ( WidthType ),
 
1170
        FT_FRAME_BYTE  ( SerifStyle ),
 
1171
        FT_FRAME_BYTE  ( Reserved ),
 
1172
      FT_FRAME_END
 
1173
    };
 
1174
 
 
1175
    FT_Error  error;
 
1176
    TT_PCLT*  pclt = &face->pclt;
 
1177
 
 
1178
 
 
1179
    /* optional table */
 
1180
    error = face->goto_table( face, TTAG_PCLT, stream, 0 );
 
1181
    if ( error )
 
1182
      goto Exit;
 
1183
 
 
1184
    if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
 
1185
      goto Exit;
 
1186
 
 
1187
  Exit:
 
1188
    return error;
 
1189
  }
 
1190
 
 
1191
 
 
1192
  /*************************************************************************/
 
1193
  /*                                                                       */
 
1194
  /* <Function>                                                            */
 
1195
  /*    tt_face_load_gasp                                                  */
 
1196
  /*                                                                       */
 
1197
  /* <Description>                                                         */
 
1198
  /*    Loads the `gasp' table into a face object.                         */
 
1199
  /*                                                                       */
 
1200
  /* <Input>                                                               */
 
1201
  /*    face   :: A handle to the target face object.                      */
 
1202
  /*                                                                       */
 
1203
  /*    stream :: The input stream.                                        */
 
1204
  /*                                                                       */
 
1205
  /* <Return>                                                              */
 
1206
  /*    FreeType error code.  0 means success.                             */
 
1207
  /*                                                                       */
 
1208
  FT_LOCAL_DEF( FT_Error )
 
1209
  tt_face_load_gasp( TT_Face    face,
 
1210
                     FT_Stream  stream )
 
1211
  {
 
1212
    FT_Error   error;
 
1213
    FT_Memory  memory = stream->memory;
 
1214
 
 
1215
    FT_UInt        j,num_ranges;
 
1216
    TT_GaspRange   gaspranges;
 
1217
 
 
1218
 
 
1219
    /* the gasp table is optional */
 
1220
    error = face->goto_table( face, TTAG_gasp, stream, 0 );
 
1221
    if ( error )
 
1222
      goto Exit;
 
1223
 
 
1224
    if ( FT_FRAME_ENTER( 4L ) )
 
1225
      goto Exit;
 
1226
 
 
1227
    face->gasp.version   = FT_GET_USHORT();
 
1228
    face->gasp.numRanges = FT_GET_USHORT();
 
1229
 
 
1230
    FT_FRAME_EXIT();
 
1231
 
 
1232
    /* only support versions 0 and 1 of the table */
 
1233
    if ( face->gasp.version >= 2 )
 
1234
    {
 
1235
      face->gasp.numRanges = 0;
 
1236
      error = SFNT_Err_Invalid_Table;
 
1237
      goto Exit;
 
1238
    }
 
1239
 
 
1240
    num_ranges = face->gasp.numRanges;
 
1241
    FT_TRACE3(( "numRanges: %u\n", num_ranges ));
 
1242
 
 
1243
    if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
 
1244
         FT_FRAME_ENTER( num_ranges * 4L )      )
 
1245
      goto Exit;
 
1246
 
 
1247
    face->gasp.gaspRanges = gaspranges;
 
1248
 
 
1249
    for ( j = 0; j < num_ranges; j++ )
 
1250
    {
 
1251
      gaspranges[j].maxPPEM  = FT_GET_USHORT();
 
1252
      gaspranges[j].gaspFlag = FT_GET_USHORT();
 
1253
 
 
1254
      FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
 
1255
                  j,
 
1256
                  gaspranges[j].maxPPEM,
 
1257
                  gaspranges[j].gaspFlag ));
 
1258
    }
 
1259
 
 
1260
    FT_FRAME_EXIT();
 
1261
 
 
1262
  Exit:
 
1263
    return error;
 
1264
  }
 
1265
 
 
1266
 
 
1267
/* END */