blob: 98b308aa0d8ade5de3f403b131fdf5e29eeb0283 [file] [log] [blame]
Michiharu Ariza633ce882018-08-15 12:00:19 -07001/*
Michiharu Ariza0dfa5842018-11-12 08:47:07 -08002 * Copyright © 2018 Adobe Inc.
Michiharu Ariza633ce882018-08-15 12:00:19 -07003 *
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 */
Michiharu Ariza1d1afdd2018-08-29 13:36:39 -070026#ifndef HB_CFF_INTERP_COMMON_HH
27#define HB_CFF_INTERP_COMMON_HH
Michiharu Ariza633ce882018-08-15 12:00:19 -070028
Michiharu Ariza633ce882018-08-15 12:00:19 -070029namespace CFF {
30
31using namespace OT;
32
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -080033typedef unsigned int op_code_t;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050034
35
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070036/* === Dict operators === */
Michiharu Ariza633ce882018-08-15 12:00:19 -070037
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070038/* One byte operators (0-31) */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050039#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
Michiharu Ariza633ce882018-08-15 12:00:19 -070067
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070068/* Numbers */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050069#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
Michiharu Ariza633ce882018-08-15 12:00:19 -070073
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070074/* 1-byte integers */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050075#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 */
Michiharu Ariza633ce882018-08-15 12:00:19 -070077
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070078/* 2-byte integers */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050079#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
Michiharu Ariza633ce882018-08-15 12:00:19 -070083
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050084#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
Michiharu Ariza633ce882018-08-15 12:00:19 -070088
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -070089/* Two byte escape operators 12, (0-41) */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050090#define OpCode_ESC_Base 256
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -080091#define Make_OpCode_ESC(byte2) ((op_code_t)(OpCode_ESC_Base + (byte2)))
Michiharu Ariza633ce882018-08-15 12:00:19 -070092
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -080093inline op_code_t Unmake_OpCode_ESC (op_code_t op) { return (op_code_t)(op - OpCode_ESC_Base); }
94inline bool Is_OpCode_ESC (op_code_t op) { return op >= OpCode_ESC_Base; }
95inline unsigned int OpCode_Size (op_code_t op) { return Is_OpCode_ESC (op) ? 2: 1; }
Michiharu Ariza633ce882018-08-15 12:00:19 -070096
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050097#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 */
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -0700136
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -0700137
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500138/* === CharString operators === */
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -0700139
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500140#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 */
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -0700173
174/* Two byte escape operators 12, (0-41) */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500175#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 */
Michiharu Arizaeed7e6b2018-10-02 13:45:14 -0700213
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500214
215#define OpCode_Invalid 0xFFFFu
216
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700217
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800218struct number_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700219{
Ebrahim Byagowi5179b962019-10-08 11:09:12 +0330220 void set_int (int v) { value = v; }
221 int to_int () const { return value; }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330222
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330223 void set_fixed (int32_t v) { value = v / 65536.0; }
Ebrahim Byagowi5179b962019-10-08 11:09:12 +0330224 int32_t to_fixed () const { return value * 65536.0; }
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700225
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430226 void set_real (double v) { value = v; }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330227 double to_real () const { return value; }
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700228
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330229 bool in_int_range () const
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330230 { return ((double) (int16_t) to_int () == value); }
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700231
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430232 bool operator > (const number_t &n) const { return value > n.to_real (); }
233 bool operator < (const number_t &n) const { return n > *this; }
234 bool operator >= (const number_t &n) const { return !(*this < n); }
235 bool operator <= (const number_t &n) const { return !(*this > n); }
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700236
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800237 const number_t &operator += (const number_t &n)
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700238 {
Michiharu Ariza9af33d72018-12-03 14:48:46 -0800239 set_real (to_real () + n.to_real ());
Michiharu Arizab51418f2018-10-08 15:05:36 -0700240
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700241 return *this;
242 }
243
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330244 protected:
Behdad Esfahbod8d24ac22022-01-18 13:14:42 -0700245 double value = 0.;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700246};
247
248/* byte string */
249struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
250{
Behdad Esfahbodfe1d85a2022-05-09 16:04:52 -0600251 hb_ubytes_t as_ubytes (unsigned l) const
252 { return hb_ubytes_t ((const unsigned char *) this, l); }
253
Michiharu Ariza633ce882018-08-15 12:00:19 -0700254 // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
ariza002f0e22020-02-27 17:34:26 -0800255 template <typename T, typename V>
256 static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700257 {
258 TRACE_SERIALIZE (this);
259
Michiharu Ariza633ce882018-08-15 12:00:19 -0700260 HBUINT8 *p = c->allocate_size<HBUINT8> (1);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430261 if (unlikely (!p)) return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700262 *p = intOp;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700263
ariza002f0e22020-02-27 17:34:26 -0800264 T *ip = c->allocate_size<T> (T::static_size);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430265 if (unlikely (!ip)) return_trace (false);
Garret Riegerb14475d2021-03-18 10:51:26 -0700266 return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW));
Michiharu Ariza633ce882018-08-15 12:00:19 -0700267 }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500268
ariza002f0e22020-02-27 17:34:26 -0800269 template <typename V>
270 static bool serialize_int4 (hb_serialize_context_t *c, V value)
271 { return serialize_int<HBINT32> (c, OpCode_longintdict, value); }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500272
ariza002f0e22020-02-27 17:34:26 -0800273 template <typename V>
274 static bool serialize_int2 (hb_serialize_context_t *c, V value)
275 { return serialize_int<HBINT16> (c, OpCode_shortint, value); }
Michiharu Ariza471db3a2018-11-28 17:06:11 -0800276
277 /* Defining null_size allows a Null object may be created. Should be safe because:
278 * A descendent struct Dict uses a Null pointer to indicate a missing table,
279 * checked before access.
Michiharu Ariza471db3a2018-11-28 17:06:11 -0800280 */
281 DEFINE_SIZE_MIN(0);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700282};
283
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800284/* A byte string associated with the current offset and an error condition */
285struct byte_str_ref_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700286{
Behdad Esfahbodf66415c2022-11-21 09:39:27 -0700287 byte_str_ref_t ()
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700288 : str () {}
Michiharu Ariza633ce882018-08-15 12:00:19 -0700289
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600290 byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0)
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700291 : str (str_) { set_offset (offset_); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700292
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600293 void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700294 {
295 str = str_;
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700296 set_offset (offset_);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700297 }
298
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800299 const unsigned char& operator [] (int i) {
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700300 if (unlikely ((unsigned int) (get_offset () + i) >= str.length))
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700301 {
302 set_error ();
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430303 return Null (unsigned char);
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700304 }
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700305 return str[get_offset () + i];
Michiharu Ariza633ce882018-08-15 12:00:19 -0700306 }
307
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600308 /* Conversion to hb_ubytes_t */
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700309 operator hb_ubytes_t () const { return str.sub_array (get_offset ()); }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800310
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600311 hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const
Behdad Esfahbodfe1d85a2022-05-09 16:04:52 -0600312 { return str.sub_array (offset_, len_); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700313
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330314 bool avail (unsigned int count=1) const
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700315 { return get_offset () + count <= str.length; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330316 void inc (unsigned int count=1)
Michiharu Ariza6708c552018-12-05 12:51:18 -0800317 {
Behdad Esfahboda81ec9b2022-11-21 14:03:28 -0700318 /* Automatically puts us in error if count is out-of-range. */
319 set_offset (get_offset () + count);
Michiharu Ariza6708c552018-12-05 12:51:18 -0800320 }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700321
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700322 /* We (ab)use ubytes backwards_length as a cursor (called offset),
323 * as well as to store error condition. */
Behdad Esfahbod7a394642022-11-21 09:48:54 -0700324
Behdad Esfahbodb51ab1a2022-11-21 10:27:07 -0700325 unsigned get_offset () const { return str.backwards_length; }
326 void set_offset (unsigned offset) { str.backwards_length = offset; }
327
328 void set_error () { str.backwards_length = str.length + 1; }
329 bool in_error () const { return str.backwards_length > str.length; }
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700330
Behdad Esfahbod7a394642022-11-21 09:48:54 -0700331 protected:
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600332 hb_ubytes_t str;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700333};
334
Behdad Esfahbodc941ece2022-05-09 16:20:22 -0600335using byte_str_array_t = hb_vector_t<hb_ubytes_t>;
Michiharu Arizad56e3382018-10-31 22:30:34 -0700336
Michiharu Ariza633ce882018-08-15 12:00:19 -0700337/* stack */
338template <typename ELEM, int LIMIT>
Ebrahim Byagowi9fea6b42019-07-05 18:46:41 +0430339struct cff_stack_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700340{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330341 ELEM& operator [] (unsigned int i)
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700342 {
Behdad Esfahbod6106ef82022-05-09 18:12:09 -0600343 if (unlikely (i >= count))
344 {
345 set_error ();
346 return Crap (ELEM);
347 }
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700348 return elements[i];
349 }
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700350
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330351 void push (const ELEM &v)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700352 {
Behdad Esfahbod8c616a62022-05-09 17:49:54 -0600353 if (likely (count < LIMIT))
Michiharu Ariza968168b2018-08-31 13:28:16 -0700354 elements[count++] = v;
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700355 else
356 set_error ();
Michiharu Ariza633ce882018-08-15 12:00:19 -0700357 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330358 ELEM &push ()
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700359 {
Behdad Esfahbod8c616a62022-05-09 17:49:54 -0600360 if (likely (count < LIMIT))
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700361 return elements[count++];
362 else
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700363 {
364 set_error ();
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430365 return Crap (ELEM);
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700366 }
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700367 }
368
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330369 ELEM& pop ()
Michiharu Ariza633ce882018-08-15 12:00:19 -0700370 {
Michiharu Ariza968168b2018-08-31 13:28:16 -0700371 if (likely (count > 0))
372 return elements[--count];
Michiharu Ariza633ce882018-08-15 12:00:19 -0700373 else
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700374 {
375 set_error ();
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430376 return Crap (ELEM);
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700377 }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700378 }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330379 void pop (unsigned int n)
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700380 {
381 if (likely (count >= n))
382 count -= n;
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700383 else
384 set_error ();
Michiharu Arizac0c85b82018-09-17 11:14:56 -0700385 }
386
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330387 const ELEM& peek ()
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700388 {
Behdad Esfahbod1b14d2f2022-05-09 18:15:31 -0600389 if (unlikely (count == 0))
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700390 {
391 set_error ();
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430392 return Null (ELEM);
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700393 }
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430394 return elements[count - 1];
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700395 }
396
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330397 void unpop ()
Michiharu Ariza633ce882018-08-15 12:00:19 -0700398 {
Behdad Esfahbod8c616a62022-05-09 17:49:54 -0600399 if (likely (count < LIMIT))
Michiharu Ariza968168b2018-08-31 13:28:16 -0700400 count++;
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700401 else
402 set_error ();
Michiharu Ariza633ce882018-08-15 12:00:19 -0700403 }
404
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330405 void clear () { count = 0; }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700406
Behdad Esfahbod8c616a62022-05-09 17:49:54 -0600407 bool in_error () const { return (error); }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330408 void set_error () { error = true; }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700409
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330410 unsigned int get_count () const { return count; }
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430411 bool is_empty () const { return !count; }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700412
Behdad Esfahbod0a424102022-05-10 12:05:19 -0600413 hb_array_t<const ELEM> sub_array (unsigned start, unsigned length) const
414 { return hb_array_t<const ELEM> (elements).sub_array (start, length); }
Behdad Esfahbod6106ef82022-05-09 18:12:09 -0600415
416 private:
Behdad Esfahbodbff78e62022-05-10 16:33:37 -0600417 bool error = false;
418 unsigned int count = 0;
Behdad Esfahbod8c616a62022-05-09 17:49:54 -0600419 ELEM elements[LIMIT];
Michiharu Ariza633ce882018-08-15 12:00:19 -0700420};
421
422/* argument stack */
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800423template <typename ARG=number_t>
Ebrahim Byagowi9fea6b42019-07-05 18:46:41 +0430424struct arg_stack_t : cff_stack_t<ARG, 513>
Michiharu Ariza633ce882018-08-15 12:00:19 -0700425{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330426 void push_int (int v)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700427 {
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700428 ARG &n = S::push ();
Michiharu Ariza633ce882018-08-15 12:00:19 -0700429 n.set_int (v);
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700430 }
431
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330432 void push_fixed (int32_t v)
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700433 {
434 ARG &n = S::push ();
435 n.set_fixed (v);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700436 }
437
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330438 void push_real (double v)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700439 {
Michiharu Arizaf2d299b2018-09-04 10:25:21 -0700440 ARG &n = S::push ();
Michiharu Ariza633ce882018-08-15 12:00:19 -0700441 n.set_real (v);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700442 }
443
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330444 ARG& pop_num () { return this->pop (); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700445
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330446 int pop_int () { return this->pop ().to_int (); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700447
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330448 unsigned int pop_uint ()
Michiharu Ariza633ce882018-08-15 12:00:19 -0700449 {
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330450 int i = pop_int ();
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700451 if (unlikely (i < 0))
452 {
453 i = 0;
454 S::set_error ();
455 }
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430456 return (unsigned) i;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700457 }
458
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800459 void push_longint_from_substr (byte_str_ref_t& str_ref)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700460 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800461 push_int ((str_ref[0] << 24) | (str_ref[1] << 16) | (str_ref[2] << 8) | (str_ref[3]));
462 str_ref.inc (4);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700463 }
464
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800465 bool push_fixed_from_substr (byte_str_ref_t& str_ref)
Michiharu Ariza27c32d82018-08-22 11:36:39 -0700466 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800467 if (unlikely (!str_ref.avail (4)))
Michiharu Ariza27c32d82018-08-22 11:36:39 -0700468 return false;
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800469 push_fixed ((int32_t)*(const HBUINT32*)&str_ref[0]);
470 str_ref.inc (4);
Michiharu Ariza27c32d82018-08-22 11:36:39 -0700471 return true;
472 }
473
Michiharu Arizafcf17782018-08-31 16:28:47 -0700474 private:
Ebrahim Byagowi9fea6b42019-07-05 18:46:41 +0430475 typedef cff_stack_t<ARG, 513> S;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700476};
477
478/* an operator prefixed by its operands in a byte string */
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800479struct op_str_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700480{
Behdad Esfahbod8aa54aa2022-05-09 16:09:56 -0600481 hb_ubytes_t str;
Behdad Esfahbod602e0ca2022-05-16 10:14:34 -0600482 op_code_t op;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700483};
484
485/* base of OP_SERIALIZER */
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800486struct op_serializer_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700487{
488 protected:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800489 bool copy_opstr (hb_serialize_context_t *c, const op_str_t& opstr) const
Michiharu Ariza633ce882018-08-15 12:00:19 -0700490 {
491 TRACE_SERIALIZE (this);
492
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800493 HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430494 if (unlikely (!d)) return_trace (false);
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800495 memcpy (d, &opstr.str[0], opstr.str.length);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700496 return_trace (true);
497 }
498};
499
Michiharu Arizad56e3382018-10-31 22:30:34 -0700500template <typename VAL>
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800501struct parsed_values_t
Michiharu Arizad56e3382018-10-31 22:30:34 -0700502{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330503 void init ()
Michiharu Arizad56e3382018-10-31 22:30:34 -0700504 {
505 opStart = 0;
506 values.init ();
507 }
Behdad Esfahbod6ef83c22022-01-18 13:08:34 -0700508 void fini () { values.fini (); }
Michiharu Arizad56e3382018-10-31 22:30:34 -0700509
Behdad Esfahbodf0853792022-05-11 12:10:03 -0600510 void alloc (unsigned n)
511 {
512 values.alloc (n);
513 }
514
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800515 void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ())
Michiharu Arizad56e3382018-10-31 22:30:34 -0700516 {
517 VAL *val = values.push ();
518 val->op = op;
Behdad Esfahbod7a394642022-11-21 09:48:54 -0700519 val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
520 opStart = str_ref.get_offset ();
Michiharu Arizad56e3382018-10-31 22:30:34 -0700521 }
522
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800523 void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v)
Michiharu Arizad56e3382018-10-31 22:30:34 -0700524 {
525 VAL *val = values.push (v);
526 val->op = op;
Behdad Esfahbod7a394642022-11-21 09:48:54 -0700527 val->str = str_ref.sub_array (opStart, str_ref.get_offset () - opStart);
528 opStart = str_ref.get_offset ();
Michiharu Arizad56e3382018-10-31 22:30:34 -0700529 }
530
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800531 bool has_op (op_code_t op) const
Michiharu Arizad56e3382018-10-31 22:30:34 -0700532 {
Behdad Esfahbodacdab172022-05-13 14:14:36 -0600533 for (const auto& v : values)
534 if (v.op == op) return true;
Michiharu Arizad56e3382018-10-31 22:30:34 -0700535 return false;
536 }
537
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500538 unsigned get_count () const { return values.length; }
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430539 const VAL &get_value (unsigned int i) const { return values[i]; }
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330540 const VAL &operator [] (unsigned int i) const { return get_value (i); }
Michiharu Arizad56e3382018-10-31 22:30:34 -0700541
542 unsigned int opStart;
543 hb_vector_t<VAL> values;
544};
545
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800546template <typename ARG=number_t>
547struct interp_env_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700548{
Behdad Esfahbodbff78e62022-05-10 16:33:37 -0600549 interp_env_t () {}
550 interp_env_t (const hb_ubytes_t &str_)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700551 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800552 str_ref.reset (str_);
Michiharu Ariza633ce882018-08-15 12:00:19 -0700553 }
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330554 bool in_error () const
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800555 { return error || str_ref.in_error () || argStack.in_error (); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700556
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330557 void set_error () { error = true; }
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700558
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800559 op_code_t fetch_op ()
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700560 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800561 op_code_t op = OpCode_Invalid;
562 if (unlikely (!str_ref.avail ()))
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700563 return OpCode_Invalid;
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800564 op = (op_code_t)(unsigned char)str_ref[0];
Behdad Esfahbod6905d362022-11-21 10:51:33 -0700565 str_ref.inc ();
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700566 if (op == OpCode_escape) {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800567 if (unlikely (!str_ref.avail ()))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500568 return OpCode_Invalid;
Behdad Esfahbod6905d362022-11-21 10:51:33 -0700569 op = Make_OpCode_ESC(str_ref[0]);
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800570 str_ref.inc ();
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700571 }
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700572 return op;
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700573 }
574
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430575 const ARG& eval_arg (unsigned int i) { return argStack[i]; }
Michiharu Arizab51418f2018-10-08 15:05:36 -0700576
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430577 ARG& pop_arg () { return argStack.pop (); }
578 void pop_n_args (unsigned int n) { argStack.pop (n); }
Michiharu Arizab51418f2018-10-08 15:05:36 -0700579
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430580 void clear_args () { pop_n_args (argStack.get_count ()); }
Michiharu Ariza968168b2018-08-31 13:28:16 -0700581
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430582 byte_str_ref_t
583 str_ref;
584 arg_stack_t<ARG>
585 argStack;
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700586 protected:
Behdad Esfahbodbff78e62022-05-10 16:33:37 -0600587 bool error = false;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700588};
589
Behdad Esfahbodbff78e62022-05-10 16:33:37 -0600590using num_interp_env_t = interp_env_t<>;
Michiharu Arizafcf17782018-08-31 16:28:47 -0700591
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800592template <typename ARG=number_t>
593struct opset_t
Michiharu Ariza633ce882018-08-15 12:00:19 -0700594{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800595 static void process_op (op_code_t op, interp_env_t<ARG>& env)
Michiharu Ariza633ce882018-08-15 12:00:19 -0700596 {
597 switch (op) {
598 case OpCode_shortint:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800599 env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1]));
600 env.str_ref.inc (2);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500601 break;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700602
603 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
604 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800605 env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108));
606 env.str_ref.inc ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500607 break;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500608
Michiharu Ariza633ce882018-08-15 12:00:19 -0700609 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
610 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
Michiharu Arizadd4c3752019-04-18 10:38:57 -0700611 env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108));
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800612 env.str_ref.inc ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500613 break;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700614
615 default:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500616 /* 1-byte integer */
617 if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
618 {
619 env.argStack.push_int ((int)op - 139);
620 } else {
621 /* invalid unknown operator */
622 env.clear_args ();
623 env.set_error ();
624 }
625 break;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700626 }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700627 }
628};
629
630template <typename ENV>
Ebrahim Byagowi9db7ce72019-06-28 23:11:52 +0430631struct interpreter_t
632{
Behdad Esfahbodbff78e62022-05-10 16:33:37 -0600633 interpreter_t (ENV& env_) : env (env_) {}
634 ENV& env;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700635};
636
637} /* namespace CFF */
638
Michiharu Ariza1d1afdd2018-08-29 13:36:39 -0700639#endif /* HB_CFF_INTERP_COMMON_HH */