~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/freetype/src/type1/t1parse.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  t1parse.c                                                              */
 
4
/*                                                                         */
 
5
/*    Type 1 parser (body).                                                */
 
6
/*                                                                         */
 
7
/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2008, 2009 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
 
70
  read_pfb_tag( FT_Stream   stream,
 
71
                FT_UShort  *atag,
 
72
                FT_ULong   *asize )
 
73
  {
 
74
    FT_Error   error;
 
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
 
98
  check_type1_format( FT_Stream    stream,
 
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
 
 
135
  FT_LOCAL_DEF( FT_Error )
 
136
  T1_New_Parser( T1_Parser      parser,
 
137
                 FT_Stream      stream,
 
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 Type1 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 )
 
244
  T1_Finalize_Parser( T1_Parser  parser )
 
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
 
 
260
  FT_LOCAL_DEF( FT_Error )
 
261
  T1_Get_Private_Dict( T1_Parser      parser,
 
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
    /* replace the four random bytes at the beginning with whitespace */
 
471
    parser->private_dict[0] = ' ';
 
472
    parser->private_dict[1] = ' ';
 
473
    parser->private_dict[2] = ' ';
 
474
    parser->private_dict[3] = ' ';
 
475
 
 
476
    parser->root.base   = parser->private_dict;
 
477
    parser->root.cursor = parser->private_dict;
 
478
    parser->root.limit  = parser->root.cursor + parser->private_len;
 
479
 
 
480
  Fail:
 
481
  Exit:
 
482
    return error;
 
483
  }
 
484
 
 
485
 
 
486
/* END */