[subset] don't copy the entire global/loca subr lists from the accelerator.
Instead run a closure on the retained charstrings and copy only the referenced subrs. This significantly speeds up cases with small character sets.
This commit is contained in:
parent
4ff09274a8
commit
71c23c1c07
|
@ -606,25 +606,27 @@ struct subr_subsetter_t
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false;
|
unsigned fd_count = acc.fdCount;
|
||||||
|
cff_subset_accelerator_t* cff_accelerator = nullptr;
|
||||||
|
if (plan->accelerator && plan->accelerator->cff_accelerator) {
|
||||||
|
cff_accelerator = plan->accelerator->cff_accelerator;
|
||||||
|
fd_count = cff_accelerator->parsed_local_subrs.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (unlikely (!parsed_local_subrs.resize (fd_count))) return false;
|
||||||
|
|
||||||
for (unsigned int i = 0; i < acc.fdCount; i++)
|
for (unsigned int i = 0; i < acc.fdCount; i++)
|
||||||
{
|
{
|
||||||
parsed_local_subrs[i].resize (acc.privateDicts[i].localSubrs->count);
|
unsigned count = cff_accelerator
|
||||||
|
? cff_accelerator->parsed_local_subrs[i].length
|
||||||
|
: acc.privateDicts[i].localSubrs->count;
|
||||||
|
parsed_local_subrs[i].resize (count);
|
||||||
if (unlikely (parsed_local_subrs[i].in_error ())) return false;
|
if (unlikely (parsed_local_subrs[i].in_error ())) return false;
|
||||||
}
|
}
|
||||||
if (unlikely (!closures.valid))
|
if (unlikely (!closures.valid))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (plan->accelerator && plan->accelerator->cff_accelerator) {
|
|
||||||
// Parsed subroutine char stsrings already exist in the accelerator. Copy
|
|
||||||
// them in.
|
|
||||||
// TODO(grieger): use reference instead of copy.
|
|
||||||
parsed_global_subrs =
|
|
||||||
plan->accelerator->cff_accelerator->parsed_global_subrs;
|
|
||||||
parsed_local_subrs =
|
|
||||||
plan->accelerator->cff_accelerator->parsed_local_subrs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* phase 1 & 2 */
|
/* phase 1 & 2 */
|
||||||
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
|
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
|
||||||
|
@ -638,13 +640,12 @@ struct subr_subsetter_t
|
||||||
if (unlikely (fd >= acc.fdCount))
|
if (unlikely (fd >= acc.fdCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (plan->accelerator && plan->accelerator->cff_accelerator)
|
if (cff_accelerator)
|
||||||
{
|
{
|
||||||
// parsed string already exists in accelerator, copy it and move
|
// parsed string already exists in accelerator, copy it and move
|
||||||
// on.
|
// on.
|
||||||
// TODO(grieger): use reference instead of copy.
|
|
||||||
parsed_charstrings[i] =
|
parsed_charstrings[i] =
|
||||||
plan->accelerator->cff_accelerator->parsed_charstrings[glyph];
|
cff_accelerator->parsed_charstrings[glyph];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,6 +667,14 @@ struct subr_subsetter_t
|
||||||
SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
|
SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since parsed strings were loaded from accelerator, we still need
|
||||||
|
// to compute the subroutine closures which would have normally happened during
|
||||||
|
// parsing.
|
||||||
|
if (cff_accelerator &&
|
||||||
|
!closure_and_copy_subroutines(cff_accelerator->parsed_global_subrs,
|
||||||
|
cff_accelerator->parsed_local_subrs))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||||
{
|
{
|
||||||
/* mark hint ops and arguments for drop */
|
/* mark hint ops and arguments for drop */
|
||||||
|
@ -694,14 +703,7 @@ struct subr_subsetter_t
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after dropping hints recreate closures of actually used subrs */
|
/* after dropping hints recreate closures of actually used subrs */
|
||||||
closures.reset ();
|
if (!closure_subroutines(parsed_global_subrs, parsed_local_subrs)) return false;
|
||||||
if (!closure_subroutines()) return false;
|
|
||||||
} else if (plan->accelerator && plan->accelerator->cff_accelerator) {
|
|
||||||
// Since parsed strings were loaded from accelerator, we still need
|
|
||||||
// to compute the subroutine closures which would have normally happened during
|
|
||||||
// parsing.
|
|
||||||
closures.reset ();
|
|
||||||
if (!closure_subroutines()) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remaps.create (closures);
|
remaps.create (closures);
|
||||||
|
@ -890,7 +892,31 @@ struct subr_subsetter_t
|
||||||
return seen_hint;
|
return seen_hint;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool closure_subroutines ()
|
bool closure_and_copy_subroutines (parsed_cs_str_vec_t& global_subrs,
|
||||||
|
hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
|
||||||
|
{
|
||||||
|
if (!closure_subroutines(global_subrs,
|
||||||
|
local_subrs)) return false;
|
||||||
|
|
||||||
|
|
||||||
|
for (unsigned s : closures.global_closure) {
|
||||||
|
parsed_global_subrs[s] = global_subrs[s];
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned fd = 0;
|
||||||
|
for (const hb_set_t& c : closures.local_closures) {
|
||||||
|
for (unsigned s : c) {
|
||||||
|
parsed_local_subrs[fd][s] = local_subrs[fd][s];
|
||||||
|
}
|
||||||
|
fd++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool closure_subroutines (parsed_cs_str_vec_t& global_subrs,
|
||||||
|
hb_vector_t<parsed_cs_str_vec_t>& local_subrs)
|
||||||
{
|
{
|
||||||
closures.reset ();
|
closures.reset ();
|
||||||
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
|
for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
|
||||||
|
@ -902,8 +928,8 @@ struct subr_subsetter_t
|
||||||
if (unlikely (fd >= acc.fdCount))
|
if (unlikely (fd >= acc.fdCount))
|
||||||
return false;
|
return false;
|
||||||
subr_subset_param_t param (&parsed_charstrings[i],
|
subr_subset_param_t param (&parsed_charstrings[i],
|
||||||
&parsed_global_subrs,
|
&global_subrs,
|
||||||
&parsed_local_subrs[fd],
|
&local_subrs[fd],
|
||||||
&closures.global_closure,
|
&closures.global_closure,
|
||||||
&closures.local_closures[fd],
|
&closures.local_closures[fd],
|
||||||
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
|
plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
|
||||||
|
@ -913,7 +939,7 @@ struct subr_subsetter_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_subr_refs_in_subr (parsed_cs_str_t &str, unsigned int pos,
|
void collect_subr_refs_in_subr (const parsed_cs_str_t &str, unsigned int pos,
|
||||||
unsigned int subr_num, parsed_cs_str_vec_t &subrs,
|
unsigned int subr_num, parsed_cs_str_vec_t &subrs,
|
||||||
hb_set_t *closure,
|
hb_set_t *closure,
|
||||||
const subr_subset_param_t ¶m)
|
const subr_subset_param_t ¶m)
|
||||||
|
@ -924,7 +950,7 @@ struct subr_subsetter_t
|
||||||
collect_subr_refs_in_str (subrs[subr_num], param);
|
collect_subr_refs_in_str (subrs[subr_num], param);
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_subr_refs_in_str (parsed_cs_str_t &str, const subr_subset_param_t ¶m)
|
void collect_subr_refs_in_str (const parsed_cs_str_t &str, const subr_subset_param_t ¶m)
|
||||||
{
|
{
|
||||||
for (unsigned int pos = 0; pos < str.values.length; pos++)
|
for (unsigned int pos = 0; pos < str.values.length; pos++)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue