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