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    for ( nn = 0; nn < sfnt.num_tables; nn++ )
388    {
389      entry->Tag      = FT_GET_TAG4();
390      entry->CheckSum = FT_GET_ULONG();
391      entry->Offset   = FT_GET_LONG();
392      entry->Length   = FT_GET_LONG();
393
394      /* ignore invalid tables */
395      if ( entry->Offset + entry->Length > stream->size )
396        continue;
397      else
398      {
399        FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
400                    (FT_Char)( entry->Tag >> 24 ),
401                    (FT_Char)( entry->Tag >> 16 ),
402                    (FT_Char)( entry->Tag >> 8  ),
403                    (FT_Char)( entry->Tag       ),
404                    entry->Offset,
405                    entry->Length ));
406        entry++;
407      }
408    }
409
410    FT_FRAME_EXIT();
411
412    FT_TRACE2(( "table directory loaded\n\n" ));
413
414  Exit:
415    return error;
416  }
417
418
419  /*************************************************************************/
420  /*                                                                       */
421  /* <Function>                                                            */
422  /*    tt_face_load_any                                                   */
423  /*                                                                       */
424  /* <Description>                                                         */
425  /*    Loads any font table into client memory.                           */
426  /*                                                                       */
427  /* <Input>                                                               */
428  /*    face   :: The face object to look for.                             */
429  /*                                                                       */
430  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
431  /*              to access the whole font file, else set this parameter   */
432  /*              to a valid TrueType table tag that you can forge with    */
433  /*              the MAKE_TT_TAG macro.                                   */
434  /*                                                                       */
435  /*    offset :: The starting offset in the table (or the file if         */
436  /*              tag == 0).                                               */
437  /*                                                                       */
438  /*    length :: The address of the decision variable:                    */
439  /*                                                                       */
440  /*                If length == NULL:                                     */
441  /*                  Loads the whole table.  Returns an error if          */
442  /*                  `offset' == 0!                                       */
443  /*                                                                       */
444  /*                If *length == 0:                                       */
445  /*                  Exits immediately; returning the length of the given */
446  /*                  table or of the font file, depending on the value of */
447  /*                  `tag'.                                               */
448  /*                                                                       */
449  /*                If *length != 0:                                       */
450  /*                  Loads the next `length' bytes of table or font,      */
451  /*                  starting at offset `offset' (in table or font too).  */
452  /*                                                                       */
453  /* <Output>                                                              */
454  /*    buffer :: The address of target buffer.                            */
455  /*                                                                       */
456  /* <Return>                                                              */
457  /*    FreeType error code.  0 means success.                             */
458  /*                                                                       */
459  FT_LOCAL_DEF( FT_Error )
460  tt_face_load_any( TT_Face    face,
461                    FT_ULong   tag,
462                    FT_Long    offset,
463                    FT_Byte*   buffer,
464                    FT_ULong*  length )
465  {
466    FT_Error   error;
467    FT_Stream  stream;
468    TT_Table   table;
469    FT_ULong   size;
470
471
472    if ( tag != 0 )
473    {
474      /* look for tag in font directory */
475      table = tt_face_lookup_table( face, tag );
476      if ( !table )
477      {
478        error = SFNT_Err_Table_Missing;
479        goto Exit;
480      }
481
482      offset += table->Offset;
483      size    = table->Length;
484    }
485    else
486      /* tag == 0 -- the user wants to access the font file directly */
487      size = face->root.stream->size;
488
489    if ( length && *length == 0 )
490    {
491      *length = size;
492
493      return SFNT_Err_Ok;
494    }
495
496    if ( length )
497      size = *length;
498
499    stream = face->root.stream;
500    /* the `if' is syntactic sugar for picky compilers */
501    if ( FT_STREAM_READ_AT( offset, buffer, size ) )
502      goto Exit;
503
504  Exit:
505    return error;
506  }
507
508
509  /*************************************************************************/
510  /*                                                                       */
511  /* <Function>                                                            */
512  /*    tt_face_load_generic_header                                        */
513  /*                                                                       */
514  /* <Description>                                                         */
515  /*    Loads the TrueType table `head' or `bhed'.                         */
516  /*                                                                       */
517  /* <Input>                                                               */
518  /*    face   :: A handle to the target face object.                      */
519  /*                                                                       */
520  /*    stream :: The input stream.                                        */
521  /*                                                                       */
522  /* <Return>                                                              */
523  /*    FreeType error code.  0 means success.                             */
524  /*                                                                       */
525  static FT_Error
526  tt_face_load_generic_header( TT_Face    face,
527                               FT_Stream  stream,
528                               FT_ULong   tag )
529  {
530    FT_Error    error;
531    TT_Header*  header;
532
533    static const FT_Frame_Field  header_fields[] =
534    {
535#undef  FT_STRUCTURE
536#define FT_STRUCTURE  TT_Header
537
538      FT_FRAME_START( 54 ),
539        FT_FRAME_ULONG ( Table_Version ),
540        FT_FRAME_ULONG ( Font_Revision ),
541        FT_FRAME_LONG  ( CheckSum_Adjust ),
542        FT_FRAME_LONG  ( Magic_Number ),
543        FT_FRAME_USHORT( Flags ),
544        FT_FRAME_USHORT( Units_Per_EM ),
545        FT_FRAME_LONG  ( Created[0] ),
546        FT_FRAME_LONG  ( Created[1] ),
547        FT_FRAME_LONG  ( Modified[0] ),
548        FT_FRAME_LONG  ( Modified[1] ),
549        FT_FRAME_SHORT ( xMin ),
550        FT_FRAME_SHORT ( yMin ),
551        FT_FRAME_SHORT ( xMax ),
552        FT_FRAME_SHORT ( yMax ),
553        FT_FRAME_USHORT( Mac_Style ),
554        FT_FRAME_USHORT( Lowest_Rec_PPEM ),
555        FT_FRAME_SHORT ( Font_Direction ),
556        FT_FRAME_SHORT ( Index_To_Loc_Format ),
557        FT_FRAME_SHORT ( Glyph_Data_Format ),
558      FT_FRAME_END
559    };
560
561
562    error = face->goto_table( face, tag, stream, 0 );
563    if ( error )
564      goto Exit;
565
566    header = &face->header;
567
568    if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
569      goto Exit;
570
571    FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
572    FT_TRACE3(( "IndexToLoc:   %4d\n", header->Index_To_Loc_Format ));
573
574  Exit:
575    return error;
576  }
577
578
579  FT_LOCAL_DEF( FT_Error )
580  tt_face_load_head( TT_Face    face,
581                     FT_Stream  stream )
582  {
583    return tt_face_load_generic_header( face, stream, TTAG_head );
584  }
585
586
587#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
588
589  FT_LOCAL_DEF( FT_Error )
590  tt_face_load_bhed( TT_Face    face,
591                     FT_Stream  stream )
592  {
593    return tt_face_load_generic_header( face, stream, TTAG_bhed );
594  }
595
596#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
597
598
599  /*************************************************************************/
600  /*                                                                       */
601  /* <Function>                                                            */
602  /*    tt_face_load_max_profile                                           */
603  /*                                                                       */
604  /* <Description>                                                         */
605  /*    Loads the maximum profile into a face object.                      */
606  /*                                                                       */
607  /* <Input>                                                               */
608  /*    face   :: A handle to the target face object.                      */
609  /*                                                                       */
610  /*    stream :: The input stream.                                        */
611  /*                                                                       */
612  /* <Return>                                                              */
613  /*    FreeType error code.  0 means success.                             */
614  /*                                                                       */
615  FT_LOCAL_DEF( FT_Error )
616  tt_face_load_maxp( TT_Face    face,
617                     FT_Stream  stream )
618  {
619    FT_Error        error;
620    TT_MaxProfile*  maxProfile = &face->max_profile;
621
622    const FT_Frame_Field  maxp_fields[] =
623    {
624#undef  FT_STRUCTURE
625#define FT_STRUCTURE  TT_MaxProfile
626
627      FT_FRAME_START( 6 ),
628        FT_FRAME_LONG  ( version ),
629        FT_FRAME_USHORT( numGlyphs ),
630      FT_FRAME_END
631    };
632
633    const FT_Frame_Field  maxp_fields_extra[] =
634    {
635      FT_FRAME_START( 26 ),
636        FT_FRAME_USHORT( maxPoints ),
637        FT_FRAME_USHORT( maxContours ),
638        FT_FRAME_USHORT( maxCompositePoints ),
639        FT_FRAME_USHORT( maxCompositeContours ),
640        FT_FRAME_USHORT( maxZones ),
641        FT_FRAME_USHORT( maxTwilightPoints ),
642        FT_FRAME_USHORT( maxStorage ),
643        FT_FRAME_USHORT( maxFunctionDefs ),
644        FT_FRAME_USHORT( maxInstructionDefs ),
645        FT_FRAME_USHORT( maxStackElements ),
646        FT_FRAME_USHORT( maxSizeOfInstructions ),
647        FT_FRAME_USHORT( maxComponentElements ),
648        FT_FRAME_USHORT( maxComponentDepth ),
649      FT_FRAME_END
650    };
651
652
653    error = face->goto_table( face, TTAG_maxp, stream, 0 );
654    if ( error )
655      goto Exit;
656
657    if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
658      goto Exit;
659
660    maxProfile->maxPoints             = 0;
661    maxProfile->maxContours           = 0;
662    maxProfile->maxCompositePoints    = 0;
663    maxProfile->maxCompositeContours  = 0;
664    maxProfile->maxZones              = 0;
665    maxProfile->maxTwilightPoints     = 0;
666    maxProfile->maxStorage            = 0;
667    maxProfile->maxFunctionDefs       = 0;
668    maxProfile->maxInstructionDefs    = 0;
669    maxProfile->maxStackElements      = 0;
670    maxProfile->maxSizeOfInstructions = 0;
671    maxProfile->maxComponentElements  = 0;
672    maxProfile->maxComponentDepth     = 0;
673
674    if ( maxProfile->version >= 0x10000L )
675    {
676      if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
677        goto Exit;
678
679      /* XXX: an adjustment that is necessary to load certain */
680      /*      broken fonts like `Keystrokes MT' :-(           */
681      /*                                                      */
682      /*   We allocate 64 function entries by default when    */
683      /*   the maxFunctionDefs field is null.                 */
684
685      if ( maxProfile->maxFunctionDefs == 0 )
686        maxProfile->maxFunctionDefs = 64;
687
688      /* we add 4 phantom points later */
689      if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
690      {
691        FT_TRACE0(( "tt_face_load_maxp:"
692                    " too much twilight points in `maxp' table;\n"
693                    "                  "
694                    " some glyphs might be rendered incorrectly\n" ));
695
696        maxProfile->maxTwilightPoints = 0xFFFFU - 4;
697      }
698
699      /* we arbitrarily limit recursion to avoid stack exhaustion */
700      if ( maxProfile->maxComponentDepth > 100 )
701      {
702        FT_TRACE0(( "tt_face_load_maxp:"
703                    " abnormally large component depth (%d) set to 100\n",
704                    maxProfile->maxComponentDepth ));
705        maxProfile->maxComponentDepth = 100;
706      }
707    }
708
709    FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
710
711  Exit:
712    return error;
713  }
714
715
716  /*************************************************************************/
717  /*                                                                       */
718  /* <Function>                                                            */
719  /*    tt_face_load_names                                                 */
720  /*                                                                       */
721  /* <Description>                                                         */
722  /*    Loads the name records.                                            */
723  /*                                                                       */
724  /* <Input>                                                               */
725  /*    face   :: A handle to the target face object.                      */
726  /*                                                                       */
727  /*    stream :: The input stream.                                        */
728  /*                                                                       */
729  /* <Return>                                                              */
730  /*    FreeType error code.  0 means success.                             */
731  /*                                                                       */
732  FT_LOCAL_DEF( FT_Error )
733  tt_face_load_name( TT_Face    face,
734                     FT_Stream  stream )
735  {
736    FT_Error      error;
737    FT_Memory     memory = stream->memory;
738    FT_ULong      table_pos, table_len;
739    FT_ULong      storage_start, storage_limit;
740    FT_UInt       count;
741    TT_NameTable  table;
742
743    static const FT_Frame_Field  name_table_fields[] =
744    {
745#undef  FT_STRUCTURE
746#define FT_STRUCTURE  TT_NameTableRec
747
748      FT_FRAME_START( 6 ),
749        FT_FRAME_USHORT( format ),
750        FT_FRAME_USHORT( numNameRecords ),
751        FT_FRAME_USHORT( storageOffset ),
752      FT_FRAME_END
753    };
754
755    static const FT_Frame_Field  name_record_fields[] =
756    {
757#undef  FT_STRUCTURE
758#define FT_STRUCTURE  TT_NameEntryRec
759
760      /* no FT_FRAME_START */
761        FT_FRAME_USHORT( platformID ),
762        FT_FRAME_USHORT( encodingID ),
763        FT_FRAME_USHORT( languageID ),
764        FT_FRAME_USHORT( nameID ),
765        FT_FRAME_USHORT( stringLength ),
766        FT_FRAME_USHORT( stringOffset ),
767      FT_FRAME_END
768    };
769
770
771    table         = &face->name_table;
772    table->stream = stream;
773
774    error = face->goto_table( face, TTAG_name, stream, &table_len );
775    if ( error )
776      goto Exit;
777
778    table_pos = FT_STREAM_POS();
779
780
781    if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
782      goto Exit;
783
784    /* Some popular Asian fonts have an invalid `storageOffset' value   */
785    /* (it should be at least "6 + 12*num_names").  However, the string */
786    /* offsets, computed as "storageOffset + entry->stringOffset", are  */
787    /* valid pointers within the name table...                          */
788    /*                                                                  */
789    /* We thus can't check `storageOffset' right now.                   */
790    /*                                                                  */
791    storage_start = table_pos + 6 + 12*table->numNameRecords;
792    storage_limit = table_pos + table_len;
793
794    if ( storage_start > storage_limit )
795    {
796      FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
797      error = SFNT_Err_Name_Table_Missing;
798      goto Exit;
799    }
800
801    /* Allocate the array of name records. */
802    count                 = table->numNameRecords;
803    table->numNameRecords = 0;
804
805    if ( FT_NEW_ARRAY( table->names, count ) ||
806         FT_FRAME_ENTER( count * 12 )        )
807      goto Exit;
808
809    /* Load the name records and determine how much storage is needed */
810    /* to hold the strings themselves.                                */
811    {
812      TT_NameEntryRec*  entry = table->names;
813
814
815      for ( ; count > 0; count-- )
816      {
817        if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
818          continue;
819
820        /* check that the name is not empty */
821        if ( entry->stringLength == 0 )
822          continue;
823
824        /* check that the name string is within the table */
825        entry->stringOffset += table_pos + table->storageOffset;
826        if ( entry->stringOffset                       < storage_start ||
827             entry->stringOffset + entry->stringLength > storage_limit )
828        {
829          /* invalid entry - ignore it */
830          entry->stringOffset = 0;
831          entry->stringLength = 0;
832          continue;
833        }
834
835        entry++;
836      }
837
838      table->numNameRecords = (FT_UInt)( entry - table->names );
839    }
840
841    FT_FRAME_EXIT();
842
843    /* everything went well, update face->num_names */
844    face->num_names = (FT_UShort) table->numNameRecords;
845
846  Exit:
847    return error;
848  }
849
850
851  /*************************************************************************/
852  /*                                                                       */
853  /* <Function>                                                            */
854  /*    tt_face_free_names                                                 */
855  /*                                                                       */
856  /* <Description>                                                         */
857  /*    Frees the name records.                                            */
858  /*                                                                       */
859  /* <Input>                                                               */
860  /*    face :: A handle to the target face object.                        */
861  /*                                                                       */
862  FT_LOCAL_DEF( void )
863  tt_face_free_name( TT_Face  face )
864  {
865    FT_Memory     memory = face->root.driver->root.memory;
866    TT_NameTable  table  = &face->name_table;
867    TT_NameEntry  entry  = table->names;
868    FT_UInt       count  = table->numNameRecords;
869
870
871    if ( table->names )
872    {
873      for ( ; count > 0; count--, entry++ )
874      {
875        FT_FREE( entry->string );
876        entry->stringLength = 0;
877      }
878
879      /* free strings table */
880      FT_FREE( table->names );
881    }
882
883    table->numNameRecords = 0;
884    table->format         = 0;
885    table->storageOffset  = 0;
886  }
887
888
889  /*************************************************************************/
890  /*                                                                       */
891  /* <Function>                                                            */
892  /*    tt_face_load_cmap                                                  */
893  /*                                                                       */
894  /* <Description>                                                         */
895  /*    Loads the cmap directory in a face object.  The cmaps themselves   */
896  /*    are loaded on demand in the `ttcmap.c' module.                     */
897  /*                                                                       */
898  /* <Input>                                                               */
899  /*    face   :: A handle to the target face object.                      */
900  /*                                                                       */
901  /*    stream :: A handle to the input stream.                            */
902  /*                                                                       */
903  /* <Return>                                                              */
904  /*    FreeType error code.  0 means success.                             */
905  /*                                                                       */
906
907  FT_LOCAL_DEF( FT_Error )
908  tt_face_load_cmap( TT_Face    face,
909                     FT_Stream  stream )
910  {
911    FT_Error  error;
912
913
914    error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
915    if ( error )
916      goto Exit;
917
918    if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
919      face->cmap_size = 0;
920
921  Exit:
922    return error;
923  }
924
925
926
927  /*************************************************************************/
928  /*                                                                       */
929  /* <Function>                                                            */
930  /*    tt_face_load_os2                                                   */
931  /*                                                                       */
932  /* <Description>                                                         */
933  /*    Loads the OS2 table.                                               */
934  /*                                                                       */
935  /* <Input>                                                               */
936  /*    face   :: A handle to the target face object.                      */
937  /*                                                                       */
938  /*    stream :: A handle to the input stream.                            */
939  /*                                                                       */
940  /* <Return>                                                              */
941  /*    FreeType error code.  0 means success.                             */
942  /*                                                                       */
943  FT_LOCAL_DEF( FT_Error )
944  tt_face_load_os2( TT_Face    face,
945                    FT_Stream  stream )
946  {
947    FT_Error  error;
948    TT_OS2*   os2;
949
950    const FT_Frame_Field  os2_fields[] =
951    {
952#undef  FT_STRUCTURE
953#define FT_STRUCTURE  TT_OS2
954
955      FT_FRAME_START( 78 ),
956        FT_FRAME_USHORT( version ),
957        FT_FRAME_SHORT ( xAvgCharWidth ),
958        FT_FRAME_USHORT( usWeightClass ),
959        FT_FRAME_USHORT( usWidthClass ),
960        FT_FRAME_SHORT ( fsType ),
961        FT_FRAME_SHORT ( ySubscriptXSize ),
962        FT_FRAME_SHORT ( ySubscriptYSize ),
963        FT_FRAME_SHORT ( ySubscriptXOffset ),
964        FT_FRAME_SHORT ( ySubscriptYOffset ),
965        FT_FRAME_SHORT ( ySuperscriptXSize ),
966        FT_FRAME_SHORT ( ySuperscriptYSize ),
967        FT_FRAME_SHORT ( ySuperscriptXOffset ),
968        FT_FRAME_SHORT ( ySuperscriptYOffset ),
969        FT_FRAME_SHORT ( yStrikeoutSize ),
970        FT_FRAME_SHORT ( yStrikeoutPosition ),
971        FT_FRAME_SHORT ( sFamilyClass ),
972        FT_FRAME_BYTE  ( panose[0] ),
973        FT_FRAME_BYTE  ( panose[1] ),
974        FT_FRAME_BYTE  ( panose[2] ),
975        FT_FRAME_BYTE  ( panose[3] ),
976        FT_FRAME_BYTE  ( panose[4] ),
977        FT_FRAME_BYTE  ( panose[5] ),
978        FT_FRAME_BYTE  ( panose[6] ),
979        FT_FRAME_BYTE  ( panose[7] ),
980        FT_FRAME_BYTE  ( panose[8] ),
981        FT_FRAME_BYTE  ( panose[9] ),
982        FT_FRAME_ULONG ( ulUnicodeRange1 ),
983        FT_FRAME_ULONG ( ulUnicodeRange2 ),
984        FT_FRAME_ULONG ( ulUnicodeRange3 ),
985        FT_FRAME_ULONG ( ulUnicodeRange4 ),
986        FT_FRAME_BYTE  ( achVendID[0] ),
987        FT_FRAME_BYTE  ( achVendID[1] ),
988        FT_FRAME_BYTE  ( achVendID[2] ),
989        FT_FRAME_BYTE  ( achVendID[3] ),
990
991        FT_FRAME_USHORT( fsSelection ),
992        FT_FRAME_USHORT( usFirstCharIndex ),
993        FT_FRAME_USHORT( usLastCharIndex ),
994        FT_FRAME_SHORT ( sTypoAscender ),
995        FT_FRAME_SHORT ( sTypoDescender ),
996        FT_FRAME_SHORT ( sTypoLineGap ),
997        FT_FRAME_USHORT( usWinAscent ),
998        FT_FRAME_USHORT( usWinDescent ),
999      FT_FRAME_END
1000    };
1001
1002    const FT_Frame_Field  os2_fields_extra[] =
1003    {
1004      FT_FRAME_START( 8 ),
1005        FT_FRAME_ULONG( ulCodePageRange1 ),
1006        FT_FRAME_ULONG( ulCodePageRange2 ),
1007      FT_FRAME_END
1008    };
1009
1010    const FT_Frame_Field  os2_fields_extra2[] =
1011    {
1012      FT_FRAME_START( 10 ),
1013        FT_FRAME_SHORT ( sxHeight ),
1014        FT_FRAME_SHORT ( sCapHeight ),
1015        FT_FRAME_USHORT( usDefaultChar ),
1016        FT_FRAME_USHORT( usBreakChar ),
1017        FT_FRAME_USHORT( usMaxContext ),
1018      FT_FRAME_END
1019    };
1020
1021
1022    /* We now support old Mac fonts where the OS/2 table doesn't  */
1023    /* exist.  Simply put, we set the `version' field to 0xFFFF   */
1024    /* and test this value each time we need to access the table. */
1025    error = face->goto_table( face, TTAG_OS2, stream, 0 );
1026    if ( error )
1027      goto Exit;
1028
1029    os2 = &face->os2;
1030
1031    if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
1032      goto Exit;
1033
1034    os2->ulCodePageRange1 = 0;
1035    os2->ulCodePageRange2 = 0;
1036    os2->sxHeight         = 0;
1037    os2->sCapHeight       = 0;
1038    os2->usDefaultChar    = 0;
1039    os2->usBreakChar      = 0;
1040    os2->usMaxContext     = 0;
1041
1042    if ( os2->version >= 0x0001 )
1043    {
1044      /* only version 1 tables */
1045      if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
1046        goto Exit;
1047
1048      if ( os2->version >= 0x0002 )
1049      {
1050        /* only version 2 tables */
1051        if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
1052          goto Exit;
1053      }
1054    }
1055
1056    FT_TRACE3(( "sTypoAscender:  %4d\n",   os2->sTypoAscender ));
1057    FT_TRACE3(( "sTypoDescender: %4d\n",   os2->sTypoDescender ));
1058    FT_TRACE3(( "usWinAscent:    %4u\n",   os2->usWinAscent ));
1059    FT_TRACE3(( "usWinDescent:   %4u\n",   os2->usWinDescent ));
1060    FT_TRACE3(( "fsSelection:    0x%2x\n", os2->fsSelection ));
1061
1062  Exit:
1063    return error;
1064  }
1065
1066
1067  /*************************************************************************/
1068  /*                                                                       */
1069  /* <Function>                                                            */
1070  /*    tt_face_load_postscript                                            */
1071  /*                                                                       */
1072  /* <Description>                                                         */
1073  /*    Loads the Postscript table.                                        */
1074  /*                                                                       */
1075  /* <Input>                                                               */
1076  /*    face   :: A handle to the target face object.                      */
1077  /*                                                                       */
1078  /*    stream :: A handle to the input stream.                            */
1079  /*                                                                       */
1080  /* <Return>                                                              */
1081  /*    FreeType error code.  0 means success.                             */
1082  /*                                                                       */
1083  FT_LOCAL_DEF( FT_Error )
1084  tt_face_load_post( TT_Face    face,
1085                     FT_Stream  stream )
1086  {
1087    FT_Error        error;
1088    TT_Postscript*  post = &face->postscript;
1089
1090    static const FT_Frame_Field  post_fields[] =
1091    {
1092#undef  FT_STRUCTURE
1093#define FT_STRUCTURE  TT_Postscript
1094
1095      FT_FRAME_START( 32 ),
1096        FT_FRAME_ULONG( FormatType ),
1097        FT_FRAME_ULONG( italicAngle ),
1098        FT_FRAME_SHORT( underlinePosition ),
1099        FT_FRAME_SHORT( underlineThickness ),
1100        FT_FRAME_ULONG( isFixedPitch ),
1101        FT_FRAME_ULONG( minMemType42 ),
1102        FT_FRAME_ULONG( maxMemType42 ),
1103        FT_FRAME_ULONG( minMemType1 ),
1104        FT_FRAME_ULONG( maxMemType1 ),
1105      FT_FRAME_END
1106    };
1107
1108
1109    error = face->goto_table( face, TTAG_post, stream, 0 );
1110    if ( error )
1111      return error;
1112
1113    if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
1114      return error;
1115
1116    /* we don't load the glyph names, we do that in another */
1117    /* module (ttpost).                                     */
1118
1119    FT_TRACE3(( "FormatType:   0x%x\n", post->FormatType ));
1120    FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
1121                                        ? "  yes" : "   no" ));
1122
1123    return SFNT_Err_Ok;
1124  }
1125
1126
1127  /*************************************************************************/
1128  /*                                                                       */
1129  /* <Function>                                                            */
1130  /*    tt_face_load_pclt                                                  */
1131  /*                                                                       */
1132  /* <Description>                                                         */
1133  /*    Loads the PCL 5 Table.                                             */
1134  /*                                                                       */
1135  /* <Input>                                                               */
1136  /*    face   :: A handle to the target face object.                      */
1137  /*                                                                       */
1138  /*    stream :: A handle to the input stream.                            */
1139  /*                                                                       */
1140  /* <Return>                                                              */
1141  /*    FreeType error code.  0 means success.                             */
1142  /*                                                                       */
1143  FT_LOCAL_DEF( FT_Error )
1144  tt_face_load_pclt( TT_Face    face,
1145                     FT_Stream  stream )
1146  {
1147    static const FT_Frame_Field  pclt_fields[] =
1148    {
1149#undef  FT_STRUCTURE
1150#define FT_STRUCTURE  TT_PCLT
1151
1152      FT_FRAME_START( 54 ),
1153        FT_FRAME_ULONG ( Version ),
1154        FT_FRAME_ULONG ( FontNumber ),
1155        FT_FRAME_USHORT( Pitch ),
1156        FT_FRAME_USHORT( xHeight ),
1157        FT_FRAME_USHORT( Style ),
1158        FT_FRAME_USHORT( TypeFamily ),
1159        FT_FRAME_USHORT( CapHeight ),
1160        FT_FRAME_BYTES ( TypeFace, 16 ),
1161        FT_FRAME_BYTES ( CharacterComplement, 8 ),
1162        FT_FRAME_BYTES ( FileName, 6 ),
1163        FT_FRAME_CHAR  ( StrokeWeight ),
1164        FT_FRAME_CHAR  ( WidthType ),
1165        FT_FRAME_BYTE  ( SerifStyle ),
1166        FT_FRAME_BYTE  ( Reserved ),
1167      FT_FRAME_END
1168    };
1169
1170    FT_Error  error;
1171    TT_PCLT*  pclt = &face->pclt;
1172
1173
1174    /* optional table */
1175    error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1176    if ( error )
1177      goto Exit;
1178
1179    if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
1180      goto Exit;
1181
1182  Exit:
1183    return error;
1184  }
1185
1186
1187  /*************************************************************************/
1188  /*                                                                       */
1189  /* <Function>                                                            */
1190  /*    tt_face_load_gasp                                                  */
1191  /*                                                                       */
1192  /* <Description>                                                         */
1193  /*    Loads the `gasp' table into a face object.                         */
1194  /*                                                                       */
1195  /* <Input>                                                               */
1196  /*    face   :: A handle to the target face object.                      */
1197  /*                                                                       */
1198  /*    stream :: The input stream.                                        */
1199  /*                                                                       */
1200  /* <Return>                                                              */
1201  /*    FreeType error code.  0 means success.                             */
1202  /*                                                                       */
1203  FT_LOCAL_DEF( FT_Error )
1204  tt_face_load_gasp( TT_Face    face,
1205                     FT_Stream  stream )
1206  {
1207    FT_Error   error;
1208    FT_Memory  memory = stream->memory;
1209
1210    FT_UInt        j,num_ranges;
1211    TT_GaspRange   gaspranges;
1212
1213
1214    /* the gasp table is optional */
1215    error = face->goto_table( face, TTAG_gasp, stream, 0 );
1216    if ( error )
1217      goto Exit;
1218
1219    if ( FT_FRAME_ENTER( 4L ) )
1220      goto Exit;
1221
1222    face->gasp.version   = FT_GET_USHORT();
1223    face->gasp.numRanges = FT_GET_USHORT();
1224
1225    FT_FRAME_EXIT();
1226
1227    /* only support versions 0 and 1 of the table */
1228    if ( face->gasp.version >= 2 )
1229    {
1230      face->gasp.numRanges = 0;
1231      error = SFNT_Err_Invalid_Table;
1232      goto Exit;
1233    }
1234
1235    num_ranges = face->gasp.numRanges;
1236    FT_TRACE3(( "numRanges: %u\n", num_ranges ));
1237
1238    if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
1239         FT_FRAME_ENTER( num_ranges * 4L )      )
1240      goto Exit;
1241
1242    face->gasp.gaspRanges = gaspranges;
1243
1244    for ( j = 0; j < num_ranges; j++ )
1245    {
1246      gaspranges[j].maxPPEM  = FT_GET_USHORT();
1247      gaspranges[j].gaspFlag = FT_GET_USHORT();
1248
1249      FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
1250                  j,
1251                  gaspranges[j].maxPPEM,
1252                  gaspranges[j].gaspFlag ));
1253    }
1254
1255    FT_FRAME_EXIT();
1256
1257  Exit:
1258    return error;
1259  }
1260
1261
1262/* END */
1263