zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
t1parse.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* t1parse.c */
4 /* */
5 /* Type 1 parser (body). */
6 /* */
7 /* Copyright 1996-2005, 2008, 2009, 2012 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_STREAM_H
39 #include FT_INTERNAL_POSTSCRIPT_AUX_H
40 
41 #include "t1parse.h"
42 
43 #include "t1errors.h"
44 
45 
46  /*************************************************************************/
47  /* */
48  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
49  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
50  /* messages during execution. */
51  /* */
52 #undef FT_COMPONENT
53 #define FT_COMPONENT trace_t1parse
54 
55 
56  /*************************************************************************/
57  /*************************************************************************/
58  /*************************************************************************/
59  /***** *****/
60  /***** INPUT STREAM PARSER *****/
61  /***** *****/
62  /*************************************************************************/
63  /*************************************************************************/
64  /*************************************************************************/
65 
66 
67  /* see Adobe Technical Note 5040.Download_Fonts.pdf */
68 
69  static FT_Error
71  FT_UShort *atag,
72  FT_ULong *asize )
73  {
75  FT_UShort tag;
76  FT_ULong size;
77 
78 
79  *atag = 0;
80  *asize = 0;
81 
82  if ( !FT_READ_USHORT( tag ) )
83  {
84  if ( tag == 0x8001U || tag == 0x8002U )
85  {
86  if ( !FT_READ_ULONG_LE( size ) )
87  *asize = size;
88  }
89 
90  *atag = tag;
91  }
92 
93  return error;
94  }
95 
96 
97  static FT_Error
99  const char* header_string,
100  size_t header_length )
101  {
102  FT_Error error;
103  FT_UShort tag;
104  FT_ULong dummy;
105 
106 
107  if ( FT_STREAM_SEEK( 0 ) )
108  goto Exit;
109 
110  error = read_pfb_tag( stream, &tag, &dummy );
111  if ( error )
112  goto Exit;
113 
114  /* We assume that the first segment in a PFB is always encoded as */
115  /* text. This might be wrong (and the specification doesn't insist */
116  /* on that), but we have never seen a counterexample. */
117  if ( tag != 0x8001U && FT_STREAM_SEEK( 0 ) )
118  goto Exit;
119 
120  if ( !FT_FRAME_ENTER( header_length ) )
121  {
122  error = T1_Err_Ok;
123 
124  if ( ft_memcmp( stream->cursor, header_string, header_length ) != 0 )
125  error = T1_Err_Unknown_File_Format;
126 
127  FT_FRAME_EXIT();
128  }
129 
130  Exit:
131  return error;
132  }
133 
134 
138  FT_Memory memory,
139  PSAux_Service psaux )
140  {
141  FT_Error error;
142  FT_UShort tag;
143  FT_ULong size;
144 
145 
146  psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
147 
148  parser->stream = stream;
149  parser->base_len = 0;
150  parser->base_dict = 0;
151  parser->private_len = 0;
152  parser->private_dict = 0;
153  parser->in_pfb = 0;
154  parser->in_memory = 0;
155  parser->single_block = 0;
156 
157  /* check the header format */
158  error = check_type1_format( stream, "%!PS-AdobeFont", 14 );
159  if ( error )
160  {
161  if ( error != T1_Err_Unknown_File_Format )
162  goto Exit;
163 
164  error = check_type1_format( stream, "%!FontType", 10 );
165  if ( error )
166  {
167  FT_TRACE2(( " not a Type 1 font\n" ));
168  goto Exit;
169  }
170  }
171 
172  /******************************************************************/
173  /* */
174  /* Here a short summary of what is going on: */
175  /* */
176  /* When creating a new Type 1 parser, we try to locate and load */
177  /* the base dictionary if this is possible (i.e., for PFB */
178  /* files). Otherwise, we load the whole font into memory. */
179  /* */
180  /* When `loading' the base dictionary, we only setup pointers */
181  /* in the case of a memory-based stream. Otherwise, we */
182  /* allocate and load the base dictionary in it. */
183  /* */
184  /* parser->in_pfb is set if we are in a binary (`.pfb') font. */
185  /* parser->in_memory is set if we have a memory stream. */
186  /* */
187 
188  /* try to compute the size of the base dictionary; */
189  /* look for a Postscript binary file tag, i.e., 0x8001 */
190  if ( FT_STREAM_SEEK( 0L ) )
191  goto Exit;
192 
193  error = read_pfb_tag( stream, &tag, &size );
194  if ( error )
195  goto Exit;
196 
197  if ( tag != 0x8001U )
198  {
199  /* assume that this is a PFA file for now; an error will */
200  /* be produced later when more things are checked */
201  if ( FT_STREAM_SEEK( 0L ) )
202  goto Exit;
203  size = stream->size;
204  }
205  else
206  parser->in_pfb = 1;
207 
208  /* now, try to load `size' bytes of the `base' dictionary we */
209  /* found previously */
210 
211  /* if it is a memory-based resource, set up pointers */
212  if ( !stream->read )
213  {
214  parser->base_dict = (FT_Byte*)stream->base + stream->pos;
215  parser->base_len = size;
216  parser->in_memory = 1;
217 
218  /* check that the `size' field is valid */
219  if ( FT_STREAM_SKIP( size ) )
220  goto Exit;
221  }
222  else
223  {
224  /* read segment in memory -- this is clumsy, but so does the format */
225  if ( FT_ALLOC( parser->base_dict, size ) ||
226  FT_STREAM_READ( parser->base_dict, size ) )
227  goto Exit;
228  parser->base_len = size;
229  }
230 
231  parser->root.base = parser->base_dict;
232  parser->root.cursor = parser->base_dict;
233  parser->root.limit = parser->root.cursor + parser->base_len;
234 
235  Exit:
236  if ( error && !parser->in_memory )
237  FT_FREE( parser->base_dict );
238 
239  return error;
240  }
241 
242 
243  FT_LOCAL_DEF( void )
245  {
246  FT_Memory memory = parser->root.memory;
247 
248 
249  /* always free the private dictionary */
250  FT_FREE( parser->private_dict );
251 
252  /* free the base dictionary only when we have a disk stream */
253  if ( !parser->in_memory )
254  FT_FREE( parser->base_dict );
255 
256  parser->root.funcs.done( &parser->root );
257  }
258 
259 
262  PSAux_Service psaux )
263  {
264  FT_Stream stream = parser->stream;
265  FT_Memory memory = parser->root.memory;
266  FT_Error error = T1_Err_Ok;
267  FT_ULong size;
268 
269 
270  if ( parser->in_pfb )
271  {
272  /* in the case of the PFB format, the private dictionary can be */
273  /* made of several segments. We thus first read the number of */
274  /* segments to compute the total size of the private dictionary */
275  /* then re-read them into memory. */
276  FT_Long start_pos = FT_STREAM_POS();
277  FT_UShort tag;
278 
279 
280  parser->private_len = 0;
281  for (;;)
282  {
283  error = read_pfb_tag( stream, &tag, &size );
284  if ( error )
285  goto Fail;
286 
287  if ( tag != 0x8002U )
288  break;
289 
290  parser->private_len += size;
291 
292  if ( FT_STREAM_SKIP( size ) )
293  goto Fail;
294  }
295 
296  /* Check that we have a private dictionary there */
297  /* and allocate private dictionary buffer */
298  if ( parser->private_len == 0 )
299  {
300  FT_ERROR(( "T1_Get_Private_Dict:"
301  " invalid private dictionary section\n" ));
302  error = T1_Err_Invalid_File_Format;
303  goto Fail;
304  }
305 
306  if ( FT_STREAM_SEEK( start_pos ) ||
307  FT_ALLOC( parser->private_dict, parser->private_len ) )
308  goto Fail;
309 
310  parser->private_len = 0;
311  for (;;)
312  {
313  error = read_pfb_tag( stream, &tag, &size );
314  if ( error || tag != 0x8002U )
315  {
316  error = T1_Err_Ok;
317  break;
318  }
319 
320  if ( FT_STREAM_READ( parser->private_dict + parser->private_len,
321  size ) )
322  goto Fail;
323 
324  parser->private_len += size;
325  }
326  }
327  else
328  {
329  /* We have already `loaded' the whole PFA font file into memory; */
330  /* if this is a memory resource, allocate a new block to hold */
331  /* the private dict. Otherwise, simply overwrite into the base */
332  /* dictionary block in the heap. */
333 
334  /* first of all, look at the `eexec' keyword */
335  FT_Byte* cur = parser->base_dict;
336  FT_Byte* limit = cur + parser->base_len;
337  FT_Byte c;
338 
339 
340  Again:
341  for (;;)
342  {
343  c = cur[0];
344  if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
345  /* newline + 4 chars */
346  {
347  if ( cur[1] == 'e' &&
348  cur[2] == 'x' &&
349  cur[3] == 'e' &&
350  cur[4] == 'c' )
351  break;
352  }
353  cur++;
354  if ( cur >= limit )
355  {
356  FT_ERROR(( "T1_Get_Private_Dict:"
357  " could not find `eexec' keyword\n" ));
358  error = T1_Err_Invalid_File_Format;
359  goto Exit;
360  }
361  }
362 
363  /* check whether `eexec' was real -- it could be in a comment */
364  /* or string (as e.g. in u003043t.gsf from ghostscript) */
365 
366  parser->root.cursor = parser->base_dict;
367  parser->root.limit = cur + 9;
368 
369  cur = parser->root.cursor;
370  limit = parser->root.limit;
371 
372  while ( cur < limit )
373  {
374  if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 )
375  goto Found;
376 
377  T1_Skip_PS_Token( parser );
378  if ( parser->root.error )
379  break;
380  T1_Skip_Spaces ( parser );
381  cur = parser->root.cursor;
382  }
383 
384  /* we haven't found the correct `eexec'; go back and continue */
385  /* searching */
386 
387  cur = limit;
388  limit = parser->base_dict + parser->base_len;
389  goto Again;
390 
391  /* now determine where to write the _encrypted_ binary private */
392  /* dictionary. We overwrite the base dictionary for disk-based */
393  /* resources and allocate a new block otherwise */
394 
395  Found:
396  parser->root.limit = parser->base_dict + parser->base_len;
397 
398  T1_Skip_PS_Token( parser );
399  cur = parser->root.cursor;
400 
401  /* according to the Type1 spec, the first cipher byte must not be */
402  /* an ASCII whitespace character code (blank, tab, carriage return */
403  /* or line feed). We have seen Type 1 fonts with two line feed */
404  /* characters... So skip now all whitespace character codes. */
405  while ( cur < limit &&
406  ( *cur == ' ' ||
407  *cur == '\t' ||
408  *cur == '\r' ||
409  *cur == '\n' ) )
410  ++cur;
411  if ( cur >= limit )
412  {
413  FT_ERROR(( "T1_Get_Private_Dict:"
414  " `eexec' not properly terminated\n" ));
415  error = T1_Err_Invalid_File_Format;
416  goto Exit;
417  }
418 
419  size = parser->base_len - ( cur - parser->base_dict );
420 
421  if ( parser->in_memory )
422  {
423  /* note that we allocate one more byte to put a terminating `0' */
424  if ( FT_ALLOC( parser->private_dict, size + 1 ) )
425  goto Fail;
426  parser->private_len = size;
427  }
428  else
429  {
430  parser->single_block = 1;
431  parser->private_dict = parser->base_dict;
432  parser->private_len = size;
433  parser->base_dict = 0;
434  parser->base_len = 0;
435  }
436 
437  /* now determine whether the private dictionary is encoded in binary */
438  /* or hexadecimal ASCII format -- decode it accordingly */
439 
440  /* we need to access the next 4 bytes (after the final \r following */
441  /* the `eexec' keyword); if they all are hexadecimal digits, then */
442  /* we have a case of ASCII storage */
443 
444  if ( ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) &&
445  ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) )
446  {
447  /* ASCII hexadecimal encoding */
448  FT_Long len;
449 
450 
451  parser->root.cursor = cur;
452  (void)psaux->ps_parser_funcs->to_bytes( &parser->root,
453  parser->private_dict,
454  parser->private_len,
455  &len,
456  0 );
457  parser->private_len = len;
458 
459  /* put a safeguard */
460  parser->private_dict[len] = '\0';
461  }
462  else
463  /* binary encoding -- copy the private dict */
464  FT_MEM_MOVE( parser->private_dict, cur, size );
465  }
466 
467  /* we now decrypt the encoded binary private dictionary */
468  psaux->t1_decrypt( parser->private_dict, parser->private_len, 55665U );
469 
470  if ( parser->private_len < 4 )
471  {
472  FT_ERROR(( "T1_Get_Private_Dict:"
473  " invalid private dictionary section\n" ));
474  error = T1_Err_Invalid_File_Format;
475  goto Fail;
476  }
477 
478  /* replace the four random bytes at the beginning with whitespace */
479  parser->private_dict[0] = ' ';
480  parser->private_dict[1] = ' ';
481  parser->private_dict[2] = ' ';
482  parser->private_dict[3] = ' ';
483 
484  parser->root.base = parser->private_dict;
485  parser->root.cursor = parser->private_dict;
486  parser->root.limit = parser->root.cursor + parser->private_len;
487 
488  Fail:
489  Exit:
490  return error;
491  }
492 
493 
494 /* END */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
T1_Finalize_Parser(T1_Parser parser)
Definition: t1parse.c:244
int FT_Error
Definition: fttypes.h:296
signed long FT_Long
Definition: fttypes.h:238
#define ft_strncmp
Definition: ftstdlib.h:88
unsigned long FT_ULong
Definition: fttypes.h:249
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
T1_New_Parser(T1_Parser parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux)
Definition: t1parse.c:136
static FT_Error check_type1_format(FT_Stream stream, const char *header_string, size_t header_length)
Definition: t1parse.c:98
#define T1_Skip_Spaces(p)
Definition: t1parse.h:94
unsigned char * cursor
Definition: ftsystem.h:333
GLuint GLuint stream
Definition: glew.h:6573
#define ft_isxdigit(x)
Definition: ftobjs.h:100
#define FT_READ_USHORT(var)
Definition: ftstream.h:316
GLenum GLsizei len
Definition: glew.h:7035
if(!yyg->yy_init)
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
unsigned char FT_Byte
Definition: fttypes.h:150
FT_Memory memory
Definition: ftsystem.h:332
#define FT_FREE(ptr)
Definition: ftmemory.h:286
#define FT_STREAM_SKIP(distance)
Definition: ftstream.h:499
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
FT_Error error
Definition: cffdrivr.c:407
#define T1_Skip_PS_Token(p)
Definition: t1parse.h:95
static FT_Error read_pfb_tag(FT_Stream stream, FT_UShort *atag, FT_ULong *asize)
Definition: t1parse.c:70
const GLfloat * c
Definition: glew.h:14913
#define FT_TRACE2(varformat)
Definition: ftdebug.h:159
GLint limit
Definition: glew.h:11829
#define FT_READ_ULONG_LE(var)
Definition: ftstream.h:325
T1_Get_Private_Dict(T1_Parser parser, PSAux_Service psaux)
Definition: t1parse.c:261
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
#define FT_FRAME_EXIT()
Definition: ftstream.h:521
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:496
#define FT_STREAM_POS()
Definition: ftstream.h:493
#define ft_memcmp
Definition: ftstdlib.h:80
#define FT_FRAME_ENTER(size)
Definition: ftstream.h:517
FT_BEGIN_HEADER struct T1_ParserRec_ * T1_Parser
unsigned short FT_UShort
Definition: fttypes.h:205
#define FT_MEM_MOVE(dest, source, count)
Definition: ftmemory.h:205
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:502
GLsizei size
Definition: gl2ext.h:1467