[subset-cff] Compact parsed strings if using accelerator
Saves 32% on SourceHanSans/10000 benchmark! Also, use memcmp now for writing out strings since now that our ops are not super short, that's faster. This makes cff-japanese test takes super long though; that needs inspection.
This commit is contained in:
parent
6012d3b228
commit
2644540a74
|
@ -118,14 +118,7 @@ struct str_encoder_t
|
||||||
else if (unlikely (!buff.resize (offset + length)))
|
else if (unlikely (!buff.resize (offset + length)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Faster than hb_memcpy for small strings. */
|
hb_memcpy (buff.arrayZ + offset, str, length);
|
||||||
auto *arr = buff.arrayZ + offset;
|
|
||||||
/* Length is at least one; and mostly just one. */
|
|
||||||
arr[0] = str[0];
|
|
||||||
for (unsigned i = 1; i < length; i++)
|
|
||||||
arr[i] = str[i];
|
|
||||||
|
|
||||||
//hb_memcpy (buff.arrayZ + offset, str, length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_error () const { return buff.in_error (); }
|
bool in_error () const { return buff.in_error (); }
|
||||||
|
@ -716,7 +709,7 @@ struct subr_subsetter_t
|
||||||
|
|
||||||
remaps.create (closures);
|
remaps.create (closures);
|
||||||
|
|
||||||
populate_subset_accelerator();
|
populate_subset_accelerator ();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1017,10 +1010,52 @@ struct subr_subsetter_t
|
||||||
return !encoder.in_error ();
|
return !encoder.in_error ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void populate_subset_accelerator() const
|
void compact_parsed_strings () const
|
||||||
|
{
|
||||||
|
for (auto &cs : parsed_charstrings)
|
||||||
|
compact_string (cs);
|
||||||
|
for (auto &cs : parsed_global_subrs_storage)
|
||||||
|
compact_string (cs);
|
||||||
|
for (auto &vec : parsed_local_subrs_storage)
|
||||||
|
for (auto &cs : vec)
|
||||||
|
compact_string (cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void compact_string (parsed_cs_str_t &str)
|
||||||
|
{
|
||||||
|
unsigned count = str.values.length;
|
||||||
|
if (unlikely (!count)) return;
|
||||||
|
auto &opstr = str.values.arrayZ;
|
||||||
|
unsigned j = 0;
|
||||||
|
for (unsigned i = 1; i < count; i++)
|
||||||
|
{
|
||||||
|
/* See if we can combine op j and op i. */
|
||||||
|
bool combine =
|
||||||
|
(opstr[j].op != OpCode_callsubr && opstr[j].op != OpCode_callgsubr) &&
|
||||||
|
(opstr[i].op != OpCode_callsubr && opstr[i].op != OpCode_callgsubr) &&
|
||||||
|
(opstr[j].is_hinting () == opstr[i].is_hinting ()) &&
|
||||||
|
(opstr[j].ptr + opstr[j].length == opstr[i].ptr) &&
|
||||||
|
(opstr[j].length + opstr[i].length <= 255);
|
||||||
|
|
||||||
|
if (combine)
|
||||||
|
{
|
||||||
|
opstr[j].length += opstr[i].length;
|
||||||
|
opstr[j].op = OpCode_Invalid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
opstr[++j] = opstr[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
str.values.shrink (j + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void populate_subset_accelerator () const
|
||||||
{
|
{
|
||||||
if (!plan->inprogress_accelerator) return;
|
if (!plan->inprogress_accelerator) return;
|
||||||
|
|
||||||
|
compact_parsed_strings ();
|
||||||
|
|
||||||
plan->inprogress_accelerator->cff_accelerator =
|
plan->inprogress_accelerator->cff_accelerator =
|
||||||
cff_subset_accelerator_t::create(acc.blob,
|
cff_subset_accelerator_t::create(acc.blob,
|
||||||
parsed_charstrings,
|
parsed_charstrings,
|
||||||
|
|
Loading…
Reference in New Issue