diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 507581bd7..e857dfae0 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -288,7 +288,9 @@ struct hb_coretext_shaper_shape_plan_data_t {}; hb_coretext_shaper_shape_plan_data_t * _hb_coretext_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } @@ -1280,7 +1282,9 @@ struct hb_coretext_aat_shaper_shape_plan_data_t {}; hb_coretext_aat_shaper_shape_plan_data_t * _hb_coretext_aat_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_coretext_aat_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-directwrite.cc b/src/hb-directwrite.cc index 76482acd3..d26b29851 100644 --- a/src/hb-directwrite.cc +++ b/src/hb-directwrite.cc @@ -258,8 +258,10 @@ struct hb_directwrite_shaper_shape_plan_data_t {}; hb_directwrite_shaper_shape_plan_data_t * _hb_directwrite_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, - const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + const hb_feature_t *user_features HB_UNUSED, + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_directwrite_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-fallback-shape.cc b/src/hb-fallback-shape.cc index e2ad24001..ac6d4b00f 100644 --- a/src/hb-fallback-shape.cc +++ b/src/hb-fallback-shape.cc @@ -73,7 +73,9 @@ struct hb_fallback_shaper_shape_plan_data_t {}; hb_fallback_shaper_shape_plan_data_t * _hb_fallback_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_fallback_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-font.cc b/src/hb-font.cc index f12dfb5d3..2935c4b4f 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -1253,8 +1253,7 @@ hb_font_destroy (hb_font_t *font) hb_face_destroy (font->face); hb_font_funcs_destroy (font->klass); - if (font->coords) - free (font->coords); + free (font->coords); free (font); } @@ -1561,8 +1560,7 @@ hb_font_set_var_coords_normalized (hb_font_t *font, if (unlikely (coords_length && !copy)) return; - if (font->coords) - free (font->coords); + free (font->coords); if (coords_length) memcpy (copy, coords, coords_length * sizeof (coords[0])); diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index c32318d27..a2d90db87 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -195,7 +195,9 @@ struct hb_graphite2_shaper_shape_plan_data_t {}; hb_graphite2_shaper_shape_plan_data_t * _hb_graphite2_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_graphite2_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; } diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index fc5ce6637..0395c9c22 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -176,7 +176,9 @@ struct hb_ot_map_builder_t inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (1, pause_func); } - HB_INTERNAL void compile (hb_ot_map_t &m); + HB_INTERNAL void compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords); inline void finish (void) { feature_infos.finish (); @@ -188,12 +190,13 @@ struct hb_ot_map_builder_t private: - HB_INTERNAL void add_lookups (hb_ot_map_t &m, - hb_face_t *face, - unsigned int table_index, - unsigned int feature_index, - hb_mask_t mask, - bool auto_zwj); + HB_INTERNAL void add_lookups (hb_ot_map_t &m, + hb_face_t *face, + unsigned int table_index, + unsigned int feature_index, + unsigned int variations_index, + hb_mask_t mask, + bool auto_zwj); struct feature_info_t { hb_tag_t tag; diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 9cd3a4472..9b331d521 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -83,6 +83,7 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, hb_face_t *face, unsigned int table_index, unsigned int feature_index, + unsigned int variations_index, hb_mask_t mask, bool auto_zwj) { @@ -95,11 +96,12 @@ hb_ot_map_builder_t::add_lookups (hb_ot_map_t &m, offset = 0; do { len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookups (face, - table_tags[table_index], - feature_index, - offset, &len, - lookup_indices); + hb_ot_layout_feature_with_variations_get_lookups (face, + table_tags[table_index], + feature_index, + variations_index, + offset, &len, + lookup_indices); for (unsigned int i = 0; i < len; i++) { @@ -130,7 +132,9 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus } void -hb_ot_map_builder_t::compile (hb_ot_map_t &m) +hb_ot_map_builder_t::compile (hb_ot_map_t &m, + const int *coords, + unsigned int num_coords) { m.global_mask = 1; @@ -264,6 +268,13 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) { /* Collect lookup indices for features */ + unsigned int variations_index; + hb_ot_layout_table_find_feature_variations (face, + table_tags[table_index], + coords, + num_coords, + &variations_index); + unsigned int stage_index = 0; unsigned int last_num_lookups = 0; for (unsigned stage = 0; stage < current_stage[table_index]; stage++) @@ -272,6 +283,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) required_feature_stage[table_index] == stage) add_lookups (m, face, table_index, required_feature_index[table_index], + variations_index, 1 /* mask */, true /* auto_zwj */); @@ -279,6 +291,7 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m) if (m.features[i].stage[table_index] == stage) add_lookups (m, face, table_index, m.features[i].index[table_index], + variations_index, m.features[i].mask, m.features[i].auto_zwj); diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh index 54ac2c3cf..594e54c02 100644 --- a/src/hb-ot-shape-private.hh +++ b/src/hb-ot-shape-private.hh @@ -77,11 +77,13 @@ struct hb_ot_shape_planner_t map (face, &props) {} ~hb_ot_shape_planner_t (void) { map.finish (); } - inline void compile (hb_ot_shape_plan_t &plan) + inline void compile (hb_ot_shape_plan_t &plan, + const int *coords, + unsigned int num_coords) { plan.props = props; plan.shaper = shaper; - map.compile (plan.map); + map.compile (plan.map, coords, num_coords); plan.rtlm_mask = plan.map.get_1_mask (HB_TAG ('r','t','l','m')); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 7811cb7f8..6c78b4752 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -163,7 +163,9 @@ _hb_ot_shaper_font_data_destroy (hb_ot_shaper_font_data_t *data) hb_ot_shaper_shape_plan_data_t * _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, - unsigned int num_user_features) + unsigned int num_user_features, + const int *coords, + unsigned int num_coords) { hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t)); if (unlikely (!plan)) @@ -173,9 +175,10 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan, planner.shaper = hb_ot_shape_complex_categorize (&planner); - hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features); + hb_ot_shape_collect_features (&planner, &shape_plan->props, + user_features, num_user_features); - planner.compile (*plan); + planner.compile (*plan, coords, num_coords); if (plan->shaper->data_create) { plan->data = plan->shaper->data_create (plan); diff --git a/src/hb-shape-plan-private.hh b/src/hb-shape-plan-private.hh index 607da5e77..aa0413a27 100644 --- a/src/hb-shape-plan-private.hh +++ b/src/hb-shape-plan-private.hh @@ -47,12 +47,17 @@ struct hb_shape_plan_t hb_feature_t *user_features; unsigned int num_user_features; + int *coords; + unsigned int num_coords; + struct hb_shaper_data_t shaper_data; }; #define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \ - , const hb_feature_t *user_features \ - , unsigned int num_user_features + , const hb_feature_t *user_features \ + , unsigned int num_user_features \ + , const int *coords \ + , unsigned int num_coords #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 87231fb33..600faaeb1 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -46,11 +46,14 @@ static void hb_shape_plan_plan (hb_shape_plan_t *shape_plan, const hb_feature_t *user_features, unsigned int num_user_features, + const int *coords, + unsigned int num_coords, const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d shaper_list=%p", + "num_features=%d num_coords=%d shaper_list=%p", num_user_features, + num_coords, shaper_list); const hb_shaper_pair_t *shapers = _hb_shapers_get (); @@ -59,7 +62,9 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, HB_STMT_START { \ if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) { \ HB_SHAPER_DATA (shaper, shape_plan) = \ - HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, user_features, num_user_features); \ + HB_SHAPER_DATA_CREATE_FUNC (shaper, shape_plan) (shape_plan, \ + user_features, num_user_features, \ + coords, num_coords); \ shape_plan->shaper_func = _hb_##shaper##_shape; \ shape_plan->shaper_name = #shaper; \ return; \ @@ -114,15 +119,32 @@ hb_shape_plan_create (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *orig_coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, - "face=%p num_features=%d shaper_list=%p", + "face=%p num_features=%d num_coords=%d shaper_list=%p", face, num_user_features, + num_coords, shaper_list); hb_shape_plan_t *shape_plan; hb_feature_t *features = NULL; + int *coords = NULL; if (unlikely (!face)) face = hb_face_get_empty (); @@ -130,7 +152,14 @@ hb_shape_plan_create (hb_face_t *face, return hb_shape_plan_get_empty (); if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) return hb_shape_plan_get_empty (); - if (!(shape_plan = hb_object_create ())) { + if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int)))) + { + free (features); + return hb_shape_plan_get_empty (); + } + if (!(shape_plan = hb_object_create ())) + { + free (coords); free (features); return hb_shape_plan_get_empty (); } @@ -145,8 +174,15 @@ hb_shape_plan_create (hb_face_t *face, shape_plan->user_features = features; if (num_user_features) memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + shape_plan->num_coords = num_coords; + shape_plan->coords = coords; + if (num_coords) + memcpy (coords, orig_coords, num_coords * sizeof (int)); - hb_shape_plan_plan (shape_plan, user_features, num_user_features, shaper_list); + hb_shape_plan_plan (shape_plan, + user_features, num_user_features, + coords, num_coords, + shaper_list); return shape_plan; } @@ -176,6 +212,9 @@ hb_shape_plan_get_empty (void) NULL, /* user_features */ 0, /* num_user_featurs */ + NULL, /* coords */ + 0, /* num_coords */ + { #define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_INVALID, #include "hb-shaper-list.hh" @@ -220,6 +259,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) #undef HB_SHAPER_IMPLEMENT free (shape_plan->user_features); + free (shape_plan->coords); free (shape_plan); } @@ -351,6 +391,8 @@ struct hb_shape_plan_proposal_t const char * const *shaper_list; const hb_feature_t *user_features; unsigned int num_user_features; + const int *coords; + unsigned int num_coords; hb_shape_func_t *shaper_func; }; @@ -358,12 +400,26 @@ static inline hb_bool_t hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, const hb_shape_plan_proposal_t *proposal) { - if (proposal->num_user_features != shape_plan->num_user_features) return false; + if (proposal->num_user_features != shape_plan->num_user_features) + return false; for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || proposal->user_features[i].value != shape_plan->user_features[i].value || proposal->user_features[i].start != shape_plan->user_features[i].start || - proposal->user_features[i].end != shape_plan->user_features[i].end) return false; + proposal->user_features[i].end != shape_plan->user_features[i].end) + return false; + return true; +} + +static inline hb_bool_t +hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan, + const hb_shape_plan_proposal_t *proposal) +{ + if (proposal->num_coords != shape_plan->num_coords) + return false; + for (unsigned int i = 0, n = proposal->num_coords; i < n; i++) + if (proposal->coords[i] != shape_plan->coords[i]) + return false; return true; } @@ -373,6 +429,7 @@ hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, { return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && hb_shape_plan_user_features_match (shape_plan, proposal) && + hb_shape_plan_coords_match (shape_plan, proposal) && ((shape_plan->default_shaper_list && proposal->shaper_list == NULL) || (shape_plan->shaper_func == proposal->shaper_func)); } @@ -389,6 +446,13 @@ hb_non_global_user_features_present (const hb_feature_t *user_features, return false; } +static inline hb_bool_t +hb_coords_present (const int *coords, + unsigned int num_coords) +{ + return num_coords != 0; +} + /** * hb_shape_plan_create_cached: * @face: @@ -409,6 +473,21 @@ hb_shape_plan_create_cached (hb_face_t *face, const hb_feature_t *user_features, unsigned int num_user_features, const char * const *shaper_list) +{ + return hb_shape_plan_create_cached2 (face, props, + user_features, num_user_features, + NULL, 0, + shaper_list); +} + +hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list) { DEBUG_MSG_FUNC (SHAPE_PLAN, NULL, "face=%p num_features=%d shaper_list=%p", @@ -456,16 +535,21 @@ retry: /* Not found. */ - hb_shape_plan_t *shape_plan = hb_shape_plan_create (face, props, user_features, num_user_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, + user_features, num_user_features, + coords, num_coords, + shaper_list); /* Don't add to the cache if face is inert. */ if (unlikely (hb_object_is_inert (face))) return shape_plan; /* Don't add the plan to the cache if there were user features with non-global ranges */ - if (hb_non_global_user_features_present (user_features, num_user_features)) return shape_plan; + /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */ + if (hb_coords_present (coords, num_coords)) + 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)); if (unlikely (!node)) diff --git a/src/hb-shape-plan.h b/src/hb-shape-plan.h index aa5e0c7d6..b62ae7ca3 100644 --- a/src/hb-shape-plan.h +++ b/src/hb-shape-plan.h @@ -52,6 +52,25 @@ hb_shape_plan_create_cached (hb_face_t *face, unsigned int num_user_features, const char * const *shaper_list); +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + +HB_EXTERN hb_shape_plan_t * +hb_shape_plan_create_cached2 (hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + + HB_EXTERN hb_shape_plan_t * hb_shape_plan_get_empty (void); diff --git a/src/hb-shape.cc b/src/hb-shape.cc index 41a4fc500..706f14420 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -373,7 +373,10 @@ hb_shape_full (hb_font_t *font, unsigned int num_features, const char * const *shaper_list) { - hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached (font->face, &buffer->props, features, num_features, shaper_list); + hb_shape_plan_t *shape_plan = hb_shape_plan_create_cached2 (font->face, &buffer->props, + features, num_features, + font->coords, font->num_coords, + shaper_list); hb_bool_t res = hb_shape_plan_execute (shape_plan, font, buffer, features, num_features); hb_shape_plan_destroy (shape_plan); diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 07007a640..6e4db0149 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -587,7 +587,9 @@ struct hb_uniscribe_shaper_shape_plan_data_t {}; hb_uniscribe_shaper_shape_plan_data_t * _hb_uniscribe_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan HB_UNUSED, const hb_feature_t *user_features HB_UNUSED, - unsigned int num_user_features HB_UNUSED) + unsigned int num_user_features HB_UNUSED, + const int *coords HB_UNUSED, + unsigned int num_coords HB_UNUSED) { return (hb_uniscribe_shaper_shape_plan_data_t *) HB_SHAPER_DATA_SUCCEEDED; }