[OT] Add per-complex-shaper shape_plan data

Hookup some Indic data to it.  More to come.
This commit is contained in:
Behdad Esfahbod 2012-08-02 10:46:34 -04:00
parent 8bb5deba96
commit a8c6da90f4
6 changed files with 113 additions and 61 deletions

View File

@ -296,6 +296,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_arabic =
"arabic",
collect_features_arabic,
NULL, /* override_features */
NULL, /* data_create */
NULL, /* data_destroy */
NULL, /* normalization_preference */
setup_masks_arabic,
true, /* zero_width_attached_marks */

View File

@ -82,56 +82,6 @@ indic_options (void)
}
struct indic_shape_plan_t
{
struct would_apply_feature_t
{
would_apply_feature_t (const hb_ot_map_t *map, hb_tag_t feature_tag)
{
map->get_stage_lookups (0/*GSUB*/,
map->get_feature_stage (0/*GSUB*/, feature_tag),
&lookups, &count);
}
inline bool would_substitute (hb_codepoint_t *glyphs,
unsigned int glyphs_count,
hb_face_t *face) const
{
for (unsigned int i = 0; i < count; i++)
if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookups[i].index))
return true;
return false;
}
private:
const hb_ot_map_t::lookup_map_t *lookups;
unsigned int count;
};
indic_shape_plan_t (const hb_ot_shape_plan_t *plan) :
pref (&plan->map, HB_TAG('p','r','e','f')),
blwf (&plan->map, HB_TAG('b','l','w','f')),
pstf (&plan->map, HB_TAG('p','s','t','f')),
is_old_spec (IS_OLD_INDIC_TAG (plan->map.get_chosen_script (0))) {}
would_apply_feature_t pref;
would_apply_feature_t blwf;
would_apply_feature_t pstf;
bool is_old_spec;
};
static indic_position_t
consonant_position_from_font (const indic_shape_plan_t *indic_plan,
hb_codepoint_t *glyphs, unsigned int glyphs_len,
hb_face_t *face)
{
if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C;
if (indic_plan->blwf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C;
if (indic_plan->pstf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_POST_C;
return POS_BASE_C;
}
struct feature_list_t {
hb_tag_t tag;
@ -230,6 +180,76 @@ override_features_indic (hb_ot_shape_planner_t *plan)
}
struct would_apply_feature_t
{
would_apply_feature_t (const hb_ot_map_t *map, hb_tag_t feature_tag)
{
map->get_stage_lookups (0/*GSUB*/,
map->get_feature_stage (0/*GSUB*/, feature_tag),
&lookups, &count);
}
inline bool would_substitute (hb_codepoint_t *glyphs,
unsigned int glyphs_count,
hb_face_t *face) const
{
for (unsigned int i = 0; i < count; i++)
if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookups[i].index))
return true;
return false;
}
private:
const hb_ot_map_t::lookup_map_t *lookups;
unsigned int count;
};
struct indic_shape_plan_t
{
indic_shape_plan_t (const hb_ot_shape_plan_t *plan) :
pref (&plan->map, HB_TAG('p','r','e','f')),
blwf (&plan->map, HB_TAG('b','l','w','f')),
pstf (&plan->map, HB_TAG('p','s','t','f')),
is_old_spec (IS_OLD_INDIC_TAG (plan->map.get_chosen_script (0))) {}
would_apply_feature_t pref;
would_apply_feature_t blwf;
would_apply_feature_t pstf;
bool is_old_spec;
};
static void *
data_create_indic (const hb_ot_shape_plan_t *plan)
{
indic_shape_plan_t *data = (indic_shape_plan_t *) calloc (1, sizeof (indic_shape_plan_t));
if (unlikely (!data))
return NULL;
/* Mixing C++ and C, oh well... */
indic_shape_plan_t indic_plan (plan);
*data = indic_plan;
return data;
}
static void
data_destroy_indic (void *data)
{
free (data);
}
static indic_position_t
consonant_position_from_face (const indic_shape_plan_t *indic_plan,
hb_codepoint_t *glyphs, unsigned int glyphs_len,
hb_face_t *face)
{
if (indic_plan->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C;
if (indic_plan->blwf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C;
if (indic_plan->pstf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_POST_C;
return POS_BASE_C;
}
static void
setup_masks_indic (const hb_ot_shape_plan_t *plan HB_UNUSED,
hb_buffer_t *buffer,
@ -278,9 +298,9 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
default: virama = 0; break;
}
indic_shape_plan_t indic_plan (plan);
const indic_shape_plan_t *indic_plan = (const indic_shape_plan_t *) plan->data;
unsigned int consonant_pos = indic_plan.is_old_spec ? 0 : 1;
unsigned int consonant_pos = indic_plan->is_old_spec ? 0 : 1;
hb_codepoint_t glyphs[2];
if (virama && font->get_glyph (virama, 0, &glyphs[1 - consonant_pos]))
{
@ -291,7 +311,7 @@ update_consonant_positions (const hb_ot_shape_plan_t *plan,
for (unsigned int i = 0; i < count; i++)
if (buffer->info[i].indic_position() == POS_BASE_C) {
glyphs[consonant_pos] = buffer->info[i].codepoint;
buffer->info[i].indic_position() = consonant_position_from_font (&indic_plan, glyphs, 2, face);
buffer->info[i].indic_position() = consonant_position_from_face (indic_plan, glyphs, 2, face);
}
}
}
@ -1086,6 +1106,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_indic =
"indic",
collect_features_indic,
override_features_indic,
data_create_indic,
data_destroy_indic,
NULL, /* normalization_preference */
setup_masks_indic,
false, /* zero_width_attached_marks */

View File

@ -88,6 +88,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_default =
"default",
collect_features_default,
NULL, /* override_features */
NULL, /* data_create */
NULL, /* data_destroy */
normalization_preference_default,
NULL, /* setup_masks */
true, /* zero_width_attached_marks */
@ -196,6 +198,8 @@ const hb_ot_complex_shaper_t _hb_ot_complex_shaper_thai =
"thai",
NULL, /* collect_features */
NULL, /* override_features */
NULL, /* data_create */
NULL, /* data_destroy */
NULL, /* normalization_preference */
setup_masks_thai,
true, /* zero_width_attached_marks */

View File

@ -69,13 +69,27 @@ struct hb_ot_complex_shaper_t
*/
void (*override_features) (hb_ot_shape_planner_t *plan);
/* data_create()
* Called at the end of shape_plan().
* Whatever shapers return will be accessible through plan->data later.
* If NULL is returned, means a plan failure.
* May be NULL. */
void *(*data_create) (const hb_ot_shape_plan_t *plan);
/* data_destroy()
* Called when the shape_plan is being destroyed.
* plan->data is passed here for destruction.
* If NULL is returned, means a plan failure.
* May be NULL. */
void (*data_destroy) (void *data);
/* normalization_preference()
* Called during shape().
*/
hb_ot_shape_normalization_mode_t
(*normalization_preference) (const hb_ot_shape_plan_t *plan);
/* setup_masks()
* Called during shape().
* Shapers should use map to get feature masks and set on buffer.

View File

@ -44,6 +44,7 @@ struct hb_ot_shape_plan_t
hb_segment_properties_t props;
const struct hb_ot_complex_shaper_t *shaper;
hb_ot_map_t map;
const void *data;
inline void substitute_closure (hb_face_t *face, hb_set_t *glyphs) const { map.substitute_closure (this, face, glyphs); }
inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); }

View File

@ -167,8 +167,8 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
const hb_feature_t *user_features,
unsigned int num_user_features)
{
hb_ot_shape_plan_t *data = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
if (unlikely (!data))
hb_ot_shape_plan_t *plan = (hb_ot_shape_plan_t *) calloc (1, sizeof (hb_ot_shape_plan_t));
if (unlikely (!plan))
return NULL;
hb_ot_shape_planner_t planner (shape_plan);
@ -177,17 +177,26 @@ _hb_ot_shaper_shape_plan_data_create (hb_shape_plan_t *shape_plan,
hb_ot_shape_collect_features (&planner, &shape_plan->props, user_features, num_user_features);
planner.compile (*data);
planner.compile (*plan);
return data;
if (plan->shaper->data_create) {
plan->data = plan->shaper->data_create (plan);
if (unlikely (!plan->data))
return NULL;
}
return plan;
}
void
_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *data)
_hb_ot_shaper_shape_plan_data_destroy (hb_ot_shaper_shape_plan_data_t *plan)
{
data->finish ();
if (plan->shaper->data_destroy)
plan->shaper->data_destroy (const_cast<void *> (plan->data));
free (data);
plan->finish ();
free (plan);
}