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 inline const unsigned int offset_at (unsigned int index) const
{ {
assert (index <= count);
const HBUINT8 *p = offsets + offSize * index; const HBUINT8 *p = offsets + offSize * index;
unsigned int size = offSize; unsigned int size = offSize;
unsigned int offset = 0; unsigned int offset = 0;
@ -317,7 +318,12 @@ struct Index
inline unsigned int get_size (void) const inline unsigned int get_size (void) const
{ {
if (this != &Null(Index)) 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 else
return 0; return 0;
} }

View File

@ -212,41 +212,17 @@ struct CFF2FontDictOpSet
} }
}; };
struct CFF2PrivateDictValues : DictValues struct CFF2PrivateDictValues_Base : DictValues
{ {
inline void init (void) inline void init (void)
{ {
DictValues::init (); DictValues::init ();
languageGroup = 0;
expansionFactor = 0.06f;
vsIndex = 0;
subrsOffset.set (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); localSubrs = &Null(Subrs);
} }
inline void fini (void) inline void fini (void)
{ {
blueValues.fini ();
otherBlues.fini ();
familyBlues.fini ();
familyOtherBlues.fini ();
stemSnapH.fini ();
stemSnapV.fini ();
DictValues::fini (); DictValues::fini ();
} }
@ -261,10 +237,48 @@ struct CFF2PrivateDictValues : DictValues
return size; 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; int languageGroup;
float expansionFactor; float expansionFactor;
int vsIndex; int vsIndex;
OffsetTo<Subrs> subrsOffset;
float blueScale; float blueScale;
float blueShift; float blueShift;
float blueFuzz; float blueFuzz;
@ -276,8 +290,6 @@ struct CFF2PrivateDictValues : DictValues
hb_vector_t <float> familyOtherBlues; hb_vector_t <float> familyOtherBlues;
hb_vector_t <float> stemSnapH; hb_vector_t <float> stemSnapH;
hb_vector_t <float> stemSnapV; hb_vector_t <float> stemSnapV;
const Subrs *localSubrs;
}; };
struct CFF2PrivateDictOpSet 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<CFF2TopDictOpSet, CFF2TopDictValues> CFF2TopDict_Interpreter;
typedef Interpreter<CFF2FontDictOpSet, CFF2FontDictValues> CFF2FontDict_Interpreter; typedef Interpreter<CFF2FontDictOpSet, CFF2FontDictValues> CFF2FontDict_Interpreter;
typedef Interpreter<CFF2PrivateDictOpSet, CFF2PrivateDictValues> CFF2PrivateDict_Interpreter; typedef Interpreter<CFF2PrivateDictOpSet, CFF2PrivateDictValues> CFF2PrivateDict_Interpreter;
@ -389,7 +451,8 @@ struct cff2
likely (version.major == 2)); likely (version.major == 2));
} }
struct accelerator_t template <typename PrivOpSet, typename PrivDictVal>
struct accelerator_templ_t
{ {
inline void init (hb_face_t *face) inline void init (hb_face_t *face)
{ {
@ -402,7 +465,7 @@ struct cff2
sc.init (this->blob); sc.init (this->blob);
sc.start_processing (); 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)) if (cff2 == &Null(OT::cff2))
{ {
@ -460,7 +523,7 @@ struct cff2
} }
const ByteStr privDictStr (font->privateDictOffset (cff2), font->privateDictSize); const ByteStr privDictStr (font->privateDictOffset (cff2), font->privateDictSize);
CFF2PrivateDict_Interpreter priv_interp; Interpreter<PrivOpSet, PrivDictVal> priv_interp;
if (unlikely (!privDictStr.sanitize (&sc) || if (unlikely (!privDictStr.sanitize (&sc) ||
!priv_interp.interpret (privDictStr, privateDicts[i]))) !priv_interp.interpret (privDictStr, privateDicts[i])))
{ {
@ -468,7 +531,12 @@ struct cff2
return; 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; const FDSelect *fdSelect;
hb_vector_t<CFF2FontDictValues> fontDicts; hb_vector_t<CFF2FontDictValues> fontDicts;
hb_vector_t<CFF2PrivateDictValues> privateDicts; hb_vector_t<PrivDictVal> privateDicts;
unsigned int num_glyphs; 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 inline bool subset (hb_subset_plan_t *plan) const
{ {
hb_blob_t *cff2_prime = nullptr; hb_blob_t *cff2_prime = nullptr;

View File

@ -156,7 +156,7 @@ struct subset_plan {
private_off_and_size_pairs.fini (); 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) hb_subset_plan_t *plan)
{ {
final_size = 0; final_size = 0;
@ -233,7 +233,7 @@ struct subset_plan {
}; };
static inline bool _write_cff2 (const subset_plan &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, unsigned int dest_sz,
void *dest) void *dest)
{ {
@ -329,14 +329,15 @@ static inline bool _write_cff2 (const subset_plan &plan,
PrivateDict *pd = c.start_embed<PrivateDict> (); PrivateDict *pd = c.start_embed<PrivateDict> ();
if (unlikely (pd == nullptr)) return false; if (unlikely (pd == nullptr)) return false;
CFF2PrivateDict_OpSerializer privSzr; 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); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Private Dict[%d]", i);
return false; return false;
} }
if (acc.privateDicts[i].subrsOffset != 0) 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)) if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(Subrs))
{ {
DEBUG_MSG (SUBSET, nullptr, "CFF2 subset: local subrs unexpectedly null [%d]", i); 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 static bool
_hb_subset_cff2 (const OT::cff2::accelerator_t &acc, _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
const char *data, const char *data,
hb_subset_plan_t *plan, hb_subset_plan_t *plan,
hb_blob_t **prime /* OUT */) 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); 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); 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); acc.init(plan->source);
bool result = likely (acc.is_valid ()) && bool result = likely (acc.is_valid ()) &&
_hb_subset_cff2 (acc, _hb_subset_cff2 (acc,