diff --git a/src/hb-ot-cff-common-private.hh b/src/hb-ot-cff-common-private.hh index 3e3ac36fc..92667653f 100644 --- a/src/hb-ot-cff-common-private.hh +++ b/src/hb-ot-cff-common-private.hh @@ -700,6 +700,28 @@ struct TableInfo unsigned int size; }; +/* font dict index remap table from fullset FDArray to subset FDArray. + * set to HB_SET_VALUE_INVALID if excluded from subset */ +struct FDMap : hb_vector_t +{ + inline void init (void) + { hb_vector_t::init (); } + + inline void fini (void) + { hb_vector_t::fini (); } + + inline bool fullset (void) const + { + for (unsigned int i = 0; i < len; i++) + if ((*this)[i] == HB_SET_VALUE_INVALID) + return false; + return true; + } + + inline bool excludes (hb_codepoint_t fd) const + { return (fd < len) && ((*this)[fd] == HB_SET_VALUE_INVALID); } +}; + template struct FDArray : IndexOf { @@ -708,7 +730,7 @@ struct FDArray : IndexOf unsigned int offSize_, const hb_vector_t &fontDicts, unsigned int fdCount, - const hb_vector_t &fdmap, + const FDMap &fdmap, OP_SERIALIZER& opszr, const hb_vector_t &privateInfos) { @@ -723,7 +745,7 @@ struct FDArray : IndexOf unsigned int offset = 1; unsigned int fid = 0; for (unsigned i = 0; i < fontDicts.len; i++) - if (!fdmap.len || fdmap[i] != HB_SET_VALUE_INVALID) + if (!fdmap.excludes (i)) { IndexOf::set_offset_at (fid++, offset); offset += FontDict::calculate_serialized_size (fontDicts[i], opszr); @@ -732,10 +754,10 @@ struct FDArray : IndexOf /* serialize font dicts */ for (unsigned int i = 0; i < fontDicts.len; i++) - if (fdmap[i] != HB_SET_VALUE_INVALID) + if (!fdmap.excludes (i)) { FontDict *dict = c->start_embed (); - if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[i]))) + if (unlikely (!dict->serialize (c, fontDicts[i], opszr, privateInfos[fdmap[i]]))) return_trace (false); } return_trace (true); @@ -746,12 +768,12 @@ struct FDArray : IndexOf inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */, const hb_vector_t &fontDicts, unsigned int fdCount, - const hb_vector_t &fdmap, + const FDMap &fdmap, OP_SERIALIZER& opszr) { unsigned int dictsSize = 0; for (unsigned int i = 0; i < fontDicts.len; i++) - if (!fdmap.len || fdmap[i] != HB_SET_VALUE_INVALID) + if (!fdmap.excludes (i)) dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr); offSize_ = calcOffSize (dictsSize + 1); diff --git a/src/hb-subset-cff-common-private.cc b/src/hb-subset-cff-common-private.cc index b74a298ee..6796709f0 100644 --- a/src/hb-subset-cff-common-private.cc +++ b/src/hb-subset-cff-common-private.cc @@ -46,7 +46,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t &glyphs, unsigned int &subst_fdselect_size /* OUT */, unsigned int &subst_fdselect_format /* OUT */, hb_vector_t &subst_first_glyphs /* OUT */, - hb_vector_t &fdmap /* OUT */) + FDMap &fdmap /* OUT */) { subset_fd_count = 0; subst_fdselect_size = 0; @@ -131,7 +131,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c, const FDSelect &src, unsigned int size, const hb_vector_t &first_glyphs, - const hb_vector_t &fdmap) + const FDMap &fdmap) { TRACE_SERIALIZE (this); FDSELECT3_4 *p = c->allocate_size (size); @@ -159,7 +159,7 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c, unsigned int fdselect_format, unsigned int size, const hb_vector_t &first_glyphs, - const hb_vector_t &fdmap) + const FDMap &fdmap) { TRACE_SERIALIZE (this); FDSelect *p = c->allocate_min (); diff --git a/src/hb-subset-cff-common-private.hh b/src/hb-subset-cff-common-private.hh index 97d5550fa..b1a743c10 100644 --- a/src/hb-subset-cff-common-private.hh +++ b/src/hb-subset-cff-common-private.hh @@ -39,7 +39,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t &glyphs, unsigned int &subst_fdselect_size /* OUT */, unsigned int &subst_fdselect_format /* OUT */, hb_vector_t &subst_first_glyphs /* OUT */, - hb_vector_t &fdmap /* OUT */); + CFF::FDMap &fdmap /* OUT */); HB_INTERNAL bool hb_serialize_cff_fdselect (hb_serialize_context_t *c, @@ -49,6 +49,6 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c, unsigned int fdselect_format, unsigned int size, const hb_vector_t &first_glyphs, - const hb_vector_t &fdmap); + const CFF::FDMap &fdmap); #endif /* HB_SUBSET_CFF_COMMON_PRIVATE_HH */ diff --git a/src/hb-subset-cff.cc b/src/hb-subset-cff.cc index ea5066787..afc32f278 100644 --- a/src/hb-subset-cff.cc +++ b/src/hb-subset-cff.cc @@ -291,10 +291,13 @@ struct cff_subset_plan { offsets.privateDictInfo.offset = final_size; for (unsigned int i = 0; i < orig_fdcount; i++) { - CFFPrivateDict_OpSerializer privSzr; - TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; - privateDictInfos.push (privInfo); - final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); + if (!fdmap.excludes (i)) + { + CFFPrivateDict_OpSerializer privSzr; + TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; + privateDictInfos.push (privInfo); + final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); + } } if (!acc.is_CID ()) @@ -317,7 +320,7 @@ struct cff_subset_plan { /* font dict index remap table from fullset FDArray to subset FDArray. * set to HB_SET_VALUE_INVALID if excluded from subset */ - hb_vector_t fdmap; + FDMap fdmap; hb_vector_t subset_charstrings; hb_vector_t privateDictInfos; @@ -474,27 +477,30 @@ static inline bool _write_cff (const cff_subset_plan &plan, assert (plan.offsets.privateDictInfo.offset == c.head - c.start); for (unsigned int i = 0; i < acc.privateDicts.len; i++) { - PrivateDict *pd = c.start_embed (); - if (unlikely (pd == nullptr)) return false; - CFFPrivateDict_OpSerializer privSzr; - /* 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.privateDictInfos[i].size))) + if (!plan.fdmap.excludes (i)) { - DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i); - return false; - } - if (acc.privateDicts[i].subrsOffset != 0) - { - CFFSubrs *subrs = c.start_embed (); - if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFFSubrs)) + PrivateDict *pd = c.start_embed (); + if (unlikely (pd == nullptr)) return false; + CFFPrivateDict_OpSerializer privSzr; + /* 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.privateDictInfos[plan.fdmap[i]].size))) { - DEBUG_MSG (SUBSET, nullptr, "CFF subset: local subrs unexpectedly null [%d]", i); + DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i); return false; } - if (unlikely (!subrs->serialize (&c, *acc.privateDicts[i].localSubrs))) + if (acc.privateDicts[i].subrsOffset != 0) { - DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF local subrs [%d]", i); - return false; + CFFSubrs *subrs = c.start_embed (); + if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFFSubrs)) + { + DEBUG_MSG (SUBSET, nullptr, "CFF subset: local subrs unexpectedly null [%d]", i); + return false; + } + if (unlikely (!subrs->serialize (&c, *acc.privateDicts[i].localSubrs))) + { + DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF local subrs [%d]", i); + return false; + } } } } diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index cd762dd81..418cdfb67 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -250,10 +250,13 @@ struct cff2_subset_plan { offsets.privateDictsOffset = final_size; for (unsigned int i = 0; i < orig_fdcount; i++) { - CFF2PrivateDict_OpSerializer privSzr; - TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; - privateDictInfos.push (privInfo); - final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); + if (!fdmap.excludes (i)) + { + CFF2PrivateDict_OpSerializer privSzr; + TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; + privateDictInfos.push (privInfo); + final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); + } } return true; @@ -270,9 +273,7 @@ struct cff2_subset_plan { unsigned int subst_fdselect_format; hb_vector_t subst_fdselect_first_glyphs; - /* font dict index remap table from fullset FDArray to subset FDArray. - * set to HB_SET_VALUE_INVALID if excluded from subset */ - hb_vector_t fdmap; + FDMap fdmap; hb_vector_t subset_charstrings; hb_vector_t privateDictInfos; @@ -390,27 +391,30 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan, assert (plan.offsets.privateDictsOffset == c.head - c.start); for (unsigned int i = 0; i < acc.privateDicts.len; i++) { - PrivateDict *pd = c.start_embed (); - if (unlikely (pd == nullptr)) return false; - CFF2PrivateDict_OpSerializer privSzr; - /* 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.privateDictInfos[i].size))) + if (!plan.fdmap.excludes (i)) { - DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Private Dict[%d]", i); - return false; - } - if (acc.privateDicts[i].subrsOffset != 0) - { - CFF2Subrs *subrs = c.start_embed (); - if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFF2Subrs)) + PrivateDict *pd = c.start_embed (); + if (unlikely (pd == nullptr)) return false; + CFF2PrivateDict_OpSerializer privSzr; + /* 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.privateDictInfos[plan.fdmap[i]].size))) { - DEBUG_MSG (SUBSET, nullptr, "CFF2 subset: local subrs unexpectedly null [%d]", i); + DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Private Dict[%d]", i); return false; } - if (unlikely (!subrs->serialize (&c, *acc.privateDicts[i].localSubrs))) + if (acc.privateDicts[i].subrsOffset != 0) { - DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 local subrs [%d]", i); - return false; + CFF2Subrs *subrs = c.start_embed (); + if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFF2Subrs)) + { + DEBUG_MSG (SUBSET, nullptr, "CFF2 subset: local subrs unexpectedly null [%d]", i); + return false; + } + if (unlikely (!subrs->serialize (&c, *acc.privateDicts[i].localSubrs))) + { + DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 local subrs [%d]", i); + return false; + } } } }