blob: 79add121008e49cfbc681b839cc924191c14dce1 [file] [log] [blame]
Michiharu Ariza633ce882018-08-15 12:00:19 -07001/*
2 * Copyright © 2018 Adobe Systems Incorporated.
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_PRIVATE_HH
27#define HB_CFF_INTERP_COMMON_PRIVATE_HH
28
Michiharu Ariza633ce882018-08-15 12:00:19 -070029namespace CFF {
30
31using namespace OT;
32
33enum OpCode {
34 /* === Dict operators === */
35
36 /* One byte operators (0-31) */
37 OpCode_version, /* 0 CFF Top */
38 OpCode_Notice, /* 1 CFF Top */
39 OpCode_FullName, /* 2 CFF Top */
40 OpCode_FamilyName, /* 3 CFF Top */
41 OpCode_Weight, /* 4 CFF Top */
42 OpCode_FontBBox, /* 5 CFF Top */
43 OpCode_BlueValues, /* 6 CFF Private, CFF2 Private */
44 OpCode_OtherBlues, /* 7 CFF Private, CFF2 Private */
45 OpCode_FamilyBlues, /* 8 CFF Private, CFF2 Private */
46 OpCode_FamilyOtherBlues, /* 9 CFF Private, CFF2 Private */
47 OpCode_StdHW, /* 10 CFF Private, CFF2 Private */
48 OpCode_StdVW, /* 11 CFF Private, CFF2 Private */
49 OpCode_escape, /* 12 All. Shared with CS */
50 OpCode_UniqueID, /* 13 CFF Top */
51 OpCode_XUID, /* 14 CFF Top */
52 OpCode_charset, /* 15 CFF Top (0) */
53 OpCode_Encoding, /* 16 CFF Top (0) */
54 OpCode_CharStrings, /* 17 CFF Top, CFF2 Top */
55 OpCode_Private, /* 18 CFF Top, CFF2 FD */
56 OpCode_Subrs, /* 19 CFF Private, CFF2 Private */
57 OpCode_defaultWidthX, /* 20 CFF Private (0) */
58 OpCode_nominalWidthX, /* 21 CFF Private (0) */
Michiharu Arizacef75ea2018-08-17 13:13:18 -070059 OpCode_vsindexdict, /* 22 CFF2 Private/CS */
Michiharu Ariza633ce882018-08-15 12:00:19 -070060 OpCode_blenddict, /* 23 CFF2 Private/CS */
61 OpCode_vstore, /* 24 CFF2 Top */
62 OpCode_reserved25, /* 25 */
63 OpCode_reserved26, /* 26 */
64 OpCode_reserved27, /* 27 */
65
66 /* Numbers */
67 OpCode_shortint, /* 28 16-bit integer, All */
68 OpCode_longintdict, /* 29 32-bit integer, All */
69 OpCode_BCD, /* 30 real number, CFF2 Top/FD */
70 OpCode_reserved31, /* 31 */
71
72 /* 1-byte integers */
73 OpCode_OneByteIntFirst = 32, /* All. beginning of the range of first byte ints */
74 OpCode_OneByteIntLast = 246, /* All. ending of the range of first byte int */
75
76 /* 2-byte integers */
77 OpCode_TwoBytePosInt0, /* 247 All. first byte of two byte positive int (+108 to +1131) */
78 OpCode_TwoBytePosInt1,
79 OpCode_TwoBytePosInt2,
80 OpCode_TwoBytePosInt3,
81
82 OpCode_TwoByteNegInt0, /* 251 All. first byte of two byte negative int (-1131 to -108) */
83 OpCode_TwoByteNegInt1,
84 OpCode_TwoByteNegInt2,
85 OpCode_TwoByteNegInt3,
86
87 /* Two byte escape operators 12, (0-41) */
88 OpCode_ESC_Base = 256,
89 OpCode_Copyright = OpCode_ESC_Base, /* Make_OpCode_ESC (0) CFF Top */
90 OpCode_isFixedPitch, /* Make_OpCode_ESC (1) CFF Top (false) */
91 OpCode_ItalicAngle, /* Make_OpCode_ESC (2) CFF Top (0) */
92 OpCode_UnderlinePosition, /* Make_OpCode_ESC (3) CFF Top (-100) */
93 OpCode_UnderlineThickness, /* Make_OpCode_ESC (4) CFF Top (50) */
94 OpCode_PaintType, /* Make_OpCode_ESC (5) CFF Top (0) */
95 OpCode_CharstringType, /* Make_OpCode_ESC (6) CFF Top (2) */
96 OpCode_FontMatrix, /* Make_OpCode_ESC (7) CFF Top, CFF2 Top (.001 0 0 .001 0 0)*/
97 OpCode_StrokeWidth, /* Make_OpCode_ESC (8) CFF Top (0) */
98 OpCode_BlueScale, /* Make_OpCode_ESC (9) CFF Private, CFF2 Private (0.039625) */
99 OpCode_BlueShift, /* Make_OpCode_ESC (10) CFF Private, CFF2 Private (7) */
100 OpCode_BlueFuzz, /* Make_OpCode_ESC (11) CFF Private, CFF2 Private (1) */
101 OpCode_StemSnapH, /* Make_OpCode_ESC (12) CFF Private, CFF2 Private */
102 OpCode_StemSnapV, /* Make_OpCode_ESC (13) CFF Private, CFF2 Private */
103 OpCode_ForceBold, /* Make_OpCode_ESC (14) CFF Private (false) */
104 OpCode_reservedESC15, /* Make_OpCode_ESC (15) */
105 OpCode_reservedESC16, /* Make_OpCode_ESC (16) */
106 OpCode_LanguageGroup, /* Make_OpCode_ESC (17) CFF Private, CFF2 Private (0) */
107 OpCode_ExpansionFactor, /* Make_OpCode_ESC (18) CFF Private, CFF2 Private (0.06) */
108 OpCode_initialRandomSeed, /* Make_OpCode_ESC (19) CFF Private (0) */
109 OpCode_SyntheticBase, /* Make_OpCode_ESC (20) CFF Top */
110 OpCode_PostScript, /* Make_OpCode_ESC (21) CFF Top */
111 OpCode_BaseFontName, /* Make_OpCode_ESC (22) CFF Top */
112 OpCode_BaseFontBlend, /* Make_OpCode_ESC (23) CFF Top */
113 OpCode_reservedESC24, /* Make_OpCode_ESC (24) */
114 OpCode_reservedESC25, /* Make_OpCode_ESC (25) */
115 OpCode_reservedESC26, /* Make_OpCode_ESC (26) */
116 OpCode_reservedESC27, /* Make_OpCode_ESC (27) */
117 OpCode_reservedESC28, /* Make_OpCode_ESC (28) */
118 OpCode_reservedESC29, /* Make_OpCode_ESC (29) */
119 OpCode_ROS, /* Make_OpCode_ESC (30) CFF Top_CID */
120 OpCode_CIDFontVersion, /* Make_OpCode_ESC (31) CFF Top_CID (0) */
121 OpCode_CIDFontRevision, /* Make_OpCode_ESC (32) CFF Top_CID (0) */
122 OpCode_CIDFontType, /* Make_OpCode_ESC (33) CFF Top_CID (0) */
123 OpCode_CIDCount, /* Make_OpCode_ESC (34) CFF Top_CID (8720) */
124 OpCode_UIDBase, /* Make_OpCode_ESC (35) CFF Top_CID */
125 OpCode_FDArray, /* Make_OpCode_ESC (36) CFF Top_CID, CFF2 Top */
126 OpCode_FDSelect, /* Make_OpCode_ESC (37) CFF Top_CID, CFF2 Top */
127 OpCode_FontName, /* Make_OpCode_ESC (38) CFF Top_CID */
128
129 /* === CharString operators === */
130
131 OpCode_hstem = 1, /* 1 CFF, CFF2 */
132 OpCode_Reserved2,
133 OpCode_vstem, /* 3 CFF, CFF2 */
134 OpCode_vmoveto, /* 4 CFF, CFF2 */
135 OpCode_rlineto, /* 5 CFF, CFF2 */
136 OpCode_hlineto, /* 6 CFF, CFF2 */
137 OpCode_vlineto, /* 7 CFF, CFF2 */
138 OpCode_rrcurveto, /* 8 CFF, CFF2 */
139 OpCode_Reserved9,
140 OpCode_callsubr, /* 10 CFF, CFF2 */
141 OpCode_return, /* 11 CFF */
142 // OpCode_escape, /* 12 CFF, CFF2 */
143 OpCode_Reserved13 = 13,
144 OpCode_endchar, /* 14 CFF */
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700145 OpCode_vsindexcs, /* 15 CFF2 */
146 OpCode_blendcs, /* 16 CFF2 */
Michiharu Ariza633ce882018-08-15 12:00:19 -0700147 OpCode_Reserved17,
148 OpCode_hstemhm, /* 18 CFF, CFF2 */
149 OpCode_hintmask, /* 19 CFF, CFF2 */
150 OpCode_cntrmask, /* 20 CFF, CFF2 */
151 OpCode_rmoveto, /* 21 CFF, CFF2 */
152 OpCode_hmoveto, /* 22 CFF, CFF2 */
153 OpCode_vstemhm, /* 23 CFF, CFF2 */
154 OpCode_rcurveline, /* 24 CFF, CFF2 */
155 OpCode_rlinecurve, /* 25 CFF, CFF2 */
156 OpCode_vvcurveto, /* 26 CFF, CFF2 */
157 OpCode_hhcurveto, /* 27 CFF, CFF2 */
158 // OpCode_shortint, /* 28 CFF, CFF2 */
159 OpCode_callgsubr = 29, /* 29 CFF, CFF2 */
160 OpCode_vhcurveto, /* 30 CFF, CFF2 */
161 OpCode_hvcurveto, /* 31 CFF, CFF2 */
162
Michiharu Ariza27c32d82018-08-22 11:36:39 -0700163 OpCode_fixedcs = 255, /* 32-bit fixed */
Michiharu Ariza633ce882018-08-15 12:00:19 -0700164
165 /* Two byte escape operators 12, (0-41) */
166 OpCode_ReservedESC0 = OpCode_ESC_Base, /* Make_OpCode_ESC (0) */
167 OpCode_ReservedESC1, /* Make_OpCode_ESC (1) */
168 OpCode_ReservedESC2, /* Make_OpCode_ESC (2) */
169 OpCode_and, /* Make_OpCode_ESC (3) CFF */
170 OpCode_or, /* Make_OpCode_ESC (4) CFF */
171 OpCode_not, /* Make_OpCode_ESC (5) CFF */
172 OpCode_ReservedESC6, /* Make_OpCode_ESC (6) */
173 OpCode_ReservedESC7, /* Make_OpCode_ESC (7) */
174 OpCode_ReservedESC8, /* Make_OpCode_ESC (8) */
175 OpCode_abs, /* Make_OpCode_ESC (9) CFF */
176 OpCode_add, /* Make_OpCode_ESC (10) CFF */
177 OpCode_sub, /* Make_OpCode_ESC (11) CFF */
178 OpCode_div, /* Make_OpCode_ESC (12) CFF */
179 OpCode_ReservedESC13, /* Make_OpCode_ESC (13) */
180 OpCode_neg, /* Make_OpCode_ESC (14) CFF */
181 OpCode_eq, /* Make_OpCode_ESC (15) CFF */
182 OpCode_ReservedESC16, /* Make_OpCode_ESC (16) */
183 OpCode_ReservedESC17, /* Make_OpCode_ESC (17) */
184 OpCode_drop, /* Make_OpCode_ESC (18) CFF */
185 OpCode_ReservedESC19, /* Make_OpCode_ESC (19) */
186 OpCode_put, /* Make_OpCode_ESC (20) CFF */
187 OpCode_get, /* Make_OpCode_ESC (21) CFF */
188 OpCode_ifelse, /* Make_OpCode_ESC (22) CFF */
189 OpCode_random, /* Make_OpCode_ESC (23) CFF */
190 OpCode_mul, /* Make_OpCode_ESC (24) CFF */
191 // OpCode_reservedESC25, /* Make_OpCode_ESC (25) */
192 OpCode_sqrt = OpCode_mul+2, /* Make_OpCode_ESC (26) CFF */
193 OpCode_dup, /* Make_OpCode_ESC (27) CFF */
194 OpCode_exch, /* Make_OpCode_ESC (28) CFF */
195 OpCode_index, /* Make_OpCode_ESC (29) CFF */
196 OpCode_roll, /* Make_OpCode_ESC (30) CFF */
197 OpCode_reservedESC31, /* Make_OpCode_ESC (31) */
198 OpCode_reservedESC32, /* Make_OpCode_ESC (32) */
199 OpCode_reservedESC33, /* Make_OpCode_ESC (33) */
200 OpCode_hflex, /* Make_OpCode_ESC (34) CFF, CFF2 */
201 OpCode_flex, /* Make_OpCode_ESC (35) CFF, CFF2 */
202 OpCode_hflex1, /* Make_OpCode_ESC (36) CFF, CFF2 */
203 OpCode_flex1 /* Make_OpCode_ESC (37) CFF, CFF2 */
204};
205
206inline OpCode Make_OpCode_ESC (unsigned char byte2) { return (OpCode)(OpCode_ESC_Base + byte2); }
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700207inline OpCode Unmake_OpCode_ESC (OpCode op) { return (OpCode)(op - OpCode_ESC_Base); }
208inline bool Is_OpCode_ESC (OpCode op) { return op >= OpCode_ESC_Base; }
209inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op)? 2: 1; }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700210
211struct Number
212{
213 inline Number (void) { set_int (0); }
214
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700215 inline void set_int (int v) { format = NumInt; u.int_val = v; };
216 inline int to_int (void) const { return is_int ()? u.int_val: (int)to_real (); }
217 inline void set_fixed (int32_t v) { format = NumFixed; u.fixed_val = v; };
218 inline int32_t to_fixed (void) const
219 {
220 if (is_fixed ())
221 return u.fixed_val;
222 else if (is_real ())
223 return (int32_t)(u.real_val * 65536.0);
224 else
225 return (int32_t)(u.int_val << 16);
226 }
227 inline void set_real (float v) { format = NumReal; u.real_val = v; };
228 inline float to_real (void) const
229 {
230 if (is_real ())
231 return u.real_val;
232 if (is_fixed ())
233 return u.fixed_val / 65536.0;
234 else
235 return (float)u.int_val;
236 }
237 inline bool in_int_range (void) const
238 {
239 if (is_int ())
240 return true;
241 if (is_fixed () && ((u.fixed_val & 0xFFFF) == 0))
242 return true;
243 else
244 return ((float)(int16_t)to_int () == u.real_val);
245 }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700246
247protected:
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700248 enum NumFormat {
249 NumInt,
250 NumFixed,
251 NumReal
252 };
253 NumFormat format;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700254 union {
255 int int_val;
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700256 int32_t fixed_val;
Michiharu Ariza633ce882018-08-15 12:00:19 -0700257 float real_val;
258 } u;
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700259
260 inline bool is_int (void) const { return format == NumInt; }
261 inline bool is_fixed (void) const { return format == NumFixed; }
262 inline bool is_real (void) const { return format == NumReal; }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700263};
264
265/* byte string */
266struct UnsizedByteStr : UnsizedArrayOf <HBUINT8>
267{
268 // encode 2-byte int (Dict/CharString) or 4-byte int (Dict)
269 template <typename INTTYPE, int minVal, int maxVal>
270 inline static bool serialize_int (hb_serialize_context_t *c, OpCode intOp, int value)
271 {
272 TRACE_SERIALIZE (this);
273
274 if (unlikely ((value < minVal || value > maxVal)))
275 return_trace (false);
276
277 HBUINT8 *p = c->allocate_size<HBUINT8> (1);
278 if (unlikely (p == nullptr)) return_trace (false);
279 p->set (intOp);
280
281 INTTYPE *ip = c->allocate_size<INTTYPE> (INTTYPE::static_size);
282 if (unlikely (ip == nullptr)) return_trace (false);
283 ip->set ((unsigned int)value);
284
285 return_trace (true);
286 }
287
288 inline static bool serialize_int4 (hb_serialize_context_t *c, int value)
289 { return serialize_int<HBUINT32, 0, 0x7FFFFFFF> (c, OpCode_longintdict, value); }
290
291 inline static bool serialize_int2 (hb_serialize_context_t *c, int value)
292 { return serialize_int<HBUINT16, 0, 0x7FFF> (c, OpCode_shortint, value); }
293};
294
295struct ByteStr
296{
297 inline ByteStr (void)
298 : str (&Null(UnsizedByteStr)), len (0) {}
299 inline ByteStr (const UnsizedByteStr& s, unsigned int l)
300 : str (&s), len (l) {}
301 inline ByteStr (const char *s, unsigned int l=0)
302 : str ((const UnsizedByteStr *)s), len (l) {}
303 /* sub-string */
304 inline ByteStr (const ByteStr &bs, unsigned int offset, unsigned int len_)
305 {
306 str = (const UnsizedByteStr *)&bs.str[offset];
307 len = len_;
308 }
309
310 inline bool sanitize (hb_sanitize_context_t *c) const { return str->sanitize (c, len); }
311
312 inline const HBUINT8& operator [] (unsigned int i) const {
313 assert (str && (i < len));
314 return (*str)[i];
315 }
316
317 inline bool serialize (hb_serialize_context_t *c, const ByteStr &src)
318 {
319 TRACE_SERIALIZE (this);
320 HBUINT8 *dest = c->allocate_size<HBUINT8> (src.len);
321 if (unlikely (dest == nullptr))
322 return_trace (false);
323 memcpy (dest, src.str, src.len);
324 return_trace (true);
325 }
326
327 inline unsigned int get_size (void) const { return len; }
328
329 inline bool check_limit (unsigned int offset, unsigned int count) const
330 { return (offset + count <= len); }
331
332 const UnsizedByteStr *str;
333 unsigned int len;
334};
335
336struct SubByteStr
337{
338 inline SubByteStr (void)
339 : str (), offset (0) {}
340
341 inline SubByteStr (const ByteStr &str_, unsigned int offset_ = 0)
342 : str (str_), offset (offset_) {}
343
344 inline void reset (const ByteStr &str_, unsigned int offset_ = 0)
345 {
346 str = str_;
347 offset = offset_;
348 }
349
Michiharu Arizaa11420b2018-08-29 12:14:30 -0700350 inline const HBUINT8& operator [] (int i) const {
Michiharu Ariza633ce882018-08-15 12:00:19 -0700351 return str[offset + i];
352 }
353
354 inline operator ByteStr (void) const { return ByteStr (str, offset, str.len - offset); }
355
356 inline bool avail (unsigned int count=1) const { return str.check_limit (offset, count); }
357 inline void inc (unsigned int count=1) { offset += count; assert (count <= str.len); }
358
359 ByteStr str;
360 unsigned int offset; /* beginning of the sub-string within str */
361};
362
363inline float parse_bcd (SubByteStr& substr, float& v)
364{
365 // XXX: TODO
366 v = 0;
367 for (;;) {
368 if (!substr.avail ())
369 return false;
370 unsigned char byte = substr[0];
371 substr.inc ();
372 if (((byte & 0xF0) == 0xF0) || ((byte & 0x0F) == 0x0F))
373 break;
374 }
375 return true;
376}
377
378/* stack */
379template <typename ELEM, int LIMIT>
380struct Stack
381{
382 inline void init (void) { size = 0; }
383 inline void fini (void) { }
384
385 inline void push (const ELEM &v)
386 {
387 if (likely (size < kSizeLimit))
388 elements[size++] = v;
389 }
390
391 inline const ELEM& pop (void)
392 {
393 if (likely (size > 0))
394 return elements[--size];
395 else
396 return Null(ELEM);
397 }
398
399 inline void unpop (void)
400 {
401 if (likely (size < kSizeLimit))
402 size++;
403 }
404
405 inline void clear (void) { size = 0; }
406
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700407 inline bool check_overflow (unsigned int count=1) const { return (count <= kSizeLimit) && (count + size <= kSizeLimit); }
408 inline bool check_underflow (unsigned int count=1) const { return (count <= size); }
Michiharu Ariza633ce882018-08-15 12:00:19 -0700409
410 inline unsigned int get_size (void) const { return size; }
411 inline bool is_empty (void) const { return size == 0; }
412
413 static const unsigned int kSizeLimit = LIMIT;
414
415 unsigned int size;
416 ELEM elements[kSizeLimit];
417};
418
419/* argument stack */
420struct ArgStack : Stack<Number, 513>
421{
422 inline void push_int (int v)
423 {
424 Number n;
425 n.set_int (v);
426 push (n);
427 }
428
429 inline void push_real (float v)
430 {
431 Number n;
432 n.set_real (v);
433 push (n);
434 }
435
436 inline bool check_pop_num (Number& n)
437 {
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700438 if (unlikely (!this->check_underflow ()))
Michiharu Ariza633ce882018-08-15 12:00:19 -0700439 return false;
440 n = this->pop ();
441 return true;
442 }
443
444 inline bool check_pop_num2 (Number& n1, Number& n2)
445 {
446 if (unlikely (!this->check_underflow (2)))
447 return false;
448 n2 = this->pop ();
449 n1 = this->pop ();
450 return true;
451 }
452
453 inline bool check_pop_int (int& v)
454 {
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700455 if (unlikely (!this->check_underflow ()))
Michiharu Ariza633ce882018-08-15 12:00:19 -0700456 return false;
457 v = this->pop ().to_int ();
458 return true;
459 }
460
461 inline bool check_pop_uint (unsigned int& v)
462 {
463 int i;
464 if (unlikely (!check_pop_int (i) || i < 0))
465 return false;
466 v = (unsigned int)i;
467 return true;
468 }
469
470 inline bool check_pop_delta (hb_vector_t<Number>& vec, bool even=false)
471 {
472 if (even && unlikely ((this->size & 1) != 0))
473 return false;
474
475 float val = 0.0f;
476 for (unsigned int i = 0; i < size; i++) {
477 val += elements[i].to_real ();
478 Number *n = vec.push ();
479 n->set_real (val);
480 }
481 return true;
482 }
483
484 inline bool push_longint_from_substr (SubByteStr& substr)
485 {
486 if (unlikely (!substr.avail (4) || !check_overflow (1)))
487 return false;
488 push_int ((int32_t)*(const HBUINT32*)&substr[0]);
489 substr.inc (4);
490 return true;
491 }
492
Michiharu Ariza27c32d82018-08-22 11:36:39 -0700493 inline bool push_fixed_from_substr (SubByteStr& substr)
494 {
495 if (unlikely (!substr.avail (4) || !check_overflow (1)))
496 return false;
497 push_real ((int32_t)*(const HBUINT32*)&substr[0] / 65536.0);
498 substr.inc (4);
499 return true;
500 }
501
Michiharu Ariza633ce882018-08-15 12:00:19 -0700502 inline void reverse_range (int i, int j)
503 {
504 assert (i >= 0 && i < j);
505 Number tmp;
506 while (i < j)
507 {
508 tmp = elements[i];
509 elements[i++] = elements[j];
510 elements[j++] = tmp;
511 }
512 }
513};
514
515/* an operator prefixed by its operands in a byte string */
516struct OpStr
517{
518 inline void init (void) {}
519
520 OpCode op;
521 ByteStr str;
522};
523
524/* base of OP_SERIALIZER */
525struct OpSerializer
526{
527 protected:
528 inline bool copy_opstr (hb_serialize_context_t *c, const OpStr& opstr) const
529 {
530 TRACE_SERIALIZE (this);
531
532 HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.len);
533 if (unlikely (d == nullptr)) return_trace (false);
534 memcpy (d, &opstr.str.str[0], opstr.str.len);
535 return_trace (true);
536 }
537};
538
539struct InterpEnv
540{
541 inline void init (const ByteStr &str_)
542 {
543 substr.reset (str_);
544 argStack.init ();
545 }
546
547 inline void fini (void)
548 {
549 argStack.fini ();
550 }
551
Michiharu Arizacef75ea2018-08-17 13:13:18 -0700552 inline bool fetch_op (OpCode &op)
553 {
554 if (unlikely (!substr.avail ()))
555 return false;
556 op = (OpCode)(unsigned char)substr[0];
557 if (op == OpCode_escape) {
558 if (unlikely (!substr.avail ()))
559 return false;
560 op = Make_OpCode_ESC (substr[1]);
561 substr.inc ();
562 }
563 substr.inc ();
564 return true;
565 }
566
Michiharu Ariza633ce882018-08-15 12:00:19 -0700567 SubByteStr substr;
568 ArgStack argStack;
569};
570
571struct OpSet
572{
573 static inline bool process_op (OpCode op, InterpEnv& env)
574 {
575 switch (op) {
576 case OpCode_shortint:
577 if (unlikely (!env.substr.avail (2) || !env.argStack.check_overflow (1)))
578 return false;
579 env.argStack.push_int ((int16_t)*(const HBUINT16*)&env.substr[0]);
580 env.substr.inc (2);
581 break;
582
583 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
584 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
585 if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1)))
586 return false;
587 env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.substr[0] + 108));
588 env.substr.inc ();
589 break;
590
591 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
592 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
593 if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1)))
594 return false;
595 env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.substr[0] - 108));
596 env.substr.inc ();
597 break;
598
599 default:
600 /* 1-byte integer */
601 if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)) &&
602 likely (env.argStack.check_overflow (1)))
603 {
604 env.argStack.push_int ((int)op - 139);
605 } else {
606 /* invalid unknown operator */
607 env.argStack.clear ();
608 return false;
609 }
610 break;
611 }
612
613 return true;
614 }
615};
616
617template <typename ENV>
618struct Interpreter {
619
620 inline ~Interpreter(void) { fini (); }
621
622 inline void fini (void) { env.fini (); }
623
Michiharu Ariza633ce882018-08-15 12:00:19 -0700624 ENV env;
625};
626
627} /* namespace CFF */
628
629#endif /* HB_CFF_INTERP_COMMON_PRIVATE_HH */