1 /***************************************************************************/ 2 /* */ 3 /* afmparse.c */ 4 /* */ 5 /* AFM parser (body). */ 6 /* */ 7 /* Copyright 2006, 2007, 2008, 2009, 2010 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 /* is this correct? */ 635 if ( tk->degree < 0 && tk->min_kern > 0 ) 636 tk->min_kern = -tk->min_kern; 637 break; 638 639 case AFM_TOKEN_ENDTRACKKERN: 640 case AFM_TOKEN_ENDKERNDATA: 641 case AFM_TOKEN_ENDFONTMETRICS: 642 fi->NumTrackKern = n + 1; 643 return PSaux_Err_Ok; 644 645 case AFM_TOKEN_UNKNOWN: 646 break; 647 648 default: 649 goto Fail; 650 } 651 } 652 653 Fail: 654 return PSaux_Err_Syntax_Error; 655 } 656 657 658 #undef KERN_INDEX 659 #define KERN_INDEX( g1, g2 ) ( ( (FT_ULong)g1 << 16 ) | g2 ) 660 661 662 /* compare two kerning pairs */ 663 FT_CALLBACK_DEF( int ) 664 afm_compare_kern_pairs( const void* a, 665 const void* b ) 666 { 667 AFM_KernPair kp1 = (AFM_KernPair)a; 668 AFM_KernPair kp2 = (AFM_KernPair)b; 669 670 FT_ULong index1 = KERN_INDEX( kp1->index1, kp1->index2 ); 671 FT_ULong index2 = KERN_INDEX( kp2->index1, kp2->index2 ); 672 673 674 if ( index1 > index2 ) 675 return 1; 676 else if ( index1 < index2 ) 677 return -1; 678 else 679 return 0; 680 } 681 682 683 static FT_Error 684 afm_parse_kern_pairs( AFM_Parser parser ) 685 { 686 AFM_FontInfo fi = parser->FontInfo; 687 AFM_KernPair kp; 688 char* key; 689 FT_Offset len; 690 int n = -1; 691 692 693 if ( afm_parser_read_int( parser, &fi->NumKernPair ) ) 694 goto Fail; 695 696 if ( fi->NumKernPair ) 697 { 698 FT_Memory memory = parser->memory; 699 FT_Error error; 700 701 702 if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) ) 703 return error; 704 } 705 706 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 707 { 708 AFM_Token token = afm_tokenize( key, len ); 709 710 711 switch ( token ) 712 { 713 case AFM_TOKEN_KP: 714 case AFM_TOKEN_KPX: 715 case AFM_TOKEN_KPY: 716 { 717 FT_Int r; 718 AFM_ValueRec shared_vals[4]; 719 720 721 n++; 722 723 if ( n >= fi->NumKernPair ) 724 goto Fail; 725 726 kp = fi->KernPairs + n; 727 728 shared_vals[0].type = AFM_VALUE_TYPE_INDEX; 729 shared_vals[1].type = AFM_VALUE_TYPE_INDEX; 730 shared_vals[2].type = AFM_VALUE_TYPE_INTEGER; 731 shared_vals[3].type = AFM_VALUE_TYPE_INTEGER; 732 r = afm_parser_read_vals( parser, shared_vals, 4 ); 733 if ( r < 3 ) 734 goto Fail; 735 736 kp->index1 = shared_vals[0].u.i; 737 kp->index2 = shared_vals[1].u.i; 738 if ( token == AFM_TOKEN_KPY ) 739 { 740 kp->x = 0; 741 kp->y = shared_vals[2].u.i; 742 } 743 else 744 { 745 kp->x = shared_vals[2].u.i; 746 kp->y = ( token == AFM_TOKEN_KP && r == 4 ) 747 ? shared_vals[3].u.i : 0; 748 } 749 } 750 break; 751 752 case AFM_TOKEN_ENDKERNPAIRS: 753 case AFM_TOKEN_ENDKERNDATA: 754 case AFM_TOKEN_ENDFONTMETRICS: 755 fi->NumKernPair = n + 1; 756 ft_qsort( fi->KernPairs, fi->NumKernPair, 757 sizeof( AFM_KernPairRec ), 758 afm_compare_kern_pairs ); 759 return PSaux_Err_Ok; 760 761 case AFM_TOKEN_UNKNOWN: 762 break; 763 764 default: 765 goto Fail; 766 } 767 } 768 769 Fail: 770 return PSaux_Err_Syntax_Error; 771 } 772 773 774 static FT_Error 775 afm_parse_kern_data( AFM_Parser parser ) 776 { 777 FT_Error error; 778 char* key; 779 FT_Offset len; 780 781 782 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 783 { 784 switch ( afm_tokenize( key, len ) ) 785 { 786 case AFM_TOKEN_STARTTRACKKERN: 787 error = afm_parse_track_kern( parser ); 788 if ( error ) 789 return error; 790 break; 791 792 case AFM_TOKEN_STARTKERNPAIRS: 793 case AFM_TOKEN_STARTKERNPAIRS0: 794 error = afm_parse_kern_pairs( parser ); 795 if ( error ) 796 return error; 797 break; 798 799 case AFM_TOKEN_ENDKERNDATA: 800 case AFM_TOKEN_ENDFONTMETRICS: 801 return PSaux_Err_Ok; 802 803 case AFM_TOKEN_UNKNOWN: 804 break; 805 806 default: 807 goto Fail; 808 } 809 } 810 811 Fail: 812 return PSaux_Err_Syntax_Error; 813 } 814 815 816 static FT_Error 817 afm_parser_skip_section( AFM_Parser parser, 818 FT_UInt n, 819 AFM_Token end_section ) 820 { 821 char* key; 822 FT_Offset len; 823 824 825 while ( n-- > 0 ) 826 { 827 key = afm_parser_next_key( parser, 1, NULL ); 828 if ( !key ) 829 goto Fail; 830 } 831 832 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 833 { 834 AFM_Token token = afm_tokenize( key, len ); 835 836 837 if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS ) 838 return PSaux_Err_Ok; 839 } 840 841 Fail: 842 return PSaux_Err_Syntax_Error; 843 } 844 845 846 FT_LOCAL_DEF( FT_Error ) 847 afm_parser_parse( AFM_Parser parser ) 848 { 849 FT_Memory memory = parser->memory; 850 AFM_FontInfo fi = parser->FontInfo; 851 FT_Error error = PSaux_Err_Syntax_Error; 852 char* key; 853 FT_Offset len; 854 FT_Int metrics_sets = 0; 855 856 857 if ( !fi ) 858 return PSaux_Err_Invalid_Argument; 859 860 key = afm_parser_next_key( parser, 1, &len ); 861 if ( !key || len != 16 || 862 ft_strncmp( key, "StartFontMetrics", 16 ) != 0 ) 863 return PSaux_Err_Unknown_File_Format; 864 865 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 866 { 867 AFM_ValueRec shared_vals[4]; 868 869 870 switch ( afm_tokenize( key, len ) ) 871 { 872 case AFM_TOKEN_METRICSSETS: 873 if ( afm_parser_read_int( parser, &metrics_sets ) ) 874 goto Fail; 875 876 if ( metrics_sets != 0 && metrics_sets != 2 ) 877 { 878 error = PSaux_Err_Unimplemented_Feature; 879 880 goto Fail; 881 } 882 break; 883 884 case AFM_TOKEN_ISCIDFONT: 885 shared_vals[0].type = AFM_VALUE_TYPE_BOOL; 886 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 887 goto Fail; 888 889 fi->IsCIDFont = shared_vals[0].u.b; 890 break; 891 892 case AFM_TOKEN_FONTBBOX: 893 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 894 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 895 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 896 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 897 if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 ) 898 goto Fail; 899 900 fi->FontBBox.xMin = shared_vals[0].u.f; 901 fi->FontBBox.yMin = shared_vals[1].u.f; 902 fi->FontBBox.xMax = shared_vals[2].u.f; 903 fi->FontBBox.yMax = shared_vals[3].u.f; 904 break; 905 906 case AFM_TOKEN_ASCENDER: 907 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 908 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 909 goto Fail; 910 911 fi->Ascender = shared_vals[0].u.f; 912 break; 913 914 case AFM_TOKEN_DESCENDER: 915 shared_vals[0].type = AFM_VALUE_TYPE_FIXED; 916 if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 ) 917 goto Fail; 918 919 fi->Descender = shared_vals[0].u.f; 920 break; 921 922 case AFM_TOKEN_STARTCHARMETRICS: 923 { 924 FT_Int n = 0; 925 926 927 if ( afm_parser_read_int( parser, &n ) ) 928 goto Fail; 929 930 error = afm_parser_skip_section( parser, n, 931 AFM_TOKEN_ENDCHARMETRICS ); 932 if ( error ) 933 return error; 934 } 935 break; 936 937 case AFM_TOKEN_STARTKERNDATA: 938 error = afm_parse_kern_data( parser ); 939 if ( error ) 940 goto Fail; 941 /* fall through since we only support kern data */ 942 943 case AFM_TOKEN_ENDFONTMETRICS: 944 return PSaux_Err_Ok; 945 946 default: 947 break; 948 } 949 } 950 951 Fail: 952 FT_FREE( fi->TrackKerns ); 953 fi->NumTrackKern = 0; 954 955 FT_FREE( fi->KernPairs ); 956 fi->NumKernPair = 0; 957 958 fi->IsCIDFont = 0; 959 960 return error; 961 } 962 963 964 /* END */ 965