1 /***************************************************************************/ 2 /* */ 3 /* afmparse.c */ 4 /* */ 5 /* AFM parser (body). */ 6 /* */ 7 /* Copyright 2006-2010, 2012, 2013 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_DEBUG_H 21 #include FT_INTERNAL_POSTSCRIPT_AUX_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 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* 120 afm_stream_read_one( AFM_Stream stream ) 121 { 122 char* str; 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 int ch = AFM_GETC(); 134 135 136 if ( AFM_IS_SPACE( ch ) ) 137 break; 138 else if ( AFM_IS_NEWLINE( ch ) ) 139 { 140 stream->status = AFM_STREAM_STATUS_EOL; 141 break; 142 } 143 else if ( AFM_IS_SEP( ch ) ) 144 { 145 stream->status = AFM_STREAM_STATUS_EOC; 146 break; 147 } 148 else if ( AFM_IS_EOF( ch ) ) 149 { 150 stream->status = AFM_STREAM_STATUS_EOF; 151 break; 152 } 153 } 154 155 return str; 156 } 157 158 159 /* read a string (i.e., read to EOL) */ 160 static char* 161 afm_stream_read_string( AFM_Stream stream ) 162 { 163 char* str; 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 int ch = AFM_GETC(); 176 177 178 if ( AFM_IS_NEWLINE( ch ) ) 179 { 180 stream->status = AFM_STREAM_STATUS_EOL; 181 break; 182 } 183 else if ( AFM_IS_EOF( ch ) ) 184 { 185 stream->status = AFM_STREAM_STATUS_EOF; 186 break; 187 } 188 } 189 190 return str; 191 } 192 193 194 /*************************************************************************/ 195 /* */ 196 /* AFM_Parser */ 197 /* */ 198 /* */ 199 200 /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */ 201 typedef enum AFM_Token_ 202 { 203 AFM_TOKEN_ASCENDER, 204 AFM_TOKEN_AXISLABEL, 205 AFM_TOKEN_AXISTYPE, 206 AFM_TOKEN_B, 207 AFM_TOKEN_BLENDAXISTYPES, 208 AFM_TOKEN_BLENDDESIGNMAP, 209 AFM_TOKEN_BLENDDESIGNPOSITIONS, 210 AFM_TOKEN_C, 211 AFM_TOKEN_CC, 212 AFM_TOKEN_CH, 213 AFM_TOKEN_CAPHEIGHT, 214 AFM_TOKEN_CHARWIDTH, 215 AFM_TOKEN_CHARACTERSET, 216 AFM_TOKEN_CHARACTERS, 217 AFM_TOKEN_DESCENDER, 218 AFM_TOKEN_ENCODINGSCHEME, 219 AFM_TOKEN_ENDAXIS, 220 AFM_TOKEN_ENDCHARMETRICS, 221 AFM_TOKEN_ENDCOMPOSITES, 222 AFM_TOKEN_ENDDIRECTION, 223 AFM_TOKEN_ENDFONTMETRICS, 224 AFM_TOKEN_ENDKERNDATA, 225 AFM_TOKEN_ENDKERNPAIRS, 226 AFM_TOKEN_ENDTRACKKERN, 227 AFM_TOKEN_ESCCHAR, 228 AFM_TOKEN_FAMILYNAME, 229 AFM_TOKEN_FONTBBOX, 230 AFM_TOKEN_FONTNAME, 231 AFM_TOKEN_FULLNAME, 232 AFM_TOKEN_ISBASEFONT, 233 AFM_TOKEN_ISCIDFONT, 234 AFM_TOKEN_ISFIXEDPITCH, 235 AFM_TOKEN_ISFIXEDV, 236 AFM_TOKEN_ITALICANGLE, 237 AFM_TOKEN_KP, 238 AFM_TOKEN_KPH, 239 AFM_TOKEN_KPX, 240 AFM_TOKEN_KPY, 241 AFM_TOKEN_L, 242 AFM_TOKEN_MAPPINGSCHEME, 243 AFM_TOKEN_METRICSSETS, 244 AFM_TOKEN_N, 245 AFM_TOKEN_NOTICE, 246 AFM_TOKEN_PCC, 247 AFM_TOKEN_STARTAXIS, 248 AFM_TOKEN_STARTCHARMETRICS, 249 AFM_TOKEN_STARTCOMPOSITES, 250 AFM_TOKEN_STARTDIRECTION, 251 AFM_TOKEN_STARTFONTMETRICS, 252 AFM_TOKEN_STARTKERNDATA, 253 AFM_TOKEN_STARTKERNPAIRS, 254 AFM_TOKEN_STARTKERNPAIRS0, 255 AFM_TOKEN_STARTKERNPAIRS1, 256 AFM_TOKEN_STARTTRACKKERN, 257 AFM_TOKEN_STDHW, 258 AFM_TOKEN_STDVW, 259 AFM_TOKEN_TRACKKERN, 260 AFM_TOKEN_UNDERLINEPOSITION, 261 AFM_TOKEN_UNDERLINETHICKNESS, 262 AFM_TOKEN_VV, 263 AFM_TOKEN_VVECTOR, 264 AFM_TOKEN_VERSION, 265 AFM_TOKEN_W, 266 AFM_TOKEN_W0, 267 AFM_TOKEN_W0X, 268 AFM_TOKEN_W0Y, 269 AFM_TOKEN_W1, 270 AFM_TOKEN_W1X, 271 AFM_TOKEN_W1Y, 272 AFM_TOKEN_WX, 273 AFM_TOKEN_WY, 274 AFM_TOKEN_WEIGHT, 275 AFM_TOKEN_WEIGHTVECTOR, 276 AFM_TOKEN_XHEIGHT, 277 N_AFM_TOKENS, 278 AFM_TOKEN_UNKNOWN 279 280 } AFM_Token; 281 282 283 static const char* const afm_key_table[N_AFM_TOKENS] = 284 { 285 "Ascender", 286 "AxisLabel", 287 "AxisType", 288 "B", 289 "BlendAxisTypes", 290 "BlendDesignMap", 291 "BlendDesignPositions", 292 "C", 293 "CC", 294 "CH", 295 "CapHeight", 296 "CharWidth", 297 "CharacterSet", 298 "Characters", 299 "Descender", 300 "EncodingScheme", 301 "EndAxis", 302 "EndCharMetrics", 303 "EndComposites", 304 "EndDirection", 305 "EndFontMetrics", 306 "EndKernData", 307 "EndKernPairs", 308 "EndTrackKern", 309 "EscChar", 310 "FamilyName", 311 "FontBBox", 312 "FontName", 313 "FullName", 314 "IsBaseFont", 315 "IsCIDFont", 316 "IsFixedPitch", 317 "IsFixedV", 318 "ItalicAngle", 319 "KP", 320 "KPH", 321 "KPX", 322 "KPY", 323 "L", 324 "MappingScheme", 325 "MetricsSets", 326 "N", 327 "Notice", 328 "PCC", 329 "StartAxis", 330 "StartCharMetrics", 331 "StartComposites", 332 "StartDirection", 333 "StartFontMetrics", 334 "StartKernData", 335 "StartKernPairs", 336 "StartKernPairs0", 337 "StartKernPairs1", 338 "StartTrackKern", 339 "StdHW", 340 "StdVW", 341 "TrackKern", 342 "UnderlinePosition", 343 "UnderlineThickness", 344 "VV", 345 "VVector", 346 "Version", 347 "W", 348 "W0", 349 "W0X", 350 "W0Y", 351 "W1", 352 "W1X", 353 "W1Y", 354 "WX", 355 "WY", 356 "Weight", 357 "WeightVector", 358 "XHeight" 359 }; 360 361 362 /* 363 * `afm_parser_read_vals' and `afm_parser_next_key' provide 364 * high-level operations to an AFM_Stream. The rest of the 365 * parser functions should use them without accessing the 366 * AFM_Stream directly. 367 */ 368 369 FT_LOCAL_DEF( FT_Int ) 370 afm_parser_read_vals( AFM_Parser parser, 371 AFM_Value vals, 372 FT_UInt n ) 373 { 374 AFM_Stream stream = parser->stream; 375 char* str; 376 FT_UInt i; 377 378 379 if ( n > AFM_MAX_ARGUMENTS ) 380 return 0; 381 382 for ( i = 0; i < n; i++ ) 383 { 384 FT_Offset len; 385 AFM_Value val = vals + i; 386 387 388 if ( val->type == AFM_VALUE_TYPE_STRING ) 389 str = afm_stream_read_string( stream ); 390 else 391 str = afm_stream_read_one( stream ); 392 393 if ( !str ) 394 break; 395 396 len = AFM_STREAM_KEY_LEN( stream, str ); 397 398 switch ( val->type ) 399 { 400 case AFM_VALUE_TYPE_STRING: 401 case AFM_VALUE_TYPE_NAME: 402 { 403 FT_Memory memory = parser->memory; 404 FT_Error error; 405 406 407 if ( !FT_QALLOC( val->u.s, len + 1 ) ) 408 { 409 ft_memcpy( val->u.s, str, len ); 410 val->u.s[len] = '\0'; 411 } 412 } 413 break; 414 415 case AFM_VALUE_TYPE_FIXED: 416 val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str, 417 (FT_Byte*)str + len, 0 ); 418 break; 419 420 case AFM_VALUE_TYPE_INTEGER: 421 val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str, 422 (FT_Byte*)str + len ); 423 break; 424 425 case AFM_VALUE_TYPE_BOOL: 426 val->u.b = FT_BOOL( len == 4 && 427 !ft_strncmp( str, "true", 4 ) ); 428 break; 429 430 case AFM_VALUE_TYPE_INDEX: 431 if ( parser->get_index ) 432 val->u.i = parser->get_index( str, len, parser->user_data ); 433 else 434 val->u.i = 0; 435 break; 436 } 437 } 438 439 return i; 440 } 441 442 443 FT_LOCAL_DEF( char* ) 444 afm_parser_next_key( AFM_Parser parser, 445 FT_Bool line, 446 FT_Offset* len ) 447 { 448 AFM_Stream stream = parser->stream; 449 char* key = 0; /* make stupid compiler happy */ 450 451 452 if ( line ) 453 { 454 while ( 1 ) 455 { 456 /* skip current line */ 457 if ( !AFM_STATUS_EOL( stream ) ) 458 afm_stream_read_string( stream ); 459 460 stream->status = AFM_STREAM_STATUS_NORMAL; 461 key = afm_stream_read_one( stream ); 462 463 /* skip empty line */ 464 if ( !key && 465 !AFM_STATUS_EOF( stream ) && 466 AFM_STATUS_EOL( stream ) ) 467 continue; 468 469 break; 470 } 471 } 472 else 473 { 474 while ( 1 ) 475 { 476 /* skip current column */ 477 while ( !AFM_STATUS_EOC( stream ) ) 478 afm_stream_read_one( stream ); 479 480 stream->status = AFM_STREAM_STATUS_NORMAL; 481 key = afm_stream_read_one( stream ); 482 483 /* skip empty column */ 484 if ( !key && 485 !AFM_STATUS_EOF( stream ) && 486 AFM_STATUS_EOC( stream ) ) 487 continue; 488 489 break; 490 } 491 } 492 493 if ( len ) 494 *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key ) 495 : 0; 496 497 return key; 498 } 499 500 501 static AFM_Token 502 afm_tokenize( const char* key, 503 FT_Offset len ) 504 { 505 int n; 506 507 508 for ( n = 0; n < N_AFM_TOKENS; n++ ) 509 { 510 if ( *( afm_key_table[n] ) == *key ) 511 { 512 for ( ; n < N_AFM_TOKENS; n++ ) 513 { 514 if ( *( afm_key_table[n] ) != *key ) 515 return AFM_TOKEN_UNKNOWN; 516 517 if ( ft_strncmp( afm_key_table[n], key, len ) == 0 ) 518 return (AFM_Token) n; 519 } 520 } 521 } 522 523 return AFM_TOKEN_UNKNOWN; 524 } 525 526 527 FT_LOCAL_DEF( FT_Error ) 528 afm_parser_init( AFM_Parser parser, 529 FT_Memory memory, 530 FT_Byte* base, 531 FT_Byte* limit ) 532 { 533 AFM_Stream stream = NULL; 534 FT_Error error; 535 536 537 if ( FT_NEW( stream ) ) 538 return error; 539 540 stream->cursor = stream->base = base; 541 stream->limit = limit; 542 543 /* don't skip the first line during the first call */ 544 stream->status = AFM_STREAM_STATUS_EOL; 545 546 parser->memory = memory; 547 parser->stream = stream; 548 parser->FontInfo = NULL; 549 parser->get_index = NULL; 550 551 return FT_Err_Ok; 552 } 553 554 555 FT_LOCAL( void ) 556 afm_parser_done( AFM_Parser parser ) 557 { 558 FT_Memory memory = parser->memory; 559 560 561 FT_FREE( parser->stream ); 562 } 563 564 565 FT_LOCAL_DEF( FT_Error ) 566 afm_parser_read_int( AFM_Parser parser, 567 FT_Int* aint ) 568 { 569 AFM_ValueRec val; 570 571 572 val.type = AFM_VALUE_TYPE_INTEGER; 573 574 if ( afm_parser_read_vals( parser, &val, 1 ) == 1 ) 575 { 576 *aint = val.u.i; 577 578 return FT_Err_Ok; 579 } 580 else 581 return FT_THROW( Syntax_Error ); 582 } 583 584 585 static FT_Error 586 afm_parse_track_kern( AFM_Parser parser ) 587 { 588 AFM_FontInfo fi = parser->FontInfo; 589 AFM_TrackKern tk; 590 char* key; 591 FT_Offset len; 592 int n = -1; 593 594 595 if ( afm_parser_read_int( parser, &fi->NumTrackKern ) ) 596 goto Fail; 597 598 if ( fi->NumTrackKern ) 599 { 600 FT_Memory memory = parser->memory; 601 FT_Error error; 602 603 604 if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) ) 605 return error; 606 } 607 608 while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 ) 609 { 610 AFM_ValueRec shared_vals[5]; 611 612 613 switch ( afm_tokenize( key, len ) ) 614 { 615 case AFM_TOKEN_TRACKKERN: 616 n++; 617 618 if ( n >= fi->NumTrackKern ) 619 goto Fail; 620 621 tk = fi->TrackKerns + n; 622 623 shared_vals[0].type = AFM_VALUE_TYPE_INTEGER; 624 shared_vals[1].type = AFM_VALUE_TYPE_FIXED; 625 shared_vals[2].type = AFM_VALUE_TYPE_FIXED; 626 shared_vals[3].type = AFM_VALUE_TYPE_FIXED; 627 shared_vals[4].type = AFM_VALUE_TYPE_FIXED; 628 if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 ) 629 goto Fail; 630 631 tk->degree = shared_vals[0].u.i; 632 tk->min_ptsize = shared_vals[1].u.f; 633 tk->min_kern = shared_vals[2].u.f; 634 tk->max_ptsize = shared_vals[3].u.f; 635 tk->max_kern = shared_vals[4].u.f; 636 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 FT_Err_Ok; 644 645 case AFM_TOKEN_UNKNOWN: 646 break; 647 648 default: 649 goto Fail; 650 } 651 } 652 653 Fail: 654 return FT_THROW( 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 FT_Err_Ok; 760 761 case AFM_TOKEN_UNKNOWN: 762 break; 763 764 default: 765 goto Fail; 766 } 767 } 768 769 Fail: 770 return FT_THROW( 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 FT_Err_Ok; 802 803 case AFM_TOKEN_UNKNOWN: 804 break; 805 806 default: 807 goto Fail; 808 } 809 } 810 811 Fail: 812 return FT_THROW( 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 FT_Err_Ok; 839 } 840 841 Fail: 842 return FT_THROW( 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 = FT_ERR( Syntax_Error ); 852 char* key; 853 FT_Offset len; 854 FT_Int metrics_sets = 0; 855 856 857 if ( !fi ) 858 return FT_THROW( 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 FT_THROW( 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 = FT_THROW( 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 FT_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