OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* t1parse.c */ | 3 /* t1parse.c */ |
4 /* */ | 4 /* */ |
5 /* Type 1 parser (body). */ | 5 /* Type 1 parser (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 1996-2005, 2008, 2009, 2012-2014 by */ | 7 /* Copyright 1996-2015 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 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 */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 T1_New_Parser( T1_Parser parser, | 136 T1_New_Parser( T1_Parser parser, |
137 FT_Stream stream, | 137 FT_Stream stream, |
138 FT_Memory memory, | 138 FT_Memory memory, |
139 PSAux_Service psaux ) | 139 PSAux_Service psaux ) |
140 { | 140 { |
141 FT_Error error; | 141 FT_Error error; |
142 FT_UShort tag; | 142 FT_UShort tag; |
143 FT_ULong size; | 143 FT_ULong size; |
144 | 144 |
145 | 145 |
146 psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); | 146 psaux->ps_parser_funcs->init( &parser->root, NULL, NULL, memory ); |
147 | 147 |
148 parser->stream = stream; | 148 parser->stream = stream; |
149 parser->base_len = 0; | 149 parser->base_len = 0; |
150 parser->base_dict = 0; | 150 parser->base_dict = NULL; |
151 parser->private_len = 0; | 151 parser->private_len = 0; |
152 parser->private_dict = 0; | 152 parser->private_dict = NULL; |
153 parser->in_pfb = 0; | 153 parser->in_pfb = 0; |
154 parser->in_memory = 0; | 154 parser->in_memory = 0; |
155 parser->single_block = 0; | 155 parser->single_block = 0; |
156 | 156 |
157 /* check the header format */ | 157 /* check the header format */ |
158 error = check_type1_format( stream, "%!PS-AdobeFont", 14 ); | 158 error = check_type1_format( stream, "%!PS-AdobeFont", 14 ); |
159 if ( error ) | 159 if ( error ) |
160 { | 160 { |
161 if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) | 161 if ( FT_ERR_NEQ( error, Unknown_File_Format ) ) |
162 goto Exit; | 162 goto Exit; |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 FT_Error error = FT_Err_Ok; | 266 FT_Error error = FT_Err_Ok; |
267 FT_ULong size; | 267 FT_ULong size; |
268 | 268 |
269 | 269 |
270 if ( parser->in_pfb ) | 270 if ( parser->in_pfb ) |
271 { | 271 { |
272 /* in the case of the PFB format, the private dictionary can be */ | 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 */ | 273 /* made of several segments. We thus first read the number of */ |
274 /* segments to compute the total size of the private dictionary */ | 274 /* segments to compute the total size of the private dictionary */ |
275 /* then re-read them into memory. */ | 275 /* then re-read them into memory. */ |
276 FT_Long start_pos = FT_STREAM_POS(); | 276 FT_ULong start_pos = FT_STREAM_POS(); |
277 FT_UShort tag; | 277 FT_UShort tag; |
278 | 278 |
279 | 279 |
280 parser->private_len = 0; | 280 parser->private_len = 0; |
281 for (;;) | 281 for (;;) |
282 { | 282 { |
283 error = read_pfb_tag( stream, &tag, &size ); | 283 error = read_pfb_tag( stream, &tag, &size ); |
284 if ( error ) | 284 if ( error ) |
285 goto Fail; | 285 goto Fail; |
286 | 286 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
327 else | 327 else |
328 { | 328 { |
329 /* We have already `loaded' the whole PFA font file into memory; */ | 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 */ | 330 /* if this is a memory resource, allocate a new block to hold */ |
331 /* the private dict. Otherwise, simply overwrite into the base */ | 331 /* the private dict. Otherwise, simply overwrite into the base */ |
332 /* dictionary block in the heap. */ | 332 /* dictionary block in the heap. */ |
333 | 333 |
334 /* first of all, look at the `eexec' keyword */ | 334 /* first of all, look at the `eexec' keyword */ |
335 FT_Byte* cur = parser->base_dict; | 335 FT_Byte* cur = parser->base_dict; |
336 FT_Byte* limit = cur + parser->base_len; | 336 FT_Byte* limit = cur + parser->base_len; |
337 FT_Byte c; | |
338 FT_Pointer pos_lf; | 337 FT_Pointer pos_lf; |
339 FT_Bool test_cr; | 338 FT_Bool test_cr; |
340 | 339 |
341 | 340 |
342 Again: | 341 Again: |
343 for (;;) | 342 for (;;) |
344 { | 343 { |
345 c = cur[0]; | 344 if ( cur[0] == 'e' && |
346 if ( c == 'e' && cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ | 345 cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */ |
347 /* whitespace + 4 chars */ | 346 /* whitespace + 4 chars */ |
348 { | 347 { |
349 if ( cur[1] == 'e' && | 348 if ( cur[1] == 'e' && |
350 cur[2] == 'x' && | 349 cur[2] == 'x' && |
351 cur[3] == 'e' && | 350 cur[3] == 'e' && |
352 cur[4] == 'c' ) | 351 cur[4] == 'c' ) |
353 break; | 352 break; |
354 } | 353 } |
355 cur++; | 354 cur++; |
356 if ( cur >= limit ) | 355 if ( cur >= limit ) |
357 { | 356 { |
358 FT_ERROR(( "T1_Get_Private_Dict:" | 357 FT_ERROR(( "T1_Get_Private_Dict:" |
359 " could not find `eexec' keyword\n" )); | 358 " could not find `eexec' keyword\n" )); |
360 error = FT_THROW( Invalid_File_Format ); | 359 error = FT_THROW( Invalid_File_Format ); |
361 goto Exit; | 360 goto Exit; |
362 } | 361 } |
363 } | 362 } |
364 | 363 |
365 /* check whether `eexec' was real -- it could be in a comment */ | 364 /* check whether `eexec' was real -- it could be in a comment */ |
366 /* or string (as e.g. in u003043t.gsf from ghostscript) */ | 365 /* or string (as e.g. in u003043t.gsf from ghostscript) */ |
367 | 366 |
368 parser->root.cursor = parser->base_dict; | 367 parser->root.cursor = parser->base_dict; |
369 /* set limit to `eexec' + whitespace + 4 characters */ | 368 /* set limit to `eexec' + whitespace + 4 characters */ |
370 parser->root.limit = cur + 10; | 369 parser->root.limit = cur + 10; |
371 | 370 |
372 cur = parser->root.cursor; | 371 cur = parser->root.cursor; |
373 limit = parser->root.limit; | 372 limit = parser->root.limit; |
374 | 373 |
375 while ( cur < limit ) | 374 while ( cur < limit ) |
376 { | 375 { |
377 if ( *cur == 'e' && ft_strncmp( (char*)cur, "eexec", 5 ) == 0 ) | 376 if ( cur[0] == 'e' && |
378 goto Found; | 377 cur + 5 < limit ) |
| 378 { |
| 379 if ( cur[1] == 'e' && |
| 380 cur[2] == 'x' && |
| 381 cur[3] == 'e' && |
| 382 cur[4] == 'c' ) |
| 383 goto Found; |
| 384 } |
379 | 385 |
380 T1_Skip_PS_Token( parser ); | 386 T1_Skip_PS_Token( parser ); |
381 if ( parser->root.error ) | 387 if ( parser->root.error ) |
382 break; | 388 break; |
383 T1_Skip_Spaces ( parser ); | 389 T1_Skip_Spaces ( parser ); |
384 cur = parser->root.cursor; | 390 cur = parser->root.cursor; |
385 } | 391 } |
386 | 392 |
387 /* we haven't found the correct `eexec'; go back and continue */ | 393 /* we haven't found the correct `eexec'; go back and continue */ |
388 /* searching */ | 394 /* searching */ |
389 | 395 |
390 cur = limit; | 396 cur = limit; |
391 limit = parser->base_dict + parser->base_len; | 397 limit = parser->base_dict + parser->base_len; |
| 398 |
| 399 if ( cur >= limit ) |
| 400 { |
| 401 FT_ERROR(( "T1_Get_Private_Dict:" |
| 402 " premature end in private dictionary\n" )); |
| 403 error = FT_THROW( Invalid_File_Format ); |
| 404 goto Exit; |
| 405 } |
| 406 |
392 goto Again; | 407 goto Again; |
393 | 408 |
394 /* now determine where to write the _encrypted_ binary private */ | 409 /* now determine where to write the _encrypted_ binary private */ |
395 /* dictionary. We overwrite the base dictionary for disk-based */ | 410 /* dictionary. We overwrite the base dictionary for disk-based */ |
396 /* resources and allocate a new block otherwise */ | 411 /* resources and allocate a new block otherwise */ |
397 | 412 |
398 Found: | 413 Found: |
399 parser->root.limit = parser->base_dict + parser->base_len; | 414 parser->root.limit = parser->base_dict + parser->base_len; |
400 | 415 |
401 T1_Skip_PS_Token( parser ); | 416 T1_Skip_PS_Token( parser ); |
402 cur = parser->root.cursor; | 417 cur = parser->root.cursor; |
403 limit = parser->root.limit; | 418 limit = parser->root.limit; |
404 | 419 |
405 /* According to the Type 1 spec, the first cipher byte must not be */ | 420 /* According to the Type 1 spec, the first cipher byte must not be */ |
406 /* an ASCII whitespace character code (blank, tab, carriage return */ | 421 /* an ASCII whitespace character code (blank, tab, carriage return */ |
407 /* or line feed). We have seen Type 1 fonts with two line feed */ | 422 /* or line feed). We have seen Type 1 fonts with two line feed */ |
408 /* characters... So skip now all whitespace character codes. */ | 423 /* characters... So skip now all whitespace character codes. */ |
409 /* */ | 424 /* */ |
410 /* On the other hand, Adobe's Type 1 parser handles fonts just */ | 425 /* On the other hand, Adobe's Type 1 parser handles fonts just */ |
411 /* fine that are violating this limitation, so we add a heuristic */ | 426 /* fine that are violating this limitation, so we add a heuristic */ |
412 /* test to stop at \r only if it is not used for EOL. */ | 427 /* test to stop at \r only if it is not used for EOL. */ |
413 | 428 |
414 pos_lf = ft_memchr( cur, '\n', limit - cur ); | 429 pos_lf = ft_memchr( cur, '\n', (size_t)( limit - cur ) ); |
415 test_cr = FT_BOOL( !pos_lf || | 430 test_cr = FT_BOOL( !pos_lf || |
416 pos_lf > ft_memchr( cur, '\r', limit - cur ) ); | 431 pos_lf > ft_memchr( cur, |
| 432 '\r', |
| 433 (size_t)( limit - cur ) ) ); |
417 | 434 |
418 while ( cur < limit && | 435 while ( cur < limit && |
419 ( *cur == ' ' || | 436 ( *cur == ' ' || |
420 *cur == '\t' || | 437 *cur == '\t' || |
421 (test_cr && *cur == '\r' ) || | 438 (test_cr && *cur == '\r' ) || |
422 *cur == '\n' ) ) | 439 *cur == '\n' ) ) |
423 ++cur; | 440 ++cur; |
424 if ( cur >= limit ) | 441 if ( cur >= limit ) |
425 { | 442 { |
426 FT_ERROR(( "T1_Get_Private_Dict:" | 443 FT_ERROR(( "T1_Get_Private_Dict:" |
427 " `eexec' not properly terminated\n" )); | 444 " `eexec' not properly terminated\n" )); |
428 error = FT_THROW( Invalid_File_Format ); | 445 error = FT_THROW( Invalid_File_Format ); |
429 goto Exit; | 446 goto Exit; |
430 } | 447 } |
431 | 448 |
432 size = (FT_ULong)( parser->base_len - ( cur - parser->base_dict ) ); | 449 size = parser->base_len - (FT_ULong)( cur - parser->base_dict ); |
433 | 450 |
434 if ( parser->in_memory ) | 451 if ( parser->in_memory ) |
435 { | 452 { |
436 /* note that we allocate one more byte to put a terminating `0' */ | 453 /* note that we allocate one more byte to put a terminating `0' */ |
437 if ( FT_ALLOC( parser->private_dict, size + 1 ) ) | 454 if ( FT_ALLOC( parser->private_dict, size + 1 ) ) |
438 goto Fail; | 455 goto Fail; |
439 parser->private_len = size; | 456 parser->private_len = size; |
440 } | 457 } |
441 else | 458 else |
442 { | 459 { |
443 parser->single_block = 1; | 460 parser->single_block = 1; |
444 parser->private_dict = parser->base_dict; | 461 parser->private_dict = parser->base_dict; |
445 parser->private_len = size; | 462 parser->private_len = size; |
446 parser->base_dict = 0; | 463 parser->base_dict = NULL; |
447 parser->base_len = 0; | 464 parser->base_len = 0; |
448 } | 465 } |
449 | 466 |
450 /* now determine whether the private dictionary is encoded in binary */ | 467 /* now determine whether the private dictionary is encoded in binary */ |
451 /* or hexadecimal ASCII format -- decode it accordingly */ | 468 /* or hexadecimal ASCII format -- decode it accordingly */ |
452 | 469 |
453 /* we need to access the next 4 bytes (after the final whitespace */ | 470 /* we need to access the next 4 bytes (after the final whitespace */ |
454 /* following the `eexec' keyword); if they all are hexadecimal */ | 471 /* following the `eexec' keyword); if they all are hexadecimal */ |
455 /* digits, then we have a case of ASCII storage */ | 472 /* digits, then we have a case of ASCII storage */ |
456 | 473 |
457 if ( cur + 3 < limit && | 474 if ( cur + 3 < limit && |
458 ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && | 475 ft_isxdigit( cur[0] ) && ft_isxdigit( cur[1] ) && |
459 ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) | 476 ft_isxdigit( cur[2] ) && ft_isxdigit( cur[3] ) ) |
460 { | 477 { |
461 /* ASCII hexadecimal encoding */ | 478 /* ASCII hexadecimal encoding */ |
462 FT_Long len; | 479 FT_ULong len; |
463 | 480 |
464 | 481 |
465 parser->root.cursor = cur; | 482 parser->root.cursor = cur; |
466 (void)psaux->ps_parser_funcs->to_bytes( &parser->root, | 483 (void)psaux->ps_parser_funcs->to_bytes( &parser->root, |
467 parser->private_dict, | 484 parser->private_dict, |
468 parser->private_len, | 485 parser->private_len, |
469 &len, | 486 &len, |
470 0 ); | 487 0 ); |
471 parser->private_len = len; | 488 parser->private_len = len; |
472 | 489 |
(...skipping 26 matching lines...) Expand all Loading... |
499 parser->root.cursor = parser->private_dict; | 516 parser->root.cursor = parser->private_dict; |
500 parser->root.limit = parser->root.cursor + parser->private_len; | 517 parser->root.limit = parser->root.cursor + parser->private_len; |
501 | 518 |
502 Fail: | 519 Fail: |
503 Exit: | 520 Exit: |
504 return error; | 521 return error; |
505 } | 522 } |
506 | 523 |
507 | 524 |
508 /* END */ | 525 /* END */ |
OLD | NEW |