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 : cff_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 ? subrs->count : 0; } 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 || 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 { set_intCFF::point_t97 void set_int (int _x, int _y) 98 { 99 x.set_int (_x); 100 y.set_int (_y); 101 } 102 move_xCFF::point_t103 void move_x (const number_t &dx) { x += dx; } move_yCFF::point_t104 void move_y (const number_t &dy) { y += dy; } moveCFF::point_t105 void move (const number_t &dx, const number_t &dy) { move_x (dx); move_y (dy); } moveCFF::point_t106 void move (const point_t &d) { move_x (d.x); move_y (d.y); } 107 108 number_t x; 109 number_t y; 110 }; 111 112 template <typename ARG, typename SUBRS> 113 struct cs_interp_env_t : interp_env_t<ARG> 114 { initCFF::cs_interp_env_t115 void init (const byte_str_t &str, const SUBRS *globalSubrs_, const SUBRS *localSubrs_) 116 { 117 interp_env_t<ARG>::init (str); 118 119 context.init (str, CSType_CharString); 120 seen_moveto = true; 121 seen_hintmask = false; 122 hstem_count = 0; 123 vstem_count = 0; 124 hintmask_size = 0; 125 pt.set_int (0, 0); 126 callStack.init (); 127 globalSubrs.init (globalSubrs_); 128 localSubrs.init (localSubrs_); 129 } finiCFF::cs_interp_env_t130 void fini () 131 { 132 interp_env_t<ARG>::fini (); 133 134 callStack.fini (); 135 globalSubrs.fini (); 136 localSubrs.fini (); 137 } 138 in_errorCFF::cs_interp_env_t139 bool in_error () const 140 { 141 return callStack.in_error () || SUPER::in_error (); 142 } 143 pop_subr_numCFF::cs_interp_env_t144 bool pop_subr_num (const biased_subrs_t<SUBRS>& biasedSubrs, unsigned int &subr_num) 145 { 146 subr_num = 0; 147 int n = SUPER::argStack.pop_int (); 148 n += biasedSubrs.get_bias (); 149 if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.get_count ()))) 150 return false; 151 152 subr_num = (unsigned int)n; 153 return true; 154 } 155 call_subrCFF::cs_interp_env_t156 void call_subr (const biased_subrs_t<SUBRS>& biasedSubrs, cs_type_t type) 157 { 158 unsigned int subr_num = 0; 159 160 if (unlikely (!pop_subr_num (biasedSubrs, subr_num) 161 || callStack.get_count () >= kMaxCallLimit)) 162 { 163 SUPER::set_error (); 164 return; 165 } 166 context.str_ref = SUPER::str_ref; 167 callStack.push (context); 168 169 context.init ( biasedSubrs[subr_num], type, subr_num); 170 SUPER::str_ref = context.str_ref; 171 } 172 return_from_subrCFF::cs_interp_env_t173 void return_from_subr () 174 { 175 if (unlikely (SUPER::str_ref.in_error ())) 176 SUPER::set_error (); 177 context = callStack.pop (); 178 SUPER::str_ref = context.str_ref; 179 } 180 determine_hintmask_sizeCFF::cs_interp_env_t181 void determine_hintmask_size () 182 { 183 if (!seen_hintmask) 184 { 185 vstem_count += SUPER::argStack.get_count() / 2; 186 hintmask_size = (hstem_count + vstem_count + 7) >> 3; 187 seen_hintmask = true; 188 } 189 } 190 set_endcharCFF::cs_interp_env_t191 void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; } is_endcharCFF::cs_interp_env_t192 bool is_endchar () const { return endchar_flag; } 193 get_xCFF::cs_interp_env_t194 const number_t &get_x () const { return pt.x; } get_yCFF::cs_interp_env_t195 const number_t &get_y () const { return pt.y; } get_ptCFF::cs_interp_env_t196 const point_t &get_pt () const { return pt; } 197 movetoCFF::cs_interp_env_t198 void moveto (const point_t &pt_ ) { pt = pt_; } 199 200 public: 201 call_context_t context; 202 bool endchar_flag; 203 bool seen_moveto; 204 bool seen_hintmask; 205 206 unsigned int hstem_count; 207 unsigned int vstem_count; 208 unsigned int hintmask_size; 209 call_stack_t callStack; 210 biased_subrs_t<SUBRS> globalSubrs; 211 biased_subrs_t<SUBRS> localSubrs; 212 213 private: 214 point_t pt; 215 216 typedef interp_env_t<ARG> SUPER; 217 }; 218 219 template <typename ENV, typename PARAM> 220 struct path_procs_null_t 221 { rmovetoCFF::path_procs_null_t222 static void rmoveto (ENV &env, PARAM& param) {} hmovetoCFF::path_procs_null_t223 static void hmoveto (ENV &env, PARAM& param) {} vmovetoCFF::path_procs_null_t224 static void vmoveto (ENV &env, PARAM& param) {} rlinetoCFF::path_procs_null_t225 static void rlineto (ENV &env, PARAM& param) {} hlinetoCFF::path_procs_null_t226 static void hlineto (ENV &env, PARAM& param) {} vlinetoCFF::path_procs_null_t227 static void vlineto (ENV &env, PARAM& param) {} rrcurvetoCFF::path_procs_null_t228 static void rrcurveto (ENV &env, PARAM& param) {} rcurvelineCFF::path_procs_null_t229 static void rcurveline (ENV &env, PARAM& param) {} rlinecurveCFF::path_procs_null_t230 static void rlinecurve (ENV &env, PARAM& param) {} vvcurvetoCFF::path_procs_null_t231 static void vvcurveto (ENV &env, PARAM& param) {} hhcurvetoCFF::path_procs_null_t232 static void hhcurveto (ENV &env, PARAM& param) {} vhcurvetoCFF::path_procs_null_t233 static void vhcurveto (ENV &env, PARAM& param) {} hvcurvetoCFF::path_procs_null_t234 static void hvcurveto (ENV &env, PARAM& param) {} movetoCFF::path_procs_null_t235 static void moveto (ENV &env, PARAM& param, const point_t &pt) {} lineCFF::path_procs_null_t236 static void line (ENV &env, PARAM& param, const point_t &pt1) {} curveCFF::path_procs_null_t237 static void curve (ENV &env, PARAM& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) {} hflexCFF::path_procs_null_t238 static void hflex (ENV &env, PARAM& param) {} flexCFF::path_procs_null_t239 static void flex (ENV &env, PARAM& param) {} hflex1CFF::path_procs_null_t240 static void hflex1 (ENV &env, PARAM& param) {} flex1CFF::path_procs_null_t241 static void flex1 (ENV &env, PARAM& param) {} 242 }; 243 244 template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=path_procs_null_t<ENV, PARAM>> 245 struct cs_opset_t : opset_t<ARG> 246 { process_opCFF::cs_opset_t247 static void process_op (op_code_t op, ENV &env, PARAM& param) 248 { 249 switch (op) { 250 251 case OpCode_return: 252 env.return_from_subr (); 253 break; 254 case OpCode_endchar: 255 OPSET::check_width (op, env, param); 256 env.set_endchar (true); 257 OPSET::flush_args_and_op (op, env, param); 258 break; 259 260 case OpCode_fixedcs: 261 env.argStack.push_fixed_from_substr (env.str_ref); 262 break; 263 264 case OpCode_callsubr: 265 env.call_subr (env.localSubrs, CSType_LocalSubr); 266 break; 267 268 case OpCode_callgsubr: 269 env.call_subr (env.globalSubrs, CSType_GlobalSubr); 270 break; 271 272 case OpCode_hstem: 273 case OpCode_hstemhm: 274 OPSET::check_width (op, env, param); 275 OPSET::process_hstem (op, env, param); 276 break; 277 case OpCode_vstem: 278 case OpCode_vstemhm: 279 OPSET::check_width (op, env, param); 280 OPSET::process_vstem (op, env, param); 281 break; 282 case OpCode_hintmask: 283 case OpCode_cntrmask: 284 OPSET::check_width (op, env, param); 285 OPSET::process_hintmask (op, env, param); 286 break; 287 case OpCode_rmoveto: 288 OPSET::check_width (op, env, param); 289 PATH::rmoveto (env, param); 290 OPSET::process_post_move (op, env, param); 291 break; 292 case OpCode_hmoveto: 293 OPSET::check_width (op, env, param); 294 PATH::hmoveto (env, param); 295 OPSET::process_post_move (op, env, param); 296 break; 297 case OpCode_vmoveto: 298 OPSET::check_width (op, env, param); 299 PATH::vmoveto (env, param); 300 OPSET::process_post_move (op, env, param); 301 break; 302 case OpCode_rlineto: 303 PATH::rlineto (env, param); 304 process_post_path (op, env, param); 305 break; 306 case OpCode_hlineto: 307 PATH::hlineto (env, param); 308 process_post_path (op, env, param); 309 break; 310 case OpCode_vlineto: 311 PATH::vlineto (env, param); 312 process_post_path (op, env, param); 313 break; 314 case OpCode_rrcurveto: 315 PATH::rrcurveto (env, param); 316 process_post_path (op, env, param); 317 break; 318 case OpCode_rcurveline: 319 PATH::rcurveline (env, param); 320 process_post_path (op, env, param); 321 break; 322 case OpCode_rlinecurve: 323 PATH::rlinecurve (env, param); 324 process_post_path (op, env, param); 325 break; 326 case OpCode_vvcurveto: 327 PATH::vvcurveto (env, param); 328 process_post_path (op, env, param); 329 break; 330 case OpCode_hhcurveto: 331 PATH::hhcurveto (env, param); 332 process_post_path (op, env, param); 333 break; 334 case OpCode_vhcurveto: 335 PATH::vhcurveto (env, param); 336 process_post_path (op, env, param); 337 break; 338 case OpCode_hvcurveto: 339 PATH::hvcurveto (env, param); 340 process_post_path (op, env, param); 341 break; 342 343 case OpCode_hflex: 344 PATH::hflex (env, param); 345 OPSET::process_post_flex (op, env, param); 346 break; 347 348 case OpCode_flex: 349 PATH::flex (env, param); 350 OPSET::process_post_flex (op, env, param); 351 break; 352 353 case OpCode_hflex1: 354 PATH::hflex1 (env, param); 355 OPSET::process_post_flex (op, env, param); 356 break; 357 358 case OpCode_flex1: 359 PATH::flex1 (env, param); 360 OPSET::process_post_flex (op, env, param); 361 break; 362 363 default: 364 SUPER::process_op (op, env); 365 break; 366 } 367 } 368 process_hstemCFF::cs_opset_t369 static void process_hstem (op_code_t op, ENV &env, PARAM& param) 370 { 371 env.hstem_count += env.argStack.get_count () / 2; 372 OPSET::flush_args_and_op (op, env, param); 373 } 374 process_vstemCFF::cs_opset_t375 static void process_vstem (op_code_t op, ENV &env, PARAM& param) 376 { 377 env.vstem_count += env.argStack.get_count () / 2; 378 OPSET::flush_args_and_op (op, env, param); 379 } 380 process_hintmaskCFF::cs_opset_t381 static void process_hintmask (op_code_t op, ENV &env, PARAM& param) 382 { 383 env.determine_hintmask_size (); 384 if (likely (env.str_ref.avail (env.hintmask_size))) 385 { 386 OPSET::flush_hintmask (op, env, param); 387 env.str_ref.inc (env.hintmask_size); 388 } 389 } 390 process_post_flexCFF::cs_opset_t391 static void process_post_flex (op_code_t op, ENV &env, PARAM& param) 392 { 393 OPSET::flush_args_and_op (op, env, param); 394 } 395 check_widthCFF::cs_opset_t396 static void check_width (op_code_t op, ENV &env, PARAM& param) 397 {} 398 process_post_moveCFF::cs_opset_t399 static void process_post_move (op_code_t op, ENV &env, PARAM& param) 400 { 401 if (!env.seen_moveto) 402 { 403 env.determine_hintmask_size (); 404 env.seen_moveto = true; 405 } 406 OPSET::flush_args_and_op (op, env, param); 407 } 408 process_post_pathCFF::cs_opset_t409 static void process_post_path (op_code_t op, ENV &env, PARAM& param) 410 { 411 OPSET::flush_args_and_op (op, env, param); 412 } 413 flush_args_and_opCFF::cs_opset_t414 static void flush_args_and_op (op_code_t op, ENV &env, PARAM& param) 415 { 416 OPSET::flush_args (env, param); 417 OPSET::flush_op (op, env, param); 418 } 419 flush_argsCFF::cs_opset_t420 static void flush_args (ENV &env, PARAM& param) 421 { 422 env.pop_n_args (env.argStack.get_count ()); 423 } 424 flush_opCFF::cs_opset_t425 static void flush_op (op_code_t op, ENV &env, PARAM& param) 426 { 427 } 428 flush_hintmaskCFF::cs_opset_t429 static void flush_hintmask (op_code_t op, ENV &env, PARAM& param) 430 { 431 OPSET::flush_args_and_op (op, env, param); 432 } 433 is_number_opCFF::cs_opset_t434 static bool is_number_op (op_code_t op) 435 { 436 switch (op) 437 { 438 case OpCode_shortint: 439 case OpCode_fixedcs: 440 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1: 441 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3: 442 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1: 443 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3: 444 return true; 445 446 default: 447 /* 1-byte integer */ 448 return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast); 449 } 450 } 451 452 protected: 453 typedef opset_t<ARG> SUPER; 454 }; 455 456 template <typename PATH, typename ENV, typename PARAM> 457 struct path_procs_t 458 { rmovetoCFF::path_procs_t459 static void rmoveto (ENV &env, PARAM& param) 460 { 461 point_t pt1 = env.get_pt (); 462 const number_t &dy = env.pop_arg (); 463 const number_t &dx = env.pop_arg (); 464 pt1.move (dx, dy); 465 PATH::moveto (env, param, pt1); 466 } 467 hmovetoCFF::path_procs_t468 static void hmoveto (ENV &env, PARAM& param) 469 { 470 point_t pt1 = env.get_pt (); 471 pt1.move_x (env.pop_arg ()); 472 PATH::moveto (env, param, pt1); 473 } 474 vmovetoCFF::path_procs_t475 static void vmoveto (ENV &env, PARAM& param) 476 { 477 point_t pt1 = env.get_pt (); 478 pt1.move_y (env.pop_arg ()); 479 PATH::moveto (env, param, pt1); 480 } 481 rlinetoCFF::path_procs_t482 static void rlineto (ENV &env, PARAM& param) 483 { 484 for (unsigned int i = 0; i + 2 <= env.argStack.get_count (); i += 2) 485 { 486 point_t pt1 = env.get_pt (); 487 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 488 PATH::line (env, param, pt1); 489 } 490 } 491 hlinetoCFF::path_procs_t492 static void hlineto (ENV &env, PARAM& param) 493 { 494 point_t pt1; 495 unsigned int i = 0; 496 for (; i + 2 <= env.argStack.get_count (); i += 2) 497 { 498 pt1 = env.get_pt (); 499 pt1.move_x (env.eval_arg (i)); 500 PATH::line (env, param, pt1); 501 pt1.move_y (env.eval_arg (i+1)); 502 PATH::line (env, param, pt1); 503 } 504 if (i < env.argStack.get_count ()) 505 { 506 pt1 = env.get_pt (); 507 pt1.move_x (env.eval_arg (i)); 508 PATH::line (env, param, pt1); 509 } 510 } 511 vlinetoCFF::path_procs_t512 static void vlineto (ENV &env, PARAM& param) 513 { 514 point_t pt1; 515 unsigned int i = 0; 516 for (; i + 2 <= env.argStack.get_count (); i += 2) 517 { 518 pt1 = env.get_pt (); 519 pt1.move_y (env.eval_arg (i)); 520 PATH::line (env, param, pt1); 521 pt1.move_x (env.eval_arg (i+1)); 522 PATH::line (env, param, pt1); 523 } 524 if (i < env.argStack.get_count ()) 525 { 526 pt1 = env.get_pt (); 527 pt1.move_y (env.eval_arg (i)); 528 PATH::line (env, param, pt1); 529 } 530 } 531 rrcurvetoCFF::path_procs_t532 static void rrcurveto (ENV &env, PARAM& param) 533 { 534 for (unsigned int i = 0; i + 6 <= env.argStack.get_count (); i += 6) 535 { 536 point_t pt1 = env.get_pt (); 537 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 538 point_t pt2 = pt1; 539 pt2.move (env.eval_arg (i+2), env.eval_arg (i+3)); 540 point_t pt3 = pt2; 541 pt3.move (env.eval_arg (i+4), env.eval_arg (i+5)); 542 PATH::curve (env, param, pt1, pt2, pt3); 543 } 544 } 545 rcurvelineCFF::path_procs_t546 static void rcurveline (ENV &env, PARAM& param) 547 { 548 unsigned int arg_count = env.argStack.get_count (); 549 if (unlikely (arg_count < 8)) 550 return; 551 552 unsigned int i = 0; 553 unsigned int curve_limit = arg_count - 2; 554 for (; i + 6 <= curve_limit; 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 565 point_t pt1 = env.get_pt (); 566 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 567 PATH::line (env, param, pt1); 568 } 569 rlinecurveCFF::path_procs_t570 static void rlinecurve (ENV &env, PARAM& param) 571 { 572 unsigned int arg_count = env.argStack.get_count (); 573 if (unlikely (arg_count < 8)) 574 return; 575 576 unsigned int i = 0; 577 unsigned int line_limit = arg_count - 6; 578 for (; i + 2 <= line_limit; i += 2) 579 { 580 point_t pt1 = env.get_pt (); 581 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 582 PATH::line (env, param, pt1); 583 } 584 585 point_t pt1 = env.get_pt (); 586 pt1.move (env.eval_arg (i), env.eval_arg (i+1)); 587 point_t pt2 = pt1; 588 pt2.move (env.eval_arg (i+2), env.eval_arg (i+3)); 589 point_t pt3 = pt2; 590 pt3.move (env.eval_arg (i+4), env.eval_arg (i+5)); 591 PATH::curve (env, param, pt1, pt2, pt3); 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 for (unsigned int i = 0; i < 10; i += 2) 839 d.move (env.eval_arg (i), env.eval_arg (i+1)); 840 841 point_t pt1 = env.get_pt (); 842 pt1.move (env.eval_arg (0), env.eval_arg (1)); 843 point_t pt2 = pt1; 844 pt2.move (env.eval_arg (2), env.eval_arg (3)); 845 point_t pt3 = pt2; 846 pt3.move (env.eval_arg (4), env.eval_arg (5)); 847 point_t pt4 = pt3; 848 pt4.move (env.eval_arg (6), env.eval_arg (7)); 849 point_t pt5 = pt4; 850 pt5.move (env.eval_arg (8), env.eval_arg (9)); 851 point_t pt6 = pt5; 852 853 if (fabs (d.x.to_real ()) > fabs (d.y.to_real ())) 854 { 855 pt6.move_x (env.eval_arg (10)); 856 pt6.y = env.get_pt ().y; 857 } 858 else 859 { 860 pt6.x = env.get_pt ().x; 861 pt6.move_y (env.eval_arg (10)); 862 } 863 864 curve2 (env, param, pt1, pt2, pt3, pt4, pt5, pt6); 865 } 866 else 867 env.set_error (); 868 } 869 870 protected: curve2CFF::path_procs_t871 static void curve2 (ENV &env, PARAM& param, 872 const point_t &pt1, const point_t &pt2, const point_t &pt3, 873 const point_t &pt4, const point_t &pt5, const point_t &pt6) 874 { 875 PATH::curve (env, param, pt1, pt2, pt3); 876 PATH::curve (env, param, pt4, pt5, pt6); 877 } 878 }; 879 880 template <typename ENV, typename OPSET, typename PARAM> 881 struct cs_interpreter_t : interpreter_t<ENV> 882 { interpretCFF::cs_interpreter_t883 bool interpret (PARAM& param) 884 { 885 SUPER::env.set_endchar (false); 886 887 for (;;) { 888 OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); 889 if (unlikely (SUPER::env.in_error ())) 890 return false; 891 if (SUPER::env.is_endchar ()) 892 break; 893 } 894 895 return true; 896 } 897 898 private: 899 typedef interpreter_t<ENV> SUPER; 900 }; 901 902 } /* namespace CFF */ 903 904 #endif /* HB_CFF_INTERP_CS_COMMON_HH */ 905