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