| OLD | NEW |
| (Empty) |
| 1 /***************************************************************************/ | |
| 2 /* */ | |
| 3 /* t1decode.c */ | |
| 4 /* */ | |
| 5 /* PostScript Type 1 decoding routines (body). */ | |
| 6 /* */ | |
| 7 /* Copyright 2000-2013 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 #include "../../include/ft2build.h" | |
| 20 #include "../../include/freetype/internal/ftcalc.h" | |
| 21 #include "../../include/freetype/internal/ftdebug.h" | |
| 22 #include "../../include/freetype/internal/pshints.h" | |
| 23 #include "../../include/freetype/ftoutln.h" | |
| 24 | |
| 25 #include "t1decode.h" | |
| 26 #include "psobjs.h" | |
| 27 | |
| 28 #include "psauxerr.h" | |
| 29 | |
| 30 /* ensure proper sign extension */ | |
| 31 #define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) | |
| 32 | |
| 33 /*************************************************************************/ | |
| 34 /* */ | |
| 35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
| 36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
| 37 /* messages during execution. */ | |
| 38 /* */ | |
| 39 #undef FT_COMPONENT | |
| 40 #define FT_COMPONENT trace_t1decode | |
| 41 | |
| 42 | |
| 43 typedef enum T1_Operator_ | |
| 44 { | |
| 45 op_none = 0, | |
| 46 op_endchar, | |
| 47 op_hsbw, | |
| 48 op_seac, | |
| 49 op_sbw, | |
| 50 op_closepath, | |
| 51 op_hlineto, | |
| 52 op_hmoveto, | |
| 53 op_hvcurveto, | |
| 54 op_rlineto, | |
| 55 op_rmoveto, | |
| 56 op_rrcurveto, | |
| 57 op_vhcurveto, | |
| 58 op_vlineto, | |
| 59 op_vmoveto, | |
| 60 op_dotsection, | |
| 61 op_hstem, | |
| 62 op_hstem3, | |
| 63 op_vstem, | |
| 64 op_vstem3, | |
| 65 op_div, | |
| 66 op_callothersubr, | |
| 67 op_callsubr, | |
| 68 op_pop, | |
| 69 op_return, | |
| 70 op_setcurrentpoint, | |
| 71 op_unknown15, | |
| 72 | |
| 73 op_max /* never remove this one */ | |
| 74 | |
| 75 } T1_Operator; | |
| 76 | |
| 77 | |
| 78 static | |
| 79 const FT_Int t1_args_count[op_max] = | |
| 80 { | |
| 81 0, /* none */ | |
| 82 0, /* endchar */ | |
| 83 2, /* hsbw */ | |
| 84 5, /* seac */ | |
| 85 4, /* sbw */ | |
| 86 0, /* closepath */ | |
| 87 1, /* hlineto */ | |
| 88 1, /* hmoveto */ | |
| 89 4, /* hvcurveto */ | |
| 90 2, /* rlineto */ | |
| 91 2, /* rmoveto */ | |
| 92 6, /* rrcurveto */ | |
| 93 4, /* vhcurveto */ | |
| 94 1, /* vlineto */ | |
| 95 1, /* vmoveto */ | |
| 96 0, /* dotsection */ | |
| 97 2, /* hstem */ | |
| 98 6, /* hstem3 */ | |
| 99 2, /* vstem */ | |
| 100 6, /* vstem3 */ | |
| 101 2, /* div */ | |
| 102 -1, /* callothersubr */ | |
| 103 1, /* callsubr */ | |
| 104 0, /* pop */ | |
| 105 0, /* return */ | |
| 106 2, /* setcurrentpoint */ | |
| 107 2 /* opcode 15 (undocumented and obsolete) */ | |
| 108 }; | |
| 109 | |
| 110 | |
| 111 /*************************************************************************/ | |
| 112 /* */ | |
| 113 /* <Function> */ | |
| 114 /* t1_lookup_glyph_by_stdcharcode */ | |
| 115 /* */ | |
| 116 /* <Description> */ | |
| 117 /* Looks up a given glyph by its StandardEncoding charcode. Used to */ | |
| 118 /* implement the SEAC Type 1 operator. */ | |
| 119 /* */ | |
| 120 /* <Input> */ | |
| 121 /* face :: The current face object. */ | |
| 122 /* */ | |
| 123 /* charcode :: The character code to look for. */ | |
| 124 /* */ | |
| 125 /* <Return> */ | |
| 126 /* A glyph index in the font face. Returns -1 if the corresponding */ | |
| 127 /* glyph wasn't found. */ | |
| 128 /* */ | |
| 129 static FT_Int | |
| 130 t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, | |
| 131 FT_Int charcode ) | |
| 132 { | |
| 133 FT_UInt n; | |
| 134 const FT_String* glyph_name; | |
| 135 FT_Service_PsCMaps psnames = decoder->psnames; | |
| 136 | |
| 137 | |
| 138 /* check range of standard char code */ | |
| 139 if ( charcode < 0 || charcode > 255 ) | |
| 140 return -1; | |
| 141 | |
| 142 glyph_name = psnames->adobe_std_strings( | |
| 143 psnames->adobe_std_encoding[charcode]); | |
| 144 | |
| 145 for ( n = 0; n < decoder->num_glyphs; n++ ) | |
| 146 { | |
| 147 FT_String* name = (FT_String*)decoder->glyph_names[n]; | |
| 148 | |
| 149 | |
| 150 if ( name && | |
| 151 name[0] == glyph_name[0] && | |
| 152 ft_strcmp( name, glyph_name ) == 0 ) | |
| 153 return n; | |
| 154 } | |
| 155 | |
| 156 return -1; | |
| 157 } | |
| 158 | |
| 159 | |
| 160 /*************************************************************************/ | |
| 161 /* */ | |
| 162 /* <Function> */ | |
| 163 /* t1operator_seac */ | |
| 164 /* */ | |
| 165 /* <Description> */ | |
| 166 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ | |
| 167 /* */ | |
| 168 /* <Input> */ | |
| 169 /* decoder :: The current CID decoder. */ | |
| 170 /* */ | |
| 171 /* asb :: The accent's side bearing. */ | |
| 172 /* */ | |
| 173 /* adx :: The horizontal offset of the accent. */ | |
| 174 /* */ | |
| 175 /* ady :: The vertical offset of the accent. */ | |
| 176 /* */ | |
| 177 /* bchar :: The base character's StandardEncoding charcode. */ | |
| 178 /* */ | |
| 179 /* achar :: The accent character's StandardEncoding charcode. */ | |
| 180 /* */ | |
| 181 /* <Return> */ | |
| 182 /* FreeType error code. 0 means success. */ | |
| 183 /* */ | |
| 184 static FT_Error | |
| 185 t1operator_seac( T1_Decoder decoder, | |
| 186 FT_Pos asb, | |
| 187 FT_Pos adx, | |
| 188 FT_Pos ady, | |
| 189 FT_Int bchar, | |
| 190 FT_Int achar ) | |
| 191 { | |
| 192 FT_Error error; | |
| 193 FT_Int bchar_index, achar_index; | |
| 194 #if 0 | |
| 195 FT_Int n_base_points; | |
| 196 FT_Outline* base = decoder->builder.base; | |
| 197 #endif | |
| 198 FT_Vector left_bearing, advance; | |
| 199 | |
| 200 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 201 T1_Face face = (T1_Face)decoder->builder.face; | |
| 202 #endif | |
| 203 | |
| 204 | |
| 205 if ( decoder->seac ) | |
| 206 { | |
| 207 FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); | |
| 208 return FT_THROW( Syntax_Error ); | |
| 209 } | |
| 210 | |
| 211 if ( decoder->builder.metrics_only ) | |
| 212 { | |
| 213 FT_ERROR(( "t1operator_seac: unexpected seac\n" )); | |
| 214 return FT_THROW( Syntax_Error ); | |
| 215 } | |
| 216 | |
| 217 /* seac weirdness */ | |
| 218 adx += decoder->builder.left_bearing.x; | |
| 219 | |
| 220 /* `glyph_names' is set to 0 for CID fonts which do not */ | |
| 221 /* include an encoding. How can we deal with these? */ | |
| 222 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 223 if ( decoder->glyph_names == 0 && | |
| 224 !face->root.internal->incremental_interface ) | |
| 225 #else | |
| 226 if ( decoder->glyph_names == 0 ) | |
| 227 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 228 { | |
| 229 FT_ERROR(( "t1operator_seac:" | |
| 230 " glyph names table not available in this font\n" )); | |
| 231 return FT_THROW( Syntax_Error ); | |
| 232 } | |
| 233 | |
| 234 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 235 if ( face->root.internal->incremental_interface ) | |
| 236 { | |
| 237 /* the caller must handle the font encoding also */ | |
| 238 bchar_index = bchar; | |
| 239 achar_index = achar; | |
| 240 } | |
| 241 else | |
| 242 #endif | |
| 243 { | |
| 244 bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); | |
| 245 achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); | |
| 246 } | |
| 247 | |
| 248 if ( bchar_index < 0 || achar_index < 0 ) | |
| 249 { | |
| 250 FT_ERROR(( "t1operator_seac:" | |
| 251 " invalid seac character code arguments\n" )); | |
| 252 return FT_THROW( Syntax_Error ); | |
| 253 } | |
| 254 | |
| 255 /* if we are trying to load a composite glyph, do not load the */ | |
| 256 /* accent character and return the array of subglyphs. */ | |
| 257 if ( decoder->builder.no_recurse ) | |
| 258 { | |
| 259 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; | |
| 260 FT_GlyphLoader loader = glyph->internal->loader; | |
| 261 FT_SubGlyph subg; | |
| 262 | |
| 263 | |
| 264 /* reallocate subglyph array if necessary */ | |
| 265 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); | |
| 266 if ( error ) | |
| 267 goto Exit; | |
| 268 | |
| 269 subg = loader->current.subglyphs; | |
| 270 | |
| 271 /* subglyph 0 = base character */ | |
| 272 subg->index = bchar_index; | |
| 273 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | | |
| 274 FT_SUBGLYPH_FLAG_USE_MY_METRICS; | |
| 275 subg->arg1 = 0; | |
| 276 subg->arg2 = 0; | |
| 277 subg++; | |
| 278 | |
| 279 /* subglyph 1 = accent character */ | |
| 280 subg->index = achar_index; | |
| 281 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; | |
| 282 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); | |
| 283 subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); | |
| 284 | |
| 285 /* set up remaining glyph fields */ | |
| 286 glyph->num_subglyphs = 2; | |
| 287 glyph->subglyphs = loader->base.subglyphs; | |
| 288 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; | |
| 289 | |
| 290 loader->current.num_subglyphs = 2; | |
| 291 goto Exit; | |
| 292 } | |
| 293 | |
| 294 /* First load `bchar' in builder */ | |
| 295 /* now load the unscaled outline */ | |
| 296 | |
| 297 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ | |
| 298 | |
| 299 /* the seac operator must not be nested */ | |
| 300 decoder->seac = TRUE; | |
| 301 error = t1_decoder_parse_glyph( decoder, bchar_index ); | |
| 302 decoder->seac = FALSE; | |
| 303 if ( error ) | |
| 304 goto Exit; | |
| 305 | |
| 306 /* save the left bearing and width of the base character */ | |
| 307 /* as they will be erased by the next load. */ | |
| 308 | |
| 309 left_bearing = decoder->builder.left_bearing; | |
| 310 advance = decoder->builder.advance; | |
| 311 | |
| 312 decoder->builder.left_bearing.x = 0; | |
| 313 decoder->builder.left_bearing.y = 0; | |
| 314 | |
| 315 decoder->builder.pos_x = adx - asb; | |
| 316 decoder->builder.pos_y = ady; | |
| 317 | |
| 318 /* Now load `achar' on top of */ | |
| 319 /* the base outline */ | |
| 320 | |
| 321 /* the seac operator must not be nested */ | |
| 322 decoder->seac = TRUE; | |
| 323 error = t1_decoder_parse_glyph( decoder, achar_index ); | |
| 324 decoder->seac = FALSE; | |
| 325 if ( error ) | |
| 326 goto Exit; | |
| 327 | |
| 328 /* restore the left side bearing and */ | |
| 329 /* advance width of the base character */ | |
| 330 | |
| 331 decoder->builder.left_bearing = left_bearing; | |
| 332 decoder->builder.advance = advance; | |
| 333 | |
| 334 decoder->builder.pos_x = 0; | |
| 335 decoder->builder.pos_y = 0; | |
| 336 | |
| 337 Exit: | |
| 338 return error; | |
| 339 } | |
| 340 | |
| 341 | |
| 342 /*************************************************************************/ | |
| 343 /* */ | |
| 344 /* <Function> */ | |
| 345 /* t1_decoder_parse_charstrings */ | |
| 346 /* */ | |
| 347 /* <Description> */ | |
| 348 /* Parses a given Type 1 charstrings program. */ | |
| 349 /* */ | |
| 350 /* <Input> */ | |
| 351 /* decoder :: The current Type 1 decoder. */ | |
| 352 /* */ | |
| 353 /* charstring_base :: The base address of the charstring stream. */ | |
| 354 /* */ | |
| 355 /* charstring_len :: The length in bytes of the charstring stream. */ | |
| 356 /* */ | |
| 357 /* <Return> */ | |
| 358 /* FreeType error code. 0 means success. */ | |
| 359 /* */ | |
| 360 FT_LOCAL_DEF( FT_Error ) | |
| 361 t1_decoder_parse_charstrings( T1_Decoder decoder, | |
| 362 FT_Byte* charstring_base, | |
| 363 FT_UInt charstring_len ) | |
| 364 { | |
| 365 FT_Error error; | |
| 366 T1_Decoder_Zone zone; | |
| 367 FT_Byte* ip; | |
| 368 FT_Byte* limit; | |
| 369 T1_Builder builder = &decoder->builder; | |
| 370 FT_Pos x, y, orig_x, orig_y; | |
| 371 FT_Int known_othersubr_result_cnt = 0; | |
| 372 FT_Int unknown_othersubr_result_cnt = 0; | |
| 373 FT_Bool large_int; | |
| 374 FT_Fixed seed; | |
| 375 | |
| 376 T1_Hints_Funcs hinter; | |
| 377 | |
| 378 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 379 FT_Bool bol = TRUE; | |
| 380 #endif | |
| 381 | |
| 382 | |
| 383 /* compute random seed from stack address of parameter */ | |
| 384 seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ | |
| 385 (FT_PtrDist)(char*)&decoder ^ | |
| 386 (FT_PtrDist)(char*)&charstring_base ) & | |
| 387 FT_ULONG_MAX ) ; | |
| 388 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; | |
| 389 if ( seed == 0 ) | |
| 390 seed = 0x7384; | |
| 391 | |
| 392 /* First of all, initialize the decoder */ | |
| 393 decoder->top = decoder->stack; | |
| 394 decoder->zone = decoder->zones; | |
| 395 zone = decoder->zones; | |
| 396 | |
| 397 builder->parse_state = T1_Parse_Start; | |
| 398 | |
| 399 hinter = (T1_Hints_Funcs)builder->hints_funcs; | |
| 400 | |
| 401 /* a font that reads BuildCharArray without setting */ | |
| 402 /* its values first is buggy, but ... */ | |
| 403 FT_ASSERT( ( decoder->len_buildchar == 0 ) == | |
| 404 ( decoder->buildchar == NULL ) ); | |
| 405 | |
| 406 if ( decoder->buildchar && decoder->len_buildchar > 0 ) | |
| 407 ft_memset( &decoder->buildchar[0], | |
| 408 0, | |
| 409 sizeof ( decoder->buildchar[0] ) * decoder->len_buildchar ); | |
| 410 | |
| 411 FT_TRACE4(( "\n" | |
| 412 "Start charstring\n" )); | |
| 413 | |
| 414 zone->base = charstring_base; | |
| 415 limit = zone->limit = charstring_base + charstring_len; | |
| 416 ip = zone->cursor = zone->base; | |
| 417 | |
| 418 error = FT_Err_Ok; | |
| 419 | |
| 420 x = orig_x = builder->pos_x; | |
| 421 y = orig_y = builder->pos_y; | |
| 422 | |
| 423 /* begin hints recording session, if any */ | |
| 424 if ( hinter ) | |
| 425 hinter->open( hinter->hints ); | |
| 426 | |
| 427 large_int = FALSE; | |
| 428 | |
| 429 /* now, execute loop */ | |
| 430 while ( ip < limit ) | |
| 431 { | |
| 432 FT_Long* top = decoder->top; | |
| 433 T1_Operator op = op_none; | |
| 434 FT_Int32 value = 0; | |
| 435 | |
| 436 | |
| 437 FT_ASSERT( known_othersubr_result_cnt == 0 || | |
| 438 unknown_othersubr_result_cnt == 0 ); | |
| 439 | |
| 440 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 441 if ( bol ) | |
| 442 { | |
| 443 FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); | |
| 444 bol = FALSE; | |
| 445 } | |
| 446 #endif | |
| 447 | |
| 448 /*********************************************************************/ | |
| 449 /* */ | |
| 450 /* Decode operator or operand */ | |
| 451 /* */ | |
| 452 /* */ | |
| 453 | |
| 454 /* first of all, decompress operator or value */ | |
| 455 switch ( *ip++ ) | |
| 456 { | |
| 457 case 1: | |
| 458 op = op_hstem; | |
| 459 break; | |
| 460 | |
| 461 case 3: | |
| 462 op = op_vstem; | |
| 463 break; | |
| 464 case 4: | |
| 465 op = op_vmoveto; | |
| 466 break; | |
| 467 case 5: | |
| 468 op = op_rlineto; | |
| 469 break; | |
| 470 case 6: | |
| 471 op = op_hlineto; | |
| 472 break; | |
| 473 case 7: | |
| 474 op = op_vlineto; | |
| 475 break; | |
| 476 case 8: | |
| 477 op = op_rrcurveto; | |
| 478 break; | |
| 479 case 9: | |
| 480 op = op_closepath; | |
| 481 break; | |
| 482 case 10: | |
| 483 op = op_callsubr; | |
| 484 break; | |
| 485 case 11: | |
| 486 op = op_return; | |
| 487 break; | |
| 488 | |
| 489 case 13: | |
| 490 op = op_hsbw; | |
| 491 break; | |
| 492 case 14: | |
| 493 op = op_endchar; | |
| 494 break; | |
| 495 | |
| 496 case 15: /* undocumented, obsolete operator */ | |
| 497 op = op_unknown15; | |
| 498 break; | |
| 499 | |
| 500 case 21: | |
| 501 op = op_rmoveto; | |
| 502 break; | |
| 503 case 22: | |
| 504 op = op_hmoveto; | |
| 505 break; | |
| 506 | |
| 507 case 30: | |
| 508 op = op_vhcurveto; | |
| 509 break; | |
| 510 case 31: | |
| 511 op = op_hvcurveto; | |
| 512 break; | |
| 513 | |
| 514 case 12: | |
| 515 if ( ip > limit ) | |
| 516 { | |
| 517 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 518 " invalid escape (12+EOF)\n" )); | |
| 519 goto Syntax_Error; | |
| 520 } | |
| 521 | |
| 522 switch ( *ip++ ) | |
| 523 { | |
| 524 case 0: | |
| 525 op = op_dotsection; | |
| 526 break; | |
| 527 case 1: | |
| 528 op = op_vstem3; | |
| 529 break; | |
| 530 case 2: | |
| 531 op = op_hstem3; | |
| 532 break; | |
| 533 case 6: | |
| 534 op = op_seac; | |
| 535 break; | |
| 536 case 7: | |
| 537 op = op_sbw; | |
| 538 break; | |
| 539 case 12: | |
| 540 op = op_div; | |
| 541 break; | |
| 542 case 16: | |
| 543 op = op_callothersubr; | |
| 544 break; | |
| 545 case 17: | |
| 546 op = op_pop; | |
| 547 break; | |
| 548 case 33: | |
| 549 op = op_setcurrentpoint; | |
| 550 break; | |
| 551 | |
| 552 default: | |
| 553 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 554 " invalid escape (12+%d)\n", | |
| 555 ip[-1] )); | |
| 556 goto Syntax_Error; | |
| 557 } | |
| 558 break; | |
| 559 | |
| 560 case 255: /* four bytes integer */ | |
| 561 if ( ip + 4 > limit ) | |
| 562 { | |
| 563 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 564 " unexpected EOF in integer\n" )); | |
| 565 goto Syntax_Error; | |
| 566 } | |
| 567 | |
| 568 value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | | |
| 569 ( (FT_UInt32)ip[1] << 16 ) | | |
| 570 ( (FT_UInt32)ip[2] << 8 ) | | |
| 571 (FT_UInt32)ip[3] ); | |
| 572 ip += 4; | |
| 573 | |
| 574 /* According to the specification, values > 32000 or < -32000 must */ | |
| 575 /* be followed by a `div' operator to make the result be in the */ | |
| 576 /* range [-32000;32000]. We expect that the second argument of */ | |
| 577 /* `div' is not a large number. Additionally, we don't handle */ | |
| 578 /* stuff like `<large1> <large2> <num> div <num> div' or */ | |
| 579 /* <large1> <large2> <num> div div'. This is probably not allowed */ | |
| 580 /* anyway. */ | |
| 581 if ( value > 32000 || value < -32000 ) | |
| 582 { | |
| 583 if ( large_int ) | |
| 584 { | |
| 585 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 586 " no `div' after large integer\n" )); | |
| 587 } | |
| 588 else | |
| 589 large_int = TRUE; | |
| 590 } | |
| 591 else | |
| 592 { | |
| 593 if ( !large_int ) | |
| 594 value = (FT_Int32)( (FT_UInt32)value << 16 ); | |
| 595 } | |
| 596 | |
| 597 break; | |
| 598 | |
| 599 default: | |
| 600 if ( ip[-1] >= 32 ) | |
| 601 { | |
| 602 if ( ip[-1] < 247 ) | |
| 603 value = (FT_Int32)ip[-1] - 139; | |
| 604 else | |
| 605 { | |
| 606 if ( ++ip > limit ) | |
| 607 { | |
| 608 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 609 " unexpected EOF in integer\n" )); | |
| 610 goto Syntax_Error; | |
| 611 } | |
| 612 | |
| 613 if ( ip[-2] < 251 ) | |
| 614 value = ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108; | |
| 615 else | |
| 616 value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 ); | |
| 617 } | |
| 618 | |
| 619 if ( !large_int ) | |
| 620 value = (FT_Int32)( (FT_UInt32)value << 16 ); | |
| 621 } | |
| 622 else | |
| 623 { | |
| 624 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 625 " invalid byte (%d)\n", ip[-1] )); | |
| 626 goto Syntax_Error; | |
| 627 } | |
| 628 } | |
| 629 | |
| 630 if ( unknown_othersubr_result_cnt > 0 ) | |
| 631 { | |
| 632 switch ( op ) | |
| 633 { | |
| 634 case op_callsubr: | |
| 635 case op_return: | |
| 636 case op_none: | |
| 637 case op_pop: | |
| 638 break; | |
| 639 | |
| 640 default: | |
| 641 /* all operands have been transferred by previous pops */ | |
| 642 unknown_othersubr_result_cnt = 0; | |
| 643 break; | |
| 644 } | |
| 645 } | |
| 646 | |
| 647 if ( large_int && !( op == op_none || op == op_div ) ) | |
| 648 { | |
| 649 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 650 " no `div' after large integer\n" )); | |
| 651 | |
| 652 large_int = FALSE; | |
| 653 } | |
| 654 | |
| 655 /*********************************************************************/ | |
| 656 /* */ | |
| 657 /* Push value on stack, or process operator */ | |
| 658 /* */ | |
| 659 /* */ | |
| 660 if ( op == op_none ) | |
| 661 { | |
| 662 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) | |
| 663 { | |
| 664 FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); | |
| 665 goto Syntax_Error; | |
| 666 } | |
| 667 | |
| 668 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 669 if ( large_int ) | |
| 670 FT_TRACE4(( " %ld", value )); | |
| 671 else | |
| 672 FT_TRACE4(( " %ld", Fix2Int( value ) )); | |
| 673 #endif | |
| 674 | |
| 675 *top++ = value; | |
| 676 decoder->top = top; | |
| 677 } | |
| 678 else if ( op == op_callothersubr ) /* callothersubr */ | |
| 679 { | |
| 680 FT_Int subr_no; | |
| 681 FT_Int arg_cnt; | |
| 682 | |
| 683 | |
| 684 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 685 FT_TRACE4(( " callothersubr\n" )); | |
| 686 bol = TRUE; | |
| 687 #endif | |
| 688 | |
| 689 if ( top - decoder->stack < 2 ) | |
| 690 goto Stack_Underflow; | |
| 691 | |
| 692 top -= 2; | |
| 693 | |
| 694 subr_no = Fix2Int( top[1] ); | |
| 695 arg_cnt = Fix2Int( top[0] ); | |
| 696 | |
| 697 /***********************************************************/ | |
| 698 /* */ | |
| 699 /* remove all operands to callothersubr from the stack */ | |
| 700 /* */ | |
| 701 /* for handled othersubrs, where we know the number of */ | |
| 702 /* arguments, we increase the stack by the value of */ | |
| 703 /* known_othersubr_result_cnt */ | |
| 704 /* */ | |
| 705 /* for unhandled othersubrs the following pops adjust the */ | |
| 706 /* stack pointer as necessary */ | |
| 707 | |
| 708 if ( arg_cnt > top - decoder->stack ) | |
| 709 goto Stack_Underflow; | |
| 710 | |
| 711 top -= arg_cnt; | |
| 712 | |
| 713 known_othersubr_result_cnt = 0; | |
| 714 unknown_othersubr_result_cnt = 0; | |
| 715 | |
| 716 /* XXX TODO: The checks to `arg_count == <whatever>' */ | |
| 717 /* might not be correct; an othersubr expects a certain */ | |
| 718 /* number of operands on the PostScript stack (as opposed */ | |
| 719 /* to the T1 stack) but it doesn't have to put them there */ | |
| 720 /* by itself; previous othersubrs might have left the */ | |
| 721 /* operands there if they were not followed by an */ | |
| 722 /* appropriate number of pops */ | |
| 723 /* */ | |
| 724 /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ | |
| 725 /* accept a font that contains charstrings like */ | |
| 726 /* */ | |
| 727 /* 100 200 2 20 callothersubr */ | |
| 728 /* 300 1 20 callothersubr pop */ | |
| 729 /* */ | |
| 730 /* Perhaps this is the reason why BuildCharArray exists. */ | |
| 731 | |
| 732 switch ( subr_no ) | |
| 733 { | |
| 734 case 0: /* end flex feature */ | |
| 735 if ( arg_cnt != 3 ) | |
| 736 goto Unexpected_OtherSubr; | |
| 737 | |
| 738 if ( decoder->flex_state == 0 || | |
| 739 decoder->num_flex_vectors != 7 ) | |
| 740 { | |
| 741 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 742 " unexpected flex end\n" )); | |
| 743 goto Syntax_Error; | |
| 744 } | |
| 745 | |
| 746 /* the two `results' are popped by the following setcurrentpoint */ | |
| 747 top[0] = x; | |
| 748 top[1] = y; | |
| 749 known_othersubr_result_cnt = 2; | |
| 750 break; | |
| 751 | |
| 752 case 1: /* start flex feature */ | |
| 753 if ( arg_cnt != 0 ) | |
| 754 goto Unexpected_OtherSubr; | |
| 755 | |
| 756 decoder->flex_state = 1; | |
| 757 decoder->num_flex_vectors = 0; | |
| 758 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 759 != FT_Err_Ok || | |
| 760 ( error = t1_builder_check_points( builder, 6 ) ) | |
| 761 != FT_Err_Ok ) | |
| 762 goto Fail; | |
| 763 break; | |
| 764 | |
| 765 case 2: /* add flex vectors */ | |
| 766 { | |
| 767 FT_Int idx; | |
| 768 | |
| 769 | |
| 770 if ( arg_cnt != 0 ) | |
| 771 goto Unexpected_OtherSubr; | |
| 772 | |
| 773 if ( decoder->flex_state == 0 ) | |
| 774 { | |
| 775 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 776 " missing flex start\n" )); | |
| 777 goto Syntax_Error; | |
| 778 } | |
| 779 | |
| 780 /* note that we should not add a point for index 0; */ | |
| 781 /* this will move our current position to the flex */ | |
| 782 /* point without adding any point to the outline */ | |
| 783 idx = decoder->num_flex_vectors++; | |
| 784 if ( idx > 0 && idx < 7 ) | |
| 785 t1_builder_add_point( builder, | |
| 786 x, | |
| 787 y, | |
| 788 (FT_Byte)( idx == 3 || idx == 6 ) ); | |
| 789 } | |
| 790 break; | |
| 791 | |
| 792 case 3: /* change hints */ | |
| 793 if ( arg_cnt != 1 ) | |
| 794 goto Unexpected_OtherSubr; | |
| 795 | |
| 796 known_othersubr_result_cnt = 1; | |
| 797 | |
| 798 if ( hinter ) | |
| 799 hinter->reset( hinter->hints, builder->current->n_points ); | |
| 800 break; | |
| 801 | |
| 802 case 12: | |
| 803 case 13: | |
| 804 /* counter control hints, clear stack */ | |
| 805 top = decoder->stack; | |
| 806 break; | |
| 807 | |
| 808 case 14: | |
| 809 case 15: | |
| 810 case 16: | |
| 811 case 17: | |
| 812 case 18: /* multiple masters */ | |
| 813 { | |
| 814 PS_Blend blend = decoder->blend; | |
| 815 FT_UInt num_points, nn, mm; | |
| 816 FT_Long* delta; | |
| 817 FT_Long* values; | |
| 818 | |
| 819 | |
| 820 if ( !blend ) | |
| 821 { | |
| 822 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 823 " unexpected multiple masters operator\n" )); | |
| 824 goto Syntax_Error; | |
| 825 } | |
| 826 | |
| 827 num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); | |
| 828 if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) | |
| 829 { | |
| 830 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 831 " incorrect number of multiple masters arguments\n" )); | |
| 832 goto Syntax_Error; | |
| 833 } | |
| 834 | |
| 835 /* We want to compute */ | |
| 836 /* */ | |
| 837 /* a0*w0 + a1*w1 + ... + ak*wk */ | |
| 838 /* */ | |
| 839 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ | |
| 840 /* */ | |
| 841 /* However, given that w0 + w1 + ... + wk == 1, we can */ | |
| 842 /* rewrite it easily as */ | |
| 843 /* */ | |
| 844 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ | |
| 845 /* */ | |
| 846 /* where k == num_designs-1. */ | |
| 847 /* */ | |
| 848 /* I guess that's why it's written in this `compact' */ | |
| 849 /* form. */ | |
| 850 /* */ | |
| 851 delta = top + num_points; | |
| 852 values = top; | |
| 853 for ( nn = 0; nn < num_points; nn++ ) | |
| 854 { | |
| 855 FT_Long tmp = values[0]; | |
| 856 | |
| 857 | |
| 858 for ( mm = 1; mm < blend->num_designs; mm++ ) | |
| 859 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); | |
| 860 | |
| 861 *values++ = tmp; | |
| 862 } | |
| 863 | |
| 864 known_othersubr_result_cnt = num_points; | |
| 865 break; | |
| 866 } | |
| 867 | |
| 868 case 19: | |
| 869 /* <idx> 1 19 callothersubr */ | |
| 870 /* => replace elements starting from index cvi( <idx> ) */ | |
| 871 /* of BuildCharArray with WeightVector */ | |
| 872 { | |
| 873 FT_Int idx; | |
| 874 PS_Blend blend = decoder->blend; | |
| 875 | |
| 876 | |
| 877 if ( arg_cnt != 1 || blend == NULL ) | |
| 878 goto Unexpected_OtherSubr; | |
| 879 | |
| 880 idx = Fix2Int( top[0] ); | |
| 881 | |
| 882 if ( idx < 0 || | |
| 883 idx + blend->num_designs > decoder->len_buildchar ) | |
| 884 goto Unexpected_OtherSubr; | |
| 885 | |
| 886 ft_memcpy( &decoder->buildchar[idx], | |
| 887 blend->weight_vector, | |
| 888 blend->num_designs * | |
| 889 sizeof ( blend->weight_vector[0] ) ); | |
| 890 } | |
| 891 break; | |
| 892 | |
| 893 case 20: | |
| 894 /* <arg1> <arg2> 2 20 callothersubr pop */ | |
| 895 /* ==> push <arg1> + <arg2> onto T1 stack */ | |
| 896 if ( arg_cnt != 2 ) | |
| 897 goto Unexpected_OtherSubr; | |
| 898 | |
| 899 top[0] += top[1]; /* XXX (over|under)flow */ | |
| 900 | |
| 901 known_othersubr_result_cnt = 1; | |
| 902 break; | |
| 903 | |
| 904 case 21: | |
| 905 /* <arg1> <arg2> 2 21 callothersubr pop */ | |
| 906 /* ==> push <arg1> - <arg2> onto T1 stack */ | |
| 907 if ( arg_cnt != 2 ) | |
| 908 goto Unexpected_OtherSubr; | |
| 909 | |
| 910 top[0] -= top[1]; /* XXX (over|under)flow */ | |
| 911 | |
| 912 known_othersubr_result_cnt = 1; | |
| 913 break; | |
| 914 | |
| 915 case 22: | |
| 916 /* <arg1> <arg2> 2 22 callothersubr pop */ | |
| 917 /* ==> push <arg1> * <arg2> onto T1 stack */ | |
| 918 if ( arg_cnt != 2 ) | |
| 919 goto Unexpected_OtherSubr; | |
| 920 | |
| 921 top[0] = FT_MulFix( top[0], top[1] ); | |
| 922 | |
| 923 known_othersubr_result_cnt = 1; | |
| 924 break; | |
| 925 | |
| 926 case 23: | |
| 927 /* <arg1> <arg2> 2 23 callothersubr pop */ | |
| 928 /* ==> push <arg1> / <arg2> onto T1 stack */ | |
| 929 if ( arg_cnt != 2 || top[1] == 0 ) | |
| 930 goto Unexpected_OtherSubr; | |
| 931 | |
| 932 top[0] = FT_DivFix( top[0], top[1] ); | |
| 933 | |
| 934 known_othersubr_result_cnt = 1; | |
| 935 break; | |
| 936 | |
| 937 case 24: | |
| 938 /* <val> <idx> 2 24 callothersubr */ | |
| 939 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ | |
| 940 { | |
| 941 FT_Int idx; | |
| 942 PS_Blend blend = decoder->blend; | |
| 943 | |
| 944 | |
| 945 if ( arg_cnt != 2 || blend == NULL ) | |
| 946 goto Unexpected_OtherSubr; | |
| 947 | |
| 948 idx = Fix2Int( top[1] ); | |
| 949 | |
| 950 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) | |
| 951 goto Unexpected_OtherSubr; | |
| 952 | |
| 953 decoder->buildchar[idx] = top[0]; | |
| 954 } | |
| 955 break; | |
| 956 | |
| 957 case 25: | |
| 958 /* <idx> 1 25 callothersubr pop */ | |
| 959 /* ==> push BuildCharArray[cvi( idx )] */ | |
| 960 /* onto T1 stack */ | |
| 961 { | |
| 962 FT_Int idx; | |
| 963 PS_Blend blend = decoder->blend; | |
| 964 | |
| 965 | |
| 966 if ( arg_cnt != 1 || blend == NULL ) | |
| 967 goto Unexpected_OtherSubr; | |
| 968 | |
| 969 idx = Fix2Int( top[0] ); | |
| 970 | |
| 971 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) | |
| 972 goto Unexpected_OtherSubr; | |
| 973 | |
| 974 top[0] = decoder->buildchar[idx]; | |
| 975 } | |
| 976 | |
| 977 known_othersubr_result_cnt = 1; | |
| 978 break; | |
| 979 | |
| 980 #if 0 | |
| 981 case 26: | |
| 982 /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ | |
| 983 /* leave mark on T1 stack */ | |
| 984 /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ | |
| 985 XXX which routine has left its mark on the (PostScript) stack?; | |
| 986 break; | |
| 987 #endif | |
| 988 | |
| 989 case 27: | |
| 990 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ | |
| 991 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ | |
| 992 /* otherwise push <res2> */ | |
| 993 if ( arg_cnt != 4 ) | |
| 994 goto Unexpected_OtherSubr; | |
| 995 | |
| 996 if ( top[2] > top[3] ) | |
| 997 top[0] = top[1]; | |
| 998 | |
| 999 known_othersubr_result_cnt = 1; | |
| 1000 break; | |
| 1001 | |
| 1002 case 28: | |
| 1003 /* 0 28 callothersubr pop */ | |
| 1004 /* => push random value from interval [0, 1) onto stack */ | |
| 1005 if ( arg_cnt != 0 ) | |
| 1006 goto Unexpected_OtherSubr; | |
| 1007 | |
| 1008 { | |
| 1009 FT_Fixed Rand; | |
| 1010 | |
| 1011 | |
| 1012 Rand = seed; | |
| 1013 if ( Rand >= 0x8000L ) | |
| 1014 Rand++; | |
| 1015 | |
| 1016 top[0] = Rand; | |
| 1017 | |
| 1018 seed = FT_MulFix( seed, 0x10000L - seed ); | |
| 1019 if ( seed == 0 ) | |
| 1020 seed += 0x2873; | |
| 1021 } | |
| 1022 | |
| 1023 known_othersubr_result_cnt = 1; | |
| 1024 break; | |
| 1025 | |
| 1026 default: | |
| 1027 if ( arg_cnt >= 0 && subr_no >= 0 ) | |
| 1028 { | |
| 1029 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1030 " unknown othersubr [%d %d], wish me luck\n", | |
| 1031 arg_cnt, subr_no )); | |
| 1032 unknown_othersubr_result_cnt = arg_cnt; | |
| 1033 break; | |
| 1034 } | |
| 1035 /* fall through */ | |
| 1036 | |
| 1037 Unexpected_OtherSubr: | |
| 1038 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1039 " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); | |
| 1040 goto Syntax_Error; | |
| 1041 } | |
| 1042 | |
| 1043 top += known_othersubr_result_cnt; | |
| 1044 | |
| 1045 decoder->top = top; | |
| 1046 } | |
| 1047 else /* general operator */ | |
| 1048 { | |
| 1049 FT_Int num_args = t1_args_count[op]; | |
| 1050 | |
| 1051 | |
| 1052 FT_ASSERT( num_args >= 0 ); | |
| 1053 | |
| 1054 if ( top - decoder->stack < num_args ) | |
| 1055 goto Stack_Underflow; | |
| 1056 | |
| 1057 /* XXX Operators usually take their operands from the */ | |
| 1058 /* bottom of the stack, i.e., the operands are */ | |
| 1059 /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ | |
| 1060 /* only div, callsubr, and callothersubr are different. */ | |
| 1061 /* In practice it doesn't matter (?). */ | |
| 1062 | |
| 1063 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 1064 | |
| 1065 switch ( op ) | |
| 1066 { | |
| 1067 case op_callsubr: | |
| 1068 case op_div: | |
| 1069 case op_callothersubr: | |
| 1070 case op_pop: | |
| 1071 case op_return: | |
| 1072 break; | |
| 1073 | |
| 1074 default: | |
| 1075 if ( top - decoder->stack != num_args ) | |
| 1076 FT_TRACE0(( "t1_decoder_parse_charstrings:" | |
| 1077 " too much operands on the stack" | |
| 1078 " (seen %d, expected %d)\n", | |
| 1079 top - decoder->stack, num_args )); | |
| 1080 break; | |
| 1081 } | |
| 1082 | |
| 1083 #endif /* FT_DEBUG_LEVEL_TRACE */ | |
| 1084 | |
| 1085 top -= num_args; | |
| 1086 | |
| 1087 switch ( op ) | |
| 1088 { | |
| 1089 case op_endchar: | |
| 1090 FT_TRACE4(( " endchar\n" )); | |
| 1091 | |
| 1092 t1_builder_close_contour( builder ); | |
| 1093 | |
| 1094 /* close hints recording session */ | |
| 1095 if ( hinter ) | |
| 1096 { | |
| 1097 if ( hinter->close( hinter->hints, builder->current->n_points ) ) | |
| 1098 goto Syntax_Error; | |
| 1099 | |
| 1100 /* apply hints to the loaded glyph outline now */ | |
| 1101 hinter->apply( hinter->hints, | |
| 1102 builder->current, | |
| 1103 (PSH_Globals)builder->hints_globals, | |
| 1104 decoder->hint_mode ); | |
| 1105 } | |
| 1106 | |
| 1107 /* add current outline to the glyph slot */ | |
| 1108 FT_GlyphLoader_Add( builder->loader ); | |
| 1109 | |
| 1110 /* the compiler should optimize away this empty loop but ... */ | |
| 1111 | |
| 1112 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 1113 | |
| 1114 if ( decoder->len_buildchar > 0 ) | |
| 1115 { | |
| 1116 FT_UInt i; | |
| 1117 | |
| 1118 | |
| 1119 FT_TRACE4(( "BuildCharArray = [ " )); | |
| 1120 | |
| 1121 for ( i = 0; i < decoder->len_buildchar; ++i ) | |
| 1122 FT_TRACE4(( "%d ", decoder->buildchar[i] )); | |
| 1123 | |
| 1124 FT_TRACE4(( "]\n" )); | |
| 1125 } | |
| 1126 | |
| 1127 #endif /* FT_DEBUG_LEVEL_TRACE */ | |
| 1128 | |
| 1129 FT_TRACE4(( "\n" )); | |
| 1130 | |
| 1131 /* return now! */ | |
| 1132 return FT_Err_Ok; | |
| 1133 | |
| 1134 case op_hsbw: | |
| 1135 FT_TRACE4(( " hsbw" )); | |
| 1136 | |
| 1137 builder->parse_state = T1_Parse_Have_Width; | |
| 1138 | |
| 1139 builder->left_bearing.x += top[0]; | |
| 1140 builder->advance.x = top[1]; | |
| 1141 builder->advance.y = 0; | |
| 1142 | |
| 1143 orig_x = x = builder->pos_x + top[0]; | |
| 1144 orig_y = y = builder->pos_y; | |
| 1145 | |
| 1146 FT_UNUSED( orig_y ); | |
| 1147 | |
| 1148 /* the `metrics_only' indicates that we only want to compute */ | |
| 1149 /* the glyph's metrics (lsb + advance width), not load the */ | |
| 1150 /* rest of it; so exit immediately */ | |
| 1151 if ( builder->metrics_only ) | |
| 1152 return FT_Err_Ok; | |
| 1153 | |
| 1154 break; | |
| 1155 | |
| 1156 case op_seac: | |
| 1157 return t1operator_seac( decoder, | |
| 1158 top[0], | |
| 1159 top[1], | |
| 1160 top[2], | |
| 1161 Fix2Int( top[3] ), | |
| 1162 Fix2Int( top[4] ) ); | |
| 1163 | |
| 1164 case op_sbw: | |
| 1165 FT_TRACE4(( " sbw" )); | |
| 1166 | |
| 1167 builder->parse_state = T1_Parse_Have_Width; | |
| 1168 | |
| 1169 builder->left_bearing.x += top[0]; | |
| 1170 builder->left_bearing.y += top[1]; | |
| 1171 builder->advance.x = top[2]; | |
| 1172 builder->advance.y = top[3]; | |
| 1173 | |
| 1174 x = builder->pos_x + top[0]; | |
| 1175 y = builder->pos_y + top[1]; | |
| 1176 | |
| 1177 /* the `metrics_only' indicates that we only want to compute */ | |
| 1178 /* the glyph's metrics (lsb + advance width), not load the */ | |
| 1179 /* rest of it; so exit immediately */ | |
| 1180 if ( builder->metrics_only ) | |
| 1181 return FT_Err_Ok; | |
| 1182 | |
| 1183 break; | |
| 1184 | |
| 1185 case op_closepath: | |
| 1186 FT_TRACE4(( " closepath" )); | |
| 1187 | |
| 1188 /* if there is no path, `closepath' is a no-op */ | |
| 1189 if ( builder->parse_state == T1_Parse_Have_Path || | |
| 1190 builder->parse_state == T1_Parse_Have_Moveto ) | |
| 1191 t1_builder_close_contour( builder ); | |
| 1192 | |
| 1193 builder->parse_state = T1_Parse_Have_Width; | |
| 1194 break; | |
| 1195 | |
| 1196 case op_hlineto: | |
| 1197 FT_TRACE4(( " hlineto" )); | |
| 1198 | |
| 1199 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1200 != FT_Err_Ok ) | |
| 1201 goto Fail; | |
| 1202 | |
| 1203 x += top[0]; | |
| 1204 goto Add_Line; | |
| 1205 | |
| 1206 case op_hmoveto: | |
| 1207 FT_TRACE4(( " hmoveto" )); | |
| 1208 | |
| 1209 x += top[0]; | |
| 1210 if ( !decoder->flex_state ) | |
| 1211 { | |
| 1212 if ( builder->parse_state == T1_Parse_Start ) | |
| 1213 goto Syntax_Error; | |
| 1214 builder->parse_state = T1_Parse_Have_Moveto; | |
| 1215 } | |
| 1216 break; | |
| 1217 | |
| 1218 case op_hvcurveto: | |
| 1219 FT_TRACE4(( " hvcurveto" )); | |
| 1220 | |
| 1221 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1222 != FT_Err_Ok || | |
| 1223 ( error = t1_builder_check_points( builder, 3 ) ) | |
| 1224 != FT_Err_Ok ) | |
| 1225 goto Fail; | |
| 1226 | |
| 1227 x += top[0]; | |
| 1228 t1_builder_add_point( builder, x, y, 0 ); | |
| 1229 x += top[1]; | |
| 1230 y += top[2]; | |
| 1231 t1_builder_add_point( builder, x, y, 0 ); | |
| 1232 y += top[3]; | |
| 1233 t1_builder_add_point( builder, x, y, 1 ); | |
| 1234 break; | |
| 1235 | |
| 1236 case op_rlineto: | |
| 1237 FT_TRACE4(( " rlineto" )); | |
| 1238 | |
| 1239 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1240 != FT_Err_Ok ) | |
| 1241 goto Fail; | |
| 1242 | |
| 1243 x += top[0]; | |
| 1244 y += top[1]; | |
| 1245 | |
| 1246 Add_Line: | |
| 1247 if ( ( error = t1_builder_add_point1( builder, x, y ) ) | |
| 1248 != FT_Err_Ok ) | |
| 1249 goto Fail; | |
| 1250 break; | |
| 1251 | |
| 1252 case op_rmoveto: | |
| 1253 FT_TRACE4(( " rmoveto" )); | |
| 1254 | |
| 1255 x += top[0]; | |
| 1256 y += top[1]; | |
| 1257 if ( !decoder->flex_state ) | |
| 1258 { | |
| 1259 if ( builder->parse_state == T1_Parse_Start ) | |
| 1260 goto Syntax_Error; | |
| 1261 builder->parse_state = T1_Parse_Have_Moveto; | |
| 1262 } | |
| 1263 break; | |
| 1264 | |
| 1265 case op_rrcurveto: | |
| 1266 FT_TRACE4(( " rrcurveto" )); | |
| 1267 | |
| 1268 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1269 != FT_Err_Ok || | |
| 1270 ( error = t1_builder_check_points( builder, 3 ) ) | |
| 1271 != FT_Err_Ok ) | |
| 1272 goto Fail; | |
| 1273 | |
| 1274 x += top[0]; | |
| 1275 y += top[1]; | |
| 1276 t1_builder_add_point( builder, x, y, 0 ); | |
| 1277 | |
| 1278 x += top[2]; | |
| 1279 y += top[3]; | |
| 1280 t1_builder_add_point( builder, x, y, 0 ); | |
| 1281 | |
| 1282 x += top[4]; | |
| 1283 y += top[5]; | |
| 1284 t1_builder_add_point( builder, x, y, 1 ); | |
| 1285 break; | |
| 1286 | |
| 1287 case op_vhcurveto: | |
| 1288 FT_TRACE4(( " vhcurveto" )); | |
| 1289 | |
| 1290 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1291 != FT_Err_Ok || | |
| 1292 ( error = t1_builder_check_points( builder, 3 ) ) | |
| 1293 != FT_Err_Ok ) | |
| 1294 goto Fail; | |
| 1295 | |
| 1296 y += top[0]; | |
| 1297 t1_builder_add_point( builder, x, y, 0 ); | |
| 1298 x += top[1]; | |
| 1299 y += top[2]; | |
| 1300 t1_builder_add_point( builder, x, y, 0 ); | |
| 1301 x += top[3]; | |
| 1302 t1_builder_add_point( builder, x, y, 1 ); | |
| 1303 break; | |
| 1304 | |
| 1305 case op_vlineto: | |
| 1306 FT_TRACE4(( " vlineto" )); | |
| 1307 | |
| 1308 if ( ( error = t1_builder_start_point( builder, x, y ) ) | |
| 1309 != FT_Err_Ok ) | |
| 1310 goto Fail; | |
| 1311 | |
| 1312 y += top[0]; | |
| 1313 goto Add_Line; | |
| 1314 | |
| 1315 case op_vmoveto: | |
| 1316 FT_TRACE4(( " vmoveto" )); | |
| 1317 | |
| 1318 y += top[0]; | |
| 1319 if ( !decoder->flex_state ) | |
| 1320 { | |
| 1321 if ( builder->parse_state == T1_Parse_Start ) | |
| 1322 goto Syntax_Error; | |
| 1323 builder->parse_state = T1_Parse_Have_Moveto; | |
| 1324 } | |
| 1325 break; | |
| 1326 | |
| 1327 case op_div: | |
| 1328 FT_TRACE4(( " div" )); | |
| 1329 | |
| 1330 /* if `large_int' is set, we divide unscaled numbers; */ | |
| 1331 /* otherwise, we divide numbers in 16.16 format -- */ | |
| 1332 /* in both cases, it is the same operation */ | |
| 1333 *top = FT_DivFix( top[0], top[1] ); | |
| 1334 ++top; | |
| 1335 | |
| 1336 large_int = FALSE; | |
| 1337 break; | |
| 1338 | |
| 1339 case op_callsubr: | |
| 1340 { | |
| 1341 FT_Int idx; | |
| 1342 | |
| 1343 | |
| 1344 FT_TRACE4(( " callsubr" )); | |
| 1345 | |
| 1346 idx = Fix2Int( top[0] ); | |
| 1347 if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) | |
| 1348 { | |
| 1349 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1350 " invalid subrs index\n" )); | |
| 1351 goto Syntax_Error; | |
| 1352 } | |
| 1353 | |
| 1354 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) | |
| 1355 { | |
| 1356 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1357 " too many nested subrs\n" )); | |
| 1358 goto Syntax_Error; | |
| 1359 } | |
| 1360 | |
| 1361 zone->cursor = ip; /* save current instruction pointer */ | |
| 1362 | |
| 1363 zone++; | |
| 1364 | |
| 1365 /* The Type 1 driver stores subroutines without the seed bytes. */ | |
| 1366 /* The CID driver stores subroutines with seed bytes. This */ | |
| 1367 /* case is taken care of when decoder->subrs_len == 0. */ | |
| 1368 zone->base = decoder->subrs[idx]; | |
| 1369 | |
| 1370 if ( decoder->subrs_len ) | |
| 1371 zone->limit = zone->base + decoder->subrs_len[idx]; | |
| 1372 else | |
| 1373 { | |
| 1374 /* We are using subroutines from a CID font. We must adjust */ | |
| 1375 /* for the seed bytes. */ | |
| 1376 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); | |
| 1377 zone->limit = decoder->subrs[idx + 1]; | |
| 1378 } | |
| 1379 | |
| 1380 zone->cursor = zone->base; | |
| 1381 | |
| 1382 if ( !zone->base ) | |
| 1383 { | |
| 1384 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1385 " invoking empty subrs\n" )); | |
| 1386 goto Syntax_Error; | |
| 1387 } | |
| 1388 | |
| 1389 decoder->zone = zone; | |
| 1390 ip = zone->base; | |
| 1391 limit = zone->limit; | |
| 1392 break; | |
| 1393 } | |
| 1394 | |
| 1395 case op_pop: | |
| 1396 FT_TRACE4(( " pop" )); | |
| 1397 | |
| 1398 if ( known_othersubr_result_cnt > 0 ) | |
| 1399 { | |
| 1400 known_othersubr_result_cnt--; | |
| 1401 /* ignore, we pushed the operands ourselves */ | |
| 1402 break; | |
| 1403 } | |
| 1404 | |
| 1405 if ( unknown_othersubr_result_cnt == 0 ) | |
| 1406 { | |
| 1407 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1408 " no more operands for othersubr\n" )); | |
| 1409 goto Syntax_Error; | |
| 1410 } | |
| 1411 | |
| 1412 unknown_othersubr_result_cnt--; | |
| 1413 top++; /* `push' the operand to callothersubr onto the stack */ | |
| 1414 break; | |
| 1415 | |
| 1416 case op_return: | |
| 1417 FT_TRACE4(( " return" )); | |
| 1418 | |
| 1419 if ( zone <= decoder->zones ) | |
| 1420 { | |
| 1421 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1422 " unexpected return\n" )); | |
| 1423 goto Syntax_Error; | |
| 1424 } | |
| 1425 | |
| 1426 zone--; | |
| 1427 ip = zone->cursor; | |
| 1428 limit = zone->limit; | |
| 1429 decoder->zone = zone; | |
| 1430 break; | |
| 1431 | |
| 1432 case op_dotsection: | |
| 1433 FT_TRACE4(( " dotsection" )); | |
| 1434 | |
| 1435 break; | |
| 1436 | |
| 1437 case op_hstem: | |
| 1438 FT_TRACE4(( " hstem" )); | |
| 1439 | |
| 1440 /* record horizontal hint */ | |
| 1441 if ( hinter ) | |
| 1442 { | |
| 1443 /* top[0] += builder->left_bearing.y; */ | |
| 1444 hinter->stem( hinter->hints, 1, top ); | |
| 1445 } | |
| 1446 break; | |
| 1447 | |
| 1448 case op_hstem3: | |
| 1449 FT_TRACE4(( " hstem3" )); | |
| 1450 | |
| 1451 /* record horizontal counter-controlled hints */ | |
| 1452 if ( hinter ) | |
| 1453 hinter->stem3( hinter->hints, 1, top ); | |
| 1454 break; | |
| 1455 | |
| 1456 case op_vstem: | |
| 1457 FT_TRACE4(( " vstem" )); | |
| 1458 | |
| 1459 /* record vertical hint */ | |
| 1460 if ( hinter ) | |
| 1461 { | |
| 1462 top[0] += orig_x; | |
| 1463 hinter->stem( hinter->hints, 0, top ); | |
| 1464 } | |
| 1465 break; | |
| 1466 | |
| 1467 case op_vstem3: | |
| 1468 FT_TRACE4(( " vstem3" )); | |
| 1469 | |
| 1470 /* record vertical counter-controlled hints */ | |
| 1471 if ( hinter ) | |
| 1472 { | |
| 1473 FT_Pos dx = orig_x; | |
| 1474 | |
| 1475 | |
| 1476 top[0] += dx; | |
| 1477 top[2] += dx; | |
| 1478 top[4] += dx; | |
| 1479 hinter->stem3( hinter->hints, 0, top ); | |
| 1480 } | |
| 1481 break; | |
| 1482 | |
| 1483 case op_setcurrentpoint: | |
| 1484 FT_TRACE4(( " setcurrentpoint" )); | |
| 1485 | |
| 1486 /* From the T1 specification, section 6.4: */ | |
| 1487 /* */ | |
| 1488 /* The setcurrentpoint command is used only in */ | |
| 1489 /* conjunction with results from OtherSubrs procedures. */ | |
| 1490 | |
| 1491 /* known_othersubr_result_cnt != 0 is already handled */ | |
| 1492 /* above. */ | |
| 1493 | |
| 1494 /* Note, however, that both Ghostscript and Adobe */ | |
| 1495 /* Distiller handle this situation by silently ignoring */ | |
| 1496 /* the inappropriate `setcurrentpoint' instruction. So */ | |
| 1497 /* we do the same. */ | |
| 1498 #if 0 | |
| 1499 | |
| 1500 if ( decoder->flex_state != 1 ) | |
| 1501 { | |
| 1502 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1503 " unexpected `setcurrentpoint'\n" )); | |
| 1504 goto Syntax_Error; | |
| 1505 } | |
| 1506 else | |
| 1507 ... | |
| 1508 #endif | |
| 1509 | |
| 1510 x = top[0]; | |
| 1511 y = top[1]; | |
| 1512 decoder->flex_state = 0; | |
| 1513 break; | |
| 1514 | |
| 1515 case op_unknown15: | |
| 1516 FT_TRACE4(( " opcode_15" )); | |
| 1517 /* nothing to do except to pop the two arguments */ | |
| 1518 break; | |
| 1519 | |
| 1520 default: | |
| 1521 FT_ERROR(( "t1_decoder_parse_charstrings:" | |
| 1522 " unhandled opcode %d\n", op )); | |
| 1523 goto Syntax_Error; | |
| 1524 } | |
| 1525 | |
| 1526 /* XXX Operators usually clear the operand stack; */ | |
| 1527 /* only div, callsubr, callothersubr, pop, and */ | |
| 1528 /* return are different. */ | |
| 1529 /* In practice it doesn't matter (?). */ | |
| 1530 | |
| 1531 decoder->top = top; | |
| 1532 | |
| 1533 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 1534 FT_TRACE4(( "\n" )); | |
| 1535 bol = TRUE; | |
| 1536 #endif | |
| 1537 | |
| 1538 } /* general operator processing */ | |
| 1539 | |
| 1540 } /* while ip < limit */ | |
| 1541 | |
| 1542 FT_TRACE4(( "..end..\n\n" )); | |
| 1543 | |
| 1544 Fail: | |
| 1545 return error; | |
| 1546 | |
| 1547 Syntax_Error: | |
| 1548 return FT_THROW( Syntax_Error ); | |
| 1549 | |
| 1550 Stack_Underflow: | |
| 1551 return FT_THROW( Stack_Underflow ); | |
| 1552 } | |
| 1553 | |
| 1554 | |
| 1555 /* parse a single Type 1 glyph */ | |
| 1556 FT_LOCAL_DEF( FT_Error ) | |
| 1557 t1_decoder_parse_glyph( T1_Decoder decoder, | |
| 1558 FT_UInt glyph ) | |
| 1559 { | |
| 1560 return decoder->parse_callback( decoder, glyph ); | |
| 1561 } | |
| 1562 | |
| 1563 | |
| 1564 /* initialize T1 decoder */ | |
| 1565 FT_LOCAL_DEF( FT_Error ) | |
| 1566 t1_decoder_init( T1_Decoder decoder, | |
| 1567 FT_Face face, | |
| 1568 FT_Size size, | |
| 1569 FT_GlyphSlot slot, | |
| 1570 FT_Byte** glyph_names, | |
| 1571 PS_Blend blend, | |
| 1572 FT_Bool hinting, | |
| 1573 FT_Render_Mode hint_mode, | |
| 1574 T1_Decoder_Callback parse_callback ) | |
| 1575 { | |
| 1576 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); | |
| 1577 | |
| 1578 /* retrieve PSNames interface from list of current modules */ | |
| 1579 { | |
| 1580 FT_Service_PsCMaps psnames = 0; | |
| 1581 | |
| 1582 | |
| 1583 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); | |
| 1584 if ( !psnames ) | |
| 1585 { | |
| 1586 FT_ERROR(( "t1_decoder_init:" | |
| 1587 " the `psnames' module is not available\n" )); | |
| 1588 return FT_THROW( Unimplemented_Feature ); | |
| 1589 } | |
| 1590 | |
| 1591 decoder->psnames = psnames; | |
| 1592 } | |
| 1593 | |
| 1594 t1_builder_init( &decoder->builder, face, size, slot, hinting ); | |
| 1595 | |
| 1596 /* decoder->buildchar and decoder->len_buildchar have to be */ | |
| 1597 /* initialized by the caller since we cannot know the length */ | |
| 1598 /* of the BuildCharArray */ | |
| 1599 | |
| 1600 decoder->num_glyphs = (FT_UInt)face->num_glyphs; | |
| 1601 decoder->glyph_names = glyph_names; | |
| 1602 decoder->hint_mode = hint_mode; | |
| 1603 decoder->blend = blend; | |
| 1604 decoder->parse_callback = parse_callback; | |
| 1605 | |
| 1606 decoder->funcs = t1_decoder_funcs; | |
| 1607 | |
| 1608 return FT_Err_Ok; | |
| 1609 } | |
| 1610 | |
| 1611 | |
| 1612 /* finalize T1 decoder */ | |
| 1613 FT_LOCAL_DEF( void ) | |
| 1614 t1_decoder_done( T1_Decoder decoder ) | |
| 1615 { | |
| 1616 t1_builder_done( &decoder->builder ); | |
| 1617 } | |
| 1618 | |
| 1619 | |
| 1620 /* END */ | |
| OLD | NEW |