| OLD | NEW |
| (Empty) |
| 1 /***************************************************************************/ | |
| 2 /* */ | |
| 3 /* cffgload.c */ | |
| 4 /* */ | |
| 5 /* OpenType Glyph Loader (body). */ | |
| 6 /* */ | |
| 7 /* Copyright 1996-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/ftdebug.h" | |
| 21 #include "../../include/freetype/internal/ftstream.h" | |
| 22 #include "../../include/freetype/internal/sfnt.h" | |
| 23 #include "../../include/freetype/ftoutln.h" | |
| 24 #include "../../include/freetype/ftcffdrv.h" | |
| 25 | |
| 26 #include "cffobjs.h" | |
| 27 #include "cffload.h" | |
| 28 #include "cffgload.h" | |
| 29 #include "cf2ft.h" /* for cf2_decoder_parse_charstrings */ | |
| 30 | |
| 31 #include "cfferrs.h" | |
| 32 | |
| 33 | |
| 34 /*************************************************************************/ | |
| 35 /* */ | |
| 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
| 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
| 38 /* messages during execution. */ | |
| 39 /* */ | |
| 40 #undef FT_COMPONENT | |
| 41 #define FT_COMPONENT trace_cffgload | |
| 42 | |
| 43 | |
| 44 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE | |
| 45 | |
| 46 typedef enum CFF_Operator_ | |
| 47 { | |
| 48 cff_op_unknown = 0, | |
| 49 | |
| 50 cff_op_rmoveto, | |
| 51 cff_op_hmoveto, | |
| 52 cff_op_vmoveto, | |
| 53 | |
| 54 cff_op_rlineto, | |
| 55 cff_op_hlineto, | |
| 56 cff_op_vlineto, | |
| 57 | |
| 58 cff_op_rrcurveto, | |
| 59 cff_op_hhcurveto, | |
| 60 cff_op_hvcurveto, | |
| 61 cff_op_rcurveline, | |
| 62 cff_op_rlinecurve, | |
| 63 cff_op_vhcurveto, | |
| 64 cff_op_vvcurveto, | |
| 65 | |
| 66 cff_op_flex, | |
| 67 cff_op_hflex, | |
| 68 cff_op_hflex1, | |
| 69 cff_op_flex1, | |
| 70 | |
| 71 cff_op_endchar, | |
| 72 | |
| 73 cff_op_hstem, | |
| 74 cff_op_vstem, | |
| 75 cff_op_hstemhm, | |
| 76 cff_op_vstemhm, | |
| 77 | |
| 78 cff_op_hintmask, | |
| 79 cff_op_cntrmask, | |
| 80 cff_op_dotsection, /* deprecated, acts as no-op */ | |
| 81 | |
| 82 cff_op_abs, | |
| 83 cff_op_add, | |
| 84 cff_op_sub, | |
| 85 cff_op_div, | |
| 86 cff_op_neg, | |
| 87 cff_op_random, | |
| 88 cff_op_mul, | |
| 89 cff_op_sqrt, | |
| 90 | |
| 91 cff_op_blend, | |
| 92 | |
| 93 cff_op_drop, | |
| 94 cff_op_exch, | |
| 95 cff_op_index, | |
| 96 cff_op_roll, | |
| 97 cff_op_dup, | |
| 98 | |
| 99 cff_op_put, | |
| 100 cff_op_get, | |
| 101 cff_op_store, | |
| 102 cff_op_load, | |
| 103 | |
| 104 cff_op_and, | |
| 105 cff_op_or, | |
| 106 cff_op_not, | |
| 107 cff_op_eq, | |
| 108 cff_op_ifelse, | |
| 109 | |
| 110 cff_op_callsubr, | |
| 111 cff_op_callgsubr, | |
| 112 cff_op_return, | |
| 113 | |
| 114 /* Type 1 opcodes: invalid but seen in real life */ | |
| 115 cff_op_hsbw, | |
| 116 cff_op_closepath, | |
| 117 cff_op_callothersubr, | |
| 118 cff_op_pop, | |
| 119 cff_op_seac, | |
| 120 cff_op_sbw, | |
| 121 cff_op_setcurrentpoint, | |
| 122 | |
| 123 /* do not remove */ | |
| 124 cff_op_max | |
| 125 | |
| 126 } CFF_Operator; | |
| 127 | |
| 128 | |
| 129 #define CFF_COUNT_CHECK_WIDTH 0x80 | |
| 130 #define CFF_COUNT_EXACT 0x40 | |
| 131 #define CFF_COUNT_CLEAR_STACK 0x20 | |
| 132 | |
| 133 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */ | |
| 134 /* used for checking the width and requested numbers of arguments */ | |
| 135 /* only; they are set to zero afterwards */ | |
| 136 | |
| 137 /* the other two flags are informative only and unused currently */ | |
| 138 | |
| 139 static const FT_Byte cff_argument_counts[] = | |
| 140 { | |
| 141 0, /* unknown */ | |
| 142 | |
| 143 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ | |
| 144 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, | |
| 145 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, | |
| 146 | |
| 147 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ | |
| 148 0 | CFF_COUNT_CLEAR_STACK, | |
| 149 0 | CFF_COUNT_CLEAR_STACK, | |
| 150 | |
| 151 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ | |
| 152 0 | CFF_COUNT_CLEAR_STACK, | |
| 153 0 | CFF_COUNT_CLEAR_STACK, | |
| 154 0 | CFF_COUNT_CLEAR_STACK, | |
| 155 0 | CFF_COUNT_CLEAR_STACK, | |
| 156 0 | CFF_COUNT_CLEAR_STACK, | |
| 157 0 | CFF_COUNT_CLEAR_STACK, | |
| 158 | |
| 159 13, /* flex */ | |
| 160 7, | |
| 161 9, | |
| 162 11, | |
| 163 | |
| 164 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ | |
| 165 | |
| 166 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ | |
| 167 2 | CFF_COUNT_CHECK_WIDTH, | |
| 168 2 | CFF_COUNT_CHECK_WIDTH, | |
| 169 2 | CFF_COUNT_CHECK_WIDTH, | |
| 170 | |
| 171 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ | |
| 172 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ | |
| 173 0, /* dotsection */ | |
| 174 | |
| 175 1, /* abs */ | |
| 176 2, | |
| 177 2, | |
| 178 2, | |
| 179 1, | |
| 180 0, | |
| 181 2, | |
| 182 1, | |
| 183 | |
| 184 1, /* blend */ | |
| 185 | |
| 186 1, /* drop */ | |
| 187 2, | |
| 188 1, | |
| 189 2, | |
| 190 1, | |
| 191 | |
| 192 2, /* put */ | |
| 193 1, | |
| 194 4, | |
| 195 3, | |
| 196 | |
| 197 2, /* and */ | |
| 198 2, | |
| 199 1, | |
| 200 2, | |
| 201 4, | |
| 202 | |
| 203 1, /* callsubr */ | |
| 204 1, | |
| 205 0, | |
| 206 | |
| 207 2, /* hsbw */ | |
| 208 0, | |
| 209 0, | |
| 210 0, | |
| 211 5, /* seac */ | |
| 212 4, /* sbw */ | |
| 213 2 /* setcurrentpoint */ | |
| 214 }; | |
| 215 | |
| 216 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ | |
| 217 | |
| 218 | |
| 219 /*************************************************************************/ | |
| 220 /*************************************************************************/ | |
| 221 /*************************************************************************/ | |
| 222 /********** *********/ | |
| 223 /********** *********/ | |
| 224 /********** GENERIC CHARSTRING PARSING *********/ | |
| 225 /********** *********/ | |
| 226 /********** *********/ | |
| 227 /*************************************************************************/ | |
| 228 /*************************************************************************/ | |
| 229 /*************************************************************************/ | |
| 230 | |
| 231 | |
| 232 /*************************************************************************/ | |
| 233 /* */ | |
| 234 /* <Function> */ | |
| 235 /* cff_builder_init */ | |
| 236 /* */ | |
| 237 /* <Description> */ | |
| 238 /* Initializes a given glyph builder. */ | |
| 239 /* */ | |
| 240 /* <InOut> */ | |
| 241 /* builder :: A pointer to the glyph builder to initialize. */ | |
| 242 /* */ | |
| 243 /* <Input> */ | |
| 244 /* face :: The current face object. */ | |
| 245 /* */ | |
| 246 /* size :: The current size object. */ | |
| 247 /* */ | |
| 248 /* glyph :: The current glyph object. */ | |
| 249 /* */ | |
| 250 /* hinting :: Whether hinting is active. */ | |
| 251 /* */ | |
| 252 static void | |
| 253 cff_builder_init( CFF_Builder* builder, | |
| 254 TT_Face face, | |
| 255 CFF_Size size, | |
| 256 CFF_GlyphSlot glyph, | |
| 257 FT_Bool hinting ) | |
| 258 { | |
| 259 builder->path_begun = 0; | |
| 260 builder->load_points = 1; | |
| 261 | |
| 262 builder->face = face; | |
| 263 builder->glyph = glyph; | |
| 264 builder->memory = face->root.memory; | |
| 265 | |
| 266 if ( glyph ) | |
| 267 { | |
| 268 FT_GlyphLoader loader = glyph->root.internal->loader; | |
| 269 | |
| 270 | |
| 271 builder->loader = loader; | |
| 272 builder->base = &loader->base.outline; | |
| 273 builder->current = &loader->current.outline; | |
| 274 FT_GlyphLoader_Rewind( loader ); | |
| 275 | |
| 276 builder->hints_globals = 0; | |
| 277 builder->hints_funcs = 0; | |
| 278 | |
| 279 if ( hinting && size ) | |
| 280 { | |
| 281 CFF_Internal internal = (CFF_Internal)size->root.internal; | |
| 282 | |
| 283 | |
| 284 builder->hints_globals = (void *)internal->topfont; | |
| 285 builder->hints_funcs = glyph->root.internal->glyph_hints; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 builder->pos_x = 0; | |
| 290 builder->pos_y = 0; | |
| 291 | |
| 292 builder->left_bearing.x = 0; | |
| 293 builder->left_bearing.y = 0; | |
| 294 builder->advance.x = 0; | |
| 295 builder->advance.y = 0; | |
| 296 } | |
| 297 | |
| 298 | |
| 299 /*************************************************************************/ | |
| 300 /* */ | |
| 301 /* <Function> */ | |
| 302 /* cff_builder_done */ | |
| 303 /* */ | |
| 304 /* <Description> */ | |
| 305 /* Finalizes a given glyph builder. Its contents can still be used */ | |
| 306 /* after the call, but the function saves important information */ | |
| 307 /* within the corresponding glyph slot. */ | |
| 308 /* */ | |
| 309 /* <Input> */ | |
| 310 /* builder :: A pointer to the glyph builder to finalize. */ | |
| 311 /* */ | |
| 312 static void | |
| 313 cff_builder_done( CFF_Builder* builder ) | |
| 314 { | |
| 315 CFF_GlyphSlot glyph = builder->glyph; | |
| 316 | |
| 317 | |
| 318 if ( glyph ) | |
| 319 glyph->root.outline = *builder->base; | |
| 320 } | |
| 321 | |
| 322 | |
| 323 /*************************************************************************/ | |
| 324 /* */ | |
| 325 /* <Function> */ | |
| 326 /* cff_compute_bias */ | |
| 327 /* */ | |
| 328 /* <Description> */ | |
| 329 /* Computes the bias value in dependence of the number of glyph */ | |
| 330 /* subroutines. */ | |
| 331 /* */ | |
| 332 /* <Input> */ | |
| 333 /* in_charstring_type :: The `CharstringType' value of the top DICT */ | |
| 334 /* dictionary. */ | |
| 335 /* */ | |
| 336 /* num_subrs :: The number of glyph subroutines. */ | |
| 337 /* */ | |
| 338 /* <Return> */ | |
| 339 /* The bias value. */ | |
| 340 static FT_Int | |
| 341 cff_compute_bias( FT_Int in_charstring_type, | |
| 342 FT_UInt num_subrs ) | |
| 343 { | |
| 344 FT_Int result; | |
| 345 | |
| 346 | |
| 347 if ( in_charstring_type == 1 ) | |
| 348 result = 0; | |
| 349 else if ( num_subrs < 1240 ) | |
| 350 result = 107; | |
| 351 else if ( num_subrs < 33900U ) | |
| 352 result = 1131; | |
| 353 else | |
| 354 result = 32768U; | |
| 355 | |
| 356 return result; | |
| 357 } | |
| 358 | |
| 359 | |
| 360 /*************************************************************************/ | |
| 361 /* */ | |
| 362 /* <Function> */ | |
| 363 /* cff_decoder_init */ | |
| 364 /* */ | |
| 365 /* <Description> */ | |
| 366 /* Initializes a given glyph decoder. */ | |
| 367 /* */ | |
| 368 /* <InOut> */ | |
| 369 /* decoder :: A pointer to the glyph builder to initialize. */ | |
| 370 /* */ | |
| 371 /* <Input> */ | |
| 372 /* face :: The current face object. */ | |
| 373 /* */ | |
| 374 /* size :: The current size object. */ | |
| 375 /* */ | |
| 376 /* slot :: The current glyph object. */ | |
| 377 /* */ | |
| 378 /* hinting :: Whether hinting is active. */ | |
| 379 /* */ | |
| 380 /* hint_mode :: The hinting mode. */ | |
| 381 /* */ | |
| 382 FT_LOCAL_DEF( void ) | |
| 383 cff_decoder_init( CFF_Decoder* decoder, | |
| 384 TT_Face face, | |
| 385 CFF_Size size, | |
| 386 CFF_GlyphSlot slot, | |
| 387 FT_Bool hinting, | |
| 388 FT_Render_Mode hint_mode ) | |
| 389 { | |
| 390 CFF_Font cff = (CFF_Font)face->extra.data; | |
| 391 | |
| 392 | |
| 393 /* clear everything */ | |
| 394 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); | |
| 395 | |
| 396 /* initialize builder */ | |
| 397 cff_builder_init( &decoder->builder, face, size, slot, hinting ); | |
| 398 | |
| 399 /* initialize Type2 decoder */ | |
| 400 decoder->cff = cff; | |
| 401 decoder->num_globals = cff->global_subrs_index.count; | |
| 402 decoder->globals = cff->global_subrs; | |
| 403 decoder->globals_bias = cff_compute_bias( | |
| 404 cff->top_font.font_dict.charstring_type, | |
| 405 decoder->num_globals ); | |
| 406 | |
| 407 decoder->hint_mode = hint_mode; | |
| 408 } | |
| 409 | |
| 410 | |
| 411 /* this function is used to select the subfont */ | |
| 412 /* and the locals subrs array */ | |
| 413 FT_LOCAL_DEF( FT_Error ) | |
| 414 cff_decoder_prepare( CFF_Decoder* decoder, | |
| 415 CFF_Size size, | |
| 416 FT_UInt glyph_index ) | |
| 417 { | |
| 418 CFF_Builder *builder = &decoder->builder; | |
| 419 CFF_Font cff = (CFF_Font)builder->face->extra.data; | |
| 420 CFF_SubFont sub = &cff->top_font; | |
| 421 FT_Error error = FT_Err_Ok; | |
| 422 | |
| 423 | |
| 424 /* manage CID fonts */ | |
| 425 if ( cff->num_subfonts ) | |
| 426 { | |
| 427 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); | |
| 428 | |
| 429 | |
| 430 if ( fd_index >= cff->num_subfonts ) | |
| 431 { | |
| 432 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); | |
| 433 error = FT_THROW( Invalid_File_Format ); | |
| 434 goto Exit; | |
| 435 } | |
| 436 | |
| 437 FT_TRACE3(( "glyph index %d (subfont %d):\n", glyph_index, fd_index )); | |
| 438 | |
| 439 sub = cff->subfonts[fd_index]; | |
| 440 | |
| 441 if ( builder->hints_funcs && size ) | |
| 442 { | |
| 443 CFF_Internal internal = (CFF_Internal)size->root.internal; | |
| 444 | |
| 445 | |
| 446 /* for CFFs without subfonts, this value has already been set */ | |
| 447 builder->hints_globals = (void *)internal->subfonts[fd_index]; | |
| 448 } | |
| 449 } | |
| 450 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 451 else | |
| 452 FT_TRACE3(( "glyph index %d:\n", glyph_index )); | |
| 453 #endif | |
| 454 | |
| 455 decoder->num_locals = sub->local_subrs_index.count; | |
| 456 decoder->locals = sub->local_subrs; | |
| 457 decoder->locals_bias = cff_compute_bias( | |
| 458 decoder->cff->top_font.font_dict.charstring_type, | |
| 459 decoder->num_locals ); | |
| 460 | |
| 461 decoder->glyph_width = sub->private_dict.default_width; | |
| 462 decoder->nominal_width = sub->private_dict.nominal_width; | |
| 463 | |
| 464 decoder->current_subfont = sub; /* for Adobe's CFF handler */ | |
| 465 | |
| 466 Exit: | |
| 467 return error; | |
| 468 } | |
| 469 | |
| 470 | |
| 471 /* check that there is enough space for `count' more points */ | |
| 472 FT_LOCAL_DEF( FT_Error ) | |
| 473 cff_check_points( CFF_Builder* builder, | |
| 474 FT_Int count ) | |
| 475 { | |
| 476 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); | |
| 477 } | |
| 478 | |
| 479 | |
| 480 /* add a new point, do not check space */ | |
| 481 FT_LOCAL_DEF( void ) | |
| 482 cff_builder_add_point( CFF_Builder* builder, | |
| 483 FT_Pos x, | |
| 484 FT_Pos y, | |
| 485 FT_Byte flag ) | |
| 486 { | |
| 487 FT_Outline* outline = builder->current; | |
| 488 | |
| 489 | |
| 490 if ( builder->load_points ) | |
| 491 { | |
| 492 FT_Vector* point = outline->points + outline->n_points; | |
| 493 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; | |
| 494 | |
| 495 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE | |
| 496 CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); | |
| 497 | |
| 498 | |
| 499 if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) | |
| 500 { | |
| 501 point->x = x >> 16; | |
| 502 point->y = y >> 16; | |
| 503 } | |
| 504 else | |
| 505 #endif | |
| 506 { | |
| 507 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ | |
| 508 point->x = x >> 10; | |
| 509 point->y = y >> 10; | |
| 510 } | |
| 511 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); | |
| 512 } | |
| 513 | |
| 514 outline->n_points++; | |
| 515 } | |
| 516 | |
| 517 | |
| 518 /* check space for a new on-curve point, then add it */ | |
| 519 FT_LOCAL_DEF( FT_Error ) | |
| 520 cff_builder_add_point1( CFF_Builder* builder, | |
| 521 FT_Pos x, | |
| 522 FT_Pos y ) | |
| 523 { | |
| 524 FT_Error error; | |
| 525 | |
| 526 | |
| 527 error = cff_check_points( builder, 1 ); | |
| 528 if ( !error ) | |
| 529 cff_builder_add_point( builder, x, y, 1 ); | |
| 530 | |
| 531 return error; | |
| 532 } | |
| 533 | |
| 534 | |
| 535 /* check space for a new contour, then add it */ | |
| 536 static FT_Error | |
| 537 cff_builder_add_contour( CFF_Builder* builder ) | |
| 538 { | |
| 539 FT_Outline* outline = builder->current; | |
| 540 FT_Error error; | |
| 541 | |
| 542 | |
| 543 if ( !builder->load_points ) | |
| 544 { | |
| 545 outline->n_contours++; | |
| 546 return FT_Err_Ok; | |
| 547 } | |
| 548 | |
| 549 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); | |
| 550 if ( !error ) | |
| 551 { | |
| 552 if ( outline->n_contours > 0 ) | |
| 553 outline->contours[outline->n_contours - 1] = | |
| 554 (short)( outline->n_points - 1 ); | |
| 555 | |
| 556 outline->n_contours++; | |
| 557 } | |
| 558 | |
| 559 return error; | |
| 560 } | |
| 561 | |
| 562 | |
| 563 /* if a path was begun, add its first on-curve point */ | |
| 564 FT_LOCAL_DEF( FT_Error ) | |
| 565 cff_builder_start_point( CFF_Builder* builder, | |
| 566 FT_Pos x, | |
| 567 FT_Pos y ) | |
| 568 { | |
| 569 FT_Error error = FT_Err_Ok; | |
| 570 | |
| 571 | |
| 572 /* test whether we are building a new contour */ | |
| 573 if ( !builder->path_begun ) | |
| 574 { | |
| 575 builder->path_begun = 1; | |
| 576 error = cff_builder_add_contour( builder ); | |
| 577 if ( !error ) | |
| 578 error = cff_builder_add_point1( builder, x, y ); | |
| 579 } | |
| 580 | |
| 581 return error; | |
| 582 } | |
| 583 | |
| 584 | |
| 585 /* close the current contour */ | |
| 586 FT_LOCAL_DEF( void ) | |
| 587 cff_builder_close_contour( CFF_Builder* builder ) | |
| 588 { | |
| 589 FT_Outline* outline = builder->current; | |
| 590 FT_Int first; | |
| 591 | |
| 592 | |
| 593 if ( !outline ) | |
| 594 return; | |
| 595 | |
| 596 first = outline->n_contours <= 1 | |
| 597 ? 0 : outline->contours[outline->n_contours - 2] + 1; | |
| 598 | |
| 599 /* We must not include the last point in the path if it */ | |
| 600 /* is located on the first point. */ | |
| 601 if ( outline->n_points > 1 ) | |
| 602 { | |
| 603 FT_Vector* p1 = outline->points + first; | |
| 604 FT_Vector* p2 = outline->points + outline->n_points - 1; | |
| 605 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; | |
| 606 | |
| 607 | |
| 608 /* `delete' last point only if it coincides with the first */ | |
| 609 /* point and if it is not a control point (which can happen). */ | |
| 610 if ( p1->x == p2->x && p1->y == p2->y ) | |
| 611 if ( *control == FT_CURVE_TAG_ON ) | |
| 612 outline->n_points--; | |
| 613 } | |
| 614 | |
| 615 if ( outline->n_contours > 0 ) | |
| 616 { | |
| 617 /* Don't add contours only consisting of one point, i.e., */ | |
| 618 /* check whether begin point and last point are the same. */ | |
| 619 if ( first == outline->n_points - 1 ) | |
| 620 { | |
| 621 outline->n_contours--; | |
| 622 outline->n_points--; | |
| 623 } | |
| 624 else | |
| 625 outline->contours[outline->n_contours - 1] = | |
| 626 (short)( outline->n_points - 1 ); | |
| 627 } | |
| 628 } | |
| 629 | |
| 630 | |
| 631 FT_LOCAL_DEF( FT_Int ) | |
| 632 cff_lookup_glyph_by_stdcharcode( CFF_Font cff, | |
| 633 FT_Int charcode ) | |
| 634 { | |
| 635 FT_UInt n; | |
| 636 FT_UShort glyph_sid; | |
| 637 | |
| 638 | |
| 639 /* CID-keyed fonts don't have glyph names */ | |
| 640 if ( !cff->charset.sids ) | |
| 641 return -1; | |
| 642 | |
| 643 /* check range of standard char code */ | |
| 644 if ( charcode < 0 || charcode > 255 ) | |
| 645 return -1; | |
| 646 | |
| 647 /* Get code to SID mapping from `cff_standard_encoding'. */ | |
| 648 glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); | |
| 649 | |
| 650 for ( n = 0; n < cff->num_glyphs; n++ ) | |
| 651 { | |
| 652 if ( cff->charset.sids[n] == glyph_sid ) | |
| 653 return n; | |
| 654 } | |
| 655 | |
| 656 return -1; | |
| 657 } | |
| 658 | |
| 659 | |
| 660 FT_LOCAL_DEF( FT_Error ) | |
| 661 cff_get_glyph_data( TT_Face face, | |
| 662 FT_UInt glyph_index, | |
| 663 FT_Byte** pointer, | |
| 664 FT_ULong* length ) | |
| 665 { | |
| 666 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 667 /* For incremental fonts get the character data using the */ | |
| 668 /* callback function. */ | |
| 669 if ( face->root.internal->incremental_interface ) | |
| 670 { | |
| 671 FT_Data data; | |
| 672 FT_Error error = | |
| 673 face->root.internal->incremental_interface->funcs->get_glyph_d
ata( | |
| 674 face->root.internal->incremental_interface->object, | |
| 675 glyph_index, &data ); | |
| 676 | |
| 677 | |
| 678 *pointer = (FT_Byte*)data.pointer; | |
| 679 *length = data.length; | |
| 680 | |
| 681 return error; | |
| 682 } | |
| 683 else | |
| 684 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 685 | |
| 686 { | |
| 687 CFF_Font cff = (CFF_Font)(face->extra.data); | |
| 688 | |
| 689 | |
| 690 return cff_index_access_element( &cff->charstrings_index, glyph_index, | |
| 691 pointer, length ); | |
| 692 } | |
| 693 } | |
| 694 | |
| 695 | |
| 696 FT_LOCAL_DEF( void ) | |
| 697 cff_free_glyph_data( TT_Face face, | |
| 698 FT_Byte** pointer, | |
| 699 FT_ULong length ) | |
| 700 { | |
| 701 #ifndef FT_CONFIG_OPTION_INCREMENTAL | |
| 702 FT_UNUSED( length ); | |
| 703 #endif | |
| 704 | |
| 705 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 706 /* For incremental fonts get the character data using the */ | |
| 707 /* callback function. */ | |
| 708 if ( face->root.internal->incremental_interface ) | |
| 709 { | |
| 710 FT_Data data; | |
| 711 | |
| 712 | |
| 713 data.pointer = *pointer; | |
| 714 data.length = length; | |
| 715 | |
| 716 face->root.internal->incremental_interface->funcs->free_glyph_data( | |
| 717 face->root.internal->incremental_interface->object, &data ); | |
| 718 } | |
| 719 else | |
| 720 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 721 | |
| 722 { | |
| 723 CFF_Font cff = (CFF_Font)(face->extra.data); | |
| 724 | |
| 725 | |
| 726 cff_index_forget_element( &cff->charstrings_index, pointer ); | |
| 727 } | |
| 728 } | |
| 729 | |
| 730 | |
| 731 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE | |
| 732 | |
| 733 static FT_Error | |
| 734 cff_operator_seac( CFF_Decoder* decoder, | |
| 735 FT_Pos asb, | |
| 736 FT_Pos adx, | |
| 737 FT_Pos ady, | |
| 738 FT_Int bchar, | |
| 739 FT_Int achar ) | |
| 740 { | |
| 741 FT_Error error; | |
| 742 CFF_Builder* builder = &decoder->builder; | |
| 743 FT_Int bchar_index, achar_index; | |
| 744 TT_Face face = decoder->builder.face; | |
| 745 FT_Vector left_bearing, advance; | |
| 746 FT_Byte* charstring; | |
| 747 FT_ULong charstring_len; | |
| 748 FT_Pos glyph_width; | |
| 749 | |
| 750 | |
| 751 if ( decoder->seac ) | |
| 752 { | |
| 753 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" )); | |
| 754 return FT_THROW( Syntax_Error ); | |
| 755 } | |
| 756 | |
| 757 adx += decoder->builder.left_bearing.x; | |
| 758 ady += decoder->builder.left_bearing.y; | |
| 759 | |
| 760 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 761 /* Incremental fonts don't necessarily have valid charsets. */ | |
| 762 /* They use the character code, not the glyph index, in this case. */ | |
| 763 if ( face->root.internal->incremental_interface ) | |
| 764 { | |
| 765 bchar_index = bchar; | |
| 766 achar_index = achar; | |
| 767 } | |
| 768 else | |
| 769 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 770 { | |
| 771 CFF_Font cff = (CFF_Font)(face->extra.data); | |
| 772 | |
| 773 | |
| 774 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); | |
| 775 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); | |
| 776 } | |
| 777 | |
| 778 if ( bchar_index < 0 || achar_index < 0 ) | |
| 779 { | |
| 780 FT_ERROR(( "cff_operator_seac:" | |
| 781 " invalid seac character code arguments\n" )); | |
| 782 return FT_THROW( Syntax_Error ); | |
| 783 } | |
| 784 | |
| 785 /* If we are trying to load a composite glyph, do not load the */ | |
| 786 /* accent character and return the array of subglyphs. */ | |
| 787 if ( builder->no_recurse ) | |
| 788 { | |
| 789 FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; | |
| 790 FT_GlyphLoader loader = glyph->internal->loader; | |
| 791 FT_SubGlyph subg; | |
| 792 | |
| 793 | |
| 794 /* reallocate subglyph array if necessary */ | |
| 795 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); | |
| 796 if ( error ) | |
| 797 goto Exit; | |
| 798 | |
| 799 subg = loader->current.subglyphs; | |
| 800 | |
| 801 /* subglyph 0 = base character */ | |
| 802 subg->index = bchar_index; | |
| 803 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | | |
| 804 FT_SUBGLYPH_FLAG_USE_MY_METRICS; | |
| 805 subg->arg1 = 0; | |
| 806 subg->arg2 = 0; | |
| 807 subg++; | |
| 808 | |
| 809 /* subglyph 1 = accent character */ | |
| 810 subg->index = achar_index; | |
| 811 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; | |
| 812 subg->arg1 = (FT_Int)( adx >> 16 ); | |
| 813 subg->arg2 = (FT_Int)( ady >> 16 ); | |
| 814 | |
| 815 /* set up remaining glyph fields */ | |
| 816 glyph->num_subglyphs = 2; | |
| 817 glyph->subglyphs = loader->base.subglyphs; | |
| 818 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; | |
| 819 | |
| 820 loader->current.num_subglyphs = 2; | |
| 821 } | |
| 822 | |
| 823 FT_GlyphLoader_Prepare( builder->loader ); | |
| 824 | |
| 825 /* First load `bchar' in builder */ | |
| 826 error = cff_get_glyph_data( face, bchar_index, | |
| 827 &charstring, &charstring_len ); | |
| 828 if ( !error ) | |
| 829 { | |
| 830 /* the seac operator must not be nested */ | |
| 831 decoder->seac = TRUE; | |
| 832 error = cff_decoder_parse_charstrings( decoder, charstring, | |
| 833 charstring_len ); | |
| 834 decoder->seac = FALSE; | |
| 835 | |
| 836 cff_free_glyph_data( face, &charstring, charstring_len ); | |
| 837 | |
| 838 if ( error ) | |
| 839 goto Exit; | |
| 840 } | |
| 841 | |
| 842 /* Save the left bearing, advance and glyph width of the base */ | |
| 843 /* character as they will be erased by the next load. */ | |
| 844 | |
| 845 left_bearing = builder->left_bearing; | |
| 846 advance = builder->advance; | |
| 847 glyph_width = decoder->glyph_width; | |
| 848 | |
| 849 builder->left_bearing.x = 0; | |
| 850 builder->left_bearing.y = 0; | |
| 851 | |
| 852 builder->pos_x = adx - asb; | |
| 853 builder->pos_y = ady; | |
| 854 | |
| 855 /* Now load `achar' on top of the base outline. */ | |
| 856 error = cff_get_glyph_data( face, achar_index, | |
| 857 &charstring, &charstring_len ); | |
| 858 if ( !error ) | |
| 859 { | |
| 860 /* the seac operator must not be nested */ | |
| 861 decoder->seac = TRUE; | |
| 862 error = cff_decoder_parse_charstrings( decoder, charstring, | |
| 863 charstring_len ); | |
| 864 decoder->seac = FALSE; | |
| 865 | |
| 866 cff_free_glyph_data( face, &charstring, charstring_len ); | |
| 867 | |
| 868 if ( error ) | |
| 869 goto Exit; | |
| 870 } | |
| 871 | |
| 872 /* Restore the left side bearing, advance and glyph width */ | |
| 873 /* of the base character. */ | |
| 874 builder->left_bearing = left_bearing; | |
| 875 builder->advance = advance; | |
| 876 decoder->glyph_width = glyph_width; | |
| 877 | |
| 878 builder->pos_x = 0; | |
| 879 builder->pos_y = 0; | |
| 880 | |
| 881 Exit: | |
| 882 return error; | |
| 883 } | |
| 884 | |
| 885 | |
| 886 /*************************************************************************/ | |
| 887 /* */ | |
| 888 /* <Function> */ | |
| 889 /* cff_decoder_parse_charstrings */ | |
| 890 /* */ | |
| 891 /* <Description> */ | |
| 892 /* Parses a given Type 2 charstrings program. */ | |
| 893 /* */ | |
| 894 /* <InOut> */ | |
| 895 /* decoder :: The current Type 1 decoder. */ | |
| 896 /* */ | |
| 897 /* <Input> */ | |
| 898 /* charstring_base :: The base of the charstring stream. */ | |
| 899 /* */ | |
| 900 /* charstring_len :: The length in bytes of the charstring stream. */ | |
| 901 /* */ | |
| 902 /* <Return> */ | |
| 903 /* FreeType error code. 0 means success. */ | |
| 904 /* */ | |
| 905 FT_LOCAL_DEF( FT_Error ) | |
| 906 cff_decoder_parse_charstrings( CFF_Decoder* decoder, | |
| 907 FT_Byte* charstring_base, | |
| 908 FT_ULong charstring_len ) | |
| 909 { | |
| 910 FT_Error error; | |
| 911 CFF_Decoder_Zone* zone; | |
| 912 FT_Byte* ip; | |
| 913 FT_Byte* limit; | |
| 914 CFF_Builder* builder = &decoder->builder; | |
| 915 FT_Pos x, y; | |
| 916 FT_Fixed seed; | |
| 917 FT_Fixed* stack; | |
| 918 FT_Int charstring_type = | |
| 919 decoder->cff->top_font.font_dict.charstring_type; | |
| 920 | |
| 921 T2_Hints_Funcs hinter; | |
| 922 | |
| 923 | |
| 924 /* set default width */ | |
| 925 decoder->num_hints = 0; | |
| 926 decoder->read_width = 1; | |
| 927 | |
| 928 /* compute random seed from stack address of parameter */ | |
| 929 seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ | |
| 930 (FT_PtrDist)(char*)&decoder ^ | |
| 931 (FT_PtrDist)(char*)&charstring_base ) & | |
| 932 FT_ULONG_MAX ) ; | |
| 933 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; | |
| 934 if ( seed == 0 ) | |
| 935 seed = 0x7384; | |
| 936 | |
| 937 /* initialize the decoder */ | |
| 938 decoder->top = decoder->stack; | |
| 939 decoder->zone = decoder->zones; | |
| 940 zone = decoder->zones; | |
| 941 stack = decoder->top; | |
| 942 | |
| 943 hinter = (T2_Hints_Funcs)builder->hints_funcs; | |
| 944 | |
| 945 builder->path_begun = 0; | |
| 946 | |
| 947 zone->base = charstring_base; | |
| 948 limit = zone->limit = charstring_base + charstring_len; | |
| 949 ip = zone->cursor = zone->base; | |
| 950 | |
| 951 error = FT_Err_Ok; | |
| 952 | |
| 953 x = builder->pos_x; | |
| 954 y = builder->pos_y; | |
| 955 | |
| 956 /* begin hints recording session, if any */ | |
| 957 if ( hinter ) | |
| 958 hinter->open( hinter->hints ); | |
| 959 | |
| 960 /* now execute loop */ | |
| 961 while ( ip < limit ) | |
| 962 { | |
| 963 CFF_Operator op; | |
| 964 FT_Byte v; | |
| 965 | |
| 966 | |
| 967 /********************************************************************/ | |
| 968 /* */ | |
| 969 /* Decode operator or operand */ | |
| 970 /* */ | |
| 971 v = *ip++; | |
| 972 if ( v >= 32 || v == 28 ) | |
| 973 { | |
| 974 FT_Int shift = 16; | |
| 975 FT_Int32 val; | |
| 976 | |
| 977 | |
| 978 /* this is an operand, push it on the stack */ | |
| 979 | |
| 980 /* if we use shifts, all computations are done with unsigned */ | |
| 981 /* values; the conversion to a signed value is the last step */ | |
| 982 if ( v == 28 ) | |
| 983 { | |
| 984 if ( ip + 1 >= limit ) | |
| 985 goto Syntax_Error; | |
| 986 val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] ); | |
| 987 ip += 2; | |
| 988 } | |
| 989 else if ( v < 247 ) | |
| 990 val = (FT_Int32)v - 139; | |
| 991 else if ( v < 251 ) | |
| 992 { | |
| 993 if ( ip >= limit ) | |
| 994 goto Syntax_Error; | |
| 995 val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108; | |
| 996 } | |
| 997 else if ( v < 255 ) | |
| 998 { | |
| 999 if ( ip >= limit ) | |
| 1000 goto Syntax_Error; | |
| 1001 val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108; | |
| 1002 } | |
| 1003 else | |
| 1004 { | |
| 1005 if ( ip + 3 >= limit ) | |
| 1006 goto Syntax_Error; | |
| 1007 val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) | | |
| 1008 ( (FT_UInt32)ip[1] << 16 ) | | |
| 1009 ( (FT_UInt32)ip[2] << 8 ) | | |
| 1010 (FT_UInt32)ip[3] ); | |
| 1011 ip += 4; | |
| 1012 if ( charstring_type == 2 ) | |
| 1013 shift = 0; | |
| 1014 } | |
| 1015 if ( decoder->top - stack >= CFF_MAX_OPERANDS ) | |
| 1016 goto Stack_Overflow; | |
| 1017 | |
| 1018 val = (FT_Int32)( (FT_UInt32)val << shift ); | |
| 1019 *decoder->top++ = val; | |
| 1020 | |
| 1021 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 1022 if ( !( val & 0xFFFFL ) ) | |
| 1023 FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) )); | |
| 1024 else | |
| 1025 FT_TRACE4(( " %.2f", val / 65536.0 )); | |
| 1026 #endif | |
| 1027 | |
| 1028 } | |
| 1029 else | |
| 1030 { | |
| 1031 /* The specification says that normally arguments are to be taken */ | |
| 1032 /* from the bottom of the stack. However, this seems not to be */ | |
| 1033 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */ | |
| 1034 /* arguments similar to a PS interpreter. */ | |
| 1035 | |
| 1036 FT_Fixed* args = decoder->top; | |
| 1037 FT_Int num_args = (FT_Int)( args - decoder->stack ); | |
| 1038 FT_Int req_args; | |
| 1039 | |
| 1040 | |
| 1041 /* find operator */ | |
| 1042 op = cff_op_unknown; | |
| 1043 | |
| 1044 switch ( v ) | |
| 1045 { | |
| 1046 case 1: | |
| 1047 op = cff_op_hstem; | |
| 1048 break; | |
| 1049 case 3: | |
| 1050 op = cff_op_vstem; | |
| 1051 break; | |
| 1052 case 4: | |
| 1053 op = cff_op_vmoveto; | |
| 1054 break; | |
| 1055 case 5: | |
| 1056 op = cff_op_rlineto; | |
| 1057 break; | |
| 1058 case 6: | |
| 1059 op = cff_op_hlineto; | |
| 1060 break; | |
| 1061 case 7: | |
| 1062 op = cff_op_vlineto; | |
| 1063 break; | |
| 1064 case 8: | |
| 1065 op = cff_op_rrcurveto; | |
| 1066 break; | |
| 1067 case 9: | |
| 1068 op = cff_op_closepath; | |
| 1069 break; | |
| 1070 case 10: | |
| 1071 op = cff_op_callsubr; | |
| 1072 break; | |
| 1073 case 11: | |
| 1074 op = cff_op_return; | |
| 1075 break; | |
| 1076 case 12: | |
| 1077 { | |
| 1078 if ( ip >= limit ) | |
| 1079 goto Syntax_Error; | |
| 1080 v = *ip++; | |
| 1081 | |
| 1082 switch ( v ) | |
| 1083 { | |
| 1084 case 0: | |
| 1085 op = cff_op_dotsection; | |
| 1086 break; | |
| 1087 case 1: /* this is actually the Type1 vstem3 operator */ | |
| 1088 op = cff_op_vstem; | |
| 1089 break; | |
| 1090 case 2: /* this is actually the Type1 hstem3 operator */ | |
| 1091 op = cff_op_hstem; | |
| 1092 break; | |
| 1093 case 3: | |
| 1094 op = cff_op_and; | |
| 1095 break; | |
| 1096 case 4: | |
| 1097 op = cff_op_or; | |
| 1098 break; | |
| 1099 case 5: | |
| 1100 op = cff_op_not; | |
| 1101 break; | |
| 1102 case 6: | |
| 1103 op = cff_op_seac; | |
| 1104 break; | |
| 1105 case 7: | |
| 1106 op = cff_op_sbw; | |
| 1107 break; | |
| 1108 case 8: | |
| 1109 op = cff_op_store; | |
| 1110 break; | |
| 1111 case 9: | |
| 1112 op = cff_op_abs; | |
| 1113 break; | |
| 1114 case 10: | |
| 1115 op = cff_op_add; | |
| 1116 break; | |
| 1117 case 11: | |
| 1118 op = cff_op_sub; | |
| 1119 break; | |
| 1120 case 12: | |
| 1121 op = cff_op_div; | |
| 1122 break; | |
| 1123 case 13: | |
| 1124 op = cff_op_load; | |
| 1125 break; | |
| 1126 case 14: | |
| 1127 op = cff_op_neg; | |
| 1128 break; | |
| 1129 case 15: | |
| 1130 op = cff_op_eq; | |
| 1131 break; | |
| 1132 case 16: | |
| 1133 op = cff_op_callothersubr; | |
| 1134 break; | |
| 1135 case 17: | |
| 1136 op = cff_op_pop; | |
| 1137 break; | |
| 1138 case 18: | |
| 1139 op = cff_op_drop; | |
| 1140 break; | |
| 1141 case 20: | |
| 1142 op = cff_op_put; | |
| 1143 break; | |
| 1144 case 21: | |
| 1145 op = cff_op_get; | |
| 1146 break; | |
| 1147 case 22: | |
| 1148 op = cff_op_ifelse; | |
| 1149 break; | |
| 1150 case 23: | |
| 1151 op = cff_op_random; | |
| 1152 break; | |
| 1153 case 24: | |
| 1154 op = cff_op_mul; | |
| 1155 break; | |
| 1156 case 26: | |
| 1157 op = cff_op_sqrt; | |
| 1158 break; | |
| 1159 case 27: | |
| 1160 op = cff_op_dup; | |
| 1161 break; | |
| 1162 case 28: | |
| 1163 op = cff_op_exch; | |
| 1164 break; | |
| 1165 case 29: | |
| 1166 op = cff_op_index; | |
| 1167 break; | |
| 1168 case 30: | |
| 1169 op = cff_op_roll; | |
| 1170 break; | |
| 1171 case 33: | |
| 1172 op = cff_op_setcurrentpoint; | |
| 1173 break; | |
| 1174 case 34: | |
| 1175 op = cff_op_hflex; | |
| 1176 break; | |
| 1177 case 35: | |
| 1178 op = cff_op_flex; | |
| 1179 break; | |
| 1180 case 36: | |
| 1181 op = cff_op_hflex1; | |
| 1182 break; | |
| 1183 case 37: | |
| 1184 op = cff_op_flex1; | |
| 1185 break; | |
| 1186 /*default: */ /* XYQ 2007-9-6: we can't just quit if we see some re
served op */ | |
| 1187 /* decrement ip for syntax error message */ | |
| 1188 /* ip--;*/ | |
| 1189 } | |
| 1190 } | |
| 1191 break; | |
| 1192 case 13: | |
| 1193 op = cff_op_hsbw; | |
| 1194 break; | |
| 1195 case 14: | |
| 1196 op = cff_op_endchar; | |
| 1197 break; | |
| 1198 case 16: | |
| 1199 op = cff_op_blend; | |
| 1200 break; | |
| 1201 case 18: | |
| 1202 op = cff_op_hstemhm; | |
| 1203 break; | |
| 1204 case 19: | |
| 1205 op = cff_op_hintmask; | |
| 1206 break; | |
| 1207 case 20: | |
| 1208 op = cff_op_cntrmask; | |
| 1209 break; | |
| 1210 case 21: | |
| 1211 op = cff_op_rmoveto; | |
| 1212 break; | |
| 1213 case 22: | |
| 1214 op = cff_op_hmoveto; | |
| 1215 break; | |
| 1216 case 23: | |
| 1217 op = cff_op_vstemhm; | |
| 1218 break; | |
| 1219 case 24: | |
| 1220 op = cff_op_rcurveline; | |
| 1221 break; | |
| 1222 case 25: | |
| 1223 op = cff_op_rlinecurve; | |
| 1224 break; | |
| 1225 case 26: | |
| 1226 op = cff_op_vvcurveto; | |
| 1227 break; | |
| 1228 case 27: | |
| 1229 op = cff_op_hhcurveto; | |
| 1230 break; | |
| 1231 case 29: | |
| 1232 op = cff_op_callgsubr; | |
| 1233 break; | |
| 1234 case 30: | |
| 1235 op = cff_op_vhcurveto; | |
| 1236 break; | |
| 1237 case 31: | |
| 1238 op = cff_op_hvcurveto; | |
| 1239 break; | |
| 1240 default: | |
| 1241 FT_TRACE4(( " unknown op (%d)\n", v )); | |
| 1242 break; | |
| 1243 } | |
| 1244 | |
| 1245 if ( op == cff_op_unknown ) | |
| 1246 continue; | |
| 1247 | |
| 1248 /* check arguments */ | |
| 1249 req_args = cff_argument_counts[op]; | |
| 1250 if ( req_args & CFF_COUNT_CHECK_WIDTH ) | |
| 1251 { | |
| 1252 if ( num_args > 0 && decoder->read_width ) | |
| 1253 { | |
| 1254 /* If `nominal_width' is non-zero, the number is really a */ | |
| 1255 /* difference against `nominal_width'. Else, the number here */ | |
| 1256 /* is truly a width, not a difference against `nominal_width'. */ | |
| 1257 /* If the font does not set `nominal_width', then */ | |
| 1258 /* `nominal_width' defaults to zero, and so we can set */ | |
| 1259 /* `glyph_width' to `nominal_width' plus number on the stack */ | |
| 1260 /* -- for either case. */ | |
| 1261 | |
| 1262 FT_Int set_width_ok; | |
| 1263 | |
| 1264 | |
| 1265 switch ( op ) | |
| 1266 { | |
| 1267 case cff_op_hmoveto: | |
| 1268 case cff_op_vmoveto: | |
| 1269 set_width_ok = num_args & 2; | |
| 1270 break; | |
| 1271 | |
| 1272 case cff_op_hstem: | |
| 1273 case cff_op_vstem: | |
| 1274 case cff_op_hstemhm: | |
| 1275 case cff_op_vstemhm: | |
| 1276 case cff_op_rmoveto: | |
| 1277 case cff_op_hintmask: | |
| 1278 case cff_op_cntrmask: | |
| 1279 set_width_ok = num_args & 1; | |
| 1280 break; | |
| 1281 | |
| 1282 case cff_op_endchar: | |
| 1283 /* If there is a width specified for endchar, we either have */ | |
| 1284 /* 1 argument or 5 arguments. We like to argue. */ | |
| 1285 set_width_ok = ( num_args == 5 ) || ( num_args == 1 ); | |
| 1286 break; | |
| 1287 | |
| 1288 default: | |
| 1289 set_width_ok = 0; | |
| 1290 break; | |
| 1291 } | |
| 1292 | |
| 1293 if ( set_width_ok ) | |
| 1294 { | |
| 1295 decoder->glyph_width = decoder->nominal_width + | |
| 1296 ( stack[0] >> 16 ); | |
| 1297 | |
| 1298 if ( decoder->width_only ) | |
| 1299 { | |
| 1300 /* we only want the advance width; stop here */ | |
| 1301 break; | |
| 1302 } | |
| 1303 | |
| 1304 /* Consumed an argument. */ | |
| 1305 num_args--; | |
| 1306 } | |
| 1307 } | |
| 1308 | |
| 1309 decoder->read_width = 0; | |
| 1310 req_args = 0; | |
| 1311 } | |
| 1312 | |
| 1313 req_args &= 0x000F; | |
| 1314 if ( num_args < req_args ) | |
| 1315 goto Stack_Underflow; | |
| 1316 args -= req_args; | |
| 1317 num_args -= req_args; | |
| 1318 | |
| 1319 /* Sunliang.Liu sync 221's revison. */ | |
| 1320 if (args > decoder->stack + CFF_MAX_OPERANDS) | |
| 1321 goto Stack_Overflow; | |
| 1322 | |
| 1323 /* At this point, `args' points to the first argument of the */ | |
| 1324 /* operand in case `req_args' isn't zero. Otherwise, we have */ | |
| 1325 /* to adjust `args' manually. */ | |
| 1326 | |
| 1327 /* Note that we only pop arguments from the stack which we */ | |
| 1328 /* really need and can digest so that we can continue in case */ | |
| 1329 /* of superfluous stack elements. */ | |
| 1330 | |
| 1331 switch ( op ) | |
| 1332 { | |
| 1333 case cff_op_hstem: | |
| 1334 case cff_op_vstem: | |
| 1335 case cff_op_hstemhm: | |
| 1336 case cff_op_vstemhm: | |
| 1337 /* the number of arguments is always even here */ | |
| 1338 FT_TRACE4(( | |
| 1339 op == cff_op_hstem ? " hstem\n" : | |
| 1340 ( op == cff_op_vstem ? " vstem\n" : | |
| 1341 ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) )); | |
| 1342 | |
| 1343 if ( hinter ) | |
| 1344 hinter->stems( hinter->hints, | |
| 1345 ( op == cff_op_hstem || op == cff_op_hstemhm ), | |
| 1346 num_args / 2, | |
| 1347 args - ( num_args & ~1 ) ); | |
| 1348 | |
| 1349 decoder->num_hints += num_args / 2; | |
| 1350 args = stack; | |
| 1351 break; | |
| 1352 | |
| 1353 case cff_op_hintmask: | |
| 1354 case cff_op_cntrmask: | |
| 1355 FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); | |
| 1356 | |
| 1357 /* implement vstem when needed -- */ | |
| 1358 /* the specification doesn't say it, but this also works */ | |
| 1359 /* with the 'cntrmask' operator */ | |
| 1360 /* */ | |
| 1361 if ( num_args > 0 ) | |
| 1362 { | |
| 1363 if ( hinter ) | |
| 1364 hinter->stems( hinter->hints, | |
| 1365 0, | |
| 1366 num_args / 2, | |
| 1367 args - ( num_args & ~1 ) ); | |
| 1368 | |
| 1369 decoder->num_hints += num_args / 2; | |
| 1370 } | |
| 1371 | |
| 1372 /* In a valid charstring there must be at least one byte */ | |
| 1373 /* after `hintmask' or `cntrmask' (e.g., for a `return' */ | |
| 1374 /* instruction). Additionally, there must be space for */ | |
| 1375 /* `num_hints' bits. */ | |
| 1376 | |
| 1377 if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit ) | |
| 1378 goto Syntax_Error; | |
| 1379 | |
| 1380 if ( hinter ) | |
| 1381 { | |
| 1382 if ( op == cff_op_hintmask ) | |
| 1383 hinter->hintmask( hinter->hints, | |
| 1384 builder->current->n_points, | |
| 1385 decoder->num_hints, | |
| 1386 ip ); | |
| 1387 else | |
| 1388 hinter->counter( hinter->hints, | |
| 1389 decoder->num_hints, | |
| 1390 ip ); | |
| 1391 } | |
| 1392 | |
| 1393 #ifdef FT_DEBUG_LEVEL_TRACE | |
| 1394 { | |
| 1395 FT_UInt maskbyte; | |
| 1396 | |
| 1397 | |
| 1398 FT_TRACE4(( " (maskbytes:" )); | |
| 1399 | |
| 1400 for ( maskbyte = 0; | |
| 1401 maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 ); | |
| 1402 maskbyte++, ip++ ) | |
| 1403 FT_TRACE4(( " 0x%02X", *ip )); | |
| 1404 | |
| 1405 FT_TRACE4(( ")\n" )); | |
| 1406 } | |
| 1407 #else | |
| 1408 ip += ( decoder->num_hints + 7 ) >> 3; | |
| 1409 #endif | |
| 1410 args = stack; | |
| 1411 break; | |
| 1412 | |
| 1413 case cff_op_rmoveto: | |
| 1414 FT_TRACE4(( " rmoveto\n" )); | |
| 1415 | |
| 1416 cff_builder_close_contour( builder ); | |
| 1417 builder->path_begun = 0; | |
| 1418 x += args[-2]; | |
| 1419 y += args[-1]; | |
| 1420 args = stack; | |
| 1421 break; | |
| 1422 | |
| 1423 case cff_op_vmoveto: | |
| 1424 FT_TRACE4(( " vmoveto\n" )); | |
| 1425 | |
| 1426 cff_builder_close_contour( builder ); | |
| 1427 builder->path_begun = 0; | |
| 1428 y += args[-1]; | |
| 1429 args = stack; | |
| 1430 break; | |
| 1431 | |
| 1432 case cff_op_hmoveto: | |
| 1433 FT_TRACE4(( " hmoveto\n" )); | |
| 1434 | |
| 1435 cff_builder_close_contour( builder ); | |
| 1436 builder->path_begun = 0; | |
| 1437 x += args[-1]; | |
| 1438 args = stack; | |
| 1439 break; | |
| 1440 | |
| 1441 case cff_op_rlineto: | |
| 1442 FT_TRACE4(( " rlineto\n" )); | |
| 1443 | |
| 1444 if ( cff_builder_start_point( builder, x, y ) || | |
| 1445 cff_check_points( builder, num_args / 2 ) ) | |
| 1446 goto Fail; | |
| 1447 | |
| 1448 if ( num_args < 2 ) | |
| 1449 goto Stack_Underflow; | |
| 1450 | |
| 1451 args -= num_args & ~1; | |
| 1452 while ( args < decoder->top ) | |
| 1453 { | |
| 1454 x += args[0]; | |
| 1455 y += args[1]; | |
| 1456 cff_builder_add_point( builder, x, y, 1 ); | |
| 1457 args += 2; | |
| 1458 } | |
| 1459 args = stack; | |
| 1460 break; | |
| 1461 | |
| 1462 case cff_op_hlineto: | |
| 1463 case cff_op_vlineto: | |
| 1464 { | |
| 1465 FT_Int phase = ( op == cff_op_hlineto ); | |
| 1466 | |
| 1467 | |
| 1468 FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n" | |
| 1469 : " vlineto\n" )); | |
| 1470 | |
| 1471 if ( num_args < 0 ) | |
| 1472 goto Stack_Underflow; | |
| 1473 | |
| 1474 /* there exist subsetted fonts (found in PDFs) */ | |
| 1475 /* which call `hlineto' without arguments */ | |
| 1476 if ( num_args == 0 ) | |
| 1477 break; | |
| 1478 | |
| 1479 if ( cff_builder_start_point( builder, x, y ) || | |
| 1480 cff_check_points( builder, num_args ) ) | |
| 1481 goto Fail; | |
| 1482 | |
| 1483 args = stack; | |
| 1484 while ( args < decoder->top ) | |
| 1485 { | |
| 1486 if ( phase ) | |
| 1487 x += args[0]; | |
| 1488 else | |
| 1489 y += args[0]; | |
| 1490 | |
| 1491 if ( cff_builder_add_point1( builder, x, y ) ) | |
| 1492 goto Fail; | |
| 1493 | |
| 1494 args++; | |
| 1495 phase ^= 1; | |
| 1496 } | |
| 1497 args = stack; | |
| 1498 } | |
| 1499 break; | |
| 1500 | |
| 1501 case cff_op_rrcurveto: | |
| 1502 { | |
| 1503 FT_Int nargs; | |
| 1504 | |
| 1505 | |
| 1506 FT_TRACE4(( " rrcurveto\n" )); | |
| 1507 | |
| 1508 if ( num_args < 6 ) | |
| 1509 goto Stack_Underflow; | |
| 1510 | |
| 1511 nargs = num_args - num_args % 6; | |
| 1512 | |
| 1513 if ( cff_builder_start_point( builder, x, y ) || | |
| 1514 cff_check_points( builder, nargs / 2 ) ) | |
| 1515 goto Fail; | |
| 1516 | |
| 1517 args -= nargs; | |
| 1518 while ( args < decoder->top ) | |
| 1519 { | |
| 1520 x += args[0]; | |
| 1521 y += args[1]; | |
| 1522 cff_builder_add_point( builder, x, y, 0 ); | |
| 1523 x += args[2]; | |
| 1524 y += args[3]; | |
| 1525 cff_builder_add_point( builder, x, y, 0 ); | |
| 1526 x += args[4]; | |
| 1527 y += args[5]; | |
| 1528 cff_builder_add_point( builder, x, y, 1 ); | |
| 1529 args += 6; | |
| 1530 } | |
| 1531 args = stack; | |
| 1532 } | |
| 1533 break; | |
| 1534 | |
| 1535 case cff_op_vvcurveto: | |
| 1536 { | |
| 1537 FT_Int nargs; | |
| 1538 | |
| 1539 | |
| 1540 FT_TRACE4(( " vvcurveto\n" )); | |
| 1541 | |
| 1542 if ( num_args < 4 ) | |
| 1543 goto Stack_Underflow; | |
| 1544 | |
| 1545 /* if num_args isn't of the form 4n or 4n+1, */ | |
| 1546 /* we enforce it by clearing the second bit */ | |
| 1547 | |
| 1548 nargs = num_args & ~2; | |
| 1549 | |
| 1550 if ( cff_builder_start_point( builder, x, y ) ) | |
| 1551 goto Fail; | |
| 1552 | |
| 1553 args -= nargs; | |
| 1554 | |
| 1555 if ( nargs & 1 ) | |
| 1556 { | |
| 1557 x += args[0]; | |
| 1558 args++; | |
| 1559 nargs--; | |
| 1560 } | |
| 1561 | |
| 1562 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) | |
| 1563 goto Fail; | |
| 1564 | |
| 1565 while ( args < decoder->top ) | |
| 1566 { | |
| 1567 y += args[0]; | |
| 1568 cff_builder_add_point( builder, x, y, 0 ); | |
| 1569 x += args[1]; | |
| 1570 y += args[2]; | |
| 1571 cff_builder_add_point( builder, x, y, 0 ); | |
| 1572 y += args[3]; | |
| 1573 cff_builder_add_point( builder, x, y, 1 ); | |
| 1574 args += 4; | |
| 1575 } | |
| 1576 args = stack; | |
| 1577 } | |
| 1578 break; | |
| 1579 | |
| 1580 case cff_op_hhcurveto: | |
| 1581 { | |
| 1582 FT_Int nargs; | |
| 1583 | |
| 1584 | |
| 1585 FT_TRACE4(( " hhcurveto\n" )); | |
| 1586 | |
| 1587 if ( num_args < 4 ) | |
| 1588 goto Stack_Underflow; | |
| 1589 | |
| 1590 /* if num_args isn't of the form 4n or 4n+1, */ | |
| 1591 /* we enforce it by clearing the second bit */ | |
| 1592 | |
| 1593 nargs = num_args & ~2; | |
| 1594 | |
| 1595 if ( cff_builder_start_point( builder, x, y ) ) | |
| 1596 goto Fail; | |
| 1597 | |
| 1598 args -= nargs; | |
| 1599 if ( nargs & 1 ) | |
| 1600 { | |
| 1601 y += args[0]; | |
| 1602 args++; | |
| 1603 nargs--; | |
| 1604 } | |
| 1605 | |
| 1606 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) ) | |
| 1607 goto Fail; | |
| 1608 | |
| 1609 while ( args < decoder->top ) | |
| 1610 { | |
| 1611 x += args[0]; | |
| 1612 cff_builder_add_point( builder, x, y, 0 ); | |
| 1613 x += args[1]; | |
| 1614 y += args[2]; | |
| 1615 cff_builder_add_point( builder, x, y, 0 ); | |
| 1616 x += args[3]; | |
| 1617 cff_builder_add_point( builder, x, y, 1 ); | |
| 1618 args += 4; | |
| 1619 } | |
| 1620 args = stack; | |
| 1621 } | |
| 1622 break; | |
| 1623 | |
| 1624 case cff_op_vhcurveto: | |
| 1625 case cff_op_hvcurveto: | |
| 1626 { | |
| 1627 FT_Int phase; | |
| 1628 FT_Int nargs; | |
| 1629 | |
| 1630 | |
| 1631 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n" | |
| 1632 : " hvcurveto\n" )); | |
| 1633 | |
| 1634 if ( cff_builder_start_point( builder, x, y ) ) | |
| 1635 goto Fail; | |
| 1636 | |
| 1637 if ( num_args < 4 ) | |
| 1638 goto Stack_Underflow; | |
| 1639 | |
| 1640 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */ | |
| 1641 /* we enforce it by clearing the second bit */ | |
| 1642 | |
| 1643 nargs = num_args & ~2; | |
| 1644 | |
| 1645 args -= nargs; | |
| 1646 if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) ) | |
| 1647 goto Stack_Underflow; | |
| 1648 | |
| 1649 phase = ( op == cff_op_hvcurveto ); | |
| 1650 | |
| 1651 while ( nargs >= 4 ) | |
| 1652 { | |
| 1653 nargs -= 4; | |
| 1654 if ( phase ) | |
| 1655 { | |
| 1656 x += args[0]; | |
| 1657 cff_builder_add_point( builder, x, y, 0 ); | |
| 1658 x += args[1]; | |
| 1659 y += args[2]; | |
| 1660 cff_builder_add_point( builder, x, y, 0 ); | |
| 1661 y += args[3]; | |
| 1662 if ( nargs == 1 ) | |
| 1663 x += args[4]; | |
| 1664 cff_builder_add_point( builder, x, y, 1 ); | |
| 1665 } | |
| 1666 else | |
| 1667 { | |
| 1668 y += args[0]; | |
| 1669 cff_builder_add_point( builder, x, y, 0 ); | |
| 1670 x += args[1]; | |
| 1671 y += args[2]; | |
| 1672 cff_builder_add_point( builder, x, y, 0 ); | |
| 1673 x += args[3]; | |
| 1674 if ( nargs == 1 ) | |
| 1675 y += args[4]; | |
| 1676 cff_builder_add_point( builder, x, y, 1 ); | |
| 1677 } | |
| 1678 args += 4; | |
| 1679 phase ^= 1; | |
| 1680 } | |
| 1681 args = stack; | |
| 1682 } | |
| 1683 break; | |
| 1684 | |
| 1685 case cff_op_rlinecurve: | |
| 1686 { | |
| 1687 FT_Int num_lines; | |
| 1688 FT_Int nargs; | |
| 1689 | |
| 1690 | |
| 1691 FT_TRACE4(( " rlinecurve\n" )); | |
| 1692 | |
| 1693 if ( num_args < 8 ) | |
| 1694 goto Stack_Underflow; | |
| 1695 | |
| 1696 nargs = num_args & ~1; | |
| 1697 num_lines = ( nargs - 6 ) / 2; | |
| 1698 | |
| 1699 if ( cff_builder_start_point( builder, x, y ) || | |
| 1700 cff_check_points( builder, num_lines + 3 ) ) | |
| 1701 goto Fail; | |
| 1702 | |
| 1703 args -= nargs; | |
| 1704 | |
| 1705 /* first, add the line segments */ | |
| 1706 while ( num_lines > 0 ) | |
| 1707 { | |
| 1708 x += args[0]; | |
| 1709 y += args[1]; | |
| 1710 cff_builder_add_point( builder, x, y, 1 ); | |
| 1711 args += 2; | |
| 1712 num_lines--; | |
| 1713 } | |
| 1714 | |
| 1715 /* then the curve */ | |
| 1716 x += args[0]; | |
| 1717 y += args[1]; | |
| 1718 cff_builder_add_point( builder, x, y, 0 ); | |
| 1719 x += args[2]; | |
| 1720 y += args[3]; | |
| 1721 cff_builder_add_point( builder, x, y, 0 ); | |
| 1722 x += args[4]; | |
| 1723 y += args[5]; | |
| 1724 cff_builder_add_point( builder, x, y, 1 ); | |
| 1725 args = stack; | |
| 1726 } | |
| 1727 break; | |
| 1728 | |
| 1729 case cff_op_rcurveline: | |
| 1730 { | |
| 1731 FT_Int num_curves; | |
| 1732 FT_Int nargs; | |
| 1733 | |
| 1734 | |
| 1735 FT_TRACE4(( " rcurveline\n" )); | |
| 1736 | |
| 1737 if ( num_args < 8 ) | |
| 1738 goto Stack_Underflow; | |
| 1739 | |
| 1740 nargs = num_args - 2; | |
| 1741 nargs = nargs - nargs % 6 + 2; | |
| 1742 num_curves = ( nargs - 2 ) / 6; | |
| 1743 | |
| 1744 if ( cff_builder_start_point( builder, x, y ) || | |
| 1745 cff_check_points( builder, num_curves * 3 + 2 ) ) | |
| 1746 goto Fail; | |
| 1747 | |
| 1748 args -= nargs; | |
| 1749 | |
| 1750 /* first, add the curves */ | |
| 1751 while ( num_curves > 0 ) | |
| 1752 { | |
| 1753 x += args[0]; | |
| 1754 y += args[1]; | |
| 1755 cff_builder_add_point( builder, x, y, 0 ); | |
| 1756 x += args[2]; | |
| 1757 y += args[3]; | |
| 1758 cff_builder_add_point( builder, x, y, 0 ); | |
| 1759 x += args[4]; | |
| 1760 y += args[5]; | |
| 1761 cff_builder_add_point( builder, x, y, 1 ); | |
| 1762 args += 6; | |
| 1763 num_curves--; | |
| 1764 } | |
| 1765 | |
| 1766 /* then the final line */ | |
| 1767 x += args[0]; | |
| 1768 y += args[1]; | |
| 1769 cff_builder_add_point( builder, x, y, 1 ); | |
| 1770 args = stack; | |
| 1771 } | |
| 1772 break; | |
| 1773 | |
| 1774 case cff_op_hflex1: | |
| 1775 { | |
| 1776 FT_Pos start_y; | |
| 1777 | |
| 1778 | |
| 1779 FT_TRACE4(( " hflex1\n" )); | |
| 1780 | |
| 1781 /* adding five more points: 4 control points, 1 on-curve point */ | |
| 1782 /* -- make sure we have enough space for the start point if it */ | |
| 1783 /* needs to be added */ | |
| 1784 if ( cff_builder_start_point( builder, x, y ) || | |
| 1785 cff_check_points( builder, 6 ) ) | |
| 1786 goto Fail; | |
| 1787 | |
| 1788 /* record the starting point's y position for later use */ | |
| 1789 start_y = y; | |
| 1790 | |
| 1791 /* first control point */ | |
| 1792 x += args[0]; | |
| 1793 y += args[1]; | |
| 1794 cff_builder_add_point( builder, x, y, 0 ); | |
| 1795 | |
| 1796 /* second control point */ | |
| 1797 x += args[2]; | |
| 1798 y += args[3]; | |
| 1799 cff_builder_add_point( builder, x, y, 0 ); | |
| 1800 | |
| 1801 /* join point; on curve, with y-value the same as the last */ | |
| 1802 /* control point's y-value */ | |
| 1803 x += args[4]; | |
| 1804 cff_builder_add_point( builder, x, y, 1 ); | |
| 1805 | |
| 1806 /* third control point, with y-value the same as the join */ | |
| 1807 /* point's y-value */ | |
| 1808 x += args[5]; | |
| 1809 cff_builder_add_point( builder, x, y, 0 ); | |
| 1810 | |
| 1811 /* fourth control point */ | |
| 1812 x += args[6]; | |
| 1813 y += args[7]; | |
| 1814 cff_builder_add_point( builder, x, y, 0 ); | |
| 1815 | |
| 1816 /* ending point, with y-value the same as the start */ | |
| 1817 x += args[8]; | |
| 1818 y = start_y; | |
| 1819 cff_builder_add_point( builder, x, y, 1 ); | |
| 1820 | |
| 1821 args = stack; | |
| 1822 break; | |
| 1823 } | |
| 1824 | |
| 1825 case cff_op_hflex: | |
| 1826 { | |
| 1827 FT_Pos start_y; | |
| 1828 | |
| 1829 | |
| 1830 FT_TRACE4(( " hflex\n" )); | |
| 1831 | |
| 1832 /* adding six more points; 4 control points, 2 on-curve points */ | |
| 1833 if ( cff_builder_start_point( builder, x, y ) || | |
| 1834 cff_check_points( builder, 6 ) ) | |
| 1835 goto Fail; | |
| 1836 | |
| 1837 /* record the starting point's y-position for later use */ | |
| 1838 start_y = y; | |
| 1839 | |
| 1840 /* first control point */ | |
| 1841 x += args[0]; | |
| 1842 cff_builder_add_point( builder, x, y, 0 ); | |
| 1843 | |
| 1844 /* second control point */ | |
| 1845 x += args[1]; | |
| 1846 y += args[2]; | |
| 1847 cff_builder_add_point( builder, x, y, 0 ); | |
| 1848 | |
| 1849 /* join point; on curve, with y-value the same as the last */ | |
| 1850 /* control point's y-value */ | |
| 1851 x += args[3]; | |
| 1852 cff_builder_add_point( builder, x, y, 1 ); | |
| 1853 | |
| 1854 /* third control point, with y-value the same as the join */ | |
| 1855 /* point's y-value */ | |
| 1856 x += args[4]; | |
| 1857 cff_builder_add_point( builder, x, y, 0 ); | |
| 1858 | |
| 1859 /* fourth control point */ | |
| 1860 x += args[5]; | |
| 1861 y = start_y; | |
| 1862 cff_builder_add_point( builder, x, y, 0 ); | |
| 1863 | |
| 1864 /* ending point, with y-value the same as the start point's */ | |
| 1865 /* y-value -- we don't add this point, though */ | |
| 1866 x += args[6]; | |
| 1867 cff_builder_add_point( builder, x, y, 1 ); | |
| 1868 | |
| 1869 args = stack; | |
| 1870 break; | |
| 1871 } | |
| 1872 | |
| 1873 case cff_op_flex1: | |
| 1874 { | |
| 1875 FT_Pos start_x, start_y; /* record start x, y values for */ | |
| 1876 /* alter use */ | |
| 1877 FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ | |
| 1878 /* algorithm below */ | |
| 1879 FT_Int horizontal, count; | |
| 1880 FT_Fixed* temp; | |
| 1881 | |
| 1882 | |
| 1883 FT_TRACE4(( " flex1\n" )); | |
| 1884 | |
| 1885 /* adding six more points; 4 control points, 2 on-curve points */ | |
| 1886 if ( cff_builder_start_point( builder, x, y ) || | |
| 1887 cff_check_points( builder, 6 ) ) | |
| 1888 goto Fail; | |
| 1889 | |
| 1890 /* record the starting point's x, y position for later use */ | |
| 1891 start_x = x; | |
| 1892 start_y = y; | |
| 1893 | |
| 1894 /* XXX: figure out whether this is supposed to be a horizontal */ | |
| 1895 /* or vertical flex; the Type 2 specification is vague... */ | |
| 1896 | |
| 1897 temp = args; | |
| 1898 | |
| 1899 /* grab up to the last argument */ | |
| 1900 for ( count = 5; count > 0; count-- ) | |
| 1901 { | |
| 1902 dx += temp[0]; | |
| 1903 dy += temp[1]; | |
| 1904 temp += 2; | |
| 1905 } | |
| 1906 | |
| 1907 if ( dx < 0 ) | |
| 1908 dx = -dx; | |
| 1909 if ( dy < 0 ) | |
| 1910 dy = -dy; | |
| 1911 | |
| 1912 /* strange test, but here it is... */ | |
| 1913 horizontal = ( dx > dy ); | |
| 1914 | |
| 1915 for ( count = 5; count > 0; count-- ) | |
| 1916 { | |
| 1917 x += args[0]; | |
| 1918 y += args[1]; | |
| 1919 cff_builder_add_point( builder, x, y, | |
| 1920 (FT_Bool)( count == 3 ) ); | |
| 1921 args += 2; | |
| 1922 } | |
| 1923 | |
| 1924 /* is last operand an x- or y-delta? */ | |
| 1925 if ( horizontal ) | |
| 1926 { | |
| 1927 x += args[0]; | |
| 1928 y = start_y; | |
| 1929 } | |
| 1930 else | |
| 1931 { | |
| 1932 x = start_x; | |
| 1933 y += args[0]; | |
| 1934 } | |
| 1935 | |
| 1936 cff_builder_add_point( builder, x, y, 1 ); | |
| 1937 | |
| 1938 args = stack; | |
| 1939 break; | |
| 1940 } | |
| 1941 | |
| 1942 case cff_op_flex: | |
| 1943 { | |
| 1944 FT_UInt count; | |
| 1945 | |
| 1946 | |
| 1947 FT_TRACE4(( " flex\n" )); | |
| 1948 | |
| 1949 if ( cff_builder_start_point( builder, x, y ) || | |
| 1950 cff_check_points( builder, 6 ) ) | |
| 1951 goto Fail; | |
| 1952 | |
| 1953 for ( count = 6; count > 0; count-- ) | |
| 1954 { | |
| 1955 x += args[0]; | |
| 1956 y += args[1]; | |
| 1957 cff_builder_add_point( builder, x, y, | |
| 1958 (FT_Bool)( count == 4 || count == 1 ) ); | |
| 1959 args += 2; | |
| 1960 } | |
| 1961 | |
| 1962 args = stack; | |
| 1963 } | |
| 1964 break; | |
| 1965 | |
| 1966 case cff_op_seac: | |
| 1967 FT_TRACE4(( " seac\n" )); | |
| 1968 | |
| 1969 error = cff_operator_seac( decoder, | |
| 1970 args[0], args[1], args[2], | |
| 1971 (FT_Int)( args[3] >> 16 ), | |
| 1972 (FT_Int)( args[4] >> 16 ) ); | |
| 1973 | |
| 1974 /* add current outline to the glyph slot */ | |
| 1975 FT_GlyphLoader_Add( builder->loader ); | |
| 1976 | |
| 1977 /* return now! */ | |
| 1978 FT_TRACE4(( "\n" )); | |
| 1979 return error; | |
| 1980 | |
| 1981 case cff_op_endchar: | |
| 1982 FT_TRACE4(( " endchar\n" )); | |
| 1983 | |
| 1984 /* We are going to emulate the seac operator. */ | |
| 1985 if ( num_args >= 4 ) | |
| 1986 { | |
| 1987 /* Save glyph width so that the subglyphs don't overwrite it. */ | |
| 1988 FT_Pos glyph_width = decoder->glyph_width; | |
| 1989 | |
| 1990 | |
| 1991 error = cff_operator_seac( decoder, | |
| 1992 0L, args[-4], args[-3], | |
| 1993 (FT_Int)( args[-2] >> 16 ), | |
| 1994 (FT_Int)( args[-1] >> 16 ) ); | |
| 1995 | |
| 1996 decoder->glyph_width = glyph_width; | |
| 1997 } | |
| 1998 else | |
| 1999 { | |
| 2000 if ( !error ) | |
| 2001 error = FT_Err_Ok; | |
| 2002 | |
| 2003 cff_builder_close_contour( builder ); | |
| 2004 | |
| 2005 /* close hints recording session */ | |
| 2006 if ( hinter ) | |
| 2007 { | |
| 2008 if ( hinter->close( hinter->hints, | |
| 2009 builder->current->n_points ) ) | |
| 2010 goto Syntax_Error; | |
| 2011 | |
| 2012 /* apply hints to the loaded glyph outline now */ | |
| 2013 hinter->apply( hinter->hints, | |
| 2014 builder->current, | |
| 2015 (PSH_Globals)builder->hints_globals, | |
| 2016 decoder->hint_mode ); | |
| 2017 } | |
| 2018 | |
| 2019 /* add current outline to the glyph slot */ | |
| 2020 FT_GlyphLoader_Add( builder->loader ); | |
| 2021 } | |
| 2022 | |
| 2023 /* return now! */ | |
| 2024 FT_TRACE4(( "\n" )); | |
| 2025 return error; | |
| 2026 | |
| 2027 case cff_op_abs: | |
| 2028 FT_TRACE4(( " abs\n" )); | |
| 2029 | |
| 2030 if ( args[0] < 0 ) | |
| 2031 args[0] = -args[0]; | |
| 2032 args++; | |
| 2033 break; | |
| 2034 | |
| 2035 case cff_op_add: | |
| 2036 FT_TRACE4(( " add\n" )); | |
| 2037 | |
| 2038 args[0] += args[1]; | |
| 2039 args++; | |
| 2040 break; | |
| 2041 | |
| 2042 case cff_op_sub: | |
| 2043 FT_TRACE4(( " sub\n" )); | |
| 2044 | |
| 2045 args[0] -= args[1]; | |
| 2046 args++; | |
| 2047 break; | |
| 2048 | |
| 2049 case cff_op_div: | |
| 2050 FT_TRACE4(( " div\n" )); | |
| 2051 | |
| 2052 args[0] = FT_DivFix( args[0], args[1] ); | |
| 2053 args++; | |
| 2054 break; | |
| 2055 | |
| 2056 case cff_op_neg: | |
| 2057 FT_TRACE4(( " neg\n" )); | |
| 2058 | |
| 2059 args[0] = -args[0]; | |
| 2060 args++; | |
| 2061 break; | |
| 2062 | |
| 2063 case cff_op_random: | |
| 2064 { | |
| 2065 FT_Fixed Rand; | |
| 2066 | |
| 2067 | |
| 2068 FT_TRACE4(( " rand\n" )); | |
| 2069 | |
| 2070 Rand = seed; | |
| 2071 if ( Rand >= 0x8000L ) | |
| 2072 Rand++; | |
| 2073 | |
| 2074 args[0] = Rand; | |
| 2075 seed = FT_MulFix( seed, 0x10000L - seed ); | |
| 2076 if ( seed == 0 ) | |
| 2077 seed += 0x2873; | |
| 2078 args++; | |
| 2079 } | |
| 2080 break; | |
| 2081 | |
| 2082 case cff_op_mul: | |
| 2083 FT_TRACE4(( " mul\n" )); | |
| 2084 | |
| 2085 args[0] = FT_MulFix( args[0], args[1] ); | |
| 2086 args++; | |
| 2087 break; | |
| 2088 | |
| 2089 case cff_op_sqrt: | |
| 2090 FT_TRACE4(( " sqrt\n" )); | |
| 2091 | |
| 2092 if ( args[0] > 0 ) | |
| 2093 { | |
| 2094 FT_Int count = 9; | |
| 2095 FT_Fixed root = args[0]; | |
| 2096 FT_Fixed new_root; | |
| 2097 | |
| 2098 | |
| 2099 for (;;) | |
| 2100 { | |
| 2101 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; | |
| 2102 if ( new_root == root || count <= 0 ) | |
| 2103 break; | |
| 2104 root = new_root; | |
| 2105 } | |
| 2106 args[0] = new_root; | |
| 2107 } | |
| 2108 else | |
| 2109 args[0] = 0; | |
| 2110 args++; | |
| 2111 break; | |
| 2112 | |
| 2113 case cff_op_drop: | |
| 2114 /* nothing */ | |
| 2115 FT_TRACE4(( " drop\n" )); | |
| 2116 | |
| 2117 break; | |
| 2118 | |
| 2119 case cff_op_exch: | |
| 2120 { | |
| 2121 FT_Fixed tmp; | |
| 2122 | |
| 2123 | |
| 2124 FT_TRACE4(( " exch\n" )); | |
| 2125 | |
| 2126 tmp = args[0]; | |
| 2127 args[0] = args[1]; | |
| 2128 args[1] = tmp; | |
| 2129 args += 2; | |
| 2130 } | |
| 2131 break; | |
| 2132 | |
| 2133 case cff_op_index: | |
| 2134 { | |
| 2135 FT_Int idx = (FT_Int)( args[0] >> 16 ); | |
| 2136 | |
| 2137 | |
| 2138 FT_TRACE4(( " index\n" )); | |
| 2139 | |
| 2140 if ( idx < 0 ) | |
| 2141 idx = 0; | |
| 2142 else if ( idx > num_args - 2 ) | |
| 2143 idx = num_args - 2; | |
| 2144 args[0] = args[-( idx + 1 )]; | |
| 2145 args++; | |
| 2146 } | |
| 2147 break; | |
| 2148 | |
| 2149 case cff_op_roll: | |
| 2150 { | |
| 2151 FT_Int count = (FT_Int)( args[0] >> 16 ); | |
| 2152 FT_Int idx = (FT_Int)( args[1] >> 16 ); | |
| 2153 | |
| 2154 | |
| 2155 FT_TRACE4(( " roll\n" )); | |
| 2156 | |
| 2157 if ( count <= 0 ) | |
| 2158 count = 1; | |
| 2159 | |
| 2160 args -= count; | |
| 2161 if ( args < stack ) | |
| 2162 goto Stack_Underflow; | |
| 2163 | |
| 2164 if ( idx >= 0 ) | |
| 2165 { | |
| 2166 while ( idx > 0 ) | |
| 2167 { | |
| 2168 FT_Fixed tmp = args[count - 1]; | |
| 2169 FT_Int i; | |
| 2170 | |
| 2171 | |
| 2172 for ( i = count - 2; i >= 0; i-- ) | |
| 2173 args[i + 1] = args[i]; | |
| 2174 args[0] = tmp; | |
| 2175 idx--; | |
| 2176 } | |
| 2177 } | |
| 2178 else | |
| 2179 { | |
| 2180 while ( idx < 0 ) | |
| 2181 { | |
| 2182 FT_Fixed tmp = args[0]; | |
| 2183 FT_Int i; | |
| 2184 | |
| 2185 | |
| 2186 for ( i = 0; i < count - 1; i++ ) | |
| 2187 args[i] = args[i + 1]; | |
| 2188 args[count - 1] = tmp; | |
| 2189 idx++; | |
| 2190 } | |
| 2191 } | |
| 2192 args += count; | |
| 2193 } | |
| 2194 break; | |
| 2195 | |
| 2196 case cff_op_dup: | |
| 2197 FT_TRACE4(( " dup\n" )); | |
| 2198 | |
| 2199 args[1] = args[0]; | |
| 2200 args += 2; | |
| 2201 break; | |
| 2202 | |
| 2203 case cff_op_put: | |
| 2204 { | |
| 2205 FT_Fixed val = args[0]; | |
| 2206 FT_Int idx = (FT_Int)( args[1] >> 16 ); | |
| 2207 | |
| 2208 | |
| 2209 FT_TRACE4(( " put\n" )); | |
| 2210 | |
| 2211 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) | |
| 2212 decoder->buildchar[idx] = val; | |
| 2213 } | |
| 2214 break; | |
| 2215 | |
| 2216 case cff_op_get: | |
| 2217 { | |
| 2218 FT_Int idx = (FT_Int)( args[0] >> 16 ); | |
| 2219 FT_Fixed val = 0; | |
| 2220 | |
| 2221 | |
| 2222 FT_TRACE4(( " get\n" )); | |
| 2223 | |
| 2224 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS ) | |
| 2225 val = decoder->buildchar[idx]; | |
| 2226 | |
| 2227 args[0] = val; | |
| 2228 args++; | |
| 2229 } | |
| 2230 break; | |
| 2231 | |
| 2232 case cff_op_store: | |
| 2233 FT_TRACE4(( " store\n")); | |
| 2234 | |
| 2235 goto Unimplemented; | |
| 2236 | |
| 2237 case cff_op_load: | |
| 2238 FT_TRACE4(( " load\n" )); | |
| 2239 | |
| 2240 goto Unimplemented; | |
| 2241 | |
| 2242 case cff_op_dotsection: | |
| 2243 /* this operator is deprecated and ignored by the parser */ | |
| 2244 FT_TRACE4(( " dotsection\n" )); | |
| 2245 break; | |
| 2246 | |
| 2247 case cff_op_closepath: | |
| 2248 /* this is an invalid Type 2 operator; however, there */ | |
| 2249 /* exist fonts which are incorrectly converted from probably */ | |
| 2250 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2251 | |
| 2252 FT_TRACE4(( " closepath (invalid op)\n" )); | |
| 2253 | |
| 2254 args = stack; | |
| 2255 break; | |
| 2256 | |
| 2257 case cff_op_hsbw: | |
| 2258 /* this is an invalid Type 2 operator; however, there */ | |
| 2259 /* exist fonts which are incorrectly converted from probably */ | |
| 2260 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2261 | |
| 2262 FT_TRACE4(( " hsbw (invalid op)\n" )); | |
| 2263 | |
| 2264 decoder->glyph_width = decoder->nominal_width + ( args[1] >> 16 ); | |
| 2265 | |
| 2266 decoder->builder.left_bearing.x = args[0]; | |
| 2267 decoder->builder.left_bearing.y = 0; | |
| 2268 | |
| 2269 x = decoder->builder.pos_x + args[0]; | |
| 2270 y = decoder->builder.pos_y; | |
| 2271 args = stack; | |
| 2272 break; | |
| 2273 | |
| 2274 case cff_op_sbw: | |
| 2275 /* this is an invalid Type 2 operator; however, there */ | |
| 2276 /* exist fonts which are incorrectly converted from probably */ | |
| 2277 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2278 | |
| 2279 FT_TRACE4(( " sbw (invalid op)\n" )); | |
| 2280 | |
| 2281 decoder->glyph_width = decoder->nominal_width + ( args[2] >> 16 ); | |
| 2282 | |
| 2283 decoder->builder.left_bearing.x = args[0]; | |
| 2284 decoder->builder.left_bearing.y = args[1]; | |
| 2285 | |
| 2286 x = decoder->builder.pos_x + args[0]; | |
| 2287 y = decoder->builder.pos_y + args[1]; | |
| 2288 args = stack; | |
| 2289 break; | |
| 2290 | |
| 2291 case cff_op_setcurrentpoint: | |
| 2292 /* this is an invalid Type 2 operator; however, there */ | |
| 2293 /* exist fonts which are incorrectly converted from probably */ | |
| 2294 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2295 | |
| 2296 FT_TRACE4(( " setcurrentpoint (invalid op)\n" )); | |
| 2297 | |
| 2298 x = decoder->builder.pos_x + args[0]; | |
| 2299 y = decoder->builder.pos_y + args[1]; | |
| 2300 args = stack; | |
| 2301 break; | |
| 2302 | |
| 2303 case cff_op_callothersubr: | |
| 2304 /* this is an invalid Type 2 operator; however, there */ | |
| 2305 /* exist fonts which are incorrectly converted from probably */ | |
| 2306 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2307 | |
| 2308 FT_TRACE4(( " callothersubr (invalid op)\n" )); | |
| 2309 | |
| 2310 /* subsequent `pop' operands should add the arguments, */ | |
| 2311 /* this is the implementation described for `unknown' other */ | |
| 2312 /* subroutines in the Type1 spec. */ | |
| 2313 /* */ | |
| 2314 /* XXX Fix return arguments (see discussion below). */ | |
| 2315 args -= 2 + ( args[-2] >> 16 ); | |
| 2316 if ( args < stack ) | |
| 2317 goto Stack_Underflow; | |
| 2318 break; | |
| 2319 | |
| 2320 case cff_op_pop: | |
| 2321 /* this is an invalid Type 2 operator; however, there */ | |
| 2322 /* exist fonts which are incorrectly converted from probably */ | |
| 2323 /* Type 1 to CFF, and some parsers seem to accept it */ | |
| 2324 | |
| 2325 FT_TRACE4(( " pop (invalid op)\n" )); | |
| 2326 | |
| 2327 /* XXX Increasing `args' is wrong: After a certain number of */ | |
| 2328 /* `pop's we get a stack overflow. Reason for doing it is */ | |
| 2329 /* code like this (actually found in a CFF font): */ | |
| 2330 /* */ | |
| 2331 /* 17 1 3 callothersubr */ | |
| 2332 /* pop */ | |
| 2333 /* callsubr */ | |
| 2334 /* */ | |
| 2335 /* Since we handle `callothersubr' as a no-op, and */ | |
| 2336 /* `callsubr' needs at least one argument, `pop' can't be a */ | |
| 2337 /* no-op too as it basically should be. */ | |
| 2338 /* */ | |
| 2339 /* The right solution would be to provide real support for */ | |
| 2340 /* `callothersubr' as done in `t1decode.c', however, given */ | |
| 2341 /* the fact that CFF fonts with `pop' are invalid, it is */ | |
| 2342 /* questionable whether it is worth the time. */ | |
| 2343 args++; | |
| 2344 break; | |
| 2345 | |
| 2346 case cff_op_and: | |
| 2347 { | |
| 2348 FT_Fixed cond = args[0] && args[1]; | |
| 2349 | |
| 2350 | |
| 2351 FT_TRACE4(( " and\n" )); | |
| 2352 | |
| 2353 args[0] = cond ? 0x10000L : 0; | |
| 2354 args++; | |
| 2355 } | |
| 2356 break; | |
| 2357 | |
| 2358 case cff_op_or: | |
| 2359 { | |
| 2360 FT_Fixed cond = args[0] || args[1]; | |
| 2361 | |
| 2362 | |
| 2363 FT_TRACE4(( " or\n" )); | |
| 2364 | |
| 2365 args[0] = cond ? 0x10000L : 0; | |
| 2366 args++; | |
| 2367 } | |
| 2368 break; | |
| 2369 | |
| 2370 case cff_op_eq: | |
| 2371 { | |
| 2372 FT_Fixed cond = !args[0]; | |
| 2373 | |
| 2374 | |
| 2375 FT_TRACE4(( " eq\n" )); | |
| 2376 | |
| 2377 args[0] = cond ? 0x10000L : 0; | |
| 2378 args++; | |
| 2379 } | |
| 2380 break; | |
| 2381 | |
| 2382 case cff_op_ifelse: | |
| 2383 { | |
| 2384 FT_Fixed cond = ( args[2] <= args[3] ); | |
| 2385 | |
| 2386 | |
| 2387 FT_TRACE4(( " ifelse\n" )); | |
| 2388 | |
| 2389 if ( !cond ) | |
| 2390 args[0] = args[1]; | |
| 2391 args++; | |
| 2392 } | |
| 2393 break; | |
| 2394 | |
| 2395 case cff_op_callsubr: | |
| 2396 { | |
| 2397 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + | |
| 2398 decoder->locals_bias ); | |
| 2399 | |
| 2400 | |
| 2401 FT_TRACE4(( " callsubr(%d)\n", idx )); | |
| 2402 | |
| 2403 if ( idx >= decoder->num_locals ) | |
| 2404 { | |
| 2405 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2406 " invalid local subr index\n" )); | |
| 2407 goto Syntax_Error; | |
| 2408 } | |
| 2409 | |
| 2410 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) | |
| 2411 { | |
| 2412 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2413 " too many nested subrs\n" )); | |
| 2414 goto Syntax_Error; | |
| 2415 } | |
| 2416 | |
| 2417 zone->cursor = ip; /* save current instruction pointer */ | |
| 2418 | |
| 2419 zone++; | |
| 2420 zone->base = decoder->locals[idx]; | |
| 2421 zone->limit = decoder->locals[idx + 1]; | |
| 2422 zone->cursor = zone->base; | |
| 2423 | |
| 2424 if ( !zone->base || zone->limit == zone->base ) | |
| 2425 { | |
| 2426 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2427 " invoking empty subrs\n" )); | |
| 2428 goto Syntax_Error; | |
| 2429 } | |
| 2430 | |
| 2431 decoder->zone = zone; | |
| 2432 ip = zone->base; | |
| 2433 limit = zone->limit; | |
| 2434 } | |
| 2435 break; | |
| 2436 | |
| 2437 case cff_op_callgsubr: | |
| 2438 { | |
| 2439 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + | |
| 2440 decoder->globals_bias ); | |
| 2441 | |
| 2442 | |
| 2443 FT_TRACE4(( " callgsubr(%d)\n", idx )); | |
| 2444 | |
| 2445 if ( idx >= decoder->num_globals ) | |
| 2446 { | |
| 2447 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2448 " invalid global subr index\n" )); | |
| 2449 goto Syntax_Error; | |
| 2450 } | |
| 2451 | |
| 2452 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) | |
| 2453 { | |
| 2454 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2455 " too many nested subrs\n" )); | |
| 2456 goto Syntax_Error; | |
| 2457 } | |
| 2458 | |
| 2459 zone->cursor = ip; /* save current instruction pointer */ | |
| 2460 | |
| 2461 zone++; | |
| 2462 zone->base = decoder->globals[idx]; | |
| 2463 zone->limit = decoder->globals[idx + 1]; | |
| 2464 zone->cursor = zone->base; | |
| 2465 | |
| 2466 if ( !zone->base || zone->limit == zone->base ) | |
| 2467 { | |
| 2468 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2469 " invoking empty subrs\n" )); | |
| 2470 goto Syntax_Error; | |
| 2471 } | |
| 2472 | |
| 2473 decoder->zone = zone; | |
| 2474 ip = zone->base; | |
| 2475 limit = zone->limit; | |
| 2476 } | |
| 2477 break; | |
| 2478 | |
| 2479 case cff_op_return: | |
| 2480 FT_TRACE4(( " return\n" )); | |
| 2481 | |
| 2482 if ( decoder->zone <= decoder->zones ) | |
| 2483 { | |
| 2484 FT_ERROR(( "cff_decoder_parse_charstrings:" | |
| 2485 " unexpected return\n" )); | |
| 2486 goto Syntax_Error; | |
| 2487 } | |
| 2488 | |
| 2489 decoder->zone--; | |
| 2490 zone = decoder->zone; | |
| 2491 ip = zone->cursor; | |
| 2492 limit = zone->limit; | |
| 2493 break; | |
| 2494 | |
| 2495 default: | |
| 2496 Unimplemented: | |
| 2497 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); | |
| 2498 | |
| 2499 if ( ip[-1] == 12 ) | |
| 2500 FT_ERROR(( " %d", ip[0] )); | |
| 2501 FT_ERROR(( "\n" )); | |
| 2502 | |
| 2503 return FT_THROW( Unimplemented_Feature ); | |
| 2504 } | |
| 2505 | |
| 2506 decoder->top = args; | |
| 2507 | |
| 2508 if ( decoder->top - stack >= CFF_MAX_OPERANDS ) | |
| 2509 goto Stack_Overflow; | |
| 2510 | |
| 2511 } /* general operator processing */ | |
| 2512 | |
| 2513 } /* while ip < limit */ | |
| 2514 | |
| 2515 FT_TRACE4(( "..end..\n\n" )); | |
| 2516 | |
| 2517 Fail: | |
| 2518 return error; | |
| 2519 | |
| 2520 Syntax_Error: | |
| 2521 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" )); | |
| 2522 return FT_THROW( Invalid_File_Format ); | |
| 2523 | |
| 2524 Stack_Underflow: | |
| 2525 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" )); | |
| 2526 return FT_THROW( Too_Few_Arguments ); | |
| 2527 | |
| 2528 Stack_Overflow: | |
| 2529 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" )); | |
| 2530 return FT_THROW( Stack_Overflow ); | |
| 2531 } | |
| 2532 | |
| 2533 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */ | |
| 2534 | |
| 2535 | |
| 2536 /*************************************************************************/ | |
| 2537 /*************************************************************************/ | |
| 2538 /*************************************************************************/ | |
| 2539 /********** *********/ | |
| 2540 /********** *********/ | |
| 2541 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ | |
| 2542 /********** *********/ | |
| 2543 /********** The following code is in charge of computing *********/ | |
| 2544 /********** the maximum advance width of the font. It *********/ | |
| 2545 /********** quickly processes each glyph charstring to *********/ | |
| 2546 /********** extract the value from either a `sbw' or `seac' *********/ | |
| 2547 /********** operator. *********/ | |
| 2548 /********** *********/ | |
| 2549 /*************************************************************************/ | |
| 2550 /*************************************************************************/ | |
| 2551 /*************************************************************************/ | |
| 2552 | |
| 2553 | |
| 2554 #if 0 /* unused until we support pure CFF fonts */ | |
| 2555 | |
| 2556 | |
| 2557 FT_LOCAL_DEF( FT_Error ) | |
| 2558 cff_compute_max_advance( TT_Face face, | |
| 2559 FT_Int* max_advance ) | |
| 2560 { | |
| 2561 FT_Error error = FT_Err_Ok; | |
| 2562 CFF_Decoder decoder; | |
| 2563 FT_Int glyph_index; | |
| 2564 CFF_Font cff = (CFF_Font)face->other; | |
| 2565 | |
| 2566 | |
| 2567 *max_advance = 0; | |
| 2568 | |
| 2569 /* Initialize load decoder */ | |
| 2570 cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); | |
| 2571 | |
| 2572 decoder.builder.metrics_only = 1; | |
| 2573 decoder.builder.load_points = 0; | |
| 2574 | |
| 2575 /* For each glyph, parse the glyph charstring and extract */ | |
| 2576 /* the advance width. */ | |
| 2577 for ( glyph_index = 0; glyph_index < face->root.num_glyphs; | |
| 2578 glyph_index++ ) | |
| 2579 { | |
| 2580 FT_Byte* charstring; | |
| 2581 FT_ULong charstring_len; | |
| 2582 | |
| 2583 | |
| 2584 /* now get load the unscaled outline */ | |
| 2585 error = cff_get_glyph_data( face, glyph_index, | |
| 2586 &charstring, &charstring_len ); | |
| 2587 if ( !error ) | |
| 2588 { | |
| 2589 error = cff_decoder_prepare( &decoder, size, glyph_index ); | |
| 2590 if ( !error ) | |
| 2591 error = cff_decoder_parse_charstrings( &decoder, | |
| 2592 charstring, | |
| 2593 charstring_len ); | |
| 2594 | |
| 2595 cff_free_glyph_data( face, &charstring, &charstring_len ); | |
| 2596 } | |
| 2597 | |
| 2598 /* ignore the error if one has occurred -- skip to next glyph */ | |
| 2599 error = FT_Err_Ok; | |
| 2600 } | |
| 2601 | |
| 2602 *max_advance = decoder.builder.advance.x; | |
| 2603 | |
| 2604 return FT_Err_Ok; | |
| 2605 } | |
| 2606 | |
| 2607 | |
| 2608 #endif /* 0 */ | |
| 2609 | |
| 2610 | |
| 2611 FT_LOCAL_DEF( FT_Error ) | |
| 2612 cff_slot_load( CFF_GlyphSlot glyph, | |
| 2613 CFF_Size size, | |
| 2614 FT_UInt glyph_index, | |
| 2615 FT_Int32 load_flags ) | |
| 2616 { | |
| 2617 FT_Error error; | |
| 2618 CFF_Decoder decoder; | |
| 2619 TT_Face face = (TT_Face)glyph->root.face; | |
| 2620 FT_Bool hinting, scaled, force_scaling; | |
| 2621 CFF_Font cff = (CFF_Font)face->extra.data; | |
| 2622 | |
| 2623 FT_Matrix font_matrix; | |
| 2624 FT_Vector font_offset; | |
| 2625 | |
| 2626 | |
| 2627 force_scaling = FALSE; | |
| 2628 | |
| 2629 /* in a CID-keyed font, consider `glyph_index' as a CID and map */ | |
| 2630 /* it immediately to the real glyph_index -- if it isn't a */ | |
| 2631 /* subsetted font, glyph_indices and CIDs are identical, though */ | |
| 2632 if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && | |
| 2633 cff->charset.cids ) | |
| 2634 { | |
| 2635 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */ | |
| 2636 if ( glyph_index != 0 ) | |
| 2637 { | |
| 2638 glyph_index = cff_charset_cid_to_gindex( &cff->charset, | |
| 2639 glyph_index ); | |
| 2640 if ( glyph_index == 0 ) | |
| 2641 return FT_THROW( Invalid_Argument ); | |
| 2642 } | |
| 2643 } | |
| 2644 else if ( glyph_index >= cff->num_glyphs ) | |
| 2645 return FT_THROW( Invalid_Argument ); | |
| 2646 | |
| 2647 if ( load_flags & FT_LOAD_NO_RECURSE ) | |
| 2648 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; | |
| 2649 | |
| 2650 glyph->x_scale = 0x10000L; | |
| 2651 glyph->y_scale = 0x10000L; | |
| 2652 if ( size ) | |
| 2653 { | |
| 2654 glyph->x_scale = size->root.metrics.x_scale; | |
| 2655 glyph->y_scale = size->root.metrics.y_scale; | |
| 2656 } | |
| 2657 | |
| 2658 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS | |
| 2659 | |
| 2660 /* try to load embedded bitmap if any */ | |
| 2661 /* */ | |
| 2662 /* XXX: The convention should be emphasized in */ | |
| 2663 /* the documents because it can be confusing. */ | |
| 2664 if ( size ) | |
| 2665 { | |
| 2666 CFF_Face cff_face = (CFF_Face)size->root.face; | |
| 2667 SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; | |
| 2668 FT_Stream stream = cff_face->root.stream; | |
| 2669 | |
| 2670 | |
| 2671 if ( size->strike_index != 0xFFFFFFFFUL && | |
| 2672 sfnt->load_eblc && | |
| 2673 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) | |
| 2674 { | |
| 2675 TT_SBit_MetricsRec metrics; | |
| 2676 | |
| 2677 | |
| 2678 error = sfnt->load_sbit_image( face, | |
| 2679 size->strike_index, | |
| 2680 glyph_index, | |
| 2681 (FT_Int)load_flags, | |
| 2682 stream, | |
| 2683 &glyph->root.bitmap, | |
| 2684 &metrics ); | |
| 2685 | |
| 2686 if ( !error ) | |
| 2687 { | |
| 2688 FT_Bool has_vertical_info; | |
| 2689 FT_UShort advance; | |
| 2690 FT_Short dummy; | |
| 2691 | |
| 2692 | |
| 2693 glyph->root.outline.n_points = 0; | |
| 2694 glyph->root.outline.n_contours = 0; | |
| 2695 | |
| 2696 glyph->root.metrics.width = (FT_Pos)metrics.width << 6; | |
| 2697 glyph->root.metrics.height = (FT_Pos)metrics.height << 6; | |
| 2698 | |
| 2699 glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; | |
| 2700 glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; | |
| 2701 glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; | |
| 2702 | |
| 2703 glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; | |
| 2704 glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; | |
| 2705 glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; | |
| 2706 | |
| 2707 glyph->root.format = FT_GLYPH_FORMAT_BITMAP; | |
| 2708 | |
| 2709 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) | |
| 2710 { | |
| 2711 glyph->root.bitmap_left = metrics.vertBearingX; | |
| 2712 glyph->root.bitmap_top = metrics.vertBearingY; | |
| 2713 } | |
| 2714 else | |
| 2715 { | |
| 2716 glyph->root.bitmap_left = metrics.horiBearingX; | |
| 2717 glyph->root.bitmap_top = metrics.horiBearingY; | |
| 2718 } | |
| 2719 | |
| 2720 /* compute linear advance widths */ | |
| 2721 | |
| 2722 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, | |
| 2723 glyph_index, | |
| 2724 &dummy, | |
| 2725 &advance ); | |
| 2726 glyph->root.linearHoriAdvance = advance; | |
| 2727 | |
| 2728 has_vertical_info = FT_BOOL( | |
| 2729 face->vertical_info && | |
| 2730 face->vertical.number_Of_VMetrics > 0 ); | |
| 2731 | |
| 2732 /* get the vertical metrics from the vtmx table if we have one */ | |
| 2733 if ( has_vertical_info ) | |
| 2734 { | |
| 2735 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, | |
| 2736 glyph_index, | |
| 2737 &dummy, | |
| 2738 &advance ); | |
| 2739 glyph->root.linearVertAdvance = advance; | |
| 2740 } | |
| 2741 else | |
| 2742 { | |
| 2743 /* make up vertical ones */ | |
| 2744 if ( face->os2.version != 0xFFFFU ) | |
| 2745 glyph->root.linearVertAdvance = (FT_Pos) | |
| 2746 ( face->os2.sTypoAscender - face->os2.sTypoDescender ); | |
| 2747 else | |
| 2748 glyph->root.linearVertAdvance = (FT_Pos) | |
| 2749 ( face->horizontal.Ascender - face->horizontal.Descender ); | |
| 2750 } | |
| 2751 | |
| 2752 return error; | |
| 2753 } | |
| 2754 } | |
| 2755 } | |
| 2756 | |
| 2757 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ | |
| 2758 | |
| 2759 /* return immediately if we only want the embedded bitmaps */ | |
| 2760 if ( load_flags & FT_LOAD_SBITS_ONLY ) | |
| 2761 return FT_THROW( Invalid_Argument ); | |
| 2762 | |
| 2763 /* if we have a CID subfont, use its matrix (which has already */ | |
| 2764 /* been multiplied with the root matrix) */ | |
| 2765 | |
| 2766 /* this scaling is only relevant if the PS hinter isn't active */ | |
| 2767 if ( cff->num_subfonts ) | |
| 2768 { | |
| 2769 FT_ULong top_upm, sub_upm; | |
| 2770 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, | |
| 2771 glyph_index ); | |
| 2772 | |
| 2773 | |
| 2774 if ( fd_index >= cff->num_subfonts ) | |
| 2775 fd_index = (FT_Byte)( cff->num_subfonts - 1 ); | |
| 2776 | |
| 2777 top_upm = cff->top_font.font_dict.units_per_em; | |
| 2778 sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; | |
| 2779 | |
| 2780 | |
| 2781 font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; | |
| 2782 font_offset = cff->subfonts[fd_index]->font_dict.font_offset; | |
| 2783 | |
| 2784 if ( top_upm != sub_upm ) | |
| 2785 { | |
| 2786 glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); | |
| 2787 glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); | |
| 2788 | |
| 2789 force_scaling = TRUE; | |
| 2790 } | |
| 2791 } | |
| 2792 else | |
| 2793 { | |
| 2794 font_matrix = cff->top_font.font_dict.font_matrix; | |
| 2795 font_offset = cff->top_font.font_dict.font_offset; | |
| 2796 } | |
| 2797 | |
| 2798 glyph->root.outline.n_points = 0; | |
| 2799 glyph->root.outline.n_contours = 0; | |
| 2800 | |
| 2801 /* top-level code ensures that FT_LOAD_NO_HINTING is set */ | |
| 2802 /* if FT_LOAD_NO_SCALE is active */ | |
| 2803 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); | |
| 2804 scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ); | |
| 2805 | |
| 2806 glyph->hint = hinting; | |
| 2807 glyph->scaled = scaled; | |
| 2808 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ | |
| 2809 | |
| 2810 { | |
| 2811 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE | |
| 2812 CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face ); | |
| 2813 #endif | |
| 2814 | |
| 2815 | |
| 2816 FT_Byte* charstring; | |
| 2817 FT_ULong charstring_len; | |
| 2818 | |
| 2819 | |
| 2820 cff_decoder_init( &decoder, face, size, glyph, hinting, | |
| 2821 FT_LOAD_TARGET_MODE( load_flags ) ); | |
| 2822 | |
| 2823 if ( load_flags & FT_LOAD_ADVANCE_ONLY ) | |
| 2824 decoder.width_only = TRUE; | |
| 2825 | |
| 2826 decoder.builder.no_recurse = | |
| 2827 (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE ); | |
| 2828 | |
| 2829 /* now load the unscaled outline */ | |
| 2830 error = cff_get_glyph_data( face, glyph_index, | |
| 2831 &charstring, &charstring_len ); | |
| 2832 if ( error ) | |
| 2833 goto Glyph_Build_Finished; | |
| 2834 | |
| 2835 error = cff_decoder_prepare( &decoder, size, glyph_index ); | |
| 2836 if ( error ) | |
| 2837 goto Glyph_Build_Finished; | |
| 2838 | |
| 2839 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE | |
| 2840 /* choose which CFF renderer to use */ | |
| 2841 if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE ) | |
| 2842 error = cff_decoder_parse_charstrings( &decoder, | |
| 2843 charstring, | |
| 2844 charstring_len ); | |
| 2845 else | |
| 2846 #endif | |
| 2847 { | |
| 2848 error = cf2_decoder_parse_charstrings( &decoder, | |
| 2849 charstring, | |
| 2850 charstring_len ); | |
| 2851 | |
| 2852 /* Adobe's engine uses 16.16 numbers everywhere; */ | |
| 2853 /* as a consequence, glyphs larger than 2000ppem get rejected */ | |
| 2854 if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) | |
| 2855 { | |
| 2856 /* this time, we retry unhinted and scale up the glyph later on */ | |
| 2857 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ | |
| 2858 /* 0x400 for both `x_scale' and `y_scale' in this case) */ | |
| 2859 hinting = FALSE; | |
| 2860 force_scaling = TRUE; | |
| 2861 glyph->hint = hinting; | |
| 2862 | |
| 2863 error = cf2_decoder_parse_charstrings( &decoder, | |
| 2864 charstring, | |
| 2865 charstring_len ); | |
| 2866 } | |
| 2867 } | |
| 2868 | |
| 2869 cff_free_glyph_data( face, &charstring, charstring_len ); | |
| 2870 | |
| 2871 if ( error ) | |
| 2872 goto Glyph_Build_Finished; | |
| 2873 | |
| 2874 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 2875 /* Control data and length may not be available for incremental */ | |
| 2876 /* fonts. */ | |
| 2877 if ( face->root.internal->incremental_interface ) | |
| 2878 { | |
| 2879 glyph->root.control_data = 0; | |
| 2880 glyph->root.control_len = 0; | |
| 2881 } | |
| 2882 else | |
| 2883 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 2884 | |
| 2885 /* We set control_data and control_len if charstrings is loaded. */ | |
| 2886 /* See how charstring loads at cff_index_access_element() in */ | |
| 2887 /* cffload.c. */ | |
| 2888 { | |
| 2889 CFF_Index csindex = &cff->charstrings_index; | |
| 2890 | |
| 2891 | |
| 2892 if ( csindex->offsets ) | |
| 2893 { | |
| 2894 glyph->root.control_data = csindex->bytes + | |
| 2895 csindex->offsets[glyph_index] - 1; | |
| 2896 glyph->root.control_len = charstring_len; | |
| 2897 } | |
| 2898 } | |
| 2899 | |
| 2900 Glyph_Build_Finished: | |
| 2901 /* save new glyph tables, if no error */ | |
| 2902 if ( !error ) | |
| 2903 cff_builder_done( &decoder.builder ); | |
| 2904 /* XXX: anything to do for broken glyph entry? */ | |
| 2905 } | |
| 2906 | |
| 2907 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 2908 | |
| 2909 /* Incremental fonts can optionally override the metrics. */ | |
| 2910 if ( !error && | |
| 2911 face->root.internal->incremental_interface && | |
| 2912 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) | |
| 2913 { | |
| 2914 FT_Incremental_MetricsRec metrics; | |
| 2915 | |
| 2916 | |
| 2917 metrics.bearing_x = decoder.builder.left_bearing.x; | |
| 2918 metrics.bearing_y = 0; | |
| 2919 metrics.advance = decoder.builder.advance.x; | |
| 2920 metrics.advance_v = decoder.builder.advance.y; | |
| 2921 | |
| 2922 error = face->root.internal->incremental_interface->funcs->get_glyph_metri
cs( | |
| 2923 face->root.internal->incremental_interface->object, | |
| 2924 glyph_index, FALSE, &metrics ); | |
| 2925 | |
| 2926 decoder.builder.left_bearing.x = metrics.bearing_x; | |
| 2927 decoder.builder.advance.x = metrics.advance; | |
| 2928 decoder.builder.advance.y = metrics.advance_v; | |
| 2929 } | |
| 2930 | |
| 2931 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ | |
| 2932 | |
| 2933 if ( !error ) | |
| 2934 { | |
| 2935 /* Now, set the metrics -- this is rather simple, as */ | |
| 2936 /* the left side bearing is the xMin, and the top side */ | |
| 2937 /* bearing the yMax. */ | |
| 2938 | |
| 2939 /* For composite glyphs, return only left side bearing and */ | |
| 2940 /* advance width. */ | |
| 2941 if ( load_flags & FT_LOAD_NO_RECURSE ) | |
| 2942 { | |
| 2943 FT_Slot_Internal internal = glyph->root.internal; | |
| 2944 | |
| 2945 | |
| 2946 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; | |
| 2947 glyph->root.metrics.horiAdvance = decoder.glyph_width; | |
| 2948 internal->glyph_matrix = font_matrix; | |
| 2949 internal->glyph_delta = font_offset; | |
| 2950 internal->glyph_transformed = 1; | |
| 2951 } | |
| 2952 else | |
| 2953 { | |
| 2954 FT_BBox cbox; | |
| 2955 FT_Glyph_Metrics* metrics = &glyph->root.metrics; | |
| 2956 FT_Vector advance; | |
| 2957 FT_Bool has_vertical_info; | |
| 2958 | |
| 2959 | |
| 2960 /* copy the _unscaled_ advance width */ | |
| 2961 metrics->horiAdvance = decoder.glyph_width; | |
| 2962 glyph->root.linearHoriAdvance = decoder.glyph_width; | |
| 2963 glyph->root.internal->glyph_transformed = 0; | |
| 2964 | |
| 2965 has_vertical_info = FT_BOOL( face->vertical_info && | |
| 2966 face->vertical.number_Of_VMetrics > 0 ); | |
| 2967 | |
| 2968 /* get the vertical metrics from the vtmx table if we have one */ | |
| 2969 if ( has_vertical_info ) | |
| 2970 { | |
| 2971 FT_Short vertBearingY = 0; | |
| 2972 FT_UShort vertAdvance = 0; | |
| 2973 | |
| 2974 | |
| 2975 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, | |
| 2976 glyph_index, | |
| 2977 &vertBearingY, | |
| 2978 &vertAdvance ); | |
| 2979 metrics->vertBearingY = vertBearingY; | |
| 2980 metrics->vertAdvance = vertAdvance; | |
| 2981 } | |
| 2982 else | |
| 2983 { | |
| 2984 /* make up vertical ones */ | |
| 2985 if ( face->os2.version != 0xFFFFU ) | |
| 2986 metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - | |
| 2987 face->os2.sTypoDescender ); | |
| 2988 else | |
| 2989 metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - | |
| 2990 face->horizontal.Descender ); | |
| 2991 } | |
| 2992 | |
| 2993 glyph->root.linearVertAdvance = metrics->vertAdvance; | |
| 2994 | |
| 2995 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; | |
| 2996 | |
| 2997 glyph->root.outline.flags = 0; | |
| 2998 if ( size && size->root.metrics.y_ppem < 24 ) | |
| 2999 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; | |
| 3000 | |
| 3001 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; | |
| 3002 | |
| 3003 if ( !( font_matrix.xx == 0x10000L && | |
| 3004 font_matrix.yy == 0x10000L && | |
| 3005 font_matrix.xy == 0 && | |
| 3006 font_matrix.yx == 0 ) ) | |
| 3007 FT_Outline_Transform( &glyph->root.outline, &font_matrix ); | |
| 3008 | |
| 3009 if ( !( font_offset.x == 0 && | |
| 3010 font_offset.y == 0 ) ) | |
| 3011 FT_Outline_Translate( &glyph->root.outline, | |
| 3012 font_offset.x, font_offset.y ); | |
| 3013 | |
| 3014 advance.x = metrics->horiAdvance; | |
| 3015 advance.y = 0; | |
| 3016 FT_Vector_Transform( &advance, &font_matrix ); | |
| 3017 metrics->horiAdvance = advance.x + font_offset.x; | |
| 3018 | |
| 3019 advance.x = 0; | |
| 3020 advance.y = metrics->vertAdvance; | |
| 3021 FT_Vector_Transform( &advance, &font_matrix ); | |
| 3022 metrics->vertAdvance = advance.y + font_offset.y; | |
| 3023 | |
| 3024 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) | |
| 3025 { | |
| 3026 /* scale the outline and the metrics */ | |
| 3027 FT_Int n; | |
| 3028 FT_Outline* cur = &glyph->root.outline; | |
| 3029 FT_Vector* vec = cur->points; | |
| 3030 FT_Fixed x_scale = glyph->x_scale; | |
| 3031 FT_Fixed y_scale = glyph->y_scale; | |
| 3032 | |
| 3033 | |
| 3034 /* First of all, scale the points */ | |
| 3035 if ( !hinting || !decoder.builder.hints_funcs ) | |
| 3036 for ( n = cur->n_points; n > 0; n--, vec++ ) | |
| 3037 { | |
| 3038 vec->x = FT_MulFix( vec->x, x_scale ); | |
| 3039 vec->y = FT_MulFix( vec->y, y_scale ); | |
| 3040 } | |
| 3041 | |
| 3042 /* Then scale the metrics */ | |
| 3043 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); | |
| 3044 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); | |
| 3045 } | |
| 3046 | |
| 3047 /* compute the other metrics */ | |
| 3048 FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); | |
| 3049 | |
| 3050 metrics->width = cbox.xMax - cbox.xMin; | |
| 3051 metrics->height = cbox.yMax - cbox.yMin; | |
| 3052 | |
| 3053 metrics->horiBearingX = cbox.xMin; | |
| 3054 metrics->horiBearingY = cbox.yMax; | |
| 3055 | |
| 3056 if ( has_vertical_info ) | |
| 3057 metrics->vertBearingX = metrics->horiBearingX - | |
| 3058 metrics->horiAdvance / 2; | |
| 3059 else | |
| 3060 { | |
| 3061 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) | |
| 3062 ft_synthesize_vertical_metrics( metrics, | |
| 3063 metrics->vertAdvance ); | |
| 3064 } | |
| 3065 } | |
| 3066 } | |
| 3067 | |
| 3068 return error; | |
| 3069 } | |
| 3070 | |
| 3071 | |
| 3072 /* END */ | |
| OLD | NEW |