[subset] also include no subset tables when guessing which tables are present.

This commit is contained in:
Garret Rieger 2022-05-25 21:49:12 +00:00
parent 9564d98739
commit 3472f73b79
2 changed files with 57 additions and 56 deletions

View File

@ -78,10 +78,24 @@ using OT::Layout::GSUB::GSUB;
* retain glyph ids option and configure the subset to pass through the layout tables untouched. * retain glyph ids option and configure the subset to pass through the layout tables untouched.
*/ */
/* static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag)
{
hb_blob_t* blob = hb_face_reference_table (face, tag);
bool result = (blob == hb_blob_get_empty ());
hb_blob_destroy (blob);
return result;
}
static unsigned int
_get_table_tags (const hb_subset_plan_t* plan,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */)
{
/*
* The list of tables that the subsetter can perform subsetting for. * The list of tables that the subsetter can perform subsetting for.
*/ */
static hb_tag_t handled_tables[] { static hb_set_t handled_tables {
HB_OT_TAG_glyf, HB_OT_TAG_glyf,
HB_OT_TAG_hdmx, HB_OT_TAG_hdmx,
HB_OT_TAG_name, HB_OT_TAG_name,
@ -110,50 +124,35 @@ static hb_tag_t handled_tables[] {
HB_OT_TAG_gvar, HB_OT_TAG_gvar,
HB_OT_TAG_HVAR, HB_OT_TAG_HVAR,
HB_OT_TAG_VVAR HB_OT_TAG_VVAR
}; };
static bool _table_is_empty (const hb_face_t *face, hb_tag_t tag) unsigned num_tables = hb_face_get_table_tags (plan->source, 0, nullptr, nullptr);
{
hb_blob_t* blob = hb_face_reference_table (face, tag);
bool result = (blob == hb_blob_get_empty ());
hb_blob_destroy (blob);
return result;
}
static unsigned int
_get_table_tags (const hb_face_t *face,
unsigned int start_offset,
unsigned int *table_count, /* IN/OUT */
hb_tag_t *table_tags /* OUT */)
{
unsigned num_tables = hb_face_get_table_tags (face, 0, nullptr, nullptr);
if (num_tables) if (num_tables)
return hb_face_get_table_tags (face, start_offset, table_count, table_tags); return hb_face_get_table_tags (plan->source, start_offset, table_count, table_tags);
// If face has 0 tables associated with it, assume that it has built from // If face has 0 tables associated with it, assume that it has built from
// hb_face_create_tables and thus is unable to list its tables. Fallback to // hb_face_create_tables and thus is unable to list its tables. Fallback to
// checking each table type we can handle for existence instead. // checking each table type we can handle for existence instead.
auto it = hb_array_t<hb_tag_t> (handled_tables); auto it =
hb_concat (
+ handled_tables.iter ()
| hb_filter ([&] (hb_tag_t tag) {
return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables->has (tag);
}),
while (bool (it) && start_offset > 0) plan->no_subset_tables->iter ()
{ | hb_filter([&] (hb_tag_t tag) {
if (!_table_is_empty (face, *it)) return !_table_is_empty (plan->source, tag);
start_offset--; }));
it++; it += start_offset;
}
unsigned num_written = 0; unsigned num_written = 0;
while (bool (it) && num_written < *table_count) while (bool (it) && num_written < *table_count)
{ table_tags[num_written++] = *it++;
if (!_table_is_empty (face, *it))
table_tags[num_written++] = *it;
it++;
}
*table_count = num_written; *table_count = num_written;
return 0; return num_written;
} }
@ -301,11 +300,11 @@ _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
} }
static bool static bool
_is_table_present (hb_face_t *source, hb_tag_t tag) _is_table_present (hb_subset_plan_t *plan, hb_tag_t tag)
{ {
hb_tag_t table_tags[32]; hb_tag_t table_tags[32];
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
while ((_get_table_tags (source, offset, &num_tables, table_tags), num_tables)) while ((_get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{ {
for (unsigned i = 0; i < num_tables; ++i) for (unsigned i = 0; i < num_tables; ++i)
if (table_tags[i] == tag) if (table_tags[i] == tag)
@ -373,7 +372,7 @@ _subset_table (hb_subset_plan_t *plan,
case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf); case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan, buf);
case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf); case HB_OT_TAG_name: return _subset<const OT::name> (plan, buf);
case HB_OT_TAG_head: case HB_OT_TAG_head:
if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf)) if (_is_table_present (plan, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
return true; /* skip head, handled by glyf */ return true; /* skip head, handled by glyf */
return _subset<const OT::head> (plan, buf); return _subset<const OT::head> (plan, buf);
case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */ case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
@ -467,7 +466,8 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
hb_vector_t<char> buf; hb_vector_t<char> buf;
buf.alloc (4096 - 16); buf.alloc (4096 - 16);
while ((_get_table_tags (plan->source, offset, &num_tables, table_tags), num_tables))
while ((_get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{ {
for (unsigned i = 0; i < num_tables; ++i) for (unsigned i = 0; i < num_tables; ++i)
{ {
@ -479,7 +479,7 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
} }
offset += num_tables; offset += num_tables;
} }
end:
end:
return success ? hb_face_reference (plan->dest) : nullptr; return success ? hb_face_reference (plan->dest) : nullptr;
} }

View File

@ -220,6 +220,7 @@ test_subset_create_for_tables_face (void)
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a')); hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f')); hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','a','s','p'));
hb_subset_input_destroy (input); hb_subset_input_destroy (input);
hb_face_destroy (face_abc_subset); hb_face_destroy (face_abc_subset);