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