misc fixes to get rrdtool working without included libraries.
[rrdtool.git] / libraries / freetype-2.0.5 / t1parse.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  t1parse.c                                                              */
4 /*                                                                         */
5 /*    Type 1 parser (body).                                                */
6 /*                                                                         */
7 /*  Copyright 1996-2001 by                                                 */
8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9 /*                                                                         */
10 /*  This file is part of the FreeType project, and may only be used,       */
11 /*  modified, and distributed under the terms of the FreeType project      */
12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13 /*  this file you indicate that you have read the license and              */
14 /*  understand and accept it fully.                                        */
15 /*                                                                         */
16 /***************************************************************************/
17
18
19   /*************************************************************************/
20   /*                                                                       */
21   /* The Type 1 parser is in charge of the following:                      */
22   /*                                                                       */
23   /*  - provide an implementation of a growing sequence of objects called  */
24   /*    a `T1_Table' (used to build various tables needed by the loader).  */
25   /*                                                                       */
26   /*  - opening .pfb and .pfa files to extract their top-level and private */
27   /*    dictionaries.                                                      */
28   /*                                                                       */
29   /*  - read numbers, arrays & strings from any dictionary.                */
30   /*                                                                       */
31   /* See `t1load.c' to see how data is loaded from the font file.          */
32   /*                                                                       */
33   /*************************************************************************/
34
35
36 #include <ft2build.h>
37 #include FT_INTERNAL_DEBUG_H
38 #include FT_INTERNAL_CALC_H
39 #include FT_INTERNAL_STREAM_H
40 #include FT_INTERNAL_POSTSCRIPT_AUX_H
41
42 #include "t1parse.h"
43
44 #include "t1errors.h"
45
46 #include <string.h>     /* for strncmp() */
47
48
49   /*************************************************************************/
50   /*                                                                       */
51   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
52   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
53   /* messages during execution.                                            */
54   /*                                                                       */
55 #undef  FT_COMPONENT
56 #define FT_COMPONENT  trace_t1parse
57
58
59   /*************************************************************************/
60   /*************************************************************************/
61   /*************************************************************************/
62   /*****                                                               *****/
63   /*****                   INPUT STREAM PARSER                         *****/
64   /*****                                                               *****/
65   /*************************************************************************/
66   /*************************************************************************/
67   /*************************************************************************/
68
69
70 #define IS_T1_WHITESPACE( c )  ( (c) == ' '  || (c) == '\t' )
71 #define IS_T1_LINESPACE( c )   ( (c) == '\r' || (c) == '\n' )
72
73 #define IS_T1_SPACE( c )  ( IS_T1_WHITESPACE( c ) || IS_T1_LINESPACE( c ) )
74
75
76   typedef struct  PFB_Tag_
77   {
78     FT_UShort  tag;
79     FT_Long    size;
80
81   } PFB_Tag;
82
83
84 #undef  FT_STRUCTURE
85 #define FT_STRUCTURE  PFB_Tag
86
87
88   static
89   const FT_Frame_Field  pfb_tag_fields[] =
90   {
91     FT_FRAME_START( 6 ),
92       FT_FRAME_USHORT ( tag ),
93       FT_FRAME_LONG_LE( size ),
94     FT_FRAME_END
95   };
96
97
98   static FT_Error
99   read_pfb_tag( FT_Stream   stream,
100                 FT_UShort*  tag,
101                 FT_Long*    size )
102   {
103     FT_Error  error;
104     PFB_Tag   head;
105
106
107     *tag  = 0;
108     *size = 0;
109     if ( !READ_Fields( pfb_tag_fields, &head ) )
110     {
111       if ( head.tag == 0x8001 || head.tag == 0x8002 )
112       {
113         *tag  = head.tag;
114         *size = head.size;
115       }
116     }
117     return error;
118   }
119
120
121   FT_LOCAL_DEF FT_Error
122   T1_New_Parser( T1_ParserRec*     parser,
123                  FT_Stream         stream,
124                  FT_Memory         memory,
125                  PSAux_Interface*  psaux )
126   {
127     FT_Error   error;
128     FT_UShort  tag;
129     FT_Long    size;
130
131
132     psaux->t1_parser_funcs->init( &parser->root,0, 0, memory );
133
134     parser->stream       = stream;
135     parser->base_len     = 0;
136     parser->base_dict    = 0;
137     parser->private_len  = 0;
138     parser->private_dict = 0;
139     parser->in_pfb       = 0;
140     parser->in_memory    = 0;
141     parser->single_block = 0;
142
143     /******************************************************************/
144     /*                                                                */
145     /* Here a short summary of what is going on:                      */
146     /*                                                                */
147     /*   When creating a new Type 1 parser, we try to locate and load */
148     /*   the base dictionary if this is possible (i.e. for PFB        */
149     /*   files).  Otherwise, we load the whole font into memory.      */
150     /*                                                                */
151     /*   When `loading' the base dictionary, we only setup pointers   */
152     /*   in the case of a memory-based stream.  Otherwise, we         */
153     /*   allocate and load the base dictionary in it.                 */
154     /*                                                                */
155     /*   parser->in_pfb is set if we are in a binary (".pfb") font.   */
156     /*   parser->in_memory is set if we have a memory stream.         */
157     /*                                                                */
158
159     /* try to compute the size of the base dictionary;   */
160     /* look for a Postscript binary file tag, i.e 0x8001 */
161     if ( FILE_Seek( 0L ) )
162       goto Exit;
163
164     error = read_pfb_tag( stream, &tag, &size );
165     if ( error )
166       goto Exit;
167
168     if ( tag != 0x8001 )
169     {
170       /* assume that this is a PFA file for now; an error will */
171       /* be produced later when more things are checked        */
172       if ( FILE_Seek( 0L ) )
173         goto Exit;
174       size = stream->size;
175     }
176     else
177       parser->in_pfb = 1;
178
179     /* now, try to load `size' bytes of the `base' dictionary we */
180     /* found previously                                          */
181
182     /* if it is a memory-based resource, set up pointers */
183     if ( !stream->read )
184     {
185       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
186       parser->base_len  = size;
187       parser->in_memory = 1;
188
189       /* check that the `size' field is valid */
190       if ( FILE_Skip( size ) )
191         goto Exit;
192     }
193     else
194     {
195       /* read segment in memory */
196       if ( ALLOC( parser->base_dict, size )     ||
197            FILE_Read( parser->base_dict, size ) )
198         goto Exit;
199       parser->base_len = size;
200     }
201
202     /* Now check font format; we must see `%!PS-AdobeFont-1' */
203     /* or `%!FontType'                                       */
204     {
205       if ( size <= 16                                    ||
206            ( strncmp( (const char*)parser->base_dict,
207                       "%!PS-AdobeFont-1", 16 )        &&
208              strncmp( (const char*)parser->base_dict,
209                       "%!FontType", 10 )              )  )
210       {
211         FT_TRACE2(( "[not a Type1 font]\n" ));
212         error = T1_Err_Unknown_File_Format;
213       }
214       else
215       {
216         parser->root.base   = parser->base_dict;
217         parser->root.cursor = parser->base_dict;
218         parser->root.limit  = parser->root.cursor + parser->base_len;
219       }
220     }
221
222   Exit:
223     if ( error && !parser->in_memory )
224       FREE( parser->base_dict );
225
226     return error;
227   }
228
229
230   FT_LOCAL_DEF void
231   T1_Finalize_Parser( T1_ParserRec*  parser )
232   {
233     FT_Memory   memory = parser->root.memory;
234
235
236     /* always free the private dictionary */
237     FREE( parser->private_dict );
238
239     /* free the base dictionary only when we have a disk stream */
240     if ( !parser->in_memory )
241       FREE( parser->base_dict );
242
243     parser->root.funcs.done( &parser->root );
244   }
245
246
247   /* return the value of an hexadecimal digit */
248   static int
249   hexa_value( char  c )
250   {
251     unsigned int  d;
252
253
254     d = (unsigned int)( c - '0' );
255     if ( d <= 9 )
256       return (int)d;
257
258     d = (unsigned int)( c - 'a' );
259     if ( d <= 5 )
260       return (int)( d + 10 );
261
262     d = (unsigned int)( c - 'A' );
263     if ( d <= 5 )
264       return (int)( d + 10 );
265
266     return -1;
267   }
268
269
270   FT_LOCAL_DEF FT_Error
271   T1_Get_Private_Dict( T1_ParserRec*     parser,
272                        PSAux_Interface*  psaux )
273   {
274     FT_Stream  stream = parser->stream;
275     FT_Memory  memory = parser->root.memory;
276     FT_Error   error  = 0;
277     FT_Long    size;
278
279
280     if ( parser->in_pfb )
281     {
282       /* in the case of the PFB format, the private dictionary can be  */
283       /* made of several segments.  We thus first read the number of   */
284       /* segments to compute the total size of the private dictionary  */
285       /* then re-read them into memory.                                */
286       FT_Long    start_pos = FILE_Pos();
287       FT_UShort  tag;
288
289
290       parser->private_len = 0;
291       for (;;)
292       {
293         error = read_pfb_tag( stream, &tag, &size );
294         if ( error )
295           goto Fail;
296
297         if ( tag != 0x8002 )
298           break;
299
300         parser->private_len += size;
301
302         if ( FILE_Skip( size ) )
303           goto Fail;
304       }
305
306       /* Check that we have a private dictionary there */
307       /* and allocate private dictionary buffer        */
308       if ( parser->private_len == 0 )
309       {
310         FT_ERROR(( "T1_Get_Private_Dict:" ));
311         FT_ERROR(( " invalid private dictionary section\n" ));
312         error = T1_Err_Invalid_File_Format;
313         goto Fail;
314       }
315
316       if ( FILE_Seek( start_pos )                             ||
317            ALLOC( parser->private_dict, parser->private_len ) )
318         goto Fail;
319
320       parser->private_len = 0;
321       for (;;)
322       {
323         error = read_pfb_tag( stream, &tag, &size );
324         if ( error || tag != 0x8002 )
325         {
326           error = T1_Err_Ok;
327           break;
328         }
329
330         if ( FILE_Read( parser->private_dict + parser->private_len, size ) )
331           goto Fail;
332
333         parser->private_len += size;
334       }
335     }
336     else
337     {
338       /* we have already `loaded' the whole PFA font file into memory; */
339       /* if this is a memory resource, allocate a new block to hold    */
340       /* the private dict. Otherwise, simply overwrite into the base   */
341       /* dictionary block in the heap.                                 */
342
343       /* first of all, look at the `eexec' keyword */
344       FT_Byte*  cur   = parser->base_dict;
345       FT_Byte*  limit = cur + parser->base_len;
346       FT_Byte   c;
347
348
349       for (;;)
350       {
351         c = cur[0];
352         if ( c == 'e' && cur + 9 < limit )  /* 9 = 5 letters for `eexec' + */
353                                             /* newline + 4 chars           */
354         {
355           if ( cur[1] == 'e' && cur[2] == 'x' &&
356                cur[3] == 'e' && cur[4] == 'c' )
357           {
358             cur += 6; /* we skip the newling after the `eexec' */
359
360             /* XXX: Some fonts use DOS-linefeeds, i.e. \r\n; we need to */
361             /*      skip the extra \n if we find it                     */
362             if ( cur[0] == '\n' )
363               cur++;
364
365             break;
366           }
367         }
368         cur++;
369         if ( cur >= limit )
370         {
371           FT_ERROR(( "T1_Get_Private_Dict:" ));
372           FT_ERROR(( " could not find `eexec' keyword\n" ));
373           error = T1_Err_Invalid_File_Format;
374           goto Exit;
375         }
376       }
377
378       /* now determine where to write the _encrypted_ binary private  */
379       /* dictionary.  We overwrite the base dictionary for disk-based */
380       /* resources and allocate a new block otherwise                 */
381
382       size = (FT_Long)( parser->base_len - ( cur - parser->base_dict ) );
383
384       if ( parser->in_memory )
385       {
386         /* note that we allocate one more byte to put a terminating `0' */
387         if ( ALLOC( parser->private_dict, size + 1 ) )
388           goto Fail;
389         parser->private_len = size;
390       }
391       else
392       {
393         parser->single_block = 1;
394         parser->private_dict = parser->base_dict;
395         parser->private_len  = size;
396         parser->base_dict    = 0;
397         parser->base_len     = 0;
398       }
399
400       /* now determine whether the private dictionary is encoded in binary */
401       /* or hexadecimal ASCII format -- decode it accordingly              */
402
403       /* we need to access the next 4 bytes (after the final \r following */
404       /* the `eexec' keyword); if they all are hexadecimal digits, then   */
405       /* we have a case of ASCII storage                                  */
406
407       if ( ( hexa_value( cur[0] ) | hexa_value( cur[1] ) |
408              hexa_value( cur[2] ) | hexa_value( cur[3] ) ) < 0 )
409
410         /* binary encoding -- `simply' copy the private dict */
411         MEM_Copy( parser->private_dict, cur, size );
412
413       else
414       {
415         /* ASCII hexadecimal encoding */
416
417         FT_Byte*  write;
418         FT_Int    count;
419
420
421         write = parser->private_dict;
422         count = 0;
423
424         for ( ;cur < limit; cur++ )
425         {
426           int  hex1;
427
428
429           /* check for newline */
430           if ( cur[0] == '\r' || cur[0] == '\n' )
431             continue;
432
433           /* exit if we have a non-hexadecimal digit that isn't a newline */
434           hex1 = hexa_value( cur[0] );
435           if ( hex1 < 0 || cur + 1 >= limit )
436             break;
437
438           /* otherwise, store byte */
439           *write++ = (FT_Byte)( ( hex1 << 4 ) | hexa_value( cur[1] ) );
440           count++;
441           cur++;
442         }
443
444         /* put a safeguard */
445         parser->private_len = (FT_Int)( write - parser->private_dict );
446         *write++ = 0;
447       }
448     }
449
450     /* we now decrypt the encoded binary private dictionary */
451     psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
452     parser->root.base = parser->private_dict;
453     parser->root.cursor = parser->private_dict;
454     parser->root.limit  = parser->root.cursor + parser->private_len;
455
456   Fail:
457   Exit:
458     return error;
459   }
460
461
462 /* END */