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