From 6c22f3fd95617a8c3cd558858c6758a0d548d370 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 12 Nov 2018 19:26:01 -0500 Subject: [PATCH] [shape-plan] Implement fine-grained caching plans with user-features Only tag, value, and global-ness of features are considered, not their start/end offsets. --- src/hb-shape-plan.cc | 69 +++++++++++++++++++++++++------------------- src/hb-shape-plan.hh | 17 ++--------- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index a4eacf50d..acb589ad3 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -66,7 +66,17 @@ hb_shape_plan_key_t::init (bool copy, this->num_user_features = num_user_features; this->user_features = copy ? features : user_features; if (copy && num_user_features) + { memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + /* Make start/end uniform to easier catch bugs. */ + for (unsigned int i = 0; i < num_user_features; i++) + { + if (features[0].start != HB_FEATURE_GLOBAL_START) + features[0].start = 1; + if (features[0].end != HB_FEATURE_GLOBAL_END) + features[0].end = 2; + } + } this->shaper_func = nullptr; this->shaper_name = nullptr; this->ot.init (face, coords, num_coords); @@ -115,6 +125,33 @@ bail: return false; } +bool +hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other) +{ + if (this->num_user_features != other->num_user_features) + return false; + for (unsigned int i = 0; i < num_user_features; i++) + { + if (this->user_features[i].tag != other->user_features[i].tag || + this->user_features[i].value != other->user_features[i].value || + (this->user_features[i].start == HB_FEATURE_GLOBAL_START && + this->user_features[i].end == HB_FEATURE_GLOBAL_END) != + (other->user_features[i].start == HB_FEATURE_GLOBAL_START && + other->user_features[i].end == HB_FEATURE_GLOBAL_END)) + return false; + } + return true; +} + +bool +hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other) +{ + return hb_segment_properties_equal (&this->props, &other->props) && + this->user_features_match (other) && + this->ot.equal (&other->ot) && + this->shaper_func == other->shaper_func; +} + /* * hb_shape_plan_t @@ -371,30 +408,6 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, * Caching */ -static inline bool -_has_non_global_user_features (const hb_feature_t *user_features, - unsigned int num_user_features) -{ - while (num_user_features) - { - if (user_features->start != HB_FEATURE_GLOBAL_START || - user_features->end != HB_FEATURE_GLOBAL_END) - return true; - num_user_features--; - user_features++; - } - return false; -} - -static inline bool -_dont_cache (const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords) -{ - return _has_non_global_user_features (user_features, num_user_features); -} - /** * hb_shape_plan_create_cached: * @face: @@ -440,11 +453,9 @@ hb_shape_plan_create_cached2 (hb_face_t *face, retry: hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans; - bool dont_cache = _dont_cache (user_features, num_user_features, - coords, num_coords) || - hb_object_is_inert (face); + bool dont_cache = hb_object_is_inert (face); - if (!dont_cache) + if (likely (!dont_cache)) { hb_shape_plan_key_t key; if (!key.init (false, @@ -470,7 +481,7 @@ retry: coords, num_coords, shaper_list); - if (dont_cache) + if (unlikely (dont_cache)) return shape_plan; hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh index 739427b2a..c69d45075 100644 --- a/src/hb-shape-plan.hh +++ b/src/hb-shape-plan.hh @@ -58,22 +58,9 @@ struct hb_shape_plan_key_t ::free ((void *) user_features); } - inline bool user_features_match (const hb_shape_plan_key_t *other) - { - /* TODO Implement non-exact matching. */ - if (this->num_user_features != other->num_user_features) - return false; - return 0 == hb_memcmp(this->user_features, other->user_features, - this->num_user_features * sizeof (this->user_features[0])); - } + HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other); - inline bool equal (const hb_shape_plan_key_t *other) - { - return hb_segment_properties_equal (&this->props, &other->props) && - this->user_features_match (other) && - this->ot.equal (&other->ot) && - this->shaper_func == other->shaper_func; - } + HB_INTERNAL bool equal (const hb_shape_plan_key_t *other); }; struct hb_shape_plan_t