XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / sfnt / ttload.c
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 */