fixed inclusion of excluded Private & local Subrs

It was bloating a multi-FD subset font unnecessarily
defined a wrapper struct FDMap for fdmap
This commit is contained in:
Michiharu Ariza 2018-08-10 12:55:22 -07:00
parent 64c5412264
commit a97ed342d1
5 changed files with 87 additions and 55 deletions

View File

@ -700,6 +700,28 @@ struct TableInfo
unsigned int size; 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<hb_codepoint_t>
{
inline void init (void)
{ hb_vector_t<hb_codepoint_t>::init (); }
inline void fini (void)
{ hb_vector_t<hb_codepoint_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 <typename COUNT> template <typename COUNT>
struct FDArray : IndexOf<COUNT, FontDict> struct FDArray : IndexOf<COUNT, FontDict>
{ {
@ -708,7 +730,7 @@ struct FDArray : IndexOf<COUNT, FontDict>
unsigned int offSize_, unsigned int offSize_,
const hb_vector_t<DICTVAL> &fontDicts, const hb_vector_t<DICTVAL> &fontDicts,
unsigned int fdCount, unsigned int fdCount,
const hb_vector_t<hb_codepoint_t> &fdmap, const FDMap &fdmap,
OP_SERIALIZER& opszr, OP_SERIALIZER& opszr,
const hb_vector_t<TableInfo> &privateInfos) const hb_vector_t<TableInfo> &privateInfos)
{ {
@ -723,7 +745,7 @@ struct FDArray : IndexOf<COUNT, FontDict>
unsigned int offset = 1; unsigned int offset = 1;
unsigned int fid = 0; unsigned int fid = 0;
for (unsigned i = 0; i < fontDicts.len; i++) for (unsigned i = 0; i < fontDicts.len; i++)
if (!fdmap.len || fdmap[i] != HB_SET_VALUE_INVALID) if (!fdmap.excludes (i))
{ {
IndexOf<COUNT, FontDict>::set_offset_at (fid++, offset); IndexOf<COUNT, FontDict>::set_offset_at (fid++, offset);
offset += FontDict::calculate_serialized_size (fontDicts[i], opszr); offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
@ -732,10 +754,10 @@ struct FDArray : IndexOf<COUNT, FontDict>
/* serialize font dicts */ /* serialize font dicts */
for (unsigned int i = 0; i < fontDicts.len; i++) 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<FontDict> (); FontDict *dict = c->start_embed<FontDict> ();
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 (false);
} }
return_trace (true); return_trace (true);
@ -746,12 +768,12 @@ struct FDArray : IndexOf<COUNT, FontDict>
inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */, inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
const hb_vector_t<DICTVAL> &fontDicts, const hb_vector_t<DICTVAL> &fontDicts,
unsigned int fdCount, unsigned int fdCount,
const hb_vector_t<hb_codepoint_t> &fdmap, const FDMap &fdmap,
OP_SERIALIZER& opszr) OP_SERIALIZER& opszr)
{ {
unsigned int dictsSize = 0; unsigned int dictsSize = 0;
for (unsigned int i = 0; i < fontDicts.len; i++) 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); dictsSize += FontDict::calculate_serialized_size (fontDicts[i], opszr);
offSize_ = calcOffSize (dictsSize + 1); offSize_ = calcOffSize (dictsSize + 1);

View File

@ -46,7 +46,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
unsigned int &subst_fdselect_size /* OUT */, unsigned int &subst_fdselect_size /* OUT */,
unsigned int &subst_fdselect_format /* OUT */, unsigned int &subst_fdselect_format /* OUT */,
hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */, hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */,
hb_vector_t<hb_codepoint_t> &fdmap /* OUT */) FDMap &fdmap /* OUT */)
{ {
subset_fd_count = 0; subset_fd_count = 0;
subst_fdselect_size = 0; subst_fdselect_size = 0;
@ -131,7 +131,7 @@ serialize_fdselect_3_4 (hb_serialize_context_t *c,
const FDSelect &src, const FDSelect &src,
unsigned int size, unsigned int size,
const hb_vector_t<hb_codepoint_t> &first_glyphs, const hb_vector_t<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap) const FDMap &fdmap)
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size); FDSELECT3_4 *p = c->allocate_size<FDSELECT3_4> (size);
@ -159,7 +159,7 @@ hb_serialize_cff_fdselect (hb_serialize_context_t *c,
unsigned int fdselect_format, unsigned int fdselect_format,
unsigned int size, unsigned int size,
const hb_vector_t<hb_codepoint_t> &first_glyphs, const hb_vector_t<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap) const FDMap &fdmap)
{ {
TRACE_SERIALIZE (this); TRACE_SERIALIZE (this);
FDSelect *p = c->allocate_min<FDSelect> (); FDSelect *p = c->allocate_min<FDSelect> ();

View File

@ -39,7 +39,7 @@ hb_plan_subset_cff_fdselect (const hb_vector_t<hb_codepoint_t> &glyphs,
unsigned int &subst_fdselect_size /* OUT */, unsigned int &subst_fdselect_size /* OUT */,
unsigned int &subst_fdselect_format /* OUT */, unsigned int &subst_fdselect_format /* OUT */,
hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */, hb_vector_t<hb_codepoint_t> &subst_first_glyphs /* OUT */,
hb_vector_t<hb_codepoint_t> &fdmap /* OUT */); CFF::FDMap &fdmap /* OUT */);
HB_INTERNAL bool HB_INTERNAL bool
hb_serialize_cff_fdselect (hb_serialize_context_t *c, 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 fdselect_format,
unsigned int size, unsigned int size,
const hb_vector_t<hb_codepoint_t> &first_glyphs, const hb_vector_t<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap); const CFF::FDMap &fdmap);
#endif /* HB_SUBSET_CFF_COMMON_PRIVATE_HH */ #endif /* HB_SUBSET_CFF_COMMON_PRIVATE_HH */

View File

@ -291,10 +291,13 @@ struct cff_subset_plan {
offsets.privateDictInfo.offset = final_size; offsets.privateDictInfo.offset = final_size;
for (unsigned int i = 0; i < orig_fdcount; i++) for (unsigned int i = 0; i < orig_fdcount; i++)
{ {
CFFPrivateDict_OpSerializer privSzr; if (!fdmap.excludes (i))
TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; {
privateDictInfos.push (privInfo); CFFPrivateDict_OpSerializer privSzr;
final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); 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 ()) if (!acc.is_CID ())
@ -317,7 +320,7 @@ struct cff_subset_plan {
/* font dict index remap table from fullset FDArray to subset FDArray. /* font dict index remap table from fullset FDArray to subset FDArray.
* set to HB_SET_VALUE_INVALID if excluded from subset */ * set to HB_SET_VALUE_INVALID if excluded from subset */
hb_vector_t<hb_codepoint_t> fdmap; FDMap fdmap;
hb_vector_t<ByteStr> subset_charstrings; hb_vector_t<ByteStr> subset_charstrings;
hb_vector_t<TableInfo> privateDictInfos; hb_vector_t<TableInfo> privateDictInfos;
@ -474,27 +477,30 @@ static inline bool _write_cff (const cff_subset_plan &plan,
assert (plan.offsets.privateDictInfo.offset == c.head - c.start); assert (plan.offsets.privateDictInfo.offset == c.head - c.start);
for (unsigned int i = 0; i < acc.privateDicts.len; i++) for (unsigned int i = 0; i < acc.privateDicts.len; i++)
{ {
PrivateDict *pd = c.start_embed<PrivateDict> (); if (!plan.fdmap.excludes (i))
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)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i); PrivateDict *pd = c.start_embed<PrivateDict> ();
return false; if (unlikely (pd == nullptr)) return false;
} CFFPrivateDict_OpSerializer privSzr;
if (acc.privateDicts[i].subrsOffset != 0) /* 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)))
CFFSubrs *subrs = c.start_embed<CFFSubrs> ();
if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFFSubrs))
{ {
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; 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); CFFSubrs *subrs = c.start_embed<CFFSubrs> ();
return false; 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;
}
} }
} }
} }

View File

@ -250,10 +250,13 @@ struct cff2_subset_plan {
offsets.privateDictsOffset = final_size; offsets.privateDictsOffset = final_size;
for (unsigned int i = 0; i < orig_fdcount; i++) for (unsigned int i = 0; i < orig_fdcount; i++)
{ {
CFF2PrivateDict_OpSerializer privSzr; if (!fdmap.excludes (i))
TableInfo privInfo = { final_size, PrivateDict::calculate_serialized_size (acc.privateDicts[i], privSzr) }; {
privateDictInfos.push (privInfo); CFF2PrivateDict_OpSerializer privSzr;
final_size += privInfo.size + acc.privateDicts[i].localSubrs->get_size (); 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; return true;
@ -270,9 +273,7 @@ struct cff2_subset_plan {
unsigned int subst_fdselect_format; unsigned int subst_fdselect_format;
hb_vector_t<hb_codepoint_t> subst_fdselect_first_glyphs; hb_vector_t<hb_codepoint_t> subst_fdselect_first_glyphs;
/* font dict index remap table from fullset FDArray to subset FDArray. FDMap fdmap;
* set to HB_SET_VALUE_INVALID if excluded from subset */
hb_vector_t<hb_codepoint_t> fdmap;
hb_vector_t<ByteStr> subset_charstrings; hb_vector_t<ByteStr> subset_charstrings;
hb_vector_t<TableInfo> privateDictInfos; hb_vector_t<TableInfo> privateDictInfos;
@ -390,27 +391,30 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
assert (plan.offsets.privateDictsOffset == c.head - c.start); assert (plan.offsets.privateDictsOffset == c.head - c.start);
for (unsigned int i = 0; i < acc.privateDicts.len; i++) for (unsigned int i = 0; i < acc.privateDicts.len; i++)
{ {
PrivateDict *pd = c.start_embed<PrivateDict> (); if (!plan.fdmap.excludes (i))
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)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Private Dict[%d]", i); PrivateDict *pd = c.start_embed<PrivateDict> ();
return false; if (unlikely (pd == nullptr)) return false;
} CFF2PrivateDict_OpSerializer privSzr;
if (acc.privateDicts[i].subrsOffset != 0) /* 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)))
CFF2Subrs *subrs = c.start_embed<CFF2Subrs> ();
if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFF2Subrs))
{ {
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; 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); CFF2Subrs *subrs = c.start_embed<CFF2Subrs> ();
return false; 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;
}
} }
} }
} }