Removed parsed hint fields from CFF2PrivateDictValues

Instead moved & stored uniformly in values vector (renamed from opstrs)
This should be fine as we aren't likely going to use them as hints after all
Templatized DictValues whether to parse them out
For subsetter, they aren't parsed
This commit is contained in:
Michiharu Ariza 2018-08-03 14:35:09 -07:00
parent 76f7397c10
commit 00970dd242
3 changed files with 120 additions and 180 deletions

View File

@ -136,6 +136,23 @@ enum OpCode {
inline OpCode Make_OpCode_ESC (unsigned char byte2) { return (OpCode)(OpCode_ESC_Base + byte2); }
inline unsigned int OpCode_Size (OpCode op) { return (op >= OpCode_ESC_Base)? 2: 1; }
struct Number
{
inline Number (void) { set_int (0); }
inline void set_int (int v) { is_real = false; u.int_val = v; };
inline int to_int (void) const { return is_real? (int)u.real_val: u.int_val; }
inline void set_real (float v) { is_real = true; u.real_val = v; };
inline float to_real (void) const { return is_real? u.real_val: (float)u.int_val; }
protected:
bool is_real;
union {
int int_val;
float real_val;
} u;
};
/* pair of table offset and length */
struct offset_size_pair {
unsigned int offset;
@ -363,36 +380,62 @@ struct IndexOf : Index
/* an operator prefixed by its operands in a byte string */
struct OpStr
{
inline void init (void) {}
OpCode op;
ByteStr str;
};
typedef hb_vector_t <OpStr> OpStrs;
/* an opstr and the parsed out dict value(s) */
struct DictVal : OpStr
{
inline void init (void)
{
single_val.set_int (0);
multi_val.init ();
}
/* base param type for dict parsing */
inline void fini (void)
{
multi_val.fini ();
}
Number single_val;
hb_vector_t<Number> multi_val;
};
template <typename VAL>
struct DictValues
{
inline void init (void)
{
opStart = 0;
opStrs.init ();
values.init ();
}
inline void fini (void)
{
opStrs.fini ();
values.fini ();
}
void pushOpStr (OpCode op, const ByteStr& str, unsigned int offset)
inline void pushVal (OpCode op, const ByteStr& str, unsigned int offset)
{
OpStr *opstr = opStrs.push ();
opstr->op = op;
opstr->str = ByteStr (str, opStart, offset - opStart);
VAL *val = values.push ();
val->op = op;
val->str = ByteStr (str, opStart, offset - opStart);
opStart = offset;
}
unsigned int opStart;
OpStrs opStrs;
inline void pushVal (OpCode op, const ByteStr& str, unsigned int offset, const VAL &v)
{
VAL *val = values.push (v);
val->op = op;
val->str = ByteStr (str, opStart, offset - opStart);
opStart = offset;
}
unsigned int opStart;
hb_vector_t<VAL> values;
};
/* base of OP_SERIALIZER */
@ -413,29 +456,29 @@ struct OpSerializer
/* Top Dict, Font Dict, Private Dict */
struct Dict : UnsizedByteStr
{
template <typename OP_SERIALIZER, typename PARAM>
template <typename DICTVAL, typename OP_SERIALIZER, typename PARAM>
inline bool serialize (hb_serialize_context_t *c,
const DictValues &values,
const DICTVAL &dictval,
OP_SERIALIZER& opszr,
PARAM& param)
{
TRACE_SERIALIZE (this);
for (unsigned int i = 0; i < values.opStrs.len; i++)
for (unsigned int i = 0; i < dictval.values.len; i++)
{
if (unlikely (!opszr.serialize (c, values.opStrs[i], param)))
if (unlikely (!opszr.serialize (c, dictval.values[i], param)))
return_trace (false);
}
return_trace (true);
}
/* in parallel to above */
template <typename OP_SERIALIZER>
inline static unsigned int calculate_serialized_size (const DictValues &values,
template <typename DICTVAL, typename OP_SERIALIZER>
inline static unsigned int calculate_serialized_size (const DICTVAL &dictval,
OP_SERIALIZER& opszr)
{
unsigned int size = 0;
for (unsigned int i = 0; i < values.opStrs.len; i++)
size += opszr.calculate_serialized_size (values.opStrs[i]);
for (unsigned int i = 0; i < dictval.values.len; i++)
size += opszr.calculate_serialized_size (dictval.values[i]);
return size;
}
@ -629,23 +672,6 @@ inline float parse_bcd (const ByteStr& str, unsigned int& offset, float& v)
return true;
}
struct Number
{
inline Number (void) { set_int (0); }
inline void set_int (int v) { is_real = false; u.int_val = v; };
inline int to_int (void) const { return is_real? (int)u.real_val: u.int_val; }
inline void set_real (float v) { is_real = true; u.real_val = v; };
inline float to_real (void) const { return is_real? u.real_val: (float)u.int_val; }
protected:
bool is_real;
union {
int int_val;
float real_val;
} u;
};
struct Stack
{
inline void init (void) { size = 0; }
@ -697,11 +723,11 @@ struct Stack
return false;
}
inline bool check_pop_int (int& v)
inline bool check_pop_num (Number& n)
{
if (unlikely (!this->check_underflow (1)))
return false;
v = this->pop ().to_int ();
n = this->pop ();
return true;
}
@ -717,15 +743,7 @@ struct Stack
return true;
}
inline bool check_pop_real (float& v)
{
if (unlikely (!this->check_underflow (1)))
return false;
v = this->pop ().to_real ();
return true;
}
inline bool check_pop_delta (hb_vector_t<float>& vec, bool even=false)
inline bool check_pop_delta (hb_vector_t<Number>& vec, bool even=false)
{
if (even && unlikely ((this->size & 1) != 0))
return false;
@ -733,7 +751,8 @@ struct Stack
float val = 0.0f;
for (unsigned int i = 0; i < size; i++) {
val += numbers[i].to_real ();
vec.push (val);
Number *n = vec.push ();
n->set_real (val);
}
return true;
}

View File

@ -64,7 +64,7 @@ struct CFF2VariationStore
DEFINE_SIZE_MIN (2 + VariationStore::min_size);
};
struct CFF2TopDictValues : DictValues
struct CFF2TopDictValues : DictValues<OpStr>
{
inline void init (void)
{
@ -85,11 +85,11 @@ struct CFF2TopDictValues : DictValues
inline unsigned int calculate_serialized_size (void) const
{
unsigned int size = 0;
for (unsigned int i = 0; i < opStrs.len; i++)
for (unsigned int i = 0; i < values.len; i++)
{
OpCode op = opStrs[i].op;
OpCode op = values[i].op;
if (op == OpCode_FontMatrix)
size += opStrs[i].str.len;
size += values[i].str.len;
else
size += OpCode_Size (OpCode_longint) + 4 + OpCode_Size (op);
}
@ -105,49 +105,44 @@ struct CFF2TopDictValues : DictValues
struct CFF2TopDictOpSet
{
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2TopDictValues& val)
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2TopDictValues& dictval)
{
switch (op) {
case OpCode_CharStrings:
if (unlikely (!check_pop_offset (stack, val.charStringsOffset)))
if (unlikely (!check_pop_offset (stack, dictval.charStringsOffset)))
return false;
val.pushOpStr (op, str, offset + 1);
break;
case OpCode_vstore:
if (unlikely (!check_pop_offset (stack, val.vstoreOffset)))
if (unlikely (!check_pop_offset (stack, dictval.vstoreOffset)))
return false;
val.pushOpStr (op, str, offset + 1);
break;
case OpCode_FDArray:
if (unlikely (!check_pop_offset (stack, val.FDArrayOffset)))
if (unlikely (!check_pop_offset (stack, dictval.FDArrayOffset)))
return false;
val.pushOpStr (op, str, offset + 1);
break;
case OpCode_FDSelect:
if (unlikely (!check_pop_offset (stack, val.FDSelectOffset)))
if (unlikely (!check_pop_offset (stack, dictval.FDSelectOffset)))
return false;
val.pushOpStr (op, str, offset + 1);
break;
case OpCode_FontMatrix:
if (unlikely (!stack.check_underflow (6)))
return false;
for (int i = 0; i < 6; i++)
val.FontMatrix[i] = stack.pop ().to_real ();
val.pushOpStr (op, str, offset + 1);
dictval.FontMatrix[i] = stack.pop ().to_real ();
break;
case OpCode_longint: /* 5-byte integer */
if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
return false;
stack.push_int ((int32_t)*(const HBUINT32*)&str[offset + 1]);
offset += 4;
break;
return true;
case OpCode_BCD: /* real number */
float v;
if (unlikely (stack.check_overflow (1) || !parse_bcd (str, offset, v)))
return false;
stack.push_real (v);
break;
return true;
default:
/* XXX: invalid */
@ -155,11 +150,12 @@ struct CFF2TopDictOpSet
return false;
}
dictval.pushVal (op, str, offset + 1);
return true;
}
};
struct CFF2FontDictValues : DictValues
struct CFF2FontDictValues : DictValues<OpStr>
{
inline void init (void)
{
@ -179,28 +175,27 @@ struct CFF2FontDictValues : DictValues
struct CFF2FontDictOpSet
{
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2FontDictValues& val)
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2FontDictValues& dictval)
{
switch (op) {
case OpCode_Private:
if (unlikely (!check_pop_offset (stack, val.privateDictOffset)))
if (unlikely (!check_pop_offset (stack, dictval.privateDictOffset)))
return false;
if (unlikely (!stack.check_pop_uint (val.privateDictSize)))
if (unlikely (!stack.check_pop_uint (dictval.privateDictSize)))
return false;
val.pushOpStr (op, str, offset + 1);
break;
case OpCode_longint: /* 5-byte integer */
if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
return false;
stack.push_int ((int32_t)((str[offset + 1] << 24) | ((uint32_t)str[offset + 2] << 16) | ((uint32_t)str[offset + 3] << 8) | str[offset + 4]));
offset += 4;
break;
return true;
case OpCode_BCD: /* real number */
float v;
if (unlikely (stack.check_overflow (1) || !parse_bcd (str, offset, v)))
return false;
stack.push_real (v);
break;
return true;
default:
/* XXX: invalid */
@ -208,32 +203,34 @@ struct CFF2FontDictOpSet
return false;
}
dictval.pushVal (op, str, offset + 1);
return true;
}
};
struct CFF2PrivateDictValues_Base : DictValues
template <typename VAL>
struct CFF2PrivateDictValues_Base : DictValues<VAL>
{
inline void init (void)
{
DictValues::init ();
DictValues<VAL>::init ();
subrsOffset.set (0);
localSubrs = &Null(Subrs);
}
inline void fini (void)
{
DictValues::fini ();
DictValues<VAL>::fini ();
}
inline unsigned int calculate_serialized_size (void) const
{
unsigned int size = 0;
for (unsigned int i = 0; i < opStrs.len; i++)
if (opStrs[i].op == OpCode_Subrs)
for (unsigned int i = 0; i < DictValues<VAL>::values.len; i++)
if (DictValues<VAL>::values[i].op == OpCode_Subrs)
size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
else
size += opStrs[i].str.len;
size += DictValues<VAL>::values[i].str.len;
return size;
}
@ -241,148 +238,71 @@ struct CFF2PrivateDictValues_Base : DictValues
const Subrs *localSubrs;
};
struct CFF2PrivateDictValues : CFF2PrivateDictValues_Base
{
inline void init (void)
{
CFF2PrivateDictValues_Base::init ();
languageGroup = 0;
expansionFactor = 0.06f;
vsIndex = 0;
blueScale = 0.039625f;
blueShift = 7.0f;
blueFuzz = 1.0f;
stdHW = UNSET_REAL_VALUE;
stdVW = UNSET_REAL_VALUE;
subrsOffset.set (0);
blueValues.init ();
otherBlues.init ();
familyBlues.init ();
familyOtherBlues.init ();
stemSnapH.init ();
stemSnapV.init ();
}
inline void fini (void)
{
blueValues.fini ();
otherBlues.fini ();
familyBlues.fini ();
familyOtherBlues.fini ();
stemSnapH.fini ();
stemSnapV.fini ();
CFF2PrivateDictValues_Base::fini ();
}
int languageGroup;
float expansionFactor;
int vsIndex;
float blueScale;
float blueShift;
float blueFuzz;
float stdHW;
float stdVW;
hb_vector_t <float> blueValues;
hb_vector_t <float> otherBlues;
hb_vector_t <float> familyBlues;
hb_vector_t <float> familyOtherBlues;
hb_vector_t <float> stemSnapH;
hb_vector_t <float> stemSnapV;
};
typedef CFF2PrivateDictValues_Base<OpStr> CFF2PrivateDictValues_Subset;
typedef CFF2PrivateDictValues_Base<DictVal> CFF2PrivateDictValues;
struct CFF2PrivateDictOpSet
{
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues& val)
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues& dictval)
{
DictVal val;
val.init ();
switch (op) {
case OpCode_BlueValues:
if (unlikely (!stack.check_pop_delta (val.blueValues)))
return false;
break;
case OpCode_OtherBlues:
if (unlikely (!stack.check_pop_delta (val.otherBlues)))
return false;
break;
case OpCode_FamilyBlues:
if (unlikely (!stack.check_pop_delta (val.familyBlues)))
return false;
break;
case OpCode_FamilyOtherBlues:
if (unlikely (!stack.check_pop_delta (val.familyOtherBlues)))
case OpCode_StemSnapH:
case OpCode_StemSnapV:
if (unlikely (!stack.check_pop_delta (val.multi_val)))
return false;
break;
case OpCode_StdHW:
if (unlikely (!stack.check_pop_real (val.stdHW)))
return false;
break;
case OpCode_StdVW:
if (unlikely (!stack.check_pop_real (val.stdVW)))
return false;
break;
case OpCode_BlueScale:
if (unlikely (!stack.check_pop_real (val.blueScale)))
return false;
break;
case OpCode_BlueShift:
if (unlikely (!stack.check_pop_real (val.blueShift)))
return false;
break;
case OpCode_BlueFuzz:
if (unlikely (!stack.check_pop_real (val.blueFuzz)))
return false;
break;
case OpCode_StemSnapH:
if (unlikely (!stack.check_pop_delta (val.stemSnapH)))
return false;
break;
case OpCode_StemSnapV:
if (unlikely (!stack.check_pop_delta (val.stemSnapV)))
case OpCode_ExpansionFactor:
if (unlikely (!stack.check_pop_num (val.single_val)))
return false;
break;
case OpCode_LanguageGroup:
if (unlikely (!stack.check_pop_int (val.languageGroup)))
return false;
break;
case OpCode_ExpansionFactor:
if (unlikely (!stack.check_pop_real (val.expansionFactor)))
if (unlikely (!stack.check_pop_num (val.single_val)))
return false;
break;
case OpCode_Subrs:
if (unlikely (!check_pop_offset (stack, val.subrsOffset)))
if (unlikely (!check_pop_offset (stack, dictval.subrsOffset)))
return false;
break;
case OpCode_blend:
// XXX: TODO
break;
return true;
case OpCode_longint: /* 5-byte integer */
if (unlikely (!str.check_limit (offset, 5) || !stack.check_overflow (1)))
return false;
stack.push_int ((int32_t)((str[offset + 1] << 24) | (str[offset + 2] << 16) || (str[offset + 3] << 8) || str[offset + 4]));
offset += 4;
break;
return true;
case OpCode_BCD: /* real number */
float v;
if (unlikely (!stack.check_overflow (1) || !parse_bcd (str, offset, v)))
return false;
stack.push_real (v);
break;
return true;
default:
return false;
}
if (op != OpCode_blend)
val.pushOpStr (op, str, offset + 1);
dictval.pushVal (op, str, offset + 1, val);
return true;
}
};
struct CFF2PrivateDictOpSet_Subset
{
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues_Base& val)
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues_Subset& dictval)
{
switch (op) {
case OpCode_BlueValues:
@ -398,10 +318,13 @@ struct CFF2PrivateDictOpSet_Subset
case OpCode_StemSnapV:
case OpCode_LanguageGroup:
case OpCode_ExpansionFactor:
case OpCode_blend:
stack.clear ();
break;
case OpCode_blend:
stack.clear ();
return true;
case OpCode_BCD:
{
float v;
@ -409,7 +332,7 @@ struct CFF2PrivateDictOpSet_Subset
}
case OpCode_Subrs:
if (unlikely (!check_pop_offset (stack, val.subrsOffset)))
if (unlikely (!check_pop_offset (stack, dictval.subrsOffset)))
return false;
break;
case OpCode_longint: /* 5-byte integer */
@ -417,15 +340,13 @@ struct CFF2PrivateDictOpSet_Subset
return false;
stack.push_int ((int32_t)((str[offset + 1] << 24) | (str[offset + 2] << 16) || (str[offset + 3] << 8) || str[offset + 4]));
offset += 4;
break;
return true;
default:
return false;
}
if (op != OpCode_blend)
val.pushOpStr (op, str, offset + 1);
dictval.pushVal (op, str, offset + 1);
return true;
}
};
@ -580,7 +501,7 @@ struct cff2
};
typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Base> accelerator_subset_t;
typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Subset> accelerator_subset_t;
inline bool subset (hb_subset_plan_t *plan) const
{

View File

@ -167,7 +167,7 @@ struct subset_plan {
/* top dict */
{
CFF2TopDict_OpSerializer topSzr;
offsets.topDictSize = TopDict::calculate_serialized_size<CFF2TopDict_OpSerializer> (acc.top, topSzr);
offsets.topDictSize = TopDict::calculate_serialized_size (acc.top, topSzr);
final_size += offsets.topDictSize;
}