templatized CFF2 accelerator for lean Private dict interpretting for subset

also fixed local subrs serialization
This commit is contained in:
Michiharu Ariza 2018-08-02 16:28:10 -07:00
parent 43040564e6
commit 76f7397c10
3 changed files with 118 additions and 40 deletions

View File

@ -289,6 +289,7 @@ struct Index
inline const unsigned int offset_at (unsigned int index) const
{
assert (index <= count);
const HBUINT8 *p = offsets + offSize * index;
unsigned int size = offSize;
unsigned int offset = 0;
@ -317,7 +318,12 @@ struct Index
inline unsigned int get_size (void) const
{
if (this != &Null(Index))
return count.static_size + offSize.static_size + offset_array_size () + (offset_at (count) - 1);
{
if (count > 0)
return min_size + offset_array_size () + (offset_at (count) - 1);
else
return count.static_size; /* empty Index contains count only */
}
else
return 0;
}

View File

@ -212,41 +212,17 @@ struct CFF2FontDictOpSet
}
};
struct CFF2PrivateDictValues : DictValues
struct CFF2PrivateDictValues_Base : DictValues
{
inline void init (void)
{
DictValues::init ();
languageGroup = 0;
expansionFactor = 0.06f;
vsIndex = 0;
subrsOffset.set (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 ();
localSubrs = &Null(Subrs);
}
inline void fini (void)
{
blueValues.fini ();
otherBlues.fini ();
familyBlues.fini ();
familyOtherBlues.fini ();
stemSnapH.fini ();
stemSnapV.fini ();
DictValues::fini ();
}
@ -261,10 +237,48 @@ struct CFF2PrivateDictValues : DictValues
return size;
}
LOffsetTo<Subrs> subrsOffset;
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;
OffsetTo<Subrs> subrsOffset;
float blueScale;
float blueShift;
float blueFuzz;
@ -276,8 +290,6 @@ struct CFF2PrivateDictValues : DictValues
hb_vector_t <float> familyOtherBlues;
hb_vector_t <float> stemSnapH;
hb_vector_t <float> stemSnapV;
const Subrs *localSubrs;
};
struct CFF2PrivateDictOpSet
@ -368,6 +380,56 @@ struct CFF2PrivateDictOpSet
}
};
struct CFF2PrivateDictOpSet_Subset
{
static inline bool process_op (const ByteStr& str, unsigned int& offset, OpCode op, Stack& stack, CFF2PrivateDictValues_Base& val)
{
switch (op) {
case OpCode_BlueValues:
case OpCode_OtherBlues:
case OpCode_FamilyBlues:
case OpCode_FamilyOtherBlues:
case OpCode_StdHW:
case OpCode_StdVW:
case OpCode_BlueScale:
case OpCode_BlueShift:
case OpCode_BlueFuzz:
case OpCode_StemSnapH:
case OpCode_StemSnapV:
case OpCode_LanguageGroup:
case OpCode_ExpansionFactor:
case OpCode_blend:
stack.clear ();
break;
case OpCode_BCD:
{
float v;
return parse_bcd (str, offset, v);
}
case OpCode_Subrs:
if (unlikely (!check_pop_offset (stack, val.subrsOffset)))
return false;
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) | (str[offset + 2] << 16) || (str[offset + 3] << 8) || str[offset + 4]));
offset += 4;
break;
default:
return false;
}
if (op != OpCode_blend)
val.pushOpStr (op, str, offset + 1);
return true;
}
};
typedef Interpreter<CFF2TopDictOpSet, CFF2TopDictValues> CFF2TopDict_Interpreter;
typedef Interpreter<CFF2FontDictOpSet, CFF2FontDictValues> CFF2FontDict_Interpreter;
typedef Interpreter<CFF2PrivateDictOpSet, CFF2PrivateDictValues> CFF2PrivateDict_Interpreter;
@ -389,7 +451,8 @@ struct cff2
likely (version.major == 2));
}
struct accelerator_t
template <typename PrivOpSet, typename PrivDictVal>
struct accelerator_templ_t
{
inline void init (hb_face_t *face)
{
@ -402,7 +465,7 @@ struct cff2
sc.init (this->blob);
sc.start_processing ();
const OT::cff2 *cff2 = this->blob->as<OT::cff2> ();
const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
if (cff2 == &Null(OT::cff2))
{
@ -460,7 +523,7 @@ struct cff2
}
const ByteStr privDictStr (font->privateDictOffset (cff2), font->privateDictSize);
CFF2PrivateDict_Interpreter priv_interp;
Interpreter<PrivOpSet, PrivDictVal> priv_interp;
if (unlikely (!privDictStr.sanitize (&sc) ||
!priv_interp.interpret (privDictStr, privateDicts[i])))
{
@ -468,7 +531,12 @@ struct cff2
return;
}
privateDicts[i].localSubrs = &privateDicts[i].subrsOffset (cff2);
privateDicts[i].localSubrs = &privateDicts[i].subrsOffset (privDictStr.str);
if (unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
{
fini ();
return;
}
}
}
@ -506,11 +574,14 @@ struct cff2
const FDSelect *fdSelect;
hb_vector_t<CFF2FontDictValues> fontDicts;
hb_vector_t<CFF2PrivateDictValues> privateDicts;
hb_vector_t<PrivDictVal> privateDicts;
unsigned int num_glyphs;
};
typedef accelerator_templ_t<CFF2PrivateDictOpSet, CFF2PrivateDictValues> accelerator_t;
typedef accelerator_templ_t<CFF2PrivateDictOpSet_Subset, CFF2PrivateDictValues_Base> accelerator_subset_t;
inline bool subset (hb_subset_plan_t *plan) const
{
hb_blob_t *cff2_prime = nullptr;

View File

@ -156,7 +156,7 @@ struct subset_plan {
private_off_and_size_pairs.fini ();
}
inline bool create (const OT::cff2::accelerator_t &acc,
inline bool create (const OT::cff2::accelerator_subset_t &acc,
hb_subset_plan_t *plan)
{
final_size = 0;
@ -233,7 +233,7 @@ struct subset_plan {
};
static inline bool _write_cff2 (const subset_plan &plan,
const OT::cff2::accelerator_t &acc,
const OT::cff2::accelerator_subset_t &acc,
unsigned int dest_sz,
void *dest)
{
@ -329,14 +329,15 @@ static inline bool _write_cff2 (const subset_plan &plan,
PrivateDict *pd = c.start_embed<PrivateDict> ();
if (unlikely (pd == nullptr)) return false;
CFF2PrivateDict_OpSerializer privSzr;
if (unlikely (!pd->serialize (&c, acc.privateDicts[i], privSzr, acc.privateDicts[i].subrsOffset)))
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
if (unlikely (!pd->serialize (&c, acc.privateDicts[i], privSzr, plan.private_off_and_size_pairs[i].size)))
{
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Private Dict[%d]", i);
return false;
}
if (acc.privateDicts[i].subrsOffset != 0)
{
Subrs *subrs = c.allocate_size<Subrs> (acc.privateDicts[i].localSubrs->get_size ());
Subrs *subrs = c.start_embed<Subrs> ();
if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(Subrs))
{
DEBUG_MSG (SUBSET, nullptr, "CFF2 subset: local subrs unexpectedly null [%d]", i);
@ -356,7 +357,7 @@ static inline bool _write_cff2 (const subset_plan &plan,
}
static bool
_hb_subset_cff2 (const OT::cff2::accelerator_t &acc,
_hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
const char *data,
hb_subset_plan_t *plan,
hb_blob_t **prime /* OUT */)
@ -400,7 +401,7 @@ hb_subset_cff2 (hb_subset_plan_t *plan,
hb_blob_t *cff2_blob = hb_sanitize_context_t().reference_table<CFF::cff2> (plan->source);
const char *data = hb_blob_get_data(cff2_blob, nullptr);
OT::cff2::accelerator_t acc;
OT::cff2::accelerator_subset_t acc;
acc.init(plan->source);
bool result = likely (acc.is_valid ()) &&
_hb_subset_cff2 (acc,