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