1 /* 2 * Copyright © 2018 Adobe Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Adobe Author(s): Michiharu Ariza 25 */ 26 #ifndef HB_CFF_INTERP_CS_COMMON_HH 27 #define HB_CFF_INTERP_CS_COMMON_HH 28 29 #include "hb.hh" 30 #include "hb-cff-interp-common.hh" 31 32 namespace CFF { 33 34 using namespace OT; 35 36 enum cs_type_t { 37 CSType_CharString, 38 CSType_GlobalSubr, 39 CSType_LocalSubr 40 }; 41 42 struct call_context_t 43 { initCFF::call_context_t44 void init (const byte_str_ref_t substr_=byte_str_ref_t (), cs_type_t type_=CSType_CharString, unsigned int subr_num_=0) 45 { 46 str_ref = substr_; 47 type = type_; 48 subr_num = subr_num_; 49 } 50 finiCFF::call_context_t51 void fini () {} 52 53 byte_str_ref_t str_ref; 54 cs_type_t type; 55 unsigned int subr_num; 56 }; 57 58 /* call stack */ 59 const unsigned int kMaxCallLimit = 10; 60 struct call_stack_t : stack_t<call_context_t, kMaxCallLimit> {}; 61 62 template <typename SUBRS> 63 struct biased_subrs_t 64 { initCFF::biased_subrs_t65 void init (const SUBRS &subrs_) 66 { 67 subrs = &subrs_; 68 unsigned int nSubrs = get_count (); 69 if (nSubrs < 1240) 70 bias = 107; 71 else if (nSubrs < 33900) 72 bias = 1131; 73 else 74 bias = 32768; 75 } 76 finiCFF::biased_subrs_t77 void fini () {} 78 get_countCFF::biased_subrs_t79 unsigned int get_count () const { return (subrs == nullptr)? 0: subrs->count; } get_biasCFF::biased_subrs_t80 unsigned int get_bias () const { return bias; } 81 operator []CFF::biased_subrs_t82 byte_str_t operator [] (unsigned int index) const 83 { 84 if (unlikely ((subrs == nullptr) || index >= subrs->count)) 85 return Null(byte_str_t); 86 else 87 return (*subrs)[index]; 88 } 89 90 protected: 91 unsigned int bias; 92 const SUBRS *subrs; 93 }; 94 95 struct point_t 96 { initCFF::point_t97 void init () 98 { 99 x.init (); 100 y.init (); 101 } 102 set_intCFF::point_t103 void set_int (int _x, int _y) 104 { 105 x.set_int (_x); 106 y.set_int (_y); 107 } 108 move_xCFF::point_t109 void move_x (const number_t &dx) { x += dx; } move_yCFF::point_t110 void move_y (const number_t &dy) { y += dy; } moveCFF::point_t111 void move (const number_t &dx, const number_t &dy) { move_x (dx); move_y (dy); } moveCFF::point_t112 void move (const point_t &d) { move_x (d.x); move_y (d.y); } 113 114 number_t x; 115 number_t y; 116 }; 117 118 template <typename ARG, typename SUBRS> 119 struct cs_interp_env_t : interp_env_t<ARG> 120 { initCFF::cs_interp_env_t121 void init (const byte_str_t &str, const SUBRS &globalSubrs_, const SUBRS &localSubrs_) 122 { 123 interp_env_t<ARG>::init (str); 124 125 context.init (str, CSType_CharString); 126 seen_moveto = true; 127 seen_hintmask = false; 128 hstem_count = 0; 129 vstem_count = 0; 130 hintmask_size = 0; 131 pt.init (); 132 callStack.init (); 133 globalSubrs.init (globalSubrs_); 134 localSubrs.init (localSubrs_); 135 } finiCFF::cs_interp_env_t136 void fini () 137 { 138 interp_env_t<ARG>::fini (); 139 140 callStack.fini (); 141 globalSubrs.fini (); 142 localSubrs.fini (); 143 } 144 in_errorCFF::cs_interp_env_t145 bool in_error () const 146 { 147 return callStack.in_error () || SUPER::in_error (); 148 } 149 popSubrNumCFF::cs_interp_env_t150 bool popSubrNum (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num) 151 { 152 int n = SUPER::argStack.pop_int (); 153 n += biasedSubrs.get_bias (); 154 if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ()))) 155 return false; 156 157 subr_num = (unsigned int)n; 158 return true; 159 } 160 callSubrCFF::cs_interp_env_t161 void callSubr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type) 162 { 163 unsigned int subr_num; 164 165 if (unlikely (!popSubrNum (biasedSubrs, subr_num) 166 || callStack.get_count () >= kMaxCallLimit)) 167 { 168 SUPER::set_error (); 169 return; 170 } 171 context.str_ref = SUPER::str_ref; 172 callStack.push (context); 173 174 context.init ( biasedSubrs[subr_num], type, subr_num); 175 SUPER::str_ref = context.str_ref; 176 } 177 returnFromSubrCFF::cs_interp_env_t178 void returnFromSubr () 179 { 180 if (unlikely (SUPER::str_ref.in_error ())) 181 SUPER::set_error (); 182 context = callStack.pop (); 183 SUPER::str_ref = context.str_ref; 184 } 185 determine_hintmask_sizeCFF::cs_interp_env_t186 void determine_hintmask_size () 187 { 188 if (!seen_hintmask) 189 { 190 vstem_count += SUPER::argStack.get_count() / 2; 191 hintmask_size = (hstem_count + vstem_count + 7) >> 3; 192 seen_hintmask = true; 193 } 194 } 195 set_endcharCFF::cs_interp_env_t196 void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; } is_endcharCFF::cs_interp_env_t197 bool is_endchar () const { return endchar_flag; } 198 get_xCFF::cs_interp_env_t199 const number_t &get_x () const { return pt.x; } get_yCFF::cs_interp_env_t200 const number_t &get_y () const { return pt.y; } get_ptCFF::cs_interp_env_t201 const point_t &get_pt () const { return pt; } 202 movetoCFF::cs_interp_env_t203 void moveto (const point_t &pt_ ) { pt = pt_; } 204 205 public: 206 call_context_t context; 207 bool endchar_flag; 208 bool seen_moveto; 209 bool seen_hintmask; 210 211 unsigned int hstem_count; 212 unsigned int vstem_count; 213 unsigned int hintmask_size; 214 call_stack_t callStack; 215 biased_subrs_t<SUBRS> globalSubrs; 216 biased_subrs_t<SUBRS> localSubrs; 217 218 private: 219 point_t pt; 220 221 typedef interp_env_t<ARG> SUPER; 222 }; 223 224 template <typename ENV, typename PARAM> 225 struct path_procs_null_t 226 { rmovetoCFF::path_procs_null_t227 static void rmoveto (ENV &env, PARAM& param) {} hmovetoCFF::path_procs_null_t228 static void hmoveto (ENV &env, PARAM& param) {} vmovetoCFF::path_procs_null_t229 static void vmoveto (ENV &env, PARAM& param) {} rlinetoCFF::path_procs_null_t230 static void rlineto (ENV &env, PARAM& param) {} hlinetoCFF::path_procs_null_t231 static void hlineto (ENV &env, PARAM& param) {} vlinetoCFF::path_procs_null_t232 static void vlineto (ENV &env, PARAM& param) {} rrcurvetoCFF::path_procs_null_t233 static void rrcurveto (ENV &env, PARAM& param) {} rcurvelineCFF::path_procs_null_t234 static void rcurveline (ENV &env, PARAM& param) {} rlinecurveCFF::path_procs_null_t235 static void rlinecurve (ENV &env, PARAM& param) {} vvcurvetoCFF::path_procs_null_t236 static void vvcurveto (ENV &env, PARAM& param) {} hhcurvetoCFF::path_procs_null_t237 static void hhcurveto (ENV &env, PARAM& param) {} vhcurvetoCFF::path_procs_null_t238 static void vhcurveto (ENV &env, PARAM& param) {} hvcurvetoCFF::path_procs_null_t239 static void hvcurveto (ENV &env, PARAM& param) {} movetoCFF::path_procs_null_t240 static void moveto (ENV &env, PARAM& param, const point_t &pt) {} lineCFF::path_procs_null_t241 static void line (ENV &env, PARAM& param, const point_t &pt1) {} curveCFF::path_procs_null_t242 static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {} hflexCFF::path_procs_null_t243 static void hflex (ENV &env, PARAM& param) {} flexCFF::path_procs_null_t244 static void flex (ENV &env, PARAM& param) {} hflex1CFF::path_procs_null_t245 static void hflex1 (ENV &env, PARAM& param) {} flex1CFF::path_procs_null_t246 static void flex1 (ENV &env, PARAM& param) {} 247 }; 248 249 template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM> > 250 struct cs_opset_t : opset_t<ARG> 251 { process_opCFF::cs_opset_t252 static void process_op (op_code_t op, ENV &env, PARAM& param) 253 { 254 switch (op) { 255 256 case OpCode_return: 257 env.returnFromSubr (); 258 break; 259 case OpCode_endchar: 260 OPSET::check_width (op, env, param); 261 env.set_endchar (true); 262 OPSET::flush_args_and_op (op, env, param); 263 break; 264 265 case OpCode_fixedcs: 266 env.argStack.push_fixed_from_substr (env.str_ref); 267 break; 268 269 case OpCode_callsubr: 270 env.callSubr (env.localSubrs, CSType_LocalSubr); 271 break; 272 273 case OpCode_callgsubr: 274 env.callSubr (env.globalSubrs, CSType_GlobalSubr); 275 break; 276 277 case OpCode_hstem: 278 case OpCode_hstemhm: 279 OPSET::check_width (op, env, param); 280 OPSET::process_hstem (op, env, param); 281 break; 282 case OpCode_vstem: 283 case OpCode_vstemhm: 284 OPSET::check_width (op, env, param); 285 OPSET::process_vstem (op, env, param); 286 break; 287 case OpCode_hintmask: 288 case OpCode_cntrmask: 289 OPSET::check_width (op, env, param); 290 OPSET::process_hintmask (op, env, param); 291 break; 292 case OpCode_rmoveto: 293 OPSET::check_width (op, env, param); 294 PATH::rmoveto (env, param); 295 OPSET::process_post_move (op, env, param); 296 break; 297 case OpCode_hmoveto: 298 OPSET::check_width (op, env, param); 299 PATH::hmoveto (env, param); 300 OPSET::process_post_move (op, env, param); 301 break; 302 case OpCode_vmoveto: 303 OPSET::check_width (op, env, param); 304 PATH::vmoveto (env, param); 305 OPSET::process_post_move (op, env, param); 306 break; 307 case OpCode_rlineto: 308 PATH::rlineto (env, param); 309 process_post_path (op, env, param); 310 break; 311 case OpCode_hlineto: 312 PATH::hlineto (env, param); 313 process_post_path (op, env, param); 314 break; 315 case OpCode_vlineto: 316 PATH::vlineto (env, param); 317 process_post_path (op, env, param); 318 break; 319 case OpCode_rrcurveto: 320 PATH::rrcurveto (env, param); 321 process_post_path (op, env, param); 322 break; 323 case OpCode_rcurveline: 324 PATH::rcurveline (env, param); 325 process_post_path (op, env, param); 326 break; 327 case OpCode_rlinecurve: 328 PATH::rlinecurve (env, param); 329 process_post_path (op, env, param); 330 break; 331 case OpCode_vvcurveto: 332 PATH::vvcurveto (env, param); 333 process_post_path (op, env, param); 334 break; 335 case OpCode_hhcurveto: 336 PATH::hhcurveto (env, param); 337 process_post_path (op, env, param); 338 break; 339 case OpCode_vhcurveto: 340 PATH::vhcurveto (env, param); 341 process_post_path (op, env, param); 342 break; 343 case OpCode_hvcurveto: 344 PATH::hvcurveto (env, param); 345 process_post_path (op, env, param); 346 break; 347 348 case OpCode_hflex: 349 PATH::hflex (env, param); 350 OPSET::process_post_flex (op, env, param); 351 break; 352 353 case OpCode_flex: 354 PATH::flex (env, param); 355 OPSET::process_post_flex (op, env, param); 356 break; 357 358 case OpCode_hflex1: 359 PATH::hflex1 (env, param); 360 OPSET::process_post_flex (op, env, param); 361 break; 362 363 case OpCode_flex1: 364 PATH::flex1 (env, param); 365 OPSET::process_post_flex (op, env, param); 366 break; 367 368 default: 369 SUPER::process_op (op, env); 370 break; 371 } 372 } 373 process_hstemCFF::cs_opset_t374 static void process_hstem (op_code_t op, ENV &env, PARAM& param) 375 { 376 env.hstem_count += env.argStack.get_count () / 2; 377 OPSET::flush_args_and_op (op, env, param); 378 } 379 process_vstemCFF::cs_opset_t380 static void process_vstem (op_code_t op, ENV &env, PARAM& param) 381 { 382 env.vstem_count += env.argStack.get_count () / 2; 383 OPSET::flush_args_and_op (op, env, param); 384 } 385 process_hintmaskCFF::cs_opset_t386 static void process_hintmask (op_code_t op, ENV &env, PARAM& param) 387 { 388 env.determine_hintmask_size (); 389 if (likely (env.str_ref.avail (env.hintmask_size))) 390 { 391 OPSET::flush_hintmask (op, env, param); 392 env.str_ref.inc (env.hintmask_size); 393 } 394 } 395 process_post_flexCFF::cs_opset_t396 static void process_post_flex (op_code_t op, ENV &env, PARAM& param) 397 { 398 OPSET::flush_args_and_op (op, env, param); 399 } 400 check_widthCFF::cs_opset_t401 static void check_width (op_code_t op, ENV &env, PARAM& param) 402 {} 403 process_post_moveCFF::cs_opset_t404 static void process_post_move (op_code_t op, ENV &env, PARAM& param) 405 { 406 if (!env.seen_moveto) 407 { 408 env.determine_hintmask_size (); 409 env.seen_moveto = true; 410 } 411 OPSET::flush_args_and_op (op, env, param); 412 } 413 process_post_pathCFF::cs_opset_t414 static void process_post_path (op_code_t op, ENV &env, PARAM& param) 415 { 416 OPSET::flush_args_and_op (op, env, param); 417 } 418 flush_args_and_opCFF::cs_opset_t419 static void flush_args_and_op (op_code_t op, ENV &env, PARAM& param) 420 { 421 OPSET::flush_args (env, param); 422 OPSET::flush_op (op, env, param); 423 } 424 flush_argsCFF::cs_opset_t425 static void flush_args (ENV &env, PARAM& param) 426 { 427 env.pop_n_args (env.argStack.get_count ()); 428 } 429 flush_opCFF::cs_opset_t430 static void flush_op (op_code_t op, ENV &env, PARAM& param) 431 { 432 } 433 flush_hintmaskCFF::cs_opset_t434 static void flush_hintmask (op_code_t op, ENV &env, PARAM& param) 435 { 436 OPSET::flush_args_and_op (op, env, param); 437 } 438 is_number_opCFF::cs_opset_t439 static bool is_number_op (op_code_t op) 440 { 441 switch (op) 442 { 443 case OpCode_shortint: 444 case OpCode_fixedcs: 445 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1: 446 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3: 447 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1: 448 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3: 449 return true; 450 451 default: 452 /* 1-byte integer */ 453 return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast); 454 } 455 } 456 457 protected: 458 typedef opset_t<ARG> SUPER; 459 }; 460 461 template <typename PATH, typename ENV, typename PARAM> 462 struct path_procs_t 463 { rmovetoCFF::path_procs_t464 static void rmoveto (ENV &env, PARAM& param) 465 { 466 point_t pt1 = env.get_pt (); 467 const number_t &dy = env.pop_arg (); 468 const number_t &dx = env.pop_arg (); 469 pt1.move (dx, dy); 470 PATH::moveto (env, param, pt1); 471 } 472 hmovetoCFF::path_procs_t473 static void hmoveto (ENV &env, PARAM& param) 474 { 475 point_t pt1 = env.get_pt (); 476 pt1.move_x (env.pop_arg ()); 477 PATH::moveto (env, param, pt1); 478 } 479 vmovetoCFF::path_procs_t480 static void vmoveto (ENV &env, PARAM& param) 481 { 482 point_t pt1 = env.get_pt (); 483 pt1.move_y (env.pop_arg ()); 484 PATH::moveto (env, param, pt1); 485 } 486 rlinetoCFF::path_procs_t487 static void rlineto (ENV &env, PARAM& param) 488 { 489 for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2) 490 { 491 point_t pt1 = env.get_pt (); 492 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 493 PATH::line (env, param, pt1); 494 } 495 } 496 hlinetoCFF::path_procs_t497 static void hlineto (ENV &env, PARAM& param) 498 { 499 point_t pt1; 500 unsigned int i = 0; 501 for (; i + 2 <= env.argStack.get_count (); i += 2) 502 { 503 pt1 = env.get_pt (); 504 pt1.move_x (env.eval_arg (i)); 505 PATH::line (env, param, pt1); 506 pt1.move_y (env.eval_arg (i+1)); 507 PATH::line (env, param, pt1); 508 } 509 if (i < env.argStack.get_count ()) 510 { 511 pt1 = env.get_pt (); 512 pt1.move_x (env.eval_arg (i)); 513 PATH::line (env, param, pt1); 514 } 515 } 516 vlinetoCFF::path_procs_t517 static void vlineto (ENV &env, PARAM& param) 518 { 519 point_t pt1; 520 unsigned int i = 0; 521 for (; i + 2 <= env.argStack.get_count (); i += 2) 522 { 523 pt1 = env.get_pt (); 524 pt1.move_y (env.eval_arg (i)); 525 PATH::line (env, param, pt1); 526 pt1.move_x (env.eval_arg (i+1)); 527 PATH::line (env, param, pt1); 528 } 529 if (i < env.argStack.get_count ()) 530 { 531 pt1 = env.get_pt (); 532 pt1.move_y (env.eval_arg (i)); 533 PATH::line (env, param, pt1); 534 } 535 } 536 rrcurvetoCFF::path_procs_t537 static void rrcurveto (ENV &env, PARAM& param) 538 { 539 for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6) 540 { 541 point_t pt1 = env.get_pt (); 542 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 543 point_t pt2 = pt1; 544 pt2.move (env.eval_arg (i+2), env.eval_arg (i+3)); 545 point_t pt3 = pt2; 546 pt3.move (env.eval_arg (i+4), env.eval_arg (i+5)); 547 PATH::curve (env, param, pt1, pt2, pt3); 548 } 549 } 550 rcurvelineCFF::path_procs_t551 static void rcurveline (ENV &env, PARAM& param) 552 { 553 unsigned int i = 0; 554 for (; i + 6 <= env.argStack.get_count (); i += 6) 555 { 556 point_t pt1 = env.get_pt (); 557 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 558 point_t pt2 = pt1; 559 pt2.move (env.eval_arg (i+2), env.eval_arg (i+3)); 560 point_t pt3 = pt2; 561 pt3.move (env.eval_arg (i+4), env.eval_arg (i+5)); 562 PATH::curve (env, param, pt1, pt2, pt3); 563 } 564 for (; i + 2 <= env.argStack.get_count (); i += 2) 565 { 566 point_t pt1 = env.get_pt (); 567 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 568 PATH::line (env, param, pt1); 569 } 570 } 571 rlinecurveCFF::path_procs_t572 static void rlinecurve (ENV &env, PARAM& param) 573 { 574 unsigned int i = 0; 575 unsigned int line_limit = (env.argStack.get_count () % 6); 576 for (; i + 2 <= line_limit; i += 2) 577 { 578 point_t pt1 = env.get_pt (); 579 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 580 PATH::line (env, param, pt1); 581 } 582 for (; i + 6 <= env.argStack.get_count (); i += 6) 583 { 584 point_t pt1 = env.get_pt (); 585 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 586 point_t pt2 = pt1; 587 pt2.move (env.eval_arg (i+2), env.eval_arg (i+3)); 588 point_t pt3 = pt2; 589 pt3.move (env.eval_arg (i+4), env.eval_arg (i+5)); 590 PATH::curve (env, param, pt1, pt2, pt3); 591 } 592 } 593 vvcurvetoCFF::path_procs_t594 static void vvcurveto (ENV &env, PARAM& param) 595 { 596 unsigned int i = 0; 597 point_t pt1 = env.get_pt (); 598 if ((env.argStack.get_count () & 1) != 0) 599 pt1.move_x (env.eval_arg (i++)); 600 for (; i + 4 <= env.argStack.get_count (); i += 4) 601 { 602 pt1.move_y (env.eval_arg (i)); 603 point_t pt2 = pt1; 604 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 605 point_t pt3 = pt2; 606 pt3.move_y (env.eval_arg (i+3)); 607 PATH::curve (env, param, pt1, pt2, pt3); 608 pt1 = env.get_pt (); 609 } 610 } 611 hhcurvetoCFF::path_procs_t612 static void hhcurveto (ENV &env, PARAM& param) 613 { 614 unsigned int i = 0; 615 point_t pt1 = env.get_pt (); 616 if ((env.argStack.get_count () & 1) != 0) 617 pt1.move_y (env.eval_arg (i++)); 618 for (; i + 4 <= env.argStack.get_count (); i += 4) 619 { 620 pt1.move_x (env.eval_arg (i)); 621 point_t pt2 = pt1; 622 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 623 point_t pt3 = pt2; 624 pt3.move_x (env.eval_arg (i+3)); 625 PATH::curve (env, param, pt1, pt2, pt3); 626 pt1 = env.get_pt (); 627 } 628 } 629 vhcurvetoCFF::path_procs_t630 static void vhcurveto (ENV &env, PARAM& param) 631 { 632 point_t pt1, pt2, pt3; 633 unsigned int i = 0; 634 if ((env.argStack.get_count () % 8) >= 4) 635 { 636 point_t pt1 = env.get_pt (); 637 pt1.move_y (env.eval_arg (i)); 638 point_t pt2 = pt1; 639 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 640 point_t pt3 = pt2; 641 pt3.move_x (env.eval_arg (i+3)); 642 i += 4; 643 644 for (; i + 8 <= env.argStack.get_count (); i += 8) 645 { 646 PATH::curve (env, param, pt1, pt2, pt3); 647 pt1 = env.get_pt (); 648 pt1.move_x (env.eval_arg (i)); 649 pt2 = pt1; 650 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 651 pt3 = pt2; 652 pt3.move_y (env.eval_arg (i+3)); 653 PATH::curve (env, param, pt1, pt2, pt3); 654 655 pt1 = pt3; 656 pt1.move_y (env.eval_arg (i+4)); 657 pt2 = pt1; 658 pt2.move (env.eval_arg (i+5), env.eval_arg (i+6)); 659 pt3 = pt2; 660 pt3.move_x (env.eval_arg (i+7)); 661 } 662 if (i < env.argStack.get_count ()) 663 pt3.move_y (env.eval_arg (i)); 664 PATH::curve (env, param, pt1, pt2, pt3); 665 } 666 else 667 { 668 for (; i + 8 <= env.argStack.get_count (); i += 8) 669 { 670 pt1 = env.get_pt (); 671 pt1.move_y (env.eval_arg (i)); 672 pt2 = pt1; 673 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 674 pt3 = pt2; 675 pt3.move_x (env.eval_arg (i+3)); 676 PATH::curve (env, param, pt1, pt2, pt3); 677 678 pt1 = pt3; 679 pt1.move_x (env.eval_arg (i+4)); 680 pt2 = pt1; 681 pt2.move (env.eval_arg (i+5), env.eval_arg (i+6)); 682 pt3 = pt2; 683 pt3.move_y (env.eval_arg (i+7)); 684 if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0)) 685 pt3.move_x (env.eval_arg (i+8)); 686 PATH::curve (env, param, pt1, pt2, pt3); 687 } 688 } 689 } 690 hvcurvetoCFF::path_procs_t691 static void hvcurveto (ENV &env, PARAM& param) 692 { 693 point_t pt1, pt2, pt3; 694 unsigned int i = 0; 695 if ((env.argStack.get_count () % 8) >= 4) 696 { 697 point_t pt1 = env.get_pt (); 698 pt1.move_x (env.eval_arg (i)); 699 point_t pt2 = pt1; 700 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 701 point_t pt3 = pt2; 702 pt3.move_y (env.eval_arg (i+3)); 703 i += 4; 704 705 for (; i + 8 <= env.argStack.get_count (); i += 8) 706 { 707 PATH::curve (env, param, pt1, pt2, pt3); 708 pt1 = env.get_pt (); 709 pt1.move_y (env.eval_arg (i)); 710 pt2 = pt1; 711 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 712 pt3 = pt2; 713 pt3.move_x (env.eval_arg (i+3)); 714 PATH::curve (env, param, pt1, pt2, pt3); 715 716 pt1 = pt3; 717 pt1.move_x (env.eval_arg (i+4)); 718 pt2 = pt1; 719 pt2.move (env.eval_arg (i+5), env.eval_arg (i+6)); 720 pt3 = pt2; 721 pt3.move_y (env.eval_arg (i+7)); 722 } 723 if (i < env.argStack.get_count ()) 724 pt3.move_x (env.eval_arg (i)); 725 PATH::curve (env, param, pt1, pt2, pt3); 726 } 727 else 728 { 729 for (; i + 8 <= env.argStack.get_count (); i += 8) 730 { 731 pt1 = env.get_pt (); 732 pt1.move_x (env.eval_arg (i)); 733 pt2 = pt1; 734 pt2.move (env.eval_arg (i+1), env.eval_arg (i+2)); 735 pt3 = pt2; 736 pt3.move_y (env.eval_arg (i+3)); 737 PATH::curve (env, param, pt1, pt2, pt3); 738 739 pt1 = pt3; 740 pt1.move_y (env.eval_arg (i+4)); 741 pt2 = pt1; 742 pt2.move (env.eval_arg (i+5), env.eval_arg (i+6)); 743 pt3 = pt2; 744 pt3.move_x (env.eval_arg (i+7)); 745 if ((env.argStack.get_count () - i < 16) && ((env.argStack.get_count () & 1) != 0)) 746 pt3.move_y (env.eval_arg (i+8)); 747 PATH::curve (env, param, pt1, pt2, pt3); 748 } 749 } 750 } 751 752 /* default actions to be overridden */ movetoCFF::path_procs_t753 static void moveto (ENV &env, PARAM& param, const point_t &pt) 754 { env.moveto (pt); } 755 lineCFF::path_procs_t756 static void line (ENV &env, PARAM& param, const point_t &pt1) 757 { PATH::moveto (env, param, pt1); } 758 curveCFF::path_procs_t759 static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) 760 { PATH::moveto (env, param, pt3); } 761 hflexCFF::path_procs_t762 static void hflex (ENV &env, PARAM& param) 763 { 764 if (likely (env.argStack.get_count () == 7)) 765 { 766 point_t pt1 = env.get_pt (); 767 pt1.move_x (env.eval_arg (0)); 768 point_t pt2 = pt1; 769 pt2.move (env.eval_arg (1), env.eval_arg (2)); 770 point_t pt3 = pt2; 771 pt3.move_x (env.eval_arg (3)); 772 point_t pt4 = pt3; 773 pt4.move_x (env.eval_arg (4)); 774 point_t pt5 = pt4; 775 pt5.move_x (env.eval_arg (5)); 776 pt5.y = pt1.y; 777 point_t pt6 = pt5; 778 pt6.move_x (env.eval_arg (6)); 779 780 curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6); 781 } 782 else 783 env.set_error (); 784 } 785 flexCFF::path_procs_t786 static void flex (ENV &env, PARAM& param) 787 { 788 if (likely (env.argStack.get_count () == 13)) 789 { 790 point_t pt1 = env.get_pt (); 791 pt1.move (env.eval_arg (0), env.eval_arg (1)); 792 point_t pt2 = pt1; 793 pt2.move (env.eval_arg (2), env.eval_arg (3)); 794 point_t pt3 = pt2; 795 pt3.move (env.eval_arg (4), env.eval_arg (5)); 796 point_t pt4 = pt3; 797 pt4.move (env.eval_arg (6), env.eval_arg (7)); 798 point_t pt5 = pt4; 799 pt5.move (env.eval_arg (8), env.eval_arg (9)); 800 point_t pt6 = pt5; 801 pt6.move (env.eval_arg (10), env.eval_arg (11)); 802 803 curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6); 804 } 805 else 806 env.set_error (); 807 } 808 hflex1CFF::path_procs_t809 static void hflex1 (ENV &env, PARAM& param) 810 { 811 if (likely (env.argStack.get_count () == 9)) 812 { 813 point_t pt1 = env.get_pt (); 814 pt1.move (env.eval_arg (0), env.eval_arg (1)); 815 point_t pt2 = pt1; 816 pt2.move (env.eval_arg (2), env.eval_arg (3)); 817 point_t pt3 = pt2; 818 pt3.move_x (env.eval_arg (4)); 819 point_t pt4 = pt3; 820 pt4.move_x (env.eval_arg (5)); 821 point_t pt5 = pt4; 822 pt5.move (env.eval_arg (6), env.eval_arg (7)); 823 point_t pt6 = pt5; 824 pt6.move_x (env.eval_arg (8)); 825 pt6.y = env.get_pt ().y; 826 827 curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6); 828 } 829 else 830 env.set_error (); 831 } 832 flex1CFF::path_procs_t833 static void flex1 (ENV &env, PARAM& param) 834 { 835 if (likely (env.argStack.get_count () == 11)) 836 { 837 point_t d; 838 d.init (); 839 for (unsigned int i = 0; i < 10; i += 2) 840 d.move (env.eval_arg (i), env.eval_arg (i+1)); 841 842 point_t pt1 = env.get_pt (); 843 pt1.move (env.eval_arg (0), env.eval_arg (1)); 844 point_t pt2 = pt1; 845 pt2.move (env.eval_arg (2), env.eval_arg (3)); 846 point_t pt3 = pt2; 847 pt3.move (env.eval_arg (4), env.eval_arg (5)); 848 point_t pt4 = pt3; 849 pt4.move (env.eval_arg (6), env.eval_arg (7)); 850 point_t pt5 = pt4; 851 pt5.move (env.eval_arg (8), env.eval_arg (9)); 852 point_t pt6 = pt5; 853 854 if (fabs (d.x.to_real ()) > fabs (d.y.to_real ())) 855 { 856 pt6.move_x (env.eval_arg (10)); 857 pt6.y = env.get_pt ().y; 858 } 859 else 860 { 861 pt6.x = env.get_pt ().x; 862 pt6.move_y (env.eval_arg (10)); 863 } 864 865 curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6); 866 } 867 else 868 env.set_error (); 869 } 870 871 protected: curve2CFF::path_procs_t872 static void curve2 (ENV &env, PARAM& param, 873 const point_t &pt1, const point_t &pt2, const point_t &pt3, 874 const point_t &pt4, const point_t &pt5, const point_t &pt6) 875 { 876 PATH::curve (env, param, pt1, pt2, pt3); 877 PATH::curve (env, param, pt4, pt5, pt6); 878 } 879 }; 880 881 template <typename ENV, typename OPSET, typename PARAM> 882 struct cs_interpreter_t : interpreter_t<ENV> 883 { interpretCFF::cs_interpreter_t884 bool interpret (PARAM& param) 885 { 886 SUPER::env.set_endchar (false); 887 888 for (;;) { 889 OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); 890 if (unlikely (SUPER::env.in_error ())) 891 return false; 892 if (SUPER::env.is_endchar ()) 893 break; 894 } 895 896 return true; 897 } 898 899 private: 900 typedef interpreter_t<ENV> SUPER; 901 }; 902 903 } /* namespace CFF */ 904 905 #endif /* HB_CFF_INTERP_CS_COMMON_HH */ 906