|
|
|
@ -392,8 +392,11 @@ struct cff1_cs_opset_subr_subset_t : cff1_cs_opset_t<cff1_cs_opset_subr_subset_t |
|
|
|
|
typedef cff1_cs_opset_t<cff1_cs_opset_subr_subset_t, subr_subset_param_t> SUPER; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t> |
|
|
|
|
struct cff1_subr_subsetter_t : subr_subsetter_t<cff1_subr_subsetter_t, CFF1Subrs, const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_subr_subset_t, OpCode_endchar> |
|
|
|
|
{ |
|
|
|
|
cff1_subr_subsetter_t (const OT::cff1::accelerator_subset_t &acc, const hb_subset_plan_t *plan) |
|
|
|
|
: subr_subsetter_t (acc, plan) {} |
|
|
|
|
|
|
|
|
|
static void finalize_parsed_str (cff1_cs_interp_env_t &env, subr_subset_param_t& param, parsed_cs_str_t &charstring) |
|
|
|
|
{ |
|
|
|
|
/* insert width at the beginning of the charstring as necessary */ |
|
|
|
@ -469,17 +472,26 @@ struct cff_subset_plan { |
|
|
|
|
supp_size = 0; |
|
|
|
|
supp_codes.init (); |
|
|
|
|
|
|
|
|
|
subset_enc_num_codes = plan->glyphs_deprecated.length - 1; |
|
|
|
|
subset_enc_num_codes = plan->num_output_glyphs () - 1; |
|
|
|
|
unsigned int glyph; |
|
|
|
|
for (glyph = 1; glyph < plan->glyphs_deprecated.length; glyph++) |
|
|
|
|
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) |
|
|
|
|
{ |
|
|
|
|
hb_codepoint_t orig_glyph; |
|
|
|
|
if (!plan->old_gid_for_new_gid (glyph, &orig_glyph)) |
|
|
|
|
{ |
|
|
|
|
/* pretend a missing glyph has the last code + 1
|
|
|
|
|
* as an attempt to minimize the number of ranges */ |
|
|
|
|
code = last_code + 1; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
hb_codepoint_t orig_glyph = plan->glyphs_deprecated[glyph]; |
|
|
|
|
code = acc.glyph_to_code (orig_glyph); |
|
|
|
|
if (code == CFF_UNDEF_CODE) |
|
|
|
|
{ |
|
|
|
|
subset_enc_num_codes = glyph - 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (code != last_code + 1) |
|
|
|
|
{ |
|
|
|
@ -526,13 +538,22 @@ struct cff_subset_plan { |
|
|
|
|
|
|
|
|
|
subset_charset_ranges.resize (0); |
|
|
|
|
unsigned int glyph; |
|
|
|
|
for (glyph = 1; glyph < plan->glyphs_deprecated.length; glyph++) |
|
|
|
|
for (glyph = 1; glyph < plan->num_output_glyphs (); glyph++) |
|
|
|
|
{ |
|
|
|
|
hb_codepoint_t orig_glyph; |
|
|
|
|
if (!plan->old_gid_for_new_gid (glyph, &orig_glyph)) |
|
|
|
|
{ |
|
|
|
|
/* pretend a missing glyph has the last sid + 1
|
|
|
|
|
* as an attempt to minimize the number of ranges */ |
|
|
|
|
sid = last_sid + 1; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
hb_codepoint_t orig_glyph = plan->glyphs_deprecated[glyph]; |
|
|
|
|
sid = acc.glyph_to_sid (orig_glyph); |
|
|
|
|
|
|
|
|
|
if (!acc.is_CID ()) |
|
|
|
|
sid = sidmap.add (sid); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (sid != last_sid + 1) |
|
|
|
|
{ |
|
|
|
@ -544,7 +565,7 @@ struct cff_subset_plan { |
|
|
|
|
|
|
|
|
|
bool two_byte = subset_charset_ranges.finalize (glyph); |
|
|
|
|
|
|
|
|
|
size0 = Charset0::min_size + HBUINT16::static_size * (plan->glyphs_deprecated.length - 1); |
|
|
|
|
size0 = Charset0::min_size + HBUINT16::static_size * (plan->num_output_glyphs () - 1); |
|
|
|
|
if (!two_byte) |
|
|
|
|
size_ranges = Charset1::min_size + Charset1_Range::static_size * subset_charset_ranges.length; |
|
|
|
|
else |
|
|
|
@ -559,7 +580,7 @@ struct cff_subset_plan { |
|
|
|
|
|
|
|
|
|
return Charset::calculate_serialized_size ( |
|
|
|
|
subset_charset_format, |
|
|
|
|
subset_charset_format? subset_charset_ranges.length: plan->glyphs_deprecated.length); |
|
|
|
|
subset_charset_format? subset_charset_ranges.length: plan->num_output_glyphs ()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool collect_sids_in_dicts (const OT::cff1::accelerator_subset_t &acc) |
|
|
|
@ -589,19 +610,22 @@ struct cff_subset_plan { |
|
|
|
|
hb_subset_plan_t *plan) |
|
|
|
|
{ |
|
|
|
|
/* make sure notdef is first */ |
|
|
|
|
if ((plan->glyphs_deprecated.length == 0) || (plan->glyphs_deprecated[0] != 0)) return false; |
|
|
|
|
hb_codepoint_t old_glyph; |
|
|
|
|
if (!plan->old_gid_for_new_gid (0, &old_glyph) || (old_glyph != 0)) return false; |
|
|
|
|
|
|
|
|
|
final_size = 0; |
|
|
|
|
num_glyphs = plan->glyphs_deprecated.length; |
|
|
|
|
num_glyphs = plan->num_output_glyphs (); |
|
|
|
|
orig_fdcount = acc.fdCount; |
|
|
|
|
drop_hints = plan->drop_hints; |
|
|
|
|
desubroutinize = plan->desubroutinize; |
|
|
|
|
|
|
|
|
|
/* check whether the subset renumbers any glyph IDs */ |
|
|
|
|
gid_renum = false; |
|
|
|
|
for (unsigned int glyph = 0; glyph < plan->glyphs_deprecated.length; glyph++) |
|
|
|
|
for (hb_codepoint_t new_glyph = 0; new_glyph < plan->num_output_glyphs (); new_glyph++) |
|
|
|
|
{ |
|
|
|
|
if (plan->glyphs_deprecated[glyph] != glyph) { |
|
|
|
|
if (!plan->old_gid_for_new_gid(new_glyph, &old_glyph)) |
|
|
|
|
continue; |
|
|
|
|
if (new_glyph != old_glyph) { |
|
|
|
|
gid_renum = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -644,7 +668,7 @@ struct cff_subset_plan { |
|
|
|
|
/* Determine re-mapping of font index as fdmap among other info */ |
|
|
|
|
if (acc.fdSelect != &Null(CFF1FDSelect)) |
|
|
|
|
{ |
|
|
|
|
if (unlikely (!hb_plan_subset_cff_fdselect (plan->glyphs_deprecated, |
|
|
|
|
if (unlikely (!hb_plan_subset_cff_fdselect (plan, |
|
|
|
|
orig_fdcount, |
|
|
|
|
*acc.fdSelect, |
|
|
|
|
subset_fdcount, |
|
|
|
@ -680,8 +704,8 @@ struct cff_subset_plan { |
|
|
|
|
if (desubroutinize) |
|
|
|
|
{ |
|
|
|
|
/* Flatten global & local subrs */ |
|
|
|
|
subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t> |
|
|
|
|
flattener(acc, plan->glyphs_deprecated, plan->drop_hints); |
|
|
|
|
subr_flattener_t<const OT::cff1::accelerator_subset_t, cff1_cs_interp_env_t, cff1_cs_opset_flatten_t, OpCode_endchar> |
|
|
|
|
flattener(acc, plan); |
|
|
|
|
if (!flattener.flatten (subset_charstrings)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
@ -690,12 +714,14 @@ struct cff_subset_plan { |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
cff1_subr_subsetter_t subr_subsetter (acc, plan); |
|
|
|
|
|
|
|
|
|
/* Subset subrs: collect used subroutines, leaving all unused ones behind */ |
|
|
|
|
if (!subr_subsetter.subset (acc, plan->glyphs_deprecated, plan->drop_hints)) |
|
|
|
|
if (!subr_subsetter.subset ()) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
/* encode charstrings, global subrs, local subrs with new subroutine numbers */ |
|
|
|
|
if (!subr_subsetter.encode_charstrings (acc, plan->glyphs_deprecated, subset_charstrings)) |
|
|
|
|
if (!subr_subsetter.encode_charstrings (subset_charstrings)) |
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
if (!subr_subsetter.encode_globalsubrs (subset_globalsubrs)) |
|
|
|
@ -784,7 +810,7 @@ struct cff_subset_plan { |
|
|
|
|
offsets.charStringsInfo.offSize = calcOffSize (dataSize); |
|
|
|
|
if (unlikely (offsets.charStringsInfo.offSize > 4)) |
|
|
|
|
return false; |
|
|
|
|
final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->glyphs_deprecated.length, dataSize); |
|
|
|
|
final_size += CFF1CharStrings::calculate_serialized_size (offsets.charStringsInfo.offSize, plan->num_output_glyphs (), dataSize); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* private dicts & local subrs */ |
|
|
|
@ -816,7 +842,7 @@ struct cff_subset_plan { |
|
|
|
|
if (!acc.is_CID ()) |
|
|
|
|
offsets.privateDictInfo = fontdicts_mod[0].privateDictInfo; |
|
|
|
|
|
|
|
|
|
return ((subset_charstrings.length == plan->glyphs_deprecated.length) |
|
|
|
|
return ((subset_charstrings.length == plan->num_output_glyphs ()) |
|
|
|
|
&& (fontdicts_mod.length == subset_fdcount)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -859,12 +885,11 @@ struct cff_subset_plan { |
|
|
|
|
unsigned int topDictModSIDs[name_dict_values_t::ValCount]; |
|
|
|
|
|
|
|
|
|
bool desubroutinize; |
|
|
|
|
cff1_subr_subsetter_t subr_subsetter; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static inline bool _write_cff1 (const cff_subset_plan &plan, |
|
|
|
|
const OT::cff1::accelerator_subset_t &acc, |
|
|
|
|
const hb_vector_t<hb_codepoint_t>& glyphs, |
|
|
|
|
unsigned int num_glyphs, |
|
|
|
|
unsigned int dest_sz, |
|
|
|
|
void *dest) |
|
|
|
|
{ |
|
|
|
@ -972,7 +997,7 @@ static inline bool _write_cff1 (const cff_subset_plan &plan, |
|
|
|
|
{ |
|
|
|
|
assert (plan.offsets.FDSelectInfo.offset == (unsigned) (c.head - c.start)); |
|
|
|
|
|
|
|
|
|
if (unlikely (!hb_serialize_cff_fdselect (&c, glyphs.length, *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_ranges))) |
|
|
|
|
{ |
|
|
|
@ -1064,7 +1089,7 @@ _hb_subset_cff1 (const OT::cff1::accelerator_subset_t &acc, |
|
|
|
|
unsigned int cff_prime_size = cff_plan.get_final_size (); |
|
|
|
|
char *cff_prime_data = (char *) calloc (1, cff_prime_size); |
|
|
|
|
|
|
|
|
|
if (unlikely (!_write_cff1 (cff_plan, acc, plan->glyphs_deprecated, |
|
|
|
|
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."); |
|
|
|
|
free (cff_prime_data); |
|
|
|
|