templatized CFF2 accelerator for lean Private dict interpretting for subset
also fixed local subrs serialization
This commit is contained in:
parent
43040564e6
commit
76f7397c10
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue