Respectively, separate planner from the actual plan.
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:
{ return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
};
- struct feature_map_t {
- hb_tag_t tag; /* should be first for our bsearch to work */
- unsigned int index[2]; /* GSUB, GPOS */
- unsigned int shift;
- hb_mask_t mask;
- hb_mask_t _1_mask; /* mask for value=1, for quick access */
-
- static int cmp (const feature_map_t *a, const feature_map_t *b)
- { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
- };
-
- struct lookup_map_t {
- unsigned int index;
- hb_mask_t mask;
-
- static int cmp (const lookup_map_t *a, const lookup_map_t *b)
- { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
- };
+ hb_prealloced_array_t<feature_info_t,16> feature_infos; /* used before compile() only */
+};
- HB_INTERNAL void add_lookups (hb_face_t *face,
- unsigned int table_index,
- unsigned int feature_index,
- hb_mask_t mask);
+struct hb_ot_map_t
+{
+ friend struct hb_ot_map_builder_t;
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);
+ 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 = feature_maps.bsearch (&tag);
+ 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 < lookup_maps[0].len; i++)
- hb_ot_layout_substitute_lookup (face, buffer, lookup_maps[0][i].index, lookup_maps[0][i].mask);
+ 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 < lookup_maps[1].len; i++)
- hb_ot_layout_position_lookup (font, buffer, lookup_maps[1][i].index, lookup_maps[1][i].mask);
+ 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) {
- feature_infos.finish ();
- feature_maps.finish ();
- lookup_maps[0].finish ();
- lookup_maps[1].finish ();
+ features.finish ();
+ lookups[0].finish ();
+ lookups[1].finish ();
}
private:
- hb_mask_t global_mask;
+ struct feature_map_t {
+ hb_tag_t tag; /* should be first for our bsearch to work */
+ unsigned int index[2]; /* GSUB, GPOS */
+ unsigned int shift;
+ hb_mask_t mask;
+ hb_mask_t _1_mask; /* mask for value=1, for quick access */
- hb_prealloced_array_t<feature_info_t,8> feature_infos; /* used before compile() only */
- hb_prealloced_array_t<feature_map_t, 8> feature_maps;
+ static int cmp (const feature_map_t *a, const feature_map_t *b)
+ { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
+ };
- hb_prealloced_array_t<lookup_map_t, 32> lookup_maps[2]; /* GSUB/GPOS */
-};
+ struct lookup_map_t {
+ unsigned int index;
+ hb_mask_t mask;
+ static int cmp (const lookup_map_t *a, const lookup_map_t *b)
+ { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
+ };
+
+ HB_INTERNAL void add_lookups (hb_face_t *face,
+ unsigned int table_index,
+ unsigned int feature_index,
+ hb_mask_t mask);
+
+
+ hb_mask_t global_mask;
+
+ hb_prealloced_array_t<feature_map_t, 8> features;
+ hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
+};
HB_END_DECLS
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;
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;
continue;
- feature_map_t *map = feature_maps.push ();
+ hb_ot_map_t::feature_map_t *map = m.features.push ();
if (unlikely (!map))
break;
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;
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);
}
}
}
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
* 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;
}
}
struct hb_ot_shape_plan_t
{
+ friend struct hb_ot_shape_planner_t;
+
hb_ot_map_t map;
hb_ot_complex_shaper_t shaper;
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
{
};
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:
}
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));
}
}
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