xref: /inferno-os/libfreetype/cidload.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  cidload.c                                                              */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    CID-keyed Type1 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 #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_CONFIG_CONFIG_H
22*37da2899SCharles.Forsyth #include FT_MULTIPLE_MASTERS_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_TYPE1_TYPES_H
24*37da2899SCharles.Forsyth 
25*37da2899SCharles.Forsyth #include "cidload.h"
26*37da2899SCharles.Forsyth 
27*37da2899SCharles.Forsyth #include "ciderrs.h"
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth   /*                                                                       */
32*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
33*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
34*37da2899SCharles.Forsyth   /* messages during execution.                                            */
35*37da2899SCharles.Forsyth   /*                                                                       */
36*37da2899SCharles.Forsyth #undef  FT_COMPONENT
37*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_cidload
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth 
40*37da2899SCharles.Forsyth   /* read a single offset */
41*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Long )
cid_get_offset(FT_Byte ** start,FT_Byte offsize)42*37da2899SCharles.Forsyth   cid_get_offset( FT_Byte**  start,
43*37da2899SCharles.Forsyth                   FT_Byte    offsize )
44*37da2899SCharles.Forsyth   {
45*37da2899SCharles.Forsyth     FT_Long   result;
46*37da2899SCharles.Forsyth     FT_Byte*  p = *start;
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth     for ( result = 0; offsize > 0; offsize-- )
50*37da2899SCharles.Forsyth     {
51*37da2899SCharles.Forsyth       result <<= 8;
52*37da2899SCharles.Forsyth       result  |= *p++;
53*37da2899SCharles.Forsyth     }
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth     *start = p;
56*37da2899SCharles.Forsyth     return result;
57*37da2899SCharles.Forsyth   }
58*37da2899SCharles.Forsyth 
59*37da2899SCharles.Forsyth 
60*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
cid_decrypt(FT_Byte * buffer,FT_Offset length,FT_UShort seed)61*37da2899SCharles.Forsyth   cid_decrypt( FT_Byte*   buffer,
62*37da2899SCharles.Forsyth                FT_Offset  length,
63*37da2899SCharles.Forsyth                FT_UShort  seed )
64*37da2899SCharles.Forsyth   {
65*37da2899SCharles.Forsyth     while ( length > 0 )
66*37da2899SCharles.Forsyth     {
67*37da2899SCharles.Forsyth       FT_Byte  plain;
68*37da2899SCharles.Forsyth 
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth       plain     = (FT_Byte)( *buffer ^ ( seed >> 8 ) );
71*37da2899SCharles.Forsyth       seed      = (FT_UShort)( ( *buffer + seed ) * 52845U + 22719 );
72*37da2899SCharles.Forsyth       *buffer++ = plain;
73*37da2899SCharles.Forsyth       length--;
74*37da2899SCharles.Forsyth     }
75*37da2899SCharles.Forsyth   }
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth 
78*37da2899SCharles.Forsyth   /*************************************************************************/
79*37da2899SCharles.Forsyth   /*************************************************************************/
80*37da2899SCharles.Forsyth   /*****                                                               *****/
81*37da2899SCharles.Forsyth   /*****                    TYPE 1 SYMBOL PARSING                      *****/
82*37da2899SCharles.Forsyth   /*****                                                               *****/
83*37da2899SCharles.Forsyth   /*************************************************************************/
84*37da2899SCharles.Forsyth   /*************************************************************************/
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth   static FT_Error
cid_load_keyword(CID_Face face,CID_Loader * loader,const T1_Field keyword)88*37da2899SCharles.Forsyth   cid_load_keyword( CID_Face        face,
89*37da2899SCharles.Forsyth                     CID_Loader*     loader,
90*37da2899SCharles.Forsyth                     const T1_Field  keyword )
91*37da2899SCharles.Forsyth   {
92*37da2899SCharles.Forsyth     FT_Error      error;
93*37da2899SCharles.Forsyth     CID_Parser*   parser = &loader->parser;
94*37da2899SCharles.Forsyth     FT_Byte*      object;
95*37da2899SCharles.Forsyth     void*         dummy_object;
96*37da2899SCharles.Forsyth     CID_FaceInfo  cid = &face->cid;
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth     /* if the keyword has a dedicated callback, call it */
100*37da2899SCharles.Forsyth     if ( keyword->type == T1_FIELD_TYPE_CALLBACK )
101*37da2899SCharles.Forsyth     {
102*37da2899SCharles.Forsyth       keyword->reader( (FT_Face)face, parser );
103*37da2899SCharles.Forsyth       error = parser->root.error;
104*37da2899SCharles.Forsyth       goto Exit;
105*37da2899SCharles.Forsyth     }
106*37da2899SCharles.Forsyth 
107*37da2899SCharles.Forsyth     /* we must now compute the address of our target object */
108*37da2899SCharles.Forsyth     switch ( keyword->location )
109*37da2899SCharles.Forsyth     {
110*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_CID_INFO:
111*37da2899SCharles.Forsyth       object = (FT_Byte*)cid;
112*37da2899SCharles.Forsyth       break;
113*37da2899SCharles.Forsyth 
114*37da2899SCharles.Forsyth     case T1_FIELD_LOCATION_FONT_INFO:
115*37da2899SCharles.Forsyth       object = (FT_Byte*)&cid->font_info;
116*37da2899SCharles.Forsyth       break;
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth     default:
119*37da2899SCharles.Forsyth       {
120*37da2899SCharles.Forsyth         CID_FaceDict  dict;
121*37da2899SCharles.Forsyth 
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth         if ( parser->num_dict < 0 )
124*37da2899SCharles.Forsyth         {
125*37da2899SCharles.Forsyth           FT_ERROR(( "cid_load_keyword: invalid use of `%s'!\n",
126*37da2899SCharles.Forsyth                      keyword->ident ));
127*37da2899SCharles.Forsyth           error = CID_Err_Syntax_Error;
128*37da2899SCharles.Forsyth           goto Exit;
129*37da2899SCharles.Forsyth         }
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth         dict = cid->font_dicts + parser->num_dict;
132*37da2899SCharles.Forsyth         switch ( keyword->location )
133*37da2899SCharles.Forsyth         {
134*37da2899SCharles.Forsyth         case T1_FIELD_LOCATION_PRIVATE:
135*37da2899SCharles.Forsyth           object = (FT_Byte*)&dict->private_dict;
136*37da2899SCharles.Forsyth           break;
137*37da2899SCharles.Forsyth 
138*37da2899SCharles.Forsyth         default:
139*37da2899SCharles.Forsyth           object = (FT_Byte*)dict;
140*37da2899SCharles.Forsyth         }
141*37da2899SCharles.Forsyth       }
142*37da2899SCharles.Forsyth     }
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth     dummy_object = object;
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth     /* now, load the keyword data in the object's field(s) */
147*37da2899SCharles.Forsyth     if ( keyword->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
148*37da2899SCharles.Forsyth          keyword->type == T1_FIELD_TYPE_FIXED_ARRAY   )
149*37da2899SCharles.Forsyth       error = cid_parser_load_field_table( &loader->parser, keyword,
150*37da2899SCharles.Forsyth                                     &dummy_object );
151*37da2899SCharles.Forsyth     else
152*37da2899SCharles.Forsyth       error = cid_parser_load_field( &loader->parser, keyword, &dummy_object );
153*37da2899SCharles.Forsyth   Exit:
154*37da2899SCharles.Forsyth     return error;
155*37da2899SCharles.Forsyth   }
156*37da2899SCharles.Forsyth 
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
parse_font_bbox(CID_Face face,CID_Parser * parser)159*37da2899SCharles.Forsyth   parse_font_bbox( CID_Face     face,
160*37da2899SCharles.Forsyth                    CID_Parser*  parser )
161*37da2899SCharles.Forsyth   {
162*37da2899SCharles.Forsyth     FT_Fixed  temp[4];
163*37da2899SCharles.Forsyth     FT_BBox*  bbox = &face->cid.font_bbox;
164*37da2899SCharles.Forsyth 
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth     (void)cid_parser_to_fixed_array( parser, 4, temp, 0 );
167*37da2899SCharles.Forsyth     bbox->xMin = FT_RoundFix( temp[0] );
168*37da2899SCharles.Forsyth     bbox->yMin = FT_RoundFix( temp[1] );
169*37da2899SCharles.Forsyth     bbox->xMax = FT_RoundFix( temp[2] );
170*37da2899SCharles.Forsyth     bbox->yMax = FT_RoundFix( temp[3] );
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth     return CID_Err_Ok;       /* this is a callback function; */
173*37da2899SCharles.Forsyth                             /* we must return an error code */
174*37da2899SCharles.Forsyth   }
175*37da2899SCharles.Forsyth 
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
parse_font_matrix(CID_Face face,CID_Parser * parser)178*37da2899SCharles.Forsyth   parse_font_matrix( CID_Face     face,
179*37da2899SCharles.Forsyth                      CID_Parser*  parser )
180*37da2899SCharles.Forsyth   {
181*37da2899SCharles.Forsyth     FT_Matrix*    matrix;
182*37da2899SCharles.Forsyth     FT_Vector*    offset;
183*37da2899SCharles.Forsyth     CID_FaceDict  dict;
184*37da2899SCharles.Forsyth     FT_Face       root = (FT_Face)&face->root;
185*37da2899SCharles.Forsyth     FT_Fixed      temp[6];
186*37da2899SCharles.Forsyth     FT_Fixed      temp_scale;
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth     if ( parser->num_dict >= 0 )
190*37da2899SCharles.Forsyth     {
191*37da2899SCharles.Forsyth       dict   = face->cid.font_dicts + parser->num_dict;
192*37da2899SCharles.Forsyth       matrix = &dict->font_matrix;
193*37da2899SCharles.Forsyth       offset = &dict->font_offset;
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth       (void)cid_parser_to_fixed_array( parser, 6, temp, 3 );
196*37da2899SCharles.Forsyth 
197*37da2899SCharles.Forsyth       temp_scale = ABS( temp[3] );
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth       /* Set Units per EM based on FontMatrix values.  We set the value to */
200*37da2899SCharles.Forsyth       /* `1000/temp_scale', because temp_scale was already multiplied by   */
201*37da2899SCharles.Forsyth       /* 1000 (in t1_tofixed(), from psobjs.c).                            */
202*37da2899SCharles.Forsyth       root->units_per_EM = (FT_UShort)( FT_DivFix( 0x10000L,
203*37da2899SCharles.Forsyth                                         FT_DivFix( temp_scale, 1000 ) ) );
204*37da2899SCharles.Forsyth 
205*37da2899SCharles.Forsyth       /* we need to scale the values by 1.0/temp[3] */
206*37da2899SCharles.Forsyth       if ( temp_scale != 0x10000L )
207*37da2899SCharles.Forsyth       {
208*37da2899SCharles.Forsyth         temp[0] = FT_DivFix( temp[0], temp_scale );
209*37da2899SCharles.Forsyth         temp[1] = FT_DivFix( temp[1], temp_scale );
210*37da2899SCharles.Forsyth         temp[2] = FT_DivFix( temp[2], temp_scale );
211*37da2899SCharles.Forsyth         temp[4] = FT_DivFix( temp[4], temp_scale );
212*37da2899SCharles.Forsyth         temp[5] = FT_DivFix( temp[5], temp_scale );
213*37da2899SCharles.Forsyth         temp[3] = 0x10000L;
214*37da2899SCharles.Forsyth       }
215*37da2899SCharles.Forsyth 
216*37da2899SCharles.Forsyth       matrix->xx = temp[0];
217*37da2899SCharles.Forsyth       matrix->yx = temp[1];
218*37da2899SCharles.Forsyth       matrix->xy = temp[2];
219*37da2899SCharles.Forsyth       matrix->yy = temp[3];
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth       /* note that the font offsets are expressed in integer font units */
222*37da2899SCharles.Forsyth       offset->x  = temp[4] >> 16;
223*37da2899SCharles.Forsyth       offset->y  = temp[5] >> 16;
224*37da2899SCharles.Forsyth     }
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth     return CID_Err_Ok;       /* this is a callback function; */
227*37da2899SCharles.Forsyth                             /* we must return an error code */
228*37da2899SCharles.Forsyth   }
229*37da2899SCharles.Forsyth 
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth   FT_CALLBACK_DEF( FT_Error )
parse_fd_array(CID_Face face,CID_Parser * parser)232*37da2899SCharles.Forsyth   parse_fd_array( CID_Face     face,
233*37da2899SCharles.Forsyth                   CID_Parser*  parser )
234*37da2899SCharles.Forsyth   {
235*37da2899SCharles.Forsyth     CID_FaceInfo  cid    = &face->cid;
236*37da2899SCharles.Forsyth     FT_Memory     memory = face->root.memory;
237*37da2899SCharles.Forsyth     FT_Error      error  = CID_Err_Ok;
238*37da2899SCharles.Forsyth     FT_Long       num_dicts;
239*37da2899SCharles.Forsyth 
240*37da2899SCharles.Forsyth 
241*37da2899SCharles.Forsyth     num_dicts = cid_parser_to_int( parser );
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth     if ( !cid->font_dicts )
244*37da2899SCharles.Forsyth     {
245*37da2899SCharles.Forsyth       FT_Int  n;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth 
248*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( cid->font_dicts, num_dicts ) )
249*37da2899SCharles.Forsyth         goto Exit;
250*37da2899SCharles.Forsyth 
251*37da2899SCharles.Forsyth       cid->num_dicts = (FT_UInt)num_dicts;
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth       /* don't forget to set a few defaults */
254*37da2899SCharles.Forsyth       for ( n = 0; n < cid->num_dicts; n++ )
255*37da2899SCharles.Forsyth       {
256*37da2899SCharles.Forsyth         CID_FaceDict  dict = cid->font_dicts + n;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth         /* default value for lenIV */
260*37da2899SCharles.Forsyth         dict->private_dict.lenIV = 4;
261*37da2899SCharles.Forsyth       }
262*37da2899SCharles.Forsyth     }
263*37da2899SCharles.Forsyth 
264*37da2899SCharles.Forsyth   Exit:
265*37da2899SCharles.Forsyth     return error;
266*37da2899SCharles.Forsyth   }
267*37da2899SCharles.Forsyth 
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth   static
270*37da2899SCharles.Forsyth   const T1_FieldRec  cid_field_records[] =
271*37da2899SCharles.Forsyth   {
272*37da2899SCharles.Forsyth 
273*37da2899SCharles.Forsyth #include "cidtoken.h"
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox )
276*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FDArray", parse_fd_array )
277*37da2899SCharles.Forsyth     T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix )
278*37da2899SCharles.Forsyth     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 }
279*37da2899SCharles.Forsyth   };
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth   static int
is_alpha(char c)283*37da2899SCharles.Forsyth   is_alpha( char  c )
284*37da2899SCharles.Forsyth   {
285*37da2899SCharles.Forsyth     return ( ft_isalnum( (int)c ) ||
286*37da2899SCharles.Forsyth              c == '.'             ||
287*37da2899SCharles.Forsyth              c == '_'             );
288*37da2899SCharles.Forsyth   }
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth 
291*37da2899SCharles.Forsyth   static FT_Error
cid_parse_dict(CID_Face face,CID_Loader * loader,FT_Byte * base,FT_Long size)292*37da2899SCharles.Forsyth   cid_parse_dict( CID_Face     face,
293*37da2899SCharles.Forsyth                   CID_Loader*  loader,
294*37da2899SCharles.Forsyth                   FT_Byte*     base,
295*37da2899SCharles.Forsyth                   FT_Long      size )
296*37da2899SCharles.Forsyth   {
297*37da2899SCharles.Forsyth     CID_Parser*  parser = &loader->parser;
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth     parser->root.cursor = base;
301*37da2899SCharles.Forsyth     parser->root.limit  = base + size;
302*37da2899SCharles.Forsyth     parser->root.error  = 0;
303*37da2899SCharles.Forsyth 
304*37da2899SCharles.Forsyth     {
305*37da2899SCharles.Forsyth       FT_Byte*  cur   = base;
306*37da2899SCharles.Forsyth       FT_Byte*  limit = cur + size;
307*37da2899SCharles.Forsyth 
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth       for ( ;cur < limit; cur++ )
310*37da2899SCharles.Forsyth       {
311*37da2899SCharles.Forsyth         /* look for `%ADOBeginFontDict' */
312*37da2899SCharles.Forsyth         if ( *cur == '%' && cur + 20 < limit &&
313*37da2899SCharles.Forsyth              ft_strncmp( (char*)cur, "%ADOBeginFontDict", 17 ) == 0 )
314*37da2899SCharles.Forsyth         {
315*37da2899SCharles.Forsyth           cur += 17;
316*37da2899SCharles.Forsyth 
317*37da2899SCharles.Forsyth           /* if /FDArray was found, then cid->num_dicts is > 0, and */
318*37da2899SCharles.Forsyth           /* we can start increasing parser->num_dict               */
319*37da2899SCharles.Forsyth           if ( face->cid.num_dicts > 0 )
320*37da2899SCharles.Forsyth             parser->num_dict++;
321*37da2899SCharles.Forsyth         }
322*37da2899SCharles.Forsyth         /* look for immediates */
323*37da2899SCharles.Forsyth         else if ( *cur == '/' && cur + 2 < limit )
324*37da2899SCharles.Forsyth         {
325*37da2899SCharles.Forsyth           FT_Byte*  cur2;
326*37da2899SCharles.Forsyth           FT_Int    len;
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth           cur++;
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth           cur2 = cur;
332*37da2899SCharles.Forsyth           while ( cur2 < limit && is_alpha( *cur2 ) )
333*37da2899SCharles.Forsyth             cur2++;
334*37da2899SCharles.Forsyth 
335*37da2899SCharles.Forsyth           len = (FT_Int)( cur2 - cur );
336*37da2899SCharles.Forsyth           if ( len > 0 && len < 22 )
337*37da2899SCharles.Forsyth           {
338*37da2899SCharles.Forsyth             /* now compare the immediate name to the keyword table */
339*37da2899SCharles.Forsyth             T1_Field  keyword = (T1_Field) cid_field_records;
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth 
342*37da2899SCharles.Forsyth             for (;;)
343*37da2899SCharles.Forsyth             {
344*37da2899SCharles.Forsyth               FT_Byte*  name;
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth 
347*37da2899SCharles.Forsyth               name = (FT_Byte*)keyword->ident;
348*37da2899SCharles.Forsyth               if ( !name )
349*37da2899SCharles.Forsyth                 break;
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth               if ( cur[0] == name[0]                          &&
352*37da2899SCharles.Forsyth                    len == (FT_Int)ft_strlen( (const char*)name ) )
353*37da2899SCharles.Forsyth               {
354*37da2899SCharles.Forsyth                 FT_Int  n;
355*37da2899SCharles.Forsyth 
356*37da2899SCharles.Forsyth 
357*37da2899SCharles.Forsyth                 for ( n = 1; n < len; n++ )
358*37da2899SCharles.Forsyth                   if ( cur[n] != name[n] )
359*37da2899SCharles.Forsyth                     break;
360*37da2899SCharles.Forsyth 
361*37da2899SCharles.Forsyth                 if ( n >= len )
362*37da2899SCharles.Forsyth                 {
363*37da2899SCharles.Forsyth                   /* we found it - run the parsing callback */
364*37da2899SCharles.Forsyth                   parser->root.cursor = cur2;
365*37da2899SCharles.Forsyth                   cid_parser_skip_spaces( parser );
366*37da2899SCharles.Forsyth                   parser->root.error = cid_load_keyword( face,
367*37da2899SCharles.Forsyth                                                          loader,
368*37da2899SCharles.Forsyth                                                          keyword );
369*37da2899SCharles.Forsyth                   if ( parser->root.error )
370*37da2899SCharles.Forsyth                     return parser->root.error;
371*37da2899SCharles.Forsyth 
372*37da2899SCharles.Forsyth                   cur = parser->root.cursor;
373*37da2899SCharles.Forsyth                   break;
374*37da2899SCharles.Forsyth                 }
375*37da2899SCharles.Forsyth               }
376*37da2899SCharles.Forsyth               keyword++;
377*37da2899SCharles.Forsyth             }
378*37da2899SCharles.Forsyth           }
379*37da2899SCharles.Forsyth         }
380*37da2899SCharles.Forsyth       }
381*37da2899SCharles.Forsyth     }
382*37da2899SCharles.Forsyth     return parser->root.error;
383*37da2899SCharles.Forsyth   }
384*37da2899SCharles.Forsyth 
385*37da2899SCharles.Forsyth 
386*37da2899SCharles.Forsyth   /* read the subrmap and the subrs of each font dict */
387*37da2899SCharles.Forsyth   static FT_Error
cid_read_subrs(CID_Face face)388*37da2899SCharles.Forsyth   cid_read_subrs( CID_Face  face )
389*37da2899SCharles.Forsyth   {
390*37da2899SCharles.Forsyth     CID_FaceInfo  cid    = &face->cid;
391*37da2899SCharles.Forsyth     FT_Memory     memory = face->root.memory;
392*37da2899SCharles.Forsyth     FT_Stream     stream = face->root.stream;
393*37da2899SCharles.Forsyth     FT_Error      error;
394*37da2899SCharles.Forsyth     FT_Int        n;
395*37da2899SCharles.Forsyth     CID_Subrs     subr;
396*37da2899SCharles.Forsyth     FT_UInt       max_offsets = 0;
397*37da2899SCharles.Forsyth     FT_ULong*     offsets = 0;
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth     if ( FT_NEW_ARRAY( face->subrs, cid->num_dicts ) )
401*37da2899SCharles.Forsyth       goto Exit;
402*37da2899SCharles.Forsyth 
403*37da2899SCharles.Forsyth     subr = face->subrs;
404*37da2899SCharles.Forsyth     for ( n = 0; n < cid->num_dicts; n++, subr++ )
405*37da2899SCharles.Forsyth     {
406*37da2899SCharles.Forsyth       CID_FaceDict  dict  = cid->font_dicts + n;
407*37da2899SCharles.Forsyth       FT_Int        lenIV = dict->private_dict.lenIV;
408*37da2899SCharles.Forsyth       FT_UInt       count, num_subrs = dict->num_subrs;
409*37da2899SCharles.Forsyth       FT_ULong      data_len;
410*37da2899SCharles.Forsyth       FT_Byte*      p;
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth 
413*37da2899SCharles.Forsyth       /* reallocate offsets array if needed */
414*37da2899SCharles.Forsyth       if ( num_subrs + 1 > max_offsets )
415*37da2899SCharles.Forsyth       {
416*37da2899SCharles.Forsyth         FT_UInt  new_max = ( num_subrs + 1 + 3 ) & -4;
417*37da2899SCharles.Forsyth 
418*37da2899SCharles.Forsyth 
419*37da2899SCharles.Forsyth         if ( FT_RENEW_ARRAY( offsets, max_offsets, new_max ) )
420*37da2899SCharles.Forsyth           goto Fail;
421*37da2899SCharles.Forsyth 
422*37da2899SCharles.Forsyth         max_offsets = new_max;
423*37da2899SCharles.Forsyth       }
424*37da2899SCharles.Forsyth 
425*37da2899SCharles.Forsyth       /* read the subrmap's offsets */
426*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( cid->data_offset + dict->subrmap_offset ) ||
427*37da2899SCharles.Forsyth            FT_FRAME_ENTER( ( num_subrs + 1 ) * dict->sd_bytes )   )
428*37da2899SCharles.Forsyth         goto Fail;
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth       p = (FT_Byte*)stream->cursor;
431*37da2899SCharles.Forsyth       for ( count = 0; count <= num_subrs; count++ )
432*37da2899SCharles.Forsyth         offsets[count] = cid_get_offset( &p, (FT_Byte)dict->sd_bytes );
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
435*37da2899SCharles.Forsyth 
436*37da2899SCharles.Forsyth       /* now, compute the size of subrs charstrings, */
437*37da2899SCharles.Forsyth       /* allocate, and read them                     */
438*37da2899SCharles.Forsyth       data_len = offsets[num_subrs] - offsets[0];
439*37da2899SCharles.Forsyth 
440*37da2899SCharles.Forsyth       if ( FT_NEW_ARRAY( subr->code, num_subrs + 1 ) ||
441*37da2899SCharles.Forsyth                FT_ALLOC( subr->code[0], data_len )   )
442*37da2899SCharles.Forsyth         goto Fail;
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth       if ( FT_STREAM_SEEK( cid->data_offset + offsets[0] ) ||
445*37da2899SCharles.Forsyth            FT_STREAM_READ( subr->code[0], data_len )  )
446*37da2899SCharles.Forsyth         goto Fail;
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth       /* set up pointers */
449*37da2899SCharles.Forsyth       for ( count = 1; count <= num_subrs; count++ )
450*37da2899SCharles.Forsyth       {
451*37da2899SCharles.Forsyth         FT_ULong  len;
452*37da2899SCharles.Forsyth 
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth         len               = offsets[count] - offsets[count - 1];
455*37da2899SCharles.Forsyth         subr->code[count] = subr->code[count - 1] + len;
456*37da2899SCharles.Forsyth       }
457*37da2899SCharles.Forsyth 
458*37da2899SCharles.Forsyth       /* decrypt subroutines, but only if lenIV >= 0 */
459*37da2899SCharles.Forsyth       if ( lenIV >= 0 )
460*37da2899SCharles.Forsyth       {
461*37da2899SCharles.Forsyth         for ( count = 0; count < num_subrs; count++ )
462*37da2899SCharles.Forsyth         {
463*37da2899SCharles.Forsyth           FT_ULong  len;
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth 
466*37da2899SCharles.Forsyth           len = offsets[count + 1] - offsets[count];
467*37da2899SCharles.Forsyth           cid_decrypt( subr->code[count], len, 4330 );
468*37da2899SCharles.Forsyth         }
469*37da2899SCharles.Forsyth       }
470*37da2899SCharles.Forsyth 
471*37da2899SCharles.Forsyth       subr->num_subrs = num_subrs;
472*37da2899SCharles.Forsyth     }
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth   Exit:
475*37da2899SCharles.Forsyth     FT_FREE( offsets );
476*37da2899SCharles.Forsyth     return error;
477*37da2899SCharles.Forsyth 
478*37da2899SCharles.Forsyth   Fail:
479*37da2899SCharles.Forsyth     if ( face->subrs )
480*37da2899SCharles.Forsyth     {
481*37da2899SCharles.Forsyth       for ( n = 0; n < cid->num_dicts; n++ )
482*37da2899SCharles.Forsyth       {
483*37da2899SCharles.Forsyth         if ( face->subrs[n].code )
484*37da2899SCharles.Forsyth           FT_FREE( face->subrs[n].code[0] );
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth         FT_FREE( face->subrs[n].code );
487*37da2899SCharles.Forsyth       }
488*37da2899SCharles.Forsyth       FT_FREE( face->subrs );
489*37da2899SCharles.Forsyth     }
490*37da2899SCharles.Forsyth     goto Exit;
491*37da2899SCharles.Forsyth   }
492*37da2899SCharles.Forsyth 
493*37da2899SCharles.Forsyth 
494*37da2899SCharles.Forsyth   static void
t1_init_loader(CID_Loader * loader,CID_Face face)495*37da2899SCharles.Forsyth   t1_init_loader( CID_Loader*  loader,
496*37da2899SCharles.Forsyth                   CID_Face     face )
497*37da2899SCharles.Forsyth   {
498*37da2899SCharles.Forsyth     FT_UNUSED( face );
499*37da2899SCharles.Forsyth 
500*37da2899SCharles.Forsyth     FT_MEM_ZERO( loader, sizeof ( *loader ) );
501*37da2899SCharles.Forsyth   }
502*37da2899SCharles.Forsyth 
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth   static void
t1_done_loader(CID_Loader * loader)505*37da2899SCharles.Forsyth   t1_done_loader( CID_Loader*  loader )
506*37da2899SCharles.Forsyth   {
507*37da2899SCharles.Forsyth     CID_Parser*  parser = &loader->parser;
508*37da2899SCharles.Forsyth 
509*37da2899SCharles.Forsyth 
510*37da2899SCharles.Forsyth     /* finalize parser */
511*37da2899SCharles.Forsyth     cid_parser_done( parser );
512*37da2899SCharles.Forsyth   }
513*37da2899SCharles.Forsyth 
514*37da2899SCharles.Forsyth 
515*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
cid_face_open(CID_Face face)516*37da2899SCharles.Forsyth   cid_face_open( CID_Face  face )
517*37da2899SCharles.Forsyth   {
518*37da2899SCharles.Forsyth     CID_Loader   loader;
519*37da2899SCharles.Forsyth     CID_Parser*  parser;
520*37da2899SCharles.Forsyth     FT_Error     error;
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth 
523*37da2899SCharles.Forsyth     t1_init_loader( &loader, face );
524*37da2899SCharles.Forsyth 
525*37da2899SCharles.Forsyth     parser = &loader.parser;
526*37da2899SCharles.Forsyth     error = cid_parser_new( parser, face->root.stream, face->root.memory,
527*37da2899SCharles.Forsyth                             (PSAux_Service)face->psaux );
528*37da2899SCharles.Forsyth     if ( error )
529*37da2899SCharles.Forsyth       goto Exit;
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth     error = cid_parse_dict( face, &loader,
532*37da2899SCharles.Forsyth                             parser->postscript,
533*37da2899SCharles.Forsyth                             parser->postscript_len );
534*37da2899SCharles.Forsyth     if ( error )
535*37da2899SCharles.Forsyth       goto Exit;
536*37da2899SCharles.Forsyth 
537*37da2899SCharles.Forsyth     face->cid.data_offset = loader.parser.data_offset;
538*37da2899SCharles.Forsyth     error = cid_read_subrs( face );
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth   Exit:
541*37da2899SCharles.Forsyth     t1_done_loader( &loader );
542*37da2899SCharles.Forsyth     return error;
543*37da2899SCharles.Forsyth   }
544*37da2899SCharles.Forsyth 
545*37da2899SCharles.Forsyth 
546*37da2899SCharles.Forsyth /* END */
547