source: trunk/poppler/freetype-2.1.10/src/sfnt/ttload.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

File size: 67.7 KB
Line 
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 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  )
56  tt_face_lookup_table( TT_Face   face,
57                        FT_ULong  tag  )
58  {
59    TT_Table  entry;
60    TT_Table  limit;
61
62
63    FT_TRACE3(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
64                face,
65                (FT_Char)( tag >> 24 ),
66                (FT_Char)( tag >> 16 ),
67                (FT_Char)( tag >> 8  ),
68                (FT_Char)( tag       ) ));
69
70    entry = face->dir_tables;
71    limit = entry + face->num_tables;
72
73    for ( ; entry < limit; entry++ )
74    {
75      /* For compatibility with Windows, we consider 0-length */
76      /* tables the same as missing tables.                   */
77      if ( entry->Tag == tag && entry->Length != 0 )
78      {
79        FT_TRACE3(( "found table.\n" ));
80        return entry;
81      }
82    }
83
84    FT_TRACE3(( "could not find table!\n" ));
85    return 0;
86  }
87
88
89  /*************************************************************************/
90  /*                                                                       */
91  /* <Function>                                                            */
92  /*    tt_face_goto_table                                                 */
93  /*                                                                       */
94  /* <Description>                                                         */
95  /*    Looks for a TrueType table by name, then seek a stream to it.      */
96  /*                                                                       */
97  /* <Input>                                                               */
98  /*    face   :: A face object handle.                                    */
99  /*                                                                       */
100  /*    tag    :: The searched tag.                                        */
101  /*                                                                       */
102  /*    stream :: The stream to seek when the table is found.              */
103  /*                                                                       */
104  /* <Output>                                                              */
105  /*    length :: The length of the table if found, undefined otherwise.   */
106  /*                                                                       */
107  /* <Return>                                                              */
108  /*    FreeType error code.  0 means success.                             */
109  /*                                                                       */
110  FT_LOCAL_DEF( FT_Error )
111  tt_face_goto_table( TT_Face    face,
112                      FT_ULong   tag,
113                      FT_Stream  stream,
114                      FT_ULong*  length )
115  {
116    TT_Table  table;
117    FT_Error  error;
118
119
120    table = tt_face_lookup_table( face, tag );
121    if ( table )
122    {
123      if ( length )
124        *length = table->Length;
125
126      if ( FT_STREAM_SEEK( table->Offset ) )
127       goto Exit;
128    }
129    else
130      error = SFNT_Err_Table_Missing;
131
132  Exit:
133    return error;
134  }
135
136
137  /* In theory, we should check the values of `search_range',              */
138  /* `entry_selector', and `range_shift' to detect non-SFNT based files    */
139  /* whose header might also start with 0x100000L (yes, these exist).      */
140  /*                                                                       */
141  /* Very unfortunately, many TrueType fonts don't have these fields       */
142  /* set correctly and we must ignore them to support them.  An            */
143  /* alternative way to check the font file is thus to:                    */
144  /*                                                                       */
145  /* - check that `num_tables' is valid                                    */
146  /* - look for a "head" table, check its size, and parse it to            */
147  /*   see if its "magic" field is correctly set                           */
148  /*                                                                       */
149  /* When checking directory entries, ignore the tables `glyx' and `locx'  */
150  /* which are hacked-out versions of `glyf' and `loca' in some PostScript */
151  /* Type 42 fonts, and will generally be invalid.                         */
152  /*                                                                       */
153  static FT_Error
154  sfnt_dir_check( FT_Stream  stream,
155                  FT_ULong   offset,
156                  FT_UInt    num_tables )
157   {
158    FT_Error        error;
159    FT_UInt         nn, has_head = 0;
160
161    const FT_ULong  glyx_tag = FT_MAKE_TAG( 'g', 'l', 'y', 'x' );
162    const FT_ULong  locx_tag = FT_MAKE_TAG( 'l', 'o', 'c', 'x' );
163
164    static const FT_Frame_Field  sfnt_dir_entry_fields[] =
165    {
166#undef  FT_STRUCTURE
167#define FT_STRUCTURE  TT_TableRec
168
169      FT_FRAME_START( 16 ),
170        FT_FRAME_ULONG( Tag ),
171        FT_FRAME_ULONG( CheckSum ),
172        FT_FRAME_ULONG( Offset ),
173        FT_FRAME_ULONG( Length ),
174      FT_FRAME_END
175    };
176
177
178    /* if 'num_tables' is 0, read the table count from the file */
179    if ( num_tables == 0 )
180    {
181      if ( FT_STREAM_SEEK( offset )     ||
182           FT_STREAM_SKIP( 4 )          ||
183           FT_READ_USHORT( num_tables ) ||
184           FT_STREAM_SKIP( 6 )          )
185        goto Bad_Format;
186
187      if ( offset + 12 + num_tables*16 > stream->size )
188        goto Bad_Format;
189    }
190    else if ( FT_STREAM_SEEK( offset + 12 ) )
191      goto Bad_Format;
192
193    for ( nn = 0; nn < num_tables; nn++ )
194    {
195      TT_TableRec  table;
196
197
198      if ( FT_STREAM_READ_FIELDS( sfnt_dir_entry_fields, &table ) )
199        goto Bad_Format;
200
201      if ( table.Offset + table.Length > stream->size     &&
202           table.Tag != glyx_tag && table.Tag != locx_tag )
203        goto Bad_Format;
204
205      if ( table.Tag == TTAG_head )
206      {
207        FT_UInt32  magic;
208
209
210#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
211      head_retry:
212#endif  /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
213
214        has_head = 1;
215
216        /* The table length should be 0x36, but certain font tools
217         * make it 0x38, so we will just check that it is greater.
218         *
219         * Note that according to the specification,
220         * the table must be padded to 32-bit lengths, but this doesn't
221         * apply to the value of its "Length" field!
222         */
223        if ( table.Length < 0x36                 ||
224             FT_STREAM_SEEK( table.Offset + 12 ) ||
225             FT_READ_ULONG( magic )              ||
226             magic != 0x5F0F3CF5UL               )
227          goto Bad_Format;
228
229        if ( FT_STREAM_SEEK( offset + 28 + 16*nn ) )
230          goto Bad_Format;
231      }
232#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
233      else if ( table.Tag == TTAG_bhed )
234        goto head_retry;
235#endif  /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */     
236    }
237
238    if ( has_head == 0 )
239      goto Bad_Format;
240
241  Exit:
242    return error;
243
244  Bad_Format:
245    error = SFNT_Err_Unknown_File_Format;
246    goto Exit;
247  }
248
249
250  /*************************************************************************/
251  /*                                                                       */
252  /* <Function>                                                            */
253  /*    tt_face_load_sfnt_header                                           */
254  /*                                                                       */
255  /* <Description>                                                         */
256  /*    Loads the header of a SFNT font file.  Supports collections.       */
257  /*                                                                       */
258  /* <Input>                                                               */
259  /*    face       :: A handle to the target face object.                  */
260  /*                                                                       */
261  /*    stream     :: The input stream.                                    */
262  /*                                                                       */
263  /*    face_index :: If the font is a collection, the number of the font  */
264  /*                  in the collection.  Must be zero otherwise.          */
265  /*                                                                       */
266  /* <Output>                                                              */
267  /*    sfnt       :: The SFNT header.                                     */
268  /*                                                                       */
269  /* <Return>                                                              */
270  /*    FreeType error code.  0 means success.                             */
271  /*                                                                       */
272  /* <Note>                                                                */
273  /*    The stream cursor must be at the font file's origin.               */
274  /*                                                                       */
275  /*    This function recognizes fonts embedded in a `TrueType collection' */
276  /*                                                                       */
277  /*    The header will be checked whether it is valid by looking at the   */
278  /*    values of `search_range', `entry_selector', and `range_shift'.     */
279  /*                                                                       */
280  FT_LOCAL_DEF( FT_Error )
281  tt_face_load_sfnt_header( TT_Face      face,
282                            FT_Stream    stream,
283                            FT_Long      face_index,
284                            SFNT_Header  sfnt )
285  {
286    FT_Error   error;
287    FT_ULong   font_format_tag, format_tag, offset;
288    FT_Memory  memory = stream->memory;
289
290    static const FT_Frame_Field  sfnt_header_fields[] =
291    {
292#undef  FT_STRUCTURE
293#define FT_STRUCTURE  SFNT_HeaderRec
294
295      FT_FRAME_START( 8 ),
296        FT_FRAME_USHORT( num_tables ),
297        FT_FRAME_USHORT( search_range ),
298        FT_FRAME_USHORT( entry_selector ),
299        FT_FRAME_USHORT( range_shift ),
300      FT_FRAME_END
301    };
302
303    static const FT_Frame_Field  ttc_header_fields[] =
304    {
305#undef  FT_STRUCTURE
306#define FT_STRUCTURE  TTC_HeaderRec
307
308      FT_FRAME_START( 8 ),
309        FT_FRAME_LONG( version ),
310        FT_FRAME_LONG( count   ),
311      FT_FRAME_END
312    };
313
314
315    FT_TRACE2(( "tt_face_load_sfnt_header: %08p, %ld\n",
316                face, face_index ));
317
318    face->ttc_header.tag     = 0;
319    face->ttc_header.version = 0;
320    face->ttc_header.count   = 0;
321
322    face->num_tables = 0;
323
324    /* First of all, read the first 4 bytes.  If it is `ttcf', then the   */
325    /* file is a TrueType collection, otherwise it is a single-face font. */
326    /*                                                                    */
327    offset = FT_STREAM_POS();
328
329    if ( FT_READ_ULONG( font_format_tag ) )
330      goto Exit;
331
332    format_tag = font_format_tag;
333
334    if ( font_format_tag == TTAG_ttcf )
335    {
336      FT_Int  n;
337
338
339      FT_TRACE3(( "tt_face_load_sfnt_header: file is a collection\n" ));
340
341      /* It is a TrueType collection, i.e. a file containing several */
342      /* font files.  Read the font directory now                    */
343      if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) )
344        goto Exit;
345
346      /* now read the offsets of each font in the file */
347      if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ||
348           FT_FRAME_ENTER( face->ttc_header.count * 4L )                    )
349        goto Exit;
350
351      for ( n = 0; n < face->ttc_header.count; n++ )
352        face->ttc_header.offsets[n] = FT_GET_ULONG();
353
354      FT_FRAME_EXIT();
355
356      /* check face index */
357      if ( face_index >= face->ttc_header.count )
358      {
359        error = SFNT_Err_Bad_Argument;
360        goto Exit;
361      }
362
363      /* seek to the appropriate TrueType file, then read tag */
364      offset = face->ttc_header.offsets[face_index];
365
366      if ( FT_STREAM_SEEK( offset )   ||
367           FT_READ_LONG( format_tag ) )
368        goto Exit;
369    }
370
371    /* the format tag was read, now check the rest of the header */
372    sfnt->format_tag = format_tag;
373    sfnt->offset     = offset;
374
375    if ( FT_STREAM_READ_FIELDS( sfnt_header_fields, sfnt ) )
376      goto Exit;
377
378    /* now check the sfnt directory */
379    error = sfnt_dir_check( stream, offset, sfnt->num_tables );
380    if ( error )
381    {
382      FT_TRACE2(( "tt_face_load_sfnt_header: file is not SFNT!\n" ));
383      error = SFNT_Err_Unknown_File_Format;
384      goto Exit;
385    }
386
387    /* disallow face index values > 0 for non-TTC files */
388    if ( font_format_tag != TTAG_ttcf && face_index > 0 )
389      error = SFNT_Err_Bad_Argument;
390
391  Exit:
392    return error;
393  }
394
395
396  /*************************************************************************/
397  /*                                                                       */
398  /* <Function>                                                            */
399  /*    tt_face_load_directory                                             */
400  /*                                                                       */
401  /* <Description>                                                         */
402  /*    Loads the table directory into a face object.                      */
403  /*                                                                       */
404  /* <InOut>                                                               */
405  /*    face   :: A handle to the target face object.                      */
406  /*                                                                       */
407  /* <Input>                                                               */
408  /*    stream :: The input stream.                                        */
409  /*                                                                       */
410  /*    sfnt   :: The SFNT directory header.                               */
411  /*                                                                       */
412  /* <Return>                                                              */
413  /*    FreeType error code.  0 means success.                             */
414  /*                                                                       */
415  /* <Note>                                                                */
416  /*    The stream cursor must be at the font file's origin.               */
417  /*                                                                       */
418  FT_LOCAL_DEF( FT_Error )
419  tt_face_load_directory( TT_Face      face,
420                          FT_Stream    stream,
421                          SFNT_Header  sfnt )
422  {
423    FT_Error     error;
424    FT_Memory    memory = stream->memory;
425
426    TT_TableRec  *entry, *limit;
427
428
429    FT_TRACE2(( "tt_face_load_directory: %08p\n", face ));
430
431    FT_TRACE2(( "-- Tables count:   %12u\n",  sfnt->num_tables ));
432    FT_TRACE2(( "-- Format version: %08lx\n", sfnt->format_tag ));
433
434    face->num_tables = sfnt->num_tables;
435
436    if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
437      goto Exit;
438
439    if ( FT_STREAM_SEEK( sfnt->offset + 12 )      ||
440         FT_FRAME_ENTER( face->num_tables * 16L ) )
441      goto Exit;
442
443    entry = face->dir_tables;
444    limit = entry + face->num_tables;
445
446    for ( ; entry < limit; entry++ )
447    {                    /* loop through the tables and get all entries */
448      entry->Tag      = FT_GET_TAG4();
449      entry->CheckSum = FT_GET_ULONG();
450      entry->Offset   = FT_GET_LONG();
451      entry->Length   = FT_GET_LONG();
452
453      FT_TRACE2(( "  %c%c%c%c  -  %08lx  -  %08lx\n",
454                  (FT_Char)( entry->Tag >> 24 ),
455                  (FT_Char)( entry->Tag >> 16 ),
456                  (FT_Char)( entry->Tag >> 8  ),
457                  (FT_Char)( entry->Tag       ),
458                  entry->Offset,
459                  entry->Length ));
460    }
461
462    FT_FRAME_EXIT();
463
464    FT_TRACE2(( "Directory loaded\n\n" ));
465
466  Exit:
467    return error;
468  }
469
470
471  /*************************************************************************/
472  /*                                                                       */
473  /* <Function>                                                            */
474  /*    tt_face_load_any                                                   */
475  /*                                                                       */
476  /* <Description>                                                         */
477  /*    Loads any font table into client memory.                           */
478  /*                                                                       */
479  /* <Input>                                                               */
480  /*    face   :: The face object to look for.                             */
481  /*                                                                       */
482  /*    tag    :: The tag of table to load.  Use the value 0 if you want   */
483  /*              to access the whole font file, else set this parameter   */
484  /*              to a valid TrueType table tag that you can forge with    */
485  /*              the MAKE_TT_TAG macro.                                   */
486  /*                                                                       */
487  /*    offset :: The starting offset in the table (or the file if         */
488  /*              tag == 0).                                               */
489  /*                                                                       */
490  /*    length :: The address of the decision variable:                    */
491  /*                                                                       */
492  /*                If length == NULL:                                     */
493  /*                  Loads the whole table.  Returns an error if          */
494  /*                  `offset' == 0!                                       */
495  /*                                                                       */
496  /*                If *length == 0:                                       */
497  /*                  Exits immediately; returning the length of the given */
498  /*                  table or of the font file, depending on the value of */
499  /*                  `tag'.                                               */
500  /*                                                                       */
501  /*                If *length != 0:                                       */
502  /*                  Loads the next `length' bytes of table or font,      */
503  /*                  starting at offset `offset' (in table or font too).  */
504  /*                                                                       */
505  /* <Output>                                                              */
506  /*    buffer :: The address of target buffer.                            */
507  /*                                                                       */
508  /* <Return>                                                              */
509  /*    FreeType error code.  0 means success.                             */
510  /*                                                                       */
511  FT_LOCAL_DEF( FT_Error )
512  tt_face_load_any( TT_Face    face,
513                    FT_ULong   tag,
514                    FT_Long    offset,
515                    FT_Byte*   buffer,
516                    FT_ULong*  length )
517  {
518    FT_Error   error;
519    FT_Stream  stream;
520    TT_Table   table;
521    FT_ULong   size;
522
523
524    if ( tag != 0 )
525    {
526      /* look for tag in font directory */
527      table = tt_face_lookup_table( face, tag );
528      if ( !table )
529      {
530        error = SFNT_Err_Table_Missing;
531        goto Exit;
532      }
533
534      offset += table->Offset;
535      size    = table->Length;
536    }
537    else
538      /* tag == 0 -- the user wants to access the font file directly */
539      size = face->root.stream->size;
540
541    if ( length && *length == 0 )
542    {
543      *length = size;
544
545      return SFNT_Err_Ok;
546    }
547
548    if ( length )
549      size = *length;
550
551    stream = face->root.stream;
552    /* the `if' is syntactic sugar for picky compilers */
553    if ( FT_STREAM_READ_AT( offset, buffer, size ) )
554      goto Exit;
555
556  Exit:
557    return error;
558  }
559
560
561  /*************************************************************************/
562  /*                                                                       */
563  /* <Function>                                                            */
564  /*    tt_face_load_generic_header                                        */
565  /*                                                                       */
566  /* <Description>                                                         */
567  /*    Loads the TrueType table `head' or `bhed'.                         */
568  /*                                                                       */
569  /* <Input>                                                               */
570  /*    face   :: A handle to the target face object.                      */
571  /*                                                                       */
572  /*    stream :: The input stream.                                        */
573  /*                                                                       */
574  /* <Return>                                                              */
575  /*    FreeType error code.  0 means success.                             */
576  /*                                                                       */
577  static FT_Error
578  tt_face_load_generic_header( TT_Face    face,
579                               FT_Stream  stream,
580                               FT_ULong   tag )
581  {
582    FT_Error    error;
583    TT_Header*  header;
584
585    static const FT_Frame_Field  header_fields[] =
586    {
587#undef  FT_STRUCTURE
588#define FT_STRUCTURE  TT_Header
589
590      FT_FRAME_START( 54 ),
591        FT_FRAME_ULONG ( Table_Version ),
592        FT_FRAME_ULONG ( Font_Revision ),
593        FT_FRAME_LONG  ( CheckSum_Adjust ),
594        FT_FRAME_LONG  ( Magic_Number ),
595        FT_FRAME_USHORT( Flags ),
596        FT_FRAME_USHORT( Units_Per_EM ),
597        FT_FRAME_LONG  ( Created[0] ),
598        FT_FRAME_LONG  ( Created[1] ),
599        FT_FRAME_LONG  ( Modified[0] ),
600        FT_FRAME_LONG  ( Modified[1] ),
601        FT_FRAME_SHORT ( xMin ),
602        FT_FRAME_SHORT ( yMin ),
603        FT_FRAME_SHORT ( xMax ),
604        FT_FRAME_SHORT ( yMax ),
605        FT_FRAME_USHORT( Mac_Style ),
606        FT_FRAME_USHORT( Lowest_Rec_PPEM ),
607        FT_FRAME_SHORT ( Font_Direction ),
608        FT_FRAME_SHORT ( Index_To_Loc_Format ),
609        FT_FRAME_SHORT ( Glyph_Data_Format ),
610      FT_FRAME_END
611    };
612
613
614    FT_TRACE2(( "tt_face_load_generic_header: "
615                "%08p, looking up font table `%c%c%c%c'.\n",
616                face,
617                (FT_Char)( tag >> 24 ),
618                (FT_Char)( tag >> 16 ),
619                (FT_Char)( tag >> 8  ),
620                (FT_Char)( tag       ) ));
621
622    error = face->goto_table( face, tag, stream, 0 );
623    if ( error )
624    {
625      FT_TRACE2(( "tt_face_load_generic_header: Font table is missing!\n" ));
626      goto Exit;
627    }
628
629    header = &face->header;
630
631    if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
632      goto Exit;
633
634    FT_TRACE2(( "    Units per EM: %8u\n", header->Units_Per_EM ));
635    FT_TRACE2(( "    IndexToLoc:   %8d\n", header->Index_To_Loc_Format ));
636    FT_TRACE2(( "tt_face_load_generic_header: Font table loaded.\n" ));
637
638  Exit:
639    return error;
640  }
641
642
643  FT_LOCAL_DEF( FT_Error )
644  tt_face_load_header( TT_Face    face,
645                       FT_Stream  stream )
646  {
647    return tt_face_load_generic_header( face, stream, TTAG_head );
648  }
649
650
651#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
652
653  FT_LOCAL_DEF( FT_Error )
654  tt_face_load_bitmap_header( TT_Face    face,
655                              FT_Stream  stream )
656  {
657    return tt_face_load_generic_header( face, stream, TTAG_bhed );
658  }
659
660#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
661
662
663  /*************************************************************************/
664  /*                                                                       */
665  /* <Function>                                                            */
666  /*    tt_face_load_max_profile                                           */
667  /*                                                                       */
668  /* <Description>                                                         */
669  /*    Loads the maximum profile into a face object.                      */
670  /*                                                                       */
671  /* <Input>                                                               */
672  /*    face   :: A handle to the target face object.                      */
673  /*                                                                       */
674  /*    stream :: The input stream.                                        */
675  /*                                                                       */
676  /* <Return>                                                              */
677  /*    FreeType error code.  0 means success.                             */
678  /*                                                                       */
679  FT_LOCAL_DEF( FT_Error )
680  tt_face_load_max_profile( TT_Face    face,
681                            FT_Stream  stream )
682  {
683    FT_Error        error;
684    TT_MaxProfile*  maxProfile = &face->max_profile;
685
686    const FT_Frame_Field  maxp_fields[] =
687    {
688#undef  FT_STRUCTURE
689#define FT_STRUCTURE  TT_MaxProfile
690
691      FT_FRAME_START( 6 ),
692        FT_FRAME_LONG  ( version ),
693        FT_FRAME_USHORT( numGlyphs ),
694      FT_FRAME_END
695    };
696
697    const FT_Frame_Field  maxp_fields_extra[] =
698    {
699      FT_FRAME_START( 26 ),
700        FT_FRAME_USHORT( maxPoints ),
701        FT_FRAME_USHORT( maxContours ),
702        FT_FRAME_USHORT( maxCompositePoints ),
703        FT_FRAME_USHORT( maxCompositeContours ),
704        FT_FRAME_USHORT( maxZones ),
705        FT_FRAME_USHORT( maxTwilightPoints ),
706        FT_FRAME_USHORT( maxStorage ),
707        FT_FRAME_USHORT( maxFunctionDefs ),
708        FT_FRAME_USHORT( maxInstructionDefs ),
709        FT_FRAME_USHORT( maxStackElements ),
710        FT_FRAME_USHORT( maxSizeOfInstructions ),
711        FT_FRAME_USHORT( maxComponentElements ),
712        FT_FRAME_USHORT( maxComponentDepth ),
713      FT_FRAME_END
714    };
715
716
717    FT_TRACE2(( "Load_TT_MaxProfile: %08p\n", face ));
718
719    error = face->goto_table( face, TTAG_maxp, stream, 0 );
720    if ( error )
721      goto Exit;
722
723    if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
724      goto Exit;
725
726    face->root.num_glyphs = maxProfile->numGlyphs;
727
728    maxProfile->maxPoints             = 0;
729    maxProfile->maxContours           = 0;
730    maxProfile->maxCompositePoints    = 0;
731    maxProfile->maxCompositeContours  = 0;
732    maxProfile->maxZones              = 0;
733    maxProfile->maxTwilightPoints     = 0;
734    maxProfile->maxStorage            = 0;
735    maxProfile->maxFunctionDefs       = 0;
736    maxProfile->maxInstructionDefs    = 0;
737    maxProfile->maxStackElements      = 0;
738    maxProfile->maxSizeOfInstructions = 0;
739    maxProfile->maxComponentElements  = 0;
740    maxProfile->maxComponentDepth     = 0;
741
742    if ( maxProfile->version >= 0x10000L )
743    {
744      if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
745        goto Exit;
746
747      /* XXX: an adjustment that is necessary to load certain */
748      /*      broken fonts like `Keystrokes MT' :-(           */
749      /*                                                      */
750      /*   We allocate 64 function entries by default when    */
751      /*   the maxFunctionDefs field is null.                 */
752
753      if ( maxProfile->maxFunctionDefs == 0 )
754        maxProfile->maxFunctionDefs = 64;
755
756      face->root.internal->max_points =
757        (FT_UShort)FT_MAX( maxProfile->maxCompositePoints,
758                           maxProfile->maxPoints );
759
760      face->root.internal->max_contours =
761        (FT_Short)FT_MAX( maxProfile->maxCompositeContours,
762                          maxProfile->maxContours );
763
764      face->max_components = (FT_ULong)maxProfile->maxComponentElements +
765                             maxProfile->maxComponentDepth;
766
767      /* XXX: some fonts have maxComponents set to 0; we will */
768      /*      then use 16 of them by default.                 */
769      if ( face->max_components == 0 )
770        face->max_components = 16;
771
772      /* We also increase maxPoints and maxContours in order to support */
773      /* some broken fonts.                                             */
774      face->root.internal->max_points   += (FT_UShort)8;
775      face->root.internal->max_contours += (FT_Short) 4;
776    }
777
778    FT_TRACE2(( "MAXP loaded.\n" ));
779
780  Exit:
781    return error;
782  }
783
784
785  /*************************************************************************/
786  /*                                                                       */
787  /* <Function>                                                            */
788  /*    tt_face_load_metrics                                               */
789  /*                                                                       */
790  /* <Description>                                                         */
791  /*    Loads the horizontal or vertical metrics table into a face object. */
792  /*                                                                       */
793  /* <Input>                                                               */
794  /*    face     :: A handle to the target face object.                    */
795  /*                                                                       */
796  /*    stream   :: The input stream.                                      */
797  /*                                                                       */
798  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
799  /*                                                                       */
800  /* <Return>                                                              */
801  /*    FreeType error code.  0 means success.                             */
802  /*                                                                       */
803#ifdef FT_OPTIMIZE_MEMORY
804
805  static FT_Error
806  tt_face_load_metrics( TT_Face    face,
807                        FT_Stream  stream,
808                        FT_Bool    vertical )
809  {
810    FT_Error   error;
811    FT_ULong   table_size;
812    FT_Byte**  ptable;
813    FT_ULong*  ptable_size;
814   
815   
816    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
817                                                       : "Horizontal",
818                                              face ));
819
820    if ( vertical )
821    {
822      ptable      = &face->vert_metrics;
823      ptable_size = &face->vert_metrics_size;
824     
825      /* The table is optional, quit silently if it wasn't found.      */
826      /*                                                               */
827      /* XXX: Some fonts have a valid vertical header with a non-null  */
828      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
829      /*      table to get the metrics from (e.g. mingliu).            */
830      /*                                                               */
831      /*      For safety, we set the field to 0!                       */
832      /*                                                               */
833      error = face->goto_table( face, TTAG_vmtx, stream, &table_size );
834      if ( error )
835      {
836        /* Set number_Of_VMetrics to 0! */
837        FT_TRACE2(( "  no vertical header in file.\n" ));
838        error = SFNT_Err_Ok;
839        goto Exit;
840      }
841    }
842    else
843    {
844      ptable      = &face->horz_metrics;
845      ptable_size = &face->horz_metrics_size;
846
847      error = face->goto_table( face, TTAG_hmtx, stream, &table_size );
848      if ( error )
849      {
850#ifdef FT_CONFIG_OPTION_INCREMENTAL
851        /* If this is an incrementally loaded font and there are */
852        /* overriding metrics, tolerate a missing `hmtx' table.  */
853        if ( face->root.internal->incremental_interface          &&
854             face->root.internal->incremental_interface->funcs->
855               get_glyph_metrics                                 )
856        {
857          face->horizontal.number_Of_HMetrics = 0;
858          error = SFNT_Err_Ok;
859          goto Exit;
860        }
861#endif
862
863        FT_ERROR(( " no horizontal metrics in file!\n" ));
864        error = SFNT_Err_Hmtx_Table_Missing;
865        goto Exit;
866      }
867    }
868   
869    if ( FT_FRAME_EXTRACT( table_size, *ptable ) )
870      goto Exit;
871     
872    *ptable_size = table_size;
873   
874  Exit:
875    return error;
876  }
877
878#else /* !OPTIMIZE_MEMORY */
879
880  static FT_Error
881  tt_face_load_metrics( TT_Face    face,
882                        FT_Stream  stream,
883                        FT_Bool    vertical )
884  {
885    FT_Error   error;
886    FT_Memory  memory = stream->memory;
887
888    FT_ULong   table_len;
889    FT_Long    num_shorts, num_longs, num_shorts_checked;
890
891    TT_LongMetrics *   longs;
892    TT_ShortMetrics**  shorts;
893
894
895    FT_TRACE2(( "TT_Load_%s_Metrics: %08p\n", vertical ? "Vertical"
896                                                       : "Horizontal",
897                                              face ));
898
899    if ( vertical )
900    {
901      /* The table is optional, quit silently if it wasn't found.      */
902      /*                                                               */
903      /* XXX: Some fonts have a valid vertical header with a non-null  */
904      /*      `number_of_VMetrics' fields, but no corresponding `vmtx' */
905      /*      table to get the metrics from (e.g. mingliu).            */
906      /*                                                               */
907      /*      For safety, we set the field to 0!                       */
908      /*                                                               */
909      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
910      if ( error )
911      {
912        /* Set number_Of_VMetrics to 0! */
913        FT_TRACE2(( "  no vertical header in file.\n" ));
914        face->vertical.number_Of_VMetrics = 0;
915        error = SFNT_Err_Ok;
916        goto Exit;
917      }
918
919      num_longs = face->vertical.number_Of_VMetrics;
920      longs     = (TT_LongMetrics *)&face->vertical.long_metrics;
921      shorts    = (TT_ShortMetrics**)&face->vertical.short_metrics;
922    }
923    else
924    {
925      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
926      if ( error )
927      {
928
929#ifdef FT_CONFIG_OPTION_INCREMENTAL
930        /* If this is an incrementally loaded font and there are */
931        /* overriding metrics, tolerate a missing `hmtx' table.  */
932        if ( face->root.internal->incremental_interface          &&
933             face->root.internal->incremental_interface->funcs->
934               get_glyph_metrics                                 )
935        {
936          face->horizontal.number_Of_HMetrics = 0;
937          error = SFNT_Err_Ok;
938          goto Exit;
939        }
940#endif
941
942        FT_ERROR(( " no horizontal metrics in file!\n" ));
943        error = SFNT_Err_Hmtx_Table_Missing;
944        goto Exit;
945      }
946
947      num_longs = face->horizontal.number_Of_HMetrics;
948      longs     = (TT_LongMetrics *)&face->horizontal.long_metrics;
949      shorts    = (TT_ShortMetrics**)&face->horizontal.short_metrics;
950    }
951
952    /* never trust derived values */
953
954    num_shorts         = face->max_profile.numGlyphs - num_longs;
955    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
956
957    if ( num_shorts < 0 )
958    {
959      FT_ERROR(( "TT_Load_%s_Metrics: more metrics than glyphs!\n",
960                 vertical ? "Vertical"
961                          : "Horizontal" ));
962
963      error = vertical ? SFNT_Err_Invalid_Vert_Metrics
964                       : SFNT_Err_Invalid_Horiz_Metrics;
965      goto Exit;
966    }
967
968    if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
969         FT_QNEW_ARRAY( *shorts, num_shorts ) )
970      goto Exit;
971
972    if ( FT_FRAME_ENTER( table_len ) )
973      goto Exit;
974
975    {
976      TT_LongMetrics  cur   = *longs;
977      TT_LongMetrics  limit = cur + num_longs;
978
979
980      for ( ; cur < limit; cur++ )
981      {
982        cur->advance = FT_GET_USHORT();
983        cur->bearing = FT_GET_SHORT();
984      }
985    }
986
987    /* do we have an inconsistent number of metric values? */
988    {
989      TT_ShortMetrics*  cur   = *shorts;
990      TT_ShortMetrics*  limit = cur +
991                                FT_MIN( num_shorts, num_shorts_checked );
992
993
994      for ( ; cur < limit; cur++ )
995        *cur = FT_GET_SHORT();
996
997      /* We fill up the missing left side bearings with the     */
998      /* last valid value.  Since this will occur for buggy CJK */
999      /* fonts usually only, nothing serious will happen.       */
1000      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
1001      {
1002        FT_Short  val = (*shorts)[num_shorts_checked - 1];
1003
1004
1005        limit = *shorts + num_shorts;
1006        for ( ; cur < limit; cur++ )
1007          *cur = val;
1008      }
1009    }
1010
1011    FT_FRAME_EXIT();
1012
1013    FT_TRACE2(( "loaded\n" ));
1014
1015  Exit:
1016    return error;
1017  }
1018
1019#endif /* !FT_OPTIMIZE_METRICS */
1020
1021
1022  /*************************************************************************/
1023  /*                                                                       */
1024  /* <Function>                                                            */
1025  /*    tt_face_load_metrics_header                                        */
1026  /*                                                                       */
1027  /* <Description>                                                         */
1028  /*    Loads the horizontal or vertical header in a face object.          */
1029  /*                                                                       */
1030  /* <Input>                                                               */
1031  /*    face     :: A handle to the target face object.                    */
1032  /*                                                                       */
1033  /*    stream   :: The input stream.                                      */
1034  /*                                                                       */
1035  /*    vertical :: A boolean flag.  If set, load vertical metrics.        */
1036  /*                                                                       */
1037  /* <Return>                                                              */
1038  /*    FreeType error code.  0 means success.                             */
1039  /*                                                                       */
1040  FT_LOCAL_DEF( FT_Error )
1041  tt_face_load_metrics_header( TT_Face    face,
1042                               FT_Stream  stream,
1043                               FT_Bool    vertical )
1044  {
1045    FT_Error        error;
1046    TT_HoriHeader*  header;
1047
1048    const FT_Frame_Field  metrics_header_fields[] =
1049    {
1050#undef  FT_STRUCTURE
1051#define FT_STRUCTURE  TT_HoriHeader
1052
1053      FT_FRAME_START( 36 ),
1054        FT_FRAME_ULONG ( Version ),
1055        FT_FRAME_SHORT ( Ascender ),
1056        FT_FRAME_SHORT ( Descender ),
1057        FT_FRAME_SHORT ( Line_Gap ),
1058        FT_FRAME_USHORT( advance_Width_Max ),
1059        FT_FRAME_SHORT ( min_Left_Side_Bearing ),
1060        FT_FRAME_SHORT ( min_Right_Side_Bearing ),
1061        FT_FRAME_SHORT ( xMax_Extent ),
1062        FT_FRAME_SHORT ( caret_Slope_Rise ),
1063        FT_FRAME_SHORT ( caret_Slope_Run ),
1064        FT_FRAME_SHORT ( caret_Offset ),
1065        FT_FRAME_SHORT ( Reserved[0] ),
1066        FT_FRAME_SHORT ( Reserved[1] ),
1067        FT_FRAME_SHORT ( Reserved[2] ),
1068        FT_FRAME_SHORT ( Reserved[3] ),
1069        FT_FRAME_SHORT ( metric_Data_Format ),
1070        FT_FRAME_USHORT( number_Of_HMetrics ),
1071      FT_FRAME_END
1072    };
1073
1074
1075    FT_TRACE2(( vertical ? "Vertical header " : "Horizontal header " ));
1076
1077    if ( vertical )
1078    {
1079      face->vertical_info = 0;
1080
1081      /* The vertical header table is optional, so return quietly if */
1082      /* we don't find it.                                           */
1083      error = face->goto_table( face, TTAG_vhea, stream, 0 );
1084      if ( error )
1085      {
1086        error = SFNT_Err_Ok;
1087        goto Exit;
1088      }
1089
1090      face->vertical_info = 1;
1091      header = (TT_HoriHeader*)&face->vertical;
1092    }
1093    else
1094    {
1095      /* The horizontal header is mandatory; return an error if we */
1096      /* don't find it.                                            */
1097      error = face->goto_table( face, TTAG_hhea, stream, 0 );
1098      if ( error )
1099      {
1100        error = SFNT_Err_Horiz_Header_Missing;
1101        goto Exit;
1102      }
1103
1104      header = &face->horizontal;
1105    }
1106
1107    if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
1108      goto Exit;
1109
1110    header->long_metrics  = NULL;
1111    header->short_metrics = NULL;
1112
1113    FT_TRACE2(( "loaded\n" ));
1114
1115    /* Now try to load the corresponding metrics */
1116
1117    error = tt_face_load_metrics( face, stream, vertical );
1118
1119  Exit:
1120    return error;
1121  }
1122
1123
1124  /*************************************************************************/
1125  /*                                                                       */
1126  /* <Function>                                                            */
1127  /*    tt_face_load_names                                                 */
1128  /*                                                                       */
1129  /* <Description>                                                         */
1130  /*    Loads the name records.                                            */
1131  /*                                                                       */
1132  /* <Input>                                                               */
1133  /*    face   :: A handle to the target face object.                      */
1134  /*                                                                       */
1135  /*    stream :: The input stream.                                        */
1136  /*                                                                       */
1137  /* <Return>                                                              */
1138  /*    FreeType error code.  0 means success.                             */
1139  /*                                                                       */
1140  FT_LOCAL_DEF( FT_Error )
1141  tt_face_load_names( TT_Face    face,
1142                      FT_Stream  stream )
1143  {
1144    FT_Error      error;
1145    FT_Memory     memory = stream->memory;
1146    FT_ULong      table_pos, table_len;
1147    FT_ULong      storage_start, storage_limit;
1148    FT_UInt       count;
1149    TT_NameTable  table;
1150
1151    static const FT_Frame_Field  name_table_fields[] =
1152    {
1153#undef  FT_STRUCTURE
1154#define FT_STRUCTURE  TT_NameTableRec
1155
1156      FT_FRAME_START( 6 ),
1157        FT_FRAME_USHORT( format ),
1158        FT_FRAME_USHORT( numNameRecords ),
1159        FT_FRAME_USHORT( storageOffset ),
1160      FT_FRAME_END
1161    };
1162
1163    static const FT_Frame_Field  name_record_fields[] =
1164    {
1165#undef  FT_STRUCTURE
1166#define FT_STRUCTURE  TT_NameEntryRec
1167
1168      /* no FT_FRAME_START */
1169        FT_FRAME_USHORT( platformID ),
1170        FT_FRAME_USHORT( encodingID ),
1171        FT_FRAME_USHORT( languageID ),
1172        FT_FRAME_USHORT( nameID ),
1173        FT_FRAME_USHORT( stringLength ),
1174        FT_FRAME_USHORT( stringOffset ),
1175      FT_FRAME_END
1176    };
1177
1178
1179    table         = &face->name_table;
1180    table->stream = stream;
1181
1182    FT_TRACE2(( "Names " ));
1183
1184    error = face->goto_table( face, TTAG_name, stream, &table_len );
1185    if ( error )
1186    {
1187      /* The name table is required so indicate failure. */
1188      FT_TRACE2(( "is missing!\n" ));
1189      error = SFNT_Err_Name_Table_Missing;
1190      goto Exit;
1191    }
1192
1193    table_pos = FT_STREAM_POS();
1194
1195
1196    if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
1197      goto Exit;
1198
1199    /* Some popular Asian fonts have an invalid `storageOffset' value   */
1200    /* (it should be at least "6 + 12*num_names").  However, the string */
1201    /* offsets, computed as "storageOffset + entry->stringOffset", are  */
1202    /* valid pointers within the name table...                          */
1203    /*                                                                  */
1204    /* We thus can't check `storageOffset' right now.                   */
1205    /*                                                                  */
1206    storage_start = table_pos + 6 + 12*table->numNameRecords;
1207    storage_limit = table_pos + table_len;
1208
1209    if ( storage_start > storage_limit )
1210    {
1211      FT_ERROR(( "tt_face_load_names: invalid `name' table\n" ));
1212      error = SFNT_Err_Name_Table_Missing;
1213      goto Exit;
1214    }
1215
1216    /* Allocate the array of name records. */
1217    count                 = table->numNameRecords;
1218    table->numNameRecords = 0;
1219
1220    if ( FT_NEW_ARRAY( table->names, count ) ||
1221         FT_FRAME_ENTER( count * 12 )        )
1222      goto Exit;
1223
1224    /* Load the name records and determine how much storage is needed */
1225    /* to hold the strings themselves.                                */
1226    {
1227      TT_NameEntryRec*  entry = table->names;
1228
1229
1230      for ( ; count > 0; count-- )
1231      {
1232        if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
1233          continue;
1234
1235        /* check that the name is not empty */
1236        if ( entry->stringLength == 0 )
1237          continue;
1238
1239        /* check that the name string is within the table */
1240        entry->stringOffset += table_pos + table->storageOffset;
1241        if ( entry->stringOffset                       < storage_start ||
1242             entry->stringOffset + entry->stringLength > storage_limit )
1243        {
1244          /* invalid entry - ignore it */
1245          entry->stringOffset = 0;
1246          entry->stringLength = 0;
1247          continue;
1248        }
1249
1250        entry++;
1251      }
1252
1253      table->numNameRecords = (FT_UInt)( entry - table->names );
1254    }
1255
1256    FT_FRAME_EXIT();
1257
1258    FT_TRACE2(( "loaded\n" ));
1259
1260    /* everything went well, update face->num_names */
1261    face->num_names = (FT_UShort) table->numNameRecords;
1262
1263  Exit:
1264    return error;
1265  }
1266
1267
1268  /*************************************************************************/
1269  /*                                                                       */
1270  /* <Function>                                                            */
1271  /*    tt_face_free_names                                                 */
1272  /*                                                                       */
1273  /* <Description>                                                         */
1274  /*    Frees the name records.                                            */
1275  /*                                                                       */
1276  /* <Input>                                                               */
1277  /*    face :: A handle to the target face object.                        */
1278  /*                                                                       */
1279  FT_LOCAL_DEF( void )
1280  tt_face_free_names( TT_Face  face )
1281  {
1282    FT_Memory     memory = face->root.driver->root.memory;
1283    TT_NameTable  table  = &face->name_table;
1284    TT_NameEntry  entry  = table->names;
1285    FT_UInt       count  = table->numNameRecords;
1286
1287
1288    if ( table->names )
1289    {
1290      for ( ; count > 0; count--, entry++ )
1291      {
1292        FT_FREE( entry->string );
1293        entry->stringLength = 0;
1294      }
1295
1296      /* free strings table */
1297      FT_FREE( table->names );
1298    }
1299
1300    table->numNameRecords = 0;
1301    table->format         = 0;
1302    table->storageOffset  = 0;
1303  }
1304
1305
1306  /*************************************************************************/
1307  /*                                                                       */
1308  /* <Function>                                                            */
1309  /*    tt_face_load_cmap                                                  */
1310  /*                                                                       */
1311  /* <Description>                                                         */
1312  /*    Loads the cmap directory in a face object.  The cmaps itselves are */
1313  /*    loaded on demand in the `ttcmap.c' module.                         */
1314  /*                                                                       */
1315  /* <Input>                                                               */
1316  /*    face   :: A handle to the target face object.                      */
1317  /*                                                                       */
1318  /*    stream :: A handle to the input stream.                            */
1319  /*                                                                       */
1320  /* <Return>                                                              */
1321  /*    FreeType error code.  0 means success.                             */
1322  /*                                                                       */
1323
1324  FT_LOCAL_DEF( FT_Error )
1325  tt_face_load_cmap( TT_Face    face,
1326                     FT_Stream  stream )
1327  {
1328    FT_Error  error;
1329
1330
1331    error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
1332    if ( error )
1333    {
1334      FT_TRACE2(( "No `cmap' table in font !\n" ));
1335      error = SFNT_Err_CMap_Table_Missing;
1336      goto Exit;
1337    }
1338
1339    if ( !FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
1340      FT_TRACE2(( "`cmap' table loaded\n" ));
1341    else
1342    {
1343      FT_ERROR(( "`cmap' table is too short!\n" ));
1344      face->cmap_size = 0;
1345    }
1346
1347  Exit:
1348    return error;
1349  }
1350
1351
1352
1353  /*************************************************************************/
1354  /*                                                                       */
1355  /* <Function>                                                            */
1356  /*    tt_face_load_os2                                                   */
1357  /*                                                                       */
1358  /* <Description>                                                         */
1359  /*    Loads the OS2 table.                                               */
1360  /*                                                                       */
1361  /* <Input>                                                               */
1362  /*    face   :: A handle to the target face object.                      */
1363  /*                                                                       */
1364  /*    stream :: A handle to the input stream.                            */
1365  /*                                                                       */
1366  /* <Return>                                                              */
1367  /*    FreeType error code.  0 means success.                             */
1368  /*                                                                       */
1369  FT_LOCAL_DEF( FT_Error )
1370  tt_face_load_os2( TT_Face    face,
1371                    FT_Stream  stream )
1372  {
1373    FT_Error  error;
1374    TT_OS2*   os2;
1375
1376    const FT_Frame_Field  os2_fields[] =
1377    {
1378#undef  FT_STRUCTURE
1379#define FT_STRUCTURE  TT_OS2
1380
1381      FT_FRAME_START( 78 ),
1382        FT_FRAME_USHORT( version ),
1383        FT_FRAME_SHORT ( xAvgCharWidth ),
1384        FT_FRAME_USHORT( usWeightClass ),
1385        FT_FRAME_USHORT( usWidthClass ),
1386        FT_FRAME_SHORT ( fsType ),
1387        FT_FRAME_SHORT ( ySubscriptXSize ),
1388        FT_FRAME_SHORT ( ySubscriptYSize ),
1389        FT_FRAME_SHORT ( ySubscriptXOffset ),
1390        FT_FRAME_SHORT ( ySubscriptYOffset ),
1391        FT_FRAME_SHORT ( ySuperscriptXSize ),
1392        FT_FRAME_SHORT ( ySuperscriptYSize ),
1393        FT_FRAME_SHORT ( ySuperscriptXOffset ),
1394        FT_FRAME_SHORT ( ySuperscriptYOffset ),
1395        FT_FRAME_SHORT ( yStrikeoutSize ),
1396        FT_FRAME_SHORT ( yStrikeoutPosition ),
1397        FT_FRAME_SHORT ( sFamilyClass ),
1398        FT_FRAME_BYTE  ( panose[0] ),
1399        FT_FRAME_BYTE  ( panose[1] ),
1400        FT_FRAME_BYTE  ( panose[2] ),
1401        FT_FRAME_BYTE  ( panose[3] ),
1402        FT_FRAME_BYTE  ( panose[4] ),
1403        FT_FRAME_BYTE  ( panose[5] ),
1404        FT_FRAME_BYTE  ( panose[6] ),
1405        FT_FRAME_BYTE  ( panose[7] ),
1406        FT_FRAME_BYTE  ( panose[8] ),
1407        FT_FRAME_BYTE  ( panose[9] ),
1408        FT_FRAME_ULONG ( ulUnicodeRange1 ),
1409        FT_FRAME_ULONG ( ulUnicodeRange2 ),
1410        FT_FRAME_ULONG ( ulUnicodeRange3 ),
1411        FT_FRAME_ULONG ( ulUnicodeRange4 ),
1412        FT_FRAME_BYTE  ( achVendID[0] ),
1413        FT_FRAME_BYTE  ( achVendID[1] ),
1414        FT_FRAME_BYTE  ( achVendID[2] ),
1415        FT_FRAME_BYTE  ( achVendID[3] ),
1416
1417        FT_FRAME_USHORT( fsSelection ),
1418        FT_FRAME_USHORT( usFirstCharIndex ),
1419        FT_FRAME_USHORT( usLastCharIndex ),
1420        FT_FRAME_SHORT ( sTypoAscender ),
1421        FT_FRAME_SHORT ( sTypoDescender ),
1422        FT_FRAME_SHORT ( sTypoLineGap ),
1423        FT_FRAME_USHORT( usWinAscent ),
1424        FT_FRAME_USHORT( usWinDescent ),
1425      FT_FRAME_END
1426    };
1427
1428    const FT_Frame_Field  os2_fields_extra[] =
1429    {
1430      FT_FRAME_START( 8 ),
1431        FT_FRAME_ULONG( ulCodePageRange1 ),
1432        FT_FRAME_ULONG( ulCodePageRange2 ),
1433      FT_FRAME_END
1434    };
1435
1436    const FT_Frame_Field  os2_fields_extra2[] =
1437    {
1438      FT_FRAME_START( 10 ),
1439        FT_FRAME_SHORT ( sxHeight ),
1440        FT_FRAME_SHORT ( sCapHeight ),
1441        FT_FRAME_USHORT( usDefaultChar ),
1442        FT_FRAME_USHORT( usBreakChar ),
1443        FT_FRAME_USHORT( usMaxContext ),
1444      FT_FRAME_END
1445    };
1446
1447
1448    FT_TRACE2(( "OS/2 Table " ));
1449
1450    /* We now support old Mac fonts where the OS/2 table doesn't  */
1451    /* exist.  Simply put, we set the `version' field to 0xFFFF   */
1452    /* and test this value each time we need to access the table. */
1453    error = face->goto_table( face, TTAG_OS2, stream, 0 );
1454    if ( error )
1455    {
1456      FT_TRACE2(( "is missing!\n" ));
1457      face->os2.version = 0xFFFFU;
1458      error = SFNT_Err_Ok;
1459      goto Exit;
1460    }
1461
1462    os2 = &face->os2;
1463
1464    if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
1465      goto Exit;
1466
1467    os2->ulCodePageRange1 = 0;
1468    os2->ulCodePageRange2 = 0;
1469    os2->sxHeight         = 0;
1470    os2->sCapHeight       = 0;
1471    os2->usDefaultChar    = 0;
1472    os2->usBreakChar      = 0;
1473    os2->usMaxContext     = 0;
1474
1475    if ( os2->version >= 0x0001 )
1476    {
1477      /* only version 1 tables */
1478      if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
1479        goto Exit;
1480
1481      if ( os2->version >= 0x0002 )
1482      {
1483        /* only version 2 tables */
1484        if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
1485          goto Exit;
1486      }
1487    }
1488
1489    FT_TRACE2(( "loaded\n" ));
1490
1491  Exit:
1492    return error;
1493  }
1494
1495
1496  /*************************************************************************/
1497  /*                                                                       */
1498  /* <Function>                                                            */
1499  /*    tt_face_load_postscript                                            */
1500  /*                                                                       */
1501  /* <Description>                                                         */
1502  /*    Loads the Postscript table.                                        */
1503  /*                                                                       */
1504  /* <Input>                                                               */
1505  /*    face   :: A handle to the target face object.                      */
1506  /*                                                                       */
1507  /*    stream :: A handle to the input stream.                            */
1508  /*                                                                       */
1509  /* <Return>                                                              */
1510  /*    FreeType error code.  0 means success.                             */
1511  /*                                                                       */
1512  FT_LOCAL_DEF( FT_Error )
1513  tt_face_load_postscript( TT_Face    face,
1514                           FT_Stream  stream )
1515  {
1516    FT_Error        error;
1517    TT_Postscript*  post = &face->postscript;
1518
1519    static const FT_Frame_Field  post_fields[] =
1520    {
1521#undef  FT_STRUCTURE
1522#define FT_STRUCTURE  TT_Postscript
1523
1524      FT_FRAME_START( 32 ),
1525        FT_FRAME_ULONG( FormatType ),
1526        FT_FRAME_ULONG( italicAngle ),
1527        FT_FRAME_SHORT( underlinePosition ),
1528        FT_FRAME_SHORT( underlineThickness ),
1529        FT_FRAME_ULONG( isFixedPitch ),
1530        FT_FRAME_ULONG( minMemType42 ),
1531        FT_FRAME_ULONG( maxMemType42 ),
1532        FT_FRAME_ULONG( minMemType1 ),
1533        FT_FRAME_ULONG( maxMemType1 ),
1534      FT_FRAME_END
1535    };
1536
1537
1538    FT_TRACE2(( "PostScript " ));
1539
1540    error = face->goto_table( face, TTAG_post, stream, 0 );
1541    if ( error )
1542      return SFNT_Err_Post_Table_Missing;
1543
1544    if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
1545      return error;
1546
1547    /* we don't load the glyph names, we do that in another */
1548    /* module (ttpost).                                     */
1549    FT_TRACE2(( "loaded\n" ));
1550
1551    return SFNT_Err_Ok;
1552  }
1553
1554
1555  /*************************************************************************/
1556  /*                                                                       */
1557  /* <Function>                                                            */
1558  /*    tt_face_load_pclt                                                  */
1559  /*                                                                       */
1560  /* <Description>                                                         */
1561  /*    Loads the PCL 5 Table.                                             */
1562  /*                                                                       */
1563  /* <Input>                                                               */
1564  /*    face   :: A handle to the target face object.                      */
1565  /*                                                                       */
1566  /*    stream :: A handle to the input stream.                            */
1567  /*                                                                       */
1568  /* <Return>                                                              */
1569  /*    FreeType error code.  0 means success.                             */
1570  /*                                                                       */
1571  FT_LOCAL_DEF( FT_Error )
1572  tt_face_load_pclt( TT_Face    face,
1573                     FT_Stream  stream )
1574  {
1575    static const FT_Frame_Field  pclt_fields[] =
1576    {
1577#undef  FT_STRUCTURE
1578#define FT_STRUCTURE  TT_PCLT
1579
1580      FT_FRAME_START( 54 ),
1581        FT_FRAME_ULONG ( Version ),
1582        FT_FRAME_ULONG ( FontNumber ),
1583        FT_FRAME_USHORT( Pitch ),
1584        FT_FRAME_USHORT( xHeight ),
1585        FT_FRAME_USHORT( Style ),
1586        FT_FRAME_USHORT( TypeFamily ),
1587        FT_FRAME_USHORT( CapHeight ),
1588        FT_FRAME_BYTES ( TypeFace, 16 ),
1589        FT_FRAME_BYTES ( CharacterComplement, 8 ),
1590        FT_FRAME_BYTES ( FileName, 6 ),
1591        FT_FRAME_CHAR  ( StrokeWeight ),
1592        FT_FRAME_CHAR  ( WidthType ),
1593        FT_FRAME_BYTE  ( SerifStyle ),
1594        FT_FRAME_BYTE  ( Reserved ),
1595      FT_FRAME_END
1596    };
1597
1598    FT_Error  error;
1599    TT_PCLT*  pclt = &face->pclt;
1600
1601
1602    FT_TRACE2(( "PCLT " ));
1603
1604    /* optional table */
1605    error = face->goto_table( face, TTAG_PCLT, stream, 0 );
1606    if ( error )
1607    {
1608      FT_TRACE2(( "missing (optional)\n" ));
1609      pclt->Version = 0;
1610      return SFNT_Err_Ok;
1611    }
1612
1613    if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
1614      goto Exit;
1615
1616    FT_TRACE2(( "loaded\n" ));
1617
1618  Exit:
1619    return error;
1620  }
1621
1622
1623  /*************************************************************************/
1624  /*                                                                       */
1625  /* <Function>                                                            */
1626  /*    tt_face_load_gasp                                                  */
1627  /*                                                                       */
1628  /* <Description>                                                         */
1629  /*    Loads the `gasp' table into a face object.                         */
1630  /*                                                                       */
1631  /* <Input>                                                               */
1632  /*    face   :: A handle to the target face object.                      */
1633  /*                                                                       */
1634  /*    stream :: The input stream.                                        */
1635  /*                                                                       */
1636  /* <Return>                                                              */
1637  /*    FreeType error code.  0 means success.                             */
1638  /*                                                                       */
1639  FT_LOCAL_DEF( FT_Error )
1640  tt_face_load_gasp( TT_Face    face,
1641                     FT_Stream  stream )
1642  {
1643    FT_Error   error;
1644    FT_Memory  memory = stream->memory;
1645
1646    FT_UInt        j,num_ranges;
1647    TT_GaspRange   gaspranges;
1648
1649
1650    FT_TRACE2(( "tt_face_load_gasp: %08p\n", face ));
1651
1652    /* the gasp table is optional */
1653    error = face->goto_table( face, TTAG_gasp, stream, 0 );
1654    if ( error )
1655      return SFNT_Err_Ok;
1656
1657    if ( FT_FRAME_ENTER( 4L ) )
1658      goto Exit;
1659
1660    face->gasp.version   = FT_GET_USHORT();
1661    face->gasp.numRanges = FT_GET_USHORT();
1662
1663    FT_FRAME_EXIT();
1664
1665    num_ranges = face->gasp.numRanges;
1666    FT_TRACE3(( "number of ranges = %d\n", num_ranges ));
1667
1668    if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
1669         FT_FRAME_ENTER( num_ranges * 4L )      )
1670      goto Exit;
1671
1672    face->gasp.gaspRanges = gaspranges;
1673
1674    for ( j = 0; j < num_ranges; j++ )
1675    {
1676      gaspranges[j].maxPPEM  = FT_GET_USHORT();
1677      gaspranges[j].gaspFlag = FT_GET_USHORT();
1678
1679      FT_TRACE3(( " [max:%d flag:%d]",
1680                    gaspranges[j].maxPPEM,
1681                    gaspranges[j].gaspFlag ));
1682    }
1683    FT_TRACE3(( "\n" ));
1684
1685    FT_FRAME_EXIT();
1686    FT_TRACE2(( "GASP loaded\n" ));
1687
1688  Exit:
1689    return error;
1690  }
1691
1692
1693  /*************************************************************************/
1694  /*                                                                       */
1695  /* <Function>                                                            */
1696  /*    tt_face_load_hdmx                                                  */
1697  /*                                                                       */
1698  /* <Description>                                                         */
1699  /*    Loads the horizontal device metrics table.                         */
1700  /*                                                                       */
1701  /* <Input>                                                               */
1702  /*    face   :: A handle to the target face object.                      */
1703  /*                                                                       */
1704  /*    stream :: A handle to the input stream.                            */
1705  /*                                                                       */
1706  /* <Return>                                                              */
1707  /*    FreeType error code.  0 means success.                             */
1708  /*                                                                       */
1709#ifdef FT_OPTIMIZE_MEMORY
1710
1711  FT_LOCAL_DEF( FT_Error )
1712  tt_face_load_hdmx( TT_Face    face,
1713                     FT_Stream  stream )
1714  {
1715    FT_Error   error;
1716    FT_Memory  memory = stream->memory;
1717    FT_UInt    version, nn, num_records;
1718    FT_ULong   table_size, record_size;
1719    FT_Byte*   p;
1720    FT_Byte*   limit;
1721
1722
1723    /* this table is optional */
1724    error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
1725    if ( error || table_size < 8 )
1726      return SFNT_Err_Ok;
1727
1728    if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
1729      goto Exit;
1730
1731    p     = face->hdmx_table;
1732    limit = p + table_size;
1733
1734    version     = FT_NEXT_USHORT( p );
1735    num_records = FT_NEXT_USHORT( p );
1736    record_size = FT_NEXT_ULONG( p );
1737
1738    if ( version != 0 || num_records > 255 || record_size > 0x40000 )
1739    {
1740      error = SFNT_Err_Invalid_File_Format;
1741      goto Fail;
1742    }
1743
1744    if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
1745      goto Fail;
1746
1747    for ( nn = 0; nn < num_records; nn++ )
1748    {
1749      if ( p + record_size > limit )
1750        break;
1751       
1752      face->hdmx_record_sizes[nn] = p[0];
1753      p                          += record_size;
1754    }
1755   
1756    face->hdmx_record_count = nn;
1757    face->hdmx_table_size   = table_size;
1758
1759  Exit:
1760    return error;
1761   
1762  Fail:
1763    FT_FRAME_RELEASE( face->hdmx_table );
1764    face->hdmx_table_size = 0;
1765    goto Exit;
1766  }
1767
1768
1769  FT_LOCAL_DEF( void )
1770  tt_face_free_hdmx( TT_Face  face )
1771  {
1772    FT_Stream  stream = face->root.stream;
1773    FT_Memory  memory = stream->memory;
1774   
1775
1776    FT_FREE( face->hdmx_record_sizes );
1777    FT_FRAME_RELEASE( face->hdmx_table );
1778  }
1779
1780#else /* !FT_OPTIMIZE_MEMORY */
1781
1782  FT_LOCAL_DEF( FT_Error )
1783  tt_face_load_hdmx( TT_Face    face,
1784                     FT_Stream  stream )
1785  {
1786    FT_Error   error;
1787    FT_Memory  memory = stream->memory;
1788
1789    TT_Hdmx    hdmx = &face->hdmx;
1790    FT_Short   num_records;
1791    FT_Long    num_glyphs;
1792    FT_Long    record_size;
1793
1794
1795    hdmx->version     = 0;
1796    hdmx->num_records = 0;
1797    hdmx->records     = 0;
1798
1799    /* this table is optional */
1800    error = face->goto_table( face, TTAG_hdmx, stream, 0 );
1801    if ( error )
1802      return SFNT_Err_Ok;
1803
1804    if ( FT_FRAME_ENTER( 8L ) )
1805      goto Exit;
1806
1807    hdmx->version = FT_GET_USHORT();
1808    num_records   = FT_GET_SHORT();
1809    record_size   = FT_GET_LONG();
1810
1811    FT_FRAME_EXIT();
1812
1813    if ( record_size < 0 || num_records < 0 )
1814      return SFNT_Err_Invalid_File_Format;
1815
1816    /* Only recognize format 0 */
1817    if ( hdmx->version != 0 )
1818      goto Exit;
1819
1820    /* we can't use FT_QNEW_ARRAY here; otherwise tt_face_free_hdmx */
1821    /* could fail during deallocation                               */
1822    if ( FT_NEW_ARRAY( hdmx->records, num_records ) )
1823      goto Exit;
1824
1825    hdmx->num_records = num_records;
1826    num_glyphs        = face->root.num_glyphs;
1827    record_size      -= num_glyphs + 2;
1828
1829    {
1830      TT_HdmxEntry  cur   = hdmx->records;
1831      TT_HdmxEntry  limit = cur + hdmx->num_records;
1832
1833
1834      for ( ; cur < limit; cur++ )
1835      {
1836        /* read record */
1837        if ( FT_READ_BYTE( cur->ppem      ) ||
1838             FT_READ_BYTE( cur->max_width ) )
1839          goto Exit;
1840
1841        if ( FT_QALLOC( cur->widths, num_glyphs )      ||
1842             FT_STREAM_READ( cur->widths, num_glyphs ) )
1843          goto Exit;
1844
1845        /* skip padding bytes */
1846        if ( record_size > 0 && FT_STREAM_SKIP( record_size ) )
1847          goto Exit;
1848      }
1849    }
1850
1851  Exit:
1852    return error;
1853  }
1854
1855
1856  FT_LOCAL_DEF( void )
1857  tt_face_free_hdmx( TT_Face  face )
1858  {
1859    if ( face )
1860    {
1861      FT_Int     n;
1862      FT_Memory  memory = face->root.driver->root.memory;
1863
1864
1865      for ( n = 0; n < face->hdmx.num_records; n++ )
1866        FT_FREE( face->hdmx.records[n].widths );
1867
1868      FT_FREE( face->hdmx.records );
1869      face->hdmx.num_records = 0;
1870    }
1871  }
1872
1873#endif /* !OPTIMIZE_MEMORY */
1874
1875
1876/* END */
Note: See TracBrowser for help on using the repository browser.