overhauled error handling in CFF interpreter
minimized "if (error) return false" idiom
This commit is contained in:
parent
ca37172ee3
commit
7d99a6cef8
|
@ -208,6 +208,8 @@ inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op)? 2: 1; }
|
|||
#define OpCode_hflex1 Make_OpCode_ESC(36) /* CFF, CFF2 */
|
||||
#define OpCode_flex1 Make_OpCode_ESC(37) /* CFF, CFF2 */
|
||||
|
||||
#define OpCode_Invalid 65535
|
||||
|
||||
struct Number
|
||||
{
|
||||
inline void init (void)
|
||||
|
@ -406,21 +408,29 @@ struct SubByteStr
|
|||
{
|
||||
str = ByteStr (0);
|
||||
offset = 0;
|
||||
error = false;
|
||||
}
|
||||
|
||||
inline void fini (void) {}
|
||||
|
||||
inline SubByteStr (const ByteStr &str_, unsigned int offset_ = 0)
|
||||
: str (str_), offset (offset_) {}
|
||||
: str (str_), offset (offset_), error (false) {}
|
||||
|
||||
inline void reset (const ByteStr &str_, unsigned int offset_ = 0)
|
||||
{
|
||||
str = str_;
|
||||
offset = offset_;
|
||||
error = false;
|
||||
}
|
||||
|
||||
inline const HBUINT8& operator [] (int i) const {
|
||||
return str[offset + i];
|
||||
inline const HBUINT8& operator [] (int i) {
|
||||
if (unlikely ((unsigned int)(offset + i) >= str.len))
|
||||
{
|
||||
set_error ();
|
||||
return Null(HBUINT8);
|
||||
}
|
||||
else
|
||||
return str[offset + i];
|
||||
}
|
||||
|
||||
inline operator ByteStr (void) const { return ByteStr (str, offset, str.len - offset); }
|
||||
|
@ -428,8 +438,14 @@ struct SubByteStr
|
|||
inline bool avail (unsigned int count=1) const { return str.check_limit (offset, count); }
|
||||
inline void inc (unsigned int count=1) { offset += count; assert (count <= str.len); }
|
||||
|
||||
inline void set_error (void) { error = true; }
|
||||
inline bool in_error (void) const { return error; }
|
||||
|
||||
ByteStr str;
|
||||
unsigned int offset; /* beginning of the sub-string within str */
|
||||
|
||||
protected:
|
||||
bool error;
|
||||
};
|
||||
|
||||
/* stack */
|
||||
|
@ -438,6 +454,7 @@ struct Stack
|
|||
{
|
||||
inline void init (void)
|
||||
{
|
||||
error = false;
|
||||
count = 0;
|
||||
elements.init ();
|
||||
elements.resize (kSizeLimit);
|
||||
|
@ -450,16 +467,18 @@ struct Stack
|
|||
elements.fini_deep ();
|
||||
}
|
||||
|
||||
inline const ELEM& operator [] (unsigned int i) const
|
||||
{ return elements[i]; }
|
||||
|
||||
inline ELEM& operator [] (unsigned int i)
|
||||
{ return elements[i]; }
|
||||
{
|
||||
if (unlikely (i >= count)) set_error ();
|
||||
return elements[i];
|
||||
}
|
||||
|
||||
inline void push (const ELEM &v)
|
||||
{
|
||||
if (likely (count < elements.len))
|
||||
elements[count++] = v;
|
||||
else
|
||||
set_error ();
|
||||
}
|
||||
|
||||
inline ELEM &push (void)
|
||||
|
@ -467,7 +486,10 @@ struct Stack
|
|||
if (likely (count < elements.len))
|
||||
return elements[count++];
|
||||
else
|
||||
{
|
||||
set_error ();
|
||||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
inline ELEM& pop (void)
|
||||
|
@ -475,13 +497,18 @@ struct Stack
|
|||
if (likely (count > 0))
|
||||
return elements[--count];
|
||||
else
|
||||
{
|
||||
set_error ();
|
||||
return Crap(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
inline void pop (unsigned int n)
|
||||
{
|
||||
if (likely (count >= n))
|
||||
count -= n;
|
||||
else
|
||||
set_error ();
|
||||
}
|
||||
|
||||
inline const ELEM& peek (void)
|
||||
|
@ -489,19 +516,24 @@ struct Stack
|
|||
if (likely (count > 0))
|
||||
return elements[count-1];
|
||||
else
|
||||
{
|
||||
set_error ();
|
||||
return Null(ELEM);
|
||||
}
|
||||
}
|
||||
|
||||
inline void unpop (void)
|
||||
{
|
||||
if (likely (count < elements.len))
|
||||
count++;
|
||||
else
|
||||
set_error ();
|
||||
}
|
||||
|
||||
inline void clear (void) { count = 0; }
|
||||
|
||||
inline bool check_overflow (unsigned int n=1) const { return (n <= kSizeLimit) && (n + count <= kSizeLimit); }
|
||||
inline bool check_underflow (unsigned int n=1) const { return (n <= count); }
|
||||
inline bool in_error (void) const { return (error || elements.in_error ()); }
|
||||
inline void set_error (void) { error = true; }
|
||||
|
||||
inline unsigned int get_count (void) const { return count; }
|
||||
inline bool is_empty (void) const { return count == 0; }
|
||||
|
@ -509,6 +541,7 @@ struct Stack
|
|||
static const unsigned int kSizeLimit = LIMIT;
|
||||
|
||||
protected:
|
||||
bool error;
|
||||
unsigned int count;
|
||||
hb_vector_t<ELEM, kSizeLimit> elements;
|
||||
};
|
||||
|
@ -535,44 +568,41 @@ struct ArgStack : Stack<ARG, 513>
|
|||
n.set_real (v);
|
||||
}
|
||||
|
||||
inline bool check_pop_num (ARG& n)
|
||||
inline ARG& pop_num (void)
|
||||
{
|
||||
if (unlikely (!this->check_underflow ()))
|
||||
return false;
|
||||
n = this->pop ();
|
||||
return true;
|
||||
return this->pop ();
|
||||
}
|
||||
|
||||
inline bool check_pop_num2 (ARG& n1, ARG& n2)
|
||||
inline void pop_num2 (ARG& n1, ARG& n2)
|
||||
{
|
||||
if (unlikely (!this->check_underflow (2)))
|
||||
return false;
|
||||
n2 = this->pop ();
|
||||
n1 = this->pop ();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool check_pop_int (int& v)
|
||||
inline int pop_int (void)
|
||||
{
|
||||
if (unlikely (!this->check_underflow ()))
|
||||
return false;
|
||||
v = this->pop ().to_int ();
|
||||
return true;
|
||||
return this->pop ().to_int ();
|
||||
}
|
||||
|
||||
inline bool check_pop_uint (unsigned int& v)
|
||||
inline unsigned int pop_uint (void)
|
||||
{
|
||||
int i;
|
||||
if (unlikely (!check_pop_int (i) || i < 0))
|
||||
return false;
|
||||
v = (unsigned int)i;
|
||||
return true;
|
||||
|
||||
int i = pop_int ();
|
||||
if (unlikely (i < 0))
|
||||
{
|
||||
i = 0;
|
||||
S::set_error ();
|
||||
}
|
||||
return (unsigned)i;
|
||||
}
|
||||
|
||||
inline bool check_pop_delta (hb_vector_t<ARG>& vec, bool even=false)
|
||||
inline void pop_delta (hb_vector_t<ARG>& vec, bool even=false)
|
||||
{
|
||||
if (even && unlikely ((this->count & 1) != 0))
|
||||
return false;
|
||||
{
|
||||
S::set_error ();
|
||||
return;
|
||||
}
|
||||
|
||||
float val = 0.0f;
|
||||
for (unsigned int i = 0; i < S::count; i++) {
|
||||
|
@ -580,21 +610,17 @@ struct ArgStack : Stack<ARG, 513>
|
|||
ARG *n = vec.push ();
|
||||
n->set_real (val);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool push_longint_from_substr (SubByteStr& substr)
|
||||
inline void push_longint_from_substr (SubByteStr& substr)
|
||||
{
|
||||
if (unlikely (!substr.avail (4) || !S::check_overflow (1)))
|
||||
return false;
|
||||
push_int ((int32_t)*(const HBUINT32*)&substr[0]);
|
||||
push_int ((substr[0] << 24) | (substr[1] << 16) | (substr[2] << 8) | (substr[3]));
|
||||
substr.inc (4);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool push_fixed_from_substr (SubByteStr& substr)
|
||||
{
|
||||
if (unlikely (!substr.avail (4) || !S::check_overflow (1)))
|
||||
if (unlikely (!substr.avail (4)))
|
||||
return false;
|
||||
push_fixed ((int32_t)*(const HBUINT32*)&substr[0]);
|
||||
substr.inc (4);
|
||||
|
@ -649,6 +675,7 @@ struct InterpEnv
|
|||
{
|
||||
substr.reset (str_);
|
||||
argStack.init ();
|
||||
error = false;
|
||||
}
|
||||
|
||||
inline void fini (void)
|
||||
|
@ -656,19 +683,27 @@ struct InterpEnv
|
|||
argStack.fini ();
|
||||
}
|
||||
|
||||
inline bool fetch_op (OpCode &op)
|
||||
inline bool in_error (void) const
|
||||
{
|
||||
return error || substr.in_error () || argStack.in_error ();
|
||||
}
|
||||
|
||||
inline void set_error (void) { error = true; }
|
||||
|
||||
inline OpCode fetch_op (void)
|
||||
{
|
||||
OpCode op = OpCode_Reserved2;
|
||||
if (unlikely (!substr.avail ()))
|
||||
return false;
|
||||
return OpCode_Invalid;
|
||||
op = (OpCode)(unsigned char)substr[0];
|
||||
if (op == OpCode_escape) {
|
||||
if (unlikely (!substr.avail ()))
|
||||
return false;
|
||||
return OpCode_Invalid;
|
||||
op = Make_OpCode_ESC(substr[1]);
|
||||
substr.inc ();
|
||||
}
|
||||
substr.inc ();
|
||||
return true;
|
||||
return op;
|
||||
}
|
||||
|
||||
inline const ARG& eval_arg (unsigned int i)
|
||||
|
@ -694,6 +729,8 @@ struct InterpEnv
|
|||
|
||||
SubByteStr substr;
|
||||
ArgStack<ARG> argStack;
|
||||
protected:
|
||||
bool error;
|
||||
};
|
||||
|
||||
typedef InterpEnv<> NumInterpEnv;
|
||||
|
@ -701,47 +738,38 @@ typedef InterpEnv<> NumInterpEnv;
|
|||
template <typename ARG=Number>
|
||||
struct OpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, InterpEnv<ARG>& env)
|
||||
static inline void process_op (OpCode op, InterpEnv<ARG>& env)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_shortint:
|
||||
if (unlikely (!env.substr.avail (2) || !env.argStack.check_overflow (1)))
|
||||
return false;
|
||||
env.argStack.push_int ((int16_t)*(const HBUINT16*)&env.substr[0]);
|
||||
env.argStack.push_int ((env.substr[0] << 8) | env.substr[1]);
|
||||
env.substr.inc (2);
|
||||
break;
|
||||
|
||||
case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
|
||||
case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
|
||||
if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1)))
|
||||
return false;
|
||||
env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.substr[0] + 108));
|
||||
env.substr.inc ();
|
||||
break;
|
||||
|
||||
case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
|
||||
case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
|
||||
if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1)))
|
||||
return false;
|
||||
env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.substr[0] - 108));
|
||||
env.substr.inc ();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* 1-byte integer */
|
||||
if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)) &&
|
||||
likely (env.argStack.check_overflow (1)))
|
||||
if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)))
|
||||
{
|
||||
env.argStack.push_int ((int)op - 139);
|
||||
} else {
|
||||
/* invalid unknown operator */
|
||||
env.clear_args ();
|
||||
return false;
|
||||
env.set_error ();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -98,12 +98,14 @@ struct CSInterpEnv : InterpEnv<ARG>
|
|||
localSubrs.fini ();
|
||||
}
|
||||
|
||||
inline bool in_error (void) const
|
||||
{
|
||||
return callStack.in_error () || SUPER::in_error ();
|
||||
}
|
||||
|
||||
inline bool popSubrNum (const BiasedSubrs<SUBRS>& biasedSubrs, unsigned int &subr_num)
|
||||
{
|
||||
int n;
|
||||
if (unlikely ((!callStack.check_overflow (1) ||
|
||||
!SUPER::argStack.check_pop_int (n))))
|
||||
return false;
|
||||
int n = SUPER::argStack.pop_int ();
|
||||
n += biasedSubrs.bias;
|
||||
if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.subrs->count)))
|
||||
return false;
|
||||
|
@ -124,13 +126,11 @@ struct CSInterpEnv : InterpEnv<ARG>
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool returnFromSubr (void)
|
||||
inline void returnFromSubr (void)
|
||||
{
|
||||
if (unlikely (!callStack.check_underflow ()))
|
||||
return false;
|
||||
|
||||
if (unlikely (SUPER::substr.in_error ()))
|
||||
SUPER::set_error ();
|
||||
SUPER::substr = callStack.pop ();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void determine_hintmask_size (void)
|
||||
|
@ -212,25 +212,29 @@ struct PathProcsNull
|
|||
template <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=PathProcsNull<ENV, PARAM> >
|
||||
struct CSOpSet : OpSet<ARG>
|
||||
{
|
||||
static inline bool process_op (OpCode op, ENV &env, PARAM& param)
|
||||
static inline void process_op (OpCode op, ENV &env, PARAM& param)
|
||||
{
|
||||
switch (op) {
|
||||
|
||||
case OpCode_return:
|
||||
return env.returnFromSubr ();
|
||||
env.returnFromSubr ();
|
||||
break;
|
||||
case OpCode_endchar:
|
||||
env.set_endchar (true);
|
||||
OPSET::flush_args_and_op (op, env, param);
|
||||
break;
|
||||
|
||||
case OpCode_fixedcs:
|
||||
return env.argStack.push_fixed_from_substr (env.substr);
|
||||
env.argStack.push_fixed_from_substr (env.substr);
|
||||
break;
|
||||
|
||||
case OpCode_callsubr:
|
||||
return env.callSubr (env.localSubrs);
|
||||
|
||||
env.callSubr (env.localSubrs);
|
||||
break;
|
||||
|
||||
case OpCode_callgsubr:
|
||||
return env.callSubr (env.globalSubrs);
|
||||
env.callSubr (env.globalSubrs);
|
||||
break;
|
||||
|
||||
case OpCode_hstem:
|
||||
case OpCode_hstemhm:
|
||||
|
@ -305,9 +309,9 @@ struct CSOpSet : OpSet<ARG>
|
|||
break;
|
||||
|
||||
default:
|
||||
return SUPER::process_op (op, env);
|
||||
SUPER::process_op (op, env);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void process_hstem (OpCode op, ENV &env, PARAM& param)
|
||||
|
@ -686,9 +690,8 @@ struct CSInterpreter : Interpreter<ENV>
|
|||
SUPER::env.set_endchar (false);
|
||||
|
||||
for (;;) {
|
||||
OpCode op;
|
||||
if (unlikely (!SUPER::env.fetch_op (op) ||
|
||||
!OPSET::process_op (op, SUPER::env, param)))
|
||||
OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
|
||||
if (unlikely (SUPER::env.in_error ()))
|
||||
return false;
|
||||
if (SUPER::env.is_endchar ())
|
||||
break;
|
||||
|
|
|
@ -132,28 +132,26 @@ struct TopDictValues : DictValues<OPSTR>
|
|||
|
||||
struct DictOpSet : OpSet<Number>
|
||||
{
|
||||
static inline bool process_op (OpCode op, InterpEnv<Number>& env)
|
||||
static inline void process_op (OpCode op, InterpEnv<Number>& env)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_longintdict: /* 5-byte integer */
|
||||
return env.argStack.push_longint_from_substr (env.substr);
|
||||
env.argStack.push_longint_from_substr (env.substr);
|
||||
break;
|
||||
|
||||
case OpCode_BCD: /* real number */
|
||||
float v;
|
||||
if (unlikely (!env.argStack.check_overflow (1) || !parse_bcd (env.substr, v)))
|
||||
return false;
|
||||
env.argStack.push_real (v);
|
||||
return true;
|
||||
env.argStack.push_real (parse_bcd (env.substr));
|
||||
break;
|
||||
|
||||
default:
|
||||
return OpSet<Number>::process_op (op, env);
|
||||
OpSet<Number>::process_op (op, env);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool parse_bcd (SubByteStr& substr, float& v)
|
||||
static inline float parse_bcd (SubByteStr& substr)
|
||||
{
|
||||
v = 0.0f;
|
||||
float v = 0.0f;
|
||||
|
||||
bool neg = false;
|
||||
double int_part = 0;
|
||||
|
@ -171,7 +169,11 @@ struct DictOpSet : OpSet<Number>
|
|||
char d;
|
||||
if ((i & 1) == 0)
|
||||
{
|
||||
if (!substr.avail ()) return false;
|
||||
if (!substr.avail ())
|
||||
{
|
||||
substr.set_error ();
|
||||
return 0.0f;
|
||||
}
|
||||
byte = substr[0];
|
||||
substr.inc ();
|
||||
d = byte >> 4;
|
||||
|
@ -182,7 +184,8 @@ struct DictOpSet : OpSet<Number>
|
|||
switch (d)
|
||||
{
|
||||
case RESERVED:
|
||||
return false;
|
||||
substr.set_error ();
|
||||
return v;
|
||||
|
||||
case END:
|
||||
value = (double)(neg? -int_part: int_part);
|
||||
|
@ -195,16 +198,23 @@ struct DictOpSet : OpSet<Number>
|
|||
else
|
||||
value *= pow (10.0, (double)exp_part);
|
||||
}
|
||||
v = (float)value;
|
||||
return true;
|
||||
return (float)value;
|
||||
|
||||
case NEG:
|
||||
if (i != 0) return false;
|
||||
if (i != 0)
|
||||
{
|
||||
substr.set_error ();
|
||||
return 0.0f;
|
||||
}
|
||||
neg = true;
|
||||
break;
|
||||
|
||||
case DECIMAL:
|
||||
if (part != INT_PART) return false;
|
||||
if (part != INT_PART)
|
||||
{
|
||||
substr.set_error ();
|
||||
return v;
|
||||
}
|
||||
part = FRAC_PART;
|
||||
break;
|
||||
|
||||
|
@ -213,7 +223,11 @@ struct DictOpSet : OpSet<Number>
|
|||
HB_FALLTHROUGH;
|
||||
|
||||
case EXP_POS:
|
||||
if (part == EXP_PART) return false;
|
||||
if (part == EXP_PART)
|
||||
{
|
||||
substr.set_error ();
|
||||
return v;
|
||||
}
|
||||
part = EXP_PART;
|
||||
break;
|
||||
|
||||
|
@ -236,7 +250,7 @@ struct DictOpSet : OpSet<Number>
|
|||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline bool is_hint_op (OpCode op)
|
||||
|
@ -267,27 +281,24 @@ struct DictOpSet : OpSet<Number>
|
|||
template <typename VAL=OpStr>
|
||||
struct TopDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & dictval)
|
||||
static inline void process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_CharStrings:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.charStringsOffset)))
|
||||
return false;
|
||||
dictval.charStringsOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_FDArray:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.FDArrayOffset)))
|
||||
return false;
|
||||
dictval.FDArrayOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_FontMatrix:
|
||||
env.clear_args ();
|
||||
break;
|
||||
default:
|
||||
return DictOpSet::process_op (op, env);
|
||||
DictOpSet::process_op (op, env);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -299,9 +310,8 @@ struct DictInterpreter : Interpreter<ENV>
|
|||
param.init ();
|
||||
do
|
||||
{
|
||||
OpCode op;
|
||||
if (unlikely (!SUPER::env.fetch_op (op) ||
|
||||
!OPSET::process_op (op, SUPER::env, param)))
|
||||
OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param);
|
||||
if (unlikely (SUPER::env.in_error ()))
|
||||
return false;
|
||||
} while (SUPER::env.substr.avail ());
|
||||
|
||||
|
|
|
@ -41,12 +41,17 @@ struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
|
|||
SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs);
|
||||
processed_width = false;
|
||||
has_width = false;
|
||||
transient_array.init ();
|
||||
transient_array.resize (kTransientArraySize);
|
||||
for (unsigned int i = 0; i < kTransientArraySize; i++)
|
||||
transient_array[i].set_int (0);
|
||||
}
|
||||
|
||||
bool check_transient_array_index (unsigned int i) const
|
||||
{ return i < kTransientArraySize; }
|
||||
inline void fini (void)
|
||||
{
|
||||
transient_array.fini ();
|
||||
SUPER::fini ();
|
||||
}
|
||||
|
||||
inline unsigned int check_width (void)
|
||||
{
|
||||
|
@ -69,7 +74,7 @@ struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
|
|||
Number width;
|
||||
|
||||
static const unsigned int kTransientArraySize = 32;
|
||||
Number transient_array[kTransientArraySize];
|
||||
hb_vector_t<Number, kTransientArraySize> transient_array;
|
||||
|
||||
private:
|
||||
typedef CSInterpEnv<Number, CFF1Subrs> SUPER;
|
||||
|
@ -78,109 +83,114 @@ struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
|
|||
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF1CSInterpEnv, PARAM> >
|
||||
struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
||||
{
|
||||
static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param)
|
||||
static inline void process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param)
|
||||
{
|
||||
Number n1, n2;
|
||||
|
||||
switch (op) {
|
||||
|
||||
case OpCode_and:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_int ((n1.to_real() != 0.0f) && (n2.to_real() != 0.0f));
|
||||
break;
|
||||
case OpCode_or:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_int ((n1.to_real() != 0.0f) || (n2.to_real() != 0.0f));
|
||||
break;
|
||||
case OpCode_not:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push_int (n1.to_real() == 0.0f);
|
||||
break;
|
||||
case OpCode_abs:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push_real (fabs(n1.to_real ()));
|
||||
break;
|
||||
case OpCode_add:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_real (n1.to_real() + n2.to_real());
|
||||
break;
|
||||
case OpCode_sub:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_real (n1.to_real() - n2.to_real());
|
||||
break;
|
||||
case OpCode_div:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
if (unlikely (n2.to_real() == 0.0f))
|
||||
env.argStack.push_int (0);
|
||||
else
|
||||
env.argStack.push_real (n1.to_real() / n2.to_real());
|
||||
break;
|
||||
case OpCode_neg:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push_real (-n1.to_real ());
|
||||
break;
|
||||
case OpCode_eq:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_int (n1.to_real() == n2.to_real());
|
||||
break;
|
||||
case OpCode_drop:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
break;
|
||||
case OpCode_put:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2) ||
|
||||
!env.check_transient_array_index (n2.to_int ()))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.transient_array[n2.to_int ()] = n1;
|
||||
break;
|
||||
case OpCode_get:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1) ||
|
||||
!env.check_transient_array_index (n1.to_int ()))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push (env.transient_array[n1.to_int ()]);
|
||||
break;
|
||||
case OpCode_ifelse:
|
||||
{
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
bool test = n1.to_real () <= n2.to_real ();
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push (test? n1: n2);
|
||||
}
|
||||
break;
|
||||
case OpCode_random:
|
||||
if (unlikely (!env.argStack.check_overflow (1))) return false;
|
||||
env.argStack.push_int (1); /* we can't deal with random behavior; make it constant */
|
||||
break;
|
||||
case OpCode_mul:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push_real (n1.to_real() * n2.to_real());
|
||||
break;
|
||||
case OpCode_sqrt:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push_real ((float)sqrt (n1.to_real ()));
|
||||
break;
|
||||
case OpCode_dup:
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
env.argStack.push (n1);
|
||||
env.argStack.push (n1);
|
||||
break;
|
||||
case OpCode_exch:
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
env.argStack.push (n2);
|
||||
env.argStack.push (n1);
|
||||
break;
|
||||
case OpCode_index:
|
||||
{
|
||||
if (unlikely (!env.argStack.check_pop_num (n1))) return false;
|
||||
n1 = env.argStack.pop_num ();
|
||||
int i = n1.to_int ();
|
||||
if (i < 0) i = 0;
|
||||
if (unlikely ((unsigned int)i >= env.argStack.get_count () || !env.argStack.check_overflow (1))) return false;
|
||||
if (unlikely ((unsigned int)i >= env.argStack.get_count ()))
|
||||
{
|
||||
env.set_error ();
|
||||
return;
|
||||
}
|
||||
env.argStack.push (env.argStack[env.argStack.get_count () - i - 1]);
|
||||
}
|
||||
break;
|
||||
case OpCode_roll:
|
||||
{
|
||||
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
|
||||
env.argStack.pop_num2 (n1, n2);
|
||||
int n = n1.to_int ();
|
||||
int j = n2.to_int ();
|
||||
if (unlikely (n < 0 || (unsigned int)n > env.argStack.get_count ())) return false;
|
||||
if (unlikely (n < 0 || (unsigned int)n > env.argStack.get_count ()))
|
||||
{
|
||||
env.set_error ();
|
||||
return;
|
||||
}
|
||||
if (likely (n > 0))
|
||||
{
|
||||
if (j < 0)
|
||||
|
@ -195,11 +205,9 @@ struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
|
|||
}
|
||||
break;
|
||||
default:
|
||||
if (unlikely (!SUPER::process_op (op, env, param)))
|
||||
return false;
|
||||
SUPER::process_op (op, env, param);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void flush_args (CFF1CSInterpEnv &env, PARAM& param, unsigned int start_arg = 0)
|
||||
|
|
|
@ -99,17 +99,16 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
|||
SUPER::fini ();
|
||||
}
|
||||
|
||||
inline bool fetch_op (OpCode &op)
|
||||
inline OpCode fetch_op (void)
|
||||
{
|
||||
if (this->substr.avail ())
|
||||
return SUPER::fetch_op (op);
|
||||
return SUPER::fetch_op ();
|
||||
|
||||
/* make up return or endchar op */
|
||||
if (this->callStack.check_underflow ())
|
||||
op = OpCode_return;
|
||||
if (this->callStack.is_empty ())
|
||||
return OpCode_endchar;
|
||||
else
|
||||
op = OpCode_endchar;
|
||||
return true;
|
||||
return OpCode_return;
|
||||
}
|
||||
|
||||
inline const BlendArg& eval_arg (unsigned int i)
|
||||
|
@ -140,14 +139,11 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
|||
|
||||
inline void process_vsindex (void)
|
||||
{
|
||||
unsigned int index;
|
||||
if (likely (argStack.check_pop_uint (index)))
|
||||
unsigned int index = argStack.pop_uint ();
|
||||
if (do_blend)
|
||||
{
|
||||
if (do_blend)
|
||||
{
|
||||
if (likely (!seen_vsindex && !seen_blend))
|
||||
set_ivs (index);
|
||||
}
|
||||
if (likely (!seen_vsindex && !seen_blend))
|
||||
set_ivs (index);
|
||||
}
|
||||
seen_vsindex = true;
|
||||
}
|
||||
|
@ -192,40 +188,45 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
|
|||
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF2CSInterpEnv, PARAM> >
|
||||
struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
||||
{
|
||||
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param)
|
||||
static inline void process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_callsubr:
|
||||
case OpCode_callgsubr:
|
||||
/* a subroutine number shoudln't be a blended value */
|
||||
if (unlikely (env.argStack.peek ().blending ()))
|
||||
return false;
|
||||
return SUPER::process_op (op, env, param);
|
||||
{
|
||||
env.set_error ();
|
||||
break;
|
||||
}
|
||||
SUPER::process_op (op, env, param);
|
||||
break;
|
||||
|
||||
case OpCode_blendcs:
|
||||
return OPSET::process_blend (env, param);
|
||||
OPSET::process_blend (env, param);
|
||||
break;
|
||||
|
||||
case OpCode_vsindexcs:
|
||||
if (unlikely (env.argStack.peek ().blending ()))
|
||||
return false;
|
||||
{
|
||||
env.set_error ();
|
||||
break;
|
||||
}
|
||||
OPSET::process_vsindex (env, param);
|
||||
break;
|
||||
|
||||
default:
|
||||
return SUPER::process_op (op, env, param);
|
||||
SUPER::process_op (op, env, param);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param)
|
||||
static inline void process_blend (CFF2CSInterpEnv &env, PARAM& param)
|
||||
{
|
||||
unsigned int n, k;
|
||||
|
||||
env.process_blend ();
|
||||
k = env.get_region_count ();
|
||||
if (unlikely (!env.argStack.check_pop_uint (n) ||
|
||||
(k+1) * n > env.argStack.get_count ()))
|
||||
return false;
|
||||
n = env.argStack.pop_uint ();
|
||||
/* copy the blend values into blend array of the default values */
|
||||
unsigned int start = env.argStack.get_count () - ((k+1) * n);
|
||||
for (unsigned int i = 0; i < n; i++)
|
||||
|
@ -233,7 +234,6 @@ struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
|
|||
|
||||
/* pop off blend values leaving default values now adorned with blend values */
|
||||
env.argStack.pop (k * n);
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void process_vsindex (CFF2CSInterpEnv &env, PARAM& param)
|
||||
|
|
|
@ -531,7 +531,7 @@ struct CFF1StringIndex : CFF1Index
|
|||
TRACE_SERIALIZE (this);
|
||||
if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
|
||||
{
|
||||
if (!unlikely (c->extend_min (*this)))
|
||||
if (!unlikely (c->extend_min (this->count)))
|
||||
return_trace (false);
|
||||
count.set (0);
|
||||
return_trace (true);
|
||||
|
@ -678,7 +678,7 @@ struct CFF1TopDictValues : TopDictValues<CFF1TopDictVal>
|
|||
|
||||
struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
|
||||
{
|
||||
static inline bool process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval)
|
||||
static inline void process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval)
|
||||
{
|
||||
CFF1TopDictVal val;
|
||||
val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */
|
||||
|
@ -692,8 +692,7 @@ struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
|
|||
case OpCode_Weight:
|
||||
case OpCode_PostScript:
|
||||
case OpCode_BaseFontName:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::name_op_to_index (op)])))
|
||||
return false;
|
||||
dictval.nameSIDs[NameDictValues::name_op_to_index (op)] = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_isFixedPitch:
|
||||
|
@ -716,56 +715,49 @@ struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
|
|||
break;
|
||||
|
||||
case OpCode_CIDCount:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.cidCount)))
|
||||
return false;
|
||||
dictval.cidCount = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
case OpCode_ROS:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.ros_supplement) ||
|
||||
!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::ordering]) ||
|
||||
!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::registry])))
|
||||
return false;
|
||||
dictval.ros_supplement = env.argStack.pop_uint ();
|
||||
dictval.nameSIDs[NameDictValues::ordering] = env.argStack.pop_uint ();
|
||||
dictval.nameSIDs[NameDictValues::registry] = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
case OpCode_Encoding:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.EncodingOffset)))
|
||||
return false;
|
||||
dictval.EncodingOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
case OpCode_charset:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.CharsetOffset)))
|
||||
return false;
|
||||
dictval.CharsetOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
case OpCode_FDSelect:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset)))
|
||||
return false;
|
||||
dictval.FDSelectOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
case OpCode_Private:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset)))
|
||||
return false;
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
|
||||
return false;
|
||||
dictval.privateDictInfo.offset = env.argStack.pop_uint ();
|
||||
dictval.privateDictInfo.size = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
env.last_offset = env.substr.offset;
|
||||
if (unlikely (!TopDictOpSet<CFF1TopDictVal>::process_op (op, env, dictval)))
|
||||
return false;
|
||||
TopDictOpSet<CFF1TopDictVal>::process_op (op, env, dictval);
|
||||
/* Record this operand below if stack is empty, otherwise done */
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr, val);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -789,12 +781,11 @@ struct CFF1FontDictValues : DictValues<OpStr>
|
|||
|
||||
struct CFF1FontDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1FontDictValues& dictval)
|
||||
static inline void process_op (OpCode op, NumInterpEnv& env, CFF1FontDictValues& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_FontName:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.fontName)))
|
||||
return false;
|
||||
dictval.fontName = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_FontMatrix:
|
||||
|
@ -802,22 +793,20 @@ struct CFF1FontDictOpSet : DictOpSet
|
|||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_Private:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset)))
|
||||
return false;
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
|
||||
return false;
|
||||
dictval.privateDictInfo.offset = env.argStack.pop_uint ();
|
||||
dictval.privateDictInfo.size = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!DictOpSet::process_op (op, env)))
|
||||
return false;
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
DictOpSet::process_op (op, env);
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -856,7 +845,7 @@ typedef CFF1PrivateDictValues_Base<NumDictVal> CFF1PrivateDictValues;
|
|||
|
||||
struct CFF1PrivateDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues& dictval)
|
||||
static inline void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues& dictval)
|
||||
{
|
||||
NumDictVal val;
|
||||
val.init ();
|
||||
|
@ -868,8 +857,7 @@ struct CFF1PrivateDictOpSet : DictOpSet
|
|||
case OpCode_FamilyOtherBlues:
|
||||
case OpCode_StemSnapH:
|
||||
case OpCode_StemSnapV:
|
||||
if (unlikely (!env.argStack.check_pop_delta (val.multi_val)))
|
||||
return false;
|
||||
env.argStack.pop_delta (val.multi_val);
|
||||
break;
|
||||
case OpCode_StdHW:
|
||||
case OpCode_StdVW:
|
||||
|
@ -882,31 +870,29 @@ struct CFF1PrivateDictOpSet : DictOpSet
|
|||
case OpCode_initialRandomSeed:
|
||||
case OpCode_defaultWidthX:
|
||||
case OpCode_nominalWidthX:
|
||||
if (unlikely (!env.argStack.check_pop_num (val.single_val)))
|
||||
return false;
|
||||
val.single_val = env.argStack.pop_num ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_Subrs:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
|
||||
return false;
|
||||
dictval.subrsOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!DictOpSet::process_op (op, env)))
|
||||
return false;
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
DictOpSet::process_op (op, env);
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr, val);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct CFF1PrivateDictOpSet_Subset : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues_Subset& dictval)
|
||||
static inline void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues_Subset& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_BlueValues:
|
||||
|
@ -930,20 +916,19 @@ struct CFF1PrivateDictOpSet_Subset : DictOpSet
|
|||
break;
|
||||
|
||||
case OpCode_Subrs:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
|
||||
return false;
|
||||
dictval.subrsOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!DictOpSet::process_op (op, env)))
|
||||
return false;
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
DictOpSet::process_op (op, env);
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -176,7 +176,7 @@ struct CFF2TopDictValues : TopDictValues<>
|
|||
|
||||
struct CFF2TopDictOpSet : TopDictOpSet<>
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2TopDictValues& dictval)
|
||||
static inline void process_op (OpCode op, NumInterpEnv& env, CFF2TopDictValues& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_FontMatrix:
|
||||
|
@ -189,25 +189,23 @@ struct CFF2TopDictOpSet : TopDictOpSet<>
|
|||
break;
|
||||
|
||||
case OpCode_vstore:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.vstoreOffset)))
|
||||
return false;
|
||||
dictval.vstoreOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_FDSelect:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset)))
|
||||
return false;
|
||||
dictval.FDSelectOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!SUPER::process_op (op, env, dictval)))
|
||||
return false;
|
||||
SUPER::process_op (op, env, dictval);
|
||||
/* Record this operand below if stack is empty, otherwise done */
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef TopDictOpSet<> SUPER;
|
||||
|
@ -231,26 +229,24 @@ struct CFF2FontDictValues : DictValues<OpStr>
|
|||
|
||||
struct CFF2FontDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2FontDictValues& dictval)
|
||||
static inline void process_op (OpCode op, NumInterpEnv& env, CFF2FontDictValues& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_Private:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset)))
|
||||
return false;
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
|
||||
return false;
|
||||
dictval.privateDictInfo.offset = env.argStack.pop_uint ();
|
||||
dictval.privateDictInfo.size = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!SUPER::process_op (op, env)))
|
||||
return false;
|
||||
SUPER::process_op (op, env);
|
||||
if (!env.argStack.is_empty ())
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -303,10 +299,9 @@ struct CFF2PrivDictInterpEnv : NumInterpEnv
|
|||
|
||||
inline void process_vsindex (void)
|
||||
{
|
||||
unsigned int index;
|
||||
if (likely (!seen_vsindex && argStack.check_pop_uint (index)))
|
||||
if (likely (!seen_vsindex))
|
||||
{
|
||||
set_ivs (argStack.check_pop_uint (index));
|
||||
set_ivs (argStack.pop_uint ());
|
||||
}
|
||||
seen_vsindex = true;
|
||||
}
|
||||
|
@ -321,7 +316,7 @@ struct CFF2PrivDictInterpEnv : NumInterpEnv
|
|||
|
||||
struct CFF2PrivateDictOpSet : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues& dictval)
|
||||
static inline void process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues& dictval)
|
||||
{
|
||||
NumDictVal val;
|
||||
val.init ();
|
||||
|
@ -334,8 +329,7 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
|||
case OpCode_BlueFuzz:
|
||||
case OpCode_ExpansionFactor:
|
||||
case OpCode_LanguageGroup:
|
||||
if (unlikely (!env.argStack.check_pop_num (val.single_val)))
|
||||
return false;
|
||||
val.single_val = env.argStack.pop_num ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_BlueValues:
|
||||
|
@ -344,13 +338,11 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
|||
case OpCode_FamilyOtherBlues:
|
||||
case OpCode_StemSnapH:
|
||||
case OpCode_StemSnapV:
|
||||
if (unlikely (!env.argStack.check_pop_delta (val.multi_val)))
|
||||
return false;
|
||||
env.argStack.pop_delta (val.multi_val);
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_Subrs:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
|
||||
return false;
|
||||
dictval.subrsOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_vsindexdict:
|
||||
|
@ -361,20 +353,20 @@ struct CFF2PrivateDictOpSet : DictOpSet
|
|||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!DictOpSet::process_op (op, env)))
|
||||
return false;
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
DictOpSet::process_op (op, env);
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr, val);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct CFF2PrivateDictOpSet_Subset : DictOpSet
|
||||
{
|
||||
static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues_Subset& dictval)
|
||||
static inline void process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues_Subset& dictval)
|
||||
{
|
||||
switch (op) {
|
||||
case OpCode_BlueValues:
|
||||
|
@ -395,23 +387,22 @@ struct CFF2PrivateDictOpSet_Subset : DictOpSet
|
|||
|
||||
case OpCode_blenddict:
|
||||
env.clear_args ();
|
||||
return true;
|
||||
return;
|
||||
|
||||
case OpCode_Subrs:
|
||||
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
|
||||
return false;
|
||||
dictval.subrsOffset = env.argStack.pop_uint ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
|
||||
default:
|
||||
if (unlikely (!SUPER::process_op (op, env)))
|
||||
return false;
|
||||
if (!env.argStack.is_empty ()) return true;
|
||||
SUPER::process_op (op, env);
|
||||
if (!env.argStack.is_empty ()) return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely (env.in_error ())) return;
|
||||
|
||||
dictval.addOp (op, env.substr);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
Loading…
Reference in New Issue