diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 02f5a9112..2c8b99f61 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -38,7 +38,31 @@ HB_BEGIN_DECLS static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}; -struct hb_ot_map_t { +struct hb_ot_map_builder_t +{ + public: + + inline void add_feature (hb_tag_t tag, unsigned int value, bool global) + { + feature_info_t *info = feature_infos.push(); + if (unlikely (!info)) return; + info->tag = tag; + info->seq = feature_infos.len; + info->max_value = value; + info->global = global; + info->default_value = global ? value : 0; + } + + inline void add_bool_feature (hb_tag_t tag, bool global = true) + { add_feature (tag, 1, global); } + + HB_INTERNAL void compile (hb_face_t *face, + const hb_segment_properties_t *props, + struct hb_ot_map_t &m); + + inline void finish (void) { + feature_infos.finish (); + } private: @@ -53,6 +77,47 @@ struct hb_ot_map_t { { return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); } }; + hb_prealloced_array_t feature_infos; /* used before compile() only */ +}; + + +struct hb_ot_map_t +{ + friend struct hb_ot_map_builder_t; + + public: + + inline hb_mask_t get_global_mask (void) const { return global_mask; } + + inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const { + const feature_map_t *map = features.bsearch (&tag); + if (shift) *shift = map ? map->shift : 0; + return map ? map->mask : 0; + } + + inline hb_mask_t get_1_mask (hb_tag_t tag) const { + const feature_map_t *map = features.bsearch (&tag); + return map ? map->_1_mask : 0; + } + + inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const { + for (unsigned int i = 0; i < lookups[0].len; i++) + hb_ot_layout_substitute_lookup (face, buffer, lookups[0][i].index, lookups[0][i].mask); + } + + inline void position (hb_font_t *font, hb_face_t *face, hb_buffer_t *buffer) const { + for (unsigned int i = 0; i < lookups[1].len; i++) + hb_ot_layout_position_lookup (font, buffer, lookups[1][i].index, lookups[1][i].mask); + } + + inline void finish (void) { + features.finish (); + lookups[0].finish (); + lookups[1].finish (); + } + + private: + struct feature_map_t { hb_tag_t tag; /* should be first for our bsearch to work */ unsigned int index[2]; /* GSUB, GPOS */ @@ -78,67 +143,13 @@ struct hb_ot_map_t { hb_mask_t mask); - public: - - void add_feature (hb_tag_t tag, unsigned int value, bool global) - { - feature_info_t *info = feature_infos.push(); - if (unlikely (!info)) return; - info->tag = tag; - info->seq = feature_infos.len; - info->max_value = value; - info->global = global; - info->default_value = global ? value : 0; - } - - inline void add_bool_feature (hb_tag_t tag, bool global = true) - { add_feature (tag, 1, global); } - - HB_INTERNAL void compile (hb_face_t *face, - const hb_segment_properties_t *props); - - inline hb_mask_t get_global_mask (void) const { return global_mask; } - - inline hb_mask_t get_mask (hb_tag_t tag, unsigned int *shift = NULL) const { - const feature_map_t *map = feature_maps.bsearch (&tag); - if (shift) *shift = map ? map->shift : 0; - return map ? map->mask : 0; - } - - inline hb_mask_t get_1_mask (hb_tag_t tag) const { - const feature_map_t *map = feature_maps.bsearch (&tag); - return map ? map->_1_mask : 0; - } - - inline void substitute (hb_face_t *face, hb_buffer_t *buffer) const { - for (unsigned int i = 0; i < lookup_maps[0].len; i++) - hb_ot_layout_substitute_lookup (face, buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask); - } - - inline void position (hb_font_t *font, hb_face_t *face, hb_buffer_t *buffer) const { - for (unsigned int i = 0; i < lookup_maps[1].len; i++) - hb_ot_layout_position_lookup (font, buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask); - } - - inline void finish (void) { - feature_infos.finish (); - feature_maps.finish (); - lookup_maps[0].finish (); - lookup_maps[1].finish (); - } - - private: - hb_mask_t global_mask; - hb_prealloced_array_t feature_infos; /* used before compile() only */ - hb_prealloced_array_t feature_maps; - - hb_prealloced_array_t lookup_maps[2]; /* GSUB/GPOS */ + hb_prealloced_array_t features; + hb_prealloced_array_t lookups[2]; /* GSUB/GPOS */ }; - HB_END_DECLS #endif /* HB_OT_MAP_PRIVATE_HH */ diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 9006bf93a..f178bed84 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -52,7 +52,7 @@ hb_ot_map_t::add_lookups (hb_face_t *face, lookup_indices); for (unsigned int i = 0; i < len; i++) { - lookup_map_t *lookup = lookup_maps[table_index].push (); + hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push (); if (unlikely (!lookup)) return; lookup->mask = mask; @@ -65,10 +65,11 @@ hb_ot_map_t::add_lookups (hb_face_t *face, void -hb_ot_map_t::compile (hb_face_t *face, - const hb_segment_properties_t *props) +hb_ot_map_builder_t::compile (hb_face_t *face, + const hb_segment_properties_t *props, + hb_ot_map_t &m) { - global_mask = 1; + m.global_mask = 1; if (!feature_infos.len) return; @@ -139,7 +140,7 @@ hb_ot_map_t::compile (hb_face_t *face, continue; - feature_map_t *map = feature_maps.push (); + hb_ot_map_t::feature_map_t *map = m.features.push (); if (unlikely (!map)) break; @@ -155,7 +156,7 @@ hb_ot_map_t::compile (hb_face_t *face, map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); next_bit += bits_needed; if (info->global) - global_mask |= (info->default_value << map->shift) & map->mask; + m.global_mask |= (info->default_value << map->shift) & map->mask; } map->_1_mask = (1 << map->shift) & map->mask; @@ -174,22 +175,22 @@ hb_ot_map_t::compile (hb_face_t *face, script_index[table_index], language_index[table_index], &required_feature_index)) - add_lookups (face, table_index, required_feature_index, 1); + m.add_lookups (face, table_index, required_feature_index, 1); - for (unsigned i = 0; i < feature_maps.len; i++) - add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask); + for (unsigned i = 0; i < m.features.len; i++) + m.add_lookups (face, table_index, m.features[i].index[table_index], m.features[i].mask); /* Sort lookups and merge duplicates */ - lookup_maps[table_index].sort (); - if (lookup_maps[table_index].len) + m.lookups[table_index].sort (); + if (m.lookups[table_index].len) { unsigned int j = 0; - for (unsigned int i = 1; i < lookup_maps[table_index].len; i++) - if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index) - lookup_maps[table_index][++j] = lookup_maps[table_index][i]; + for (unsigned int i = 1; i < m.lookups[table_index].len; i++) + if (m.lookups[table_index][i].index != m.lookups[table_index][j].index) + m.lookups[table_index][++j] = m.lookups[table_index][i]; else - lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask; - lookup_maps[table_index].shrink (j + 1); + m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; + m.lookups[table_index].shrink (j + 1); } } } diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index f2d325fcc..1b5b23147 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -152,14 +152,14 @@ static const struct arabic_state_table_entry { void -_hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_plan_t *plan, const hb_segment_properties_t *props) +_hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_planner_t *planner, const hb_segment_properties_t *props) { /* ArabicOT spec enables 'cswh' for Arabic where as for basic shaper it's disabled by default. */ - plan->map.add_bool_feature (HB_TAG('c','s','w','h')); + planner->map.add_bool_feature (HB_TAG('c','s','w','h')); unsigned int num_features = props->script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES; for (unsigned int i = 0; i < num_features; i++) - plan->map.add_bool_feature (arabic_syriac_features[i], false); + planner->map.add_bool_feature (arabic_syriac_features[i], false); } void diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index b3afe2b7b..f58e5da84 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -61,14 +61,14 @@ hb_ot_shape_complex_categorize (const hb_segment_properties_t *props) * Shapers should use plan->map to add their features. */ -HB_INTERNAL void _hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_plan_t *plan, const hb_segment_properties_t *props); +HB_INTERNAL void _hb_ot_shape_complex_collect_features_arabic (hb_ot_shape_planner_t *plan, const hb_segment_properties_t *props); static inline void -hb_ot_shape_complex_collect_features (hb_ot_shape_plan_t *plan, +hb_ot_shape_complex_collect_features (hb_ot_shape_planner_t *planner, const hb_segment_properties_t *props) { - switch (plan->shaper) { - case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_collect_features_arabic (plan, props); return; + switch (planner->shaper) { + case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_collect_features_arabic (planner, props); return; case hb_ot_complex_shaper_none: default: return; } } diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh index 4ea73f54d..60269ce30 100644 --- a/src/hb-ot-shape-private.hh +++ b/src/hb-ot-shape-private.hh @@ -49,6 +49,8 @@ enum hb_ot_complex_shaper_t { struct hb_ot_shape_plan_t { + friend struct hb_ot_shape_planner_t; + hb_ot_map_t map; hb_ot_complex_shaper_t shaper; @@ -59,6 +61,26 @@ struct hb_ot_shape_plan_t NO_COPY (hb_ot_shape_plan_t); }; +struct hb_ot_shape_planner_t +{ + hb_ot_map_builder_t map; + hb_ot_complex_shaper_t shaper; + + hb_ot_shape_planner_t (void) : map () {} + ~hb_ot_shape_planner_t (void) { map.finish (); } + + inline void compile (hb_face_t *face, + const hb_segment_properties_t *props, + struct hb_ot_shape_plan_t &plan) + { + plan.shaper = shaper; + map.compile (face, props, plan.map); + } + + private: + NO_COPY (hb_ot_shape_planner_t); +}; + struct hb_ot_shape_context_t { diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 02be2375f..4b66dd1b1 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -49,19 +49,19 @@ hb_tag_t default_features[] = { }; static void -hb_ot_shape_collect_features (hb_ot_shape_plan_t *plan, +hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, const hb_segment_properties_t *props, - const hb_feature_t *user_features, - unsigned int num_user_features) + const hb_feature_t *user_features, + unsigned int num_user_features) { switch (props->direction) { case HB_DIRECTION_LTR: - plan->map.add_bool_feature (HB_TAG ('l','t','r','a')); - plan->map.add_bool_feature (HB_TAG ('l','t','r','m')); + planner->map.add_bool_feature (HB_TAG ('l','t','r','a')); + planner->map.add_bool_feature (HB_TAG ('l','t','r','m')); break; case HB_DIRECTION_RTL: - plan->map.add_bool_feature (HB_TAG ('r','t','l','a')); - plan->map.add_bool_feature (HB_TAG ('r','t','l','m'), false); + planner->map.add_bool_feature (HB_TAG ('r','t','l','a')); + planner->map.add_bool_feature (HB_TAG ('r','t','l','m'), false); break; case HB_DIRECTION_TTB: case HB_DIRECTION_BTT: @@ -71,13 +71,13 @@ hb_ot_shape_collect_features (hb_ot_shape_plan_t *plan, } for (unsigned int i = 0; i < ARRAY_LENGTH (default_features); i++) - plan->map.add_bool_feature (default_features[i]); + planner->map.add_bool_feature (default_features[i]); - hb_ot_shape_complex_collect_features (plan, props); + hb_ot_shape_complex_collect_features (planner, props); for (unsigned int i = 0; i < num_user_features; i++) { const hb_feature_t *feature = &user_features[i]; - plan->map.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1)); + planner->map.add_feature (feature->tag, feature->value, (feature->start == 0 && feature->end == (unsigned int) -1)); } } @@ -384,11 +384,13 @@ hb_ot_shape_plan_internal (hb_ot_shape_plan_t *plan, const hb_feature_t *user_features, unsigned int num_user_features) { - plan->shaper = hb_ot_shape_complex_categorize (props); + hb_ot_shape_planner_t planner; - hb_ot_shape_collect_features (plan, props, user_features, num_user_features); + planner.shaper = hb_ot_shape_complex_categorize (props); - plan->map.compile (face, props); + hb_ot_shape_collect_features (&planner, props, user_features, num_user_features); + + planner.compile (face, props, *plan); } static void