first rewrite of cff/cff2 _subset with _subset2

This commit is contained in:
ariza 2020-02-02 22:00:53 -08:00 committed by Ebrahim Byagowi
parent b2a68ed587
commit 2792fb8ba1
7 changed files with 89 additions and 141 deletions

View File

@ -1376,20 +1376,16 @@ struct cff1
struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {}; struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
bool subset (hb_subset_plan_t *plan) const bool subset (hb_subset_context_t *c) const
{ {
hb_blob_t *cff_prime = nullptr;
bool success = true; bool success = true;
if (hb_subset_cff1 (plan, &cff_prime)) { if (hb_subset_cff1 (c)) {
success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime); hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (c->plan->source);
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source); success = success && head_blob && c->plan->add_table (HB_OT_TAG_head, head_blob);
success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
hb_blob_destroy (head_blob); hb_blob_destroy (head_blob);
} else { } else {
success = false; success = false;
} }
hb_blob_destroy (cff_prime);
return success; return success;
} }

View File

@ -539,20 +539,16 @@ struct cff2
typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t; typedef accelerator_templ_t<cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t> accelerator_subset_t;
bool subset (hb_subset_plan_t *plan) const bool subset (hb_subset_context_t *c) const
{ {
hb_blob_t *cff2_prime = nullptr;
bool success = true; bool success = true;
if (hb_subset_cff2 (plan, &cff2_prime)) { if (hb_subset_cff2 (c)) {
success = success && plan->add_table (HB_OT_TAG_cff2, cff2_prime); hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (c->plan->source);
hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source); success = success && head_blob && c->plan->add_table (HB_OT_TAG_head, head_blob);
success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
hb_blob_destroy (head_blob); hb_blob_destroy (head_blob);
} else { } else {
success = false; success = false;
} }
hb_blob_destroy (cff2_prime);
return success; return success;
} }

View File

@ -883,16 +883,13 @@ struct cff_subset_plan {
bool desubroutinize; bool desubroutinize;
}; };
static inline bool _write_cff1 (const cff_subset_plan &plan, static inline bool _write_cff1 (hb_serialize_context_t *c,
const cff_subset_plan &plan,
const OT::cff1::accelerator_subset_t &acc, const OT::cff1::accelerator_subset_t &acc,
unsigned int num_glyphs, unsigned int num_glyphs)
unsigned int dest_sz,
void *dest)
{ {
hb_serialize_context_t c (dest, dest_sz); OT::cff1 *cff = c->allocate_min<OT::cff1> ();
if (unlikely (!cff))
OT::cff1 *cff = c.start_serialize<OT::cff1> ();
if (unlikely (!c.extend_min (*cff)))
return false; return false;
/* header */ /* header */
@ -903,10 +900,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* name INDEX */ /* name INDEX */
{ {
assert (cff->nameIndex == (unsigned) (c.head - c.start)); assert (cff->nameIndex == (unsigned) (c->head - c->start));
CFF1NameIndex *dest = c.start_embed<CFF1NameIndex> (); CFF1NameIndex *dest = c->start_embed<CFF1NameIndex> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, *acc.nameIndex))) if (unlikely (!dest->serialize (c, *acc.nameIndex)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF name INDEX");
return false; return false;
@ -915,12 +912,12 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* top dict INDEX */ /* top dict INDEX */
{ {
assert (plan.offsets.topDictInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.topDictInfo.offset == (unsigned) (c->head - c->start));
CFF1IndexOf<TopDict> *dest = c.start_embed< CFF1IndexOf<TopDict>> (); CFF1IndexOf<TopDict> *dest = c->start_embed< CFF1IndexOf<TopDict>> ();
if (dest == nullptr) return false; if (dest == nullptr) return false;
cff1_top_dict_op_serializer_t topSzr; cff1_top_dict_op_serializer_t topSzr;
top_dict_modifiers_t modifier (plan.offsets, plan.topDictModSIDs); top_dict_modifiers_t modifier (plan.offsets, plan.topDictModSIDs);
if (unlikely (!dest->serialize (&c, plan.offsets.topDictInfo.offSize, if (unlikely (!dest->serialize (c, plan.offsets.topDictInfo.offSize,
&plan.topdict_mod, 1, &plan.topdict_mod, 1,
plan.topdict_sizes, topSzr, modifier))) plan.topdict_sizes, topSzr, modifier)))
{ {
@ -931,10 +928,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* String INDEX */ /* String INDEX */
{ {
assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.stringIndexInfo.offset == (unsigned) (c->head - c->start));
CFF1StringIndex *dest = c.start_embed<CFF1StringIndex> (); CFF1StringIndex *dest = c->start_embed<CFF1StringIndex> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap))) if (unlikely (!dest->serialize (c, *acc.stringIndex, plan.offsets.stringIndexInfo.offSize, plan.sidmap)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF string INDEX");
return false; return false;
@ -944,11 +941,11 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* global subrs */ /* global subrs */
{ {
assert (plan.offsets.globalSubrsInfo.offset != 0); assert (plan.offsets.globalSubrsInfo.offset != 0);
assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.globalSubrsInfo.offset == (unsigned) (c->head - c->start));
CFF1Subrs *dest = c.start_embed <CFF1Subrs> (); CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs))) if (unlikely (!dest->serialize (c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
return false; return false;
@ -958,10 +955,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* Encoding */ /* Encoding */
if (plan.subset_encoding) if (plan.subset_encoding)
{ {
assert (plan.offsets.encodingOffset == (unsigned) (c.head - c.start)); assert (plan.offsets.encodingOffset == (unsigned) (c->head - c->start));
Encoding *dest = c.start_embed<Encoding> (); Encoding *dest = c->start_embed<Encoding> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, if (unlikely (!dest->serialize (c,
plan.subset_enc_format, plan.subset_enc_format,
plan.subset_enc_num_codes, plan.subset_enc_num_codes,
plan.subset_enc_code_ranges, plan.subset_enc_code_ranges,
@ -975,10 +972,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* Charset */ /* Charset */
if (plan.subset_charset) if (plan.subset_charset)
{ {
assert (plan.offsets.charsetInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.charsetInfo.offset == (unsigned) (c->head - c->start));
Charset *dest = c.start_embed<Charset> (); Charset *dest = c->start_embed<Charset> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, if (unlikely (!dest->serialize (c,
plan.subset_charset_format, plan.subset_charset_format,
plan.num_glyphs, plan.num_glyphs,
plan.subset_charset_ranges))) plan.subset_charset_ranges)))
@ -991,9 +988,9 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* FDSelect */ /* FDSelect */
if (acc.fdSelect != &Null(CFF1FDSelect)) if (acc.fdSelect != &Null(CFF1FDSelect))
{ {
assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c->head - c->start));
if (unlikely (!hb_serialize_cff_fdselect (&c, num_glyphs, *acc.fdSelect, acc.fdCount, if (unlikely (!hb_serialize_cff_fdselect (c, num_glyphs, *acc.fdSelect, acc.fdCount,
plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size, plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
plan.subset_fdselect_ranges))) plan.subset_fdselect_ranges)))
{ {
@ -1005,11 +1002,11 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* FDArray (FD Index) */ /* FDArray (FD Index) */
if (acc.fdArray != &Null(CFF1FDArray)) if (acc.fdArray != &Null(CFF1FDArray))
{ {
assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c->head - c->start));
CFF1FDArray *fda = c.start_embed<CFF1FDArray> (); CFF1FDArray *fda = c->start_embed<CFF1FDArray> ();
if (unlikely (fda == nullptr)) return false; if (unlikely (fda == nullptr)) return false;
cff1_font_dict_op_serializer_t fontSzr; cff1_font_dict_op_serializer_t fontSzr;
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize, if (unlikely (!fda->serialize (c, plan.offsets.FDArrayInfo.offSize,
plan.fontdicts_mod, plan.fontdicts_mod,
fontSzr))) fontSzr)))
{ {
@ -1020,10 +1017,10 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
/* CharStrings */ /* CharStrings */
{ {
assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.charStringsInfo.offset == (unsigned) (c->head - c->start));
CFF1CharStrings *cs = c.start_embed<CFF1CharStrings> (); CFF1CharStrings *cs = c->start_embed<CFF1CharStrings> ();
if (unlikely (cs == nullptr)) return false; if (unlikely (cs == nullptr)) return false;
if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings))) if (unlikely (!cs->serialize (c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF CharStrings");
return false; return false;
@ -1031,19 +1028,19 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
} }
/* private dicts & local subrs */ /* private dicts & local subrs */
assert (plan.offsets.privateDictInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.privateDictInfo.offset == (unsigned) (c->head - c->start));
for (unsigned int i = 0; i < acc.privateDicts.length; i++) for (unsigned int i = 0; i < acc.privateDicts.length; i++)
{ {
if (plan.fdmap.has (i)) if (plan.fdmap.has (i))
{ {
PrivateDict *pd = c.start_embed<PrivateDict> (); PrivateDict *pd = c->start_embed<PrivateDict> ();
if (unlikely (pd == nullptr)) return false; if (unlikely (pd == nullptr)) return false;
unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size; unsigned int priv_size = plan.fontdicts_mod[plan.fdmap[i]].privateDictInfo.size;
bool result; bool result;
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0; unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset); result = pd->serialize (c, acc.privateDicts[i], privSzr, subroffset);
if (unlikely (!result)) if (unlikely (!result))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
@ -1051,9 +1048,9 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
} }
if (plan.offsets.localSubrsInfos[i].size > 0) if (plan.offsets.localSubrsInfos[i].size > 0)
{ {
CFF1Subrs *dest = c.start_embed <CFF1Subrs> (); CFF1Subrs *dest = c->start_embed <CFF1Subrs> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i]))) if (unlikely (!dest->serialize (c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
return false; return false;
@ -1062,41 +1059,26 @@ static inline bool _write_cff1 (const cff_subset_plan &plan,
} }
} }
assert (c.head == c.end);
c.end_serialize ();
return true; return true;
} }
static inline bool static inline bool
_hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc, _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
const char *data, hb_subset_context_t *c)
hb_subset_plan_t *plan,
hb_blob_t **prime /* OUT */)
{ {
cff_subset_plan cff_plan; cff_subset_plan cff_plan;
if (unlikely (!cff_plan.create (acc, plan))) if (unlikely (!cff_plan.create (acc, c->plan)))
{ {
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan."); DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff subsetting plan.");
return false; return false;
} }
unsigned int cff_prime_size = cff_plan.get_final_size (); if (unlikely (!_write_cff1 (c->serializer, cff_plan, acc, c->plan->num_output_glyphs ()))) {
char *cff_prime_data = (char *) calloc (1, cff_prime_size);
if (unlikely (!_write_cff1 (cff_plan, acc, plan->num_output_glyphs (),
cff_prime_size, cff_prime_data))) {
DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff."); DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff.");
free (cff_prime_data);
return false; return false;
} }
*prime = hb_blob_create (cff_prime_data,
cff_prime_size,
HB_MEMORY_MODE_READONLY,
cff_prime_data,
free);
return true; return true;
} }
@ -1107,16 +1089,14 @@ _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc,
* Return value: subsetted cff table. * Return value: subsetted cff table.
**/ **/
bool bool
hb_subset_cff1 (hb_subset_plan_t *plan, hb_subset_cff1 (hb_subset_context_t *c)
hb_blob_t **prime /* OUT */)
{ {
hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (plan->source); hb_blob_t *cff_blob = hb_sanitize_context_t().reference_table<CFF::cff1> (c->plan->source);
const char *data = hb_blob_get_data(cff_blob, nullptr);
OT::cff1::accelerator_subset_t acc; OT::cff1::accelerator_subset_t acc;
acc.init(plan->source); acc.init(c->plan->source);
bool result = likely (acc.is_valid ()) && bool result = likely (acc.is_valid ()) &&
_hb_subset_cff1 (acc, data, plan, prime); _hb_subset_cff1 (acc, c);
hb_blob_destroy (cff_blob); hb_blob_destroy (cff_blob);
acc.fini (); acc.fini ();

View File

@ -32,7 +32,6 @@
#include "hb-subset-plan.hh" #include "hb-subset-plan.hh"
HB_INTERNAL bool HB_INTERNAL bool
hb_subset_cff1 (hb_subset_plan_t *plan, hb_subset_cff1 (hb_subset_context_t *c);
hb_blob_t **cff_prime /* OUT */);
#endif /* HB_SUBSET_CFF1_HH */ #endif /* HB_SUBSET_CFF1_HH */

View File

@ -439,16 +439,13 @@ struct cff2_subset_plan {
bool desubroutinize; bool desubroutinize;
}; };
static inline bool _write_cff2 (const cff2_subset_plan &plan, static inline bool _write_cff2 (hb_serialize_context_t *c,
const cff2_subset_plan &plan,
const OT::cff2::accelerator_subset_t &acc, const OT::cff2::accelerator_subset_t &acc,
unsigned int num_glyphs, unsigned int num_glyphs)
unsigned int dest_sz,
void *dest)
{ {
hb_serialize_context_t c (dest, dest_sz); OT::cff2 *cff2 = c->allocate_min<OT::cff2> ();
if (unlikely (!cff2))
OT::cff2 *cff2 = c.start_serialize<OT::cff2> ();
if (unlikely (!c.extend_min (*cff2)))
return false; return false;
/* header */ /* header */
@ -458,11 +455,11 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* top dict */ /* top dict */
{ {
assert (cff2->topDict == (unsigned) (c.head - c.start)); assert (cff2->topDict == (unsigned) (c->head - c->start));
cff2->topDictSize = plan.offsets.topDictInfo.size; cff2->topDictSize = plan.offsets.topDictInfo.size;
TopDict &dict = cff2 + cff2->topDict; TopDict &dict = cff2 + cff2->topDict;
cff2_top_dict_op_serializer_t topSzr; cff2_top_dict_op_serializer_t topSzr;
if (unlikely (!dict.serialize (&c, acc.topDict, topSzr, plan.offsets))) if (unlikely (!dict.serialize (c, acc.topDict, topSzr, plan.offsets)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 top dict");
return false; return false;
@ -471,10 +468,10 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* global subrs */ /* global subrs */
{ {
assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c.head - c.start)); assert (cff2->topDict + plan.offsets.topDictInfo.size == (unsigned) (c->head - c->start));
CFF2Subrs *dest = c.start_embed <CFF2Subrs> (); CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs))) if (unlikely (!dest->serialize (c, plan.offsets.globalSubrsInfo.offSize, plan.subset_globalsubrs)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize global subroutines");
return false; return false;
@ -484,9 +481,9 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* variation store */ /* variation store */
if (acc.varStore != &Null(CFF2VariationStore)) if (acc.varStore != &Null(CFF2VariationStore))
{ {
assert (plan.offsets.varStoreOffset == (unsigned) (c.head - c.start)); assert (plan.offsets.varStoreOffset == (unsigned) (c->head - c->start));
CFF2VariationStore *dest = c.start_embed<CFF2VariationStore> (); CFF2VariationStore *dest = c->start_embed<CFF2VariationStore> ();
if (unlikely (!dest->serialize (&c, acc.varStore))) if (unlikely (!dest->serialize (c, acc.varStore)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 Variation Store");
return false; return false;
@ -496,9 +493,9 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* FDSelect */ /* FDSelect */
if (acc.fdSelect != &Null(CFF2FDSelect)) if (acc.fdSelect != &Null(CFF2FDSelect))
{ {
assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c->head - c->start));
if (unlikely (!hb_serialize_cff_fdselect (&c, num_glyphs, *(const FDSelect *)acc.fdSelect, acc.fdArray->count, if (unlikely (!hb_serialize_cff_fdselect (c, num_glyphs, *(const FDSelect *)acc.fdSelect, acc.fdArray->count,
plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size, plan.subset_fdselect_format, plan.offsets.FDSelectInfo.size,
plan.subset_fdselect_ranges))) plan.subset_fdselect_ranges)))
{ {
@ -509,11 +506,11 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* FDArray (FD Index) */ /* FDArray (FD Index) */
{ {
assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.FDArrayInfo.offset == (unsigned) (c->head - c->start));
CFF2FDArray *fda = c.start_embed<CFF2FDArray> (); CFF2FDArray *fda = c->start_embed<CFF2FDArray> ();
if (unlikely (fda == nullptr)) return false; if (unlikely (fda == nullptr)) return false;
cff_font_dict_op_serializer_t fontSzr; cff_font_dict_op_serializer_t fontSzr;
if (unlikely (!fda->serialize (&c, plan.offsets.FDArrayInfo.offSize, if (unlikely (!fda->serialize (c, plan.offsets.FDArrayInfo.offSize,
acc.fontDicts, plan.subset_fdcount, plan.fdmap, acc.fontDicts, plan.subset_fdcount, plan.fdmap,
fontSzr, plan.privateDictInfos))) fontSzr, plan.privateDictInfos)))
{ {
@ -524,10 +521,10 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
/* CharStrings */ /* CharStrings */
{ {
assert (plan.offsets.charStringsInfo.offset == (unsigned) (c.head - c.start)); assert (plan.offsets.charStringsInfo.offset == (unsigned) (c->head - c->start));
CFF2CharStrings *cs = c.start_embed<CFF2CharStrings> (); CFF2CharStrings *cs = c->start_embed<CFF2CharStrings> ();
if (unlikely (cs == nullptr)) return false; if (unlikely (cs == nullptr)) return false;
if (unlikely (!cs->serialize (&c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings))) if (unlikely (!cs->serialize (c, plan.offsets.charStringsInfo.offSize, plan.subset_charstrings)))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF2 CharStrings");
return false; return false;
@ -535,19 +532,19 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
} }
/* private dicts & local subrs */ /* private dicts & local subrs */
assert (plan.offsets.privateDictsOffset == (unsigned) (c.head - c.start)); assert (plan.offsets.privateDictsOffset == (unsigned) (c->head - c->start));
for (unsigned int i = 0; i < acc.privateDicts.length; i++) for (unsigned int i = 0; i < acc.privateDicts.length; i++)
{ {
if (plan.fdmap.has (i)) if (plan.fdmap.has (i))
{ {
PrivateDict *pd = c.start_embed<PrivateDict> (); PrivateDict *pd = c->start_embed<PrivateDict> ();
if (unlikely (pd == nullptr)) return false; if (unlikely (pd == nullptr)) return false;
unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size; unsigned int priv_size = plan.privateDictInfos[plan.fdmap[i]].size;
bool result; bool result;
cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints); cff_private_dict_op_serializer_t privSzr (plan.desubroutinize, plan.drop_hints);
/* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */ /* N.B. local subrs immediately follows its corresponding private dict. i.e., subr offset == private dict size */
unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0; unsigned int subroffset = (plan.offsets.localSubrsInfos[i].size > 0) ? priv_size : 0;
result = pd->serialize (&c, acc.privateDicts[i], privSzr, subroffset); result = pd->serialize (c, acc.privateDicts[i], privSzr, subroffset);
if (unlikely (!result)) if (unlikely (!result))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i); DEBUG_MSG (SUBSET, nullptr, "failed to serialize CFF Private Dict[%d]", i);
@ -555,9 +552,9 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
} }
if (plan.offsets.localSubrsInfos[i].size > 0) if (plan.offsets.localSubrsInfos[i].size > 0)
{ {
CFF2Subrs *dest = c.start_embed <CFF2Subrs> (); CFF2Subrs *dest = c->start_embed <CFF2Subrs> ();
if (unlikely (dest == nullptr)) return false; if (unlikely (dest == nullptr)) return false;
if (unlikely (!dest->serialize (&c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i]))) if (unlikely (!dest->serialize (c, plan.offsets.localSubrsInfos[i].offSize, plan.subset_localsubrs[i])))
{ {
DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines"); DEBUG_MSG (SUBSET, nullptr, "failed to serialize local subroutines");
return false; return false;
@ -566,61 +563,42 @@ static inline bool _write_cff2 (const cff2_subset_plan &plan,
} }
} }
assert (c.head == c.end);
c.end_serialize ();
return true; return true;
} }
static inline bool static inline bool
_hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc, _hb_subset_cff2 (const OT::cff2::accelerator_subset_t &acc,
const char *data, hb_subset_context_t *c)
hb_subset_plan_t *plan,
hb_blob_t **prime /* OUT */)
{ {
cff2_subset_plan cff2_plan; cff2_subset_plan cff2_plan;
if (unlikely (!cff2_plan.create (acc, plan))) if (unlikely (!cff2_plan.create (acc, c->plan)))
{ {
DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan."); DEBUG_MSG(SUBSET, nullptr, "Failed to generate a cff2 subsetting plan.");
return false; return false;
} }
unsigned int cff2_prime_size = cff2_plan.get_final_size (); if (unlikely (!_write_cff2 (c->serializer, cff2_plan, acc, c->plan->num_output_glyphs ()))) {
char *cff2_prime_data = (char *) calloc (1, cff2_prime_size);
if (unlikely (!_write_cff2 (cff2_plan, acc, plan->num_output_glyphs (),
cff2_prime_size, cff2_prime_data))) {
DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2."); DEBUG_MSG(SUBSET, nullptr, "Failed to write a subset cff2.");
free (cff2_prime_data);
return false; return false;
} }
*prime = hb_blob_create (cff2_prime_data,
cff2_prime_size,
HB_MEMORY_MODE_READONLY,
cff2_prime_data,
free);
return true; return true;
} }
/** /**
* hb_subset_cff2: * hb_subset_cff2:
* Subsets the CFF2 table according to a provided plan. * Subsets the CFF2 table according to a provided subset context.
*
* Return value: subsetted cff2 table.
**/ **/
bool bool
hb_subset_cff2 (hb_subset_plan_t *plan, hb_subset_cff2 (hb_subset_context_t *c)
hb_blob_t **prime /* OUT */)
{ {
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> (c->plan->source);
const char *data = hb_blob_get_data(cff2_blob, nullptr);
OT::cff2::accelerator_subset_t acc; OT::cff2::accelerator_subset_t acc;
acc.init(plan->source); acc.init(c->plan->source);
bool result = likely (acc.is_valid ()) && bool result = likely (acc.is_valid ()) &&
_hb_subset_cff2 (acc, data, plan, prime); _hb_subset_cff2 (acc, c);
hb_blob_destroy (cff2_blob); hb_blob_destroy (cff2_blob);
acc.fini (); acc.fini ();

View File

@ -32,7 +32,6 @@
#include "hb-subset-plan.hh" #include "hb-subset-plan.hh"
HB_INTERNAL bool HB_INTERNAL bool
hb_subset_cff2 (hb_subset_plan_t *plan, hb_subset_cff2 (hb_subset_context_t *c);
hb_blob_t **cff2_prime /* OUT */);
#endif /* HB_SUBSET_CFF2_HH */ #endif /* HB_SUBSET_CFF2_HH */

View File

@ -210,10 +210,10 @@ _subset_table (hb_subset_plan_t *plan,
#ifndef HB_NO_SUBSET_CFF #ifndef HB_NO_SUBSET_CFF
case HB_OT_TAG_cff1: case HB_OT_TAG_cff1:
result = _subset<const OT::cff1> (plan); result = _subset2<const OT::cff1> (plan);
break; break;
case HB_OT_TAG_cff2: case HB_OT_TAG_cff2:
result = _subset<const OT::cff2> (plan); result = _subset2<const OT::cff2> (plan);
break; break;
case HB_OT_TAG_VORG: case HB_OT_TAG_VORG:
result = _subset2<const OT::VORG> (plan); result = _subset2<const OT::VORG> (plan);