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