2 * Copyright © 2018 Adobe Inc.
4 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
24 * Adobe Author(s): Michiharu Ariza
26 #ifndef HB_CFF_INTERP_CS_COMMON_HH
27 #define HB_CFF_INTERP_CS_COMMON_HH
30 #include "hb-cff-interp-common.hh"
44 void init (const byte_str_ref_t substr_
=byte_str_ref_t (), cs_type_t type_
=CSType_CharString
, unsigned int subr_num_
=0)
53 byte_str_ref_t str_ref
;
55 unsigned int subr_num
;
59 const unsigned int kMaxCallLimit
= 10;
60 struct call_stack_t
: cff_stack_t
<call_context_t
, kMaxCallLimit
> {};
62 template <typename SUBRS
>
65 void init (const SUBRS
*subrs_
)
68 unsigned int nSubrs
= get_count ();
71 else if (nSubrs
< 33900)
79 unsigned int get_count () const { return subrs
? subrs
->count
: 0; }
80 unsigned int get_bias () const { return bias
; }
82 hb_ubytes_t
operator [] (unsigned int index
) const
84 if (unlikely (!subrs
|| index
>= subrs
->count
))
85 return hb_ubytes_t ();
87 return (*subrs
)[index
];
97 void set_int (int _x
, int _y
)
103 void move_x (const number_t
&dx
) { x
+= dx
; }
104 void move_y (const number_t
&dy
) { y
+= dy
; }
105 void move (const number_t
&dx
, const number_t
&dy
) { move_x (dx
); move_y (dy
); }
106 void move (const point_t
&d
) { move_x (d
.x
); move_y (d
.y
); }
112 template <typename ARG
, typename SUBRS
>
113 struct cs_interp_env_t
: interp_env_t
<ARG
>
115 cs_interp_env_t (const hb_ubytes_t
&str
, const SUBRS
*globalSubrs_
, const SUBRS
*localSubrs_
) :
116 interp_env_t
<ARG
> (str
)
118 context
.init (str
, CSType_CharString
);
120 seen_hintmask
= false;
125 globalSubrs
.init (globalSubrs_
);
126 localSubrs
.init (localSubrs_
);
134 bool in_error () const
136 return callStack
.in_error () || SUPER::in_error ();
139 bool pop_subr_num (const biased_subrs_t
<SUBRS
>& biasedSubrs
, unsigned int &subr_num
)
142 int n
= SUPER::argStack
.pop_int ();
143 n
+= biasedSubrs
.get_bias ();
144 if (unlikely ((n
< 0) || ((unsigned int)n
>= biasedSubrs
.get_count ())))
147 subr_num
= (unsigned int)n
;
151 void call_subr (const biased_subrs_t
<SUBRS
>& biasedSubrs
, cs_type_t type
)
153 unsigned int subr_num
= 0;
155 if (unlikely (!pop_subr_num (biasedSubrs
, subr_num
)
156 || callStack
.get_count () >= kMaxCallLimit
))
161 context
.str_ref
= SUPER::str_ref
;
162 callStack
.push (context
);
164 context
.init ( biasedSubrs
[subr_num
], type
, subr_num
);
165 SUPER::str_ref
= context
.str_ref
;
168 void return_from_subr ()
170 if (unlikely (SUPER::str_ref
.in_error ()))
172 context
= callStack
.pop ();
173 SUPER::str_ref
= context
.str_ref
;
176 void determine_hintmask_size ()
180 vstem_count
+= SUPER::argStack
.get_count() / 2;
181 hintmask_size
= (hstem_count
+ vstem_count
+ 7) >> 3;
182 seen_hintmask
= true;
186 void set_endchar (bool endchar_flag_
) { endchar_flag
= endchar_flag_
; }
187 bool is_endchar () const { return endchar_flag
; }
189 const number_t
&get_x () const { return pt
.x
; }
190 const number_t
&get_y () const { return pt
.y
; }
191 const point_t
&get_pt () const { return pt
; }
193 void moveto (const point_t
&pt_
) { pt
= pt_
; }
196 call_context_t context
;
201 unsigned int hstem_count
;
202 unsigned int vstem_count
;
203 unsigned int hintmask_size
;
204 call_stack_t callStack
;
205 biased_subrs_t
<SUBRS
> globalSubrs
;
206 biased_subrs_t
<SUBRS
> localSubrs
;
211 typedef interp_env_t
<ARG
> SUPER
;
214 template <typename ENV
, typename PARAM
>
215 struct path_procs_null_t
217 static void rmoveto (ENV
&env
, PARAM
& param
) {}
218 static void hmoveto (ENV
&env
, PARAM
& param
) {}
219 static void vmoveto (ENV
&env
, PARAM
& param
) {}
220 static void rlineto (ENV
&env
, PARAM
& param
) {}
221 static void hlineto (ENV
&env
, PARAM
& param
) {}
222 static void vlineto (ENV
&env
, PARAM
& param
) {}
223 static void rrcurveto (ENV
&env
, PARAM
& param
) {}
224 static void rcurveline (ENV
&env
, PARAM
& param
) {}
225 static void rlinecurve (ENV
&env
, PARAM
& param
) {}
226 static void vvcurveto (ENV
&env
, PARAM
& param
) {}
227 static void hhcurveto (ENV
&env
, PARAM
& param
) {}
228 static void vhcurveto (ENV
&env
, PARAM
& param
) {}
229 static void hvcurveto (ENV
&env
, PARAM
& param
) {}
230 static void moveto (ENV
&env
, PARAM
& param
, const point_t
&pt
) {}
231 static void line (ENV
&env
, PARAM
& param
, const point_t
&pt1
) {}
232 static void curve (ENV
&env
, PARAM
& param
, const point_t
&pt1
, const point_t
&pt2
, const point_t
&pt3
) {}
233 static void hflex (ENV
&env
, PARAM
& param
) {}
234 static void flex (ENV
&env
, PARAM
& param
) {}
235 static void hflex1 (ENV
&env
, PARAM
& param
) {}
236 static void flex1 (ENV
&env
, PARAM
& param
) {}
239 template <typename ARG
, typename OPSET
, typename ENV
, typename PARAM
, typename PATH
=path_procs_null_t
<ENV
, PARAM
>>
240 struct cs_opset_t
: opset_t
<ARG
>
242 static void process_op (op_code_t op
, ENV
&env
, PARAM
& param
)
247 env
.return_from_subr ();
250 OPSET::check_width (op
, env
, param
);
251 env
.set_endchar (true);
252 OPSET::flush_args_and_op (op
, env
, param
);
256 env
.argStack
.push_fixed_from_substr (env
.str_ref
);
259 case OpCode_callsubr
:
260 env
.call_subr (env
.localSubrs
, CSType_LocalSubr
);
263 case OpCode_callgsubr
:
264 env
.call_subr (env
.globalSubrs
, CSType_GlobalSubr
);
269 OPSET::check_width (op
, env
, param
);
270 OPSET::process_hstem (op
, env
, param
);
274 OPSET::check_width (op
, env
, param
);
275 OPSET::process_vstem (op
, env
, param
);
277 case OpCode_hintmask
:
278 case OpCode_cntrmask
:
279 OPSET::check_width (op
, env
, param
);
280 OPSET::process_hintmask (op
, env
, param
);
283 OPSET::check_width (op
, env
, param
);
284 PATH::rmoveto (env
, param
);
285 OPSET::process_post_move (op
, env
, param
);
288 OPSET::check_width (op
, env
, param
);
289 PATH::hmoveto (env
, param
);
290 OPSET::process_post_move (op
, env
, param
);
293 OPSET::check_width (op
, env
, param
);
294 PATH::vmoveto (env
, param
);
295 OPSET::process_post_move (op
, env
, param
);
298 PATH::rlineto (env
, param
);
299 process_post_path (op
, env
, param
);
302 PATH::hlineto (env
, param
);
303 process_post_path (op
, env
, param
);
306 PATH::vlineto (env
, param
);
307 process_post_path (op
, env
, param
);
309 case OpCode_rrcurveto
:
310 PATH::rrcurveto (env
, param
);
311 process_post_path (op
, env
, param
);
313 case OpCode_rcurveline
:
314 PATH::rcurveline (env
, param
);
315 process_post_path (op
, env
, param
);
317 case OpCode_rlinecurve
:
318 PATH::rlinecurve (env
, param
);
319 process_post_path (op
, env
, param
);
321 case OpCode_vvcurveto
:
322 PATH::vvcurveto (env
, param
);
323 process_post_path (op
, env
, param
);
325 case OpCode_hhcurveto
:
326 PATH::hhcurveto (env
, param
);
327 process_post_path (op
, env
, param
);
329 case OpCode_vhcurveto
:
330 PATH::vhcurveto (env
, param
);
331 process_post_path (op
, env
, param
);
333 case OpCode_hvcurveto
:
334 PATH::hvcurveto (env
, param
);
335 process_post_path (op
, env
, param
);
339 PATH::hflex (env
, param
);
340 OPSET::process_post_flex (op
, env
, param
);
344 PATH::flex (env
, param
);
345 OPSET::process_post_flex (op
, env
, param
);
349 PATH::hflex1 (env
, param
);
350 OPSET::process_post_flex (op
, env
, param
);
354 PATH::flex1 (env
, param
);
355 OPSET::process_post_flex (op
, env
, param
);
359 SUPER::process_op (op
, env
);
364 static void process_hstem (op_code_t op
, ENV
&env
, PARAM
& param
)
366 env
.hstem_count
+= env
.argStack
.get_count () / 2;
367 OPSET::flush_args_and_op (op
, env
, param
);
370 static void process_vstem (op_code_t op
, ENV
&env
, PARAM
& param
)
372 env
.vstem_count
+= env
.argStack
.get_count () / 2;
373 OPSET::flush_args_and_op (op
, env
, param
);
376 static void process_hintmask (op_code_t op
, ENV
&env
, PARAM
& param
)
378 env
.determine_hintmask_size ();
379 if (likely (env
.str_ref
.avail (env
.hintmask_size
)))
381 OPSET::flush_hintmask (op
, env
, param
);
382 env
.str_ref
.inc (env
.hintmask_size
);
386 static void process_post_flex (op_code_t op
, ENV
&env
, PARAM
& param
)
388 OPSET::flush_args_and_op (op
, env
, param
);
391 static void check_width (op_code_t op
, ENV
&env
, PARAM
& param
)
394 static void process_post_move (op_code_t op
, ENV
&env
, PARAM
& param
)
396 if (!env
.seen_moveto
)
398 env
.determine_hintmask_size ();
399 env
.seen_moveto
= true;
401 OPSET::flush_args_and_op (op
, env
, param
);
404 static void process_post_path (op_code_t op
, ENV
&env
, PARAM
& param
)
406 OPSET::flush_args_and_op (op
, env
, param
);
409 static void flush_args_and_op (op_code_t op
, ENV
&env
, PARAM
& param
)
411 OPSET::flush_args (env
, param
);
412 OPSET::flush_op (op
, env
, param
);
415 static void flush_args (ENV
&env
, PARAM
& param
)
417 env
.pop_n_args (env
.argStack
.get_count ());
420 static void flush_op (op_code_t op
, ENV
&env
, PARAM
& param
)
424 static void flush_hintmask (op_code_t op
, ENV
&env
, PARAM
& param
)
426 OPSET::flush_args_and_op (op
, env
, param
);
429 static bool is_number_op (op_code_t op
)
433 case OpCode_shortint
:
435 case OpCode_TwoBytePosInt0
: case OpCode_TwoBytePosInt1
:
436 case OpCode_TwoBytePosInt2
: case OpCode_TwoBytePosInt3
:
437 case OpCode_TwoByteNegInt0
: case OpCode_TwoByteNegInt1
:
438 case OpCode_TwoByteNegInt2
: case OpCode_TwoByteNegInt3
:
443 return (OpCode_OneByteIntFirst
<= op
) && (op
<= OpCode_OneByteIntLast
);
448 typedef opset_t
<ARG
> SUPER
;
451 template <typename PATH
, typename ENV
, typename PARAM
>
454 static void rmoveto (ENV
&env
, PARAM
& param
)
456 point_t pt1
= env
.get_pt ();
457 const number_t
&dy
= env
.pop_arg ();
458 const number_t
&dx
= env
.pop_arg ();
460 PATH::moveto (env
, param
, pt1
);
463 static void hmoveto (ENV
&env
, PARAM
& param
)
465 point_t pt1
= env
.get_pt ();
466 pt1
.move_x (env
.pop_arg ());
467 PATH::moveto (env
, param
, pt1
);
470 static void vmoveto (ENV
&env
, PARAM
& param
)
472 point_t pt1
= env
.get_pt ();
473 pt1
.move_y (env
.pop_arg ());
474 PATH::moveto (env
, param
, pt1
);
477 static void rlineto (ENV
&env
, PARAM
& param
)
479 for (unsigned int i
= 0; i
+ 2 <= env
.argStack
.get_count (); i
+= 2)
481 point_t pt1
= env
.get_pt ();
482 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
483 PATH::line (env
, param
, pt1
);
487 static void hlineto (ENV
&env
, PARAM
& param
)
491 for (; i
+ 2 <= env
.argStack
.get_count (); i
+= 2)
494 pt1
.move_x (env
.eval_arg (i
));
495 PATH::line (env
, param
, pt1
);
496 pt1
.move_y (env
.eval_arg (i
+1));
497 PATH::line (env
, param
, pt1
);
499 if (i
< env
.argStack
.get_count ())
502 pt1
.move_x (env
.eval_arg (i
));
503 PATH::line (env
, param
, pt1
);
507 static void vlineto (ENV
&env
, PARAM
& param
)
511 for (; i
+ 2 <= env
.argStack
.get_count (); i
+= 2)
514 pt1
.move_y (env
.eval_arg (i
));
515 PATH::line (env
, param
, pt1
);
516 pt1
.move_x (env
.eval_arg (i
+1));
517 PATH::line (env
, param
, pt1
);
519 if (i
< env
.argStack
.get_count ())
522 pt1
.move_y (env
.eval_arg (i
));
523 PATH::line (env
, param
, pt1
);
527 static void rrcurveto (ENV
&env
, PARAM
& param
)
529 for (unsigned int i
= 0; i
+ 6 <= env
.argStack
.get_count (); i
+= 6)
531 point_t pt1
= env
.get_pt ();
532 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
534 pt2
.move (env
.eval_arg (i
+2), env
.eval_arg (i
+3));
536 pt3
.move (env
.eval_arg (i
+4), env
.eval_arg (i
+5));
537 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
541 static void rcurveline (ENV
&env
, PARAM
& param
)
543 unsigned int arg_count
= env
.argStack
.get_count ();
544 if (unlikely (arg_count
< 8))
548 unsigned int curve_limit
= arg_count
- 2;
549 for (; i
+ 6 <= curve_limit
; i
+= 6)
551 point_t pt1
= env
.get_pt ();
552 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
554 pt2
.move (env
.eval_arg (i
+2), env
.eval_arg (i
+3));
556 pt3
.move (env
.eval_arg (i
+4), env
.eval_arg (i
+5));
557 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
560 point_t pt1
= env
.get_pt ();
561 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
562 PATH::line (env
, param
, pt1
);
565 static void rlinecurve (ENV
&env
, PARAM
& param
)
567 unsigned int arg_count
= env
.argStack
.get_count ();
568 if (unlikely (arg_count
< 8))
572 unsigned int line_limit
= arg_count
- 6;
573 for (; i
+ 2 <= line_limit
; i
+= 2)
575 point_t pt1
= env
.get_pt ();
576 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
577 PATH::line (env
, param
, pt1
);
580 point_t pt1
= env
.get_pt ();
581 pt1
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
583 pt2
.move (env
.eval_arg (i
+2), env
.eval_arg (i
+3));
585 pt3
.move (env
.eval_arg (i
+4), env
.eval_arg (i
+5));
586 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
589 static void vvcurveto (ENV
&env
, PARAM
& param
)
592 point_t pt1
= env
.get_pt ();
593 if ((env
.argStack
.get_count () & 1) != 0)
594 pt1
.move_x (env
.eval_arg (i
++));
595 for (; i
+ 4 <= env
.argStack
.get_count (); i
+= 4)
597 pt1
.move_y (env
.eval_arg (i
));
599 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
601 pt3
.move_y (env
.eval_arg (i
+3));
602 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
607 static void hhcurveto (ENV
&env
, PARAM
& param
)
610 point_t pt1
= env
.get_pt ();
611 if ((env
.argStack
.get_count () & 1) != 0)
612 pt1
.move_y (env
.eval_arg (i
++));
613 for (; i
+ 4 <= env
.argStack
.get_count (); i
+= 4)
615 pt1
.move_x (env
.eval_arg (i
));
617 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
619 pt3
.move_x (env
.eval_arg (i
+3));
620 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
625 static void vhcurveto (ENV
&env
, PARAM
& param
)
627 point_t pt1
, pt2
, pt3
;
629 if ((env
.argStack
.get_count () % 8) >= 4)
631 point_t pt1
= env
.get_pt ();
632 pt1
.move_y (env
.eval_arg (i
));
634 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
636 pt3
.move_x (env
.eval_arg (i
+3));
639 for (; i
+ 8 <= env
.argStack
.get_count (); i
+= 8)
641 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
643 pt1
.move_x (env
.eval_arg (i
));
645 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
647 pt3
.move_y (env
.eval_arg (i
+3));
648 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
651 pt1
.move_y (env
.eval_arg (i
+4));
653 pt2
.move (env
.eval_arg (i
+5), env
.eval_arg (i
+6));
655 pt3
.move_x (env
.eval_arg (i
+7));
657 if (i
< env
.argStack
.get_count ())
658 pt3
.move_y (env
.eval_arg (i
));
659 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
663 for (; i
+ 8 <= env
.argStack
.get_count (); i
+= 8)
666 pt1
.move_y (env
.eval_arg (i
));
668 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
670 pt3
.move_x (env
.eval_arg (i
+3));
671 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
674 pt1
.move_x (env
.eval_arg (i
+4));
676 pt2
.move (env
.eval_arg (i
+5), env
.eval_arg (i
+6));
678 pt3
.move_y (env
.eval_arg (i
+7));
679 if ((env
.argStack
.get_count () - i
< 16) && ((env
.argStack
.get_count () & 1) != 0))
680 pt3
.move_x (env
.eval_arg (i
+8));
681 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
686 static void hvcurveto (ENV
&env
, PARAM
& param
)
688 point_t pt1
, pt2
, pt3
;
690 if ((env
.argStack
.get_count () % 8) >= 4)
692 point_t pt1
= env
.get_pt ();
693 pt1
.move_x (env
.eval_arg (i
));
695 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
697 pt3
.move_y (env
.eval_arg (i
+3));
700 for (; i
+ 8 <= env
.argStack
.get_count (); i
+= 8)
702 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
704 pt1
.move_y (env
.eval_arg (i
));
706 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
708 pt3
.move_x (env
.eval_arg (i
+3));
709 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
712 pt1
.move_x (env
.eval_arg (i
+4));
714 pt2
.move (env
.eval_arg (i
+5), env
.eval_arg (i
+6));
716 pt3
.move_y (env
.eval_arg (i
+7));
718 if (i
< env
.argStack
.get_count ())
719 pt3
.move_x (env
.eval_arg (i
));
720 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
724 for (; i
+ 8 <= env
.argStack
.get_count (); i
+= 8)
727 pt1
.move_x (env
.eval_arg (i
));
729 pt2
.move (env
.eval_arg (i
+1), env
.eval_arg (i
+2));
731 pt3
.move_y (env
.eval_arg (i
+3));
732 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
735 pt1
.move_y (env
.eval_arg (i
+4));
737 pt2
.move (env
.eval_arg (i
+5), env
.eval_arg (i
+6));
739 pt3
.move_x (env
.eval_arg (i
+7));
740 if ((env
.argStack
.get_count () - i
< 16) && ((env
.argStack
.get_count () & 1) != 0))
741 pt3
.move_y (env
.eval_arg (i
+8));
742 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
747 /* default actions to be overridden */
748 static void moveto (ENV
&env
, PARAM
& param
, const point_t
&pt
)
751 static void line (ENV
&env
, PARAM
& param
, const point_t
&pt1
)
752 { PATH::moveto (env
, param
, pt1
); }
754 static void curve (ENV
&env
, PARAM
& param
, const point_t
&pt1
, const point_t
&pt2
, const point_t
&pt3
)
755 { PATH::moveto (env
, param
, pt3
); }
757 static void hflex (ENV
&env
, PARAM
& param
)
759 if (likely (env
.argStack
.get_count () == 7))
761 point_t pt1
= env
.get_pt ();
762 pt1
.move_x (env
.eval_arg (0));
764 pt2
.move (env
.eval_arg (1), env
.eval_arg (2));
766 pt3
.move_x (env
.eval_arg (3));
768 pt4
.move_x (env
.eval_arg (4));
770 pt5
.move_x (env
.eval_arg (5));
773 pt6
.move_x (env
.eval_arg (6));
775 curve2 (env
, param
, pt1
, pt2
, pt3
, pt4
, pt5
, pt6
);
781 static void flex (ENV
&env
, PARAM
& param
)
783 if (likely (env
.argStack
.get_count () == 13))
785 point_t pt1
= env
.get_pt ();
786 pt1
.move (env
.eval_arg (0), env
.eval_arg (1));
788 pt2
.move (env
.eval_arg (2), env
.eval_arg (3));
790 pt3
.move (env
.eval_arg (4), env
.eval_arg (5));
792 pt4
.move (env
.eval_arg (6), env
.eval_arg (7));
794 pt5
.move (env
.eval_arg (8), env
.eval_arg (9));
796 pt6
.move (env
.eval_arg (10), env
.eval_arg (11));
798 curve2 (env
, param
, pt1
, pt2
, pt3
, pt4
, pt5
, pt6
);
804 static void hflex1 (ENV
&env
, PARAM
& param
)
806 if (likely (env
.argStack
.get_count () == 9))
808 point_t pt1
= env
.get_pt ();
809 pt1
.move (env
.eval_arg (0), env
.eval_arg (1));
811 pt2
.move (env
.eval_arg (2), env
.eval_arg (3));
813 pt3
.move_x (env
.eval_arg (4));
815 pt4
.move_x (env
.eval_arg (5));
817 pt5
.move (env
.eval_arg (6), env
.eval_arg (7));
819 pt6
.move_x (env
.eval_arg (8));
820 pt6
.y
= env
.get_pt ().y
;
822 curve2 (env
, param
, pt1
, pt2
, pt3
, pt4
, pt5
, pt6
);
828 static void flex1 (ENV
&env
, PARAM
& param
)
830 if (likely (env
.argStack
.get_count () == 11))
833 for (unsigned int i
= 0; i
< 10; i
+= 2)
834 d
.move (env
.eval_arg (i
), env
.eval_arg (i
+1));
836 point_t pt1
= env
.get_pt ();
837 pt1
.move (env
.eval_arg (0), env
.eval_arg (1));
839 pt2
.move (env
.eval_arg (2), env
.eval_arg (3));
841 pt3
.move (env
.eval_arg (4), env
.eval_arg (5));
843 pt4
.move (env
.eval_arg (6), env
.eval_arg (7));
845 pt5
.move (env
.eval_arg (8), env
.eval_arg (9));
848 if (fabs (d
.x
.to_real ()) > fabs (d
.y
.to_real ()))
850 pt6
.move_x (env
.eval_arg (10));
851 pt6
.y
= env
.get_pt ().y
;
855 pt6
.x
= env
.get_pt ().x
;
856 pt6
.move_y (env
.eval_arg (10));
859 curve2 (env
, param
, pt1
, pt2
, pt3
, pt4
, pt5
, pt6
);
866 static void curve2 (ENV
&env
, PARAM
& param
,
867 const point_t
&pt1
, const point_t
&pt2
, const point_t
&pt3
,
868 const point_t
&pt4
, const point_t
&pt5
, const point_t
&pt6
)
870 PATH::curve (env
, param
, pt1
, pt2
, pt3
);
871 PATH::curve (env
, param
, pt4
, pt5
, pt6
);
875 template <typename ENV
, typename OPSET
, typename PARAM
>
876 struct cs_interpreter_t
: interpreter_t
<ENV
>
878 cs_interpreter_t (ENV
& env_
) : interpreter_t
<ENV
> (env_
) {}
880 bool interpret (PARAM
& param
)
882 SUPER::env
.set_endchar (false);
884 unsigned max_ops
= HB_CFF_MAX_OPS
;
886 OPSET::process_op (SUPER::env
.fetch_op (), SUPER::env
, param
);
887 if (unlikely (SUPER::env
.in_error () || !--max_ops
))
889 SUPER::env
.set_error ();
892 if (SUPER::env
.is_endchar ())
900 typedef interpreter_t
<ENV
> SUPER
;
903 } /* namespace CFF */
905 #endif /* HB_CFF_INTERP_CS_COMMON_HH */