1 /***************************************************************************/ 2 /* */ 3 /* afmparse.c */ 4 /* */ 5 /* AFM parser (body). */ 6 /* */ 7 /* Copyright 2006-2010, 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 #include <ft2build.h> 19 #include FT_FREETYPE_H 20 #include FT_INTERNAL_POSTSCRIPT_AUX_H 21 22 #include "afmparse.h" 23 #include "psconv.h" 24 25 #include "psauxerr.h" 26 27 28 /***************************************************************************/ 29 /* */ 30 /* AFM_Stream */ 31 /* */ 32 /* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib. */ 33 /* */ 34 /* */ 35 36 enum 37 { 38 AFM_STREAM_STATUS_NORMAL, 39 AFM_STREAM_STATUS_EOC, 40 AFM_STREAM_STATUS_EOL, 41 AFM_STREAM_STATUS_EOF 42 }; 43 44 45 typedef struct AFM_StreamRec_ 46 { 47 FT_Byte* cursor; 48 FT_Byte* base; 49 FT_Byte* limit; 50 51 FT_Int status; 52 53 } AFM_StreamRec; 54 55 56 #ifndef EOF 57 #define EOF -1 58 #endif 59 60 61 /* this works because empty lines are ignored */ 62 #define AFM_IS_NEWLINE( ch ) ( (ch) == '\r' || (ch) == '\n' ) 63 64 #define AFM_IS_EOF( ch ) ( (ch) == EOF || (ch) == '\x1a' ) 65 #define AFM_IS_SPACE( ch ) ( (ch) == ' ' || (ch) == '\t' ) 66 67 /* column separator; there is no `column' in the spec actually */ 68 #define AFM_IS_SEP( ch ) ( (ch) == ';' ) 69 70 #define AFM_GETC() \ 71 ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \ 72 : EOF ) 73 74 #define AFM_STREAM_KEY_BEGIN( stream ) \ 75 (char*)( (stream)->cursor - 1 ) 76 77 #define AFM_STREAM_KEY_LEN( stream, key ) \ 78 ( (char*)(stream)->cursor - key - 1 ) 79 80 #define AFM_STATUS_EOC( stream ) \ 81 ( (stream)->status >= AFM_STREAM_STATUS_EOC ) 82 83 #define AFM_STATUS_EOL( stream ) \ 84 ( (stream)->status >= AFM_STREAM_STATUS_EOL ) 85 86 #define AFM_STATUS_EOF( stream ) \ 87 ( (stream)->status >= AFM_STREAM_STATUS_EOF ) 88 89 90 static int 91 afm_stream_skip_spaces( AFM_Stream stream ) 92 { 93 int ch = 0; /* make stupid compiler happy */ 94 95 96 if ( AFM_STATUS_EOC( stream ) ) 97 return ';'; 98 99 while ( 1 ) 100 { 101 ch = AFM_GETC(); 102 if ( !AFM_IS_SPACE( ch ) ) 103 break; 104 } 105 106 if ( AFM_IS_NEWLINE( ch ) ) 107 stream->status = AFM_STREAM_STATUS_EOL; 108 else if ( AFM_IS_SEP( ch ) ) 109 stream->status = AFM_STREAM_STATUS_EOC; 110 else if ( AFM_IS_EOF( ch ) ) 111 stream->status = AFM_STREAM_STATUS_EOF; 112 113 return ch; 114 } 115 116 117 /* read a key or value in current column */ 118 static char* 119 afm_stream_read_one( AFM_Stream stream ) 120 { 121 char* str; 122 int ch; 123 124 125 afm_stream_skip_spaces( stream ); 126 if ( AFM_STATUS_EOC( stream ) ) 127 return NULL; 128 129 str = AFM_STREAM_KEY_BEGIN( stream ); 130 131 while ( 1 ) 132 { 133 ch = AFM_GETC(); 134 if ( AFM_IS_SPACE( ch ) ) 135 break; 136 else if ( AFM_IS_NEWLINE( ch ) ) 137 { 138 stream->status = AFM_STREAM_STATUS_EOL; 139 break; 140 } 141 else if ( AFM_IS_SEP( ch ) ) 142 { 143 stream->status = AFM_STREAM_STATUS_EOC; 144 break; 145 } 146 else if ( AFM_IS_EOF( ch ) ) 147 { 148 stream->status = AFM_STREAM_STATUS_EOF; 149 break; 150 } 151 } 152 153 return str; 154 } 155 156 157 /* read a string (i.e., read to EOL) */ 158 static char* 159 afm_stream_read_string( AFM_Stream stream ) 160 { 161 char* str; 162 int ch; 163 164 165 afm_stream_skip_spaces( stream ); 166 if ( AFM_STATUS_EOL( stream ) ) 167 return NULL; 168 169 str = AFM_STREAM_KEY_BEGIN( stream ); 170 171 /* scan to eol */ 172 while ( 1 ) 173 { 174 ch = AFM_GETC(); 175 if ( AFM_IS_NEWLINE( ch ) ) 176 { 177 stream->status = AFM_STREAM_STATUS_EOL; 178 break; 179 } 180 else if ( AFM_IS_EOF( ch ) ) 181 { 182 stream->status = AFM_STREAM_STATUS_EOF; 183 break; 184 } 185 } 186 187 return str; 188 } 189 190 191 /*************************************************************************/ 192 /* */ 193 /* AFM_Parser */ 194 /* */ 195 /* */ 196 197 /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */ 198 typedef enum AFM_Token_ 199 { 200 AFM_TOKEN_ASCENDER, 201 AFM_TOKEN_AXISLABEL, 202 AFM_TOKEN_AXISTYPE, 203 AFM_TOKEN_B, 204 AFM_TOKEN_BLENDAXISTYPES, 205 AFM_TOKEN_BLENDDESIGNMAP, 206 AFM_TOKEN_BLENDDESIGNPOSITIONS, 207 AFM_TOKEN_C, 208 AFM_TOKEN_CC, 209 AFM_TOKEN_CH, 210 AFM_TOKEN_CAPHEIGHT, 211 AFM_TOKEN_CHARWIDTH, 212 AFM_TOKEN_CHARACTERSET, 213 AFM_TOKEN_CHARACTERS, 214 AFM_TOKEN_DESCENDER, 215 AFM_TOKEN_ENCODINGSCHEME, 216 AFM_TOKEN_ENDAXIS, 217 AFM_TOKEN_ENDCHARMETRICS, 218 AFM_TOKEN_ENDCOMPOSITES, 219 AFM_TOKEN_ENDDIRECTION, 220 AFM_TOKEN_ENDFONTMETRICS, 221 AFM_TOKEN_ENDKERNDATA, 222 AFM_TOKEN_ENDKERNPAIRS, 223 AFM_TOKEN_ENDTRACKKERN, 224 AFM_TOKEN_ESCCHAR, 225 AFM_TOKEN_FAMILYNAME, 226 AFM_TOKEN_FONTBBOX, 227 AFM_TOKEN_FONTNAME, 228 AFM_TOKEN_FULLNAME, 229 AFM_TOKEN_ISBASEFONT, 230 AFM_TOKEN_ISCIDFONT, 231 AFM_TOKEN_ISFIXEDPITCH, 232 AFM_TOKEN_ISFIXEDV, 233 AFM_TOKEN_ITALICANGLE, 234 AFM_TOKEN_KP, 235 AFM_TOKEN_KPH, 236 AFM_TOKEN_KPX, 237 AFM_TOKEN_KPY, 238 AFM_TOKEN_L, 239 AFM_TOKEN_MAPPINGSCHEME, 240 AFM_TOKEN_METRICSSETS, 241 AFM_TOKEN_N, 242 AFM_TOKEN_NOTICE, 243 AFM_TOKEN_PCC, 244 AFM_TOKEN_STARTAXIS, 245 AFM_TOKEN_STARTCHARMETRICS, 246 AFM_TOKEN_STARTCOMPOSITES, 247 AFM_TOKEN_STARTDIRECTION, 248 AFM_TOKEN_STARTFONTMETRICS, 249 AFM_TOKEN_STARTKERNDATA, 250 AFM_TOKEN_STARTKERNPAIRS, 251 AFM_TOKEN_STARTKERNPAIRS0, 252 AFM_TOKEN_STARTKERNPAIRS1, 253 AFM_TOKEN_STARTTRACKKERN, 254 AFM_TOKEN_STDHW, 255 AFM_TOKEN_STDVW, 256 AFM_TOKEN_TRACKKERN, 257 AFM_TOKEN_UNDERLINEPOSITION, 258 AFM_TOKEN_UNDERLINETHICKNESS, 259 AFM_TOKEN_VV, 260 AFM_TOKEN_VVECTOR, 261 AFM_TOKEN_VERSION, 262 AFM_TOKEN_W, 263 AFM_TOKEN_W0, 264 AFM_TOKEN_W0X, 265 AFM_TOKEN_W0Y, 266 AFM_TOKEN_W1, 267 AFM_TOKEN_W1X, 268 AFM_TOKEN_W1Y, 269 AFM_TOKEN_WX, 270 AFM_TOKEN_WY, 271 AFM_TOKEN_WEIGHT, 272 AFM_TOKEN_WEIGHTVECTOR, 273 AFM_TOKEN_XHEIGHT, 274 N_AFM_TOKENS, 275 AFM_TOKEN_UNKNOWN 276 277 } AFM_Token; 278 279 280 static const char* const afm_key_table[N_AFM_TOKENS] = 281 { 282 "Ascender", 283 "AxisLabel", 284 "AxisType", 285 "B", 286 "BlendAxisTypes", 287 "BlendDesignMap", 288 "BlendDesignPositions", 289 "C", 290 "CC", 291 "CH", 292 "CapHeight", 293 "CharWidth", 294 "CharacterSet", 295 "Characters", 296 "Descender", 297 "EncodingScheme", 298 "EndAxis", 299 "EndCharMetrics", 300 "EndComposites", 301 "EndDirection", 302 "EndFontMetrics", 303 "EndKernData", 304 "EndKernPairs", 305 "EndTrackKern", 306 "EscChar", 307 "FamilyName", 308 "FontBBox", 309 "FontName", 310 "FullName", 311 "IsBaseFont", 312 "IsCIDFont", 313 "IsFixedPitch", 314 "IsFixedV", 315 "ItalicAngle", 316 "KP", 317 "KPH", 318 "KPX", 319 "KPY", 320 "L", 321 "MappingScheme", 322 "MetricsSets", 323 "N", 324 "Notice", 325 "PCC", 326 "StartAxis", 327 "StartCharMetrics", 328 "StartComposites", 329 "StartDirection", 330 "StartFontMetrics", 331 "StartKernData", 332 "StartKernPairs", 333 "StartKernPairs0", 334 "StartKernPairs1", 335 "StartTrackKern", 336 "StdHW", 337 "StdVW", 338 "TrackKern", 339 "UnderlinePosition", 340 "UnderlineThickness", 341 "VV", 342 "VVector", 343 "Version", 344 "W", 345 "W0", 346 "W0X", 347 "W0Y", 348 "W1", 349 "W1X", 350 "W1Y", 351 "WX", 352 "WY", 353 "Weight", 354 "WeightVector", 355 "XHeight" 356 }; 357 358 359 /* 360 * `afm_parser_read_vals' and `afm_parser_next_key' provide 361 * high-level operations to an AFM_Stream. The rest of the 362 * parser functions should use them without accessing the 363 * AFM_Stream directly. 364 */ 365 366 FT_LOCAL_DEF( FT_Int ) 367 afm_parser_read_vals( AFM_Parser parser, 368 AFM_Value vals, 369 FT_UInt n ) 370 { 371 AFM_Stream stream = parser->stream; 372 char* str; 373 FT_UInt i; 374 375 376 if ( n > AFM_MAX_ARGUMENTS ) 377 return 0; 378 379 for ( i = 0; i < n; i++ ) 380 { 381 FT_Offset len; 382 AFM_Value val = vals + i; 383 384 385 if ( val->type == AFM_VALUE_TYPE_STRING ) 386 str = afm_stream_read_string( stream ); 387 else 388 str = afm_stream_read_one( stream ); 389 390 if ( !str ) 391 break; 392 393 len = AFM_STREAM_KEY_LEN( stream, str ); 394 395 switch ( val->type ) 396 { 397 case AFM_VALUE_TYPE_STRING: 398 case AFM_VALUE_TYPE_NAME: 399 { 400 FT_Memory memory = parser->memory; 401 FT_Error error; 402 403 404 if ( !FT_QALLOC( val->u.s, len + 1 ) ) 405 { 406 ft_memcpy( val->u.s, str, len ); 407 val->u.s[len] = '\0'; 408 } 409 } 410 break; 411 412 case AFM_VALUE_TYPE_FIXED: 413 val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str, 414 (FT_Byte*)str + len, 0 ); 415 break; 416 417 case AFM_VALUE_TYPE_INTEGER: 418 val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str, 419 (FT_Byte*)str + len ); 420 break; 421 422 case AFM_VALUE_TYPE_BOOL: 423 val->u.b = FT_BOOL( len == 4 && 424 !ft_strncmp( str, "true", 4 ) ); 425 break; 426 427 case AFM_VALUE_TYPE_INDEX: 428 if ( parser->get_index ) 429 val->u.i = parser->get_index( str, len, parser->user_data ); 430 else 431 val->u.i = 0; 432 break; 433 } 434 } 435 436 return i; 437 } 438 439 440 FT_LOCAL_DEF( char* ) 441 afm_parser_next_key( AFM_Parser parser, 442 FT_Bool line, 443 FT_Offset* len ) 444 { 445 AFM_Stream stream = parser->stream; 446 char* key = 0; /* make stupid compiler happy */ 447 448 449 if ( line ) 450 { 451 while ( 1 ) 452 { 453 /* skip current line */ 454 if ( !AFM_STATUS_EOL( stream ) ) 455 afm_stream_read_string( stream ); 456 457 stream->status = AFM_STREAM_STATUS_NORMAL; 458 key = afm_stream_read_one( stream ); 459 460 /* skip empty line */ 461 if ( !key && 462 !AFM_STATUS_EOF( stream ) && 463 AFM_STATUS_EOL( stream ) ) 464 continue; 465 466 break; 467 } 468 } 469 else 470 { 471 while ( 1 ) 472 { 473 /* skip current column */ 474 while ( !AFM_STATUS_EOC( stream ) ) 475 afm_stream_read_one( stream ); 476 477 stream->status = AFM_STREAM_STATUS_NORMAL; 478 key = afm_stream_read_one( stream ); 479 480 /* skip empty column */ 481 if ( !key && 482 !AFM_STATUS_EOF( stream ) && 483 AFM_STATUS_EOC( stream ) ) 484 continue; 485 486 break; 487 } 488 } 489 490 if ( len ) 491 *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key ) 492 : 0; 493 494 return key; 495 } 496 497 498 static AFM_Token 499 afm_tokenize( const char* key, 500 FT_Offset len ) 501 { 502 int n; 503 504 505 for ( n = 0; n < N_AFM_TOKENS; n++ ) 506 { 507 if ( *( afm_key_table[n] ) == *key ) 508 { 509 for ( ; n < N_AFM_TOKENS; n++ ) 510 { 511 if ( *( afm_key_table[n] ) != *key ) 512 return AFM_TOKEN_UNKNOWN; 513 514 if ( ft_strncmp( afm_key_table[n], key, len ) == 0 ) 515 return (AFM_Token) n; 516 } 517 } 518 } 519 520 return AFM_TOKEN_UNKNOWN; 521 } 522 523 524 FT_LOCAL_DEF( FT_Error ) 525 afm_parser_init( AFM_Parser parser, 526 FT_Memory memory, 527 FT_Byte* base, 528 FT_Byte* limit ) 529 { 530 AFM_Stream stream = NULL; 531 FT_Error error; 532 533 534 if ( FT_NEW( stream ) ) 535 return error; 536 537 stream->cursor = stream->base = base; 538 stream->limit = limit; 539 540 /* don't skip the first line during the first call */ 541 stream->status = AFM_STREAM_STATUS_EOL; 542 543 parser->memory = memory; 544 parser->stream = stream; 545 parser->FontInfo = NULL; 546 parser->get_index = NULL; 547 548 return PSaux_Err_Ok; 549 } 550 551 552 FT_LOCAL( void ) 553 afm_parser_done( AFM_Parser parser ) 554 { 555 FT_Memory memory = parser->memory; 556 557 558 FT_FREE( parser->stream ); 559 } 560 561 562 FT_LOCAL_DEF( FT_Error ) 563 afm_parser_read_int( AFM_Parser parser, 564 FT_Int* aint ) 565 { 566 AFM_ValueRec val; 567 568 569 val.type = AFM_VALUE_TYPE_INTEGER; 570 571 if ( afm_parser_read_vals( parser, &val, 1 ) == 1 ) 572 { 573 *aint = val.u.i; 574 575 return PSaux_Err_Ok; 576 } 577 else 578 return PSaux_Err_Syntax_Error; 579 } 580 581 582 static FT_Error 583 afm_parse_track_kern( AFM_Parser parser ) 584 { 585 AFM_FontInfo fi = parser->FontInfo; 586 AFM_TrackKern tk; 587 char* key; 588 FT_Offset len; 589 int n = -1; 590 591 592 if ( afm_parser_read_int( parser, &fi->NumTrackKern ) ) 593 goto Fail; 594 595 if ( fi->NumTrackKern ) 596 { 597 FT_Memory memory = parser->memory; 598 FT_Error error; 599 600 601 if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) ) 602 return error; 603 } 604 605 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 606 { 607 AFM_ValueRec shared_vals[5]; 608 609 610 switch ( afm_tokenize( key, len ) ) 611 { 612 case AFM_TOKEN_TRACKKERN: 613 n++; 614 615 if ( n >= fi->NumTrackKern ) 616 goto Fail; 617 618 tk = fi->TrackKerns + n; 619 620 shared_vals[0].type = AFM_VALUE_TYPE_INTEGER; 621 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 622 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 623 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 624 shared_vals[4].type = AFM_VALUE_TYPE_FIXED; 625 if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) 626 goto Fail; 627 628 tk->degree = shared_vals[0].u.i; 629 tk->min_ptsize = shared_vals[1].u.f; 630 tk->min_kern = shared_vals[2].u.f; 631 tk->max_ptsize = shared_vals[3].u.f; 632 tk->max_kern = shared_vals[4].u.f; 633 634 break; 635 636 case AFM_TOKEN_ENDTRACKKERN: 637 case AFM_TOKEN_ENDKERNDATA: 638 case AFM_TOKEN_ENDFONTMETRICS: 639 fi->NumTrackKern = n + 1; 640 return PSaux_Err_Ok; 641 642 case AFM_TOKEN_UNKNOWN: 643 break; 644 645 default: 646 goto Fail; 647 } 648 } 649 650 Fail: 651 return PSaux_Err_Syntax_Error; 652 } 653 654 655 #undef KERN_INDEX 656 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) 657 658 659 /* compare two kerning pairs */ 660 FT_CALLBACK_DEF( int ) 661 afm_compare_kern_pairs( const void* a, 662 const void* b ) 663 { 664 AFM_KernPair kp1 = (AFM_KernPair)a; 665 AFM_KernPair kp2 = (AFM_KernPair)b; 666 667 FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 ); 668 FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 ); 669 670 671 if ( index1 > index2 ) 672 return 1; 673 else if ( index1 < index2 ) 674 return -1; 675 else 676 return 0; 677 } 678 679 680 static FT_Error 681 afm_parse_kern_pairs( AFM_Parser parser ) 682 { 683 AFM_FontInfo fi = parser->FontInfo; 684 AFM_KernPair kp; 685 char* key; 686 FT_Offset len; 687 int n = -1; 688 689 690 if ( afm_parser_read_int( parser, &fi->NumKernPair ) ) 691 goto Fail; 692 693 if ( fi->NumKernPair ) 694 { 695 FT_Memory memory = parser->memory; 696 FT_Error error; 697 698 699 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) 700 return error; 701 } 702 703 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 704 { 705 AFM_Token token = afm_tokenize( key, len ); 706 707 708 switch ( token ) 709 { 710 case AFM_TOKEN_KP: 711 case AFM_TOKEN_KPX: 712 case AFM_TOKEN_KPY: 713 { 714 FT_Int r; 715 AFM_ValueRec shared_vals[4]; 716 717 718 n++; 719 720 if ( n >= fi->NumKernPair ) 721 goto Fail; 722 723 kp = fi->KernPairs + n; 724 725 shared_vals[0].type = AFM_VALUE_TYPE_INDEX; 726 shared_vals[1].type = AFM_VALUE_TYPE_INDEX; 727 shared_vals[2].type = AFM_VALUE_TYPE_INTEGER; 728 shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; 729 r = afm_parser_read_vals( parser, shared_vals, 4 ); 730 if ( r < 3 ) 731 goto Fail; 732 733 kp->index1 = shared_vals[0].u.i; 734 kp->index2 = shared_vals[1].u.i; 735 if ( token == AFM_TOKEN_KPY ) 736 { 737 kp->x = 0; 738 kp->y = shared_vals[2].u.i; 739 } 740 else 741 { 742 kp->x = shared_vals[2].u.i; 743 kp->y = ( token == AFM_TOKEN_KP && r == 4 ) 744 ? shared_vals[3].u.i : 0; 745 } 746 } 747 break; 748 749 case AFM_TOKEN_ENDKERNPAIRS: 750 case AFM_TOKEN_ENDKERNDATA: 751 case AFM_TOKEN_ENDFONTMETRICS: 752 fi->NumKernPair = n + 1; 753 ft_qsort( fi->KernPairs, fi->NumKernPair, 754 sizeof ( AFM_KernPairRec ), 755 afm_compare_kern_pairs ); 756 return PSaux_Err_Ok; 757 758 case AFM_TOKEN_UNKNOWN: 759 break; 760 761 default: 762 goto Fail; 763 } 764 } 765 766 Fail: 767 return PSaux_Err_Syntax_Error; 768 } 769 770 771 static FT_Error 772 afm_parse_kern_data( AFM_Parser parser ) 773 { 774 FT_Error error; 775 char* key; 776 FT_Offset len; 777 778 779 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 780 { 781 switch ( afm_tokenize( key, len ) ) 782 { 783 case AFM_TOKEN_STARTTRACKKERN: 784 error = afm_parse_track_kern( parser ); 785 if ( error ) 786 return error; 787 break; 788 789 case AFM_TOKEN_STARTKERNPAIRS: 790 case AFM_TOKEN_STARTKERNPAIRS0: 791 error = afm_parse_kern_pairs( parser ); 792 if ( error ) 793 return error; 794 break; 795 796 case AFM_TOKEN_ENDKERNDATA: 797 case AFM_TOKEN_ENDFONTMETRICS: 798 return PSaux_Err_Ok; 799 800 case AFM_TOKEN_UNKNOWN: 801 break; 802 803 default: 804 goto Fail; 805 } 806 } 807 808 Fail: 809 return PSaux_Err_Syntax_Error; 810 } 811 812 813 static FT_Error 814 afm_parser_skip_section( AFM_Parser parser, 815 FT_UInt n, 816 AFM_Token end_section ) 817 { 818 char* key; 819 FT_Offset len; 820 821 822 while ( n-- > 0 ) 823 { 824 key = afm_parser_next_key( parser, 1, NULL ); 825 if ( !key ) 826 goto Fail; 827 } 828 829 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 830 { 831 AFM_Token token = afm_tokenize( key, len ); 832 833 834 if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS ) 835 return PSaux_Err_Ok; 836 } 837 838 Fail: 839 return PSaux_Err_Syntax_Error; 840 } 841 842 843 FT_LOCAL_DEF( FT_Error ) 844 afm_parser_parse( AFM_Parser parser ) 845 { 846 FT_Memory memory = parser->memory; 847 AFM_FontInfo fi = parser->FontInfo; 848 FT_Error error = PSaux_Err_Syntax_Error; 849 char* key; 850 FT_Offset len; 851 FT_Int metrics_sets = 0; 852 853 854 if ( !fi ) 855 return PSaux_Err_Invalid_Argument; 856 857 key = afm_parser_next_key( parser, 1, &len ); 858 if ( !key || len != 16 || 859 ft_strncmp( key, "StartFontMetrics", 16 ) != 0 ) 860 return PSaux_Err_Unknown_File_Format; 861 862 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 863 { 864 AFM_ValueRec shared_vals[4]; 865 866 867 switch ( afm_tokenize( key, len ) ) 868 { 869 case AFM_TOKEN_METRICSSETS: 870 if ( afm_parser_read_int( parser, &metrics_sets ) ) 871 goto Fail; 872 873 if ( metrics_sets != 0 && metrics_sets != 2 ) 874 { 875 error = PSaux_Err_Unimplemented_Feature; 876 877 goto Fail; 878 } 879 break; 880 881 case AFM_TOKEN_ISCIDFONT: 882 shared_vals[0].type = AFM_VALUE_TYPE_BOOL; 883 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 884 goto Fail; 885 886 fi->IsCIDFont = shared_vals[0].u.b; 887 break; 888 889 case AFM_TOKEN_FONTBBOX: 890 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 891 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 892 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 893 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 894 if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 ) 895 goto Fail; 896 897 fi->FontBBox.xMin = shared_vals[0].u.f; 898 fi->FontBBox.yMin = shared_vals[1].u.f; 899 fi->FontBBox.xMax = shared_vals[2].u.f; 900 fi->FontBBox.yMax = shared_vals[3].u.f; 901 break; 902 903 case AFM_TOKEN_ASCENDER: 904 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 905 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 906 goto Fail; 907 908 fi->Ascender = shared_vals[0].u.f; 909 break; 910 911 case AFM_TOKEN_DESCENDER: 912 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 913 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 914 goto Fail; 915 916 fi->Descender = shared_vals[0].u.f; 917 break; 918 919 case AFM_TOKEN_STARTCHARMETRICS: 920 { 921 FT_Int n = 0; 922 923 924 if ( afm_parser_read_int( parser, &n ) ) 925 goto Fail; 926 927 error = afm_parser_skip_section( parser, n, 928 AFM_TOKEN_ENDCHARMETRICS ); 929 if ( error ) 930 return error; 931 } 932 break; 933 934 case AFM_TOKEN_STARTKERNDATA: 935 error = afm_parse_kern_data( parser ); 936 if ( error ) 937 goto Fail; 938 /* fall through since we only support kern data */ 939 940 case AFM_TOKEN_ENDFONTMETRICS: 941 return PSaux_Err_Ok; 942 943 default: 944 break; 945 } 946 } 947 948 Fail: 949 FT_FREE( fi->TrackKerns ); 950 fi->NumTrackKern = 0; 951 952 FT_FREE( fi->KernPairs ); 953 fi->NumKernPair = 0; 954 955 fi->IsCIDFont = 0; 956 957 return error; 958 } 959 960 961 /* END */ 962