xref: /inferno-os/libfreetype/t42parse.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  t42parse.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    Type 42 font parser (body).                                          */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2002 by Roberto Alameda.                                     */
8*37da2899SCharles.Forsyth /*                                                                         */
9*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
10*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
11*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
12*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
13*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
14*37da2899SCharles.Forsyth /*                                                                         */
15*37da2899SCharles.Forsyth /***************************************************************************/
16*37da2899SCharles.Forsyth 
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth #include "t42parse.h"
19*37da2899SCharles.Forsyth #include "t42error.h"
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
22*37da2899SCharles.Forsyth #include FT_LIST_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_POSTSCRIPT_AUX_H
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth   /*************************************************************************/
27*37da2899SCharles.Forsyth   /*                                                                       */
28*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
29*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
30*37da2899SCharles.Forsyth   /* messages during execution.                                            */
31*37da2899SCharles.Forsyth   /*                                                                       */
32*37da2899SCharles.Forsyth #undef  FT_COMPONENT
33*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_t42
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth   static void
37*37da2899SCharles.Forsyth   t42_parse_font_name( T42_Face    face,
38*37da2899SCharles.Forsyth                        T42_Loader  loader );
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth   static void
41*37da2899SCharles.Forsyth   t42_parse_font_bbox( T42_Face    face,
42*37da2899SCharles.Forsyth                        T42_Loader  loader );
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth   static void
45*37da2899SCharles.Forsyth   t42_parse_font_matrix( T42_Face    face,
46*37da2899SCharles.Forsyth                          T42_Loader  loader );
47*37da2899SCharles.Forsyth   static void
48*37da2899SCharles.Forsyth   t42_parse_encoding( T42_Face    face,
49*37da2899SCharles.Forsyth                       T42_Loader  loader );
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth   static void
52*37da2899SCharles.Forsyth   t42_parse_charstrings( T42_Face    face,
53*37da2899SCharles.Forsyth                          T42_Loader  loader );
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth   static void
56*37da2899SCharles.Forsyth   t42_parse_sfnts( T42_Face    face,
57*37da2899SCharles.Forsyth                    T42_Loader  loader );
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth   static const
61*37da2899SCharles.Forsyth   T1_FieldRec  t42_keywords[] = {
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
64*37da2899SCharles.Forsyth #define FT_STRUCTURE  T1_FontInfo
65*37da2899SCharles.Forsyth #undef  T1CODE
66*37da2899SCharles.Forsyth #define T1CODE        T1_FIELD_LOCATION_FONT_INFO
67*37da2899SCharles.Forsyth 
68*37da2899SCharles.Forsyth     T1_FIELD_STRING   ( "version",            version )
69*37da2899SCharles.Forsyth     T1_FIELD_STRING   ( "Notice",             notice )
70*37da2899SCharles.Forsyth     T1_FIELD_STRING   ( "FullName",           full_name )
71*37da2899SCharles.Forsyth     T1_FIELD_STRING   ( "FamilyName",         family_name )
72*37da2899SCharles.Forsyth     T1_FIELD_STRING   ( "Weight",             weight )
73*37da2899SCharles.Forsyth     T1_FIELD_NUM      ( "ItalicAngle",        italic_angle )
74*37da2899SCharles.Forsyth     T1_FIELD_TYPE_BOOL( "isFixedPitch",       is_fixed_pitch )
75*37da2899SCharles.Forsyth     T1_FIELD_NUM      ( "UnderlinePosition",  underline_position )
76*37da2899SCharles.Forsyth     T1_FIELD_NUM      ( "UnderlineThickness", underline_thickness )
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth #undef  FT_STRUCTURE
79*37da2899SCharles.Forsyth #define FT_STRUCTURE  T1_FontRec
80*37da2899SCharles.Forsyth #undef  T1CODE
81*37da2899SCharles.Forsyth #define T1CODE        T1_FIELD_LOCATION_FONT_DICT
82*37da2899SCharles.Forsyth 
83*37da2899SCharles.Forsyth     T1_FIELD_NUM( "PaintType",   paint_type )
84*37da2899SCharles.Forsyth     T1_FIELD_NUM( "FontType",    font_type )
85*37da2899SCharles.Forsyth     T1_FIELD_NUM( "StrokeWidth", stroke_width )
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontName",    t42_parse_font_name )
88*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontBBox",    t42_parse_font_bbox )
89*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontMatrix",  t42_parse_font_matrix )
90*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "Encoding",    t42_parse_encoding )
91*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings )
92*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "sfnts",       t42_parse_sfnts )
93*37da2899SCharles.Forsyth 
94*37da2899SCharles.Forsyth     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
95*37da2899SCharles.Forsyth   };
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth #define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
99*37da2899SCharles.Forsyth #define T1_Done_Table( p )          \
100*37da2899SCharles.Forsyth           do                        \
101*37da2899SCharles.Forsyth           {                         \
102*37da2899SCharles.Forsyth             if ( (p)->funcs.done )  \
103*37da2899SCharles.Forsyth               (p)->funcs.done( p ); \
104*37da2899SCharles.Forsyth           } while ( 0 )
105*37da2899SCharles.Forsyth #define T1_Release_Table( p )          \
106*37da2899SCharles.Forsyth           do                           \
107*37da2899SCharles.Forsyth           {                            \
108*37da2899SCharles.Forsyth             if ( (p)->funcs.release )  \
109*37da2899SCharles.Forsyth               (p)->funcs.release( p ); \
110*37da2899SCharles.Forsyth           } while ( 0 )
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth #define T1_Skip_Spaces( p )  (p)->root.funcs.skip_spaces( &(p)->root )
113*37da2899SCharles.Forsyth #define T1_Skip_Alpha( p )   (p)->root.funcs.skip_alpha ( &(p)->root )
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth #define T1_ToInt( p )       (p)->root.funcs.to_int( &(p)->root )
116*37da2899SCharles.Forsyth #define T1_ToFixed( p, t )  (p)->root.funcs.to_fixed( &(p)->root, t )
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth #define T1_ToCoordArray( p, m, c )                           \
119*37da2899SCharles.Forsyth           (p)->root.funcs.to_coord_array( &(p)->root, m, c )
120*37da2899SCharles.Forsyth #define T1_ToFixedArray( p, m, f, t )                           \
121*37da2899SCharles.Forsyth           (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
122*37da2899SCharles.Forsyth #define T1_ToToken( p, t )                          \
123*37da2899SCharles.Forsyth           (p)->root.funcs.to_token( &(p)->root, t )
124*37da2899SCharles.Forsyth #define T1_ToTokenArray( p, t, m, c )                           \
125*37da2899SCharles.Forsyth           (p)->root.funcs.to_token_array( &(p)->root, t, m, c )
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth #define T1_Load_Field( p, f, o, m, pf )                         \
128*37da2899SCharles.Forsyth           (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
129*37da2899SCharles.Forsyth #define T1_Load_Field_Table( p, f, o, m, pf )                         \
130*37da2899SCharles.Forsyth           (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth   /********************* Parsing Functions ******************/
134*37da2899SCharles.Forsyth 
135*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
t42_parser_init(T42_Parser parser,FT_Stream stream,FT_Memory memory,PSAux_Service psaux)136*37da2899SCharles.Forsyth   t42_parser_init( T42_Parser     parser,
137*37da2899SCharles.Forsyth                    FT_Stream      stream,
138*37da2899SCharles.Forsyth                    FT_Memory      memory,
139*37da2899SCharles.Forsyth                    PSAux_Service  psaux )
140*37da2899SCharles.Forsyth   {
141*37da2899SCharles.Forsyth     FT_Error  error = T42_Err_Ok;
142*37da2899SCharles.Forsyth     FT_Long   size;
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
146*37da2899SCharles.Forsyth 
147*37da2899SCharles.Forsyth     parser->stream    = stream;
148*37da2899SCharles.Forsyth     parser->base_len  = 0;
149*37da2899SCharles.Forsyth     parser->base_dict = 0;
150*37da2899SCharles.Forsyth     parser->in_memory = 0;
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth     /*******************************************************************/
153*37da2899SCharles.Forsyth     /*                                                                 */
154*37da2899SCharles.Forsyth     /* Here a short summary of what is going on:                       */
155*37da2899SCharles.Forsyth     /*                                                                 */
156*37da2899SCharles.Forsyth     /*   When creating a new Type 42 parser, we try to locate and load */
157*37da2899SCharles.Forsyth     /*   the base dictionary, loading the whole font into memory.      */
158*37da2899SCharles.Forsyth     /*                                                                 */
159*37da2899SCharles.Forsyth     /*   When `loading' the base dictionary, we only setup pointers in */
160*37da2899SCharles.Forsyth     /*   the case of a memory-based stream.  Otherwise, we allocate    */
161*37da2899SCharles.Forsyth     /*   and load the base dictionary in it.                           */
162*37da2899SCharles.Forsyth     /*                                                                 */
163*37da2899SCharles.Forsyth     /*   parser->in_memory is set if we have a memory stream.          */
164*37da2899SCharles.Forsyth     /*                                                                 */
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( 0L ) )
167*37da2899SCharles.Forsyth       goto Exit;
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth     size = stream->size;
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth     /* now, try to load `size' bytes of the `base' dictionary we */
172*37da2899SCharles.Forsyth     /* found previously                                          */
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth     /* if it is a memory-based resource, set up pointers */
175*37da2899SCharles.Forsyth     if ( !stream->read )
176*37da2899SCharles.Forsyth     {
177*37da2899SCharles.Forsyth       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
178*37da2899SCharles.Forsyth       parser->base_len  = size;
179*37da2899SCharles.Forsyth       parser->in_memory = 1;
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth       /* check that the `size' field is valid */
182*37da2899SCharles.Forsyth       if ( FT_STREAM_SKIP( size ) )
183*37da2899SCharles.Forsyth         goto Exit;
184*37da2899SCharles.Forsyth     }
185*37da2899SCharles.Forsyth     else
186*37da2899SCharles.Forsyth     {
187*37da2899SCharles.Forsyth       /* read segment in memory */
188*37da2899SCharles.Forsyth       if ( FT_ALLOC( parser->base_dict, size )       ||
189*37da2899SCharles.Forsyth            FT_STREAM_READ( parser->base_dict, size ) )
190*37da2899SCharles.Forsyth         goto Exit;
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth       parser->base_len = size;
193*37da2899SCharles.Forsyth     }
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth     /* Now check font format; we must see `%!PS-TrueTypeFont' */
196*37da2899SCharles.Forsyth     if (size <= 17                                    ||
197*37da2899SCharles.Forsyth         ( ft_strncmp( (const char*)parser->base_dict,
198*37da2899SCharles.Forsyth                       "%!PS-TrueTypeFont", 17) )      )
199*37da2899SCharles.Forsyth       error = T42_Err_Unknown_File_Format;
200*37da2899SCharles.Forsyth     else
201*37da2899SCharles.Forsyth     {
202*37da2899SCharles.Forsyth       parser->root.base   = parser->base_dict;
203*37da2899SCharles.Forsyth       parser->root.cursor = parser->base_dict;
204*37da2899SCharles.Forsyth       parser->root.limit  = parser->root.cursor + parser->base_len;
205*37da2899SCharles.Forsyth     }
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth   Exit:
208*37da2899SCharles.Forsyth     if ( error && !parser->in_memory )
209*37da2899SCharles.Forsyth       FT_FREE( parser->base_dict );
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth     return error;
212*37da2899SCharles.Forsyth   }
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth 
215*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
t42_parser_done(T42_Parser parser)216*37da2899SCharles.Forsyth   t42_parser_done( T42_Parser  parser )
217*37da2899SCharles.Forsyth   {
218*37da2899SCharles.Forsyth     FT_Memory  memory = parser->root.memory;
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth     /* free the base dictionary only when we have a disk stream */
222*37da2899SCharles.Forsyth     if ( !parser->in_memory )
223*37da2899SCharles.Forsyth       FT_FREE( parser->base_dict );
224*37da2899SCharles.Forsyth 
225*37da2899SCharles.Forsyth     parser->root.funcs.done( &parser->root );
226*37da2899SCharles.Forsyth   }
227*37da2899SCharles.Forsyth 
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth   static int
t42_is_alpha(FT_Byte c)230*37da2899SCharles.Forsyth   t42_is_alpha( FT_Byte  c )
231*37da2899SCharles.Forsyth   {
232*37da2899SCharles.Forsyth     /* Note: we must accept "+" as a valid character, as it is used in */
233*37da2899SCharles.Forsyth     /*       embedded type1 fonts in PDF documents.                    */
234*37da2899SCharles.Forsyth     /*                                                                 */
235*37da2899SCharles.Forsyth     return ( ft_isalnum( c ) ||
236*37da2899SCharles.Forsyth              c == '.'        ||
237*37da2899SCharles.Forsyth              c == '_'        ||
238*37da2899SCharles.Forsyth              c == '-'        ||
239*37da2899SCharles.Forsyth              c == '+'        );
240*37da2899SCharles.Forsyth   }
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth   static int
t42_is_space(FT_Byte c)244*37da2899SCharles.Forsyth   t42_is_space( FT_Byte  c )
245*37da2899SCharles.Forsyth   {
246*37da2899SCharles.Forsyth     return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
247*37da2899SCharles.Forsyth   }
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth   static void
t42_parse_font_name(T42_Face face,T42_Loader loader)251*37da2899SCharles.Forsyth   t42_parse_font_name( T42_Face    face,
252*37da2899SCharles.Forsyth                        T42_Loader  loader )
253*37da2899SCharles.Forsyth   {
254*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
255*37da2899SCharles.Forsyth     FT_Error    error;
256*37da2899SCharles.Forsyth     FT_Memory   memory = parser->root.memory;
257*37da2899SCharles.Forsyth     FT_Int      len;
258*37da2899SCharles.Forsyth     FT_Byte*    cur;
259*37da2899SCharles.Forsyth     FT_Byte*    cur2;
260*37da2899SCharles.Forsyth     FT_Byte*    limit;
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth     T1_Skip_Spaces( parser );
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth     cur   = parser->root.cursor;
266*37da2899SCharles.Forsyth     limit = parser->root.limit;
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth     if ( cur >= limit - 1              ||
269*37da2899SCharles.Forsyth          ( *cur != '/' && *cur != '(') )
270*37da2899SCharles.Forsyth       return;
271*37da2899SCharles.Forsyth 
272*37da2899SCharles.Forsyth     cur++;
273*37da2899SCharles.Forsyth     cur2 = cur;
274*37da2899SCharles.Forsyth     while ( cur2 < limit && t42_is_alpha( *cur2 ) )
275*37da2899SCharles.Forsyth       cur2++;
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth     len = (FT_Int)( cur2 - cur );
278*37da2899SCharles.Forsyth     if ( len > 0 )
279*37da2899SCharles.Forsyth     {
280*37da2899SCharles.Forsyth       if ( FT_ALLOC( face->type1.font_name, len + 1 ) )
281*37da2899SCharles.Forsyth       {
282*37da2899SCharles.Forsyth         parser->root.error = error;
283*37da2899SCharles.Forsyth         return;
284*37da2899SCharles.Forsyth       }
285*37da2899SCharles.Forsyth 
286*37da2899SCharles.Forsyth       FT_MEM_COPY( face->type1.font_name, cur, len );
287*37da2899SCharles.Forsyth       face->type1.font_name[len] = '\0';
288*37da2899SCharles.Forsyth     }
289*37da2899SCharles.Forsyth     parser->root.cursor = cur2;
290*37da2899SCharles.Forsyth   }
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth 
293*37da2899SCharles.Forsyth   static void
t42_parse_font_bbox(T42_Face face,T42_Loader loader)294*37da2899SCharles.Forsyth   t42_parse_font_bbox( T42_Face   face,
295*37da2899SCharles.Forsyth                        T42_Loader  loader )
296*37da2899SCharles.Forsyth   {
297*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
298*37da2899SCharles.Forsyth     FT_BBox*    bbox   = &face->type1.font_bbox;
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth     bbox->xMin = T1_ToInt( parser );
301*37da2899SCharles.Forsyth     bbox->yMin = T1_ToInt( parser );
302*37da2899SCharles.Forsyth     bbox->xMax = T1_ToInt( parser );
303*37da2899SCharles.Forsyth     bbox->yMax = T1_ToInt( parser );
304*37da2899SCharles.Forsyth   }
305*37da2899SCharles.Forsyth 
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth   static void
t42_parse_font_matrix(T42_Face face,T42_Loader loader)308*37da2899SCharles.Forsyth   t42_parse_font_matrix( T42_Face    face,
309*37da2899SCharles.Forsyth                          T42_Loader  loader )
310*37da2899SCharles.Forsyth   {
311*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
312*37da2899SCharles.Forsyth     FT_Matrix*  matrix = &face->type1.font_matrix;
313*37da2899SCharles.Forsyth     FT_Vector*  offset = &face->type1.font_offset;
314*37da2899SCharles.Forsyth     FT_Face     root   = (FT_Face)&face->root;
315*37da2899SCharles.Forsyth     FT_Fixed    temp[6];
316*37da2899SCharles.Forsyth     FT_Fixed    temp_scale;
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth     (void)T1_ToFixedArray( parser, 6, temp, 3 );
320*37da2899SCharles.Forsyth 
321*37da2899SCharles.Forsyth     temp_scale = ABS( temp[3] );
322*37da2899SCharles.Forsyth 
323*37da2899SCharles.Forsyth     /* Set Units per EM based on FontMatrix values.  We set the value to */
324*37da2899SCharles.Forsyth     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
325*37da2899SCharles.Forsyth     /* 1000 (in t1_tofixed, from psobjs.c).                              */
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth     root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
328*37da2899SCharles.Forsyth                                                  temp_scale ) >> 16 );
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth     /* we need to scale the values by 1.0/temp_scale */
331*37da2899SCharles.Forsyth     if ( temp_scale != 0x10000L ) {
332*37da2899SCharles.Forsyth       temp[0] = FT_DivFix( temp[0], temp_scale );
333*37da2899SCharles.Forsyth       temp[1] = FT_DivFix( temp[1], temp_scale );
334*37da2899SCharles.Forsyth       temp[2] = FT_DivFix( temp[2], temp_scale );
335*37da2899SCharles.Forsyth       temp[4] = FT_DivFix( temp[4], temp_scale );
336*37da2899SCharles.Forsyth       temp[5] = FT_DivFix( temp[5], temp_scale );
337*37da2899SCharles.Forsyth       temp[3] = 0x10000L;
338*37da2899SCharles.Forsyth     }
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth     matrix->xx = temp[0];
341*37da2899SCharles.Forsyth     matrix->yx = temp[1];
342*37da2899SCharles.Forsyth     matrix->xy = temp[2];
343*37da2899SCharles.Forsyth     matrix->yy = temp[3];
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth     /* note that the offsets must be expressed in integer font units */
346*37da2899SCharles.Forsyth     offset->x  = temp[4] >> 16;
347*37da2899SCharles.Forsyth     offset->y  = temp[5] >> 16;
348*37da2899SCharles.Forsyth   }
349*37da2899SCharles.Forsyth 
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth   static void
t42_parse_encoding(T42_Face face,T42_Loader loader)352*37da2899SCharles.Forsyth   t42_parse_encoding( T42_Face    face,
353*37da2899SCharles.Forsyth                       T42_Loader  loader )
354*37da2899SCharles.Forsyth   {
355*37da2899SCharles.Forsyth     T42_Parser     parser = &loader->parser;
356*37da2899SCharles.Forsyth     FT_Byte*       cur    = parser->root.cursor;
357*37da2899SCharles.Forsyth     FT_Byte*       limit  = parser->root.limit;
358*37da2899SCharles.Forsyth 
359*37da2899SCharles.Forsyth     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth     /* skip whitespace */
363*37da2899SCharles.Forsyth     while ( t42_is_space( *cur ) )
364*37da2899SCharles.Forsyth     {
365*37da2899SCharles.Forsyth       cur++;
366*37da2899SCharles.Forsyth       if ( cur >= limit )
367*37da2899SCharles.Forsyth       {
368*37da2899SCharles.Forsyth         FT_ERROR(( "t42_parse_encoding: out of bounds!\n" ));
369*37da2899SCharles.Forsyth         parser->root.error = T42_Err_Invalid_File_Format;
370*37da2899SCharles.Forsyth         return;
371*37da2899SCharles.Forsyth       }
372*37da2899SCharles.Forsyth     }
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth     /* if we have a number, then the encoding is an array, */
375*37da2899SCharles.Forsyth     /* and we must load it now                             */
376*37da2899SCharles.Forsyth     if ( (FT_Byte)( *cur - '0' ) < 10 )
377*37da2899SCharles.Forsyth     {
378*37da2899SCharles.Forsyth       T1_Encoding  encode     = &face->type1.encoding;
379*37da2899SCharles.Forsyth       FT_Int       count, n;
380*37da2899SCharles.Forsyth       PS_Table     char_table = &loader->encoding_table;
381*37da2899SCharles.Forsyth       FT_Memory    memory     = parser->root.memory;
382*37da2899SCharles.Forsyth       FT_Error     error;
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth       /* read the number of entries in the encoding, should be 256 */
386*37da2899SCharles.Forsyth       count = T1_ToInt( parser );
387*37da2899SCharles.Forsyth       if ( parser->root.error )
388*37da2899SCharles.Forsyth         return;
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth       /* we use a T1_Table to store our charnames */
391*37da2899SCharles.Forsyth       loader->num_chars = encode->num_chars = count;
392*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( encode->char_index, count ) ||
393*37da2899SCharles.Forsyth            FT_NEW_ARRAY( encode->char_name,  count ) ||
394*37da2899SCharles.Forsyth            FT_SET_ERROR( psaux->ps_table_funcs->init(
395*37da2899SCharles.Forsyth                            char_table, count, memory ) ) )
396*37da2899SCharles.Forsyth       {
397*37da2899SCharles.Forsyth         parser->root.error = error;
398*37da2899SCharles.Forsyth         return;
399*37da2899SCharles.Forsyth       }
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth       /* We need to `zero' out encoding_table.elements */
402*37da2899SCharles.Forsyth       for ( n = 0; n < count; n++ )
403*37da2899SCharles.Forsyth       {
404*37da2899SCharles.Forsyth         char*  notdef = (char *)".notdef";
405*37da2899SCharles.Forsyth 
406*37da2899SCharles.Forsyth 
407*37da2899SCharles.Forsyth         T1_Add_Table( char_table, n, notdef, 8 );
408*37da2899SCharles.Forsyth       }
409*37da2899SCharles.Forsyth 
410*37da2899SCharles.Forsyth       /* Now, we will need to read a record of the form         */
411*37da2899SCharles.Forsyth       /* ... charcode /charname ... for each entry in our table */
412*37da2899SCharles.Forsyth       /*                                                        */
413*37da2899SCharles.Forsyth       /* We simply look for a number followed by an immediate   */
414*37da2899SCharles.Forsyth       /* name.  Note that this ignores correctly the sequence   */
415*37da2899SCharles.Forsyth       /* that is often seen in type1 fonts:                     */
416*37da2899SCharles.Forsyth       /*                                                        */
417*37da2899SCharles.Forsyth       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
418*37da2899SCharles.Forsyth       /*                                                        */
419*37da2899SCharles.Forsyth       /* used to clean the encoding array before anything else. */
420*37da2899SCharles.Forsyth       /*                                                        */
421*37da2899SCharles.Forsyth       /* We stop when we encounter a `def'.                     */
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth       cur   = parser->root.cursor;
424*37da2899SCharles.Forsyth       limit = parser->root.limit;
425*37da2899SCharles.Forsyth       n     = 0;
426*37da2899SCharles.Forsyth 
427*37da2899SCharles.Forsyth       for ( ; cur < limit; )
428*37da2899SCharles.Forsyth       {
429*37da2899SCharles.Forsyth         FT_Byte  c;
430*37da2899SCharles.Forsyth 
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth         c = *cur;
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth         /* we stop when we encounter a `def' */
435*37da2899SCharles.Forsyth         if ( c == 'd' && cur + 3 < limit )
436*37da2899SCharles.Forsyth         {
437*37da2899SCharles.Forsyth           if ( cur[1] == 'e'       &&
438*37da2899SCharles.Forsyth                cur[2] == 'f'       &&
439*37da2899SCharles.Forsyth                t42_is_space( cur[-1] ) &&
440*37da2899SCharles.Forsyth                t42_is_space( cur[3] )  )
441*37da2899SCharles.Forsyth           {
442*37da2899SCharles.Forsyth             FT_TRACE6(( "encoding end\n" ));
443*37da2899SCharles.Forsyth             break;
444*37da2899SCharles.Forsyth           }
445*37da2899SCharles.Forsyth         }
446*37da2899SCharles.Forsyth 
447*37da2899SCharles.Forsyth         /* otherwise, we must find a number before anything else */
448*37da2899SCharles.Forsyth         if ( (FT_Byte)( c - '0' ) < 10 )
449*37da2899SCharles.Forsyth         {
450*37da2899SCharles.Forsyth           FT_Int  charcode;
451*37da2899SCharles.Forsyth 
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth           parser->root.cursor = cur;
454*37da2899SCharles.Forsyth           charcode = T1_ToInt( parser );
455*37da2899SCharles.Forsyth           cur      = parser->root.cursor;
456*37da2899SCharles.Forsyth 
457*37da2899SCharles.Forsyth           /* skip whitespace */
458*37da2899SCharles.Forsyth           while ( cur < limit && t42_is_space( *cur ) )
459*37da2899SCharles.Forsyth             cur++;
460*37da2899SCharles.Forsyth 
461*37da2899SCharles.Forsyth           if ( cur < limit && *cur == '/' )
462*37da2899SCharles.Forsyth           {
463*37da2899SCharles.Forsyth             /* bingo, we have an immediate name -- it must be a */
464*37da2899SCharles.Forsyth             /* character name                                   */
465*37da2899SCharles.Forsyth             FT_Byte*  cur2 = cur + 1;
466*37da2899SCharles.Forsyth             FT_Int    len;
467*37da2899SCharles.Forsyth 
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth             while ( cur2 < limit && t42_is_alpha( *cur2 ) )
470*37da2899SCharles.Forsyth               cur2++;
471*37da2899SCharles.Forsyth 
472*37da2899SCharles.Forsyth             len = (FT_Int)( cur2 - cur - 1 );
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth             parser->root.error = T1_Add_Table( char_table, charcode,
475*37da2899SCharles.Forsyth                                                cur + 1, len + 1 );
476*37da2899SCharles.Forsyth             char_table->elements[charcode][len] = '\0';
477*37da2899SCharles.Forsyth             if ( parser->root.error )
478*37da2899SCharles.Forsyth               return;
479*37da2899SCharles.Forsyth 
480*37da2899SCharles.Forsyth             cur = cur2;
481*37da2899SCharles.Forsyth           }
482*37da2899SCharles.Forsyth         }
483*37da2899SCharles.Forsyth         else
484*37da2899SCharles.Forsyth           cur++;
485*37da2899SCharles.Forsyth       }
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth       face->type1.encoding_type  = T1_ENCODING_TYPE_ARRAY;
488*37da2899SCharles.Forsyth       parser->root.cursor        = cur;
489*37da2899SCharles.Forsyth     }
490*37da2899SCharles.Forsyth     /* Otherwise, we should have either `StandardEncoding', */
491*37da2899SCharles.Forsyth     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
492*37da2899SCharles.Forsyth     else
493*37da2899SCharles.Forsyth     {
494*37da2899SCharles.Forsyth       if ( cur + 17 < limit                                            &&
495*37da2899SCharles.Forsyth            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
496*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
497*37da2899SCharles.Forsyth 
498*37da2899SCharles.Forsyth       else if ( cur + 15 < limit                                          &&
499*37da2899SCharles.Forsyth                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
500*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth       else if ( cur + 18 < limit                                             &&
503*37da2899SCharles.Forsyth                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
504*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
505*37da2899SCharles.Forsyth 
506*37da2899SCharles.Forsyth       else {
507*37da2899SCharles.Forsyth         FT_ERROR(( "t42_parse_encoding: invalid token!\n" ));
508*37da2899SCharles.Forsyth         parser->root.error = T42_Err_Invalid_File_Format;
509*37da2899SCharles.Forsyth       }
510*37da2899SCharles.Forsyth     }
511*37da2899SCharles.Forsyth   }
512*37da2899SCharles.Forsyth 
513*37da2899SCharles.Forsyth 
514*37da2899SCharles.Forsyth   static FT_UInt
t42_hexval(FT_Byte v)515*37da2899SCharles.Forsyth   t42_hexval( FT_Byte  v )
516*37da2899SCharles.Forsyth   {
517*37da2899SCharles.Forsyth     FT_UInt  d;
518*37da2899SCharles.Forsyth 
519*37da2899SCharles.Forsyth     d = (FT_UInt)( v - 'A' );
520*37da2899SCharles.Forsyth     if ( d < 6 )
521*37da2899SCharles.Forsyth     {
522*37da2899SCharles.Forsyth       d += 10;
523*37da2899SCharles.Forsyth       goto Exit;
524*37da2899SCharles.Forsyth     }
525*37da2899SCharles.Forsyth 
526*37da2899SCharles.Forsyth     d = (FT_UInt)( v - 'a' );
527*37da2899SCharles.Forsyth     if ( d < 6 )
528*37da2899SCharles.Forsyth     {
529*37da2899SCharles.Forsyth       d += 10;
530*37da2899SCharles.Forsyth       goto Exit;
531*37da2899SCharles.Forsyth     }
532*37da2899SCharles.Forsyth 
533*37da2899SCharles.Forsyth     d = (FT_UInt)( v - '0' );
534*37da2899SCharles.Forsyth     if ( d < 10 )
535*37da2899SCharles.Forsyth       goto Exit;
536*37da2899SCharles.Forsyth 
537*37da2899SCharles.Forsyth     d = 0;
538*37da2899SCharles.Forsyth 
539*37da2899SCharles.Forsyth   Exit:
540*37da2899SCharles.Forsyth     return d;
541*37da2899SCharles.Forsyth   }
542*37da2899SCharles.Forsyth 
543*37da2899SCharles.Forsyth 
544*37da2899SCharles.Forsyth   static void
t42_parse_sfnts(T42_Face face,T42_Loader loader)545*37da2899SCharles.Forsyth   t42_parse_sfnts( T42_Face    face,
546*37da2899SCharles.Forsyth                    T42_Loader  loader )
547*37da2899SCharles.Forsyth   {
548*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
549*37da2899SCharles.Forsyth     FT_Memory   memory = parser->root.memory;
550*37da2899SCharles.Forsyth     FT_Byte*    cur    = parser->root.cursor;
551*37da2899SCharles.Forsyth     FT_Byte*    limit  = parser->root.limit;
552*37da2899SCharles.Forsyth     FT_Error    error;
553*37da2899SCharles.Forsyth     FT_Int      num_tables = 0, status;
554*37da2899SCharles.Forsyth     FT_ULong    count, ttf_size = 0, string_size = 0;
555*37da2899SCharles.Forsyth     FT_Bool     in_string  = 0;
556*37da2899SCharles.Forsyth     FT_Byte     v = 0;
557*37da2899SCharles.Forsyth 
558*37da2899SCharles.Forsyth 
559*37da2899SCharles.Forsyth     /* The format is `/sfnts [ <...> <...> ... ] def' */
560*37da2899SCharles.Forsyth 
561*37da2899SCharles.Forsyth     while ( t42_is_space( *cur ) )
562*37da2899SCharles.Forsyth       cur++;
563*37da2899SCharles.Forsyth 
564*37da2899SCharles.Forsyth     if (*cur++ == '[')
565*37da2899SCharles.Forsyth     {
566*37da2899SCharles.Forsyth       status = 0;
567*37da2899SCharles.Forsyth       count = 0;
568*37da2899SCharles.Forsyth     }
569*37da2899SCharles.Forsyth     else
570*37da2899SCharles.Forsyth     {
571*37da2899SCharles.Forsyth       FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" ));
572*37da2899SCharles.Forsyth       error = T42_Err_Invalid_File_Format;
573*37da2899SCharles.Forsyth       goto Fail;
574*37da2899SCharles.Forsyth     }
575*37da2899SCharles.Forsyth 
576*37da2899SCharles.Forsyth     while ( cur < limit - 2 )
577*37da2899SCharles.Forsyth     {
578*37da2899SCharles.Forsyth       while ( t42_is_space( *cur ) )
579*37da2899SCharles.Forsyth         cur++;
580*37da2899SCharles.Forsyth 
581*37da2899SCharles.Forsyth       switch ( *cur )
582*37da2899SCharles.Forsyth       {
583*37da2899SCharles.Forsyth       case ']':
584*37da2899SCharles.Forsyth         parser->root.cursor = cur++;
585*37da2899SCharles.Forsyth         return;
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth       case '<':
588*37da2899SCharles.Forsyth         in_string   = 1;
589*37da2899SCharles.Forsyth         string_size = 0;
590*37da2899SCharles.Forsyth         cur++;
591*37da2899SCharles.Forsyth         continue;
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth       case '>':
594*37da2899SCharles.Forsyth         if ( !in_string )
595*37da2899SCharles.Forsyth         {
596*37da2899SCharles.Forsyth           FT_ERROR(( "t42_parse_sfnts: found unpaired `>'!\n" ));
597*37da2899SCharles.Forsyth           error = T42_Err_Invalid_File_Format;
598*37da2899SCharles.Forsyth           goto Fail;
599*37da2899SCharles.Forsyth         }
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth         /* A string can have, as a last byte,         */
602*37da2899SCharles.Forsyth         /* a zero byte for padding.  If so, ignore it */
603*37da2899SCharles.Forsyth         if ( ( v == 0 ) && ( string_size % 2 == 1 ) )
604*37da2899SCharles.Forsyth           count--;
605*37da2899SCharles.Forsyth         in_string = 0;
606*37da2899SCharles.Forsyth         cur++;
607*37da2899SCharles.Forsyth         continue;
608*37da2899SCharles.Forsyth 
609*37da2899SCharles.Forsyth       case '%':
610*37da2899SCharles.Forsyth         if ( !in_string )
611*37da2899SCharles.Forsyth         {
612*37da2899SCharles.Forsyth           /* Comment found; skip till end of line */
613*37da2899SCharles.Forsyth           while ( *cur != '\n' )
614*37da2899SCharles.Forsyth             cur++;
615*37da2899SCharles.Forsyth           continue;
616*37da2899SCharles.Forsyth         }
617*37da2899SCharles.Forsyth         else
618*37da2899SCharles.Forsyth         {
619*37da2899SCharles.Forsyth           FT_ERROR(( "t42_parse_sfnts: found `%' in string!\n" ));
620*37da2899SCharles.Forsyth           error = T42_Err_Invalid_File_Format;
621*37da2899SCharles.Forsyth           goto Fail;
622*37da2899SCharles.Forsyth         }
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth       default:
625*37da2899SCharles.Forsyth         if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) )
626*37da2899SCharles.Forsyth         {
627*37da2899SCharles.Forsyth           FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" ));
628*37da2899SCharles.Forsyth           error = T42_Err_Invalid_File_Format;
629*37da2899SCharles.Forsyth           goto Fail;
630*37da2899SCharles.Forsyth         }
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth         v = (FT_Byte)( 16 * t42_hexval( cur[0] ) + t42_hexval( cur[1] ) );
633*37da2899SCharles.Forsyth         cur += 2;
634*37da2899SCharles.Forsyth         string_size++;
635*37da2899SCharles.Forsyth       }
636*37da2899SCharles.Forsyth 
637*37da2899SCharles.Forsyth       switch ( status )
638*37da2899SCharles.Forsyth       {
639*37da2899SCharles.Forsyth       case 0: /* The '[' was read, so load offset table, 12 bytes */
640*37da2899SCharles.Forsyth         if ( count < 12 )
641*37da2899SCharles.Forsyth         {
642*37da2899SCharles.Forsyth           face->ttf_data[count++] = v;
643*37da2899SCharles.Forsyth           continue;
644*37da2899SCharles.Forsyth         }
645*37da2899SCharles.Forsyth         else
646*37da2899SCharles.Forsyth         {
647*37da2899SCharles.Forsyth           num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
648*37da2899SCharles.Forsyth           status     = 1;
649*37da2899SCharles.Forsyth           ttf_size   = 12 + 16 * num_tables;
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth           if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
652*37da2899SCharles.Forsyth             goto Fail;
653*37da2899SCharles.Forsyth         }
654*37da2899SCharles.Forsyth         /* No break, fall-through */
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth       case 1: /* The offset table is read; read now the table directory */
657*37da2899SCharles.Forsyth         if ( count < ttf_size )
658*37da2899SCharles.Forsyth         {
659*37da2899SCharles.Forsyth           face->ttf_data[count++] = v;
660*37da2899SCharles.Forsyth           continue;
661*37da2899SCharles.Forsyth         }
662*37da2899SCharles.Forsyth         else
663*37da2899SCharles.Forsyth         {
664*37da2899SCharles.Forsyth           int      i;
665*37da2899SCharles.Forsyth           FT_ULong len;
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth 
668*37da2899SCharles.Forsyth           for ( i = 0; i < num_tables; i++ )
669*37da2899SCharles.Forsyth           {
670*37da2899SCharles.Forsyth             FT_Byte*  p = face->ttf_data + 12 + 16*i + 12;
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth             len = FT_PEEK_ULONG( p );
673*37da2899SCharles.Forsyth 
674*37da2899SCharles.Forsyth             /* Pad to a 4-byte boundary length */
675*37da2899SCharles.Forsyth             ttf_size += ( len + 3 ) & ~3;
676*37da2899SCharles.Forsyth           }
677*37da2899SCharles.Forsyth 
678*37da2899SCharles.Forsyth           status         = 2;
679*37da2899SCharles.Forsyth           face->ttf_size = ttf_size;
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth           if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
682*37da2899SCharles.Forsyth                            ttf_size + 1 ) )
683*37da2899SCharles.Forsyth             goto Fail;
684*37da2899SCharles.Forsyth         }
685*37da2899SCharles.Forsyth         /* No break, fall-through */
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth       case 2: /* We are reading normal tables; just swallow them */
688*37da2899SCharles.Forsyth         face->ttf_data[count++] = v;
689*37da2899SCharles.Forsyth 
690*37da2899SCharles.Forsyth       }
691*37da2899SCharles.Forsyth     }
692*37da2899SCharles.Forsyth 
693*37da2899SCharles.Forsyth     /* If control reaches this point, the format was not valid */
694*37da2899SCharles.Forsyth     error = T42_Err_Invalid_File_Format;
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth   Fail:
697*37da2899SCharles.Forsyth     parser->root.error = error;
698*37da2899SCharles.Forsyth   }
699*37da2899SCharles.Forsyth 
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth   static void
t42_parse_charstrings(T42_Face face,T42_Loader loader)702*37da2899SCharles.Forsyth   t42_parse_charstrings( T42_Face    face,
703*37da2899SCharles.Forsyth                          T42_Loader  loader )
704*37da2899SCharles.Forsyth   {
705*37da2899SCharles.Forsyth     T42_Parser     parser     = &loader->parser;
706*37da2899SCharles.Forsyth     PS_Table       code_table = &loader->charstrings;
707*37da2899SCharles.Forsyth     PS_Table       name_table = &loader->glyph_names;
708*37da2899SCharles.Forsyth     FT_Memory      memory     = parser->root.memory;
709*37da2899SCharles.Forsyth     FT_Error       error;
710*37da2899SCharles.Forsyth 
711*37da2899SCharles.Forsyth     PSAux_Service  psaux      = (PSAux_Service)face->psaux;
712*37da2899SCharles.Forsyth 
713*37da2899SCharles.Forsyth     FT_Byte*       cur;
714*37da2899SCharles.Forsyth     FT_Byte*       limit      = parser->root.limit;
715*37da2899SCharles.Forsyth     FT_Int         n;
716*37da2899SCharles.Forsyth 
717*37da2899SCharles.Forsyth 
718*37da2899SCharles.Forsyth     loader->num_glyphs = T1_ToInt( parser );
719*37da2899SCharles.Forsyth     if ( parser->root.error )
720*37da2899SCharles.Forsyth       return;
721*37da2899SCharles.Forsyth 
722*37da2899SCharles.Forsyth     /* initialize tables */
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( code_table,
725*37da2899SCharles.Forsyth                                          loader->num_glyphs,
726*37da2899SCharles.Forsyth                                          memory );
727*37da2899SCharles.Forsyth     if ( error )
728*37da2899SCharles.Forsyth       goto Fail;
729*37da2899SCharles.Forsyth 
730*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( name_table,
731*37da2899SCharles.Forsyth                                          loader->num_glyphs,
732*37da2899SCharles.Forsyth                                          memory );
733*37da2899SCharles.Forsyth     if ( error )
734*37da2899SCharles.Forsyth       goto Fail;
735*37da2899SCharles.Forsyth 
736*37da2899SCharles.Forsyth     n = 0;
737*37da2899SCharles.Forsyth 
738*37da2899SCharles.Forsyth     for (;;)
739*37da2899SCharles.Forsyth     {
740*37da2899SCharles.Forsyth       /* the format is simple:                    */
741*37da2899SCharles.Forsyth       /*   `/glyphname' + index + def             */
742*37da2899SCharles.Forsyth       /*                                          */
743*37da2899SCharles.Forsyth       /* note that we stop when we find an `end'  */
744*37da2899SCharles.Forsyth       /*                                          */
745*37da2899SCharles.Forsyth       T1_Skip_Spaces( parser );
746*37da2899SCharles.Forsyth 
747*37da2899SCharles.Forsyth       cur = parser->root.cursor;
748*37da2899SCharles.Forsyth       if ( cur >= limit )
749*37da2899SCharles.Forsyth         break;
750*37da2899SCharles.Forsyth 
751*37da2899SCharles.Forsyth       /* we stop when we find an `end' keyword */
752*37da2899SCharles.Forsyth       if ( *cur   == 'e'   &&
753*37da2899SCharles.Forsyth            cur + 3 < limit &&
754*37da2899SCharles.Forsyth            cur[1] == 'n'   &&
755*37da2899SCharles.Forsyth            cur[2] == 'd'   )
756*37da2899SCharles.Forsyth         break;
757*37da2899SCharles.Forsyth 
758*37da2899SCharles.Forsyth       if ( *cur != '/' )
759*37da2899SCharles.Forsyth         T1_Skip_Alpha( parser );
760*37da2899SCharles.Forsyth       else
761*37da2899SCharles.Forsyth       {
762*37da2899SCharles.Forsyth         FT_Byte*  cur2 = cur + 1;
763*37da2899SCharles.Forsyth         FT_Int    len;
764*37da2899SCharles.Forsyth 
765*37da2899SCharles.Forsyth 
766*37da2899SCharles.Forsyth         while ( cur2 < limit && t42_is_alpha( *cur2 ) )
767*37da2899SCharles.Forsyth           cur2++;
768*37da2899SCharles.Forsyth         len = (FT_Int)( cur2 - cur - 1 );
769*37da2899SCharles.Forsyth 
770*37da2899SCharles.Forsyth         error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
771*37da2899SCharles.Forsyth         if ( error )
772*37da2899SCharles.Forsyth           goto Fail;
773*37da2899SCharles.Forsyth 
774*37da2899SCharles.Forsyth         /* add a trailing zero to the name table */
775*37da2899SCharles.Forsyth         name_table->elements[n][len] = '\0';
776*37da2899SCharles.Forsyth 
777*37da2899SCharles.Forsyth         parser->root.cursor = cur2;
778*37da2899SCharles.Forsyth         T1_Skip_Spaces( parser );
779*37da2899SCharles.Forsyth 
780*37da2899SCharles.Forsyth         cur2 = cur = parser->root.cursor;
781*37da2899SCharles.Forsyth         if ( cur >= limit )
782*37da2899SCharles.Forsyth           break;
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth         while ( cur2 < limit && t42_is_alpha( *cur2 ) )
785*37da2899SCharles.Forsyth           cur2++;
786*37da2899SCharles.Forsyth         len = (FT_Int)( cur2 - cur );
787*37da2899SCharles.Forsyth 
788*37da2899SCharles.Forsyth         error = T1_Add_Table( code_table, n, cur, len + 1 );
789*37da2899SCharles.Forsyth         if ( error )
790*37da2899SCharles.Forsyth           goto Fail;
791*37da2899SCharles.Forsyth 
792*37da2899SCharles.Forsyth         code_table->elements[n][len] = '\0';
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth         n++;
795*37da2899SCharles.Forsyth         if ( n >= loader->num_glyphs )
796*37da2899SCharles.Forsyth           break;
797*37da2899SCharles.Forsyth       }
798*37da2899SCharles.Forsyth     }
799*37da2899SCharles.Forsyth 
800*37da2899SCharles.Forsyth     /* Index 0 must be a .notdef element */
801*37da2899SCharles.Forsyth     if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) )
802*37da2899SCharles.Forsyth     {
803*37da2899SCharles.Forsyth       FT_ERROR(( "t42_parse_charstrings: Index 0 is not `.notdef'!\n" ));
804*37da2899SCharles.Forsyth       error = T42_Err_Invalid_File_Format;
805*37da2899SCharles.Forsyth       goto Fail;
806*37da2899SCharles.Forsyth     }
807*37da2899SCharles.Forsyth 
808*37da2899SCharles.Forsyth     loader->num_glyphs = n;
809*37da2899SCharles.Forsyth     return;
810*37da2899SCharles.Forsyth 
811*37da2899SCharles.Forsyth   Fail:
812*37da2899SCharles.Forsyth     parser->root.error = error;
813*37da2899SCharles.Forsyth   }
814*37da2899SCharles.Forsyth 
815*37da2899SCharles.Forsyth 
816*37da2899SCharles.Forsyth   static FT_Error
t42_load_keyword(T42_Face face,T42_Loader loader,T1_Field field)817*37da2899SCharles.Forsyth   t42_load_keyword( T42_Face    face,
818*37da2899SCharles.Forsyth                     T42_Loader  loader,
819*37da2899SCharles.Forsyth                     T1_Field    field )
820*37da2899SCharles.Forsyth   {
821*37da2899SCharles.Forsyth     FT_Error  error;
822*37da2899SCharles.Forsyth     void*     dummy_object;
823*37da2899SCharles.Forsyth     void**    objects;
824*37da2899SCharles.Forsyth     FT_UInt   max_objects = 0;
825*37da2899SCharles.Forsyth 
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth     /* if the keyword has a dedicated callback, call it */
828*37da2899SCharles.Forsyth     if ( field->type == T1_FIELD_TYPE_CALLBACK ) {
829*37da2899SCharles.Forsyth       field->reader( (FT_Face)face, loader );
830*37da2899SCharles.Forsyth       error = loader->parser.root.error;
831*37da2899SCharles.Forsyth       goto Exit;
832*37da2899SCharles.Forsyth     }
833*37da2899SCharles.Forsyth 
834*37da2899SCharles.Forsyth     /* now, the keyword is either a simple field, or a table of fields; */
835*37da2899SCharles.Forsyth     /* we are now going to take care of it                              */
836*37da2899SCharles.Forsyth     switch ( field->location )
837*37da2899SCharles.Forsyth     {
838*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_FONT_INFO:
839*37da2899SCharles.Forsyth       dummy_object = &face->type1.font_info;
840*37da2899SCharles.Forsyth       objects      = &dummy_object;
841*37da2899SCharles.Forsyth       break;
842*37da2899SCharles.Forsyth 
843*37da2899SCharles.Forsyth     default:
844*37da2899SCharles.Forsyth       dummy_object = &face->type1;
845*37da2899SCharles.Forsyth       objects      = &dummy_object;
846*37da2899SCharles.Forsyth     }
847*37da2899SCharles.Forsyth 
848*37da2899SCharles.Forsyth     if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
849*37da2899SCharles.Forsyth          field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
850*37da2899SCharles.Forsyth       error = T1_Load_Field_Table( &loader->parser, field,
851*37da2899SCharles.Forsyth                                    objects, max_objects, 0 );
852*37da2899SCharles.Forsyth     else
853*37da2899SCharles.Forsyth       error = T1_Load_Field( &loader->parser, field,
854*37da2899SCharles.Forsyth                              objects, max_objects, 0 );
855*37da2899SCharles.Forsyth 
856*37da2899SCharles.Forsyth    Exit:
857*37da2899SCharles.Forsyth     return error;
858*37da2899SCharles.Forsyth   }
859*37da2899SCharles.Forsyth 
860*37da2899SCharles.Forsyth 
861*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
t42_parse_dict(T42_Face face,T42_Loader loader,FT_Byte * base,FT_Long size)862*37da2899SCharles.Forsyth   t42_parse_dict( T42_Face    face,
863*37da2899SCharles.Forsyth                   T42_Loader  loader,
864*37da2899SCharles.Forsyth                   FT_Byte*    base,
865*37da2899SCharles.Forsyth                   FT_Long     size )
866*37da2899SCharles.Forsyth   {
867*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
868*37da2899SCharles.Forsyth     FT_Byte*    cur    = base;
869*37da2899SCharles.Forsyth     FT_Byte*    limit  = cur + size;
870*37da2899SCharles.Forsyth     FT_UInt     n_keywords = sizeof ( t42_keywords ) /
871*37da2899SCharles.Forsyth                              sizeof ( t42_keywords[0] );
872*37da2899SCharles.Forsyth 
873*37da2899SCharles.Forsyth 
874*37da2899SCharles.Forsyth     parser->root.cursor = base;
875*37da2899SCharles.Forsyth     parser->root.limit  = base + size;
876*37da2899SCharles.Forsyth     parser->root.error  = 0;
877*37da2899SCharles.Forsyth 
878*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
879*37da2899SCharles.Forsyth     {
880*37da2899SCharles.Forsyth       /* look for `FontDirectory', which causes problems on some fonts */
881*37da2899SCharles.Forsyth       if ( *cur == 'F' && cur + 25 < limit                    &&
882*37da2899SCharles.Forsyth            ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
883*37da2899SCharles.Forsyth       {
884*37da2899SCharles.Forsyth         FT_Byte*  cur2;
885*37da2899SCharles.Forsyth 
886*37da2899SCharles.Forsyth 
887*37da2899SCharles.Forsyth         /* skip the `FontDirectory' keyword */
888*37da2899SCharles.Forsyth         cur += 13;
889*37da2899SCharles.Forsyth         cur2 = cur;
890*37da2899SCharles.Forsyth 
891*37da2899SCharles.Forsyth         /* lookup the `known' keyword */
892*37da2899SCharles.Forsyth         while ( cur < limit && *cur != 'k'           &&
893*37da2899SCharles.Forsyth                 ft_strncmp( (char*)cur, "known", 5 ) )
894*37da2899SCharles.Forsyth           cur++;
895*37da2899SCharles.Forsyth 
896*37da2899SCharles.Forsyth         if ( cur < limit )
897*37da2899SCharles.Forsyth         {
898*37da2899SCharles.Forsyth           T1_TokenRec  token;
899*37da2899SCharles.Forsyth 
900*37da2899SCharles.Forsyth 
901*37da2899SCharles.Forsyth           /* skip the `known' keyword and the token following it */
902*37da2899SCharles.Forsyth           cur += 5;
903*37da2899SCharles.Forsyth           loader->parser.root.cursor = cur;
904*37da2899SCharles.Forsyth           T1_ToToken( &loader->parser, &token );
905*37da2899SCharles.Forsyth 
906*37da2899SCharles.Forsyth           /* if the last token was an array, skip it! */
907*37da2899SCharles.Forsyth           if ( token.type == T1_TOKEN_TYPE_ARRAY )
908*37da2899SCharles.Forsyth             cur2 = parser->root.cursor;
909*37da2899SCharles.Forsyth         }
910*37da2899SCharles.Forsyth         cur = cur2;
911*37da2899SCharles.Forsyth       }
912*37da2899SCharles.Forsyth       /* look for immediates */
913*37da2899SCharles.Forsyth       else if ( *cur == '/' && cur + 2 < limit )
914*37da2899SCharles.Forsyth       {
915*37da2899SCharles.Forsyth         FT_Byte*  cur2;
916*37da2899SCharles.Forsyth         FT_UInt    i, len;
917*37da2899SCharles.Forsyth 
918*37da2899SCharles.Forsyth 
919*37da2899SCharles.Forsyth         cur++;
920*37da2899SCharles.Forsyth         cur2 = cur;
921*37da2899SCharles.Forsyth         while ( cur2 < limit && t42_is_alpha( *cur2 ) )
922*37da2899SCharles.Forsyth           cur2++;
923*37da2899SCharles.Forsyth 
924*37da2899SCharles.Forsyth         len  = (FT_UInt)( cur2 - cur );
925*37da2899SCharles.Forsyth         if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */
926*37da2899SCharles.Forsyth         {
927*37da2899SCharles.Forsyth           /* now, compare the immediate name to the keyword table */
928*37da2899SCharles.Forsyth 
929*37da2899SCharles.Forsyth           /* Loop through all known keywords */
930*37da2899SCharles.Forsyth           for ( i = 0; i < n_keywords; i++ )
931*37da2899SCharles.Forsyth           {
932*37da2899SCharles.Forsyth             T1_Field  keyword = (T1_Field)&t42_keywords[i];
933*37da2899SCharles.Forsyth             FT_Byte   *name   = (FT_Byte*)keyword->ident;
934*37da2899SCharles.Forsyth 
935*37da2899SCharles.Forsyth 
936*37da2899SCharles.Forsyth             if ( !name )
937*37da2899SCharles.Forsyth               continue;
938*37da2899SCharles.Forsyth 
939*37da2899SCharles.Forsyth             if ( ( len == ft_strlen( (const char *)name ) ) &&
940*37da2899SCharles.Forsyth                  ( ft_memcmp( cur, name, len ) == 0 )       )
941*37da2899SCharles.Forsyth             {
942*37da2899SCharles.Forsyth               /* we found it -- run the parsing callback! */
943*37da2899SCharles.Forsyth               parser->root.cursor = cur2;
944*37da2899SCharles.Forsyth               T1_Skip_Spaces( parser );
945*37da2899SCharles.Forsyth               parser->root.error = t42_load_keyword(face,
946*37da2899SCharles.Forsyth                                                     loader,
947*37da2899SCharles.Forsyth                                                     keyword );
948*37da2899SCharles.Forsyth               if ( parser->root.error )
949*37da2899SCharles.Forsyth                 return parser->root.error;
950*37da2899SCharles.Forsyth               cur = parser->root.cursor;
951*37da2899SCharles.Forsyth               break;
952*37da2899SCharles.Forsyth             }
953*37da2899SCharles.Forsyth           }
954*37da2899SCharles.Forsyth         }
955*37da2899SCharles.Forsyth       }
956*37da2899SCharles.Forsyth     }
957*37da2899SCharles.Forsyth     return parser->root.error;
958*37da2899SCharles.Forsyth   }
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
t42_loader_init(T42_Loader loader,T42_Face face)962*37da2899SCharles.Forsyth   t42_loader_init( T42_Loader  loader,
963*37da2899SCharles.Forsyth                    T42_Face    face )
964*37da2899SCharles.Forsyth   {
965*37da2899SCharles.Forsyth     FT_UNUSED( face );
966*37da2899SCharles.Forsyth 
967*37da2899SCharles.Forsyth     FT_MEM_ZERO( loader, sizeof ( *loader ) );
968*37da2899SCharles.Forsyth     loader->num_glyphs = 0;
969*37da2899SCharles.Forsyth     loader->num_chars  = 0;
970*37da2899SCharles.Forsyth 
971*37da2899SCharles.Forsyth     /* initialize the tables -- simply set their `init' field to 0 */
972*37da2899SCharles.Forsyth     loader->encoding_table.init = 0;
973*37da2899SCharles.Forsyth     loader->charstrings.init    = 0;
974*37da2899SCharles.Forsyth     loader->glyph_names.init    = 0;
975*37da2899SCharles.Forsyth   }
976*37da2899SCharles.Forsyth 
977*37da2899SCharles.Forsyth 
978*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
t42_loader_done(T42_Loader loader)979*37da2899SCharles.Forsyth   t42_loader_done( T42_Loader  loader )
980*37da2899SCharles.Forsyth   {
981*37da2899SCharles.Forsyth     T42_Parser  parser = &loader->parser;
982*37da2899SCharles.Forsyth 
983*37da2899SCharles.Forsyth 
984*37da2899SCharles.Forsyth     /* finalize tables */
985*37da2899SCharles.Forsyth     T1_Release_Table( &loader->encoding_table );
986*37da2899SCharles.Forsyth     T1_Release_Table( &loader->charstrings );
987*37da2899SCharles.Forsyth     T1_Release_Table( &loader->glyph_names );
988*37da2899SCharles.Forsyth 
989*37da2899SCharles.Forsyth     /* finalize parser */
990*37da2899SCharles.Forsyth     t42_parser_done( parser );
991*37da2899SCharles.Forsyth   }
992*37da2899SCharles.Forsyth 
993*37da2899SCharles.Forsyth 
994*37da2899SCharles.Forsyth /* END */
995