// If face has 0 tables associated with it, assume that it was built from // hb_face_create_tables and thus is unable to list its tables. Fallback to // checking each table type we can handle for existence instead. auto it =
hb_concat (
+ hb_array (known_tables)
| hb_filter ([&] (hb_tag_t tag) { return !_table_is_empty (plan->source, tag) && !plan->no_subset_tables.has (tag);
})
| hb_map ([] (hb_tag_t tag) -> hb_tag_t { return tag; }),
if (!hb_face_get_table_tags (source, 0, nullptr, nullptr)) { // If face has 0 tables associated with it, assume that it was built from // hb_face_create_tables and thus is unable to list its tables. Fallback to // checking if the blob associated with tag is empty. return !_table_is_empty (source, tag);
}
hb_tag_t table_tags[32]; unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags); while (((void) hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
{ for (unsigned i = 0; i < num_tables; ++i) if (table_tags[i] == tag) returntrue;
offset += num_tables;
} returnfalse;
}
switch (tag)
{ case HB_TAG('c','v','a','r'): /* hint table, fallthrough */ return plan->all_axes_pinned || (plan->flags & HB_SUBSET_FLAGS_NO_HINTING);
case HB_TAG('c','v','t',' '): /* hint table, fallthrough */ case HB_TAG('f','p','g','m'): /* hint table, fallthrough */ case HB_TAG('p','r','e','p'): /* hint table, fallthrough */ case HB_TAG('h','d','m','x'): /* hint table, fallthrough */ case HB_TAG('V','D','M','X'): /* hint table, fallthrough */ return plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
#ifdef HB_NO_SUBSET_LAYOUT // Drop Layout Tables if requested. case HB_TAG('G','D','E','F'): case HB_TAG('G','P','O','S'): case HB_TAG('G','S','U','B'): case HB_TAG('m','o','r','x'): case HB_TAG('m','o','r','t'): case HB_TAG('k','e','r','x'): case HB_TAG('k','e','r','n'): returntrue; #endif
case HB_TAG('a','v','a','r'): case HB_TAG('f','v','a','r'): case HB_TAG('g','v','a','r'): case HB_TAG('H','V','A','R'): case HB_TAG('V','V','A','R'): case HB_TAG('M','V','A','R'): return plan->all_axes_pinned;
default: returnfalse;
}
}
staticbool
_dependencies_satisfied (hb_subset_plan_t *plan, hb_tag_t tag, const hb_set_t &subsetted_tags, const hb_set_t &pending_subset_tags)
{ switch (tag)
{ case HB_TAG('h','m','t','x'): case HB_TAG('v','m','t','x'): case HB_TAG('m','a','x','p'): case HB_TAG('O','S','/','2'): return !plan->normalized_coords || !pending_subset_tags.has (HB_TAG('g','l','y','f')); case HB_TAG('G','P','O','S'): return plan->all_axes_pinned || !pending_subset_tags.has (HB_TAG('G','D','E','F')); default: returntrue;
}
}
if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) return _hb_subset_table_passthrough (plan, tag);
// Drop table returntrue;
}
staticvoid _attach_accelerator_data (hb_subset_plan_t* plan,
hb_face_t* face /* IN/OUT */)
{ if (!plan->inprogress_accelerator) return;
// Transfer the accelerator from the plan to us.
hb_subset_accelerator_t* accel = plan->inprogress_accelerator;
plan->inprogress_accelerator = nullptr;
if (accel->in_error ())
{
hb_subset_accelerator_t::destroy (accel); return;
}
// Populate caches that need access to the final tables.
hb_blob_ptr_t<OT::cmap> cmap_ptr (hb_sanitize_context_t ().reference_table<OT::cmap> (face));
accel->cmap_cache = OT::cmap::create_filled_cache (cmap_ptr);
accel->destroy_cmap_cache = OT::SubtableUnicodesCache::destroy;
if (!hb_face_set_user_data(face,
hb_subset_accelerator_t::user_data_key(),
accel,
hb_subset_accelerator_t::destroy, true))
hb_subset_accelerator_t::destroy (accel);
}
hb_set_t subsetted_tags, pending_subset_tags; while (((void) _get_table_tags (plan, offset, &num_tables, table_tags), num_tables))
{ for (unsigned i = 0; i < num_tables; ++i)
{
hb_tag_t tag = table_tags[i]; if (_should_drop_table (plan, tag)) continue;
pending_subset_tags.add (tag);
}
offset += num_tables;
}
bool success = true;
{ // Grouping to deallocate buf before calling hb_face_reference (plan->dest).
hb_vector_t<char> buf;
buf.alloc (8192 - 16);
while (!pending_subset_tags.is_empty ())
{ if (subsetted_tags.in_error ()
|| pending_subset_tags.in_error ()) {
success = false; goto end;
}
bool made_changes = false; for (hb_tag_t tag : pending_subset_tags)
{ if (!_dependencies_satisfied (plan, tag,
subsetted_tags,
pending_subset_tags))
{ // delayed subsetting for some tables since they might have dependency on other tables // in some cases: e.g: during instantiating glyf tables, hmetrics/vmetrics are updated // and saved in subset plan, hmtx/vmtx subsetting need to use these updated metrics values continue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.