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