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