[instance] store active featurevariation record/condition idxes in the plan
This commit is contained in:
parent
0a6c16a313
commit
64e2f2fc58
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>> ());
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue