[subset] use inverted set for all unicodes.

Modify the code that handles input->unicodes to be safe with possibly inverted sets. Also adds --unicodes-= and --unicodes+= flags.
This commit is contained in:
Garret Rieger 2021-08-25 13:34:05 -07:00
parent e9e6d66cd6
commit 8f4f47df7c
2 changed files with 39 additions and 21 deletions

View File

@ -240,7 +240,12 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
{ {
OT::cmap::accelerator_t cmap; OT::cmap::accelerator_t cmap;
cmap.init (plan->source); cmap.init (plan->source);
constexpr static const int size_threshold = 65000;
if (unicodes->get_population () < size_threshold && glyphs->is_empty ())
{
// This is the fast path if it's anticipated that size of unicodes
// is << then the number of codepoints in the font.
for (hb_codepoint_t cp : *unicodes) for (hb_codepoint_t cp : *unicodes)
{ {
hb_codepoint_t gid; hb_codepoint_t gid;
@ -253,9 +258,6 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
plan->codepoint_to_glyph->set (cp, gid); plan->codepoint_to_glyph->set (cp, gid);
plan->_glyphset_gsub->add (gid); plan->_glyphset_gsub->add (gid);
} }
if (glyphs->is_empty ())
{
cmap.fini (); cmap.fini ();
return; return;
} }
@ -265,17 +267,27 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
cmap.fini (); cmap.fini ();
for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid : for (hb_pair_t<hb_codepoint_t, hb_codepoint_t> cp_gid :
+ unicode_glyphid_map.iter () | hb_filter (glyphs, hb_second)) + unicode_glyphid_map.iter ())
{ {
if (!unicodes->has (cp_gid.first) && !glyphs->has (cp_gid.second))
continue;
plan->unicodes->add (cp_gid.first); plan->unicodes->add (cp_gid.first);
plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second); plan->codepoint_to_glyph->set (cp_gid.first, cp_gid.second);
plan->_glyphset_gsub->add (cp_gid.second);
}
// Add gids which where requested, but not mapped in cmap
for (hb_codepoint_t gid : glyphs->iter ())
{
if (gid >= plan->source->get_num_glyphs ())
break;
plan->_glyphset_gsub->add (gid);
} }
} }
static void static void
_populate_gids_to_retain (hb_subset_plan_t* plan, _populate_gids_to_retain (hb_subset_plan_t* plan,
const hb_set_t *unicodes,
const hb_set_t *input_glyphs_to_retain,
bool close_over_gsub, bool close_over_gsub,
bool close_over_gpos, bool close_over_gpos,
bool close_over_gdef) bool close_over_gdef)
@ -292,7 +304,6 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
colr.init (plan->source); colr.init (plan->source);
plan->_glyphset_gsub->add (0); // Not-def plan->_glyphset_gsub->add (0); // Not-def
hb_set_union (plan->_glyphset_gsub, input_glyphs_to_retain);
_cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub); _cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
@ -477,8 +488,6 @@ hb_subset_plan_create (hb_face_t *face,
_populate_unicodes_to_retain (input->unicodes, input->glyphs, plan); _populate_unicodes_to_retain (input->unicodes, input->glyphs, plan);
_populate_gids_to_retain (plan, _populate_gids_to_retain (plan,
input->unicodes,
input->glyphs,
!input->drop_tables->has (HB_OT_TAG_GSUB), !input->drop_tables->has (HB_OT_TAG_GSUB),
!input->drop_tables->has (HB_OT_TAG_GPOS), !input->drop_tables->has (HB_OT_TAG_GPOS),
!input->drop_tables->has (HB_OT_TAG_GDEF)); !input->drop_tables->has (HB_OT_TAG_GDEF));

View File

@ -265,20 +265,26 @@ parse_text (const char *name G_GNUC_UNUSED,
GError **error G_GNUC_UNUSED) GError **error G_GNUC_UNUSED)
{ {
subset_main_t *subset_main = (subset_main_t *) data; subset_main_t *subset_main = (subset_main_t *) data;
hb_bool_t is_remove = (name[strlen (name) - 1] == '-');
hb_set_t *unicodes = hb_subset_input_unicode_set (subset_main->input);
if (0 == strcmp (arg, "*")) if (0 == strcmp (arg, "*"))
{ {
subset_main->add_all_unicodes (); hb_set_clear (unicodes);
if (!is_remove)
hb_set_invert (unicodes);
return true; return true;
} }
hb_set_t *unicodes = hb_subset_input_unicode_set (subset_main->input);
for (gchar *c = (gchar *) arg; for (gchar *c = (gchar *) arg;
*c; *c;
c = g_utf8_find_next_char(c, nullptr)) c = g_utf8_find_next_char(c, nullptr))
{ {
gunichar cp = g_utf8_get_char(c); gunichar cp = g_utf8_get_char(c);
if (!is_remove)
hb_set_add (unicodes, cp); hb_set_add (unicodes, cp);
else
hb_set_del (unicodes, cp);
} }
return true; return true;
} }
@ -674,6 +680,9 @@ subset_main_t::add_options ()
{"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Specify text to include in the subset", "string"}, {"text", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_text, "Specify text to include in the subset", "string"},
{"text-file", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_text, false>,"Specify file to read text from", "filename"}, {"text-file", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_text, false>,"Specify file to read text from", "filename"},
{"unicodes", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Specify Unicode codepoints or ranges to include in the subset", "list of hex numbers/ranges"}, {"unicodes", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Specify Unicode codepoints or ranges to include in the subset", "list of hex numbers/ranges"},
{"unicodes-", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Specify Unicode codepoints or ranges to include in the subset", "list of hex numbers/ranges"},
{"unicodes+", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_unicodes, "Specify Unicode codepoints or ranges to include in the subset", "list of hex numbers/ranges"},
{"unicodes-file", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_unicodes>,"Specify file to read Unicode codepoints or ranges from", "filename"}, {"unicodes-file", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_file_for<parse_unicodes>,"Specify file to read Unicode codepoints or ranges from", "filename"},
{nullptr} {nullptr}
}; };