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