[OT] Separate map_builder from the actual map
Respectively, separate planner from the actual plan.
This commit is contained in:
parent
5560a19e2b
commit
90645fb24b
|
@ -38,7 +38,31 @@ HB_BEGIN_DECLS
|
||||||
|
|
||||||
static const hb_tag_t table_tags[2] = {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS};
|
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:
|
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); }
|
{ return (a->tag != b->tag) ? (a->tag < b->tag ? -1 : 1) : (a->seq < b->seq ? -1 : 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hb_prealloced_array_t<feature_info_t,16> 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 {
|
struct feature_map_t {
|
||||||
hb_tag_t tag; /* should be first for our bsearch to work */
|
hb_tag_t tag; /* should be first for our bsearch to work */
|
||||||
unsigned int index[2]; /* GSUB, GPOS */
|
unsigned int index[2]; /* GSUB, GPOS */
|
||||||
|
@ -78,67 +143,13 @@ struct hb_ot_map_t {
|
||||||
hb_mask_t mask);
|
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_mask_t global_mask;
|
||||||
|
|
||||||
hb_prealloced_array_t<feature_info_t,8> feature_infos; /* used before compile() only */
|
hb_prealloced_array_t<feature_map_t, 8> features;
|
||||||
hb_prealloced_array_t<feature_map_t, 8> feature_maps;
|
hb_prealloced_array_t<lookup_map_t, 32> lookups[2]; /* GSUB/GPOS */
|
||||||
|
|
||||||
hb_prealloced_array_t<lookup_map_t, 32> lookup_maps[2]; /* GSUB/GPOS */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
HB_END_DECLS
|
HB_END_DECLS
|
||||||
|
|
||||||
#endif /* HB_OT_MAP_PRIVATE_HH */
|
#endif /* HB_OT_MAP_PRIVATE_HH */
|
||||||
|
|
|
@ -52,7 +52,7 @@ hb_ot_map_t::add_lookups (hb_face_t *face,
|
||||||
lookup_indices);
|
lookup_indices);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len; i++) {
|
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))
|
if (unlikely (!lookup))
|
||||||
return;
|
return;
|
||||||
lookup->mask = mask;
|
lookup->mask = mask;
|
||||||
|
@ -65,10 +65,11 @@ hb_ot_map_t::add_lookups (hb_face_t *face,
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hb_ot_map_t::compile (hb_face_t *face,
|
hb_ot_map_builder_t::compile (hb_face_t *face,
|
||||||
const hb_segment_properties_t *props)
|
const hb_segment_properties_t *props,
|
||||||
|
hb_ot_map_t &m)
|
||||||
{
|
{
|
||||||
global_mask = 1;
|
m.global_mask = 1;
|
||||||
|
|
||||||
if (!feature_infos.len)
|
if (!feature_infos.len)
|
||||||
return;
|
return;
|
||||||
|
@ -139,7 +140,7 @@ hb_ot_map_t::compile (hb_face_t *face,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
feature_map_t *map = feature_maps.push ();
|
hb_ot_map_t::feature_map_t *map = m.features.push ();
|
||||||
if (unlikely (!map))
|
if (unlikely (!map))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -155,7 +156,7 @@ hb_ot_map_t::compile (hb_face_t *face,
|
||||||
map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
|
map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit);
|
||||||
next_bit += bits_needed;
|
next_bit += bits_needed;
|
||||||
if (info->global)
|
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;
|
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],
|
script_index[table_index],
|
||||||
language_index[table_index],
|
language_index[table_index],
|
||||||
&required_feature_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++)
|
for (unsigned i = 0; i < m.features.len; i++)
|
||||||
add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask);
|
m.add_lookups (face, table_index, m.features[i].index[table_index], m.features[i].mask);
|
||||||
|
|
||||||
/* Sort lookups and merge duplicates */
|
/* Sort lookups and merge duplicates */
|
||||||
lookup_maps[table_index].sort ();
|
m.lookups[table_index].sort ();
|
||||||
if (lookup_maps[table_index].len)
|
if (m.lookups[table_index].len)
|
||||||
{
|
{
|
||||||
unsigned int j = 0;
|
unsigned int j = 0;
|
||||||
for (unsigned int i = 1; i < lookup_maps[table_index].len; i++)
|
for (unsigned int i = 1; i < m.lookups[table_index].len; i++)
|
||||||
if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index)
|
if (m.lookups[table_index][i].index != m.lookups[table_index][j].index)
|
||||||
lookup_maps[table_index][++j] = lookup_maps[table_index][i];
|
m.lookups[table_index][++j] = m.lookups[table_index][i];
|
||||||
else
|
else
|
||||||
lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask;
|
m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask;
|
||||||
lookup_maps[table_index].shrink (j + 1);
|
m.lookups[table_index].shrink (j + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,14 +152,14 @@ static const struct arabic_state_table_entry {
|
||||||
|
|
||||||
|
|
||||||
void
|
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. */
|
/* 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;
|
unsigned int num_features = props->script == HB_SCRIPT_SYRIAC ? SYRIAC_NUM_FEATURES : COMMON_NUM_FEATURES;
|
||||||
for (unsigned int i = 0; i < num_features; i++)
|
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
|
void
|
||||||
|
|
|
@ -61,14 +61,14 @@ hb_ot_shape_complex_categorize (const hb_segment_properties_t *props)
|
||||||
* Shapers should use plan->map to add their features.
|
* 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
|
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)
|
const hb_segment_properties_t *props)
|
||||||
{
|
{
|
||||||
switch (plan->shaper) {
|
switch (planner->shaper) {
|
||||||
case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_collect_features_arabic (plan, props); return;
|
case hb_ot_complex_shaper_arabic: _hb_ot_shape_complex_collect_features_arabic (planner, props); return;
|
||||||
case hb_ot_complex_shaper_none: default: return;
|
case hb_ot_complex_shaper_none: default: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,8 @@ enum hb_ot_complex_shaper_t {
|
||||||
|
|
||||||
struct hb_ot_shape_plan_t
|
struct hb_ot_shape_plan_t
|
||||||
{
|
{
|
||||||
|
friend struct hb_ot_shape_planner_t;
|
||||||
|
|
||||||
hb_ot_map_t map;
|
hb_ot_map_t map;
|
||||||
hb_ot_complex_shaper_t shaper;
|
hb_ot_complex_shaper_t shaper;
|
||||||
|
|
||||||
|
@ -59,6 +61,26 @@ struct hb_ot_shape_plan_t
|
||||||
NO_COPY (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
|
struct hb_ot_shape_context_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,19 +49,19 @@ hb_tag_t default_features[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
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_segment_properties_t *props,
|
||||||
const hb_feature_t *user_features,
|
const hb_feature_t *user_features,
|
||||||
unsigned int num_user_features)
|
unsigned int num_user_features)
|
||||||
{
|
{
|
||||||
switch (props->direction) {
|
switch (props->direction) {
|
||||||
case HB_DIRECTION_LTR:
|
case HB_DIRECTION_LTR:
|
||||||
plan->map.add_bool_feature (HB_TAG ('l','t','r','a'));
|
planner->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','m'));
|
||||||
break;
|
break;
|
||||||
case HB_DIRECTION_RTL:
|
case HB_DIRECTION_RTL:
|
||||||
plan->map.add_bool_feature (HB_TAG ('r','t','l','a'));
|
planner->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','m'), false);
|
||||||
break;
|
break;
|
||||||
case HB_DIRECTION_TTB:
|
case HB_DIRECTION_TTB:
|
||||||
case HB_DIRECTION_BTT:
|
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++)
|
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++) {
|
for (unsigned int i = 0; i < num_user_features; i++) {
|
||||||
const hb_feature_t *feature = &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,
|
const hb_feature_t *user_features,
|
||||||
unsigned int num_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
|
static void
|
||||||
|
|
Loading…
Reference in New Issue