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