[subset] cache sanitized tables in subset plan to avoid sanitizing tables multiple times.

This commit is contained in:
Garret Rieger 2022-07-07 20:16:16 +00:00
parent 8b349e1139
commit 29f149c16c
3 changed files with 54 additions and 22 deletions

View File

@ -164,7 +164,7 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_map_t *features, hb_map_t *features,
script_langsys_map *langsys_map) script_langsys_map *langsys_map)
{ {
hb_blob_ptr_t<T> table = hb_sanitize_context_t ().reference_table<T> (plan->source); hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag; hb_tag_t table_tag = table->tableTag;
hb_set_t lookup_indices; hb_set_t lookup_indices;
_collect_layout_indices<T> (plan, _collect_layout_indices<T> (plan,
@ -203,14 +203,14 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
#ifndef HB_NO_VAR #ifndef HB_NO_VAR
static inline void static inline void
_collect_layout_variation_indices (hb_face_t *face, _collect_layout_variation_indices (hb_subset_plan_t* plan,
const hb_set_t *glyphset, const hb_set_t *glyphset,
const hb_map_t *gpos_lookups, const hb_map_t *gpos_lookups,
hb_set_t *layout_variation_indices, hb_set_t *layout_variation_indices,
hb_map_t *layout_variation_idx_map) hb_map_t *layout_variation_idx_map)
{ {
hb_blob_ptr_t<OT::GDEF> gdef = hb_sanitize_context_t ().reference_table<OT::GDEF> (face); hb_blob_ptr_t<OT::GDEF> gdef = plan->source_table<OT::GDEF> ();
hb_blob_ptr_t<GPOS> gpos = hb_sanitize_context_t ().reference_table<GPOS> (face); hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
if (!gdef->has_data ()) if (!gdef->has_data ())
{ {
@ -221,7 +221,7 @@ static inline void
OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups); OT::hb_collect_variation_indices_context_t c (layout_variation_indices, glyphset, gpos_lookups);
gdef->collect_variation_indices (&c); gdef->collect_variation_indices (&c);
if (hb_ot_layout_has_positioning (face)) if (hb_ot_layout_has_positioning (plan->source))
gpos->collect_variation_indices (&c); gpos->collect_variation_indices (&c);
gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map); gdef->remap_layout_variation_indices (layout_variation_indices, layout_variation_idx_map);
@ -271,10 +271,10 @@ static void _colr_closure (hb_face_t *face,
} }
static inline void static inline void
_math_closure (hb_face_t *face, _math_closure (hb_subset_plan_t *plan,
hb_set_t *glyphset) hb_set_t *glyphset)
{ {
hb_blob_ptr_t<OT::MATH> math = hb_sanitize_context_t ().reference_table<OT::MATH> (face); hb_blob_ptr_t<OT::MATH> math = plan->source_table<OT::MATH> ();
if (math->has_data ()) if (math->has_data ())
math->closure_glyphs (glyphset); math->closure_glyphs (glyphset);
math.destroy (); math.destroy ();
@ -418,7 +418,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ()); _remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub); hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
_math_closure (plan->source, plan->_glyphset_mathed); _math_closure (plan, plan->_glyphset_mathed);
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ()); _remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
hb_set_t cur_glyphset = *plan->_glyphset_mathed; hb_set_t cur_glyphset = *plan->_glyphset_mathed;
@ -446,7 +446,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
#ifndef HB_NO_VAR #ifndef HB_NO_VAR
if (close_over_gdef) if (close_over_gdef)
_collect_layout_variation_indices (plan->source, _collect_layout_variation_indices (plan,
plan->_glyphset_gsub, plan->_glyphset_gsub,
plan->gpos_lookups, plan->gpos_lookups,
plan->layout_variation_indices, plan->layout_variation_indices,
@ -583,6 +583,11 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->layout_variation_indices = hb_set_create (); plan->layout_variation_indices = hb_set_create ();
plan->layout_variation_idx_map = hb_map_create (); plan->layout_variation_idx_map = hb_map_create ();
if ((plan->sanitized_table_cache = hb_object_create<hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>> ())) {
plan->sanitized_table_cache->init_shallow ();
}
if (unlikely (plan->in_error ())) { if (unlikely (plan->in_error ())) {
hb_subset_plan_destroy (plan); hb_subset_plan_destroy (plan);
return nullptr; return nullptr;
@ -678,6 +683,12 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
hb_free (plan->gpos_langsys); hb_free (plan->gpos_langsys);
} }
if (plan->sanitized_table_cache) {
hb_object_destroy (plan->sanitized_table_cache);
plan->sanitized_table_cache->fini ();
hb_free (plan->sanitized_table_cache);
}
hb_free (plan); hb_free (plan);
} }

View File

@ -106,8 +106,29 @@ struct hb_subset_plan_t
//Old -> New layout item variation store delta set index mapping //Old -> New layout item variation store delta set index mapping
hb_map_t *layout_variation_idx_map; hb_map_t *layout_variation_idx_map;
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
public: public:
template<typename T>
hb_blob_ptr_t<T> source_table()
{
if (sanitized_table_cache
&& !sanitized_table_cache->in_error ()
&& sanitized_table_cache->has (T::tableTag)) {
return hb_blob_reference (sanitized_table_cache->get (T::tableTag).get ());
}
hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (source)};
hb_blob_t* ret = hb_blob_reference (table_blob.get ());
if (likely (sanitized_table_cache))
sanitized_table_cache->set (T::tableTag,
std::move (table_blob));
return ret;
}
bool in_error () const { return !successful; } bool in_error () const { return !successful; }
bool check_success(bool success) bool check_success(bool success)

View File

@ -260,15 +260,15 @@ template<typename TableType>
static bool static bool
_subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf) _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
{ {
hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source); hb_blob_ptr_t<TableType> source_blob = plan->source_table<TableType> ();
const TableType *table = source_blob->as<TableType> (); const TableType *table = source_blob.get ();
hb_tag_t tag = TableType::tableTag; hb_tag_t tag = TableType::tableTag;
if (!source_blob->data) if (!source_blob.get_blob()->data)
{ {
DEBUG_MSG (SUBSET, nullptr, DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag)); "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
hb_blob_destroy (source_blob); source_blob.destroy ();
return false; return false;
} }
@ -278,23 +278,23 @@ _subset (hb_subset_plan_t *plan, hb_vector_t<char> &buf)
TableType::tableTag == HB_OT_TAG_GPOS || TableType::tableTag == HB_OT_TAG_GPOS ||
TableType::tableTag == HB_OT_TAG_name; TableType::tableTag == HB_OT_TAG_name;
unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length, same_size_table); unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob.get_length (), same_size_table);
DEBUG_MSG (SUBSET, nullptr, DEBUG_MSG (SUBSET, nullptr,
"OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size); "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
if (unlikely (!buf.alloc (buf_size))) if (unlikely (!buf.alloc (buf_size)))
{ {
DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size); DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
hb_blob_destroy (source_blob); source_blob.destroy ();
return false; return false;
} }
bool needed = false; bool needed = false;
hb_serialize_context_t serializer (buf.arrayZ, buf.allocated); hb_serialize_context_t serializer (buf.arrayZ, buf.allocated);
{ {
hb_subset_context_t c (source_blob, plan, &serializer, tag); hb_subset_context_t c (source_blob.get_blob (), plan, &serializer, tag);
needed = _try_subset (table, &buf, &c); needed = _try_subset (table, &buf, &c);
} }
hb_blob_destroy (source_blob); source_blob.destroy ();
if (serializer.in_error () && !serializer.only_offset_overflow ()) if (serializer.in_error () && !serializer.only_offset_overflow ())
{ {