xref: /inferno-os/libfreetype/sfobjs.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  sfobjs.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    SFNT object management (base).                                       */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include "sfobjs.h"
21*37da2899SCharles.Forsyth #include "ttload.h"
22*37da2899SCharles.Forsyth #include "ttcmap0.h"
23*37da2899SCharles.Forsyth #include FT_INTERNAL_SFNT_H
24*37da2899SCharles.Forsyth #include FT_INTERNAL_POSTSCRIPT_NAMES_H
25*37da2899SCharles.Forsyth #include FT_TRUETYPE_IDS_H
26*37da2899SCharles.Forsyth #include FT_TRUETYPE_TAGS_H
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth #include "sferrors.h"
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth   /*************************************************************************/
32*37da2899SCharles.Forsyth   /*                                                                       */
33*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
34*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
35*37da2899SCharles.Forsyth   /* messages during execution.                                            */
36*37da2899SCharles.Forsyth   /*                                                                       */
37*37da2899SCharles.Forsyth #undef  FT_COMPONENT
38*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_sfobjs
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth 
42*37da2899SCharles.Forsyth   /* convert a UTF-16 name entry to ASCII */
43*37da2899SCharles.Forsyth   static FT_String*
tt_name_entry_ascii_from_utf16(TT_NameEntry entry,FT_Memory memory)44*37da2899SCharles.Forsyth   tt_name_entry_ascii_from_utf16( TT_NameEntry  entry,
45*37da2899SCharles.Forsyth                                   FT_Memory     memory )
46*37da2899SCharles.Forsyth   {
47*37da2899SCharles.Forsyth     FT_String*  string;
48*37da2899SCharles.Forsyth     FT_UInt     len, code, n;
49*37da2899SCharles.Forsyth     FT_Byte*    read = (FT_Byte*)entry->string;
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth     len = (FT_UInt)entry->stringLength / 2;
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth     if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
55*37da2899SCharles.Forsyth       return NULL;
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth     for ( n = 0; n < len; n++ )
58*37da2899SCharles.Forsyth     {
59*37da2899SCharles.Forsyth       code = FT_NEXT_USHORT( read );
60*37da2899SCharles.Forsyth       if ( code < 32 || code > 127 )
61*37da2899SCharles.Forsyth         code = '?';
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth       string[n] = (char)code;
64*37da2899SCharles.Forsyth     }
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth     string[len] = 0;
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth     return string;
69*37da2899SCharles.Forsyth   }
70*37da2899SCharles.Forsyth 
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth   /* convert a UCS-4 name entry to ASCII */
73*37da2899SCharles.Forsyth   static FT_String*
tt_name_entry_ascii_from_ucs4(TT_NameEntry entry,FT_Memory memory)74*37da2899SCharles.Forsyth   tt_name_entry_ascii_from_ucs4( TT_NameEntry  entry,
75*37da2899SCharles.Forsyth                                  FT_Memory     memory )
76*37da2899SCharles.Forsyth   {
77*37da2899SCharles.Forsyth     FT_String*  string;
78*37da2899SCharles.Forsyth     FT_UInt     len, code, n;
79*37da2899SCharles.Forsyth     FT_Byte*    read = (FT_Byte*)entry->string;
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth 
82*37da2899SCharles.Forsyth     len = (FT_UInt)entry->stringLength / 4;
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth     if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
85*37da2899SCharles.Forsyth       return NULL;
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     for ( n = 0; n < len; n++ )
88*37da2899SCharles.Forsyth     {
89*37da2899SCharles.Forsyth       code = (FT_UInt)FT_NEXT_ULONG( read );
90*37da2899SCharles.Forsyth       if ( code < 32 || code > 127 )
91*37da2899SCharles.Forsyth         code = '?';
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth       string[n] = (char)code;
94*37da2899SCharles.Forsyth     }
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth     string[len] = 0;
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth     return string;
99*37da2899SCharles.Forsyth   }
100*37da2899SCharles.Forsyth 
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth   /* convert an Apple Roman or symbol name entry to ASCII */
103*37da2899SCharles.Forsyth   static FT_String*
tt_name_entry_ascii_from_other(TT_NameEntry entry,FT_Memory memory)104*37da2899SCharles.Forsyth   tt_name_entry_ascii_from_other( TT_NameEntry  entry,
105*37da2899SCharles.Forsyth                                   FT_Memory     memory )
106*37da2899SCharles.Forsyth   {
107*37da2899SCharles.Forsyth     FT_String*  string;
108*37da2899SCharles.Forsyth     FT_UInt     len, code, n;
109*37da2899SCharles.Forsyth     FT_Byte*    read = (FT_Byte*)entry->string;
110*37da2899SCharles.Forsyth 
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth     len = (FT_UInt)entry->stringLength;
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth     if ( FT_MEM_NEW_ARRAY( string, len + 1 ) )
115*37da2899SCharles.Forsyth       return NULL;
116*37da2899SCharles.Forsyth 
117*37da2899SCharles.Forsyth     for ( n = 0; n < len; n++ )
118*37da2899SCharles.Forsyth     {
119*37da2899SCharles.Forsyth       code = *read++;
120*37da2899SCharles.Forsyth       if ( code < 32 || code > 127 )
121*37da2899SCharles.Forsyth         code = '?';
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth       string[n] = (char)code;
124*37da2899SCharles.Forsyth     }
125*37da2899SCharles.Forsyth 
126*37da2899SCharles.Forsyth     string[len] = 0;
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth     return string;
129*37da2899SCharles.Forsyth   }
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth   typedef FT_String*  (*TT_NameEntry_ConvertFunc)( TT_NameEntry  entry,
133*37da2899SCharles.Forsyth                                                    FT_Memory     memory );
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth   /*************************************************************************/
137*37da2899SCharles.Forsyth   /*                                                                       */
138*37da2899SCharles.Forsyth   /* <Function>                                                            */
139*37da2899SCharles.Forsyth   /*    tt_face_get_name                                                   */
140*37da2899SCharles.Forsyth   /*                                                                       */
141*37da2899SCharles.Forsyth   /* <Description>                                                         */
142*37da2899SCharles.Forsyth   /*    Returns a given ENGLISH name record in ASCII.                      */
143*37da2899SCharles.Forsyth   /*                                                                       */
144*37da2899SCharles.Forsyth   /* <Input>                                                               */
145*37da2899SCharles.Forsyth   /*    face   :: A handle to the source face object.                      */
146*37da2899SCharles.Forsyth   /*                                                                       */
147*37da2899SCharles.Forsyth   /*    nameid :: The name id of the name record to return.                */
148*37da2899SCharles.Forsyth   /*                                                                       */
149*37da2899SCharles.Forsyth   /* <Return>                                                              */
150*37da2899SCharles.Forsyth   /*    Character string.  NULL if no name is present.                     */
151*37da2899SCharles.Forsyth   /*                                                                       */
152*37da2899SCharles.Forsyth   static FT_String*
tt_face_get_name(TT_Face face,FT_UShort nameid)153*37da2899SCharles.Forsyth   tt_face_get_name( TT_Face    face,
154*37da2899SCharles.Forsyth                     FT_UShort  nameid )
155*37da2899SCharles.Forsyth   {
156*37da2899SCharles.Forsyth     FT_Memory         memory = face->root.memory;
157*37da2899SCharles.Forsyth     FT_String*        result = NULL;
158*37da2899SCharles.Forsyth     FT_UShort         n;
159*37da2899SCharles.Forsyth     TT_NameEntryRec*  rec;
160*37da2899SCharles.Forsyth     FT_Int            found_apple   = -1;
161*37da2899SCharles.Forsyth     FT_Int            found_win     = -1;
162*37da2899SCharles.Forsyth     FT_Int            found_unicode = -1;
163*37da2899SCharles.Forsyth 
164*37da2899SCharles.Forsyth     TT_NameEntry_ConvertFunc  convert;
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth 
167*37da2899SCharles.Forsyth     rec = face->name_table.names;
168*37da2899SCharles.Forsyth     for ( n = 0; n < face->num_names; n++, rec++ )
169*37da2899SCharles.Forsyth     {
170*37da2899SCharles.Forsyth       /* According to the OpenType 1.3 specification, only Microsoft or  */
171*37da2899SCharles.Forsyth       /* Apple platform IDs might be used in the `name' table.  The      */
172*37da2899SCharles.Forsyth       /* `Unicode' platform is reserved for the `cmap' table, and the    */
173*37da2899SCharles.Forsyth       /* `Iso' one is deprecated.                                        */
174*37da2899SCharles.Forsyth       /*                                                                 */
175*37da2899SCharles.Forsyth       /* However, the Apple TrueType specification doesn't say the same  */
176*37da2899SCharles.Forsyth       /* thing and goes to suggest that all Unicode `name' table entries */
177*37da2899SCharles.Forsyth       /* should be coded in UTF-16 (in big-endian format I suppose).     */
178*37da2899SCharles.Forsyth       /*                                                                 */
179*37da2899SCharles.Forsyth       if ( rec->nameID == nameid && rec->stringLength > 0 )
180*37da2899SCharles.Forsyth       {
181*37da2899SCharles.Forsyth         switch ( rec->platformID )
182*37da2899SCharles.Forsyth         {
183*37da2899SCharles.Forsyth         case TT_PLATFORM_APPLE_UNICODE:
184*37da2899SCharles.Forsyth         case TT_PLATFORM_ISO:
185*37da2899SCharles.Forsyth           /* there is `languageID' to check there.  We should use this */
186*37da2899SCharles.Forsyth           /* field only as a last solution when nothing else is        */
187*37da2899SCharles.Forsyth           /* available.                                                */
188*37da2899SCharles.Forsyth           /*                                                           */
189*37da2899SCharles.Forsyth           found_unicode = n;
190*37da2899SCharles.Forsyth           break;
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth         case TT_PLATFORM_MACINTOSH:
193*37da2899SCharles.Forsyth           if ( rec->languageID == TT_MAC_LANGID_ENGLISH )
194*37da2899SCharles.Forsyth             found_apple = n;
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth           break;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth         case TT_PLATFORM_MICROSOFT:
199*37da2899SCharles.Forsyth           /* we only take a non-English name when there is nothing */
200*37da2899SCharles.Forsyth           /* else available in the font                            */
201*37da2899SCharles.Forsyth           /*                                                       */
202*37da2899SCharles.Forsyth           if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 )
203*37da2899SCharles.Forsyth           {
204*37da2899SCharles.Forsyth             switch ( rec->encodingID )
205*37da2899SCharles.Forsyth             {
206*37da2899SCharles.Forsyth             case TT_MS_ID_SYMBOL_CS:
207*37da2899SCharles.Forsyth             case TT_MS_ID_UNICODE_CS:
208*37da2899SCharles.Forsyth             case TT_MS_ID_UCS_4:
209*37da2899SCharles.Forsyth               found_win = n;
210*37da2899SCharles.Forsyth               break;
211*37da2899SCharles.Forsyth 
212*37da2899SCharles.Forsyth             default:
213*37da2899SCharles.Forsyth               ;
214*37da2899SCharles.Forsyth             }
215*37da2899SCharles.Forsyth           }
216*37da2899SCharles.Forsyth           break;
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth         default:
219*37da2899SCharles.Forsyth           ;
220*37da2899SCharles.Forsyth         }
221*37da2899SCharles.Forsyth       }
222*37da2899SCharles.Forsyth     }
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth     /* some fonts contain invalid Unicode or Macintosh formatted entries; */
225*37da2899SCharles.Forsyth     /* we will thus favor names encoded in Windows formats if available   */
226*37da2899SCharles.Forsyth     /*                                                                    */
227*37da2899SCharles.Forsyth     convert = NULL;
228*37da2899SCharles.Forsyth     if ( found_win >= 0 )
229*37da2899SCharles.Forsyth     {
230*37da2899SCharles.Forsyth       rec = face->name_table.names + found_win;
231*37da2899SCharles.Forsyth       switch ( rec->encodingID )
232*37da2899SCharles.Forsyth       {
233*37da2899SCharles.Forsyth       case TT_MS_ID_UNICODE_CS:
234*37da2899SCharles.Forsyth       case TT_MS_ID_SYMBOL_CS:
235*37da2899SCharles.Forsyth         convert = tt_name_entry_ascii_from_utf16;
236*37da2899SCharles.Forsyth         break;
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth       case TT_MS_ID_UCS_4:
239*37da2899SCharles.Forsyth         convert = tt_name_entry_ascii_from_ucs4;
240*37da2899SCharles.Forsyth         break;
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth       default:
243*37da2899SCharles.Forsyth         ;
244*37da2899SCharles.Forsyth       }
245*37da2899SCharles.Forsyth     }
246*37da2899SCharles.Forsyth     else if ( found_apple >= 0 )
247*37da2899SCharles.Forsyth     {
248*37da2899SCharles.Forsyth       rec     = face->name_table.names + found_apple;
249*37da2899SCharles.Forsyth       convert = tt_name_entry_ascii_from_other;
250*37da2899SCharles.Forsyth     }
251*37da2899SCharles.Forsyth     else if ( found_unicode >= 0 )
252*37da2899SCharles.Forsyth     {
253*37da2899SCharles.Forsyth       rec     = face->name_table.names + found_unicode;
254*37da2899SCharles.Forsyth       convert = tt_name_entry_ascii_from_utf16;
255*37da2899SCharles.Forsyth     }
256*37da2899SCharles.Forsyth 
257*37da2899SCharles.Forsyth     if ( rec && convert )
258*37da2899SCharles.Forsyth     {
259*37da2899SCharles.Forsyth       if ( rec->string == NULL )
260*37da2899SCharles.Forsyth       {
261*37da2899SCharles.Forsyth         FT_Error   error;
262*37da2899SCharles.Forsyth         FT_Stream  stream = face->name_table.stream;
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY  ( rec->string, rec->stringLength ) ||
266*37da2899SCharles.Forsyth              FT_STREAM_SEEK( rec->stringOffset )              ||
267*37da2899SCharles.Forsyth              FT_STREAM_READ( rec->string, rec->stringLength ) )
268*37da2899SCharles.Forsyth         {
269*37da2899SCharles.Forsyth           FT_FREE( rec->string );
270*37da2899SCharles.Forsyth           rec->stringLength = 0;
271*37da2899SCharles.Forsyth           result            = NULL;
272*37da2899SCharles.Forsyth           goto Exit;
273*37da2899SCharles.Forsyth         }
274*37da2899SCharles.Forsyth       }
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth       result = convert( rec, memory );
277*37da2899SCharles.Forsyth     }
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth   Exit:
280*37da2899SCharles.Forsyth     return result;
281*37da2899SCharles.Forsyth   }
282*37da2899SCharles.Forsyth 
283*37da2899SCharles.Forsyth 
284*37da2899SCharles.Forsyth   static FT_Encoding
sfnt_find_encoding(int platform_id,int encoding_id)285*37da2899SCharles.Forsyth   sfnt_find_encoding( int  platform_id,
286*37da2899SCharles.Forsyth                       int  encoding_id )
287*37da2899SCharles.Forsyth   {
288*37da2899SCharles.Forsyth     typedef struct  TEncoding
289*37da2899SCharles.Forsyth     {
290*37da2899SCharles.Forsyth       int          platform_id;
291*37da2899SCharles.Forsyth       int          encoding_id;
292*37da2899SCharles.Forsyth       FT_Encoding  encoding;
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth     } TEncoding;
295*37da2899SCharles.Forsyth 
296*37da2899SCharles.Forsyth     static
297*37da2899SCharles.Forsyth     const TEncoding  tt_encodings[] =
298*37da2899SCharles.Forsyth     {
299*37da2899SCharles.Forsyth       { TT_PLATFORM_ISO,           -1,                  FT_ENCODING_UNICODE },
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth       { TT_PLATFORM_APPLE_UNICODE, -1,                  FT_ENCODING_UNICODE },
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     FT_ENCODING_APPLE_ROMAN },
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,  FT_ENCODING_MS_SYMBOL },
306*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,      FT_ENCODING_UNICODE },
307*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE },
308*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       FT_ENCODING_MS_SJIS },
309*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     FT_ENCODING_MS_GB2312 },
310*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      FT_ENCODING_MS_BIG5 },
311*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    FT_ENCODING_MS_WANSUNG },
312*37da2899SCharles.Forsyth       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      FT_ENCODING_MS_JOHAB }
313*37da2899SCharles.Forsyth     };
314*37da2899SCharles.Forsyth 
315*37da2899SCharles.Forsyth     const TEncoding  *cur, *limit;
316*37da2899SCharles.Forsyth 
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth     cur   = tt_encodings;
319*37da2899SCharles.Forsyth     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
320*37da2899SCharles.Forsyth 
321*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
322*37da2899SCharles.Forsyth     {
323*37da2899SCharles.Forsyth       if ( cur->platform_id == platform_id )
324*37da2899SCharles.Forsyth       {
325*37da2899SCharles.Forsyth         if ( cur->encoding_id == encoding_id ||
326*37da2899SCharles.Forsyth              cur->encoding_id == -1          )
327*37da2899SCharles.Forsyth           return cur->encoding;
328*37da2899SCharles.Forsyth       }
329*37da2899SCharles.Forsyth     }
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth     return FT_ENCODING_NONE;
332*37da2899SCharles.Forsyth   }
333*37da2899SCharles.Forsyth 
334*37da2899SCharles.Forsyth 
335*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
sfnt_init_face(FT_Stream stream,TT_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)336*37da2899SCharles.Forsyth   sfnt_init_face( FT_Stream      stream,
337*37da2899SCharles.Forsyth                   TT_Face        face,
338*37da2899SCharles.Forsyth                   FT_Int         face_index,
339*37da2899SCharles.Forsyth                   FT_Int         num_params,
340*37da2899SCharles.Forsyth                   FT_Parameter*  params )
341*37da2899SCharles.Forsyth   {
342*37da2899SCharles.Forsyth     FT_Error         error;
343*37da2899SCharles.Forsyth     FT_Library       library = face->root.driver->root.library;
344*37da2899SCharles.Forsyth     SFNT_Service     sfnt;
345*37da2899SCharles.Forsyth     SFNT_HeaderRec   sfnt_header;
346*37da2899SCharles.Forsyth 
347*37da2899SCharles.Forsyth     /* for now, parameters are unused */
348*37da2899SCharles.Forsyth     FT_UNUSED( num_params );
349*37da2899SCharles.Forsyth     FT_UNUSED( params );
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth 
352*37da2899SCharles.Forsyth     sfnt = (SFNT_Service)face->sfnt;
353*37da2899SCharles.Forsyth     if ( !sfnt )
354*37da2899SCharles.Forsyth     {
355*37da2899SCharles.Forsyth       sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" );
356*37da2899SCharles.Forsyth       if ( !sfnt )
357*37da2899SCharles.Forsyth       {
358*37da2899SCharles.Forsyth         error = SFNT_Err_Invalid_File_Format;
359*37da2899SCharles.Forsyth         goto Exit;
360*37da2899SCharles.Forsyth       }
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth       face->sfnt       = sfnt;
363*37da2899SCharles.Forsyth       face->goto_table = sfnt->goto_table;
364*37da2899SCharles.Forsyth     }
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth     if ( !face->psnames )
367*37da2899SCharles.Forsyth     {
368*37da2899SCharles.Forsyth       face->psnames = (PSNames_Service)
369*37da2899SCharles.Forsyth                         FT_Get_Module_Interface( library, "psnames" );
370*37da2899SCharles.Forsyth     }
371*37da2899SCharles.Forsyth 
372*37da2899SCharles.Forsyth     /* check that we have a valid TrueType file */
373*37da2899SCharles.Forsyth     error = sfnt->load_sfnt_header( face, stream, face_index, &sfnt_header );
374*37da2899SCharles.Forsyth     if ( error )
375*37da2899SCharles.Forsyth       goto Exit;
376*37da2899SCharles.Forsyth 
377*37da2899SCharles.Forsyth     face->format_tag = sfnt_header.format_tag;
378*37da2899SCharles.Forsyth     face->num_tables = sfnt_header.num_tables;
379*37da2899SCharles.Forsyth 
380*37da2899SCharles.Forsyth     /* Load font directory */
381*37da2899SCharles.Forsyth     error = sfnt->load_directory( face, stream, &sfnt_header );
382*37da2899SCharles.Forsyth     if ( error )
383*37da2899SCharles.Forsyth       goto Exit;
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth     face->root.num_faces = face->ttc_header.count;
386*37da2899SCharles.Forsyth     if ( face->root.num_faces < 1 )
387*37da2899SCharles.Forsyth       face->root.num_faces = 1;
388*37da2899SCharles.Forsyth 
389*37da2899SCharles.Forsyth   Exit:
390*37da2899SCharles.Forsyth     return error;
391*37da2899SCharles.Forsyth   }
392*37da2899SCharles.Forsyth 
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth #undef  LOAD_
395*37da2899SCharles.Forsyth #define LOAD_( x )  ( ( error = sfnt->load_##x( face, stream ) ) \
396*37da2899SCharles.Forsyth                       != SFNT_Err_Ok )
397*37da2899SCharles.Forsyth 
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
sfnt_load_face(FT_Stream stream,TT_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)400*37da2899SCharles.Forsyth   sfnt_load_face( FT_Stream      stream,
401*37da2899SCharles.Forsyth                   TT_Face        face,
402*37da2899SCharles.Forsyth                   FT_Int         face_index,
403*37da2899SCharles.Forsyth                   FT_Int         num_params,
404*37da2899SCharles.Forsyth                   FT_Parameter*  params )
405*37da2899SCharles.Forsyth   {
406*37da2899SCharles.Forsyth     FT_Error      error;
407*37da2899SCharles.Forsyth     FT_Bool       has_outline;
408*37da2899SCharles.Forsyth     FT_Bool       is_apple_sbit;
409*37da2899SCharles.Forsyth 
410*37da2899SCharles.Forsyth     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth     FT_UNUSED( face_index );
413*37da2899SCharles.Forsyth     FT_UNUSED( num_params );
414*37da2899SCharles.Forsyth     FT_UNUSED( params );
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth 
417*37da2899SCharles.Forsyth     /* Load tables */
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth     /* We now support two SFNT-based bitmapped font formats.  They */
420*37da2899SCharles.Forsyth     /* are recognized easily as they do not include a `glyf'       */
421*37da2899SCharles.Forsyth     /* table.                                                      */
422*37da2899SCharles.Forsyth     /*                                                             */
423*37da2899SCharles.Forsyth     /* The first format comes from Apple, and uses a table named   */
424*37da2899SCharles.Forsyth     /* `bhed' instead of `head' to store the font header (using    */
425*37da2899SCharles.Forsyth     /* the same format).  It also doesn't include horizontal and   */
426*37da2899SCharles.Forsyth     /* vertical metrics tables (i.e. `hhea' and `vhea' tables are  */
427*37da2899SCharles.Forsyth     /* missing).                                                   */
428*37da2899SCharles.Forsyth     /*                                                             */
429*37da2899SCharles.Forsyth     /* The other format comes from Microsoft, and is used with     */
430*37da2899SCharles.Forsyth     /* WinCE/PocketPC.  It looks like a standard TTF, except that  */
431*37da2899SCharles.Forsyth     /* it doesn't contain outlines.                                */
432*37da2899SCharles.Forsyth     /*                                                             */
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth     /* do we have outlines in there? */
435*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
436*37da2899SCharles.Forsyth     has_outline   = FT_BOOL( face->root.internal->incremental_interface != 0 ||
437*37da2899SCharles.Forsyth                              tt_face_lookup_table( face, TTAG_glyf ) != 0         ||
438*37da2899SCharles.Forsyth                              tt_face_lookup_table( face, TTAG_CFF ) != 0          );
439*37da2899SCharles.Forsyth #else
440*37da2899SCharles.Forsyth     has_outline   = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 ||
441*37da2899SCharles.Forsyth                              tt_face_lookup_table( face, TTAG_CFF ) != 0  );
442*37da2899SCharles.Forsyth #endif
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth     is_apple_sbit = 0;
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth     /* if this font doesn't contain outlines, we try to load */
449*37da2899SCharles.Forsyth     /* a `bhed' table                                        */
450*37da2899SCharles.Forsyth     if ( !has_outline )
451*37da2899SCharles.Forsyth       is_apple_sbit = FT_BOOL( !LOAD_( bitmap_header ) );
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
454*37da2899SCharles.Forsyth 
455*37da2899SCharles.Forsyth     /* load the font header (`head' table) if this isn't an Apple */
456*37da2899SCharles.Forsyth     /* sbit font file                                             */
457*37da2899SCharles.Forsyth     if ( !is_apple_sbit && LOAD_( header ) )
458*37da2899SCharles.Forsyth       goto Exit;
459*37da2899SCharles.Forsyth 
460*37da2899SCharles.Forsyth     /* the following tables are often not present in embedded TrueType */
461*37da2899SCharles.Forsyth     /* fonts within PDF documents, so don't check for them.            */
462*37da2899SCharles.Forsyth     (void)LOAD_( max_profile );
463*37da2899SCharles.Forsyth     (void)LOAD_( charmaps );
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth     /* the following tables are optional in PCL fonts -- */
466*37da2899SCharles.Forsyth     /* don't check for errors                            */
467*37da2899SCharles.Forsyth     (void)LOAD_( names );
468*37da2899SCharles.Forsyth     (void)LOAD_( psnames );
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth     /* do not load the metrics headers and tables if this is an Apple */
471*37da2899SCharles.Forsyth     /* sbit font file                                                 */
472*37da2899SCharles.Forsyth     if ( !is_apple_sbit )
473*37da2899SCharles.Forsyth     {
474*37da2899SCharles.Forsyth       /* load the `hhea' and `hmtx' tables at once */
475*37da2899SCharles.Forsyth       error = sfnt->load_metrics( face, stream, 0 );
476*37da2899SCharles.Forsyth       if ( error )
477*37da2899SCharles.Forsyth         goto Exit;
478*37da2899SCharles.Forsyth 
479*37da2899SCharles.Forsyth       /* try to load the `vhea' and `vmtx' tables at once */
480*37da2899SCharles.Forsyth       error = sfnt->load_metrics( face, stream, 1 );
481*37da2899SCharles.Forsyth       if ( error )
482*37da2899SCharles.Forsyth         goto Exit;
483*37da2899SCharles.Forsyth 
484*37da2899SCharles.Forsyth       if ( LOAD_( os2 ) )
485*37da2899SCharles.Forsyth         goto Exit;
486*37da2899SCharles.Forsyth     }
487*37da2899SCharles.Forsyth 
488*37da2899SCharles.Forsyth     /* the optional tables */
489*37da2899SCharles.Forsyth 
490*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
491*37da2899SCharles.Forsyth 
492*37da2899SCharles.Forsyth     /* embedded bitmap support. */
493*37da2899SCharles.Forsyth     if ( sfnt->load_sbits && LOAD_( sbits ) )
494*37da2899SCharles.Forsyth     {
495*37da2899SCharles.Forsyth       /* return an error if this font file has no outlines */
496*37da2899SCharles.Forsyth       if ( error == SFNT_Err_Table_Missing && has_outline )
497*37da2899SCharles.Forsyth         error = SFNT_Err_Ok;
498*37da2899SCharles.Forsyth       else
499*37da2899SCharles.Forsyth         goto Exit;
500*37da2899SCharles.Forsyth     }
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth     if ( LOAD_( hdmx )    ||
505*37da2899SCharles.Forsyth          LOAD_( gasp )    ||
506*37da2899SCharles.Forsyth          LOAD_( kerning ) ||
507*37da2899SCharles.Forsyth          LOAD_( pclt )    )
508*37da2899SCharles.Forsyth       goto Exit;
509*37da2899SCharles.Forsyth 
510*37da2899SCharles.Forsyth     face->root.family_name = tt_face_get_name( face,
511*37da2899SCharles.Forsyth                                                TT_NAME_ID_FONT_FAMILY );
512*37da2899SCharles.Forsyth     face->root.style_name  = tt_face_get_name( face,
513*37da2899SCharles.Forsyth                                                TT_NAME_ID_FONT_SUBFAMILY );
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth     /* now set up root fields */
516*37da2899SCharles.Forsyth     {
517*37da2899SCharles.Forsyth       FT_Face    root = &face->root;
518*37da2899SCharles.Forsyth       FT_Int32   flags = 0;
519*37da2899SCharles.Forsyth       FT_Memory  memory;
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth       memory = root->memory;
523*37da2899SCharles.Forsyth 
524*37da2899SCharles.Forsyth       /*********************************************************************/
525*37da2899SCharles.Forsyth       /*                                                                   */
526*37da2899SCharles.Forsyth       /* Compute face flags.                                               */
527*37da2899SCharles.Forsyth       /*                                                                   */
528*37da2899SCharles.Forsyth       if ( has_outline == TRUE )
529*37da2899SCharles.Forsyth         flags = FT_FACE_FLAG_SCALABLE;    /* scalable outlines */
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth       flags |= FT_FACE_FLAG_SFNT      |   /* SFNT file format  */
532*37da2899SCharles.Forsyth                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
533*37da2899SCharles.Forsyth 
534*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
535*37da2899SCharles.Forsyth       /* might need more polish to detect the presence of a Postscript */
536*37da2899SCharles.Forsyth       /* name table in the font                                        */
537*37da2899SCharles.Forsyth       flags |= FT_FACE_FLAG_GLYPH_NAMES;
538*37da2899SCharles.Forsyth #endif
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth       /* fixed width font? */
541*37da2899SCharles.Forsyth       if ( face->postscript.isFixedPitch )
542*37da2899SCharles.Forsyth         flags |= FT_FACE_FLAG_FIXED_WIDTH;
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth       /* vertical information? */
545*37da2899SCharles.Forsyth       if ( face->vertical_info )
546*37da2899SCharles.Forsyth         flags |= FT_FACE_FLAG_VERTICAL;
547*37da2899SCharles.Forsyth 
548*37da2899SCharles.Forsyth       /* kerning available ? */
549*37da2899SCharles.Forsyth       if ( face->kern_pairs )
550*37da2899SCharles.Forsyth         flags |= FT_FACE_FLAG_KERNING;
551*37da2899SCharles.Forsyth 
552*37da2899SCharles.Forsyth       root->face_flags = flags;
553*37da2899SCharles.Forsyth 
554*37da2899SCharles.Forsyth       /*********************************************************************/
555*37da2899SCharles.Forsyth       /*                                                                   */
556*37da2899SCharles.Forsyth       /* Compute style flags.                                              */
557*37da2899SCharles.Forsyth       /*                                                                   */
558*37da2899SCharles.Forsyth       flags = 0;
559*37da2899SCharles.Forsyth       if ( has_outline == TRUE && face->os2.version != 0xFFFF )
560*37da2899SCharles.Forsyth       {
561*37da2899SCharles.Forsyth         /* we have an OS/2 table; use the `fsSelection' field */
562*37da2899SCharles.Forsyth         if ( face->os2.fsSelection & 1 )
563*37da2899SCharles.Forsyth           flags |= FT_STYLE_FLAG_ITALIC;
564*37da2899SCharles.Forsyth 
565*37da2899SCharles.Forsyth         if ( face->os2.fsSelection & 32 )
566*37da2899SCharles.Forsyth           flags |= FT_STYLE_FLAG_BOLD;
567*37da2899SCharles.Forsyth       }
568*37da2899SCharles.Forsyth       else
569*37da2899SCharles.Forsyth       {
570*37da2899SCharles.Forsyth         /* this is an old Mac font, use the header field */
571*37da2899SCharles.Forsyth         if ( face->header.Mac_Style & 1 )
572*37da2899SCharles.Forsyth           flags |= FT_STYLE_FLAG_BOLD;
573*37da2899SCharles.Forsyth 
574*37da2899SCharles.Forsyth         if ( face->header.Mac_Style & 2 )
575*37da2899SCharles.Forsyth           flags |= FT_STYLE_FLAG_ITALIC;
576*37da2899SCharles.Forsyth       }
577*37da2899SCharles.Forsyth 
578*37da2899SCharles.Forsyth       root->style_flags = flags;
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth       /*********************************************************************/
581*37da2899SCharles.Forsyth       /*                                                                   */
582*37da2899SCharles.Forsyth       /* Polish the charmaps.                                              */
583*37da2899SCharles.Forsyth       /*                                                                   */
584*37da2899SCharles.Forsyth       /*   Try to set the charmap encoding according to the platform &     */
585*37da2899SCharles.Forsyth       /*   encoding ID of each charmap.                                    */
586*37da2899SCharles.Forsyth       /*                                                                   */
587*37da2899SCharles.Forsyth 
588*37da2899SCharles.Forsyth       tt_face_build_cmaps( face );  /* ignore errors */
589*37da2899SCharles.Forsyth 
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth       /* set the encoding fields */
592*37da2899SCharles.Forsyth       {
593*37da2899SCharles.Forsyth         FT_Int  m;
594*37da2899SCharles.Forsyth 
595*37da2899SCharles.Forsyth 
596*37da2899SCharles.Forsyth         for ( m = 0; m < root->num_charmaps; m++ )
597*37da2899SCharles.Forsyth         {
598*37da2899SCharles.Forsyth           FT_CharMap  charmap = root->charmaps[m];
599*37da2899SCharles.Forsyth 
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth           charmap->encoding = sfnt_find_encoding( charmap->platform_id,
602*37da2899SCharles.Forsyth                                                   charmap->encoding_id );
603*37da2899SCharles.Forsyth 
604*37da2899SCharles.Forsyth #if 0
605*37da2899SCharles.Forsyth           if ( root->charmap     == NULL &&
606*37da2899SCharles.Forsyth                charmap->encoding == FT_ENCODING_UNICODE )
607*37da2899SCharles.Forsyth           {
608*37da2899SCharles.Forsyth             /* set 'root->charmap' to the first Unicode encoding we find */
609*37da2899SCharles.Forsyth             root->charmap = charmap;
610*37da2899SCharles.Forsyth           }
611*37da2899SCharles.Forsyth #endif
612*37da2899SCharles.Forsyth         }
613*37da2899SCharles.Forsyth       }
614*37da2899SCharles.Forsyth 
615*37da2899SCharles.Forsyth 
616*37da2899SCharles.Forsyth #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth       if ( face->num_sbit_strikes )
619*37da2899SCharles.Forsyth       {
620*37da2899SCharles.Forsyth         FT_ULong  n;
621*37da2899SCharles.Forsyth 
622*37da2899SCharles.Forsyth 
623*37da2899SCharles.Forsyth         root->face_flags |= FT_FACE_FLAG_FIXED_SIZES;
624*37da2899SCharles.Forsyth 
625*37da2899SCharles.Forsyth #if 0
626*37da2899SCharles.Forsyth         /* XXX: I don't know criteria whether layout is horizontal */
627*37da2899SCharles.Forsyth         /*      or vertical.                                       */
628*37da2899SCharles.Forsyth         if ( has_outline.... )
629*37da2899SCharles.Forsyth         {
630*37da2899SCharles.Forsyth           ...
631*37da2899SCharles.Forsyth           root->face_flags |= FT_FACE_FLAG_VERTICAL;
632*37da2899SCharles.Forsyth         }
633*37da2899SCharles.Forsyth #endif
634*37da2899SCharles.Forsyth         root->num_fixed_sizes = face->num_sbit_strikes;
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( root->available_sizes, face->num_sbit_strikes ) )
637*37da2899SCharles.Forsyth           goto Exit;
638*37da2899SCharles.Forsyth 
639*37da2899SCharles.Forsyth         for ( n = 0 ; n < face->num_sbit_strikes ; n++ )
640*37da2899SCharles.Forsyth         {
641*37da2899SCharles.Forsyth           root->available_sizes[n].width =
642*37da2899SCharles.Forsyth             face->sbit_strikes[n].x_ppem;
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth           root->available_sizes[n].height =
645*37da2899SCharles.Forsyth             face->sbit_strikes[n].y_ppem;
646*37da2899SCharles.Forsyth         }
647*37da2899SCharles.Forsyth       }
648*37da2899SCharles.Forsyth       else
649*37da2899SCharles.Forsyth 
650*37da2899SCharles.Forsyth #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth       {
653*37da2899SCharles.Forsyth         root->num_fixed_sizes = 0;
654*37da2899SCharles.Forsyth         root->available_sizes = 0;
655*37da2899SCharles.Forsyth       }
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth       /*********************************************************************/
658*37da2899SCharles.Forsyth       /*                                                                   */
659*37da2899SCharles.Forsyth       /*  Set up metrics.                                                  */
660*37da2899SCharles.Forsyth       /*                                                                   */
661*37da2899SCharles.Forsyth       if ( has_outline == TRUE )
662*37da2899SCharles.Forsyth       {
663*37da2899SCharles.Forsyth         /* XXX What about if outline header is missing */
664*37da2899SCharles.Forsyth         /*     (e.g. sfnt wrapped outline)?            */
665*37da2899SCharles.Forsyth         root->bbox.xMin    = face->header.xMin;
666*37da2899SCharles.Forsyth         root->bbox.yMin    = face->header.yMin;
667*37da2899SCharles.Forsyth         root->bbox.xMax    = face->header.xMax;
668*37da2899SCharles.Forsyth         root->bbox.yMax    = face->header.yMax;
669*37da2899SCharles.Forsyth         root->units_per_EM = face->header.Units_Per_EM;
670*37da2899SCharles.Forsyth 
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth         /* XXX: Computing the ascender/descender/height is very different */
673*37da2899SCharles.Forsyth         /*      from what the specification tells you.  Apparently, we    */
674*37da2899SCharles.Forsyth         /*      must be careful because                                   */
675*37da2899SCharles.Forsyth         /*                                                                */
676*37da2899SCharles.Forsyth         /*      - not all fonts have an OS/2 table; in this case, we take */
677*37da2899SCharles.Forsyth         /*        the values in the horizontal header.  However, these    */
678*37da2899SCharles.Forsyth         /*        values very often are not reliable.                     */
679*37da2899SCharles.Forsyth         /*                                                                */
680*37da2899SCharles.Forsyth         /*      - otherwise, the correct typographic values are in the    */
681*37da2899SCharles.Forsyth         /*        sTypoAscender, sTypoDescender & sTypoLineGap fields.    */
682*37da2899SCharles.Forsyth         /*                                                                */
683*37da2899SCharles.Forsyth         /*        However, certains fonts have these fields set to 0.     */
684*37da2899SCharles.Forsyth         /*        Rather, they have usWinAscent & usWinDescent correctly  */
685*37da2899SCharles.Forsyth         /*        set (but with different values).                        */
686*37da2899SCharles.Forsyth         /*                                                                */
687*37da2899SCharles.Forsyth         /*      As an example, Arial Narrow is implemented through four   */
688*37da2899SCharles.Forsyth         /*      files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */
689*37da2899SCharles.Forsyth         /*                                                                */
690*37da2899SCharles.Forsyth         /*      Strangely, all fonts have the same values in their        */
691*37da2899SCharles.Forsyth         /*      sTypoXXX fields, except ARIALNB which sets them to 0.     */
692*37da2899SCharles.Forsyth         /*                                                                */
693*37da2899SCharles.Forsyth         /*      On the other hand, they all have different                */
694*37da2899SCharles.Forsyth         /*      usWinAscent/Descent values -- as a conclusion, the OS/2   */
695*37da2899SCharles.Forsyth         /*      table cannot be used to compute the text height reliably! */
696*37da2899SCharles.Forsyth         /*                                                                */
697*37da2899SCharles.Forsyth 
698*37da2899SCharles.Forsyth         /* The ascender/descender/height are computed from the OS/2 table */
699*37da2899SCharles.Forsyth         /* when found.  Otherwise, they're taken from the horizontal      */
700*37da2899SCharles.Forsyth         /* header.                                                        */
701*37da2899SCharles.Forsyth         /*                                                                */
702*37da2899SCharles.Forsyth 
703*37da2899SCharles.Forsyth         root->ascender  = face->horizontal.Ascender;
704*37da2899SCharles.Forsyth         root->descender = face->horizontal.Descender;
705*37da2899SCharles.Forsyth 
706*37da2899SCharles.Forsyth         root->height    = (FT_Short)( root->ascender - root->descender +
707*37da2899SCharles.Forsyth                                       face->horizontal.Line_Gap );
708*37da2899SCharles.Forsyth 
709*37da2899SCharles.Forsyth         /* if the line_gap is 0, we add an extra 15% to the text height --  */
710*37da2899SCharles.Forsyth         /* this computation is based on various versions of Times New Roman */
711*37da2899SCharles.Forsyth         if ( face->horizontal.Line_Gap == 0 )
712*37da2899SCharles.Forsyth           root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 );
713*37da2899SCharles.Forsyth 
714*37da2899SCharles.Forsyth #if 0
715*37da2899SCharles.Forsyth 
716*37da2899SCharles.Forsyth         /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */
717*37da2899SCharles.Forsyth         /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF             */
718*37da2899SCharles.Forsyth         if ( face->os2.version != 0xFFFF && root->ascender )
719*37da2899SCharles.Forsyth         {
720*37da2899SCharles.Forsyth           FT_Int  height;
721*37da2899SCharles.Forsyth 
722*37da2899SCharles.Forsyth 
723*37da2899SCharles.Forsyth           root->ascender  =  face->os2.sTypoAscender;
724*37da2899SCharles.Forsyth           root->descender = -face->os2.sTypoDescender;
725*37da2899SCharles.Forsyth 
726*37da2899SCharles.Forsyth           height = root->ascender + root->descender + face->os2.sTypoLineGap;
727*37da2899SCharles.Forsyth           if ( height > root->height )
728*37da2899SCharles.Forsyth             root->height = height;
729*37da2899SCharles.Forsyth         }
730*37da2899SCharles.Forsyth 
731*37da2899SCharles.Forsyth #endif /* 0 */
732*37da2899SCharles.Forsyth 
733*37da2899SCharles.Forsyth         root->max_advance_width   = face->horizontal.advance_Width_Max;
734*37da2899SCharles.Forsyth 
735*37da2899SCharles.Forsyth         root->max_advance_height  = (FT_Short)( face->vertical_info
736*37da2899SCharles.Forsyth                                       ? face->vertical.advance_Height_Max
737*37da2899SCharles.Forsyth                                       : root->height );
738*37da2899SCharles.Forsyth 
739*37da2899SCharles.Forsyth         root->underline_position  = face->postscript.underlinePosition;
740*37da2899SCharles.Forsyth         root->underline_thickness = face->postscript.underlineThickness;
741*37da2899SCharles.Forsyth 
742*37da2899SCharles.Forsyth         /* root->max_points   -- already set up */
743*37da2899SCharles.Forsyth         /* root->max_contours -- already set up */
744*37da2899SCharles.Forsyth       }
745*37da2899SCharles.Forsyth     }
746*37da2899SCharles.Forsyth 
747*37da2899SCharles.Forsyth   Exit:
748*37da2899SCharles.Forsyth     return error;
749*37da2899SCharles.Forsyth   }
750*37da2899SCharles.Forsyth 
751*37da2899SCharles.Forsyth 
752*37da2899SCharles.Forsyth #undef LOAD_
753*37da2899SCharles.Forsyth 
754*37da2899SCharles.Forsyth 
755*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
sfnt_done_face(TT_Face face)756*37da2899SCharles.Forsyth   sfnt_done_face( TT_Face  face )
757*37da2899SCharles.Forsyth   {
758*37da2899SCharles.Forsyth     FT_Memory     memory = face->root.memory;
759*37da2899SCharles.Forsyth     SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
760*37da2899SCharles.Forsyth 
761*37da2899SCharles.Forsyth 
762*37da2899SCharles.Forsyth     if ( sfnt )
763*37da2899SCharles.Forsyth     {
764*37da2899SCharles.Forsyth       /* destroy the postscript names table if it is loaded */
765*37da2899SCharles.Forsyth       if ( sfnt->free_psnames )
766*37da2899SCharles.Forsyth         sfnt->free_psnames( face );
767*37da2899SCharles.Forsyth 
768*37da2899SCharles.Forsyth       /* destroy the embedded bitmaps table if it is loaded */
769*37da2899SCharles.Forsyth       if ( sfnt->free_sbits )
770*37da2899SCharles.Forsyth         sfnt->free_sbits( face );
771*37da2899SCharles.Forsyth     }
772*37da2899SCharles.Forsyth 
773*37da2899SCharles.Forsyth     /* freeing the kerning table */
774*37da2899SCharles.Forsyth     FT_FREE( face->kern_pairs );
775*37da2899SCharles.Forsyth     face->num_kern_pairs = 0;
776*37da2899SCharles.Forsyth 
777*37da2899SCharles.Forsyth     /* freeing the collection table */
778*37da2899SCharles.Forsyth     FT_FREE( face->ttc_header.offsets );
779*37da2899SCharles.Forsyth     face->ttc_header.count = 0;
780*37da2899SCharles.Forsyth 
781*37da2899SCharles.Forsyth     /* freeing table directory */
782*37da2899SCharles.Forsyth     FT_FREE( face->dir_tables );
783*37da2899SCharles.Forsyth     face->num_tables = 0;
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth     {
786*37da2899SCharles.Forsyth       FT_Stream  stream = FT_FACE_STREAM( face );
787*37da2899SCharles.Forsyth 
788*37da2899SCharles.Forsyth 
789*37da2899SCharles.Forsyth       /* simply release the 'cmap' table frame */
790*37da2899SCharles.Forsyth       FT_FRAME_RELEASE( face->cmap_table );
791*37da2899SCharles.Forsyth       face->cmap_size = 0;
792*37da2899SCharles.Forsyth     }
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth     /* freeing the horizontal metrics */
795*37da2899SCharles.Forsyth     FT_FREE( face->horizontal.long_metrics );
796*37da2899SCharles.Forsyth     FT_FREE( face->horizontal.short_metrics );
797*37da2899SCharles.Forsyth 
798*37da2899SCharles.Forsyth     /* freeing the vertical ones, if any */
799*37da2899SCharles.Forsyth     if ( face->vertical_info )
800*37da2899SCharles.Forsyth     {
801*37da2899SCharles.Forsyth       FT_FREE( face->vertical.long_metrics  );
802*37da2899SCharles.Forsyth       FT_FREE( face->vertical.short_metrics );
803*37da2899SCharles.Forsyth       face->vertical_info = 0;
804*37da2899SCharles.Forsyth     }
805*37da2899SCharles.Forsyth 
806*37da2899SCharles.Forsyth     /* freeing the gasp table */
807*37da2899SCharles.Forsyth     FT_FREE( face->gasp.gaspRanges );
808*37da2899SCharles.Forsyth     face->gasp.numRanges = 0;
809*37da2899SCharles.Forsyth 
810*37da2899SCharles.Forsyth     /* freeing the name table */
811*37da2899SCharles.Forsyth     sfnt->free_names( face );
812*37da2899SCharles.Forsyth 
813*37da2899SCharles.Forsyth     /* freeing the hdmx table */
814*37da2899SCharles.Forsyth     sfnt->free_hdmx( face );
815*37da2899SCharles.Forsyth 
816*37da2899SCharles.Forsyth     /* freeing family and style name */
817*37da2899SCharles.Forsyth     FT_FREE( face->root.family_name );
818*37da2899SCharles.Forsyth     FT_FREE( face->root.style_name );
819*37da2899SCharles.Forsyth 
820*37da2899SCharles.Forsyth     /* freeing sbit size table */
821*37da2899SCharles.Forsyth     face->root.num_fixed_sizes = 0;
822*37da2899SCharles.Forsyth     if ( face->root.available_sizes )
823*37da2899SCharles.Forsyth       FT_FREE( face->root.available_sizes );
824*37da2899SCharles.Forsyth 
825*37da2899SCharles.Forsyth     face->sfnt = 0;
826*37da2899SCharles.Forsyth   }
827*37da2899SCharles.Forsyth 
828*37da2899SCharles.Forsyth 
829*37da2899SCharles.Forsyth /* END */
830