Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/thirdparty/harfbuzz/src/hb-cff-interp-common.hh @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 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 set_int (int v) { value = v; } | |
| 221 int to_int () const { return value; } | |
| 222 | |
| 223 void set_fixed (int32_t v) { value = v / 65536.0; } | |
| 224 int32_t to_fixed () const { return value * 65536.0; } | |
| 225 | |
| 226 void set_real (double v) { value = v; } | |
| 227 double to_real () const { return value; } | |
| 228 | |
| 229 bool in_int_range () const | |
| 230 { return ((double) (int16_t) to_int () == value); } | |
| 231 | |
| 232 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); } | |
| 236 | |
| 237 const number_t &operator += (const number_t &n) | |
| 238 { | |
| 239 set_real (to_real () + n.to_real ()); | |
| 240 | |
| 241 return *this; | |
| 242 } | |
| 243 | |
| 244 protected: | |
| 245 double value = 0.; | |
| 246 }; | |
| 247 | |
| 248 /* byte string */ | |
| 249 struct UnsizedByteStr : UnsizedArrayOf <HBUINT8> | |
| 250 { | |
| 251 hb_ubytes_t as_ubytes (unsigned l) const | |
| 252 { return hb_ubytes_t ((const unsigned char *) this, l); } | |
| 253 | |
| 254 // encode 2-byte int (Dict/CharString) or 4-byte int (Dict) | |
| 255 template <typename T, typename V> | |
| 256 static bool serialize_int (hb_serialize_context_t *c, op_code_t intOp, V value) | |
| 257 { | |
| 258 TRACE_SERIALIZE (this); | |
| 259 | |
| 260 HBUINT8 *p = c->allocate_size<HBUINT8> (1); | |
| 261 if (unlikely (!p)) return_trace (false); | |
| 262 *p = intOp; | |
| 263 | |
| 264 T *ip = c->allocate_size<T> (T::static_size); | |
| 265 if (unlikely (!ip)) return_trace (false); | |
| 266 return_trace (c->check_assign (*ip, value, HB_SERIALIZE_ERROR_INT_OVERFLOW)); | |
| 267 } | |
| 268 | |
| 269 template <typename V> | |
| 270 static bool serialize_int4 (hb_serialize_context_t *c, V value) | |
| 271 { return serialize_int<HBINT32> (c, OpCode_longintdict, value); } | |
| 272 | |
| 273 template <typename V> | |
| 274 static bool serialize_int2 (hb_serialize_context_t *c, V value) | |
| 275 { return serialize_int<HBINT16> (c, OpCode_shortint, value); } | |
| 276 | |
| 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. | |
| 280 */ | |
| 281 DEFINE_SIZE_MIN(0); | |
| 282 }; | |
| 283 | |
| 284 /* A byte string associated with the current offset and an error condition */ | |
| 285 struct byte_str_ref_t | |
| 286 { | |
| 287 byte_str_ref_t () | |
| 288 : str () {} | |
| 289 | |
| 290 byte_str_ref_t (const hb_ubytes_t &str_, unsigned int offset_ = 0) | |
| 291 : str (str_) { set_offset (offset_); } | |
| 292 | |
| 293 void reset (const hb_ubytes_t &str_, unsigned int offset_ = 0) | |
| 294 { | |
| 295 str = str_; | |
| 296 set_offset (offset_); | |
| 297 } | |
| 298 | |
| 299 const unsigned char& operator [] (int i) { | |
| 300 if (unlikely ((unsigned int) (get_offset () + i) >= str.length)) | |
| 301 { | |
| 302 set_error (); | |
| 303 return Null (unsigned char); | |
| 304 } | |
| 305 return str.arrayZ[get_offset () + i]; | |
| 306 } | |
| 307 | |
| 308 unsigned char head_unchecked () const { return str.arrayZ[get_offset ()]; } | |
| 309 | |
| 310 /* Conversion to hb_ubytes_t */ | |
| 311 operator hb_ubytes_t () const { return str.sub_array (get_offset ()); } | |
| 312 | |
| 313 hb_ubytes_t sub_array (unsigned int offset_, unsigned int len_) const | |
| 314 { return str.sub_array (offset_, len_); } | |
| 315 | |
| 316 bool avail (unsigned int count=1) const | |
| 317 { return get_offset () + count <= str.length; } | |
| 318 void inc (unsigned int count=1) | |
| 319 { | |
| 320 /* Automatically puts us in error if count is out-of-range. */ | |
| 321 set_offset (get_offset () + count); | |
| 322 } | |
| 323 | |
| 324 /* We (ab)use ubytes backwards_length as a cursor (called offset), | |
| 325 * as well as to store error condition. */ | |
| 326 | |
| 327 unsigned get_offset () const { return str.backwards_length; } | |
| 328 void set_offset (unsigned offset) { str.backwards_length = offset; } | |
| 329 | |
| 330 void set_error () { str.backwards_length = str.length + 1; } | |
| 331 bool in_error () const { return str.backwards_length > str.length; } | |
| 332 | |
| 333 unsigned total_size () const { return str.length; } | |
| 334 | |
| 335 protected: | |
| 336 hb_ubytes_t str; | |
| 337 }; | |
| 338 | |
| 339 using byte_str_array_t = hb_vector_t<hb_ubytes_t>; | |
| 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; | |
| 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 (n); | |
| 526 } | |
| 527 | |
| 528 void add_op (op_code_t op, const byte_str_ref_t& str_ref = byte_str_ref_t ()) | |
| 529 { | |
| 530 VAL *val = values.push (); | |
| 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 void add_op (op_code_t op, const byte_str_ref_t& str_ref, const VAL &v) | |
| 539 { | |
| 540 VAL *val = values.push (v); | |
| 541 val->op = op; | |
| 542 auto arr = str_ref.sub_array (opStart, str_ref.get_offset () - opStart); | |
| 543 val->ptr = arr.arrayZ; | |
| 544 val->length = arr.length; | |
| 545 opStart = str_ref.get_offset (); | |
| 546 } | |
| 547 | |
| 548 bool has_op (op_code_t op) const | |
| 549 { | |
| 550 for (const auto& v : values) | |
| 551 if (v.op == op) return true; | |
| 552 return false; | |
| 553 } | |
| 554 | |
| 555 unsigned get_count () const { return values.length; } | |
| 556 const VAL &operator [] (unsigned int i) const { return values[i]; } | |
| 557 | |
| 558 unsigned int opStart; | |
| 559 hb_vector_t<VAL> values; | |
| 560 }; | |
| 561 | |
| 562 template <typename ARG=number_t> | |
| 563 struct interp_env_t | |
| 564 { | |
| 565 interp_env_t () {} | |
| 566 interp_env_t (const hb_ubytes_t &str_) | |
| 567 { | |
| 568 str_ref.reset (str_); | |
| 569 } | |
| 570 bool in_error () const | |
| 571 { return str_ref.in_error () || argStack.in_error (); } | |
| 572 | |
| 573 void set_error () { str_ref.set_error (); } | |
| 574 | |
| 575 op_code_t fetch_op () | |
| 576 { | |
| 577 op_code_t op = OpCode_Invalid; | |
| 578 if (unlikely (!str_ref.avail ())) | |
| 579 return OpCode_Invalid; | |
| 580 op = (op_code_t) str_ref.head_unchecked (); | |
| 581 str_ref.inc (); | |
| 582 if (op == OpCode_escape) { | |
| 583 if (unlikely (!str_ref.avail ())) | |
| 584 return OpCode_Invalid; | |
| 585 op = Make_OpCode_ESC (str_ref.head_unchecked ()); | |
| 586 str_ref.inc (); | |
| 587 } | |
| 588 return op; | |
| 589 } | |
| 590 | |
| 591 const ARG& eval_arg (unsigned int i) { return argStack[i]; } | |
| 592 | |
| 593 ARG& pop_arg () { return argStack.pop (); } | |
| 594 void pop_n_args (unsigned int n) { argStack.pop (n); } | |
| 595 | |
| 596 void clear_args () { pop_n_args (argStack.get_count ()); } | |
| 597 | |
| 598 byte_str_ref_t | |
| 599 str_ref; | |
| 600 arg_stack_t<ARG> | |
| 601 argStack; | |
| 602 }; | |
| 603 | |
| 604 using num_interp_env_t = interp_env_t<>; | |
| 605 | |
| 606 template <typename ARG=number_t> | |
| 607 struct opset_t | |
| 608 { | |
| 609 static void process_op (op_code_t op, interp_env_t<ARG>& env) | |
| 610 { | |
| 611 switch (op) { | |
| 612 case OpCode_shortint: | |
| 613 env.argStack.push_int ((int16_t)((env.str_ref[0] << 8) | env.str_ref[1])); | |
| 614 env.str_ref.inc (2); | |
| 615 break; | |
| 616 | |
| 617 case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1: | |
| 618 case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3: | |
| 619 env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.str_ref[0] + 108)); | |
| 620 env.str_ref.inc (); | |
| 621 break; | |
| 622 | |
| 623 case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1: | |
| 624 case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3: | |
| 625 env.argStack.push_int ((-(int16_t)(op - OpCode_TwoByteNegInt0) * 256 - env.str_ref[0] - 108)); | |
| 626 env.str_ref.inc (); | |
| 627 break; | |
| 628 | |
| 629 default: | |
| 630 /* 1-byte integer */ | |
| 631 if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast))) | |
| 632 { | |
| 633 env.argStack.push_int ((int)op - 139); | |
| 634 } else { | |
| 635 /* invalid unknown operator */ | |
| 636 env.clear_args (); | |
| 637 env.set_error (); | |
| 638 } | |
| 639 break; | |
| 640 } | |
| 641 } | |
| 642 }; | |
| 643 | |
| 644 template <typename ENV> | |
| 645 struct interpreter_t | |
| 646 { | |
| 647 interpreter_t (ENV& env_) : env (env_) {} | |
| 648 ENV& env; | |
| 649 }; | |
| 650 | |
| 651 } /* namespace CFF */ | |
| 652 | |
| 653 #endif /* HB_CFF_INTERP_COMMON_HH */ |
