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;
};
/* 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>
struct FDArray : IndexOf<COUNT, FontDict>
{
@ -708,7 +730,7 @@ struct FDArray : IndexOf<COUNT, FontDict>
unsigned int offSize_,
const hb_vector_t<DICTVAL> &fontDicts,
unsigned int fdCount,
const hb_vector_t<hb_codepoint_t> &fdmap,
const FDMap &fdmap,
OP_SERIALIZER& opszr,
const hb_vector_t<TableInfo> &privateInfos)
{
@ -723,7 +745,7 @@ struct FDArray : IndexOf<COUNT, FontDict>
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<COUNT, FontDict>::set_offset_at (fid++, offset);
offset += FontDict::calculate_serialized_size (fontDicts[i], opszr);
@ -732,10 +754,10 @@ struct FDArray : IndexOf<COUNT, FontDict>
/* 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<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 (true);
@ -746,12 +768,12 @@ struct FDArray : IndexOf<COUNT, FontDict>
inline static unsigned int calculate_serialized_size (unsigned int &offSize_ /* OUT */,
const hb_vector_t<DICTVAL> &fontDicts,
unsigned int fdCount,
const hb_vector_t<hb_codepoint_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);

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_format /* 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;
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<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap)
const FDMap &fdmap)
{
TRACE_SERIALIZE (this);
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 size,
const hb_vector_t<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap)
const FDMap &fdmap)
{
TRACE_SERIALIZE (this);
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_format /* 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_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<hb_codepoint_t> &first_glyphs,
const hb_vector_t<hb_codepoint_t> &fdmap);
const CFF::FDMap &fdmap);
#endif /* HB_SUBSET_CFF_COMMON_PRIVATE_HH */

View File

@ -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<hb_codepoint_t> fdmap;
FDMap fdmap;
hb_vector_t<ByteStr> subset_charstrings;
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);
for (unsigned int i = 0; i < acc.privateDicts.len; i++)
{
PrivateDict *pd = c.start_embed<PrivateDict> ();
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<CFFSubrs> ();
if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFFSubrs))
PrivateDict *pd = c.start_embed<PrivateDict> ();
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<CFFSubrs> ();
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;
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<hb_codepoint_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<hb_codepoint_t> fdmap;
FDMap fdmap;
hb_vector_t<ByteStr> subset_charstrings;
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);
for (unsigned int i = 0; i < acc.privateDicts.len; i++)
{
PrivateDict *pd = c.start_embed<PrivateDict> ();
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<CFF2Subrs> ();
if (unlikely (subrs == nullptr) || acc.privateDicts[i].localSubrs == &Null(CFF2Subrs))
PrivateDict *pd = c.start_embed<PrivateDict> ();
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<CFF2Subrs> ();
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;
}
}
}
}