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