tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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 */