first rewrite of cff/cff2 _subset with _subset2
This commit is contained in:
parent
b2a68ed587
commit
2792fb8ba1
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue