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