[instance] store active featurevariation record/condition idxes in the plan

This commit is contained in:
Qunxin Liu 2022-09-09 09:36:19 -07:00 committed by Garret Rieger
parent 0a6c16a313
commit 64e2f2fc58
4 changed files with 178 additions and 3 deletions

View File

@ -94,6 +94,19 @@ static bool ClassDef_remap_and_serialize (
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
hb_map_t *klass_map /*IN/OUT*/);
struct hb_collect_feature_substitutes_with_var_context_t
{
const hb_map_t *axes_index_tag_map;
const hb_hashmap_t<hb_tag_t, int> *axes_location;
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
// not stored in subset_plan
hb_set_t *feature_indices;
bool apply;
unsigned cur_record_idx;
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
};
struct hb_prune_langsys_context_t
{
@ -2692,6 +2705,13 @@ struct VariationStore
/*
* Feature Variations
*/
enum Cond_with_Var_flag_t
{
KEEP_COND_WITH_VAR = 0,
DROP_COND_WITH_VAR = 1,
DROP_RECORD_WITH_VAR = 2,
MEM_ERR_WITH_VAR = 3,
};
struct ConditionFormat1
{
@ -2706,6 +2726,40 @@ struct ConditionFormat1
}
private:
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
hb_map_t *condition_map /* OUT */) const
{
//invalid axis index, drop the entire record
if (!c->axes_index_tag_map->has (axisIndex))
return DROP_RECORD_WITH_VAR;
hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
//axis not pinned, keep the condition
if (!c->axes_location->has (axis_tag))
{
// add axisIndex->value into the hashmap so we can check if the record is
// unique with variations
int16_t min_val = filterRangeMinValue;
int16_t max_val = filterRangeMaxValue;
hb_codepoint_t val = (max_val << 16) + min_val;
condition_map->set (axisIndex, val);
return KEEP_COND_WITH_VAR;
}
//axis pinned, check if condition is met
//TODO: add check for axis Ranges
int v = c->axes_location->get (axis_tag);
//condition not met, drop the entire record
if (v < filterRangeMinValue || v > filterRangeMaxValue)
return DROP_RECORD_WITH_VAR;
//axis pinned and condition met, drop the condition
return DROP_COND_WITH_VAR;
}
bool evaluate (const int *coords, unsigned int coord_len) const
{
int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
@ -2737,6 +2791,15 @@ struct Condition
}
}
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
hb_map_t *condition_map /* OUT */) const
{
switch (u.format) {
case 1: return u.format1.keep_with_variations (c, condition_map);
default:return KEEP_COND_WITH_VAR;
}
}
template <typename context_t, typename ...Ts>
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
{
@ -2778,6 +2841,47 @@ struct ConditionSet
return true;
}
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
{
hb_map_t *condition_map = hb_map_create ();
if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
hb::shared_ptr<hb_map_t> p {condition_map};
hb_set_t *cond_set = hb_set_create ();
if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
hb::shared_ptr<hb_set_t> s {cond_set};
unsigned num_kept_cond = 0, cond_idx = 0;
for (const auto& offset : conditions)
{
Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
// one condition is not met, drop the entire record
if (ret == DROP_RECORD_WITH_VAR)
return DROP_RECORD_WITH_VAR;
// axis not pinned, keep this condition
if (ret == KEEP_COND_WITH_VAR)
{
cond_set->add (cond_idx);
num_kept_cond++;
}
cond_idx++;
}
// all conditions met
if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
//check if condition_set is unique with variations
if (c->conditionset_map->has (p))
//duplicate found, drop the entire record
return DROP_RECORD_WITH_VAR;
c->conditionset_map->set (p, 1);
c->record_cond_idx_map->set (c->cur_record_idx, s);
return KEEP_COND_WITH_VAR;
}
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
@ -2820,6 +2924,14 @@ struct FeatureTableSubstitutionRecord
feature_indexes->add (featureIndex);
}
void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
const hb_set_t *feature_indices,
const void *base) const
{
if (feature_indices->has (featureIndex))
feature_substitutes_map->set (featureIndex, &(base+feature));
}
bool subset (hb_subset_layout_context_t *c, const void *base) const
{
TRACE_SUBSET (this);
@ -2890,6 +3002,12 @@ struct FeatureTableSubstitution
return false;
}
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
{
for (const FeatureTableSubstitutionRecord& record : substitutions)
record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
}
bool subset (hb_subset_context_t *c,
hb_subset_layout_context_t *l) const
{
@ -2946,6 +3064,18 @@ struct FeatureVariationRecord
return (base+substitutions).intersects_features (feature_index_map);
}
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
const void *base) const
{
// ret == 1, all conditions met
if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
c->apply)
{
(base+substitutions).collect_feature_substitutes_with_variations (c);
c->apply = false; // set variations only once
}
}
bool subset (hb_subset_layout_context_t *c, const void *base) const
{
TRACE_SUBSET (this);
@ -3002,6 +3132,16 @@ struct FeatureVariations
return (this+record.substitutions).find_substitute (feature_index);
}
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
{
unsigned int count = varRecords.len;
for (unsigned int i = 0; i < count; i++)
{
c->cur_record_idx = i;
varRecords[i].collect_feature_substitutes_with_variations (c, this);
}
}
FeatureVariations* copy (hb_serialize_context_t *c) const
{
TRACE_SERIALIZE (this);

View File

@ -4243,6 +4243,11 @@ struct GSUBGPOS
#endif
}
#ifndef HB_NO_VAR
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
{ get_feature_variations ().collect_feature_substitutes_with_variations (c); }
#endif
template <typename TLookup>
void closure_lookups (hb_face_t *face,
const hb_set_t *glyphs,

View File

@ -237,7 +237,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
hb_set_t *gids_to_retain,
hb_map_t *lookups,
hb_map_t *features,
script_langsys_map *langsys_map)
script_langsys_map *langsys_map,
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *feature_record_cond_idx_map,
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
{
hb_blob_ptr_t<T> table = plan->source_table<T> ();
hb_tag_t table_tag = table->tableTag;
@ -528,7 +530,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
plan->_glyphset_gsub,
plan->gsub_lookups,
plan->gsub_features,
plan->gsub_langsys);
plan->gsub_langsys,
plan->gsub_feature_record_cond_idx_map,
plan->gsub_feature_substitutes_map);
if (!drop_tables->has (HB_OT_TAG_GPOS))
_closure_glyphs_lookups_features<GPOS> (
@ -536,7 +540,9 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
plan->_glyphset_gsub,
plan->gpos_lookups,
plan->gpos_features,
plan->gpos_langsys);
plan->gpos_langsys,
plan->gpos_feature_record_cond_idx_map,
plan->gpos_feature_substitutes_map);
#endif
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
@ -749,6 +755,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
plan->gsub_features = hb_map_create ();
plan->gpos_features = hb_map_create ();
plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::unique_ptr<hb_set_t>> ());
plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
plan->colrv1_layers = hb_map_create ();
plan->colr_palettes = hb_map_create ();
plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());

View File

@ -36,6 +36,10 @@
#include "hb-bimap.hh"
#include "hb-set.hh"
namespace OT {
struct Feature;
}
struct hb_subset_plan_t
{
hb_subset_plan_t ()
@ -72,6 +76,10 @@ struct hb_subset_plan_t
hb_hashmap_destroy (gsub_langsys);
hb_hashmap_destroy (gpos_langsys);
hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
hb_hashmap_destroy (gsub_feature_substitutes_map);
hb_hashmap_destroy (gpos_feature_substitutes_map);
hb_hashmap_destroy (axes_location);
hb_hashmap_destroy (sanitized_table_cache);
hb_hashmap_destroy (hmtx_map);
@ -145,6 +153,15 @@ struct hb_subset_plan_t
hb_map_t *gsub_features;
hb_map_t *gpos_features;
//active feature variation records/condition index with variations
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
//feature index-> address of substituation feature table mapping with
//variations
hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
//active layers/palettes we'd like to retain
hb_map_t *colrv1_layers;
hb_map_t *colr_palettes;