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