drop hints from CFF1 charstrings

renamed confusing Stack.size to Stack.count
pull/1113/head
Michiharu Ariza 6 years ago
parent 8c5e03b541
commit 968168bf0e
  1. 43
      src/hb-cff-interp-common.hh
  2. 140
      src/hb-cff-interp-cs-common.hh
  3. 4
      src/hb-cff-interp-dict-common.hh
  4. 14
      src/hb-cff1-interp-cs.hh
  5. 18
      src/hb-cff2-interp-cs.hh
  6. 26
      src/hb-ot-cff1-table.hh
  7. 20
      src/hb-ot-cff2-table.hh
  8. 53
      src/hb-subset-cff1.cc
  9. 69
      src/hb-subset-cff2.cc

@ -379,40 +379,40 @@ inline float parse_bcd (SubByteStr& substr, float& v)
template <typename ELEM, int LIMIT> template <typename ELEM, int LIMIT>
struct Stack struct Stack
{ {
inline void init (void) { size = 0; } inline void init (void) { count = 0; }
inline void fini (void) { } inline void fini (void) { }
inline void push (const ELEM &v) inline void push (const ELEM &v)
{ {
if (likely (size < kSizeLimit)) if (likely (count < kSizeLimit))
elements[size++] = v; elements[count++] = v;
} }
inline const ELEM& pop (void) inline const ELEM& pop (void)
{ {
if (likely (size > 0)) if (likely (count > 0))
return elements[--size]; return elements[--count];
else else
return Null(ELEM); return Null(ELEM);
} }
inline void unpop (void) inline void unpop (void)
{ {
if (likely (size < kSizeLimit)) if (likely (count < kSizeLimit))
size++; count++;
} }
inline void clear (void) { size = 0; } inline void clear (void) { count = 0; }
inline bool check_overflow (unsigned int count=1) const { return (count <= kSizeLimit) && (count + size <= kSizeLimit); } inline bool check_overflow (unsigned int n=1) const { return (n <= kSizeLimit) && (n + count <= kSizeLimit); }
inline bool check_underflow (unsigned int count=1) const { return (count <= size); } inline bool check_underflow (unsigned int n=1) const { return (n <= count); }
inline unsigned int get_size (void) const { return size; } inline unsigned int get_count (void) const { return count; }
inline bool is_empty (void) const { return size == 0; } inline bool is_empty (void) const { return count == 0; }
static const unsigned int kSizeLimit = LIMIT; static const unsigned int kSizeLimit = LIMIT;
unsigned int size; unsigned int count;
ELEM elements[kSizeLimit]; ELEM elements[kSizeLimit];
}; };
@ -469,11 +469,11 @@ struct ArgStack : Stack<Number, 513>
inline bool check_pop_delta (hb_vector_t<Number>& vec, bool even=false) inline bool check_pop_delta (hb_vector_t<Number>& vec, bool even=false)
{ {
if (even && unlikely ((this->size & 1) != 0)) if (even && unlikely ((this->count & 1) != 0))
return false; return false;
float val = 0.0f; float val = 0.0f;
for (unsigned int i = 0; i < size; i++) { for (unsigned int i = 0; i < count; i++) {
val += elements[i].to_real (); val += elements[i].to_real ();
Number *n = vec.push (); Number *n = vec.push ();
n->set_real (val); n->set_real (val);
@ -564,6 +564,17 @@ struct InterpEnv
return true; return true;
} }
inline void pop_n_args (unsigned int n)
{
assert (n <= argStack.count);
argStack.count -= n;
}
inline void clear_args (void)
{
pop_n_args (argStack.count);
}
SubByteStr substr; SubByteStr substr;
ArgStack argStack; ArgStack argStack;
}; };
@ -604,7 +615,7 @@ struct OpSet
env.argStack.push_int ((int)op - 139); env.argStack.push_int ((int)op - 139);
} else { } else {
/* invalid unknown operator */ /* invalid unknown operator */
env.argStack.clear (); env.clear_args ();
return false; return false;
} }
break; break;

@ -64,7 +64,6 @@ struct CSInterpEnv : InterpEnv
{ {
InterpEnv::init (str); InterpEnv::init (str);
stack_cleared = false;
seen_moveto = true; seen_moveto = true;
seen_hintmask = false; seen_hintmask = false;
hstem_count = 0; hstem_count = 0;
@ -121,25 +120,17 @@ struct CSInterpEnv : InterpEnv
{ {
if (!seen_hintmask) if (!seen_hintmask)
{ {
vstem_count += argStack.size / 2; vstem_count += argStack.get_count() / 2;
hintmask_size = (hstem_count + vstem_count + 7) >> 3; hintmask_size = (hstem_count + vstem_count + 7) >> 3;
seen_hintmask = true; seen_hintmask = true;
} }
} }
inline void clear_stack (void)
{
stack_cleared = true;
argStack.clear ();
}
inline void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; } inline void set_endchar (bool endchar_flag_) { endchar_flag = endchar_flag_; }
inline bool is_endchar (void) const { return endchar_flag; } inline bool is_endchar (void) const { return endchar_flag; }
inline bool is_stack_cleared (void) const { return stack_cleared; }
public: public:
bool endchar_flag; bool endchar_flag;
bool stack_cleared;
bool seen_moveto; bool seen_moveto;
bool seen_hintmask; bool seen_hintmask;
@ -162,7 +153,8 @@ struct CSOpSet : OpSet
return env.returnFromSubr (); return env.returnFromSubr ();
case OpCode_endchar: case OpCode_endchar:
env.set_endchar (true); env.set_endchar (true);
return true; OPSET::flush_op (op, env, param);
break;
case OpCode_fixedcs: case OpCode_fixedcs:
return env.argStack.push_fixed_from_substr (env.substr); return env.argStack.push_fixed_from_substr (env.substr);
@ -175,19 +167,15 @@ struct CSOpSet : OpSet
case OpCode_hstem: case OpCode_hstem:
case OpCode_hstemhm: case OpCode_hstemhm:
OPSET::process_hstem (env, param); OPSET::process_hstem (op, env, param);
break; break;
case OpCode_vstem: case OpCode_vstem:
case OpCode_vstemhm: case OpCode_vstemhm:
OPSET::process_vstem (env, param); OPSET::process_vstem (op, env, param);
break; break;
case OpCode_hintmask: case OpCode_hintmask:
case OpCode_cntrmask: case OpCode_cntrmask:
env.determine_hintmask_size (); OPSET::process_hintmask (op, env, param);
OPSET::flush_stack (env, param);
if (unlikely (!env.substr.avail (env.hintmask_size)))
return false;
env.substr.inc (env.hintmask_size);
break; break;
case OpCode_vmoveto: case OpCode_vmoveto:
@ -196,7 +184,7 @@ struct CSOpSet : OpSet
case OpCode_vlineto: case OpCode_vlineto:
case OpCode_rmoveto: case OpCode_rmoveto:
case OpCode_hmoveto: case OpCode_hmoveto:
OPSET::process_moveto (env, param); OPSET::process_moveto (op, env, param);
break; break;
case OpCode_rrcurveto: case OpCode_rrcurveto:
case OpCode_rcurveline: case OpCode_rcurveline:
@ -205,11 +193,14 @@ struct CSOpSet : OpSet
case OpCode_hhcurveto: case OpCode_hhcurveto:
case OpCode_vhcurveto: case OpCode_vhcurveto:
case OpCode_hvcurveto: case OpCode_hvcurveto:
OPSET::process_path (op, env, param);
break;
case OpCode_hflex: case OpCode_hflex:
case OpCode_flex: case OpCode_flex:
case OpCode_hflex1: case OpCode_hflex1:
case OpCode_flex1: case OpCode_flex1:
OPSET::flush_stack (env, param); OPSET::process_flex (op, env, param);
break; break;
default: default:
@ -218,87 +209,76 @@ struct CSOpSet : OpSet
return true; return true;
} }
static inline void process_hstem (ENV &env, PARAM& param) static inline void process_hstem (OpCode op, ENV &env, PARAM& param)
{
env.hstem_count += env.argStack.count / 2;
OPSET::flush_args_and_op (op, env, param);
}
static inline void process_vstem (OpCode op, ENV &env, PARAM& param)
{
env.vstem_count += env.argStack.count / 2;
OPSET::flush_args_and_op (op, env, param);
}
static inline void process_hintmask (OpCode op, ENV &env, PARAM& param)
{ {
env.hstem_count += env.argStack.size / 2; env.determine_hintmask_size ();
OPSET::flush_stack (env, param); if (likely (env.substr.avail (env.hintmask_size)))
{
OPSET::flush_hintmask (op, env, param);
env.substr.inc (env.hintmask_size);
}
} }
static inline void process_vstem (ENV &env, PARAM& param) static inline void process_flex (OpCode op, ENV &env, PARAM& param)
{ {
env.vstem_count += env.argStack.size / 2; OPSET::flush_args_and_op (op, env, param);
OPSET::flush_stack (env, param);
} }
static inline void process_moveto (ENV &env, PARAM& param) static inline void process_moveto (OpCode op, ENV &env, PARAM& param)
{ {
if (!env.seen_moveto) if (!env.seen_moveto)
{ {
env.determine_hintmask_size (); env.determine_hintmask_size ();
env.seen_moveto = true; env.seen_moveto = true;
} }
OPSET::flush_stack (env, param); OPSET::flush_args_and_op (op, env, param);
} }
static inline void flush_stack (ENV &env, PARAM& param) static inline void process_path (OpCode op, ENV &env, PARAM& param)
{ {
env.clear_stack (); OPSET::flush_args_and_op (op, env, param);
} }
/* numeric / logical / arithmetic operators */ static inline void flush_args_and_op (OpCode op, ENV &env, PARAM& param)
static inline bool is_arg_op (OpCode op)
{ {
switch (op) OPSET::flush_n_args_and_op (op, env.argStack.count, env, param);
{
case OpCode_shortint:
case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1:
case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3:
case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1:
case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3:
case OpCode_fixedcs:
case OpCode_and:
case OpCode_or:
case OpCode_not:
case OpCode_abs:
case OpCode_add:
case OpCode_sub:
case OpCode_div:
case OpCode_neg:
case OpCode_eq:
case OpCode_drop:
case OpCode_put:
case OpCode_get:
case OpCode_ifelse:
case OpCode_random:
case OpCode_mul:
case OpCode_sqrt:
case OpCode_dup:
case OpCode_exch:
case OpCode_index:
case OpCode_roll:
return true;
default:
return (OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast);
}
} }
/* hint operators (excluding hint/counter mask) */ static inline void flush_n_args_and_op (OpCode op, unsigned int n, ENV &env, PARAM& param)
static inline bool is_hint_op (OpCode op)
{ {
switch (op) OPSET::flush_n_args (n, env, param);
{ OPSET::flush_op (op, env, param);
case OpCode_hstem: }
case OpCode_vstem:
case OpCode_hstemhm: static inline void flush_args (ENV &env, PARAM& param)
case OpCode_vstemhm: {
case OpCode_hflex: OPSET::flush_n_args (env.argStack.count, env, param);
case OpCode_flex: }
case OpCode_hflex1:
case OpCode_flex1: static inline void flush_n_args (unsigned int n, ENV &env, PARAM& param)
return true; {
default: env.pop_n_args (n);
return false; }
}
static inline void flush_op (OpCode op, ENV &env, PARAM& param)
{
}
static inline void flush_hintmask (OpCode op, ENV &env, PARAM& param)
{
OPSET::flush_args_and_op (op, env, param);
} }
static inline bool is_subr_op (OpCode op) static inline bool is_subr_op (OpCode op)

@ -169,12 +169,12 @@ struct TopDictOpSet : DictOpSet
case OpCode_CharStrings: case OpCode_CharStrings:
if (unlikely (!env.argStack.check_pop_uint (dictval.charStringsOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.charStringsOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_FDArray: case OpCode_FDArray:
if (unlikely (!env.argStack.check_pop_uint (dictval.FDArrayOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.FDArrayOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
return DictOpSet::process_op (op, env); return DictOpSet::process_op (op, env);

@ -51,7 +51,7 @@ struct CFF1CSInterpEnv : CSInterpEnv<CFF1Subrs>
{ {
if (!processed_width) if (!processed_width)
{ {
if ((this->argStack.size & 1) != 0) if ((this->argStack.count & 1) != 0)
{ {
width = this->argStack.elements[0]; width = this->argStack.elements[0];
has_width = true; has_width = true;
@ -163,8 +163,8 @@ struct CFF1CSOpSet : CSOpSet<OPSET, CFF1CSInterpEnv, PARAM>
if (unlikely (!env.argStack.check_pop_num (n1))) return false; if (unlikely (!env.argStack.check_pop_num (n1))) return false;
int i = n1.to_int (); int i = n1.to_int ();
if (i < 0) i = 0; if (i < 0) i = 0;
if (unlikely (i >= env.argStack.size || !env.argStack.check_overflow (1))) return false; if (unlikely (i >= env.argStack.count || !env.argStack.check_overflow (1))) return false;
env.argStack.push (env.argStack.elements[env.argStack.size - i - 1]); env.argStack.push (env.argStack.elements[env.argStack.count - i - 1]);
} }
break; break;
case OpCode_roll: case OpCode_roll:
@ -172,13 +172,13 @@ struct CFF1CSOpSet : CSOpSet<OPSET, CFF1CSInterpEnv, PARAM>
if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false;
int n = n1.to_int (); int n = n1.to_int ();
int j = n2.to_int (); int j = n2.to_int ();
if (unlikely (n < 0 || n > env.argStack.size)) return false; if (unlikely (n < 0 || n > env.argStack.count)) return false;
if (likely (n > 0)) if (likely (n > 0))
{ {
if (j < 0) if (j < 0)
j = n - (-j % n); j = n - (-j % n);
j %= n; j %= n;
unsigned int top = env.argStack.size - 1; unsigned int top = env.argStack.count - 1;
unsigned int bot = top - n + 1; unsigned int bot = top - n + 1;
env.argStack.reverse_range (top - j + 1, top); env.argStack.reverse_range (top - j + 1, top);
env.argStack.reverse_range (bot, top - j); env.argStack.reverse_range (bot, top - j);
@ -194,10 +194,10 @@ struct CFF1CSOpSet : CSOpSet<OPSET, CFF1CSInterpEnv, PARAM>
return true; return true;
} }
static inline void flush_stack (CFF1CSInterpEnv &env, PARAM& param) static inline void flush_args (CFF1CSInterpEnv &env, PARAM& param)
{ {
env.check_width (); env.check_width ();
SUPER::flush_stack (env, param); SUPER::flush_args (env, param);
} }
private: private:

@ -54,13 +54,11 @@ struct CFF2CSInterpEnv : CSInterpEnv<CFF2Subrs>
return true; return true;
} }
inline bool process_vsindex (void) inline void process_vsindex (void)
{ {
unsigned int index; unsigned int index;
if (unlikely (!argStack.check_pop_uint (index))) if (likely (argStack.check_pop_uint (index)))
return false; set_ivs (argStack.check_pop_uint (index));
set_ivs (index);
return true;
} }
inline unsigned int get_ivs (void) const { return ivs; } inline unsigned int get_ivs (void) const { return ivs; }
@ -81,7 +79,8 @@ struct CFF2CSOpSet : CSOpSet<OPSET, CFF2CSInterpEnv, PARAM>
return OPSET::process_blend (env, param); return OPSET::process_blend (env, param);
case OpCode_vsindexcs: case OpCode_vsindexcs:
return OPSET::process_vsindex (env, param); OPSET::process_vsindex (env, param);
break;
default: default:
typedef CSOpSet<OPSET, CFF2CSInterpEnv, PARAM> SUPER; typedef CSOpSet<OPSET, CFF2CSInterpEnv, PARAM> SUPER;
@ -95,13 +94,14 @@ struct CFF2CSOpSet : CSOpSet<OPSET, CFF2CSInterpEnv, PARAM>
static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param) static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param)
{ {
// XXX: TODO leave default values? // XXX: TODO leave default values?
OPSET::flush_stack (env, param); OPSET::flush_args (env, param);
return true; return true;
} }
static inline bool process_vsindex (CFF2CSInterpEnv &env, PARAM& param) static inline void process_vsindex (CFF2CSInterpEnv &env, PARAM& param)
{ {
return env.process_vsindex (); env.process_vsindex ();
OPSET::flush_n_args_and_op (OpCode_vsindexcs, 1, env, param);
} }
}; };

@ -437,13 +437,13 @@ struct CFF1TopDictOpSet : TopDictOpSet
case OpCode_FontBBox: case OpCode_FontBBox:
case OpCode_XUID: case OpCode_XUID:
case OpCode_BaseFontBlend: case OpCode_BaseFontBlend:
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_CIDCount: case OpCode_CIDCount:
if (unlikely (!env.argStack.check_pop_uint (dictval.cidCount))) if (unlikely (!env.argStack.check_pop_uint (dictval.cidCount)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_ROS: case OpCode_ROS:
@ -451,25 +451,25 @@ struct CFF1TopDictOpSet : TopDictOpSet
!env.argStack.check_pop_uint (dictval.ros[1]) || !env.argStack.check_pop_uint (dictval.ros[1]) ||
!env.argStack.check_pop_uint (dictval.ros[0]))) !env.argStack.check_pop_uint (dictval.ros[0])))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Encoding: case OpCode_Encoding:
if (unlikely (!env.argStack.check_pop_uint (dictval.EncodingOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.EncodingOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_charset: case OpCode_charset:
if (unlikely (!env.argStack.check_pop_uint (dictval.CharsetOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.CharsetOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_FDSelect: case OpCode_FDSelect:
if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Private: case OpCode_Private:
@ -477,7 +477,7 @@ struct CFF1TopDictOpSet : TopDictOpSet
return false; return false;
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
@ -517,14 +517,14 @@ struct CFF1FontDictOpSet : DictOpSet
case OpCode_FontName: case OpCode_FontName:
case OpCode_FontMatrix: case OpCode_FontMatrix:
case OpCode_PaintType: case OpCode_PaintType:
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Private: case OpCode_Private:
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset))) if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset)))
return false; return false;
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
@ -602,12 +602,12 @@ struct CFF1PrivateDictOpSet : DictOpSet
case OpCode_nominalWidthX: case OpCode_nominalWidthX:
if (unlikely (!env.argStack.check_pop_num (val.single_val))) if (unlikely (!env.argStack.check_pop_num (val.single_val)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Subrs: case OpCode_Subrs:
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
@ -644,13 +644,13 @@ struct CFF1PrivateDictOpSet_Subset : DictOpSet
case OpCode_initialRandomSeed: case OpCode_initialRandomSeed:
case OpCode_defaultWidthX: case OpCode_defaultWidthX:
case OpCode_nominalWidthX: case OpCode_nominalWidthX:
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Subrs: case OpCode_Subrs:
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:

@ -183,19 +183,19 @@ struct CFF2TopDictOpSet : TopDictOpSet
DictVal val; DictVal val;
val.init (); val.init ();
dictval.pushVal (op, env.substr); dictval.pushVal (op, env.substr);
env.argStack.clear (); env.clear_args ();
} }
break; break;
case OpCode_vstore: case OpCode_vstore:
if (unlikely (!env.argStack.check_pop_uint (dictval.vstoreOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.vstoreOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_FDSelect: case OpCode_FDSelect:
if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
@ -236,7 +236,7 @@ struct CFF2FontDictOpSet : DictOpSet
return false; return false;
if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:
@ -301,7 +301,7 @@ struct CFF2PrivateDictOpSet : DictOpSet
case OpCode_LanguageGroup: case OpCode_LanguageGroup:
if (unlikely (!env.argStack.check_pop_num (val.single_val))) if (unlikely (!env.argStack.check_pop_num (val.single_val)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_BlueValues: case OpCode_BlueValues:
case OpCode_OtherBlues: case OpCode_OtherBlues:
@ -311,12 +311,12 @@ struct CFF2PrivateDictOpSet : DictOpSet
case OpCode_StemSnapV: case OpCode_StemSnapV:
if (unlikely (!env.argStack.check_pop_delta (val.multi_val))) if (unlikely (!env.argStack.check_pop_delta (val.multi_val)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_Subrs: case OpCode_Subrs:
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_vsindexdict: case OpCode_vsindexdict:
case OpCode_blenddict: case OpCode_blenddict:
@ -353,17 +353,17 @@ struct CFF2PrivateDictOpSet_Subset : DictOpSet
case OpCode_StemSnapV: case OpCode_StemSnapV:
case OpCode_LanguageGroup: case OpCode_LanguageGroup:
case OpCode_ExpansionFactor: case OpCode_ExpansionFactor:
env.argStack.clear (); env.clear_args ();
break; break;
case OpCode_blenddict: case OpCode_blenddict:
env.argStack.clear (); env.clear_args ();
return true; return true;
case OpCode_Subrs: case OpCode_Subrs:
if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset)))
return false; return false;
env.argStack.clear (); env.clear_args ();
break; break;
default: default:

@ -106,43 +106,50 @@ struct CFF1TopDict_OpSerializer : CFFTopDict_OpSerializer
struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam> struct CFF1CSOpSet_Flatten : CFF1CSOpSet<CFF1CSOpSet_Flatten, FlattenParam>
{ {
static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param) static inline void flush_args_and_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
{ {
if (param.drop_hints && CSOPSET::is_hint_op (op))
{
env.clear_stack ();
return true;
}
if (unlikely (!SUPER::process_op (op, env, param)))
return false;
switch (op) switch (op)
{ {
case OpCode_hstem:
case OpCode_hstemhm:
case OpCode_vstem:
case OpCode_vstemhm:
case OpCode_hintmask: case OpCode_hintmask:
case OpCode_cntrmask: case OpCode_cntrmask:
case OpCode_hflex:
case OpCode_flex:
case OpCode_hflex1:
case OpCode_flex1:
if (param.drop_hints) if (param.drop_hints)
{ {
env.clear_stack (); env.clear_args ();
return true; return;
} }
if (unlikely (!param.flatStr.encode_op (op))) /* NO BREAK */
return false;
for (int i = -env.hintmask_size; i < 0; i++)
if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
return false;
break;
default: default:
if (!CSOPSET::is_subr_op (op) && SUPER::flush_args_and_op (op, env, param);
!CSOPSET::is_arg_op (op)) break;
return param.flatStr.encode_op (op);
} }
return true;
} }
static inline void flush_stack (CFF1CSInterpEnv &env, FlattenParam& param) static inline void flush_n_args (unsigned int n, CFF1CSInterpEnv &env, FlattenParam& param)
{ {
for (unsigned int i = 0; i < env.argStack.size; i++) for (unsigned int i = env.argStack.count - n; i < env.argStack.count; i++)
param.flatStr.encode_num (env.argStack.elements[i]); param.flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, param); SUPER::flush_n_args (n, env, param);
}
static inline void flush_op (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
{
param.flatStr.encode_op (op);
}
static inline void flush_hintmask (OpCode op, CFF1CSInterpEnv &env, FlattenParam& param)
{
SUPER::flush_hintmask (op, env, param);
for (unsigned int i = 0; i < env.hintmask_size; i++)
param.flatStr.encode_byte (env.substr[i]);
} }
private: private:

@ -77,59 +77,54 @@ struct CFF2TopDict_OpSerializer : CFFTopDict_OpSerializer
struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam> struct CFF2CSOpSet_Flatten : CFF2CSOpSet<CFF2CSOpSet_Flatten, FlattenParam>
{ {
static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param) static inline bool process_blend (CFF2CSInterpEnv &env, FlattenParam& param)
{
flush_args (env, param);
return true;
}
static inline void flush_args_and_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
{ {
if (param.drop_hints && CSOPSET::is_hint_op (op))
{
env.clear_stack ();
return true;
}
if (unlikely (!SUPER::process_op (op, env, param)))
return false;
switch (op) switch (op)
{ {
case OpCode_return:
case OpCode_endchar:
/* dummy opcodes in CFF2. ignore */
break;
case OpCode_hstem:
case OpCode_hstemhm:
case OpCode_vstem:
case OpCode_vstemhm:
case OpCode_hintmask: case OpCode_hintmask:
case OpCode_cntrmask: case OpCode_cntrmask:
case OpCode_hflex:
case OpCode_flex:
case OpCode_hflex1:
case OpCode_flex1:
if (param.drop_hints) if (param.drop_hints)
{ {
env.clear_stack (); env.clear_args ();
return true; return;
} }
if (unlikely (!param.flatStr.encode_op (op))) /* NO BREAK */
return false;
for (int i = -env.hintmask_size; i < 0; i++)
if (unlikely (!param.flatStr.encode_byte (env.substr[i])))
return false;
break;
case OpCode_return:
case OpCode_endchar:
/* dummy opcodes in CFF2. ignore */
break;
default: default:
if (!CSOPSET::is_subr_op (op) && SUPER::flush_args_and_op (op, env, param);
!CSOPSET::is_arg_op (op)) break;
return param.flatStr.encode_op (op);
} }
return true;
} }
static inline bool process_blend (CFF2CSInterpEnv &env, FlattenParam& param) static inline void flush_n_args (unsigned int n, CFF2CSInterpEnv &env, FlattenParam& param)
{ {
flush_stack (env, param); for (unsigned int i = env.argStack.count - n; i < env.argStack.count; i++)
return true; param.flatStr.encode_num (env.argStack.elements[i]);
} SUPER::flush_n_args (n, env, param);
static inline bool process_vsindex (CFF2CSInterpEnv &env, FlattenParam& param)
{
flush_stack (env, param);
return true;
} }
static inline void flush_stack (CFF2CSInterpEnv &env, FlattenParam& param) static inline void flush_op (OpCode op, CFF2CSInterpEnv &env, FlattenParam& param)
{ {
for (unsigned int i = 0; i < env.argStack.size; i++) param.flatStr.encode_op (op);
param.flatStr.encode_num (env.argStack.elements[i]);
SUPER::flush_stack (env, param);
} }
private: private:

Loading…
Cancel
Save