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