hb-cff-interp-common.hh (20035B)
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_COMMON_HH 27 #define HB_CFF_INTERP_COMMON_HH 28 29 extern HB_INTERNAL const unsigned char *endchar_str; 30 31 namespace CFF { 32 33 using namespace OT; 34 35 typedef unsigned int op_code_t; 36 37 38 /* === Dict operators === */ 39 40 /* One byte operators (0-31) */ 41 #define OpCode_version 0 /* CFF Top */ 42 #define OpCode_Notice 1 /* CFF Top */ 43 #define OpCode_FullName 2 /* CFF Top */ 44 #define OpCode_FamilyName 3 /* CFF Top */ 45 #define OpCode_Weight 4 /* CFF Top */ 46 #define OpCode_FontBBox 5 /* CFF Top */ 47 #define OpCode_BlueValues 6 /* CFF Private, CFF2 Private */ 48 #define OpCode_OtherBlues 7 /* CFF Private, CFF2 Private */ 49 #define OpCode_FamilyBlues 8 /* CFF Private, CFF2 Private */ 50 #define OpCode_FamilyOtherBlues 9 /* CFF Private, CFF2 Private */ 51 #define OpCode_StdHW 10 /* CFF Private, CFF2 Private */ 52 #define OpCode_StdVW 11 /* CFF Private, CFF2 Private */ 53 #define OpCode_escape 12 /* All. Shared with CS */ 54 #define OpCode_UniqueID 13 /* CFF Top */ 55 #define OpCode_XUID 14 /* CFF Top */ 56 #define OpCode_charset 15 /* CFF Top (0) */ 57 #define OpCode_Encoding 16 /* CFF Top (0) */ 58 #define OpCode_CharStrings 17 /* CFF Top, CFF2 Top */ 59 #define OpCode_Private 18 /* CFF Top, CFF2 FD */ 60 #define OpCode_Subrs 19 /* CFF Private, CFF2 Private */ 61 #define OpCode_defaultWidthX 20 /* CFF Private (0) */ 62 #define OpCode_nominalWidthX 21 /* CFF Private (0) */ 63 #define OpCode_vsindexdict 22 /* CFF2 Private/CS */ 64 #define OpCode_blenddict 23 /* CFF2 Private/CS */ 65 #define OpCode_vstore 24 /* CFF2 Top */ 66 #define OpCode_reserved25 25 67 #define OpCode_reserved26 26 68 #define OpCode_reserved27 27 69 70 /* Numbers */ 71 #define OpCode_shortint 28 /* 16-bit integer, All */ 72 #define OpCode_longintdict 29 /* 32-bit integer, All */ 73 #define OpCode_BCD 30 /* Real number, CFF2 Top/FD */ 74 #define OpCode_reserved31 31 75 76 /* 1-byte integers */ 77 #define OpCode_OneByteIntFirst 32 /* All. beginning of the range of first byte ints */ 78 #define OpCode_OneByteIntLast 246 /* All. ending of the range of first byte int */ 79 80 /* 2-byte integers */ 81 #define OpCode_TwoBytePosInt0 247 /* All. first byte of two byte positive int (+108 to +1131) */ 82 #define OpCode_TwoBytePosInt1 248 83 #define OpCode_TwoBytePosInt2 249 84 #define OpCode_TwoBytePosInt3 250 85 86 #define OpCode_TwoByteNegInt0 251 /* All. first byte of two byte negative int (-1131 to -108) */ 87 #define OpCode_TwoByteNegInt1 252 88 #define OpCode_TwoByteNegInt2 253 89 #define OpCode_TwoByteNegInt3 254 90 91 /* Two byte escape operators 12, (0-41) */ 92 #define OpCode_ESC_Base 256 93 #define Make_OpCode_ESC(byte2) ((op_code_t)(OpCode_ESC_Base + (byte2))) 94 95 inline op_code_t Unmake_OpCode_ESC (op_code_t op) { return (op_code_t)(op - OpCode_ESC_Base); } 96 inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; } 97 inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; } 98 99 #define OpCode_Copyright Make_OpCode_ESC(0) /* CFF Top */ 100 #define OpCode_isFixedPitch Make_OpCode_ESC(1) /* CFF Top (false) */ 101 #define OpCode_ItalicAngle Make_OpCode_ESC(2) /* CFF Top (0) */ 102 #define OpCode_UnderlinePosition Make_OpCode_ESC(3) /* CFF Top (-100) */ 103 #define OpCode_UnderlineThickness Make_OpCode_ESC(4) /* CFF Top (50) */ 104 #define OpCode_PaintType Make_OpCode_ESC(5) /* CFF Top (0) */ 105 #define OpCode_CharstringType Make_OpCode_ESC(6) /* CFF Top (2) */ 106 #define OpCode_FontMatrix Make_OpCode_ESC(7) /* CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/ 107 #define OpCode_StrokeWidth Make_OpCode_ESC(8) /* CFF Top (0) */ 108 #define OpCode_BlueScale Make_OpCode_ESC(9) /* CFF Private, CFF2 Private (0.039625) */ 109 #define OpCode_BlueShift Make_OpCode_ESC(10) /* CFF Private, CFF2 Private (7) */ 110 #define OpCode_BlueFuzz Make_OpCode_ESC(11) /* CFF Private, CFF2 Private (1) */ 111 #define OpCode_StemSnapH Make_OpCode_ESC(12) /* CFF Private, CFF2 Private */ 112 #define OpCode_StemSnapV Make_OpCode_ESC(13) /* CFF Private, CFF2 Private */ 113 #define OpCode_ForceBold Make_OpCode_ESC(14) /* CFF Private (false) */ 114 #define OpCode_reservedESC15 Make_OpCode_ESC(15) 115 #define OpCode_reservedESC16 Make_OpCode_ESC(16) 116 #define OpCode_LanguageGroup Make_OpCode_ESC(17) /* CFF Private, CFF2 Private (0) */ 117 #define OpCode_ExpansionFactor Make_OpCode_ESC(18) /* CFF Private, CFF2 Private (0.06) */ 118 #define OpCode_initialRandomSeed Make_OpCode_ESC(19) /* CFF Private (0) */ 119 #define OpCode_SyntheticBase Make_OpCode_ESC(20) /* CFF Top */ 120 #define OpCode_PostScript Make_OpCode_ESC(21) /* CFF Top */ 121 #define OpCode_BaseFontName Make_OpCode_ESC(22) /* CFF Top */ 122 #define OpCode_BaseFontBlend Make_OpCode_ESC(23) /* CFF Top */ 123 #define OpCode_reservedESC24 Make_OpCode_ESC(24) 124 #define OpCode_reservedESC25 Make_OpCode_ESC(25) 125 #define OpCode_reservedESC26 Make_OpCode_ESC(26) 126 #define OpCode_reservedESC27 Make_OpCode_ESC(27) 127 #define OpCode_reservedESC28 Make_OpCode_ESC(28) 128 #define OpCode_reservedESC29 Make_OpCode_ESC(29) 129 #define OpCode_ROS Make_OpCode_ESC(30) /* CFF Top_CID */ 130 #define OpCode_CIDFontVersion Make_OpCode_ESC(31) /* CFF Top_CID (0) */ 131 #define OpCode_CIDFontRevision Make_OpCode_ESC(32) /* CFF Top_CID (0) */ 132 #define OpCode_CIDFontType Make_OpCode_ESC(33) /* CFF Top_CID (0) */ 133 #define OpCode_CIDCount Make_OpCode_ESC(34) /* CFF Top_CID (8720) */ 134 #define OpCode_UIDBase Make_OpCode_ESC(35) /* CFF Top_CID */ 135 #define OpCode_FDArray Make_OpCode_ESC(36) /* CFF Top_CID, CFF2 Top */ 136 #define OpCode_FDSelect Make_OpCode_ESC(37) /* CFF Top_CID, CFF2 Top */ 137 #define OpCode_FontName Make_OpCode_ESC(38) /* CFF Top_CID */ 138 139 140 /* === CharString operators === */ 141 142 #define OpCode_hstem 1 /* CFF, CFF2 */ 143 #define OpCode_Reserved2 2 144 #define OpCode_vstem 3 /* CFF, CFF2 */ 145 #define OpCode_vmoveto 4 /* CFF, CFF2 */ 146 #define OpCode_rlineto 5 /* CFF, CFF2 */ 147 #define OpCode_hlineto 6 /* CFF, CFF2 */ 148 #define OpCode_vlineto 7 /* CFF, CFF2 */ 149 #define OpCode_rrcurveto 8 /* CFF, CFF2 */ 150 #define OpCode_Reserved9 9 151 #define OpCode_callsubr 10 /* CFF, CFF2 */ 152 #define OpCode_return 11 /* CFF */ 153 //#define OpCode_escape 12 /* CFF, CFF2 */ 154 #define OpCode_Reserved13 13 155 #define OpCode_endchar 14 /* CFF */ 156 #define OpCode_vsindexcs 15 /* CFF2 */ 157 #define OpCode_blendcs 16 /* CFF2 */ 158 #define OpCode_Reserved17 17 159 #define OpCode_hstemhm 18 /* CFF, CFF2 */ 160 #define OpCode_hintmask 19 /* CFF, CFF2 */ 161 #define OpCode_cntrmask 20 /* CFF, CFF2 */ 162 #define OpCode_rmoveto 21 /* CFF, CFF2 */ 163 #define OpCode_hmoveto 22 /* CFF, CFF2 */ 164 #define OpCode_vstemhm 23 /* CFF, CFF2 */ 165 #define OpCode_rcurveline 24 /* CFF, CFF2 */ 166 #define OpCode_rlinecurve 25 /* CFF, CFF2 */ 167 #define OpCode_vvcurveto 26 /* CFF, CFF2 */ 168 #define OpCode_hhcurveto 27 /* CFF, CFF2 */ 169 //#define OpCode_shortint 28 /* CFF, CFF2 */ 170 #define OpCode_callgsubr 29 /* CFF, CFF2 */ 171 #define OpCode_vhcurveto 30 /* CFF, CFF2 */ 172 #define OpCode_hvcurveto 31 /* CFF, CFF2 */ 173 174 #define OpCode_fixedcs 255 /* 32-bit fixed */ 175 176 /* Two byte escape operators 12, (0-41) */ 177 #define OpCode_dotsection Make_OpCode_ESC(0) /* CFF (obsoleted) */ 178 #define OpCode_ReservedESC1 Make_OpCode_ESC(1) 179 #define OpCode_ReservedESC2 Make_OpCode_ESC(2) 180 #define OpCode_and Make_OpCode_ESC(3) /* CFF */ 181 #define OpCode_or Make_OpCode_ESC(4) /* CFF */ 182 #define OpCode_not Make_OpCode_ESC(5) /* CFF */ 183 #define OpCode_ReservedESC6 Make_OpCode_ESC(6) 184 #define OpCode_ReservedESC7 Make_OpCode_ESC(7) 185 #define OpCode_ReservedESC8 Make_OpCode_ESC(8) 186 #define OpCode_abs Make_OpCode_ESC(9) /* CFF */ 187 #define OpCode_add Make_OpCode_ESC(10) /* CFF */ 188 #define OpCode_sub Make_OpCode_ESC(11) /* CFF */ 189 #define OpCode_div Make_OpCode_ESC(12) /* CFF */ 190 #define OpCode_ReservedESC13 Make_OpCode_ESC(13) 191 #define OpCode_neg Make_OpCode_ESC(14) /* CFF */ 192 #define OpCode_eq Make_OpCode_ESC(15) /* CFF */ 193 #define OpCode_ReservedESC16 Make_OpCode_ESC(16) 194 #define OpCode_ReservedESC17 Make_OpCode_ESC(17) 195 #define OpCode_drop Make_OpCode_ESC(18) /* CFF */ 196 #define OpCode_ReservedESC19 Make_OpCode_ESC(19) 197 #define OpCode_put Make_OpCode_ESC(20) /* CFF */ 198 #define OpCode_get Make_OpCode_ESC(21) /* CFF */ 199 #define OpCode_ifelse Make_OpCode_ESC(22) /* CFF */ 200 #define OpCode_random Make_OpCode_ESC(23) /* CFF */ 201 #define OpCode_mul Make_OpCode_ESC(24) /* CFF */ 202 //#define OpCode_reservedESC25 Make_OpCode_ESC(25) 203 #define OpCode_sqrt Make_OpCode_ESC(26) /* CFF */ 204 #define OpCode_dup Make_OpCode_ESC(27) /* CFF */ 205 #define OpCode_exch Make_OpCode_ESC(28) /* CFF */ 206 #define OpCode_index Make_OpCode_ESC(29) /* CFF */ 207 #define OpCode_roll Make_OpCode_ESC(30) /* CFF */ 208 #define OpCode_reservedESC31 Make_OpCode_ESC(31) 209 #define OpCode_reservedESC32 Make_OpCode_ESC(32) 210 #define OpCode_reservedESC33 Make_OpCode_ESC(33) 211 #define OpCode_hflex Make_OpCode_ESC(34) /* CFF, CFF2 */ 212 #define OpCode_flex Make_OpCode_ESC(35) /* CFF, CFF2 */ 213 #define OpCode_hflex1 Make_OpCode_ESC(36) /* CFF, CFF2 */ 214 #define OpCode_flex1 Make_OpCode_ESC(37) /* CFF, CFF2 */ 215 216 217 #define OpCode_Invalid 0xFFFFu 218 219 220 struct number_t 221 { 222 void set_int (int v) { value = v; } 223 int to_int () const { return value; } 224 225 void set_fixed (int32_t v) { value = v / 65536.0; } 226 int32_t to_fixed () const { return value * 65536.0; } 227 228 void set_real (double v) { value = v; } 229 double to_real () const { return value; } 230 231 bool in_int_range () const 232 { return ((double) (int16_t) to_int () == value); } 233 234 bool operator > (const number_t &n) const { return value > n.to_real (); } 235 bool operator < (const number_t &n) const { return n > *this; } 236 bool operator >= (const number_t &n) const { return !(*this < n); } 237 bool operator <= (const number_t &n) const { return !(*this > n); } 238 239 const number_t &operator += (const number_t &n) 240 { 241 set_real (to_real () + n.to_real ()); 242 243 return *this; 244 } 245 246 protected: 247 double value = 0.; 248 }; 249 250 /* byte string */ 251 struct UnsizedByteStr : UnsizedArrayOf <HBUINT8> 252 { 253 hb_ubytes_t as_ubytes (unsigned l) const 254 { return hb_ubytes_t ((const unsigned char *) this, l); } 255 256 // encode 2-byte int (Dict/CharString) or 4-byte int (Dict) 257 template <typename T, typename V> 258 static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value) 259 { 260 TRACE_SERIALIZE (this); 261 262 HBUINT8 *p = c->allocate_size<HBUINT8> (1); 263 if (unlikely (!p)) return_trace (false); 264 *p = intOp; 265 266 T *ip = c->allocate_size<T> (T::static_size); 267 if (unlikely (!ip)) return_trace (false); 268 return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW)); 269 } 270 271 template <typename V> 272 static bool serialize_int4 (hb_serialize_context_t *c, V value) 273 { return serialize_int<HBINT32> (c, OpCode_longintdict, value); } 274 275 template <typename V> 276 static bool serialize_int2 (hb_serialize_context_t *c, V value) 277 { return serialize_int<HBINT16> (c, OpCode_shortint, value); } 278 279 /* Defining null_size allows a Null object may be created. Should be safe because: 280 * A descendent struct Dict uses a Null pointer to indicate a missing table, 281 * checked before access. 282 */ 283 DEFINE_SIZE_MIN(0); 284 }; 285 286 /* A byte string associated with the current offset and an error condition */ 287 struct byte_str_ref_t 288 { 289 byte_str_ref_t () 290 : str () {} 291 292 byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0) 293 : str (str_) { set_offset (offset_); } 294 295 void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0) 296 { 297 str = str_; 298 set_offset (offset_); 299 } 300 301 const unsigned char& operator [] (int i) { 302 if (unlikely ((unsigned int) (get_offset () + i) >= str.length)) 303 { 304 set_error (); 305 return Null (unsigned char); 306 } 307 return str.arrayZ[get_offset () + i]; 308 } 309 310 unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; } 311 312 /* Conversion to hb_ubytes_t */ 313 operator hb_ubytes_t () const { return str.sub_array (get_offset ()); } 314 315 hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const 316 { return str.sub_array (offset_, len_); } 317 318 bool avail (unsigned int count=1) const 319 { return get_offset () + count <= str.length; } 320 void inc (unsigned int count=1) 321 { 322 /* Automatically puts us in error if count is out-of-range. */ 323 set_offset (get_offset () + count); 324 } 325 326 /* We (ab)use ubytes backwards_length as a cursor (called offset), 327 * as well as to store error condition. */ 328 329 unsigned get_offset () const { return str.backwards_length; } 330 void set_offset (unsigned offset) { str.backwards_length = offset; } 331 332 void set_error () { str.backwards_length = str.length + 1; } 333 bool in_error () const { return str.backwards_length > str.length; } 334 335 unsigned total_size () const { return str.length; } 336 337 protected: 338 hb_ubytes_t str; 339 }; 340 341 /* stack */ 342 template <typename ELEM, int LIMIT> 343 struct cff_stack_t 344 { 345 ELEM& operator [] (unsigned int i) 346 { 347 if (unlikely (i >= count)) 348 { 349 set_error (); 350 return Crap (ELEM); 351 } 352 return elements[i]; 353 } 354 355 void push (const ELEM &v) 356 { 357 if (likely (count < LIMIT)) 358 elements[count++] = v; 359 else 360 set_error (); 361 } 362 ELEM &push () 363 { 364 if (likely (count < LIMIT)) 365 return elements[count++]; 366 else 367 { 368 set_error (); 369 return Crap (ELEM); 370 } 371 } 372 373 ELEM& pop () 374 { 375 if (likely (count > 0)) 376 return elements[--count]; 377 else 378 { 379 set_error (); 380 return Crap (ELEM); 381 } 382 } 383 void pop (unsigned int n) 384 { 385 if (likely (count >= n)) 386 count -= n; 387 else 388 set_error (); 389 } 390 391 const ELEM& peek () 392 { 393 if (unlikely (count == 0)) 394 { 395 set_error (); 396 return Null (ELEM); 397 } 398 return elements[count - 1]; 399 } 400 401 void unpop () 402 { 403 if (likely (count < LIMIT)) 404 count++; 405 else 406 set_error (); 407 } 408 409 void clear () { count = 0; } 410 411 bool in_error () const { return (error); } 412 void set_error () { error = true; } 413 414 unsigned int get_count () const { return count; } 415 bool is_empty () const { return !count; } 416 417 hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const 418 { return hb_array_t<const ELEM> (elements).sub_array (start, length); } 419 420 private: 421 bool error = false; 422 unsigned int count = 0; 423 ELEM elements[LIMIT]; 424 }; 425 426 /* argument stack */ 427 template <typename ARG=number_t> 428 struct arg_stack_t : cff_stack_t<ARG, 513> 429 { 430 void push_int (int v) 431 { 432 ARG &n = S::push (); 433 n.set_int (v); 434 } 435 436 void push_fixed (int32_t v) 437 { 438 ARG &n = S::push (); 439 n.set_fixed (v); 440 } 441 442 void push_real (double v) 443 { 444 ARG &n = S::push (); 445 n.set_real (v); 446 } 447 448 ARG& pop_num () { return this->pop (); } 449 450 int pop_int () { return this->pop ().to_int (); } 451 452 unsigned int pop_uint () 453 { 454 int i = pop_int (); 455 if (unlikely (i < 0)) 456 { 457 i = 0; 458 S::set_error (); 459 } 460 return (unsigned) i; 461 } 462 463 void push_longint_from_substr (byte_str_ref_t& str_ref) 464 { 465 push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3])); 466 str_ref.inc (4); 467 } 468 469 bool push_fixed_from_substr (byte_str_ref_t& str_ref) 470 { 471 if (unlikely (!str_ref.avail (4))) 472 return false; 473 push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]); 474 str_ref.inc (4); 475 return true; 476 } 477 478 private: 479 typedef cff_stack_t<ARG, 513> S; 480 }; 481 482 /* an operator prefixed by its operands in a byte string */ 483 struct op_str_t 484 { 485 /* This used to have a hb_ubytes_t. Using a pointer and length 486 * in a particular order, saves 8 bytes in this struct and more 487 * in our parsed_cs_op_t subclass. */ 488 489 const unsigned char *ptr = nullptr; 490 491 op_code_t op = OpCode_Invalid; 492 493 uint8_t length = 0; 494 }; 495 496 /* base of OP_SERIALIZER */ 497 struct op_serializer_t 498 { 499 protected: 500 bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const 501 { 502 TRACE_SERIALIZE (this); 503 504 unsigned char *d = c->allocate_size<unsigned char> (opstr.length); 505 if (unlikely (!d)) return_trace (false); 506 /* Faster than hb_memcpy for small strings. */ 507 for (unsigned i = 0; i < opstr.length; i++) 508 d[i] = opstr.ptr[i]; 509 return_trace (true); 510 } 511 }; 512 513 template <typename VAL> 514 struct parsed_values_t 515 { 516 void init () 517 { 518 opStart = 0; 519 values.init (); 520 } 521 void fini () { values.fini (); } 522 523 void alloc (unsigned n) 524 { 525 values.alloc_exact (n); 526 } 527 528 void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t (), const VAL &v = VAL ()) 529 { 530 VAL *val = values.push (v); 531 val->op = op; 532 auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart); 533 val->ptr = arr.arrayZ; 534 val->length = arr.length; 535 opStart = str_ref.get_offset (); 536 } 537 538 bool has_op (op_code_t op) const 539 { 540 for (const auto& v : values) 541 if (v.op == op) return true; 542 return false; 543 } 544 545 unsigned get_count () const { return values.length; } 546 const VAL &operator [] (unsigned int i) const { return values[i]; } 547 548 unsigned int opStart; 549 hb_vector_t<VAL> values; 550 }; 551 552 template <typename ARG=number_t> 553 struct interp_env_t 554 { 555 interp_env_t () {} 556 interp_env_t (const hb_ubytes_t &str_) 557 { 558 str_ref.reset (str_); 559 } 560 bool in_error () const 561 { return str_ref.in_error () || argStack.in_error (); } 562 563 void set_error () { str_ref.set_error (); } 564 565 op_code_t fetch_op () 566 { 567 op_code_t op = OpCode_Invalid; 568 if (unlikely (!str_ref.avail ())) 569 return OpCode_Invalid; 570 op = (op_code_t) str_ref.head_unchecked (); 571 str_ref.inc (); 572 if (op == OpCode_escape) { 573 if (unlikely (!str_ref.avail ())) 574 return OpCode_Invalid; 575 op = Make_OpCode_ESC (str_ref.head_unchecked ()); 576 str_ref.inc (); 577 } 578 return op; 579 } 580 581 const ARG& eval_arg (unsigned int i) { return argStack[i]; } 582 583 ARG& pop_arg () { return argStack.pop (); } 584 void pop_n_args (unsigned int n) { argStack.pop (n); } 585 586 void clear_args () { pop_n_args (argStack.get_count ()); } 587 588 byte_str_ref_t 589 str_ref; 590 arg_stack_t<ARG> 591 argStack; 592 }; 593 594 using num_interp_env_t = interp_env_t<>; 595 596 template <typename ARG=number_t> 597 struct opset_t 598 { 599 static void process_op (op_code_t op, interp_env_t<ARG>& env) 600 { 601 switch (op) { 602 case OpCode_shortint: 603 env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1])); 604 env.str_ref.inc (2); 605 break; 606 607 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1: 608 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3: 609 env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108)); 610 env.str_ref.inc (); 611 break; 612 613 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1: 614 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3: 615 env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108)); 616 env.str_ref.inc (); 617 break; 618 619 default: 620 /* 1-byte integer */ 621 if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast))) 622 { 623 env.argStack.push_int ((int)op - 139); 624 } else { 625 /* invalid unknown operator */ 626 env.clear_args (); 627 } 628 break; 629 } 630 } 631 }; 632 633 template <typename ENV> 634 struct interpreter_t 635 { 636 interpreter_t (ENV& env_) : env (env_) {} 637 ENV& env; 638 }; 639 640 } /* namespace CFF */ 641 642 #endif /* HB_CFF_INTERP_COMMON_HH */