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