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