1 /**************************************************************************** 2 * 3 * t1load.c 4 * 5 * Type 1 font loader (body). 6 * 7 * Copyright (C) 1996-2019 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 19 /************************************************************************** 20 * 21 * This is the new and improved Type 1 data loader for FreeType 2. The 22 * old loader has several problems: it is slow, complex, difficult to 23 * maintain, and contains incredible hacks to make it accept some 24 * ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of 25 * the Type 1 fonts on my machine still aren't loaded correctly by it. 26 * 27 * This version is much simpler, much faster and also easier to read and 28 * maintain by a great order of magnitude. The idea behind it is to 29 * _not_ try to read the Type 1 token stream with a state machine (i.e. 30 * a Postscript-like interpreter) but rather to perform simple pattern 31 * matching. 32 * 33 * Indeed, nearly all data definitions follow a simple pattern like 34 * 35 * ... /Field <data> ... 36 * 37 * where <data> can be a number, a boolean, a string, or an array of 38 * numbers. There are a few exceptions, namely the encoding, font name, 39 * charstrings, and subrs; they are handled with a special pattern 40 * matching routine. 41 * 42 * All other common cases are handled very simply. The matching rules 43 * are defined in the file `t1tokens.h' through the use of several 44 * macros calls PARSE_XXX. This file is included twice here; the first 45 * time to generate parsing callback functions, the second time to 46 * generate a table of keywords (with pointers to the associated 47 * callback functions). 48 * 49 * The function `parse_dict' simply scans *linearly* a given dictionary 50 * (either the top-level or private one) and calls the appropriate 51 * callback when it encounters an immediate keyword. 52 * 53 * This is by far the fastest way one can find to parse and read all 54 * data. 55 * 56 * This led to tremendous code size reduction. Note that later, the 57 * glyph loader will also be _greatly_ simplified, and the automatic 58 * hinter will replace the clumsy `t1hinter'. 59 * 60 */ 61 62 63 #include <ft2build.h> 64 #include FT_INTERNAL_DEBUG_H 65 #include FT_CONFIG_CONFIG_H 66 #include FT_MULTIPLE_MASTERS_H 67 #include FT_INTERNAL_TYPE1_TYPES_H 68 #include FT_INTERNAL_CALC_H 69 #include FT_INTERNAL_HASH_H 70 71 #include "t1load.h" 72 #include "t1errors.h" 73 74 75 #ifdef FT_CONFIG_OPTION_INCREMENTAL 76 #define IS_INCREMENTAL FT_BOOL( face->root.internal->incremental_interface ) 77 #else 78 #define IS_INCREMENTAL 0 79 #endif 80 81 82 /************************************************************************** 83 * 84 * The macro FT_COMPONENT is used in trace mode. It is an implicit 85 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 86 * messages during execution. 87 */ 88 #undef FT_COMPONENT 89 #define FT_COMPONENT t1load 90 91 92 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 93 94 95 /*************************************************************************/ 96 /*************************************************************************/ 97 /***** *****/ 98 /***** MULTIPLE MASTERS SUPPORT *****/ 99 /***** *****/ 100 /*************************************************************************/ 101 /*************************************************************************/ 102 103 static FT_Error 104 t1_allocate_blend( T1_Face face, 105 FT_UInt num_designs, 106 FT_UInt num_axis ) 107 { 108 PS_Blend blend; 109 FT_Memory memory = face->root.memory; 110 FT_Error error = FT_Err_Ok; 111 112 113 blend = face->blend; 114 if ( !blend ) 115 { 116 if ( FT_NEW( blend ) ) 117 goto Exit; 118 119 blend->num_default_design_vector = 0; 120 121 face->blend = blend; 122 } 123 124 /* allocate design data if needed */ 125 if ( num_designs > 0 ) 126 { 127 if ( blend->num_designs == 0 ) 128 { 129 FT_UInt nn; 130 131 132 /* allocate the blend `private' and `font_info' dictionaries */ 133 if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || 134 FT_NEW_ARRAY( blend->privates [1], num_designs ) || 135 FT_NEW_ARRAY( blend->bboxes [1], num_designs ) || 136 FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) 137 goto Exit; 138 139 blend->default_weight_vector = blend->weight_vector + num_designs; 140 141 blend->font_infos[0] = &face->type1.font_info; 142 blend->privates [0] = &face->type1.private_dict; 143 blend->bboxes [0] = &face->type1.font_bbox; 144 145 for ( nn = 2; nn <= num_designs; nn++ ) 146 { 147 blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; 148 blend->privates [nn] = blend->privates [nn - 1] + 1; 149 blend->bboxes [nn] = blend->bboxes [nn - 1] + 1; 150 } 151 152 blend->num_designs = num_designs; 153 } 154 else if ( blend->num_designs != num_designs ) 155 goto Fail; 156 } 157 158 /* allocate axis data if needed */ 159 if ( num_axis > 0 ) 160 { 161 if ( blend->num_axis != 0 && blend->num_axis != num_axis ) 162 goto Fail; 163 164 blend->num_axis = num_axis; 165 } 166 167 /* allocate the blend design pos table if needed */ 168 num_designs = blend->num_designs; 169 num_axis = blend->num_axis; 170 if ( num_designs && num_axis && blend->design_pos[0] == 0 ) 171 { 172 FT_UInt n; 173 174 175 if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) 176 goto Exit; 177 178 for ( n = 1; n < num_designs; n++ ) 179 blend->design_pos[n] = blend->design_pos[0] + num_axis * n; 180 } 181 182 Exit: 183 return error; 184 185 Fail: 186 error = FT_THROW( Invalid_File_Format ); 187 goto Exit; 188 } 189 190 191 FT_LOCAL_DEF( FT_Error ) 192 T1_Get_Multi_Master( T1_Face face, 193 FT_Multi_Master* master ) 194 { 195 PS_Blend blend = face->blend; 196 FT_UInt n; 197 FT_Error error; 198 199 200 error = FT_THROW( Invalid_Argument ); 201 202 if ( blend ) 203 { 204 master->num_axis = blend->num_axis; 205 master->num_designs = blend->num_designs; 206 207 for ( n = 0; n < blend->num_axis; n++ ) 208 { 209 FT_MM_Axis* axis = master->axis + n; 210 PS_DesignMap map = blend->design_map + n; 211 212 213 axis->name = blend->axis_names[n]; 214 axis->minimum = map->design_points[0]; 215 axis->maximum = map->design_points[map->num_points - 1]; 216 } 217 218 error = FT_Err_Ok; 219 } 220 221 return error; 222 } 223 224 225 /************************************************************************** 226 * 227 * Given a normalized (blend) coordinate, figure out the design 228 * coordinate appropriate for that value. 229 */ 230 static FT_Fixed 231 mm_axis_unmap( PS_DesignMap axismap, 232 FT_Fixed ncv ) 233 { 234 int j; 235 236 237 if ( ncv <= axismap->blend_points[0] ) 238 return INT_TO_FIXED( axismap->design_points[0] ); 239 240 for ( j = 1; j < axismap->num_points; j++ ) 241 { 242 if ( ncv <= axismap->blend_points[j] ) 243 return INT_TO_FIXED( axismap->design_points[j - 1] ) + 244 ( axismap->design_points[j] - axismap->design_points[j - 1] ) * 245 FT_DivFix( ncv - axismap->blend_points[j - 1], 246 axismap->blend_points[j] - 247 axismap->blend_points[j - 1] ); 248 } 249 250 return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] ); 251 } 252 253 254 /************************************************************************** 255 * 256 * Given a vector of weights, one for each design, figure out the 257 * normalized axis coordinates which gave rise to those weights. 258 */ 259 static void 260 mm_weights_unmap( FT_Fixed* weights, 261 FT_Fixed* axiscoords, 262 FT_UInt axis_count ) 263 { 264 FT_ASSERT( axis_count <= T1_MAX_MM_AXIS ); 265 266 if ( axis_count == 1 ) 267 axiscoords[0] = weights[1]; 268 269 else if ( axis_count == 2 ) 270 { 271 axiscoords[0] = weights[3] + weights[1]; 272 axiscoords[1] = weights[3] + weights[2]; 273 } 274 275 else if ( axis_count == 3 ) 276 { 277 axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1]; 278 axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2]; 279 axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4]; 280 } 281 282 else 283 { 284 axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] + 285 weights[7] + weights[5] + weights[3] + weights[1]; 286 axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] + 287 weights[7] + weights[6] + weights[3] + weights[2]; 288 axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] + 289 weights[7] + weights[6] + weights[5] + weights[4]; 290 axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] + 291 weights[11] + weights[10] + weights[9] + weights[8]; 292 } 293 } 294 295 296 /************************************************************************** 297 * 298 * Just a wrapper around T1_Get_Multi_Master to support the different 299 * arguments needed by the GX var distortable fonts. 300 */ 301 FT_LOCAL_DEF( FT_Error ) 302 T1_Get_MM_Var( T1_Face face, 303 FT_MM_Var* *master ) 304 { 305 FT_Memory memory = face->root.memory; 306 FT_MM_Var *mmvar = NULL; 307 FT_Multi_Master mmaster; 308 FT_Error error; 309 FT_UInt i; 310 FT_Fixed axiscoords[T1_MAX_MM_AXIS]; 311 PS_Blend blend = face->blend; 312 313 314 error = T1_Get_Multi_Master( face, &mmaster ); 315 if ( error ) 316 goto Exit; 317 if ( FT_ALLOC( mmvar, 318 sizeof ( FT_MM_Var ) + 319 mmaster.num_axis * sizeof ( FT_Var_Axis ) ) ) 320 goto Exit; 321 322 mmvar->num_axis = mmaster.num_axis; 323 mmvar->num_designs = mmaster.num_designs; 324 mmvar->num_namedstyles = 0; /* Not supported */ 325 mmvar->axis = (FT_Var_Axis*)&mmvar[1]; 326 /* Point to axes after MM_Var struct */ 327 mmvar->namedstyle = NULL; 328 329 for ( i = 0; i < mmaster.num_axis; i++ ) 330 { 331 mmvar->axis[i].name = mmaster.axis[i].name; 332 mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum ); 333 mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum ); 334 mmvar->axis[i].def = ( mmvar->axis[i].minimum + 335 mmvar->axis[i].maximum ) / 2; 336 /* Does not apply. But this value is in range */ 337 mmvar->axis[i].strid = ~0U; /* Does not apply */ 338 mmvar->axis[i].tag = ~0U; /* Does not apply */ 339 340 if ( !mmvar->axis[i].name ) 341 continue; 342 343 if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 ) 344 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' ); 345 else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 ) 346 mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' ); 347 else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 ) 348 mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' ); 349 } 350 351 mm_weights_unmap( blend->default_weight_vector, 352 axiscoords, 353 blend->num_axis ); 354 355 for ( i = 0; i < mmaster.num_axis; i++ ) 356 mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i], 357 axiscoords[i] ); 358 359 *master = mmvar; 360 361 Exit: 362 return error; 363 } 364 365 366 static FT_Error 367 t1_set_mm_blend( T1_Face face, 368 FT_UInt num_coords, 369 FT_Fixed* coords ) 370 { 371 PS_Blend blend = face->blend; 372 FT_UInt n, m; 373 374 FT_Bool have_diff = 0; 375 376 377 if ( !blend ) 378 return FT_THROW( Invalid_Argument ); 379 380 if ( num_coords > blend->num_axis ) 381 num_coords = blend->num_axis; 382 383 /* recompute the weight vector from the blend coordinates */ 384 for ( n = 0; n < blend->num_designs; n++ ) 385 { 386 FT_Fixed result = 0x10000L; /* 1.0 fixed */ 387 FT_Fixed factor; 388 389 390 for ( m = 0; m < blend->num_axis; m++ ) 391 { 392 /* use a default value if we don't have a coordinate */ 393 if ( m >= num_coords ) 394 { 395 result >>= 1; 396 continue; 397 } 398 399 /* get current blend axis position */ 400 factor = coords[m]; 401 if ( ( n & ( 1 << m ) ) == 0 ) 402 factor = 0x10000L - factor; 403 404 if ( factor <= 0 ) 405 { 406 result = 0; 407 break; 408 } 409 else if ( factor >= 0x10000L ) 410 continue; 411 412 result = FT_MulFix( result, factor ); 413 } 414 415 if ( blend->weight_vector[n] != result ) 416 { 417 blend->weight_vector[n] = result; 418 have_diff = 1; 419 } 420 } 421 422 /* return value -1 indicates `no change' */ 423 return have_diff ? FT_Err_Ok : -1; 424 } 425 426 427 FT_LOCAL_DEF( FT_Error ) 428 T1_Set_MM_Blend( T1_Face face, 429 FT_UInt num_coords, 430 FT_Fixed* coords ) 431 { 432 FT_Error error; 433 434 435 error = t1_set_mm_blend( face, num_coords, coords ); 436 if ( error ) 437 return error; 438 439 if ( num_coords ) 440 face->root.face_flags |= FT_FACE_FLAG_VARIATION; 441 else 442 face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; 443 444 return FT_Err_Ok; 445 } 446 447 448 FT_LOCAL_DEF( FT_Error ) 449 T1_Get_MM_Blend( T1_Face face, 450 FT_UInt num_coords, 451 FT_Fixed* coords ) 452 { 453 PS_Blend blend = face->blend; 454 455 FT_Fixed axiscoords[4]; 456 FT_UInt i, nc; 457 458 459 if ( !blend ) 460 return FT_THROW( Invalid_Argument ); 461 462 mm_weights_unmap( blend->weight_vector, 463 axiscoords, 464 blend->num_axis ); 465 466 nc = num_coords; 467 if ( num_coords > blend->num_axis ) 468 { 469 FT_TRACE2(( "T1_Get_MM_Blend: only using first %d of %d coordinates\n", 470 blend->num_axis, num_coords )); 471 nc = blend->num_axis; 472 } 473 474 for ( i = 0; i < nc; i++ ) 475 coords[i] = axiscoords[i]; 476 for ( ; i < num_coords; i++ ) 477 coords[i] = 0x8000; 478 479 return FT_Err_Ok; 480 } 481 482 483 FT_LOCAL_DEF( FT_Error ) 484 T1_Set_MM_WeightVector( T1_Face face, 485 FT_UInt len, 486 FT_Fixed* weightvector ) 487 { 488 PS_Blend blend = face->blend; 489 FT_UInt i, n; 490 491 492 if ( !blend ) 493 return FT_THROW( Invalid_Argument ); 494 495 if ( !len && !weightvector ) 496 { 497 for ( i = 0; i < blend->num_designs; i++ ) 498 blend->weight_vector[i] = blend->default_weight_vector[i]; 499 } 500 else 501 { 502 if ( !weightvector ) 503 return FT_THROW( Invalid_Argument ); 504 505 n = len < blend->num_designs ? len : blend->num_designs; 506 507 for ( i = 0; i < n; i++ ) 508 blend->weight_vector[i] = weightvector[i]; 509 510 for ( ; i < blend->num_designs; i++ ) 511 blend->weight_vector[i] = (FT_Fixed)0; 512 513 if ( len ) 514 face->root.face_flags |= FT_FACE_FLAG_VARIATION; 515 else 516 face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; 517 } 518 519 return FT_Err_Ok; 520 } 521 522 523 FT_LOCAL_DEF( FT_Error ) 524 T1_Get_MM_WeightVector( T1_Face face, 525 FT_UInt* len, 526 FT_Fixed* weightvector ) 527 { 528 PS_Blend blend = face->blend; 529 FT_UInt i; 530 531 532 if ( !blend ) 533 return FT_THROW( Invalid_Argument ); 534 535 if ( *len < blend->num_designs ) 536 { 537 *len = blend->num_designs; 538 return FT_THROW( Invalid_Argument ); 539 } 540 541 for ( i = 0; i < blend->num_designs; i++ ) 542 weightvector[i] = blend->weight_vector[i]; 543 for ( ; i < *len; i++ ) 544 weightvector[i] = (FT_Fixed)0; 545 546 *len = blend->num_designs; 547 548 return FT_Err_Ok; 549 } 550 551 552 FT_LOCAL_DEF( FT_Error ) 553 T1_Set_MM_Design( T1_Face face, 554 FT_UInt num_coords, 555 FT_Long* coords ) 556 { 557 FT_Error error; 558 PS_Blend blend = face->blend; 559 FT_UInt n, p; 560 FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; 561 562 563 if ( !blend ) 564 return FT_THROW( Invalid_Argument ); 565 566 if ( num_coords > blend->num_axis ) 567 num_coords = blend->num_axis; 568 569 /* compute the blend coordinates through the blend design map */ 570 571 for ( n = 0; n < blend->num_axis; n++ ) 572 { 573 FT_Long design; 574 FT_Fixed the_blend; 575 PS_DesignMap map = blend->design_map + n; 576 FT_Long* designs = map->design_points; 577 FT_Fixed* blends = map->blend_points; 578 FT_Int before = -1, after = -1; 579 580 581 /* use a default value if we don't have a coordinate */ 582 if ( n < num_coords ) 583 design = coords[n]; 584 else 585 design = ( designs[map->num_points - 1] - designs[0] ) / 2; 586 587 for ( p = 0; p < (FT_UInt)map->num_points; p++ ) 588 { 589 FT_Long p_design = designs[p]; 590 591 592 /* exact match? */ 593 if ( design == p_design ) 594 { 595 the_blend = blends[p]; 596 goto Found; 597 } 598 599 if ( design < p_design ) 600 { 601 after = (FT_Int)p; 602 break; 603 } 604 605 before = (FT_Int)p; 606 } 607 608 /* now interpolate if necessary */ 609 if ( before < 0 ) 610 the_blend = blends[0]; 611 612 else if ( after < 0 ) 613 the_blend = blends[map->num_points - 1]; 614 615 else 616 the_blend = FT_MulDiv( design - designs[before], 617 blends [after] - blends [before], 618 designs[after] - designs[before] ); 619 620 Found: 621 final_blends[n] = the_blend; 622 } 623 624 error = t1_set_mm_blend( face, blend->num_axis, final_blends ); 625 if ( error ) 626 return error; 627 628 if ( num_coords ) 629 face->root.face_flags |= FT_FACE_FLAG_VARIATION; 630 else 631 face->root.face_flags &= ~FT_FACE_FLAG_VARIATION; 632 633 return FT_Err_Ok; 634 } 635 636 637 /* MM fonts don't have named instances, so only the design is reset */ 638 639 FT_LOCAL_DEF( FT_Error ) 640 T1_Reset_MM_Blend( T1_Face face, 641 FT_UInt instance_index ) 642 { 643 FT_UNUSED( instance_index ); 644 645 return T1_Set_MM_Blend( face, 0, NULL ); 646 } 647 648 649 /************************************************************************** 650 * 651 * Just a wrapper around T1_Set_MM_Design to support the different 652 * arguments needed by the GX var distortable fonts. 653 */ 654 FT_LOCAL_DEF( FT_Error ) 655 T1_Set_Var_Design( T1_Face face, 656 FT_UInt num_coords, 657 FT_Fixed* coords ) 658 { 659 FT_Long lcoords[T1_MAX_MM_AXIS]; 660 FT_UInt i; 661 662 663 if ( num_coords > T1_MAX_MM_AXIS ) 664 num_coords = T1_MAX_MM_AXIS; 665 666 for ( i = 0; i < num_coords; i++ ) 667 lcoords[i] = FIXED_TO_INT( coords[i] ); 668 669 return T1_Set_MM_Design( face, num_coords, lcoords ); 670 } 671 672 673 FT_LOCAL_DEF( FT_Error ) 674 T1_Get_Var_Design( T1_Face face, 675 FT_UInt num_coords, 676 FT_Fixed* coords ) 677 { 678 PS_Blend blend = face->blend; 679 680 FT_Fixed axiscoords[4]; 681 FT_UInt i, nc; 682 683 684 if ( !blend ) 685 return FT_THROW( Invalid_Argument ); 686 687 mm_weights_unmap( blend->weight_vector, 688 axiscoords, 689 blend->num_axis ); 690 691 nc = num_coords; 692 if ( num_coords > blend->num_axis ) 693 { 694 FT_TRACE2(( "T1_Get_Var_Design:" 695 " only using first %d of %d coordinates\n", 696 blend->num_axis, num_coords )); 697 nc = blend->num_axis; 698 } 699 700 for ( i = 0; i < nc; i++ ) 701 coords[i] = mm_axis_unmap( &blend->design_map[i], axiscoords[i] ); 702 for ( ; i < num_coords; i++ ) 703 coords[i] = 0; 704 705 return FT_Err_Ok; 706 } 707 708 709 FT_LOCAL_DEF( void ) 710 T1_Done_Blend( T1_Face face ) 711 { 712 FT_Memory memory = face->root.memory; 713 PS_Blend blend = face->blend; 714 715 716 if ( blend ) 717 { 718 FT_UInt num_designs = blend->num_designs; 719 FT_UInt num_axis = blend->num_axis; 720 FT_UInt n; 721 722 723 /* release design pos table */ 724 FT_FREE( blend->design_pos[0] ); 725 for ( n = 1; n < num_designs; n++ ) 726 blend->design_pos[n] = NULL; 727 728 /* release blend `private' and `font info' dictionaries */ 729 FT_FREE( blend->privates[1] ); 730 FT_FREE( blend->font_infos[1] ); 731 FT_FREE( blend->bboxes[1] ); 732 733 for ( n = 0; n < num_designs; n++ ) 734 { 735 blend->privates [n] = NULL; 736 blend->font_infos[n] = NULL; 737 blend->bboxes [n] = NULL; 738 } 739 740 /* release weight vectors */ 741 FT_FREE( blend->weight_vector ); 742 blend->default_weight_vector = NULL; 743 744 /* release axis names */ 745 for ( n = 0; n < num_axis; n++ ) 746 FT_FREE( blend->axis_names[n] ); 747 748 /* release design map */ 749 for ( n = 0; n < num_axis; n++ ) 750 { 751 PS_DesignMap dmap = blend->design_map + n; 752 753 754 FT_FREE( dmap->design_points ); 755 dmap->num_points = 0; 756 } 757 758 FT_FREE( face->blend ); 759 } 760 } 761 762 763 static void 764 parse_blend_axis_types( T1_Face face, 765 T1_Loader loader ) 766 { 767 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; 768 FT_Int n, num_axis; 769 FT_Error error = FT_Err_Ok; 770 PS_Blend blend; 771 FT_Memory memory; 772 773 774 /* take an array of objects */ 775 T1_ToTokenArray( &loader->parser, axis_tokens, 776 T1_MAX_MM_AXIS, &num_axis ); 777 if ( num_axis < 0 ) 778 { 779 error = FT_ERR( Ignore ); 780 goto Exit; 781 } 782 if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) 783 { 784 FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", 785 num_axis )); 786 error = FT_THROW( Invalid_File_Format ); 787 goto Exit; 788 } 789 790 /* allocate blend if necessary */ 791 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); 792 if ( error ) 793 goto Exit; 794 795 FT_TRACE4(( " [" )); 796 797 blend = face->blend; 798 memory = face->root.memory; 799 800 /* each token is an immediate containing the name of the axis */ 801 for ( n = 0; n < num_axis; n++ ) 802 { 803 T1_Token token = axis_tokens + n; 804 FT_Byte* name; 805 FT_UInt len; 806 807 808 /* skip first slash, if any */ 809 if ( token->start[0] == '/' ) 810 token->start++; 811 812 len = (FT_UInt)( token->limit - token->start ); 813 if ( len == 0 ) 814 { 815 error = FT_THROW( Invalid_File_Format ); 816 goto Exit; 817 } 818 819 FT_TRACE4(( " /%.*s", len, token->start )); 820 821 name = (FT_Byte*)blend->axis_names[n]; 822 if ( name ) 823 { 824 FT_TRACE0(( "parse_blend_axis_types:" 825 " overwriting axis name `%s' with `%.*s'\n", 826 name, len, token->start )); 827 FT_FREE( name ); 828 } 829 830 if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) 831 goto Exit; 832 833 name = (FT_Byte*)blend->axis_names[n]; 834 FT_MEM_COPY( name, token->start, len ); 835 name[len] = '\0'; 836 } 837 838 FT_TRACE4(( "]\n" )); 839 840 Exit: 841 loader->parser.root.error = error; 842 } 843 844 845 static void 846 parse_blend_design_positions( T1_Face face, 847 T1_Loader loader ) 848 { 849 T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; 850 FT_Int num_designs; 851 FT_Int num_axis; 852 T1_Parser parser = &loader->parser; 853 854 FT_Error error = FT_Err_Ok; 855 PS_Blend blend; 856 857 858 /* get the array of design tokens -- compute number of designs */ 859 T1_ToTokenArray( parser, design_tokens, 860 T1_MAX_MM_DESIGNS, &num_designs ); 861 if ( num_designs < 0 ) 862 { 863 error = FT_ERR( Ignore ); 864 goto Exit; 865 } 866 if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) 867 { 868 FT_ERROR(( "parse_blend_design_positions:" 869 " incorrect number of designs: %d\n", 870 num_designs )); 871 error = FT_THROW( Invalid_File_Format ); 872 goto Exit; 873 } 874 875 { 876 FT_Byte* old_cursor = parser->root.cursor; 877 FT_Byte* old_limit = parser->root.limit; 878 FT_Int n; 879 880 881 blend = face->blend; 882 num_axis = 0; /* make compiler happy */ 883 884 FT_TRACE4(( " [" )); 885 886 for ( n = 0; n < num_designs; n++ ) 887 { 888 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; 889 T1_Token token; 890 FT_Int axis, n_axis; 891 892 893 /* read axis/coordinates tokens */ 894 token = design_tokens + n; 895 parser->root.cursor = token->start; 896 parser->root.limit = token->limit; 897 T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); 898 899 if ( n == 0 ) 900 { 901 if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS ) 902 { 903 FT_ERROR(( "parse_blend_design_positions:" 904 " invalid number of axes: %d\n", 905 n_axis )); 906 error = FT_THROW( Invalid_File_Format ); 907 goto Exit; 908 } 909 910 num_axis = n_axis; 911 error = t1_allocate_blend( face, 912 (FT_UInt)num_designs, 913 (FT_UInt)num_axis ); 914 if ( error ) 915 goto Exit; 916 blend = face->blend; 917 } 918 else if ( n_axis != num_axis ) 919 { 920 FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); 921 error = FT_THROW( Invalid_File_Format ); 922 goto Exit; 923 } 924 925 /* now read each axis token into the design position */ 926 FT_TRACE4(( " [" )) ; 927 for ( axis = 0; axis < n_axis; axis++ ) 928 { 929 T1_Token token2 = axis_tokens + axis; 930 931 932 parser->root.cursor = token2->start; 933 parser->root.limit = token2->limit; 934 blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); 935 FT_TRACE4(( " %f", (double)blend->design_pos[n][axis] / 65536 )); 936 } 937 FT_TRACE4(( "]" )) ; 938 } 939 940 FT_TRACE4(( "]\n" )); 941 942 loader->parser.root.cursor = old_cursor; 943 loader->parser.root.limit = old_limit; 944 } 945 946 Exit: 947 loader->parser.root.error = error; 948 } 949 950 951 static void 952 parse_blend_design_map( T1_Face face, 953 T1_Loader loader ) 954 { 955 FT_Error error = FT_Err_Ok; 956 T1_Parser parser = &loader->parser; 957 PS_Blend blend; 958 T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; 959 FT_Int n, num_axis; 960 FT_Byte* old_cursor; 961 FT_Byte* old_limit; 962 FT_Memory memory = face->root.memory; 963 964 965 T1_ToTokenArray( parser, axis_tokens, 966 T1_MAX_MM_AXIS, &num_axis ); 967 if ( num_axis < 0 ) 968 { 969 error = FT_ERR( Ignore ); 970 goto Exit; 971 } 972 if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS ) 973 { 974 FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", 975 num_axis )); 976 error = FT_THROW( Invalid_File_Format ); 977 goto Exit; 978 } 979 980 old_cursor = parser->root.cursor; 981 old_limit = parser->root.limit; 982 983 error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); 984 if ( error ) 985 goto Exit; 986 blend = face->blend; 987 988 FT_TRACE4(( " [" )); 989 990 /* now read each axis design map */ 991 for ( n = 0; n < num_axis; n++ ) 992 { 993 PS_DesignMap map = blend->design_map + n; 994 T1_Token axis_token; 995 T1_TokenRec point_tokens[T1_MAX_MM_MAP_POINTS]; 996 FT_Int p, num_points; 997 998 999 axis_token = axis_tokens + n; 1000 1001 parser->root.cursor = axis_token->start; 1002 parser->root.limit = axis_token->limit; 1003 T1_ToTokenArray( parser, point_tokens, 1004 T1_MAX_MM_MAP_POINTS, &num_points ); 1005 1006 FT_TRACE4(( " [" )); 1007 1008 if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) 1009 { 1010 FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); 1011 error = FT_THROW( Invalid_File_Format ); 1012 goto Exit; 1013 } 1014 1015 if ( map->design_points ) 1016 { 1017 FT_ERROR(( "parse_blend_design_map: duplicate table\n" )); 1018 error = FT_THROW( Invalid_File_Format ); 1019 goto Exit; 1020 } 1021 1022 /* allocate design map data */ 1023 if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) 1024 goto Exit; 1025 map->blend_points = map->design_points + num_points; 1026 map->num_points = (FT_Byte)num_points; 1027 1028 for ( p = 0; p < num_points; p++ ) 1029 { 1030 T1_Token point_token; 1031 1032 1033 point_token = point_tokens + p; 1034 1035 /* don't include delimiting brackets */ 1036 parser->root.cursor = point_token->start + 1; 1037 parser->root.limit = point_token->limit - 1; 1038 1039 map->design_points[p] = T1_ToInt( parser ); 1040 map->blend_points [p] = T1_ToFixed( parser, 0 ); 1041 1042 FT_TRACE4(( " [%d %f]", 1043 map->design_points[p], 1044 (double)map->blend_points[p] / 65536 )); 1045 } 1046 1047 FT_TRACE4(( "]" )); 1048 } 1049 1050 FT_TRACE4(( "]\n" )); 1051 1052 parser->root.cursor = old_cursor; 1053 parser->root.limit = old_limit; 1054 1055 Exit: 1056 parser->root.error = error; 1057 } 1058 1059 1060 static void 1061 parse_weight_vector( T1_Face face, 1062 T1_Loader loader ) 1063 { 1064 T1_TokenRec design_tokens[T1_MAX_MM_DESIGNS]; 1065 FT_Int num_designs; 1066 FT_Error error = FT_Err_Ok; 1067 T1_Parser parser = &loader->parser; 1068 PS_Blend blend = face->blend; 1069 T1_Token token; 1070 FT_Int n; 1071 FT_Byte* old_cursor; 1072 FT_Byte* old_limit; 1073 1074 1075 T1_ToTokenArray( parser, design_tokens, 1076 T1_MAX_MM_DESIGNS, &num_designs ); 1077 if ( num_designs < 0 ) 1078 { 1079 error = FT_ERR( Ignore ); 1080 goto Exit; 1081 } 1082 if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS ) 1083 { 1084 FT_ERROR(( "parse_weight_vector:" 1085 " incorrect number of designs: %d\n", 1086 num_designs )); 1087 error = FT_THROW( Invalid_File_Format ); 1088 goto Exit; 1089 } 1090 1091 if ( !blend || !blend->num_designs ) 1092 { 1093 error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 ); 1094 if ( error ) 1095 goto Exit; 1096 blend = face->blend; 1097 } 1098 else if ( blend->num_designs != (FT_UInt)num_designs ) 1099 { 1100 FT_ERROR(( "parse_weight_vector:" 1101 " /BlendDesignPosition and /WeightVector have\n" 1102 " " 1103 " different number of elements\n" )); 1104 error = FT_THROW( Invalid_File_Format ); 1105 goto Exit; 1106 } 1107 1108 old_cursor = parser->root.cursor; 1109 old_limit = parser->root.limit; 1110 1111 FT_TRACE4(( "[" )); 1112 1113 for ( n = 0; n < num_designs; n++ ) 1114 { 1115 token = design_tokens + n; 1116 parser->root.cursor = token->start; 1117 parser->root.limit = token->limit; 1118 1119 blend->default_weight_vector[n] = 1120 blend->weight_vector[n] = T1_ToFixed( parser, 0 ); 1121 1122 FT_TRACE4(( " %f", (double)blend->weight_vector[n] / 65536 )); 1123 } 1124 1125 FT_TRACE4(( "]\n" )); 1126 1127 parser->root.cursor = old_cursor; 1128 parser->root.limit = old_limit; 1129 1130 Exit: 1131 parser->root.error = error; 1132 } 1133 1134 1135 /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def */ 1136 /* we're only interested in the number of array elements */ 1137 static void 1138 parse_buildchar( T1_Face face, 1139 T1_Loader loader ) 1140 { 1141 face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser, 1142 0, NULL, 0 ); 1143 1144 #ifdef FT_DEBUG_LEVEL_TRACE 1145 { 1146 FT_UInt i; 1147 1148 1149 FT_TRACE4(( " [" )); 1150 for ( i = 0; i < face->len_buildchar; i++ ) 1151 FT_TRACE4(( " 0" )); 1152 1153 FT_TRACE4(( "]\n" )); 1154 } 1155 #endif 1156 1157 return; 1158 } 1159 1160 1161 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ 1162 1163 1164 1165 1166 /*************************************************************************/ 1167 /*************************************************************************/ 1168 /***** *****/ 1169 /***** TYPE 1 SYMBOL PARSING *****/ 1170 /***** *****/ 1171 /*************************************************************************/ 1172 /*************************************************************************/ 1173 1174 static FT_Error 1175 t1_load_keyword( T1_Face face, 1176 T1_Loader loader, 1177 const T1_Field field ) 1178 { 1179 FT_Error error; 1180 void* dummy_object; 1181 void** objects; 1182 FT_UInt max_objects; 1183 PS_Blend blend = face->blend; 1184 1185 1186 if ( blend && blend->num_designs == 0 ) 1187 blend = NULL; 1188 1189 /* if the keyword has a dedicated callback, call it */ 1190 if ( field->type == T1_FIELD_TYPE_CALLBACK ) 1191 { 1192 FT_TRACE4(( " %s", field->ident )); 1193 1194 field->reader( (FT_Face)face, loader ); 1195 error = loader->parser.root.error; 1196 goto Exit; 1197 } 1198 1199 /* now, the keyword is either a simple field, or a table of fields; */ 1200 /* we are now going to take care of it */ 1201 switch ( field->location ) 1202 { 1203 case T1_FIELD_LOCATION_FONT_INFO: 1204 dummy_object = &face->type1.font_info; 1205 objects = &dummy_object; 1206 max_objects = 0; 1207 1208 if ( blend ) 1209 { 1210 objects = (void**)blend->font_infos; 1211 max_objects = blend->num_designs; 1212 } 1213 break; 1214 1215 case T1_FIELD_LOCATION_FONT_EXTRA: 1216 dummy_object = &face->type1.font_extra; 1217 objects = &dummy_object; 1218 max_objects = 0; 1219 break; 1220 1221 case T1_FIELD_LOCATION_PRIVATE: 1222 dummy_object = &face->type1.private_dict; 1223 objects = &dummy_object; 1224 max_objects = 0; 1225 1226 if ( blend ) 1227 { 1228 objects = (void**)blend->privates; 1229 max_objects = blend->num_designs; 1230 } 1231 break; 1232 1233 case T1_FIELD_LOCATION_BBOX: 1234 dummy_object = &face->type1.font_bbox; 1235 objects = &dummy_object; 1236 max_objects = 0; 1237 1238 if ( blend ) 1239 { 1240 objects = (void**)blend->bboxes; 1241 max_objects = blend->num_designs; 1242 } 1243 break; 1244 1245 case T1_FIELD_LOCATION_LOADER: 1246 dummy_object = loader; 1247 objects = &dummy_object; 1248 max_objects = 0; 1249 break; 1250 1251 case T1_FIELD_LOCATION_FACE: 1252 dummy_object = face; 1253 objects = &dummy_object; 1254 max_objects = 0; 1255 break; 1256 1257 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 1258 case T1_FIELD_LOCATION_BLEND: 1259 dummy_object = face->blend; 1260 objects = &dummy_object; 1261 max_objects = 0; 1262 break; 1263 #endif 1264 1265 default: 1266 dummy_object = &face->type1; 1267 objects = &dummy_object; 1268 max_objects = 0; 1269 } 1270 1271 FT_TRACE4(( " %s", field->ident )); 1272 1273 if ( *objects ) 1274 { 1275 if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || 1276 field->type == T1_FIELD_TYPE_FIXED_ARRAY ) 1277 error = T1_Load_Field_Table( &loader->parser, field, 1278 objects, max_objects, 0 ); 1279 else 1280 error = T1_Load_Field( &loader->parser, field, 1281 objects, max_objects, 0 ); 1282 } 1283 else 1284 { 1285 FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'" 1286 " which is not valid at this point\n" 1287 " (probably due to missing keywords)\n", 1288 field->ident )); 1289 error = FT_Err_Ok; 1290 } 1291 1292 FT_TRACE4(( "\n" )); 1293 1294 Exit: 1295 return error; 1296 } 1297 1298 1299 static void 1300 parse_private( T1_Face face, 1301 T1_Loader loader ) 1302 { 1303 FT_UNUSED( face ); 1304 1305 loader->keywords_encountered |= T1_PRIVATE; 1306 1307 FT_TRACE4(( "\n" )); 1308 } 1309 1310 1311 /* return 1 in case of success */ 1312 1313 static int 1314 read_binary_data( T1_Parser parser, 1315 FT_ULong* size, 1316 FT_Byte** base, 1317 FT_Bool incremental ) 1318 { 1319 FT_Byte* cur; 1320 FT_Byte* limit = parser->root.limit; 1321 1322 1323 /* the binary data has one of the following formats */ 1324 /* */ 1325 /* `size' [white*] RD white ....... ND */ 1326 /* `size' [white*] -| white ....... |- */ 1327 /* */ 1328 1329 T1_Skip_Spaces( parser ); 1330 1331 cur = parser->root.cursor; 1332 1333 if ( cur < limit && ft_isdigit( *cur ) ) 1334 { 1335 FT_Long s = T1_ToInt( parser ); 1336 1337 1338 T1_Skip_PS_Token( parser ); /* `RD' or `-|' or something else */ 1339 1340 /* there is only one whitespace char after the */ 1341 /* `RD' or `-|' token */ 1342 *base = parser->root.cursor + 1; 1343 1344 if ( s >= 0 && s < limit - *base ) 1345 { 1346 parser->root.cursor += s + 1; 1347 *size = (FT_ULong)s; 1348 return !parser->root.error; 1349 } 1350 } 1351 1352 if( !incremental ) 1353 { 1354 FT_ERROR(( "read_binary_data: invalid size field\n" )); 1355 parser->root.error = FT_THROW( Invalid_File_Format ); 1356 } 1357 1358 return 0; 1359 } 1360 1361 1362 /* We now define the routines to handle the `/Encoding', `/Subrs', */ 1363 /* and `/CharStrings' dictionaries. */ 1364 1365 static void 1366 t1_parse_font_matrix( T1_Face face, 1367 T1_Loader loader ) 1368 { 1369 T1_Parser parser = &loader->parser; 1370 FT_Matrix* matrix = &face->type1.font_matrix; 1371 FT_Vector* offset = &face->type1.font_offset; 1372 FT_Face root = (FT_Face)&face->root; 1373 FT_Fixed temp[6]; 1374 FT_Fixed temp_scale; 1375 FT_Int result; 1376 1377 1378 /* input is scaled by 1000 to accommodate default FontMatrix */ 1379 result = T1_ToFixedArray( parser, 6, temp, 3 ); 1380 1381 if ( result < 6 ) 1382 { 1383 parser->root.error = FT_THROW( Invalid_File_Format ); 1384 return; 1385 } 1386 1387 FT_TRACE4(( " [%f %f %f %f %f %f]\n", 1388 (double)temp[0] / 65536 / 1000, 1389 (double)temp[1] / 65536 / 1000, 1390 (double)temp[2] / 65536 / 1000, 1391 (double)temp[3] / 65536 / 1000, 1392 (double)temp[4] / 65536 / 1000, 1393 (double)temp[5] / 65536 / 1000 )); 1394 1395 temp_scale = FT_ABS( temp[3] ); 1396 1397 if ( temp_scale == 0 ) 1398 { 1399 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); 1400 parser->root.error = FT_THROW( Invalid_File_Format ); 1401 return; 1402 } 1403 1404 /* atypical case */ 1405 if ( temp_scale != 0x10000L ) 1406 { 1407 /* set units per EM based on FontMatrix values */ 1408 root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale ); 1409 1410 temp[0] = FT_DivFix( temp[0], temp_scale ); 1411 temp[1] = FT_DivFix( temp[1], temp_scale ); 1412 temp[2] = FT_DivFix( temp[2], temp_scale ); 1413 temp[4] = FT_DivFix( temp[4], temp_scale ); 1414 temp[5] = FT_DivFix( temp[5], temp_scale ); 1415 temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L; 1416 } 1417 matrix->xx = temp[0]; 1418 matrix->yx = temp[1]; 1419 matrix->xy = temp[2]; 1420 matrix->yy = temp[3]; 1421 1422 if ( !FT_Matrix_Check( matrix ) ) 1423 { 1424 FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" )); 1425 parser->root.error = FT_THROW( Invalid_File_Format ); 1426 return; 1427 } 1428 1429 /* note that the offsets must be expressed in integer font units */ 1430 offset->x = temp[4] >> 16; 1431 offset->y = temp[5] >> 16; 1432 } 1433 1434 1435 static void 1436 parse_encoding( T1_Face face, 1437 T1_Loader loader ) 1438 { 1439 T1_Parser parser = &loader->parser; 1440 FT_Byte* cur; 1441 FT_Byte* limit = parser->root.limit; 1442 1443 PSAux_Service psaux = (PSAux_Service)face->psaux; 1444 1445 1446 T1_Skip_Spaces( parser ); 1447 cur = parser->root.cursor; 1448 if ( cur >= limit ) 1449 { 1450 FT_ERROR(( "parse_encoding: out of bounds\n" )); 1451 parser->root.error = FT_THROW( Invalid_File_Format ); 1452 return; 1453 } 1454 1455 /* if we have a number or `[', the encoding is an array, */ 1456 /* and we must load it now */ 1457 if ( ft_isdigit( *cur ) || *cur == '[' ) 1458 { 1459 T1_Encoding encode = &face->type1.encoding; 1460 FT_Int count, array_size, n; 1461 PS_Table char_table = &loader->encoding_table; 1462 FT_Memory memory = parser->root.memory; 1463 FT_Error error; 1464 FT_Bool only_immediates = 0; 1465 1466 1467 /* read the number of entries in the encoding; should be 256 */ 1468 if ( *cur == '[' ) 1469 { 1470 count = 256; 1471 only_immediates = 1; 1472 parser->root.cursor++; 1473 } 1474 else 1475 count = (FT_Int)T1_ToInt( parser ); 1476 1477 array_size = count; 1478 if ( count > 256 ) 1479 { 1480 FT_TRACE2(( "parse_encoding:" 1481 " only using first 256 encoding array entries\n" )); 1482 array_size = 256; 1483 } 1484 1485 T1_Skip_Spaces( parser ); 1486 if ( parser->root.cursor >= limit ) 1487 return; 1488 1489 /* PostScript happily allows overwriting of encoding arrays */ 1490 if ( encode->char_index ) 1491 { 1492 FT_FREE( encode->char_index ); 1493 FT_FREE( encode->char_name ); 1494 T1_Release_Table( char_table ); 1495 } 1496 1497 /* we use a T1_Table to store our charnames */ 1498 loader->num_chars = encode->num_chars = array_size; 1499 if ( FT_NEW_ARRAY( encode->char_index, array_size ) || 1500 FT_NEW_ARRAY( encode->char_name, array_size ) || 1501 FT_SET_ERROR( psaux->ps_table_funcs->init( 1502 char_table, array_size, memory ) ) ) 1503 { 1504 parser->root.error = error; 1505 return; 1506 } 1507 1508 /* We need to `zero' out encoding_table.elements */ 1509 for ( n = 0; n < array_size; n++ ) 1510 { 1511 char* notdef = (char *)".notdef"; 1512 1513 1514 (void)T1_Add_Table( char_table, n, notdef, 8 ); 1515 } 1516 1517 /* Now we need to read records of the form */ 1518 /* */ 1519 /* ... charcode /charname ... */ 1520 /* */ 1521 /* for each entry in our table. */ 1522 /* */ 1523 /* We simply look for a number followed by an immediate */ 1524 /* name. Note that this ignores correctly the sequence */ 1525 /* that is often seen in type1 fonts: */ 1526 /* */ 1527 /* 0 1 255 { 1 index exch /.notdef put } for dup */ 1528 /* */ 1529 /* used to clean the encoding array before anything else. */ 1530 /* */ 1531 /* Alternatively, if the array is directly given as */ 1532 /* */ 1533 /* /Encoding [ ... ] */ 1534 /* */ 1535 /* we only read immediates. */ 1536 1537 n = 0; 1538 T1_Skip_Spaces( parser ); 1539 1540 while ( parser->root.cursor < limit ) 1541 { 1542 cur = parser->root.cursor; 1543 1544 /* we stop when we encounter a `def' or `]' */ 1545 if ( *cur == 'd' && cur + 3 < limit ) 1546 { 1547 if ( cur[1] == 'e' && 1548 cur[2] == 'f' && 1549 IS_PS_DELIM( cur[3] ) ) 1550 { 1551 FT_TRACE6(( "encoding end\n" )); 1552 cur += 3; 1553 break; 1554 } 1555 } 1556 if ( *cur == ']' ) 1557 { 1558 FT_TRACE6(( "encoding end\n" )); 1559 cur++; 1560 break; 1561 } 1562 1563 /* check whether we've found an entry */ 1564 if ( ft_isdigit( *cur ) || only_immediates ) 1565 { 1566 FT_Int charcode; 1567 1568 1569 if ( only_immediates ) 1570 charcode = n; 1571 else 1572 { 1573 charcode = (FT_Int)T1_ToInt( parser ); 1574 T1_Skip_Spaces( parser ); 1575 1576 /* protect against invalid charcode */ 1577 if ( cur == parser->root.cursor ) 1578 { 1579 parser->root.error = FT_THROW( Unknown_File_Format ); 1580 return; 1581 } 1582 } 1583 1584 cur = parser->root.cursor; 1585 1586 if ( cur + 2 < limit && *cur == '/' && n < count ) 1587 { 1588 FT_UInt len; 1589 1590 1591 cur++; 1592 1593 parser->root.cursor = cur; 1594 T1_Skip_PS_Token( parser ); 1595 if ( parser->root.cursor >= limit ) 1596 return; 1597 if ( parser->root.error ) 1598 return; 1599 1600 len = (FT_UInt)( parser->root.cursor - cur ); 1601 1602 if ( n < array_size ) 1603 { 1604 parser->root.error = T1_Add_Table( char_table, charcode, 1605 cur, len + 1 ); 1606 if ( parser->root.error ) 1607 return; 1608 char_table->elements[charcode][len] = '\0'; 1609 } 1610 1611 n++; 1612 } 1613 else if ( only_immediates ) 1614 { 1615 /* Since the current position is not updated for */ 1616 /* immediates-only mode we would get an infinite loop if */ 1617 /* we don't do anything here. */ 1618 /* */ 1619 /* This encoding array is not valid according to the type1 */ 1620 /* specification (it might be an encoding for a CID type1 */ 1621 /* font, however), so we conclude that this font is NOT a */ 1622 /* type1 font. */ 1623 parser->root.error = FT_THROW( Unknown_File_Format ); 1624 return; 1625 } 1626 } 1627 else 1628 { 1629 T1_Skip_PS_Token( parser ); 1630 if ( parser->root.error ) 1631 return; 1632 } 1633 1634 T1_Skip_Spaces( parser ); 1635 } 1636 1637 #ifdef FT_DEBUG_LEVEL_TRACE 1638 FT_TRACE4(( " [" )); 1639 1640 /* XXX show encoding vector */ 1641 FT_TRACE4(( "..." )); 1642 1643 FT_TRACE4(( "]\n" )); 1644 #endif 1645 1646 face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; 1647 parser->root.cursor = cur; 1648 } 1649 1650 /* Otherwise, we should have either `StandardEncoding', */ 1651 /* `ExpertEncoding', or `ISOLatin1Encoding' */ 1652 else 1653 { 1654 if ( cur + 17 < limit && 1655 ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) 1656 { 1657 face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; 1658 FT_TRACE4(( " StandardEncoding\n" )); 1659 } 1660 1661 else if ( cur + 15 < limit && 1662 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) 1663 { 1664 face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; 1665 FT_TRACE4(( " ExpertEncoding\n" )); 1666 } 1667 1668 else if ( cur + 18 < limit && 1669 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) 1670 { 1671 face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; 1672 FT_TRACE4(( " ISOLatin1Encoding\n" )); 1673 } 1674 1675 else 1676 { 1677 parser->root.error = FT_ERR( Ignore ); 1678 FT_TRACE4(( "<unknown>\n" )); 1679 } 1680 } 1681 } 1682 1683 1684 static void 1685 parse_subrs( T1_Face face, 1686 T1_Loader loader ) 1687 { 1688 T1_Parser parser = &loader->parser; 1689 PS_Table table = &loader->subrs; 1690 FT_Memory memory = parser->root.memory; 1691 FT_Error error; 1692 FT_Int num_subrs; 1693 FT_UInt count; 1694 1695 PSAux_Service psaux = (PSAux_Service)face->psaux; 1696 1697 1698 T1_Skip_Spaces( parser ); 1699 1700 /* test for empty array */ 1701 if ( parser->root.cursor < parser->root.limit && 1702 *parser->root.cursor == '[' ) 1703 { 1704 T1_Skip_PS_Token( parser ); 1705 T1_Skip_Spaces ( parser ); 1706 if ( parser->root.cursor >= parser->root.limit || 1707 *parser->root.cursor != ']' ) 1708 parser->root.error = FT_THROW( Invalid_File_Format ); 1709 return; 1710 } 1711 1712 num_subrs = (FT_Int)T1_ToInt( parser ); 1713 if ( num_subrs < 0 ) 1714 { 1715 parser->root.error = FT_THROW( Invalid_File_Format ); 1716 return; 1717 } 1718 1719 /* we certainly need more than 8 bytes per subroutine */ 1720 if ( parser->root.limit >= parser->root.cursor && 1721 num_subrs > ( parser->root.limit - parser->root.cursor ) >> 3 ) 1722 { 1723 /* 1724 * There are two possibilities. Either the font contains an invalid 1725 * value for `num_subrs', or we have a subsetted font where the 1726 * subroutine indices are not adjusted, e.g. 1727 * 1728 * /Subrs 812 array 1729 * dup 0 { ... } NP 1730 * dup 51 { ... } NP 1731 * dup 681 { ... } NP 1732 * ND 1733 * 1734 * In both cases, we use a number hash that maps from subr indices to 1735 * actual array elements. 1736 */ 1737 1738 FT_TRACE0(( "parse_subrs: adjusting number of subroutines" 1739 " (from %d to %d)\n", 1740 num_subrs, 1741 ( parser->root.limit - parser->root.cursor ) >> 3 )); 1742 num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3; 1743 1744 if ( !loader->subrs_hash ) 1745 { 1746 if ( FT_NEW( loader->subrs_hash ) ) 1747 goto Fail; 1748 1749 error = ft_hash_num_init( loader->subrs_hash, memory ); 1750 if ( error ) 1751 goto Fail; 1752 } 1753 } 1754 1755 /* position the parser right before the `dup' of the first subr */ 1756 T1_Skip_PS_Token( parser ); /* `array' */ 1757 if ( parser->root.error ) 1758 return; 1759 T1_Skip_Spaces( parser ); 1760 1761 /* initialize subrs array -- with synthetic fonts it is possible */ 1762 /* we get here twice */ 1763 if ( !loader->num_subrs ) 1764 { 1765 error = psaux->ps_table_funcs->init( table, num_subrs, memory ); 1766 if ( error ) 1767 goto Fail; 1768 } 1769 1770 /* the format is simple: */ 1771 /* */ 1772 /* `index' + binary data */ 1773 /* */ 1774 for ( count = 0; ; count++ ) 1775 { 1776 FT_Long idx; 1777 FT_ULong size; 1778 FT_Byte* base; 1779 1780 1781 /* If we are out of data, or if the next token isn't `dup', */ 1782 /* we are done. */ 1783 if ( parser->root.cursor + 4 >= parser->root.limit || 1784 ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 ) 1785 break; 1786 1787 T1_Skip_PS_Token( parser ); /* `dup' */ 1788 1789 idx = T1_ToInt( parser ); 1790 1791 if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) ) 1792 return; 1793 1794 /* The binary string is followed by one token, e.g. `NP' */ 1795 /* (bound to `noaccess put') or by two separate tokens: */ 1796 /* `noaccess' & `put'. We position the parser right */ 1797 /* before the next `dup', if any. */ 1798 T1_Skip_PS_Token( parser ); /* `NP' or `|' or `noaccess' */ 1799 if ( parser->root.error ) 1800 return; 1801 T1_Skip_Spaces ( parser ); 1802 1803 if ( parser->root.cursor + 4 < parser->root.limit && 1804 ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 ) 1805 { 1806 T1_Skip_PS_Token( parser ); /* skip `put' */ 1807 T1_Skip_Spaces ( parser ); 1808 } 1809 1810 /* if we use a hash, the subrs index is the key, and a running */ 1811 /* counter specified for `T1_Add_Table' acts as the value */ 1812 if ( loader->subrs_hash ) 1813 { 1814 ft_hash_num_insert( idx, count, loader->subrs_hash, memory ); 1815 idx = count; 1816 } 1817 1818 /* with synthetic fonts it is possible we get here twice */ 1819 if ( loader->num_subrs ) 1820 continue; 1821 1822 /* some fonts use a value of -1 for lenIV to indicate that */ 1823 /* the charstrings are unencoded */ 1824 /* */ 1825 /* thanks to Tom Kacvinsky for pointing this out */ 1826 /* */ 1827 if ( face->type1.private_dict.lenIV >= 0 ) 1828 { 1829 FT_Byte* temp = NULL; 1830 1831 1832 /* some fonts define empty subr records -- this is not totally */ 1833 /* compliant to the specification (which says they should at */ 1834 /* least contain a `return'), but we support them anyway */ 1835 if ( size < (FT_ULong)face->type1.private_dict.lenIV ) 1836 { 1837 error = FT_THROW( Invalid_File_Format ); 1838 goto Fail; 1839 } 1840 1841 /* t1_decrypt() shouldn't write to base -- make temporary copy */ 1842 if ( FT_ALLOC( temp, size ) ) 1843 goto Fail; 1844 FT_MEM_COPY( temp, base, size ); 1845 psaux->t1_decrypt( temp, size, 4330 ); 1846 size -= (FT_ULong)face->type1.private_dict.lenIV; 1847 error = T1_Add_Table( table, (FT_Int)idx, 1848 temp + face->type1.private_dict.lenIV, size ); 1849 FT_FREE( temp ); 1850 } 1851 else 1852 error = T1_Add_Table( table, (FT_Int)idx, base, size ); 1853 if ( error ) 1854 goto Fail; 1855 } 1856 1857 if ( !loader->num_subrs ) 1858 loader->num_subrs = num_subrs; 1859 1860 #ifdef FT_DEBUG_LEVEL_TRACE 1861 FT_TRACE4(( " <" )); 1862 1863 /* XXX show subrs? */ 1864 FT_TRACE4(( "%d elements", num_subrs )); 1865 1866 FT_TRACE4(( ">\n" )); 1867 #endif 1868 1869 return; 1870 1871 Fail: 1872 parser->root.error = error; 1873 } 1874 1875 1876 #define TABLE_EXTEND 5 1877 1878 1879 static void 1880 parse_charstrings( T1_Face face, 1881 T1_Loader loader ) 1882 { 1883 T1_Parser parser = &loader->parser; 1884 PS_Table code_table = &loader->charstrings; 1885 PS_Table name_table = &loader->glyph_names; 1886 PS_Table swap_table = &loader->swap_table; 1887 FT_Memory memory = parser->root.memory; 1888 FT_Error error; 1889 1890 PSAux_Service psaux = (PSAux_Service)face->psaux; 1891 1892 FT_Byte* cur = parser->root.cursor; 1893 FT_Byte* limit = parser->root.limit; 1894 FT_Int n, num_glyphs; 1895 FT_Int notdef_index = 0; 1896 FT_Byte notdef_found = 0; 1897 1898 1899 num_glyphs = (FT_Int)T1_ToInt( parser ); 1900 if ( num_glyphs < 0 ) 1901 { 1902 error = FT_THROW( Invalid_File_Format ); 1903 goto Fail; 1904 } 1905 1906 /* we certainly need more than 8 bytes per glyph */ 1907 if ( num_glyphs > ( limit - cur ) >> 3 ) 1908 { 1909 FT_TRACE0(( "parse_charstrings: adjusting number of glyphs" 1910 " (from %d to %d)\n", 1911 num_glyphs, ( limit - cur ) >> 3 )); 1912 num_glyphs = ( limit - cur ) >> 3; 1913 } 1914 1915 /* some fonts like Optima-Oblique not only define the /CharStrings */ 1916 /* array but access it also */ 1917 if ( num_glyphs == 0 || parser->root.error ) 1918 return; 1919 1920 /* initialize tables, leaving space for addition of .notdef, */ 1921 /* if necessary, and a few other glyphs to handle buggy */ 1922 /* fonts which have more glyphs than specified. */ 1923 1924 /* for some non-standard fonts like `Optima' which provides */ 1925 /* different outlines depending on the resolution it is */ 1926 /* possible to get here twice */ 1927 if ( !loader->num_glyphs ) 1928 { 1929 error = psaux->ps_table_funcs->init( 1930 code_table, num_glyphs + 1 + TABLE_EXTEND, memory ); 1931 if ( error ) 1932 goto Fail; 1933 1934 error = psaux->ps_table_funcs->init( 1935 name_table, num_glyphs + 1 + TABLE_EXTEND, memory ); 1936 if ( error ) 1937 goto Fail; 1938 1939 /* Initialize table for swapping index notdef_index and */ 1940 /* index 0 names and codes (if necessary). */ 1941 1942 error = psaux->ps_table_funcs->init( swap_table, 4, memory ); 1943 if ( error ) 1944 goto Fail; 1945 } 1946 1947 n = 0; 1948 1949 for (;;) 1950 { 1951 FT_ULong size; 1952 FT_Byte* base; 1953 1954 1955 /* the format is simple: */ 1956 /* `/glyphname' + binary data */ 1957 1958 T1_Skip_Spaces( parser ); 1959 1960 cur = parser->root.cursor; 1961 if ( cur >= limit ) 1962 break; 1963 1964 /* we stop when we find a `def' or `end' keyword */ 1965 if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) ) 1966 { 1967 if ( cur[0] == 'd' && 1968 cur[1] == 'e' && 1969 cur[2] == 'f' ) 1970 { 1971 /* There are fonts which have this: */ 1972 /* */ 1973 /* /CharStrings 118 dict def */ 1974 /* Private begin */ 1975 /* CharStrings begin */ 1976 /* ... */ 1977 /* */ 1978 /* To catch this we ignore `def' if */ 1979 /* no charstring has actually been */ 1980 /* seen. */ 1981 if ( n ) 1982 break; 1983 } 1984 1985 if ( cur[0] == 'e' && 1986 cur[1] == 'n' && 1987 cur[2] == 'd' ) 1988 break; 1989 } 1990 1991 T1_Skip_PS_Token( parser ); 1992 if ( parser->root.cursor >= limit ) 1993 { 1994 error = FT_THROW( Invalid_File_Format ); 1995 goto Fail; 1996 } 1997 if ( parser->root.error ) 1998 return; 1999 2000 if ( *cur == '/' ) 2001 { 2002 FT_UInt len; 2003 2004 2005 if ( cur + 2 >= limit ) 2006 { 2007 error = FT_THROW( Invalid_File_Format ); 2008 goto Fail; 2009 } 2010 2011 cur++; /* skip `/' */ 2012 len = (FT_UInt)( parser->root.cursor - cur ); 2013 2014 if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) ) 2015 return; 2016 2017 /* for some non-standard fonts like `Optima' which provides */ 2018 /* different outlines depending on the resolution it is */ 2019 /* possible to get here twice */ 2020 if ( loader->num_glyphs ) 2021 continue; 2022 2023 error = T1_Add_Table( name_table, n, cur, len + 1 ); 2024 if ( error ) 2025 goto Fail; 2026 2027 /* add a trailing zero to the name table */ 2028 name_table->elements[n][len] = '\0'; 2029 2030 /* record index of /.notdef */ 2031 if ( *cur == '.' && 2032 ft_strcmp( ".notdef", 2033 (const char*)(name_table->elements[n]) ) == 0 ) 2034 { 2035 notdef_index = n; 2036 notdef_found = 1; 2037 } 2038 2039 if ( face->type1.private_dict.lenIV >= 0 && 2040 n < num_glyphs + TABLE_EXTEND ) 2041 { 2042 FT_Byte* temp = NULL; 2043 2044 2045 if ( size <= (FT_ULong)face->type1.private_dict.lenIV ) 2046 { 2047 error = FT_THROW( Invalid_File_Format ); 2048 goto Fail; 2049 } 2050 2051 /* t1_decrypt() shouldn't write to base -- make temporary copy */ 2052 if ( FT_ALLOC( temp, size ) ) 2053 goto Fail; 2054 FT_MEM_COPY( temp, base, size ); 2055 psaux->t1_decrypt( temp, size, 4330 ); 2056 size -= (FT_ULong)face->type1.private_dict.lenIV; 2057 error = T1_Add_Table( code_table, n, 2058 temp + face->type1.private_dict.lenIV, size ); 2059 FT_FREE( temp ); 2060 } 2061 else 2062 error = T1_Add_Table( code_table, n, base, size ); 2063 if ( error ) 2064 goto Fail; 2065 2066 n++; 2067 } 2068 } 2069 2070 if ( !n ) 2071 { 2072 error = FT_THROW( Invalid_File_Format ); 2073 goto Fail; 2074 } 2075 2076 loader->num_glyphs = n; 2077 2078 /* if /.notdef is found but does not occupy index 0, do our magic. */ 2079 if ( notdef_found && 2080 ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) ) 2081 { 2082 /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ 2083 /* name and code entries to swap_table. Then place notdef_index */ 2084 /* name and code entries into swap_table. Then swap name and code */ 2085 /* entries at indices notdef_index and 0 using values stored in */ 2086 /* swap_table. */ 2087 2088 /* Index 0 name */ 2089 error = T1_Add_Table( swap_table, 0, 2090 name_table->elements[0], 2091 name_table->lengths [0] ); 2092 if ( error ) 2093 goto Fail; 2094 2095 /* Index 0 code */ 2096 error = T1_Add_Table( swap_table, 1, 2097 code_table->elements[0], 2098 code_table->lengths [0] ); 2099 if ( error ) 2100 goto Fail; 2101 2102 /* Index notdef_index name */ 2103 error = T1_Add_Table( swap_table, 2, 2104 name_table->elements[notdef_index], 2105 name_table->lengths [notdef_index] ); 2106 if ( error ) 2107 goto Fail; 2108 2109 /* Index notdef_index code */ 2110 error = T1_Add_Table( swap_table, 3, 2111 code_table->elements[notdef_index], 2112 code_table->lengths [notdef_index] ); 2113 if ( error ) 2114 goto Fail; 2115 2116 error = T1_Add_Table( name_table, notdef_index, 2117 swap_table->elements[0], 2118 swap_table->lengths [0] ); 2119 if ( error ) 2120 goto Fail; 2121 2122 error = T1_Add_Table( code_table, notdef_index, 2123 swap_table->elements[1], 2124 swap_table->lengths [1] ); 2125 if ( error ) 2126 goto Fail; 2127 2128 error = T1_Add_Table( name_table, 0, 2129 swap_table->elements[2], 2130 swap_table->lengths [2] ); 2131 if ( error ) 2132 goto Fail; 2133 2134 error = T1_Add_Table( code_table, 0, 2135 swap_table->elements[3], 2136 swap_table->lengths [3] ); 2137 if ( error ) 2138 goto Fail; 2139 2140 } 2141 else if ( !notdef_found ) 2142 { 2143 /* notdef_index is already 0, or /.notdef is undefined in */ 2144 /* charstrings dictionary. Worry about /.notdef undefined. */ 2145 /* We take index 0 and add it to the end of the table(s) */ 2146 /* and add our own /.notdef glyph to index 0. */ 2147 2148 /* 0 333 hsbw endchar */ 2149 FT_Byte notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E }; 2150 char* notdef_name = (char *)".notdef"; 2151 2152 2153 error = T1_Add_Table( swap_table, 0, 2154 name_table->elements[0], 2155 name_table->lengths [0] ); 2156 if ( error ) 2157 goto Fail; 2158 2159 error = T1_Add_Table( swap_table, 1, 2160 code_table->elements[0], 2161 code_table->lengths [0] ); 2162 if ( error ) 2163 goto Fail; 2164 2165 error = T1_Add_Table( name_table, 0, notdef_name, 8 ); 2166 if ( error ) 2167 goto Fail; 2168 2169 error = T1_Add_Table( code_table, 0, notdef_glyph, 5 ); 2170 2171 if ( error ) 2172 goto Fail; 2173 2174 error = T1_Add_Table( name_table, n, 2175 swap_table->elements[0], 2176 swap_table->lengths [0] ); 2177 if ( error ) 2178 goto Fail; 2179 2180 error = T1_Add_Table( code_table, n, 2181 swap_table->elements[1], 2182 swap_table->lengths [1] ); 2183 if ( error ) 2184 goto Fail; 2185 2186 /* we added a glyph. */ 2187 loader->num_glyphs += 1; 2188 } 2189 2190 #ifdef FT_DEBUG_LEVEL_TRACE 2191 FT_TRACE4(( " <" )); 2192 2193 /* XXX show charstrings? */ 2194 FT_TRACE4(( "%d elements", loader->num_glyphs )); 2195 2196 FT_TRACE4(( ">\n" )); 2197 #endif 2198 2199 return; 2200 2201 Fail: 2202 parser->root.error = error; 2203 } 2204 2205 2206 /************************************************************************** 2207 * 2208 * Define the token field static variables. This is a set of 2209 * T1_FieldRec variables. 2210 * 2211 */ 2212 2213 2214 static 2215 const T1_FieldRec t1_keywords[] = 2216 { 2217 2218 #include "t1tokens.h" 2219 2220 /* now add the special functions... */ 2221 T1_FIELD_CALLBACK( "FontMatrix", t1_parse_font_matrix, 2222 T1_FIELD_DICT_FONTDICT ) 2223 T1_FIELD_CALLBACK( "Encoding", parse_encoding, 2224 T1_FIELD_DICT_FONTDICT ) 2225 T1_FIELD_CALLBACK( "Subrs", parse_subrs, 2226 T1_FIELD_DICT_PRIVATE ) 2227 T1_FIELD_CALLBACK( "CharStrings", parse_charstrings, 2228 T1_FIELD_DICT_PRIVATE ) 2229 T1_FIELD_CALLBACK( "Private", parse_private, 2230 T1_FIELD_DICT_FONTDICT ) 2231 2232 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 2233 T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions, 2234 T1_FIELD_DICT_FONTDICT ) 2235 T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map, 2236 T1_FIELD_DICT_FONTDICT ) 2237 T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types, 2238 T1_FIELD_DICT_FONTDICT ) 2239 T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector, 2240 T1_FIELD_DICT_FONTDICT ) 2241 T1_FIELD_CALLBACK( "BuildCharArray", parse_buildchar, 2242 T1_FIELD_DICT_PRIVATE ) 2243 #endif 2244 2245 { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 } 2246 }; 2247 2248 2249 static FT_Error 2250 parse_dict( T1_Face face, 2251 T1_Loader loader, 2252 FT_Byte* base, 2253 FT_ULong size ) 2254 { 2255 T1_Parser parser = &loader->parser; 2256 FT_Byte *limit, *start_binary = NULL; 2257 FT_Bool have_integer = 0; 2258 2259 2260 parser->root.cursor = base; 2261 parser->root.limit = base + size; 2262 parser->root.error = FT_Err_Ok; 2263 2264 limit = parser->root.limit; 2265 2266 T1_Skip_Spaces( parser ); 2267 2268 while ( parser->root.cursor < limit ) 2269 { 2270 FT_Byte* cur; 2271 2272 2273 cur = parser->root.cursor; 2274 2275 /* look for `eexec' */ 2276 if ( IS_PS_TOKEN( cur, limit, "eexec" ) ) 2277 break; 2278 2279 /* look for `closefile' which ends the eexec section */ 2280 else if ( IS_PS_TOKEN( cur, limit, "closefile" ) ) 2281 break; 2282 2283 /* in a synthetic font the base font starts after a */ 2284 /* `FontDictionary' token that is placed after a Private dict */ 2285 else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) ) 2286 { 2287 if ( loader->keywords_encountered & T1_PRIVATE ) 2288 loader->keywords_encountered |= 2289 T1_FONTDIR_AFTER_PRIVATE; 2290 parser->root.cursor += 13; 2291 } 2292 2293 /* check whether we have an integer */ 2294 else if ( ft_isdigit( *cur ) ) 2295 { 2296 start_binary = cur; 2297 T1_Skip_PS_Token( parser ); 2298 if ( parser->root.error ) 2299 goto Exit; 2300 have_integer = 1; 2301 } 2302 2303 /* in valid Type 1 fonts we don't see `RD' or `-|' directly */ 2304 /* since those tokens are handled by parse_subrs and */ 2305 /* parse_charstrings */ 2306 else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' && 2307 have_integer ) 2308 { 2309 FT_ULong s; 2310 FT_Byte* b; 2311 2312 2313 parser->root.cursor = start_binary; 2314 if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) ) 2315 return FT_THROW( Invalid_File_Format ); 2316 have_integer = 0; 2317 } 2318 2319 else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' && 2320 have_integer ) 2321 { 2322 FT_ULong s; 2323 FT_Byte* b; 2324 2325 2326 parser->root.cursor = start_binary; 2327 if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) ) 2328 return FT_THROW( Invalid_File_Format ); 2329 have_integer = 0; 2330 } 2331 2332 /* look for immediates */ 2333 else if ( *cur == '/' && cur + 2 < limit ) 2334 { 2335 FT_UInt len; 2336 2337 2338 cur++; 2339 2340 parser->root.cursor = cur; 2341 T1_Skip_PS_Token( parser ); 2342 if ( parser->root.error ) 2343 goto Exit; 2344 2345 len = (FT_UInt)( parser->root.cursor - cur ); 2346 2347 if ( len > 0 && len < 22 && parser->root.cursor < limit ) 2348 { 2349 /* now compare the immediate name to the keyword table */ 2350 T1_Field keyword = (T1_Field)t1_keywords; 2351 2352 2353 for (;;) 2354 { 2355 FT_Byte* name; 2356 2357 2358 name = (FT_Byte*)keyword->ident; 2359 if ( !name ) 2360 break; 2361 2362 if ( cur[0] == name[0] && 2363 len == ft_strlen( (const char *)name ) && 2364 ft_memcmp( cur, name, len ) == 0 ) 2365 { 2366 /* We found it -- run the parsing callback! */ 2367 /* We record every instance of every field */ 2368 /* (until we reach the base font of a */ 2369 /* synthetic font) to deal adequately with */ 2370 /* multiple master fonts; this is also */ 2371 /* necessary because later PostScript */ 2372 /* definitions override earlier ones. */ 2373 2374 /* Once we encounter `FontDirectory' after */ 2375 /* `/Private', we know that this is a synthetic */ 2376 /* font; except for `/CharStrings' we are not */ 2377 /* interested in anything that follows this */ 2378 /* `FontDirectory'. */ 2379 2380 /* MM fonts have more than one /Private token at */ 2381 /* the top level; let's hope that all the junk */ 2382 /* that follows the first /Private token is not */ 2383 /* interesting to us. */ 2384 2385 /* According to Adobe Tech Note #5175 (CID-Keyed */ 2386 /* Font Installation for ATM Software) a `begin' */ 2387 /* must be followed by exactly one `end', and */ 2388 /* `begin' -- `end' pairs must be accurately */ 2389 /* paired. We could use this to distinguish */ 2390 /* between the global Private and the Private */ 2391 /* dict that is a member of the Blend dict. */ 2392 2393 const FT_UInt dict = 2394 ( loader->keywords_encountered & T1_PRIVATE ) 2395 ? T1_FIELD_DICT_PRIVATE 2396 : T1_FIELD_DICT_FONTDICT; 2397 2398 2399 if ( !( dict & keyword->dict ) ) 2400 { 2401 FT_TRACE1(( "parse_dict: found `%s' but ignoring it" 2402 " since it is in the wrong dictionary\n", 2403 keyword->ident )); 2404 break; 2405 } 2406 2407 if ( !( loader->keywords_encountered & 2408 T1_FONTDIR_AFTER_PRIVATE ) || 2409 ft_strcmp( (const char*)name, "CharStrings" ) == 0 ) 2410 { 2411 parser->root.error = t1_load_keyword( face, 2412 loader, 2413 keyword ); 2414 if ( parser->root.error ) 2415 { 2416 if ( FT_ERR_EQ( parser->root.error, Ignore ) ) 2417 parser->root.error = FT_Err_Ok; 2418 else 2419 return parser->root.error; 2420 } 2421 } 2422 break; 2423 } 2424 2425 keyword++; 2426 } 2427 } 2428 2429 have_integer = 0; 2430 } 2431 else 2432 { 2433 T1_Skip_PS_Token( parser ); 2434 if ( parser->root.error ) 2435 goto Exit; 2436 have_integer = 0; 2437 } 2438 2439 T1_Skip_Spaces( parser ); 2440 } 2441 2442 Exit: 2443 return parser->root.error; 2444 } 2445 2446 2447 static void 2448 t1_init_loader( T1_Loader loader, 2449 T1_Face face ) 2450 { 2451 FT_UNUSED( face ); 2452 2453 FT_ZERO( loader ); 2454 } 2455 2456 2457 static void 2458 t1_done_loader( T1_Loader loader ) 2459 { 2460 T1_Parser parser = &loader->parser; 2461 FT_Memory memory = parser->root.memory; 2462 2463 2464 /* finalize tables */ 2465 T1_Release_Table( &loader->encoding_table ); 2466 T1_Release_Table( &loader->charstrings ); 2467 T1_Release_Table( &loader->glyph_names ); 2468 T1_Release_Table( &loader->swap_table ); 2469 T1_Release_Table( &loader->subrs ); 2470 2471 /* finalize hash */ 2472 ft_hash_num_free( loader->subrs_hash, memory ); 2473 FT_FREE( loader->subrs_hash ); 2474 2475 /* finalize parser */ 2476 T1_Finalize_Parser( parser ); 2477 } 2478 2479 2480 FT_LOCAL_DEF( FT_Error ) 2481 T1_Open_Face( T1_Face face ) 2482 { 2483 T1_LoaderRec loader; 2484 T1_Parser parser; 2485 T1_Font type1 = &face->type1; 2486 PS_Private priv = &type1->private_dict; 2487 FT_Error error; 2488 2489 PSAux_Service psaux = (PSAux_Service)face->psaux; 2490 2491 2492 t1_init_loader( &loader, face ); 2493 2494 /* default values */ 2495 face->ndv_idx = -1; 2496 face->cdv_idx = -1; 2497 face->len_buildchar = 0; 2498 2499 priv->blue_shift = 7; 2500 priv->blue_fuzz = 1; 2501 priv->lenIV = 4; 2502 priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L ); 2503 priv->blue_scale = (FT_Fixed)( 0.039625 * 0x10000L * 1000 ); 2504 2505 parser = &loader.parser; 2506 error = T1_New_Parser( parser, 2507 face->root.stream, 2508 face->root.memory, 2509 psaux ); 2510 if ( error ) 2511 goto Exit; 2512 2513 FT_TRACE4(( " top dictionary:\n" )); 2514 error = parse_dict( face, &loader, 2515 parser->base_dict, parser->base_len ); 2516 if ( error ) 2517 goto Exit; 2518 2519 error = T1_Get_Private_Dict( parser, psaux ); 2520 if ( error ) 2521 goto Exit; 2522 2523 FT_TRACE4(( " private dictionary:\n" )); 2524 error = parse_dict( face, &loader, 2525 parser->private_dict, parser->private_len ); 2526 if ( error ) 2527 goto Exit; 2528 2529 /* ensure even-ness of `num_blue_values' */ 2530 priv->num_blue_values &= ~1; 2531 2532 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 2533 2534 /* we don't support Multiple Master fonts with intermediate designs; */ 2535 /* this implies that `num_designs' must be equal to `2^^num_axis' */ 2536 if ( face->blend && 2537 face->blend->num_designs != ( 1U << face->blend->num_axis ) ) 2538 { 2539 FT_ERROR(( "T1_Open_Face:" 2540 " number-of-designs != 2 ^^ number-of-axes\n" )); 2541 T1_Done_Blend( face ); 2542 } 2543 2544 if ( face->blend && 2545 face->blend->num_default_design_vector != 0 && 2546 face->blend->num_default_design_vector != face->blend->num_axis ) 2547 { 2548 /* we don't use it currently so just warn, reset, and ignore */ 2549 FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries " 2550 "while there are %u axes.\n", 2551 face->blend->num_default_design_vector, 2552 face->blend->num_axis )); 2553 2554 face->blend->num_default_design_vector = 0; 2555 } 2556 2557 /* the following can happen for MM instances; we then treat the */ 2558 /* font as a normal PS font */ 2559 if ( face->blend && 2560 ( !face->blend->num_designs || !face->blend->num_axis ) ) 2561 T1_Done_Blend( face ); 2562 2563 /* another safety check */ 2564 if ( face->blend ) 2565 { 2566 FT_UInt i; 2567 2568 2569 for ( i = 0; i < face->blend->num_axis; i++ ) 2570 if ( !face->blend->design_map[i].num_points ) 2571 { 2572 T1_Done_Blend( face ); 2573 break; 2574 } 2575 } 2576 2577 if ( face->blend ) 2578 { 2579 if ( face->len_buildchar > 0 ) 2580 { 2581 FT_Memory memory = face->root.memory; 2582 2583 2584 if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) ) 2585 { 2586 FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" )); 2587 face->len_buildchar = 0; 2588 goto Exit; 2589 } 2590 } 2591 } 2592 else 2593 face->len_buildchar = 0; 2594 2595 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */ 2596 2597 /* now, propagate the subrs, charstrings, and glyphnames tables */ 2598 /* to the Type1 data */ 2599 type1->num_glyphs = loader.num_glyphs; 2600 2601 if ( loader.subrs.init ) 2602 { 2603 type1->num_subrs = loader.num_subrs; 2604 type1->subrs_block = loader.subrs.block; 2605 type1->subrs = loader.subrs.elements; 2606 type1->subrs_len = loader.subrs.lengths; 2607 type1->subrs_hash = loader.subrs_hash; 2608 2609 /* prevent `t1_done_loader' from freeing the propagated data */ 2610 loader.subrs.init = 0; 2611 loader.subrs_hash = NULL; 2612 } 2613 2614 if ( !IS_INCREMENTAL ) 2615 if ( !loader.charstrings.init ) 2616 { 2617 FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" )); 2618 error = FT_THROW( Invalid_File_Format ); 2619 } 2620 2621 loader.charstrings.init = 0; 2622 type1->charstrings_block = loader.charstrings.block; 2623 type1->charstrings = loader.charstrings.elements; 2624 type1->charstrings_len = loader.charstrings.lengths; 2625 2626 /* we copy the glyph names `block' and `elements' fields; */ 2627 /* the `lengths' field must be released later */ 2628 type1->glyph_names_block = loader.glyph_names.block; 2629 type1->glyph_names = (FT_String**)loader.glyph_names.elements; 2630 loader.glyph_names.block = NULL; 2631 loader.glyph_names.elements = NULL; 2632 2633 /* we must now build type1.encoding when we have a custom array */ 2634 if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) 2635 { 2636 FT_Int charcode, idx, min_char, max_char; 2637 FT_Byte* glyph_name; 2638 2639 2640 /* OK, we do the following: for each element in the encoding */ 2641 /* table, look up the index of the glyph having the same name */ 2642 /* the index is then stored in type1.encoding.char_index, and */ 2643 /* the name to type1.encoding.char_name */ 2644 2645 min_char = 0; 2646 max_char = 0; 2647 2648 charcode = 0; 2649 for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) 2650 { 2651 FT_Byte* char_name; 2652 2653 2654 type1->encoding.char_index[charcode] = 0; 2655 type1->encoding.char_name [charcode] = (char *)".notdef"; 2656 2657 char_name = loader.encoding_table.elements[charcode]; 2658 if ( char_name ) 2659 for ( idx = 0; idx < type1->num_glyphs; idx++ ) 2660 { 2661 glyph_name = (FT_Byte*)type1->glyph_names[idx]; 2662 if ( ft_strcmp( (const char*)char_name, 2663 (const char*)glyph_name ) == 0 ) 2664 { 2665 type1->encoding.char_index[charcode] = (FT_UShort)idx; 2666 type1->encoding.char_name [charcode] = (char*)glyph_name; 2667 2668 /* Change min/max encoded char only if glyph name is */ 2669 /* not /.notdef */ 2670 if ( ft_strcmp( (const char*)".notdef", 2671 (const char*)glyph_name ) != 0 ) 2672 { 2673 if ( charcode < min_char ) 2674 min_char = charcode; 2675 if ( charcode >= max_char ) 2676 max_char = charcode + 1; 2677 } 2678 break; 2679 } 2680 } 2681 } 2682 2683 type1->encoding.code_first = min_char; 2684 type1->encoding.code_last = max_char; 2685 type1->encoding.num_chars = loader.num_chars; 2686 } 2687 2688 /* some sanitizing to avoid overflows later on; */ 2689 /* the upper limits are ad-hoc values */ 2690 if ( priv->blue_shift > 1000 || priv->blue_shift < 0 ) 2691 { 2692 FT_TRACE2(( "T1_Open_Face:" 2693 " setting unlikely BlueShift value %d to default (7)\n", 2694 priv->blue_shift )); 2695 priv->blue_shift = 7; 2696 } 2697 2698 if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 ) 2699 { 2700 FT_TRACE2(( "T1_Open_Face:" 2701 " setting unlikely BlueFuzz value %d to default (1)\n", 2702 priv->blue_fuzz )); 2703 priv->blue_fuzz = 1; 2704 } 2705 2706 Exit: 2707 t1_done_loader( &loader ); 2708 return error; 2709 } 2710 2711 2712 /* END */