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