xref: /inferno-os/libfreetype/t1load.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  t1load.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    Type 1 font loader (body).                                           */
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   /*************************************************************************/
20*37da2899SCharles.Forsyth   /*                                                                       */
21*37da2899SCharles.Forsyth   /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
22*37da2899SCharles.Forsyth   /* old loader has several problems: it is slow, complex, difficult to    */
23*37da2899SCharles.Forsyth   /* maintain, and contains incredible hacks to make it accept some        */
24*37da2899SCharles.Forsyth   /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
25*37da2899SCharles.Forsyth   /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
26*37da2899SCharles.Forsyth   /*                                                                       */
27*37da2899SCharles.Forsyth   /* This version is much simpler, much faster and also easier to read and */
28*37da2899SCharles.Forsyth   /* maintain by a great order of magnitude.  The idea behind it is to     */
29*37da2899SCharles.Forsyth   /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
30*37da2899SCharles.Forsyth   /* a Postscript-like interpreter) but rather to perform simple pattern   */
31*37da2899SCharles.Forsyth   /* matching.                                                             */
32*37da2899SCharles.Forsyth   /*                                                                       */
33*37da2899SCharles.Forsyth   /* Indeed, nearly all data definitions follow a simple pattern like      */
34*37da2899SCharles.Forsyth   /*                                                                       */
35*37da2899SCharles.Forsyth   /*  ... /Field <data> ...                                                */
36*37da2899SCharles.Forsyth   /*                                                                       */
37*37da2899SCharles.Forsyth   /* where <data> can be a number, a boolean, a string, or an array of     */
38*37da2899SCharles.Forsyth   /* numbers.  There are a few exceptions, namely the encoding, font name, */
39*37da2899SCharles.Forsyth   /* charstrings, and subrs; they are handled with a special pattern       */
40*37da2899SCharles.Forsyth   /* matching routine.                                                     */
41*37da2899SCharles.Forsyth   /*                                                                       */
42*37da2899SCharles.Forsyth   /* All other common cases are handled very simply.  The matching rules   */
43*37da2899SCharles.Forsyth   /* are defined in the file `t1tokens.h' through the use of several       */
44*37da2899SCharles.Forsyth   /* macros calls PARSE_XXX.                                               */
45*37da2899SCharles.Forsyth   /*                                                                       */
46*37da2899SCharles.Forsyth   /* This file is included twice here; the first time to generate parsing  */
47*37da2899SCharles.Forsyth   /* callback functions, the second to generate a table of keywords (with  */
48*37da2899SCharles.Forsyth   /* pointers to the associated callback).                                 */
49*37da2899SCharles.Forsyth   /*                                                                       */
50*37da2899SCharles.Forsyth   /* The function `parse_dict' simply scans *linearly* a given dictionary  */
51*37da2899SCharles.Forsyth   /* (either the top-level or private one) and calls the appropriate       */
52*37da2899SCharles.Forsyth   /* callback when it encounters an immediate keyword.                     */
53*37da2899SCharles.Forsyth   /*                                                                       */
54*37da2899SCharles.Forsyth   /* This is by far the fastest way one can find to parse and read all     */
55*37da2899SCharles.Forsyth   /* data.                                                                 */
56*37da2899SCharles.Forsyth   /*                                                                       */
57*37da2899SCharles.Forsyth   /* This led to tremendous code size reduction.  Note that later, the     */
58*37da2899SCharles.Forsyth   /* glyph loader will also be _greatly_ simplified, and the automatic     */
59*37da2899SCharles.Forsyth   /* hinter will replace the clumsy `t1hinter'.                            */
60*37da2899SCharles.Forsyth   /*                                                                       */
61*37da2899SCharles.Forsyth   /*************************************************************************/
62*37da2899SCharles.Forsyth 
63*37da2899SCharles.Forsyth 
64*37da2899SCharles.Forsyth #include <ft2build.h>
65*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
66*37da2899SCharles.Forsyth #include FT_CONFIG_CONFIG_H
67*37da2899SCharles.Forsyth #include FT_MULTIPLE_MASTERS_H
68*37da2899SCharles.Forsyth #include FT_INTERNAL_TYPE1_TYPES_H
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth #include "t1load.h"
71*37da2899SCharles.Forsyth #include "t1errors.h"
72*37da2899SCharles.Forsyth 
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth 
75*37da2899SCharles.Forsyth   /*************************************************************************/
76*37da2899SCharles.Forsyth   /*                                                                       */
77*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
78*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
79*37da2899SCharles.Forsyth   /* messages during execution.                                            */
80*37da2899SCharles.Forsyth   /*                                                                       */
81*37da2899SCharles.Forsyth #undef  FT_COMPONENT
82*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_t1load
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth 
85*37da2899SCharles.Forsyth #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth 
88*37da2899SCharles.Forsyth   /*************************************************************************/
89*37da2899SCharles.Forsyth   /*************************************************************************/
90*37da2899SCharles.Forsyth   /*****                                                               *****/
91*37da2899SCharles.Forsyth   /*****                    MULTIPLE MASTERS SUPPORT                   *****/
92*37da2899SCharles.Forsyth   /*****                                                               *****/
93*37da2899SCharles.Forsyth   /*************************************************************************/
94*37da2899SCharles.Forsyth   /*************************************************************************/
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth   static FT_Error
t1_allocate_blend(T1_Face face,FT_UInt num_designs,FT_UInt num_axis)97*37da2899SCharles.Forsyth   t1_allocate_blend( T1_Face  face,
98*37da2899SCharles.Forsyth                      FT_UInt  num_designs,
99*37da2899SCharles.Forsyth                      FT_UInt  num_axis )
100*37da2899SCharles.Forsyth   {
101*37da2899SCharles.Forsyth     PS_Blend   blend;
102*37da2899SCharles.Forsyth     FT_Memory  memory = face->root.memory;
103*37da2899SCharles.Forsyth     FT_Error   error  = 0;
104*37da2899SCharles.Forsyth 
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth     blend = face->blend;
107*37da2899SCharles.Forsyth     if ( !blend )
108*37da2899SCharles.Forsyth     {
109*37da2899SCharles.Forsyth       if ( FT_NEW( blend ) )
110*37da2899SCharles.Forsyth         goto Exit;
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth       face->blend = blend;
113*37da2899SCharles.Forsyth     }
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth     /* allocate design data if needed */
116*37da2899SCharles.Forsyth     if ( num_designs > 0 )
117*37da2899SCharles.Forsyth     {
118*37da2899SCharles.Forsyth       if ( blend->num_designs == 0 )
119*37da2899SCharles.Forsyth       {
120*37da2899SCharles.Forsyth         FT_UInt  nn;
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth         /* allocate the blend `private' and `font_info' dictionaries */
124*37da2899SCharles.Forsyth         if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs     ) ||
125*37da2899SCharles.Forsyth              FT_NEW_ARRAY( blend->privates[1], num_designs       ) ||
126*37da2899SCharles.Forsyth              FT_NEW_ARRAY( blend->bboxes[1], num_designs         ) ||
127*37da2899SCharles.Forsyth              FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
128*37da2899SCharles.Forsyth           goto Exit;
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth         blend->default_weight_vector = blend->weight_vector + num_designs;
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth         blend->font_infos[0] = &face->type1.font_info;
133*37da2899SCharles.Forsyth         blend->privates  [0] = &face->type1.private_dict;
134*37da2899SCharles.Forsyth         blend->bboxes    [0] = &face->type1.font_bbox;
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth         for ( nn = 2; nn <= num_designs; nn++ )
137*37da2899SCharles.Forsyth         {
138*37da2899SCharles.Forsyth           blend->privates[nn]   = blend->privates  [nn - 1] + 1;
139*37da2899SCharles.Forsyth           blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
140*37da2899SCharles.Forsyth           blend->bboxes[nn]     = blend->bboxes    [nn - 1] + 1;
141*37da2899SCharles.Forsyth         }
142*37da2899SCharles.Forsyth 
143*37da2899SCharles.Forsyth         blend->num_designs   = num_designs;
144*37da2899SCharles.Forsyth       }
145*37da2899SCharles.Forsyth       else if ( blend->num_designs != num_designs )
146*37da2899SCharles.Forsyth         goto Fail;
147*37da2899SCharles.Forsyth     }
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth     /* allocate axis data if needed */
150*37da2899SCharles.Forsyth     if ( num_axis > 0 )
151*37da2899SCharles.Forsyth     {
152*37da2899SCharles.Forsyth       if ( blend->num_axis != 0 && blend->num_axis != num_axis )
153*37da2899SCharles.Forsyth         goto Fail;
154*37da2899SCharles.Forsyth 
155*37da2899SCharles.Forsyth       blend->num_axis = num_axis;
156*37da2899SCharles.Forsyth     }
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth     /* allocate the blend design pos table if needed */
159*37da2899SCharles.Forsyth     num_designs = blend->num_designs;
160*37da2899SCharles.Forsyth     num_axis    = blend->num_axis;
161*37da2899SCharles.Forsyth     if ( num_designs && num_axis && blend->design_pos[0] == 0 )
162*37da2899SCharles.Forsyth     {
163*37da2899SCharles.Forsyth       FT_UInt  n;
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
167*37da2899SCharles.Forsyth         goto Exit;
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth       for ( n = 1; n < num_designs; n++ )
170*37da2899SCharles.Forsyth         blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
171*37da2899SCharles.Forsyth     }
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth   Exit:
174*37da2899SCharles.Forsyth     return error;
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth   Fail:
177*37da2899SCharles.Forsyth     error = -1;
178*37da2899SCharles.Forsyth     goto Exit;
179*37da2899SCharles.Forsyth   }
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
T1_Get_Multi_Master(T1_Face face,FT_Multi_Master * master)183*37da2899SCharles.Forsyth   T1_Get_Multi_Master( T1_Face           face,
184*37da2899SCharles.Forsyth                        FT_Multi_Master*  master )
185*37da2899SCharles.Forsyth   {
186*37da2899SCharles.Forsyth     PS_Blend  blend = face->blend;
187*37da2899SCharles.Forsyth     FT_UInt   n;
188*37da2899SCharles.Forsyth     FT_Error  error;
189*37da2899SCharles.Forsyth 
190*37da2899SCharles.Forsyth 
191*37da2899SCharles.Forsyth     error = T1_Err_Invalid_Argument;
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth     if ( blend )
194*37da2899SCharles.Forsyth     {
195*37da2899SCharles.Forsyth       master->num_axis    = blend->num_axis;
196*37da2899SCharles.Forsyth       master->num_designs = blend->num_designs;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth       for ( n = 0; n < blend->num_axis; n++ )
199*37da2899SCharles.Forsyth       {
200*37da2899SCharles.Forsyth         FT_MM_Axis*   axis = master->axis + n;
201*37da2899SCharles.Forsyth         PS_DesignMap  map = blend->design_map + n;
202*37da2899SCharles.Forsyth 
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth         axis->name    = blend->axis_names[n];
205*37da2899SCharles.Forsyth         axis->minimum = map->design_points[0];
206*37da2899SCharles.Forsyth         axis->maximum = map->design_points[map->num_points - 1];
207*37da2899SCharles.Forsyth       }
208*37da2899SCharles.Forsyth       error = 0;
209*37da2899SCharles.Forsyth     }
210*37da2899SCharles.Forsyth     return error;
211*37da2899SCharles.Forsyth   }
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth 
214*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
T1_Set_MM_Blend(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)215*37da2899SCharles.Forsyth   T1_Set_MM_Blend( T1_Face    face,
216*37da2899SCharles.Forsyth                    FT_UInt    num_coords,
217*37da2899SCharles.Forsyth                    FT_Fixed*  coords )
218*37da2899SCharles.Forsyth   {
219*37da2899SCharles.Forsyth     PS_Blend  blend = face->blend;
220*37da2899SCharles.Forsyth     FT_Error  error;
221*37da2899SCharles.Forsyth     FT_UInt   n, m;
222*37da2899SCharles.Forsyth 
223*37da2899SCharles.Forsyth 
224*37da2899SCharles.Forsyth     error = T1_Err_Invalid_Argument;
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth     if ( blend && blend->num_axis == num_coords )
227*37da2899SCharles.Forsyth     {
228*37da2899SCharles.Forsyth       /* recompute the weight vector from the blend coordinates */
229*37da2899SCharles.Forsyth       error = T1_Err_Ok;
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth       for ( n = 0; n < blend->num_designs; n++ )
232*37da2899SCharles.Forsyth       {
233*37da2899SCharles.Forsyth         FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth         for ( m = 0; m < blend->num_axis; m++ )
237*37da2899SCharles.Forsyth         {
238*37da2899SCharles.Forsyth           FT_Fixed  factor;
239*37da2899SCharles.Forsyth 
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth           /* get current blend axis position */
242*37da2899SCharles.Forsyth           factor = coords[m];
243*37da2899SCharles.Forsyth           if ( factor < 0 )        factor = 0;
244*37da2899SCharles.Forsyth           if ( factor > 0x10000L ) factor = 0x10000L;
245*37da2899SCharles.Forsyth 
246*37da2899SCharles.Forsyth           if ( ( n & ( 1 << m ) ) == 0 )
247*37da2899SCharles.Forsyth             factor = 0x10000L - factor;
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth           result = FT_MulFix( result, factor );
250*37da2899SCharles.Forsyth         }
251*37da2899SCharles.Forsyth         blend->weight_vector[n] = result;
252*37da2899SCharles.Forsyth       }
253*37da2899SCharles.Forsyth 
254*37da2899SCharles.Forsyth       error = T1_Err_Ok;
255*37da2899SCharles.Forsyth     }
256*37da2899SCharles.Forsyth     return error;
257*37da2899SCharles.Forsyth   }
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth 
260*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
T1_Set_MM_Design(T1_Face face,FT_UInt num_coords,FT_Long * coords)261*37da2899SCharles.Forsyth   T1_Set_MM_Design( T1_Face   face,
262*37da2899SCharles.Forsyth                     FT_UInt   num_coords,
263*37da2899SCharles.Forsyth                     FT_Long*  coords )
264*37da2899SCharles.Forsyth   {
265*37da2899SCharles.Forsyth     PS_Blend  blend = face->blend;
266*37da2899SCharles.Forsyth     FT_Error  error;
267*37da2899SCharles.Forsyth     FT_UInt   n, p;
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth 
270*37da2899SCharles.Forsyth     error = T1_Err_Invalid_Argument;
271*37da2899SCharles.Forsyth     if ( blend && blend->num_axis == num_coords )
272*37da2899SCharles.Forsyth     {
273*37da2899SCharles.Forsyth       /* compute the blend coordinates through the blend design map */
274*37da2899SCharles.Forsyth       FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth 
277*37da2899SCharles.Forsyth       for ( n = 0; n < blend->num_axis; n++ )
278*37da2899SCharles.Forsyth       {
279*37da2899SCharles.Forsyth         FT_Long       design  = coords[n];
280*37da2899SCharles.Forsyth         FT_Fixed      the_blend;
281*37da2899SCharles.Forsyth         PS_DesignMap  map     = blend->design_map + n;
282*37da2899SCharles.Forsyth         FT_Fixed*     designs = map->design_points;
283*37da2899SCharles.Forsyth         FT_Fixed*     blends  = map->blend_points;
284*37da2899SCharles.Forsyth         FT_Int        before  = -1, after = -1;
285*37da2899SCharles.Forsyth 
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth         for ( p = 0; p < (FT_UInt)map->num_points; p++ )
288*37da2899SCharles.Forsyth         {
289*37da2899SCharles.Forsyth           FT_Fixed  p_design = designs[p];
290*37da2899SCharles.Forsyth 
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth           /* exact match ? */
293*37da2899SCharles.Forsyth           if ( design == p_design )
294*37da2899SCharles.Forsyth           {
295*37da2899SCharles.Forsyth             the_blend = blends[p];
296*37da2899SCharles.Forsyth             goto Found;
297*37da2899SCharles.Forsyth           }
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth           if ( design < p_design )
300*37da2899SCharles.Forsyth           {
301*37da2899SCharles.Forsyth             after = p;
302*37da2899SCharles.Forsyth             break;
303*37da2899SCharles.Forsyth           }
304*37da2899SCharles.Forsyth 
305*37da2899SCharles.Forsyth           before = p;
306*37da2899SCharles.Forsyth         }
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth         /* now, interpolate if needed */
309*37da2899SCharles.Forsyth         if ( before < 0 )
310*37da2899SCharles.Forsyth           the_blend = blends[0];
311*37da2899SCharles.Forsyth 
312*37da2899SCharles.Forsyth         else if ( after < 0 )
313*37da2899SCharles.Forsyth           the_blend = blends[map->num_points - 1];
314*37da2899SCharles.Forsyth 
315*37da2899SCharles.Forsyth         else
316*37da2899SCharles.Forsyth           the_blend = FT_MulDiv( design         - designs[before],
317*37da2899SCharles.Forsyth                                  blends [after] - blends [before],
318*37da2899SCharles.Forsyth                                  designs[after] - designs[before] );
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth       Found:
321*37da2899SCharles.Forsyth         final_blends[n] = the_blend;
322*37da2899SCharles.Forsyth       }
323*37da2899SCharles.Forsyth 
324*37da2899SCharles.Forsyth       error = T1_Set_MM_Blend( face, num_coords, final_blends );
325*37da2899SCharles.Forsyth     }
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth     return error;
328*37da2899SCharles.Forsyth   }
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
T1_Done_Blend(T1_Face face)332*37da2899SCharles.Forsyth   T1_Done_Blend( T1_Face  face )
333*37da2899SCharles.Forsyth   {
334*37da2899SCharles.Forsyth     FT_Memory  memory = face->root.memory;
335*37da2899SCharles.Forsyth     PS_Blend   blend  = face->blend;
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth     if ( blend )
339*37da2899SCharles.Forsyth     {
340*37da2899SCharles.Forsyth       FT_UInt  num_designs = blend->num_designs;
341*37da2899SCharles.Forsyth       FT_UInt  num_axis    = blend->num_axis;
342*37da2899SCharles.Forsyth       FT_UInt  n;
343*37da2899SCharles.Forsyth 
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth       /* release design pos table */
346*37da2899SCharles.Forsyth       FT_FREE( blend->design_pos[0] );
347*37da2899SCharles.Forsyth       for ( n = 1; n < num_designs; n++ )
348*37da2899SCharles.Forsyth         blend->design_pos[n] = 0;
349*37da2899SCharles.Forsyth 
350*37da2899SCharles.Forsyth       /* release blend `private' and `font info' dictionaries */
351*37da2899SCharles.Forsyth       FT_FREE( blend->privates[1] );
352*37da2899SCharles.Forsyth       FT_FREE( blend->font_infos[1] );
353*37da2899SCharles.Forsyth       FT_FREE( blend->bboxes[1] );
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth       for ( n = 0; n < num_designs; n++ )
356*37da2899SCharles.Forsyth       {
357*37da2899SCharles.Forsyth         blend->privates  [n] = 0;
358*37da2899SCharles.Forsyth         blend->font_infos[n] = 0;
359*37da2899SCharles.Forsyth         blend->bboxes    [n] = 0;
360*37da2899SCharles.Forsyth       }
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth       /* release weight vectors */
363*37da2899SCharles.Forsyth       FT_FREE( blend->weight_vector );
364*37da2899SCharles.Forsyth       blend->default_weight_vector = 0;
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth       /* release axis names */
367*37da2899SCharles.Forsyth       for ( n = 0; n < num_axis; n++ )
368*37da2899SCharles.Forsyth         FT_FREE( blend->axis_names[n] );
369*37da2899SCharles.Forsyth 
370*37da2899SCharles.Forsyth       /* release design map */
371*37da2899SCharles.Forsyth       for ( n = 0; n < num_axis; n++ )
372*37da2899SCharles.Forsyth       {
373*37da2899SCharles.Forsyth         PS_DesignMap  dmap = blend->design_map + n;
374*37da2899SCharles.Forsyth 
375*37da2899SCharles.Forsyth 
376*37da2899SCharles.Forsyth         FT_FREE( dmap->design_points );
377*37da2899SCharles.Forsyth         dmap->num_points = 0;
378*37da2899SCharles.Forsyth       }
379*37da2899SCharles.Forsyth 
380*37da2899SCharles.Forsyth       FT_FREE( face->blend );
381*37da2899SCharles.Forsyth     }
382*37da2899SCharles.Forsyth   }
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth   static void
parse_blend_axis_types(T1_Face face,T1_Loader loader)386*37da2899SCharles.Forsyth   parse_blend_axis_types( T1_Face    face,
387*37da2899SCharles.Forsyth                           T1_Loader  loader )
388*37da2899SCharles.Forsyth   {
389*37da2899SCharles.Forsyth     T1_TokenRec  axis_tokens[ T1_MAX_MM_AXIS ];
390*37da2899SCharles.Forsyth     FT_Int       n, num_axis;
391*37da2899SCharles.Forsyth     FT_Error     error = 0;
392*37da2899SCharles.Forsyth     PS_Blend     blend;
393*37da2899SCharles.Forsyth     FT_Memory    memory;
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth     /* take an array of objects */
397*37da2899SCharles.Forsyth     T1_ToTokenArray( &loader->parser, axis_tokens,
398*37da2899SCharles.Forsyth                      T1_MAX_MM_AXIS, &num_axis );
399*37da2899SCharles.Forsyth     if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
400*37da2899SCharles.Forsyth     {
401*37da2899SCharles.Forsyth       FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
402*37da2899SCharles.Forsyth                  num_axis ));
403*37da2899SCharles.Forsyth       error = T1_Err_Invalid_File_Format;
404*37da2899SCharles.Forsyth       goto Exit;
405*37da2899SCharles.Forsyth     }
406*37da2899SCharles.Forsyth 
407*37da2899SCharles.Forsyth     /* allocate blend if necessary */
408*37da2899SCharles.Forsyth     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
409*37da2899SCharles.Forsyth     if ( error )
410*37da2899SCharles.Forsyth       goto Exit;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth     blend  = face->blend;
413*37da2899SCharles.Forsyth     memory = face->root.memory;
414*37da2899SCharles.Forsyth 
415*37da2899SCharles.Forsyth     /* each token is an immediate containing the name of the axis */
416*37da2899SCharles.Forsyth     for ( n = 0; n < num_axis; n++ )
417*37da2899SCharles.Forsyth     {
418*37da2899SCharles.Forsyth       T1_Token    token = axis_tokens + n;
419*37da2899SCharles.Forsyth       FT_Byte*    name;
420*37da2899SCharles.Forsyth       FT_PtrDist  len;
421*37da2899SCharles.Forsyth 
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth       /* skip first slash, if any */
424*37da2899SCharles.Forsyth       if ( token->start[0] == '/' )
425*37da2899SCharles.Forsyth         token->start++;
426*37da2899SCharles.Forsyth 
427*37da2899SCharles.Forsyth       len = token->limit - token->start;
428*37da2899SCharles.Forsyth       if ( len <= 0 )
429*37da2899SCharles.Forsyth       {
430*37da2899SCharles.Forsyth         error = T1_Err_Invalid_File_Format;
431*37da2899SCharles.Forsyth         goto Exit;
432*37da2899SCharles.Forsyth       }
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth       if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
435*37da2899SCharles.Forsyth         goto Exit;
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth       name = (FT_Byte*)blend->axis_names[n];
438*37da2899SCharles.Forsyth       FT_MEM_COPY( name, token->start, len );
439*37da2899SCharles.Forsyth       name[len] = 0;
440*37da2899SCharles.Forsyth     }
441*37da2899SCharles.Forsyth 
442*37da2899SCharles.Forsyth   Exit:
443*37da2899SCharles.Forsyth     loader->parser.root.error = error;
444*37da2899SCharles.Forsyth   }
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth 
447*37da2899SCharles.Forsyth   static void
parse_blend_design_positions(T1_Face face,T1_Loader loader)448*37da2899SCharles.Forsyth   parse_blend_design_positions( T1_Face    face,
449*37da2899SCharles.Forsyth                                 T1_Loader  loader )
450*37da2899SCharles.Forsyth   {
451*37da2899SCharles.Forsyth     T1_TokenRec  design_tokens[ T1_MAX_MM_DESIGNS ];
452*37da2899SCharles.Forsyth     FT_Int       num_designs;
453*37da2899SCharles.Forsyth     FT_Int       num_axis;
454*37da2899SCharles.Forsyth     T1_Parser    parser = &loader->parser;
455*37da2899SCharles.Forsyth 
456*37da2899SCharles.Forsyth     FT_Error     error = 0;
457*37da2899SCharles.Forsyth     PS_Blend     blend;
458*37da2899SCharles.Forsyth 
459*37da2899SCharles.Forsyth 
460*37da2899SCharles.Forsyth     /* get the array of design tokens - compute number of designs */
461*37da2899SCharles.Forsyth     T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs );
462*37da2899SCharles.Forsyth     if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS )
463*37da2899SCharles.Forsyth     {
464*37da2899SCharles.Forsyth       FT_ERROR(( "parse_blend_design_positions:" ));
465*37da2899SCharles.Forsyth       FT_ERROR(( " incorrect number of designs: %d\n",
466*37da2899SCharles.Forsyth                  num_designs ));
467*37da2899SCharles.Forsyth       error = T1_Err_Invalid_File_Format;
468*37da2899SCharles.Forsyth       goto Exit;
469*37da2899SCharles.Forsyth     }
470*37da2899SCharles.Forsyth 
471*37da2899SCharles.Forsyth     {
472*37da2899SCharles.Forsyth       FT_Byte*  old_cursor = parser->root.cursor;
473*37da2899SCharles.Forsyth       FT_Byte*  old_limit  = parser->root.limit;
474*37da2899SCharles.Forsyth       FT_UInt   n;
475*37da2899SCharles.Forsyth 
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth       blend    = face->blend;
478*37da2899SCharles.Forsyth       num_axis = 0;  /* make compiler happy */
479*37da2899SCharles.Forsyth 
480*37da2899SCharles.Forsyth       for ( n = 0; n < (FT_UInt)num_designs; n++ )
481*37da2899SCharles.Forsyth       {
482*37da2899SCharles.Forsyth         T1_TokenRec  axis_tokens[ T1_MAX_MM_DESIGNS ];
483*37da2899SCharles.Forsyth         T1_Token     token;
484*37da2899SCharles.Forsyth         FT_Int       axis, n_axis;
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth         /* read axis/coordinates tokens */
488*37da2899SCharles.Forsyth         token = design_tokens + n;
489*37da2899SCharles.Forsyth         parser->root.cursor = token->start - 1;
490*37da2899SCharles.Forsyth         parser->root.limit  = token->limit + 1;
491*37da2899SCharles.Forsyth         T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
492*37da2899SCharles.Forsyth 
493*37da2899SCharles.Forsyth         if ( n == 0 )
494*37da2899SCharles.Forsyth         {
495*37da2899SCharles.Forsyth           num_axis = n_axis;
496*37da2899SCharles.Forsyth           error = t1_allocate_blend( face, num_designs, num_axis );
497*37da2899SCharles.Forsyth           if ( error )
498*37da2899SCharles.Forsyth             goto Exit;
499*37da2899SCharles.Forsyth           blend = face->blend;
500*37da2899SCharles.Forsyth         }
501*37da2899SCharles.Forsyth         else if ( n_axis != num_axis )
502*37da2899SCharles.Forsyth         {
503*37da2899SCharles.Forsyth           FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
504*37da2899SCharles.Forsyth           error = T1_Err_Invalid_File_Format;
505*37da2899SCharles.Forsyth           goto Exit;
506*37da2899SCharles.Forsyth         }
507*37da2899SCharles.Forsyth 
508*37da2899SCharles.Forsyth         /* now, read each axis token into the design position */
509*37da2899SCharles.Forsyth         for ( axis = 0; axis < n_axis; axis++ )
510*37da2899SCharles.Forsyth         {
511*37da2899SCharles.Forsyth           T1_Token  token2 = axis_tokens + axis;
512*37da2899SCharles.Forsyth 
513*37da2899SCharles.Forsyth 
514*37da2899SCharles.Forsyth           parser->root.cursor = token2->start;
515*37da2899SCharles.Forsyth           parser->root.limit  = token2->limit;
516*37da2899SCharles.Forsyth           blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
517*37da2899SCharles.Forsyth         }
518*37da2899SCharles.Forsyth       }
519*37da2899SCharles.Forsyth 
520*37da2899SCharles.Forsyth       loader->parser.root.cursor = old_cursor;
521*37da2899SCharles.Forsyth       loader->parser.root.limit  = old_limit;
522*37da2899SCharles.Forsyth     }
523*37da2899SCharles.Forsyth 
524*37da2899SCharles.Forsyth   Exit:
525*37da2899SCharles.Forsyth     loader->parser.root.error = error;
526*37da2899SCharles.Forsyth   }
527*37da2899SCharles.Forsyth 
528*37da2899SCharles.Forsyth 
529*37da2899SCharles.Forsyth   static void
parse_blend_design_map(T1_Face face,T1_Loader loader)530*37da2899SCharles.Forsyth   parse_blend_design_map( T1_Face    face,
531*37da2899SCharles.Forsyth                           T1_Loader  loader )
532*37da2899SCharles.Forsyth   {
533*37da2899SCharles.Forsyth     FT_Error     error  = 0;
534*37da2899SCharles.Forsyth     T1_Parser    parser = &loader->parser;
535*37da2899SCharles.Forsyth     PS_Blend     blend;
536*37da2899SCharles.Forsyth     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
537*37da2899SCharles.Forsyth     FT_Int       n, num_axis;
538*37da2899SCharles.Forsyth     FT_Byte*     old_cursor;
539*37da2899SCharles.Forsyth     FT_Byte*     old_limit;
540*37da2899SCharles.Forsyth     FT_Memory    memory = face->root.memory;
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth 
543*37da2899SCharles.Forsyth     T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis );
544*37da2899SCharles.Forsyth     if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS )
545*37da2899SCharles.Forsyth     {
546*37da2899SCharles.Forsyth       FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
547*37da2899SCharles.Forsyth                  num_axis ));
548*37da2899SCharles.Forsyth       error = T1_Err_Invalid_File_Format;
549*37da2899SCharles.Forsyth       goto Exit;
550*37da2899SCharles.Forsyth     }
551*37da2899SCharles.Forsyth     old_cursor = parser->root.cursor;
552*37da2899SCharles.Forsyth     old_limit  = parser->root.limit;
553*37da2899SCharles.Forsyth 
554*37da2899SCharles.Forsyth     error = t1_allocate_blend( face, 0, num_axis );
555*37da2899SCharles.Forsyth     if ( error )
556*37da2899SCharles.Forsyth       goto Exit;
557*37da2899SCharles.Forsyth     blend = face->blend;
558*37da2899SCharles.Forsyth 
559*37da2899SCharles.Forsyth     /* now, read each axis design map */
560*37da2899SCharles.Forsyth     for ( n = 0; n < num_axis; n++ )
561*37da2899SCharles.Forsyth     {
562*37da2899SCharles.Forsyth       PS_DesignMap  map = blend->design_map + n;
563*37da2899SCharles.Forsyth       T1_Token      token;
564*37da2899SCharles.Forsyth       FT_Int        p, num_points;
565*37da2899SCharles.Forsyth 
566*37da2899SCharles.Forsyth 
567*37da2899SCharles.Forsyth       token = axis_tokens + n;
568*37da2899SCharles.Forsyth       parser->root.cursor = token->start;
569*37da2899SCharles.Forsyth       parser->root.limit  = token->limit;
570*37da2899SCharles.Forsyth 
571*37da2899SCharles.Forsyth       /* count the number of map points */
572*37da2899SCharles.Forsyth       {
573*37da2899SCharles.Forsyth         FT_Byte*  ptr   = token->start;
574*37da2899SCharles.Forsyth         FT_Byte*  limit = token->limit;
575*37da2899SCharles.Forsyth 
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth         num_points = 0;
578*37da2899SCharles.Forsyth         for ( ; ptr < limit; ptr++ )
579*37da2899SCharles.Forsyth           if ( ptr[0] == '[' )
580*37da2899SCharles.Forsyth             num_points++;
581*37da2899SCharles.Forsyth       }
582*37da2899SCharles.Forsyth       if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
583*37da2899SCharles.Forsyth       {
584*37da2899SCharles.Forsyth         FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
585*37da2899SCharles.Forsyth         error = T1_Err_Invalid_File_Format;
586*37da2899SCharles.Forsyth         goto Exit;
587*37da2899SCharles.Forsyth       }
588*37da2899SCharles.Forsyth 
589*37da2899SCharles.Forsyth       /* allocate design map data */
590*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
591*37da2899SCharles.Forsyth         goto Exit;
592*37da2899SCharles.Forsyth       map->blend_points = map->design_points + num_points;
593*37da2899SCharles.Forsyth       map->num_points   = (FT_Byte)num_points;
594*37da2899SCharles.Forsyth 
595*37da2899SCharles.Forsyth       for ( p = 0; p < num_points; p++ )
596*37da2899SCharles.Forsyth       {
597*37da2899SCharles.Forsyth         map->design_points[p] = T1_ToInt( parser );
598*37da2899SCharles.Forsyth         map->blend_points [p] = T1_ToFixed( parser, 0 );
599*37da2899SCharles.Forsyth       }
600*37da2899SCharles.Forsyth     }
601*37da2899SCharles.Forsyth 
602*37da2899SCharles.Forsyth     parser->root.cursor = old_cursor;
603*37da2899SCharles.Forsyth     parser->root.limit  = old_limit;
604*37da2899SCharles.Forsyth 
605*37da2899SCharles.Forsyth   Exit:
606*37da2899SCharles.Forsyth     parser->root.error = error;
607*37da2899SCharles.Forsyth   }
608*37da2899SCharles.Forsyth 
609*37da2899SCharles.Forsyth 
610*37da2899SCharles.Forsyth   static void
parse_weight_vector(T1_Face face,T1_Loader loader)611*37da2899SCharles.Forsyth   parse_weight_vector( T1_Face    face,
612*37da2899SCharles.Forsyth                        T1_Loader  loader )
613*37da2899SCharles.Forsyth   {
614*37da2899SCharles.Forsyth     FT_Error     error  = 0;
615*37da2899SCharles.Forsyth     T1_Parser    parser = &loader->parser;
616*37da2899SCharles.Forsyth     PS_Blend     blend  = face->blend;
617*37da2899SCharles.Forsyth     T1_TokenRec  master;
618*37da2899SCharles.Forsyth     FT_UInt      n;
619*37da2899SCharles.Forsyth     FT_Byte*     old_cursor;
620*37da2899SCharles.Forsyth     FT_Byte*     old_limit;
621*37da2899SCharles.Forsyth 
622*37da2899SCharles.Forsyth 
623*37da2899SCharles.Forsyth     if ( !blend || blend->num_designs == 0 )
624*37da2899SCharles.Forsyth     {
625*37da2899SCharles.Forsyth       FT_ERROR(( "parse_weight_vector: too early!\n" ));
626*37da2899SCharles.Forsyth       error = T1_Err_Invalid_File_Format;
627*37da2899SCharles.Forsyth       goto Exit;
628*37da2899SCharles.Forsyth     }
629*37da2899SCharles.Forsyth 
630*37da2899SCharles.Forsyth     T1_ToToken( parser, &master );
631*37da2899SCharles.Forsyth     if ( master.type != T1_TOKEN_TYPE_ARRAY )
632*37da2899SCharles.Forsyth     {
633*37da2899SCharles.Forsyth       FT_ERROR(( "parse_weight_vector: incorrect format!\n" ));
634*37da2899SCharles.Forsyth       error = T1_Err_Invalid_File_Format;
635*37da2899SCharles.Forsyth       goto Exit;
636*37da2899SCharles.Forsyth     }
637*37da2899SCharles.Forsyth 
638*37da2899SCharles.Forsyth     old_cursor = parser->root.cursor;
639*37da2899SCharles.Forsyth     old_limit  = parser->root.limit;
640*37da2899SCharles.Forsyth 
641*37da2899SCharles.Forsyth     parser->root.cursor = master.start;
642*37da2899SCharles.Forsyth     parser->root.limit  = master.limit;
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth     for ( n = 0; n < blend->num_designs; n++ )
645*37da2899SCharles.Forsyth     {
646*37da2899SCharles.Forsyth       blend->default_weight_vector[n] =
647*37da2899SCharles.Forsyth       blend->weight_vector[n]         = T1_ToFixed( parser, 0 );
648*37da2899SCharles.Forsyth     }
649*37da2899SCharles.Forsyth 
650*37da2899SCharles.Forsyth     parser->root.cursor = old_cursor;
651*37da2899SCharles.Forsyth     parser->root.limit  = old_limit;
652*37da2899SCharles.Forsyth 
653*37da2899SCharles.Forsyth   Exit:
654*37da2899SCharles.Forsyth     parser->root.error = error;
655*37da2899SCharles.Forsyth   }
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth 
658*37da2899SCharles.Forsyth   /* the keyword `/shareddict' appears in some multiple master fonts   */
659*37da2899SCharles.Forsyth   /* with a lot of Postscript garbage behind it (that's completely out */
660*37da2899SCharles.Forsyth   /* of spec!); we detect it and terminate the parsing                 */
661*37da2899SCharles.Forsyth   /*                                                                   */
662*37da2899SCharles.Forsyth   static void
parse_shared_dict(T1_Face face,T1_Loader loader)663*37da2899SCharles.Forsyth   parse_shared_dict( T1_Face    face,
664*37da2899SCharles.Forsyth                      T1_Loader  loader )
665*37da2899SCharles.Forsyth   {
666*37da2899SCharles.Forsyth     T1_Parser  parser = &loader->parser;
667*37da2899SCharles.Forsyth 
668*37da2899SCharles.Forsyth     FT_UNUSED( face );
669*37da2899SCharles.Forsyth 
670*37da2899SCharles.Forsyth 
671*37da2899SCharles.Forsyth     parser->root.cursor = parser->root.limit;
672*37da2899SCharles.Forsyth     parser->root.error  = 0;
673*37da2899SCharles.Forsyth   }
674*37da2899SCharles.Forsyth 
675*37da2899SCharles.Forsyth #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */
676*37da2899SCharles.Forsyth 
677*37da2899SCharles.Forsyth 
678*37da2899SCharles.Forsyth   /*************************************************************************/
679*37da2899SCharles.Forsyth   /*************************************************************************/
680*37da2899SCharles.Forsyth   /*****                                                               *****/
681*37da2899SCharles.Forsyth   /*****                      TYPE 1 SYMBOL PARSING                    *****/
682*37da2899SCharles.Forsyth   /*****                                                               *****/
683*37da2899SCharles.Forsyth   /*************************************************************************/
684*37da2899SCharles.Forsyth   /*************************************************************************/
685*37da2899SCharles.Forsyth 
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth   /*************************************************************************/
688*37da2899SCharles.Forsyth   /*                                                                       */
689*37da2899SCharles.Forsyth   /* First of all, define the token field static variables.  This is a set */
690*37da2899SCharles.Forsyth   /* of T1_FieldRec variables used later.                                  */
691*37da2899SCharles.Forsyth   /*                                                                       */
692*37da2899SCharles.Forsyth   /*************************************************************************/
693*37da2899SCharles.Forsyth 
694*37da2899SCharles.Forsyth 
695*37da2899SCharles.Forsyth   static FT_Error
t1_load_keyword(T1_Face face,T1_Loader loader,T1_Field field)696*37da2899SCharles.Forsyth   t1_load_keyword( T1_Face    face,
697*37da2899SCharles.Forsyth                    T1_Loader  loader,
698*37da2899SCharles.Forsyth                    T1_Field   field )
699*37da2899SCharles.Forsyth   {
700*37da2899SCharles.Forsyth     FT_Error  error;
701*37da2899SCharles.Forsyth     void*     dummy_object;
702*37da2899SCharles.Forsyth     void**    objects;
703*37da2899SCharles.Forsyth     FT_UInt   max_objects;
704*37da2899SCharles.Forsyth     PS_Blend  blend = face->blend;
705*37da2899SCharles.Forsyth 
706*37da2899SCharles.Forsyth 
707*37da2899SCharles.Forsyth     /* if the keyword has a dedicated callback, call it */
708*37da2899SCharles.Forsyth     if ( field->type == T1_FIELD_TYPE_CALLBACK )
709*37da2899SCharles.Forsyth     {
710*37da2899SCharles.Forsyth       field->reader( (FT_Face)face, loader );
711*37da2899SCharles.Forsyth       error = loader->parser.root.error;
712*37da2899SCharles.Forsyth       goto Exit;
713*37da2899SCharles.Forsyth     }
714*37da2899SCharles.Forsyth 
715*37da2899SCharles.Forsyth     /* now, the keyword is either a simple field, or a table of fields; */
716*37da2899SCharles.Forsyth     /* we are now going to take care of it                              */
717*37da2899SCharles.Forsyth     switch ( field->location )
718*37da2899SCharles.Forsyth     {
719*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_FONT_INFO:
720*37da2899SCharles.Forsyth       dummy_object = &face->type1.font_info;
721*37da2899SCharles.Forsyth       objects      = &dummy_object;
722*37da2899SCharles.Forsyth       max_objects  = 0;
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth       if ( blend )
725*37da2899SCharles.Forsyth       {
726*37da2899SCharles.Forsyth         objects     = (void**)blend->font_infos;
727*37da2899SCharles.Forsyth         max_objects = blend->num_designs;
728*37da2899SCharles.Forsyth       }
729*37da2899SCharles.Forsyth       break;
730*37da2899SCharles.Forsyth 
731*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_PRIVATE:
732*37da2899SCharles.Forsyth       dummy_object = &face->type1.private_dict;
733*37da2899SCharles.Forsyth       objects      = &dummy_object;
734*37da2899SCharles.Forsyth       max_objects  = 0;
735*37da2899SCharles.Forsyth 
736*37da2899SCharles.Forsyth       if ( blend )
737*37da2899SCharles.Forsyth       {
738*37da2899SCharles.Forsyth         objects     = (void**)blend->privates;
739*37da2899SCharles.Forsyth         max_objects = blend->num_designs;
740*37da2899SCharles.Forsyth       }
741*37da2899SCharles.Forsyth       break;
742*37da2899SCharles.Forsyth 
743*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_BBOX:
744*37da2899SCharles.Forsyth       dummy_object = &face->type1.font_bbox;
745*37da2899SCharles.Forsyth       objects      = &dummy_object;
746*37da2899SCharles.Forsyth       max_objects  = 0;
747*37da2899SCharles.Forsyth 
748*37da2899SCharles.Forsyth       if ( blend )
749*37da2899SCharles.Forsyth       {
750*37da2899SCharles.Forsyth         objects     = (void**)blend->bboxes;
751*37da2899SCharles.Forsyth         max_objects = blend->num_designs;
752*37da2899SCharles.Forsyth       }
753*37da2899SCharles.Forsyth       break;
754*37da2899SCharles.Forsyth 
755*37da2899SCharles.Forsyth     default:
756*37da2899SCharles.Forsyth       dummy_object = &face->type1;
757*37da2899SCharles.Forsyth       objects      = &dummy_object;
758*37da2899SCharles.Forsyth       max_objects  = 0;
759*37da2899SCharles.Forsyth     }
760*37da2899SCharles.Forsyth 
761*37da2899SCharles.Forsyth     if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
762*37da2899SCharles.Forsyth          field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
763*37da2899SCharles.Forsyth       error = T1_Load_Field_Table( &loader->parser, field,
764*37da2899SCharles.Forsyth                                    objects, max_objects, 0 );
765*37da2899SCharles.Forsyth     else
766*37da2899SCharles.Forsyth       error = T1_Load_Field( &loader->parser, field,
767*37da2899SCharles.Forsyth                              objects, max_objects, 0 );
768*37da2899SCharles.Forsyth 
769*37da2899SCharles.Forsyth   Exit:
770*37da2899SCharles.Forsyth     return error;
771*37da2899SCharles.Forsyth   }
772*37da2899SCharles.Forsyth 
773*37da2899SCharles.Forsyth 
774*37da2899SCharles.Forsyth   static int
is_space(FT_Byte c)775*37da2899SCharles.Forsyth   is_space( FT_Byte  c )
776*37da2899SCharles.Forsyth   {
777*37da2899SCharles.Forsyth     return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' );
778*37da2899SCharles.Forsyth   }
779*37da2899SCharles.Forsyth 
780*37da2899SCharles.Forsyth 
781*37da2899SCharles.Forsyth   static int
is_alpha(FT_Byte c)782*37da2899SCharles.Forsyth   is_alpha( FT_Byte  c )
783*37da2899SCharles.Forsyth   {
784*37da2899SCharles.Forsyth     /* Note: we must accept "+" as a valid character, as it is used in */
785*37da2899SCharles.Forsyth     /*       embedded type1 fonts in PDF documents.                    */
786*37da2899SCharles.Forsyth     /*                                                                 */
787*37da2899SCharles.Forsyth     return ( ft_isalnum( c ) ||
788*37da2899SCharles.Forsyth              c == '.'        ||
789*37da2899SCharles.Forsyth              c == '_'        ||
790*37da2899SCharles.Forsyth              c == '-'        ||
791*37da2899SCharles.Forsyth              c == '+'        );
792*37da2899SCharles.Forsyth   }
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth 
795*37da2899SCharles.Forsyth   static int
read_binary_data(T1_Parser parser,FT_Long * size,FT_Byte ** base)796*37da2899SCharles.Forsyth   read_binary_data( T1_Parser  parser,
797*37da2899SCharles.Forsyth                     FT_Long*   size,
798*37da2899SCharles.Forsyth                     FT_Byte**  base )
799*37da2899SCharles.Forsyth   {
800*37da2899SCharles.Forsyth     FT_Byte*  cur;
801*37da2899SCharles.Forsyth     FT_Byte*  limit = parser->root.limit;
802*37da2899SCharles.Forsyth 
803*37da2899SCharles.Forsyth 
804*37da2899SCharles.Forsyth     /* the binary data has the following format */
805*37da2899SCharles.Forsyth     /*                                          */
806*37da2899SCharles.Forsyth     /* `size' [white*] RD white ....... ND      */
807*37da2899SCharles.Forsyth     /*                                          */
808*37da2899SCharles.Forsyth 
809*37da2899SCharles.Forsyth     T1_Skip_Spaces( parser );
810*37da2899SCharles.Forsyth     cur = parser->root.cursor;
811*37da2899SCharles.Forsyth 
812*37da2899SCharles.Forsyth     if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 )
813*37da2899SCharles.Forsyth     {
814*37da2899SCharles.Forsyth       *size = T1_ToInt( parser );
815*37da2899SCharles.Forsyth 
816*37da2899SCharles.Forsyth       T1_Skip_Spaces( parser );
817*37da2899SCharles.Forsyth       T1_Skip_Alpha ( parser );  /* `RD' or `-|' or something else */
818*37da2899SCharles.Forsyth 
819*37da2899SCharles.Forsyth       /* there is only one whitespace char after the */
820*37da2899SCharles.Forsyth       /* `RD' or `-|' token                          */
821*37da2899SCharles.Forsyth       *base = parser->root.cursor + 1;
822*37da2899SCharles.Forsyth 
823*37da2899SCharles.Forsyth       parser->root.cursor += *size + 1;
824*37da2899SCharles.Forsyth       return 1;
825*37da2899SCharles.Forsyth     }
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth     FT_ERROR(( "read_binary_data: invalid size field\n" ));
828*37da2899SCharles.Forsyth     parser->root.error = T1_Err_Invalid_File_Format;
829*37da2899SCharles.Forsyth     return 0;
830*37da2899SCharles.Forsyth   }
831*37da2899SCharles.Forsyth 
832*37da2899SCharles.Forsyth 
833*37da2899SCharles.Forsyth   /* we will now define the routines used to handle */
834*37da2899SCharles.Forsyth   /* the `/Encoding', `/Subrs', and `/CharStrings'  */
835*37da2899SCharles.Forsyth   /* dictionaries                                   */
836*37da2899SCharles.Forsyth 
837*37da2899SCharles.Forsyth   static void
parse_font_name(T1_Face face,T1_Loader loader)838*37da2899SCharles.Forsyth   parse_font_name( T1_Face    face,
839*37da2899SCharles.Forsyth                    T1_Loader  loader )
840*37da2899SCharles.Forsyth   {
841*37da2899SCharles.Forsyth     T1_Parser   parser = &loader->parser;
842*37da2899SCharles.Forsyth     FT_Error    error;
843*37da2899SCharles.Forsyth     FT_Memory   memory = parser->root.memory;
844*37da2899SCharles.Forsyth     FT_PtrDist  len;
845*37da2899SCharles.Forsyth     FT_Byte*    cur;
846*37da2899SCharles.Forsyth     FT_Byte*    cur2;
847*37da2899SCharles.Forsyth     FT_Byte*    limit;
848*37da2899SCharles.Forsyth 
849*37da2899SCharles.Forsyth 
850*37da2899SCharles.Forsyth     if ( face->type1.font_name )
851*37da2899SCharles.Forsyth       /*  with synthetic fonts, it's possible we get here twice  */
852*37da2899SCharles.Forsyth       return;
853*37da2899SCharles.Forsyth 
854*37da2899SCharles.Forsyth     T1_Skip_Spaces( parser );
855*37da2899SCharles.Forsyth 
856*37da2899SCharles.Forsyth     cur   = parser->root.cursor;
857*37da2899SCharles.Forsyth     limit = parser->root.limit;
858*37da2899SCharles.Forsyth 
859*37da2899SCharles.Forsyth     if ( cur >= limit - 1 || *cur != '/' )
860*37da2899SCharles.Forsyth       return;
861*37da2899SCharles.Forsyth 
862*37da2899SCharles.Forsyth     cur++;
863*37da2899SCharles.Forsyth     cur2 = cur;
864*37da2899SCharles.Forsyth     while ( cur2 < limit && is_alpha( *cur2 ) )
865*37da2899SCharles.Forsyth       cur2++;
866*37da2899SCharles.Forsyth 
867*37da2899SCharles.Forsyth     len = cur2 - cur;
868*37da2899SCharles.Forsyth     if ( len > 0 )
869*37da2899SCharles.Forsyth     {
870*37da2899SCharles.Forsyth       if ( FT_ALLOC( face->type1.font_name, len + 1 ) )
871*37da2899SCharles.Forsyth       {
872*37da2899SCharles.Forsyth         parser->root.error = error;
873*37da2899SCharles.Forsyth         return;
874*37da2899SCharles.Forsyth       }
875*37da2899SCharles.Forsyth 
876*37da2899SCharles.Forsyth       FT_MEM_COPY( face->type1.font_name, cur, len );
877*37da2899SCharles.Forsyth       face->type1.font_name[len] = '\0';
878*37da2899SCharles.Forsyth     }
879*37da2899SCharles.Forsyth     parser->root.cursor = cur2;
880*37da2899SCharles.Forsyth   }
881*37da2899SCharles.Forsyth 
882*37da2899SCharles.Forsyth 
883*37da2899SCharles.Forsyth #if 0
884*37da2899SCharles.Forsyth   static void
885*37da2899SCharles.Forsyth   parse_font_bbox( T1_Face    face,
886*37da2899SCharles.Forsyth                    T1_Loader  loader )
887*37da2899SCharles.Forsyth   {
888*37da2899SCharles.Forsyth     T1_Parser  parser = &loader->parser;
889*37da2899SCharles.Forsyth     FT_Fixed   temp[4];
890*37da2899SCharles.Forsyth     FT_BBox*   bbox   = &face->type1.font_bbox;
891*37da2899SCharles.Forsyth 
892*37da2899SCharles.Forsyth 
893*37da2899SCharles.Forsyth     (void)T1_ToFixedArray( parser, 4, temp, 0 );
894*37da2899SCharles.Forsyth     bbox->xMin = FT_RoundFix( temp[0] );
895*37da2899SCharles.Forsyth     bbox->yMin = FT_RoundFix( temp[1] );
896*37da2899SCharles.Forsyth     bbox->xMax = FT_RoundFix( temp[2] );
897*37da2899SCharles.Forsyth     bbox->yMax = FT_RoundFix( temp[3] );
898*37da2899SCharles.Forsyth   }
899*37da2899SCharles.Forsyth #endif
900*37da2899SCharles.Forsyth 
901*37da2899SCharles.Forsyth 
902*37da2899SCharles.Forsyth   static void
parse_font_matrix(T1_Face face,T1_Loader loader)903*37da2899SCharles.Forsyth   parse_font_matrix( T1_Face    face,
904*37da2899SCharles.Forsyth                      T1_Loader  loader )
905*37da2899SCharles.Forsyth   {
906*37da2899SCharles.Forsyth     T1_Parser   parser = &loader->parser;
907*37da2899SCharles.Forsyth     FT_Matrix*  matrix = &face->type1.font_matrix;
908*37da2899SCharles.Forsyth     FT_Vector*  offset = &face->type1.font_offset;
909*37da2899SCharles.Forsyth     FT_Face     root   = (FT_Face)&face->root;
910*37da2899SCharles.Forsyth     FT_Fixed    temp[6];
911*37da2899SCharles.Forsyth     FT_Fixed    temp_scale;
912*37da2899SCharles.Forsyth 
913*37da2899SCharles.Forsyth 
914*37da2899SCharles.Forsyth     if ( matrix->xx || matrix->yx )
915*37da2899SCharles.Forsyth       /* with synthetic fonts, it's possible we get here twice  */
916*37da2899SCharles.Forsyth       return;
917*37da2899SCharles.Forsyth 
918*37da2899SCharles.Forsyth     (void)T1_ToFixedArray( parser, 6, temp, 3 );
919*37da2899SCharles.Forsyth 
920*37da2899SCharles.Forsyth     temp_scale = ABS( temp[3] );
921*37da2899SCharles.Forsyth 
922*37da2899SCharles.Forsyth     /* Set Units per EM based on FontMatrix values.  We set the value to */
923*37da2899SCharles.Forsyth     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
924*37da2899SCharles.Forsyth     /* 1000 (in t1_tofixed, from psobjs.c).                              */
925*37da2899SCharles.Forsyth 
926*37da2899SCharles.Forsyth     root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L,
927*37da2899SCharles.Forsyth                                                  temp_scale ) >> 16 );
928*37da2899SCharles.Forsyth 
929*37da2899SCharles.Forsyth     /* we need to scale the values by 1.0/temp_scale */
930*37da2899SCharles.Forsyth     if ( temp_scale != 0x10000L )
931*37da2899SCharles.Forsyth     {
932*37da2899SCharles.Forsyth       temp[0] = FT_DivFix( temp[0], temp_scale );
933*37da2899SCharles.Forsyth       temp[1] = FT_DivFix( temp[1], temp_scale );
934*37da2899SCharles.Forsyth       temp[2] = FT_DivFix( temp[2], temp_scale );
935*37da2899SCharles.Forsyth       temp[4] = FT_DivFix( temp[4], temp_scale );
936*37da2899SCharles.Forsyth       temp[5] = FT_DivFix( temp[5], temp_scale );
937*37da2899SCharles.Forsyth       temp[3] = 0x10000L;
938*37da2899SCharles.Forsyth     }
939*37da2899SCharles.Forsyth 
940*37da2899SCharles.Forsyth     matrix->xx = temp[0];
941*37da2899SCharles.Forsyth     matrix->yx = temp[1];
942*37da2899SCharles.Forsyth     matrix->xy = temp[2];
943*37da2899SCharles.Forsyth     matrix->yy = temp[3];
944*37da2899SCharles.Forsyth 
945*37da2899SCharles.Forsyth     /* note that the offsets must be expressed in integer font units */
946*37da2899SCharles.Forsyth     offset->x  = temp[4] >> 16;
947*37da2899SCharles.Forsyth     offset->y  = temp[5] >> 16;
948*37da2899SCharles.Forsyth   }
949*37da2899SCharles.Forsyth 
950*37da2899SCharles.Forsyth 
951*37da2899SCharles.Forsyth   static void
parse_encoding(T1_Face face,T1_Loader loader)952*37da2899SCharles.Forsyth   parse_encoding( T1_Face    face,
953*37da2899SCharles.Forsyth                   T1_Loader  loader )
954*37da2899SCharles.Forsyth   {
955*37da2899SCharles.Forsyth     T1_Parser      parser = &loader->parser;
956*37da2899SCharles.Forsyth     FT_Byte*       cur    = parser->root.cursor;
957*37da2899SCharles.Forsyth     FT_Byte*       limit  = parser->root.limit;
958*37da2899SCharles.Forsyth 
959*37da2899SCharles.Forsyth     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth 
962*37da2899SCharles.Forsyth     /* skip whitespace */
963*37da2899SCharles.Forsyth     while ( is_space( *cur ) )
964*37da2899SCharles.Forsyth     {
965*37da2899SCharles.Forsyth       cur++;
966*37da2899SCharles.Forsyth       if ( cur >= limit )
967*37da2899SCharles.Forsyth       {
968*37da2899SCharles.Forsyth         FT_ERROR(( "parse_encoding: out of bounds!\n" ));
969*37da2899SCharles.Forsyth         parser->root.error = T1_Err_Invalid_File_Format;
970*37da2899SCharles.Forsyth         return;
971*37da2899SCharles.Forsyth       }
972*37da2899SCharles.Forsyth     }
973*37da2899SCharles.Forsyth 
974*37da2899SCharles.Forsyth     /* if we have a number, then the encoding is an array, */
975*37da2899SCharles.Forsyth     /* and we must load it now                             */
976*37da2899SCharles.Forsyth     if ( (FT_Byte)( *cur - '0' ) < 10 )
977*37da2899SCharles.Forsyth     {
978*37da2899SCharles.Forsyth       T1_Encoding  encode     = &face->type1.encoding;
979*37da2899SCharles.Forsyth       FT_Int       count, n;
980*37da2899SCharles.Forsyth       PS_Table     char_table = &loader->encoding_table;
981*37da2899SCharles.Forsyth       FT_Memory    memory     = parser->root.memory;
982*37da2899SCharles.Forsyth       FT_Error     error;
983*37da2899SCharles.Forsyth 
984*37da2899SCharles.Forsyth 
985*37da2899SCharles.Forsyth       if ( encode->char_index )
986*37da2899SCharles.Forsyth         /*  with synthetic fonts, it's possible we get here twice  */
987*37da2899SCharles.Forsyth         return;
988*37da2899SCharles.Forsyth 
989*37da2899SCharles.Forsyth       /* read the number of entries in the encoding, should be 256 */
990*37da2899SCharles.Forsyth       count = (FT_Int)T1_ToInt( parser );
991*37da2899SCharles.Forsyth       if ( parser->root.error )
992*37da2899SCharles.Forsyth         return;
993*37da2899SCharles.Forsyth 
994*37da2899SCharles.Forsyth       /* we use a T1_Table to store our charnames */
995*37da2899SCharles.Forsyth       loader->num_chars = encode->num_chars = count;
996*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( encode->char_index, count ) ||
997*37da2899SCharles.Forsyth            FT_NEW_ARRAY( encode->char_name,  count ) ||
998*37da2899SCharles.Forsyth            FT_SET_ERROR( psaux->ps_table_funcs->init(
999*37da2899SCharles.Forsyth                            char_table, count, memory ) ) )
1000*37da2899SCharles.Forsyth       {
1001*37da2899SCharles.Forsyth         parser->root.error = error;
1002*37da2899SCharles.Forsyth         return;
1003*37da2899SCharles.Forsyth       }
1004*37da2899SCharles.Forsyth 
1005*37da2899SCharles.Forsyth       /* We need to `zero' out encoding_table.elements */
1006*37da2899SCharles.Forsyth       for ( n = 0; n < count; n++ )
1007*37da2899SCharles.Forsyth       {
1008*37da2899SCharles.Forsyth         char*  notdef = (char *)".notdef";
1009*37da2899SCharles.Forsyth 
1010*37da2899SCharles.Forsyth 
1011*37da2899SCharles.Forsyth         T1_Add_Table( char_table, n, notdef, 8 );
1012*37da2899SCharles.Forsyth       }
1013*37da2899SCharles.Forsyth 
1014*37da2899SCharles.Forsyth       /* Now, we will need to read a record of the form         */
1015*37da2899SCharles.Forsyth       /* ... charcode /charname ... for each entry in our table */
1016*37da2899SCharles.Forsyth       /*                                                        */
1017*37da2899SCharles.Forsyth       /* We simply look for a number followed by an immediate   */
1018*37da2899SCharles.Forsyth       /* name.  Note that this ignores correctly the sequence   */
1019*37da2899SCharles.Forsyth       /* that is often seen in type1 fonts:                     */
1020*37da2899SCharles.Forsyth       /*                                                        */
1021*37da2899SCharles.Forsyth       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
1022*37da2899SCharles.Forsyth       /*                                                        */
1023*37da2899SCharles.Forsyth       /* used to clean the encoding array before anything else. */
1024*37da2899SCharles.Forsyth       /*                                                        */
1025*37da2899SCharles.Forsyth       /* We stop when we encounter a `def'.                     */
1026*37da2899SCharles.Forsyth 
1027*37da2899SCharles.Forsyth       cur   = parser->root.cursor;
1028*37da2899SCharles.Forsyth       limit = parser->root.limit;
1029*37da2899SCharles.Forsyth       n     = 0;
1030*37da2899SCharles.Forsyth 
1031*37da2899SCharles.Forsyth       for ( ; cur < limit; )
1032*37da2899SCharles.Forsyth       {
1033*37da2899SCharles.Forsyth         FT_Byte  c;
1034*37da2899SCharles.Forsyth 
1035*37da2899SCharles.Forsyth 
1036*37da2899SCharles.Forsyth         c = *cur;
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth         /* we stop when we encounter a `def' */
1039*37da2899SCharles.Forsyth         if ( c == 'd' && cur + 3 < limit )
1040*37da2899SCharles.Forsyth         {
1041*37da2899SCharles.Forsyth           if ( cur[1] == 'e'       &&
1042*37da2899SCharles.Forsyth                cur[2] == 'f'       &&
1043*37da2899SCharles.Forsyth                is_space( cur[-1] ) &&
1044*37da2899SCharles.Forsyth                is_space( cur[3] )  )
1045*37da2899SCharles.Forsyth           {
1046*37da2899SCharles.Forsyth             FT_TRACE6(( "encoding end\n" ));
1047*37da2899SCharles.Forsyth             break;
1048*37da2899SCharles.Forsyth           }
1049*37da2899SCharles.Forsyth         }
1050*37da2899SCharles.Forsyth 
1051*37da2899SCharles.Forsyth         /* otherwise, we must find a number before anything else */
1052*37da2899SCharles.Forsyth         if ( (FT_Byte)( c - '0' ) < 10 )
1053*37da2899SCharles.Forsyth         {
1054*37da2899SCharles.Forsyth           FT_Int  charcode;
1055*37da2899SCharles.Forsyth 
1056*37da2899SCharles.Forsyth 
1057*37da2899SCharles.Forsyth           parser->root.cursor = cur;
1058*37da2899SCharles.Forsyth           charcode = (FT_Int)T1_ToInt( parser );
1059*37da2899SCharles.Forsyth           cur      = parser->root.cursor;
1060*37da2899SCharles.Forsyth 
1061*37da2899SCharles.Forsyth           /* skip whitespace */
1062*37da2899SCharles.Forsyth           while ( cur < limit && is_space( *cur ) )
1063*37da2899SCharles.Forsyth             cur++;
1064*37da2899SCharles.Forsyth 
1065*37da2899SCharles.Forsyth           if ( cur < limit && *cur == '/' )
1066*37da2899SCharles.Forsyth           {
1067*37da2899SCharles.Forsyth             /* bingo, we have an immediate name -- it must be a */
1068*37da2899SCharles.Forsyth             /* character name                                   */
1069*37da2899SCharles.Forsyth             FT_Byte*    cur2 = cur + 1;
1070*37da2899SCharles.Forsyth             FT_PtrDist  len;
1071*37da2899SCharles.Forsyth 
1072*37da2899SCharles.Forsyth 
1073*37da2899SCharles.Forsyth             while ( cur2 < limit && is_alpha( *cur2 ) )
1074*37da2899SCharles.Forsyth               cur2++;
1075*37da2899SCharles.Forsyth 
1076*37da2899SCharles.Forsyth             len = cur2 - cur - 1;
1077*37da2899SCharles.Forsyth 
1078*37da2899SCharles.Forsyth             parser->root.error = T1_Add_Table( char_table, charcode,
1079*37da2899SCharles.Forsyth                                                cur + 1, len + 1 );
1080*37da2899SCharles.Forsyth             char_table->elements[charcode][len] = '\0';
1081*37da2899SCharles.Forsyth             if ( parser->root.error )
1082*37da2899SCharles.Forsyth               return;
1083*37da2899SCharles.Forsyth 
1084*37da2899SCharles.Forsyth             cur = cur2;
1085*37da2899SCharles.Forsyth           }
1086*37da2899SCharles.Forsyth         }
1087*37da2899SCharles.Forsyth         else
1088*37da2899SCharles.Forsyth           cur++;
1089*37da2899SCharles.Forsyth       }
1090*37da2899SCharles.Forsyth 
1091*37da2899SCharles.Forsyth       face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
1092*37da2899SCharles.Forsyth       parser->root.cursor       = cur;
1093*37da2899SCharles.Forsyth     }
1094*37da2899SCharles.Forsyth     /* Otherwise, we should have either `StandardEncoding', */
1095*37da2899SCharles.Forsyth     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
1096*37da2899SCharles.Forsyth     else
1097*37da2899SCharles.Forsyth     {
1098*37da2899SCharles.Forsyth       if ( cur + 17 < limit                                            &&
1099*37da2899SCharles.Forsyth            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1100*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
1101*37da2899SCharles.Forsyth 
1102*37da2899SCharles.Forsyth       else if ( cur + 15 < limit                                          &&
1103*37da2899SCharles.Forsyth                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1104*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
1105*37da2899SCharles.Forsyth 
1106*37da2899SCharles.Forsyth       else if ( cur + 18 < limit                                             &&
1107*37da2899SCharles.Forsyth                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
1108*37da2899SCharles.Forsyth         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
1109*37da2899SCharles.Forsyth 
1110*37da2899SCharles.Forsyth       else
1111*37da2899SCharles.Forsyth       {
1112*37da2899SCharles.Forsyth         FT_ERROR(( "parse_encoding: invalid token!\n" ));
1113*37da2899SCharles.Forsyth         parser->root.error = T1_Err_Invalid_File_Format;
1114*37da2899SCharles.Forsyth       }
1115*37da2899SCharles.Forsyth     }
1116*37da2899SCharles.Forsyth   }
1117*37da2899SCharles.Forsyth 
1118*37da2899SCharles.Forsyth 
1119*37da2899SCharles.Forsyth   static void
parse_subrs(T1_Face face,T1_Loader loader)1120*37da2899SCharles.Forsyth   parse_subrs( T1_Face    face,
1121*37da2899SCharles.Forsyth                T1_Loader  loader )
1122*37da2899SCharles.Forsyth   {
1123*37da2899SCharles.Forsyth     T1_Parser      parser = &loader->parser;
1124*37da2899SCharles.Forsyth     PS_Table       table  = &loader->subrs;
1125*37da2899SCharles.Forsyth     FT_Memory      memory = parser->root.memory;
1126*37da2899SCharles.Forsyth     FT_Error       error;
1127*37da2899SCharles.Forsyth     FT_Int         n;
1128*37da2899SCharles.Forsyth 
1129*37da2899SCharles.Forsyth     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
1130*37da2899SCharles.Forsyth 
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth     if ( loader->num_subrs )
1133*37da2899SCharles.Forsyth       /*  with synthetic fonts, it's possible we get here twice  */
1134*37da2899SCharles.Forsyth       return;
1135*37da2899SCharles.Forsyth 
1136*37da2899SCharles.Forsyth     loader->num_subrs = (FT_Int)T1_ToInt( parser );
1137*37da2899SCharles.Forsyth     if ( parser->root.error )
1138*37da2899SCharles.Forsyth       return;
1139*37da2899SCharles.Forsyth 
1140*37da2899SCharles.Forsyth     /* position the parser right before the `dup' of the first subr */
1141*37da2899SCharles.Forsyth     T1_Skip_Spaces( parser );
1142*37da2899SCharles.Forsyth     T1_Skip_Alpha( parser );      /* `array' */
1143*37da2899SCharles.Forsyth     T1_Skip_Spaces( parser );
1144*37da2899SCharles.Forsyth 
1145*37da2899SCharles.Forsyth     /* initialize subrs array */
1146*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory );
1147*37da2899SCharles.Forsyth     if ( error )
1148*37da2899SCharles.Forsyth       goto Fail;
1149*37da2899SCharles.Forsyth 
1150*37da2899SCharles.Forsyth     /* the format is simple:                                 */
1151*37da2899SCharles.Forsyth     /*                                                       */
1152*37da2899SCharles.Forsyth     /*   `index' + binary data                               */
1153*37da2899SCharles.Forsyth     /*                                                       */
1154*37da2899SCharles.Forsyth     for ( n = 0; n < loader->num_subrs; n++ )
1155*37da2899SCharles.Forsyth     {
1156*37da2899SCharles.Forsyth       FT_Long   idx, size;
1157*37da2899SCharles.Forsyth       FT_Byte*  base;
1158*37da2899SCharles.Forsyth 
1159*37da2899SCharles.Forsyth 
1160*37da2899SCharles.Forsyth       /* If the next token isn't `dup', we are also done.  This */
1161*37da2899SCharles.Forsyth       /* happens when there are `holes' in the Subrs array.     */
1162*37da2899SCharles.Forsyth       if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
1163*37da2899SCharles.Forsyth         break;
1164*37da2899SCharles.Forsyth 
1165*37da2899SCharles.Forsyth       idx = T1_ToInt( parser );
1166*37da2899SCharles.Forsyth 
1167*37da2899SCharles.Forsyth       if ( !read_binary_data( parser, &size, &base ) )
1168*37da2899SCharles.Forsyth         return;
1169*37da2899SCharles.Forsyth 
1170*37da2899SCharles.Forsyth       /* The binary string is followed by one token, e.g. `NP' */
1171*37da2899SCharles.Forsyth       /* (bound to `noaccess put') or by two separate tokens:  */
1172*37da2899SCharles.Forsyth       /* `noaccess' & `put'.  We position the parser right     */
1173*37da2899SCharles.Forsyth       /* before the next `dup', if any.                        */
1174*37da2899SCharles.Forsyth       T1_Skip_Spaces( parser );
1175*37da2899SCharles.Forsyth       T1_Skip_Alpha( parser );    /* `NP' or `I' or `noaccess' */
1176*37da2899SCharles.Forsyth       T1_Skip_Spaces( parser );
1177*37da2899SCharles.Forsyth 
1178*37da2899SCharles.Forsyth       if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
1179*37da2899SCharles.Forsyth       {
1180*37da2899SCharles.Forsyth         T1_Skip_Alpha( parser );  /* skip `put' */
1181*37da2899SCharles.Forsyth         T1_Skip_Spaces( parser );
1182*37da2899SCharles.Forsyth       }
1183*37da2899SCharles.Forsyth 
1184*37da2899SCharles.Forsyth       /* some fonts use a value of -1 for lenIV to indicate that */
1185*37da2899SCharles.Forsyth       /* the charstrings are unencoded                           */
1186*37da2899SCharles.Forsyth       /*                                                         */
1187*37da2899SCharles.Forsyth       /* thanks to Tom Kacvinsky for pointing this out           */
1188*37da2899SCharles.Forsyth       /*                                                         */
1189*37da2899SCharles.Forsyth       if ( face->type1.private_dict.lenIV >= 0 )
1190*37da2899SCharles.Forsyth       {
1191*37da2899SCharles.Forsyth         FT_Byte*  temp;
1192*37da2899SCharles.Forsyth 
1193*37da2899SCharles.Forsyth 
1194*37da2899SCharles.Forsyth         /* t1_decrypt() shouldn't write to base -- make temporary copy */
1195*37da2899SCharles.Forsyth         if ( FT_ALLOC( temp, size ) )
1196*37da2899SCharles.Forsyth           goto Fail;
1197*37da2899SCharles.Forsyth         FT_MEM_COPY( temp, base, size );
1198*37da2899SCharles.Forsyth         psaux->t1_decrypt( temp, size, 4330 );
1199*37da2899SCharles.Forsyth         size -= face->type1.private_dict.lenIV;
1200*37da2899SCharles.Forsyth         error = T1_Add_Table( table, idx,
1201*37da2899SCharles.Forsyth                               temp + face->type1.private_dict.lenIV, size );
1202*37da2899SCharles.Forsyth         FT_FREE( temp );
1203*37da2899SCharles.Forsyth       }
1204*37da2899SCharles.Forsyth       else
1205*37da2899SCharles.Forsyth         error = T1_Add_Table( table, idx, base, size );
1206*37da2899SCharles.Forsyth       if ( error )
1207*37da2899SCharles.Forsyth         goto Fail;
1208*37da2899SCharles.Forsyth     }
1209*37da2899SCharles.Forsyth     return;
1210*37da2899SCharles.Forsyth 
1211*37da2899SCharles.Forsyth   Fail:
1212*37da2899SCharles.Forsyth     parser->root.error = error;
1213*37da2899SCharles.Forsyth   }
1214*37da2899SCharles.Forsyth 
1215*37da2899SCharles.Forsyth 
1216*37da2899SCharles.Forsyth   static void
parse_charstrings(T1_Face face,T1_Loader loader)1217*37da2899SCharles.Forsyth   parse_charstrings( T1_Face    face,
1218*37da2899SCharles.Forsyth                      T1_Loader  loader )
1219*37da2899SCharles.Forsyth   {
1220*37da2899SCharles.Forsyth     T1_Parser      parser       = &loader->parser;
1221*37da2899SCharles.Forsyth     PS_Table       code_table   = &loader->charstrings;
1222*37da2899SCharles.Forsyth     PS_Table       name_table   = &loader->glyph_names;
1223*37da2899SCharles.Forsyth     PS_Table       swap_table   = &loader->swap_table;
1224*37da2899SCharles.Forsyth     FT_Memory      memory       = parser->root.memory;
1225*37da2899SCharles.Forsyth     FT_Error       error;
1226*37da2899SCharles.Forsyth 
1227*37da2899SCharles.Forsyth     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
1228*37da2899SCharles.Forsyth 
1229*37da2899SCharles.Forsyth     FT_Byte*       cur;
1230*37da2899SCharles.Forsyth     FT_Byte*       limit        = parser->root.limit;
1231*37da2899SCharles.Forsyth     FT_Int         n;
1232*37da2899SCharles.Forsyth     FT_UInt        notdef_index = 0;
1233*37da2899SCharles.Forsyth     FT_Byte        notdef_found = 0;
1234*37da2899SCharles.Forsyth 
1235*37da2899SCharles.Forsyth 
1236*37da2899SCharles.Forsyth     if ( loader->num_glyphs )
1237*37da2899SCharles.Forsyth       /*  with synthetic fonts, it's possible we get here twice  */
1238*37da2899SCharles.Forsyth       return;
1239*37da2899SCharles.Forsyth 
1240*37da2899SCharles.Forsyth     loader->num_glyphs = (FT_Int)T1_ToInt( parser );
1241*37da2899SCharles.Forsyth     if ( parser->root.error )
1242*37da2899SCharles.Forsyth       return;
1243*37da2899SCharles.Forsyth 
1244*37da2899SCharles.Forsyth     /* initialize tables (leaving room for addition of .notdef, */
1245*37da2899SCharles.Forsyth     /* if necessary).                                           */
1246*37da2899SCharles.Forsyth 
1247*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( code_table,
1248*37da2899SCharles.Forsyth                                          loader->num_glyphs + 1,
1249*37da2899SCharles.Forsyth                                          memory );
1250*37da2899SCharles.Forsyth     if ( error )
1251*37da2899SCharles.Forsyth       goto Fail;
1252*37da2899SCharles.Forsyth 
1253*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( name_table,
1254*37da2899SCharles.Forsyth                                          loader->num_glyphs + 1,
1255*37da2899SCharles.Forsyth                                          memory );
1256*37da2899SCharles.Forsyth     if ( error )
1257*37da2899SCharles.Forsyth       goto Fail;
1258*37da2899SCharles.Forsyth 
1259*37da2899SCharles.Forsyth     /* Initialize table for swapping index notdef_index and */
1260*37da2899SCharles.Forsyth     /* index 0 names and codes (if necessary).              */
1261*37da2899SCharles.Forsyth 
1262*37da2899SCharles.Forsyth     error = psaux->ps_table_funcs->init( swap_table, 4, memory );
1263*37da2899SCharles.Forsyth 
1264*37da2899SCharles.Forsyth     if ( error )
1265*37da2899SCharles.Forsyth       goto Fail;
1266*37da2899SCharles.Forsyth 
1267*37da2899SCharles.Forsyth     n = 0;
1268*37da2899SCharles.Forsyth 
1269*37da2899SCharles.Forsyth     for (;;)
1270*37da2899SCharles.Forsyth     {
1271*37da2899SCharles.Forsyth       FT_Long   size;
1272*37da2899SCharles.Forsyth       FT_Byte*  base;
1273*37da2899SCharles.Forsyth 
1274*37da2899SCharles.Forsyth 
1275*37da2899SCharles.Forsyth       /* the format is simple:                    */
1276*37da2899SCharles.Forsyth       /*   `/glyphname' + binary data             */
1277*37da2899SCharles.Forsyth       /*                                          */
1278*37da2899SCharles.Forsyth       /* note that we stop when we find a `def'   */
1279*37da2899SCharles.Forsyth       /*                                          */
1280*37da2899SCharles.Forsyth       T1_Skip_Spaces( parser );
1281*37da2899SCharles.Forsyth 
1282*37da2899SCharles.Forsyth       cur = parser->root.cursor;
1283*37da2899SCharles.Forsyth       if ( cur >= limit )
1284*37da2899SCharles.Forsyth         break;
1285*37da2899SCharles.Forsyth 
1286*37da2899SCharles.Forsyth       /* we stop when we find a `def' or `end' keyword */
1287*37da2899SCharles.Forsyth       if ( *cur   == 'd'   &&
1288*37da2899SCharles.Forsyth            cur + 3 < limit &&
1289*37da2899SCharles.Forsyth            cur[1] == 'e'   &&
1290*37da2899SCharles.Forsyth            cur[2] == 'f'   )
1291*37da2899SCharles.Forsyth         break;
1292*37da2899SCharles.Forsyth 
1293*37da2899SCharles.Forsyth       if ( *cur   == 'e'   &&
1294*37da2899SCharles.Forsyth            cur + 3 < limit &&
1295*37da2899SCharles.Forsyth            cur[1] == 'n'   &&
1296*37da2899SCharles.Forsyth            cur[2] == 'd'   )
1297*37da2899SCharles.Forsyth         break;
1298*37da2899SCharles.Forsyth 
1299*37da2899SCharles.Forsyth       if ( *cur != '/' )
1300*37da2899SCharles.Forsyth         T1_Skip_Alpha( parser );
1301*37da2899SCharles.Forsyth       else
1302*37da2899SCharles.Forsyth       {
1303*37da2899SCharles.Forsyth         FT_Byte*    cur2 = cur + 1;
1304*37da2899SCharles.Forsyth         FT_PtrDist  len;
1305*37da2899SCharles.Forsyth 
1306*37da2899SCharles.Forsyth 
1307*37da2899SCharles.Forsyth         while ( cur2 < limit && is_alpha( *cur2 ) )
1308*37da2899SCharles.Forsyth           cur2++;
1309*37da2899SCharles.Forsyth         len = cur2 - cur - 1;
1310*37da2899SCharles.Forsyth 
1311*37da2899SCharles.Forsyth         error = T1_Add_Table( name_table, n, cur + 1, len + 1 );
1312*37da2899SCharles.Forsyth         if ( error )
1313*37da2899SCharles.Forsyth           goto Fail;
1314*37da2899SCharles.Forsyth 
1315*37da2899SCharles.Forsyth         /* add a trailing zero to the name table */
1316*37da2899SCharles.Forsyth         name_table->elements[n][len] = '\0';
1317*37da2899SCharles.Forsyth 
1318*37da2899SCharles.Forsyth         /* record index of /.notdef              */
1319*37da2899SCharles.Forsyth         if ( ft_strcmp( (const char*)".notdef",
1320*37da2899SCharles.Forsyth                         (const char*)(name_table->elements[n]) ) == 0 )
1321*37da2899SCharles.Forsyth         {
1322*37da2899SCharles.Forsyth           notdef_index = n;
1323*37da2899SCharles.Forsyth           notdef_found = 1;
1324*37da2899SCharles.Forsyth         }
1325*37da2899SCharles.Forsyth 
1326*37da2899SCharles.Forsyth         parser->root.cursor = cur2;
1327*37da2899SCharles.Forsyth         if ( !read_binary_data( parser, &size, &base ) )
1328*37da2899SCharles.Forsyth           return;
1329*37da2899SCharles.Forsyth 
1330*37da2899SCharles.Forsyth         if ( face->type1.private_dict.lenIV >= 0 )
1331*37da2899SCharles.Forsyth         {
1332*37da2899SCharles.Forsyth           FT_Byte*  temp;
1333*37da2899SCharles.Forsyth 
1334*37da2899SCharles.Forsyth 
1335*37da2899SCharles.Forsyth           /* t1_decrypt() shouldn't write to base -- make temporary copy */
1336*37da2899SCharles.Forsyth           if ( FT_ALLOC( temp, size ) )
1337*37da2899SCharles.Forsyth             goto Fail;
1338*37da2899SCharles.Forsyth           FT_MEM_COPY( temp, base, size );
1339*37da2899SCharles.Forsyth           psaux->t1_decrypt( temp, size, 4330 );
1340*37da2899SCharles.Forsyth           size -= face->type1.private_dict.lenIV;
1341*37da2899SCharles.Forsyth           error = T1_Add_Table( code_table, n,
1342*37da2899SCharles.Forsyth                                 temp + face->type1.private_dict.lenIV, size );
1343*37da2899SCharles.Forsyth           FT_FREE( temp );
1344*37da2899SCharles.Forsyth         }
1345*37da2899SCharles.Forsyth         else
1346*37da2899SCharles.Forsyth           error = T1_Add_Table( code_table, n, base, size );
1347*37da2899SCharles.Forsyth         if ( error )
1348*37da2899SCharles.Forsyth           goto Fail;
1349*37da2899SCharles.Forsyth 
1350*37da2899SCharles.Forsyth         n++;
1351*37da2899SCharles.Forsyth         if ( n >= loader->num_glyphs )
1352*37da2899SCharles.Forsyth           break;
1353*37da2899SCharles.Forsyth       }
1354*37da2899SCharles.Forsyth     }
1355*37da2899SCharles.Forsyth 
1356*37da2899SCharles.Forsyth     loader->num_glyphs = n;
1357*37da2899SCharles.Forsyth 
1358*37da2899SCharles.Forsyth     /* if /.notdef is found but does not occupy index 0, do our magic.      */
1359*37da2899SCharles.Forsyth     if ( ft_strcmp( (const char*)".notdef",
1360*37da2899SCharles.Forsyth                     (const char*)name_table->elements[0] ) &&
1361*37da2899SCharles.Forsyth          notdef_found                                      )
1362*37da2899SCharles.Forsyth     {
1363*37da2899SCharles.Forsyth       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0    */
1364*37da2899SCharles.Forsyth       /* name and code entries to swap_table. Then place notdef_index name */
1365*37da2899SCharles.Forsyth       /* and code entries into swap_table.  Then swap name and code        */
1366*37da2899SCharles.Forsyth       /* entries at indices notdef_index and 0 using values stored in      */
1367*37da2899SCharles.Forsyth       /* swap_table.                                                       */
1368*37da2899SCharles.Forsyth 
1369*37da2899SCharles.Forsyth       /* Index 0 name */
1370*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 0,
1371*37da2899SCharles.Forsyth                             name_table->elements[0],
1372*37da2899SCharles.Forsyth                             name_table->lengths [0] );
1373*37da2899SCharles.Forsyth       if ( error )
1374*37da2899SCharles.Forsyth         goto Fail;
1375*37da2899SCharles.Forsyth 
1376*37da2899SCharles.Forsyth       /* Index 0 code */
1377*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 1,
1378*37da2899SCharles.Forsyth                             code_table->elements[0],
1379*37da2899SCharles.Forsyth                             code_table->lengths [0] );
1380*37da2899SCharles.Forsyth       if ( error )
1381*37da2899SCharles.Forsyth         goto Fail;
1382*37da2899SCharles.Forsyth 
1383*37da2899SCharles.Forsyth       /* Index notdef_index name */
1384*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 2,
1385*37da2899SCharles.Forsyth                             name_table->elements[notdef_index],
1386*37da2899SCharles.Forsyth                             name_table->lengths [notdef_index] );
1387*37da2899SCharles.Forsyth       if ( error )
1388*37da2899SCharles.Forsyth         goto Fail;
1389*37da2899SCharles.Forsyth 
1390*37da2899SCharles.Forsyth       /* Index notdef_index code */
1391*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 3,
1392*37da2899SCharles.Forsyth                             code_table->elements[notdef_index],
1393*37da2899SCharles.Forsyth                             code_table->lengths [notdef_index] );
1394*37da2899SCharles.Forsyth       if ( error )
1395*37da2899SCharles.Forsyth         goto Fail;
1396*37da2899SCharles.Forsyth 
1397*37da2899SCharles.Forsyth       error = T1_Add_Table( name_table, notdef_index,
1398*37da2899SCharles.Forsyth                             swap_table->elements[0],
1399*37da2899SCharles.Forsyth                             swap_table->lengths [0] );
1400*37da2899SCharles.Forsyth       if ( error )
1401*37da2899SCharles.Forsyth         goto Fail;
1402*37da2899SCharles.Forsyth 
1403*37da2899SCharles.Forsyth       error = T1_Add_Table( code_table, notdef_index,
1404*37da2899SCharles.Forsyth                             swap_table->elements[1],
1405*37da2899SCharles.Forsyth                             swap_table->lengths [1] );
1406*37da2899SCharles.Forsyth       if ( error )
1407*37da2899SCharles.Forsyth         goto Fail;
1408*37da2899SCharles.Forsyth 
1409*37da2899SCharles.Forsyth       error = T1_Add_Table( name_table, 0,
1410*37da2899SCharles.Forsyth                             swap_table->elements[2],
1411*37da2899SCharles.Forsyth                             swap_table->lengths [2] );
1412*37da2899SCharles.Forsyth       if ( error )
1413*37da2899SCharles.Forsyth         goto Fail;
1414*37da2899SCharles.Forsyth 
1415*37da2899SCharles.Forsyth       error = T1_Add_Table( code_table, 0,
1416*37da2899SCharles.Forsyth                             swap_table->elements[3],
1417*37da2899SCharles.Forsyth                             swap_table->lengths [3] );
1418*37da2899SCharles.Forsyth       if ( error )
1419*37da2899SCharles.Forsyth         goto Fail;
1420*37da2899SCharles.Forsyth 
1421*37da2899SCharles.Forsyth     }
1422*37da2899SCharles.Forsyth     else if ( !notdef_found )
1423*37da2899SCharles.Forsyth     {
1424*37da2899SCharles.Forsyth       /* notdef_index is already 0, or /.notdef is undefined in   */
1425*37da2899SCharles.Forsyth       /* charstrings dictionary.  Worry about /.notdef undefined. */
1426*37da2899SCharles.Forsyth       /* We take index 0 and add it to the end of the table(s)    */
1427*37da2899SCharles.Forsyth       /* and add our own /.notdef glyph to index 0.               */
1428*37da2899SCharles.Forsyth 
1429*37da2899SCharles.Forsyth       /* 0 333 hsbw endchar                                      */
1430*37da2899SCharles.Forsyth       FT_Byte  notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E};
1431*37da2899SCharles.Forsyth       char*    notdef_name    = (char *)".notdef";
1432*37da2899SCharles.Forsyth 
1433*37da2899SCharles.Forsyth 
1434*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 0,
1435*37da2899SCharles.Forsyth                             name_table->elements[0],
1436*37da2899SCharles.Forsyth                             name_table->lengths [0] );
1437*37da2899SCharles.Forsyth       if ( error )
1438*37da2899SCharles.Forsyth         goto Fail;
1439*37da2899SCharles.Forsyth 
1440*37da2899SCharles.Forsyth       error = T1_Add_Table( swap_table, 1,
1441*37da2899SCharles.Forsyth                             code_table->elements[0],
1442*37da2899SCharles.Forsyth                             code_table->lengths [0] );
1443*37da2899SCharles.Forsyth       if ( error )
1444*37da2899SCharles.Forsyth         goto Fail;
1445*37da2899SCharles.Forsyth 
1446*37da2899SCharles.Forsyth       error = T1_Add_Table( name_table, 0, notdef_name, 8 );
1447*37da2899SCharles.Forsyth       if ( error )
1448*37da2899SCharles.Forsyth         goto Fail;
1449*37da2899SCharles.Forsyth 
1450*37da2899SCharles.Forsyth       error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
1451*37da2899SCharles.Forsyth 
1452*37da2899SCharles.Forsyth       if ( error )
1453*37da2899SCharles.Forsyth         goto Fail;
1454*37da2899SCharles.Forsyth 
1455*37da2899SCharles.Forsyth       error = T1_Add_Table( name_table, n,
1456*37da2899SCharles.Forsyth                             swap_table->elements[0],
1457*37da2899SCharles.Forsyth                             swap_table->lengths [0] );
1458*37da2899SCharles.Forsyth       if ( error )
1459*37da2899SCharles.Forsyth         goto Fail;
1460*37da2899SCharles.Forsyth 
1461*37da2899SCharles.Forsyth       error = T1_Add_Table( code_table, n,
1462*37da2899SCharles.Forsyth                             swap_table->elements[1],
1463*37da2899SCharles.Forsyth                             swap_table->lengths [1] );
1464*37da2899SCharles.Forsyth       if ( error )
1465*37da2899SCharles.Forsyth         goto Fail;
1466*37da2899SCharles.Forsyth 
1467*37da2899SCharles.Forsyth       /* we added a glyph. */
1468*37da2899SCharles.Forsyth       loader->num_glyphs = n + 1;
1469*37da2899SCharles.Forsyth     }
1470*37da2899SCharles.Forsyth 
1471*37da2899SCharles.Forsyth     return;
1472*37da2899SCharles.Forsyth 
1473*37da2899SCharles.Forsyth   Fail:
1474*37da2899SCharles.Forsyth     parser->root.error = error;
1475*37da2899SCharles.Forsyth   }
1476*37da2899SCharles.Forsyth 
1477*37da2899SCharles.Forsyth 
1478*37da2899SCharles.Forsyth   static
1479*37da2899SCharles.Forsyth   const T1_FieldRec  t1_keywords[] =
1480*37da2899SCharles.Forsyth   {
1481*37da2899SCharles.Forsyth 
1482*37da2899SCharles.Forsyth #include "t1tokens.h"
1483*37da2899SCharles.Forsyth 
1484*37da2899SCharles.Forsyth     /* now add the special functions... */
1485*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontName", parse_font_name )
1486*37da2899SCharles.Forsyth #if 0
1487*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
1488*37da2899SCharles.Forsyth #endif
1489*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
1490*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "Encoding", parse_encoding )
1491*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "Subrs", parse_subrs )
1492*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "CharStrings", parse_charstrings )
1493*37da2899SCharles.Forsyth 
1494*37da2899SCharles.Forsyth #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
1495*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions )
1496*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map )
1497*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types )
1498*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector )
1499*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "shareddict", parse_shared_dict )
1500*37da2899SCharles.Forsyth #endif
1501*37da2899SCharles.Forsyth 
1502*37da2899SCharles.Forsyth     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
1503*37da2899SCharles.Forsyth   };
1504*37da2899SCharles.Forsyth 
1505*37da2899SCharles.Forsyth 
1506*37da2899SCharles.Forsyth   static FT_Error
parse_dict(T1_Face face,T1_Loader loader,FT_Byte * base,FT_Long size)1507*37da2899SCharles.Forsyth   parse_dict( T1_Face    face,
1508*37da2899SCharles.Forsyth               T1_Loader  loader,
1509*37da2899SCharles.Forsyth               FT_Byte*   base,
1510*37da2899SCharles.Forsyth               FT_Long    size )
1511*37da2899SCharles.Forsyth   {
1512*37da2899SCharles.Forsyth     T1_Parser  parser = &loader->parser;
1513*37da2899SCharles.Forsyth 
1514*37da2899SCharles.Forsyth 
1515*37da2899SCharles.Forsyth     parser->root.cursor = base;
1516*37da2899SCharles.Forsyth     parser->root.limit  = base + size;
1517*37da2899SCharles.Forsyth     parser->root.error  = 0;
1518*37da2899SCharles.Forsyth 
1519*37da2899SCharles.Forsyth     {
1520*37da2899SCharles.Forsyth       FT_Byte*  cur   = base;
1521*37da2899SCharles.Forsyth       FT_Byte*  limit = cur + size;
1522*37da2899SCharles.Forsyth 
1523*37da2899SCharles.Forsyth 
1524*37da2899SCharles.Forsyth       for ( ; cur < limit; cur++ )
1525*37da2899SCharles.Forsyth       {
1526*37da2899SCharles.Forsyth         /* look for `FontDirectory', which causes problems on some fonts */
1527*37da2899SCharles.Forsyth         if ( *cur == 'F' && cur + 25 < limit                    &&
1528*37da2899SCharles.Forsyth              ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
1529*37da2899SCharles.Forsyth         {
1530*37da2899SCharles.Forsyth           FT_Byte*  cur2;
1531*37da2899SCharles.Forsyth 
1532*37da2899SCharles.Forsyth 
1533*37da2899SCharles.Forsyth           /* skip the `FontDirectory' keyword */
1534*37da2899SCharles.Forsyth           cur += 13;
1535*37da2899SCharles.Forsyth           cur2 = cur;
1536*37da2899SCharles.Forsyth 
1537*37da2899SCharles.Forsyth           /* lookup the `known' keyword */
1538*37da2899SCharles.Forsyth           while ( cur < limit && *cur != 'k'           &&
1539*37da2899SCharles.Forsyth                   ft_strncmp( (char*)cur, "known", 5 ) )
1540*37da2899SCharles.Forsyth             cur++;
1541*37da2899SCharles.Forsyth 
1542*37da2899SCharles.Forsyth           if ( cur < limit )
1543*37da2899SCharles.Forsyth           {
1544*37da2899SCharles.Forsyth             T1_TokenRec  token;
1545*37da2899SCharles.Forsyth 
1546*37da2899SCharles.Forsyth 
1547*37da2899SCharles.Forsyth             /* skip the `known' keyword and the token following it */
1548*37da2899SCharles.Forsyth             cur += 5;
1549*37da2899SCharles.Forsyth             loader->parser.root.cursor = cur;
1550*37da2899SCharles.Forsyth             T1_ToToken( &loader->parser, &token );
1551*37da2899SCharles.Forsyth 
1552*37da2899SCharles.Forsyth             /* if the last token was an array, skip it! */
1553*37da2899SCharles.Forsyth             if ( token.type == T1_TOKEN_TYPE_ARRAY )
1554*37da2899SCharles.Forsyth               cur2 = parser->root.cursor;
1555*37da2899SCharles.Forsyth           }
1556*37da2899SCharles.Forsyth           cur = cur2;
1557*37da2899SCharles.Forsyth         }
1558*37da2899SCharles.Forsyth         /* look for immediates */
1559*37da2899SCharles.Forsyth         else if ( *cur == '/' && cur + 2 < limit )
1560*37da2899SCharles.Forsyth         {
1561*37da2899SCharles.Forsyth           FT_Byte*    cur2;
1562*37da2899SCharles.Forsyth           FT_PtrDist  len;
1563*37da2899SCharles.Forsyth 
1564*37da2899SCharles.Forsyth 
1565*37da2899SCharles.Forsyth           cur++;
1566*37da2899SCharles.Forsyth           cur2 = cur;
1567*37da2899SCharles.Forsyth           while ( cur2 < limit && is_alpha( *cur2 ) )
1568*37da2899SCharles.Forsyth             cur2++;
1569*37da2899SCharles.Forsyth 
1570*37da2899SCharles.Forsyth           len = cur2 - cur;
1571*37da2899SCharles.Forsyth           if ( len > 0 && len < 22 )
1572*37da2899SCharles.Forsyth           {
1573*37da2899SCharles.Forsyth             {
1574*37da2899SCharles.Forsyth               /* now, compare the immediate name to the keyword table */
1575*37da2899SCharles.Forsyth               T1_Field  keyword = (T1_Field)t1_keywords;
1576*37da2899SCharles.Forsyth 
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth               for (;;)
1579*37da2899SCharles.Forsyth               {
1580*37da2899SCharles.Forsyth                 FT_Byte*  name;
1581*37da2899SCharles.Forsyth 
1582*37da2899SCharles.Forsyth 
1583*37da2899SCharles.Forsyth                 name = (FT_Byte*)keyword->ident;
1584*37da2899SCharles.Forsyth                 if ( !name )
1585*37da2899SCharles.Forsyth                   break;
1586*37da2899SCharles.Forsyth 
1587*37da2899SCharles.Forsyth                 if ( cur[0] == name[0]                     &&
1588*37da2899SCharles.Forsyth                      len == ft_strlen( (const char*)name ) )
1589*37da2899SCharles.Forsyth                 {
1590*37da2899SCharles.Forsyth                   FT_PtrDist  n;
1591*37da2899SCharles.Forsyth 
1592*37da2899SCharles.Forsyth 
1593*37da2899SCharles.Forsyth                   for ( n = 1; n < len; n++ )
1594*37da2899SCharles.Forsyth                     if ( cur[n] != name[n] )
1595*37da2899SCharles.Forsyth                       break;
1596*37da2899SCharles.Forsyth 
1597*37da2899SCharles.Forsyth                   if ( n >= len )
1598*37da2899SCharles.Forsyth                   {
1599*37da2899SCharles.Forsyth                     /* we found it -- run the parsing callback! */
1600*37da2899SCharles.Forsyth                     parser->root.cursor = cur2;
1601*37da2899SCharles.Forsyth                     T1_Skip_Spaces( parser );
1602*37da2899SCharles.Forsyth                     parser->root.error = t1_load_keyword( face,
1603*37da2899SCharles.Forsyth                                                           loader,
1604*37da2899SCharles.Forsyth                                                           keyword );
1605*37da2899SCharles.Forsyth                     if ( parser->root.error )
1606*37da2899SCharles.Forsyth                       return parser->root.error;
1607*37da2899SCharles.Forsyth 
1608*37da2899SCharles.Forsyth                     cur = parser->root.cursor;
1609*37da2899SCharles.Forsyth                     break;
1610*37da2899SCharles.Forsyth                   }
1611*37da2899SCharles.Forsyth                 }
1612*37da2899SCharles.Forsyth                 keyword++;
1613*37da2899SCharles.Forsyth               }
1614*37da2899SCharles.Forsyth             }
1615*37da2899SCharles.Forsyth           }
1616*37da2899SCharles.Forsyth         }
1617*37da2899SCharles.Forsyth       }
1618*37da2899SCharles.Forsyth     }
1619*37da2899SCharles.Forsyth     return parser->root.error;
1620*37da2899SCharles.Forsyth   }
1621*37da2899SCharles.Forsyth 
1622*37da2899SCharles.Forsyth 
1623*37da2899SCharles.Forsyth   static void
t1_init_loader(T1_Loader loader,T1_Face face)1624*37da2899SCharles.Forsyth   t1_init_loader( T1_Loader  loader,
1625*37da2899SCharles.Forsyth                   T1_Face    face )
1626*37da2899SCharles.Forsyth   {
1627*37da2899SCharles.Forsyth     FT_UNUSED( face );
1628*37da2899SCharles.Forsyth 
1629*37da2899SCharles.Forsyth     FT_MEM_ZERO( loader, sizeof ( *loader ) );
1630*37da2899SCharles.Forsyth     loader->num_glyphs = 0;
1631*37da2899SCharles.Forsyth     loader->num_chars  = 0;
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth     /* initialize the tables -- simply set their `init' field to 0 */
1634*37da2899SCharles.Forsyth     loader->encoding_table.init = 0;
1635*37da2899SCharles.Forsyth     loader->charstrings.init    = 0;
1636*37da2899SCharles.Forsyth     loader->glyph_names.init    = 0;
1637*37da2899SCharles.Forsyth     loader->subrs.init          = 0;
1638*37da2899SCharles.Forsyth     loader->swap_table.init     = 0;
1639*37da2899SCharles.Forsyth     loader->fontdata            = 0;
1640*37da2899SCharles.Forsyth   }
1641*37da2899SCharles.Forsyth 
1642*37da2899SCharles.Forsyth 
1643*37da2899SCharles.Forsyth   static void
t1_done_loader(T1_Loader loader)1644*37da2899SCharles.Forsyth   t1_done_loader( T1_Loader  loader )
1645*37da2899SCharles.Forsyth   {
1646*37da2899SCharles.Forsyth     T1_Parser  parser = &loader->parser;
1647*37da2899SCharles.Forsyth 
1648*37da2899SCharles.Forsyth 
1649*37da2899SCharles.Forsyth     /* finalize tables */
1650*37da2899SCharles.Forsyth     T1_Release_Table( &loader->encoding_table );
1651*37da2899SCharles.Forsyth     T1_Release_Table( &loader->charstrings );
1652*37da2899SCharles.Forsyth     T1_Release_Table( &loader->glyph_names );
1653*37da2899SCharles.Forsyth     T1_Release_Table( &loader->swap_table );
1654*37da2899SCharles.Forsyth     T1_Release_Table( &loader->subrs );
1655*37da2899SCharles.Forsyth 
1656*37da2899SCharles.Forsyth     /* finalize parser */
1657*37da2899SCharles.Forsyth     T1_Finalize_Parser( parser );
1658*37da2899SCharles.Forsyth   }
1659*37da2899SCharles.Forsyth 
1660*37da2899SCharles.Forsyth 
1661*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
T1_Open_Face(T1_Face face)1662*37da2899SCharles.Forsyth   T1_Open_Face( T1_Face  face )
1663*37da2899SCharles.Forsyth   {
1664*37da2899SCharles.Forsyth     T1_LoaderRec   loader;
1665*37da2899SCharles.Forsyth     T1_Parser      parser;
1666*37da2899SCharles.Forsyth     T1_Font        type1 = &face->type1;
1667*37da2899SCharles.Forsyth     FT_Error       error;
1668*37da2899SCharles.Forsyth 
1669*37da2899SCharles.Forsyth     PSAux_Service  psaux = (PSAux_Service)face->psaux;
1670*37da2899SCharles.Forsyth 
1671*37da2899SCharles.Forsyth 
1672*37da2899SCharles.Forsyth     t1_init_loader( &loader, face );
1673*37da2899SCharles.Forsyth 
1674*37da2899SCharles.Forsyth     /* default lenIV */
1675*37da2899SCharles.Forsyth     type1->private_dict.lenIV = 4;
1676*37da2899SCharles.Forsyth 
1677*37da2899SCharles.Forsyth     /* default blue fuzz, we put it there since 0 is a valid value */
1678*37da2899SCharles.Forsyth     type1->private_dict.blue_fuzz = 1;
1679*37da2899SCharles.Forsyth 
1680*37da2899SCharles.Forsyth     parser = &loader.parser;
1681*37da2899SCharles.Forsyth     error  = T1_New_Parser( parser,
1682*37da2899SCharles.Forsyth                             face->root.stream,
1683*37da2899SCharles.Forsyth                             face->root.memory,
1684*37da2899SCharles.Forsyth                             psaux );
1685*37da2899SCharles.Forsyth     if ( error )
1686*37da2899SCharles.Forsyth       goto Exit;
1687*37da2899SCharles.Forsyth 
1688*37da2899SCharles.Forsyth     error = parse_dict( face, &loader, parser->base_dict, parser->base_len );
1689*37da2899SCharles.Forsyth     if ( error )
1690*37da2899SCharles.Forsyth       goto Exit;
1691*37da2899SCharles.Forsyth 
1692*37da2899SCharles.Forsyth     error = T1_Get_Private_Dict( parser, psaux );
1693*37da2899SCharles.Forsyth     if ( error )
1694*37da2899SCharles.Forsyth       goto Exit;
1695*37da2899SCharles.Forsyth 
1696*37da2899SCharles.Forsyth     error = parse_dict( face, &loader, parser->private_dict,
1697*37da2899SCharles.Forsyth                         parser->private_len );
1698*37da2899SCharles.Forsyth     if ( error )
1699*37da2899SCharles.Forsyth       goto Exit;
1700*37da2899SCharles.Forsyth 
1701*37da2899SCharles.Forsyth     /* now, propagate the subrs, charstrings, and glyphnames tables */
1702*37da2899SCharles.Forsyth     /* to the Type1 data                                            */
1703*37da2899SCharles.Forsyth     type1->num_glyphs = loader.num_glyphs;
1704*37da2899SCharles.Forsyth 
1705*37da2899SCharles.Forsyth     if ( loader.subrs.init )
1706*37da2899SCharles.Forsyth     {
1707*37da2899SCharles.Forsyth       loader.subrs.init  = 0;
1708*37da2899SCharles.Forsyth       type1->num_subrs   = loader.num_subrs;
1709*37da2899SCharles.Forsyth       type1->subrs_block = loader.subrs.block;
1710*37da2899SCharles.Forsyth       type1->subrs       = loader.subrs.elements;
1711*37da2899SCharles.Forsyth       type1->subrs_len   = loader.subrs.lengths;
1712*37da2899SCharles.Forsyth     }
1713*37da2899SCharles.Forsyth 
1714*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
1715*37da2899SCharles.Forsyth     if ( !face->root.internal->incremental_interface )
1716*37da2899SCharles.Forsyth #endif
1717*37da2899SCharles.Forsyth       if ( !loader.charstrings.init )
1718*37da2899SCharles.Forsyth       {
1719*37da2899SCharles.Forsyth         FT_ERROR(( "T1_Open_Face: no charstrings array in face!\n" ));
1720*37da2899SCharles.Forsyth         error = T1_Err_Invalid_File_Format;
1721*37da2899SCharles.Forsyth       }
1722*37da2899SCharles.Forsyth 
1723*37da2899SCharles.Forsyth     loader.charstrings.init  = 0;
1724*37da2899SCharles.Forsyth     type1->charstrings_block = loader.charstrings.block;
1725*37da2899SCharles.Forsyth     type1->charstrings       = loader.charstrings.elements;
1726*37da2899SCharles.Forsyth     type1->charstrings_len   = loader.charstrings.lengths;
1727*37da2899SCharles.Forsyth 
1728*37da2899SCharles.Forsyth     /* we copy the glyph names `block' and `elements' fields; */
1729*37da2899SCharles.Forsyth     /* the `lengths' field must be released later             */
1730*37da2899SCharles.Forsyth     type1->glyph_names_block    = loader.glyph_names.block;
1731*37da2899SCharles.Forsyth     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
1732*37da2899SCharles.Forsyth     loader.glyph_names.block    = 0;
1733*37da2899SCharles.Forsyth     loader.glyph_names.elements = 0;
1734*37da2899SCharles.Forsyth 
1735*37da2899SCharles.Forsyth     /* we must now build type1.encoding when we have a custom array */
1736*37da2899SCharles.Forsyth     if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
1737*37da2899SCharles.Forsyth     {
1738*37da2899SCharles.Forsyth       FT_Int    charcode, idx, min_char, max_char;
1739*37da2899SCharles.Forsyth       FT_Byte*  char_name;
1740*37da2899SCharles.Forsyth       FT_Byte*  glyph_name;
1741*37da2899SCharles.Forsyth 
1742*37da2899SCharles.Forsyth 
1743*37da2899SCharles.Forsyth       /* OK, we do the following: for each element in the encoding  */
1744*37da2899SCharles.Forsyth       /* table, look up the index of the glyph having the same name */
1745*37da2899SCharles.Forsyth       /* the index is then stored in type1.encoding.char_index, and */
1746*37da2899SCharles.Forsyth       /* a the name to type1.encoding.char_name                     */
1747*37da2899SCharles.Forsyth 
1748*37da2899SCharles.Forsyth       min_char = +32000;
1749*37da2899SCharles.Forsyth       max_char = -32000;
1750*37da2899SCharles.Forsyth 
1751*37da2899SCharles.Forsyth       charcode = 0;
1752*37da2899SCharles.Forsyth       for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
1753*37da2899SCharles.Forsyth       {
1754*37da2899SCharles.Forsyth         type1->encoding.char_index[charcode] = 0;
1755*37da2899SCharles.Forsyth         type1->encoding.char_name [charcode] = (char *)".notdef";
1756*37da2899SCharles.Forsyth 
1757*37da2899SCharles.Forsyth         char_name = loader.encoding_table.elements[charcode];
1758*37da2899SCharles.Forsyth         if ( char_name )
1759*37da2899SCharles.Forsyth           for ( idx = 0; idx < type1->num_glyphs; idx++ )
1760*37da2899SCharles.Forsyth           {
1761*37da2899SCharles.Forsyth             glyph_name = (FT_Byte*)type1->glyph_names[idx];
1762*37da2899SCharles.Forsyth             if ( ft_strcmp( (const char*)char_name,
1763*37da2899SCharles.Forsyth                             (const char*)glyph_name ) == 0 )
1764*37da2899SCharles.Forsyth             {
1765*37da2899SCharles.Forsyth               type1->encoding.char_index[charcode] = (FT_UShort)idx;
1766*37da2899SCharles.Forsyth               type1->encoding.char_name [charcode] = (char*)glyph_name;
1767*37da2899SCharles.Forsyth 
1768*37da2899SCharles.Forsyth               /* Change min/max encoded char only if glyph name is */
1769*37da2899SCharles.Forsyth               /* not /.notdef                                      */
1770*37da2899SCharles.Forsyth               if ( ft_strcmp( (const char*)".notdef",
1771*37da2899SCharles.Forsyth                               (const char*)glyph_name ) != 0 )
1772*37da2899SCharles.Forsyth               {
1773*37da2899SCharles.Forsyth                 if ( charcode < min_char ) min_char = charcode;
1774*37da2899SCharles.Forsyth                 if ( charcode > max_char ) max_char = charcode;
1775*37da2899SCharles.Forsyth               }
1776*37da2899SCharles.Forsyth               break;
1777*37da2899SCharles.Forsyth             }
1778*37da2899SCharles.Forsyth           }
1779*37da2899SCharles.Forsyth       }
1780*37da2899SCharles.Forsyth       type1->encoding.code_first = min_char;
1781*37da2899SCharles.Forsyth       type1->encoding.code_last  = max_char;
1782*37da2899SCharles.Forsyth       type1->encoding.num_chars  = loader.num_chars;
1783*37da2899SCharles.Forsyth     }
1784*37da2899SCharles.Forsyth 
1785*37da2899SCharles.Forsyth   Exit:
1786*37da2899SCharles.Forsyth     t1_done_loader( &loader );
1787*37da2899SCharles.Forsyth     return error;
1788*37da2899SCharles.Forsyth   }
1789*37da2899SCharles.Forsyth 
1790*37da2899SCharles.Forsyth 
1791*37da2899SCharles.Forsyth /* END */
1792