diff --git a/src/hb-ot-shape-complex-arabic.cc b/src/hb-ot-shape-complex-arabic.cc index d08d3649e..b014c744f 100644 --- a/src/hb-ot-shape-complex-arabic.cc +++ b/src/hb-ot-shape-complex-arabic.cc @@ -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 */ diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index be37cddb3..cdfd5b94b 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -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 */ diff --git a/src/hb-ot-shape-complex-misc.cc b/src/hb-ot-shape-complex-misc.cc index 6ae9f5050..4f1dd5b2d 100644 --- a/src/hb-ot-shape-complex-misc.cc +++ b/src/hb-ot-shape-complex-misc.cc @@ -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 */ diff --git a/src/hb-ot-shape-complex-private.hh b/src/hb-ot-shape-complex-private.hh index e7f96976f..baece320d 100644 --- a/src/hb-ot-shape-complex-private.hh +++ b/src/hb-ot-shape-complex-private.hh @@ -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. diff --git a/src/hb-ot-shape-private.hh b/src/hb-ot-shape-private.hh index da8a6dbe3..975665e96 100644 --- a/src/hb-ot-shape-private.hh +++ b/src/hb-ot-shape-private.hh @@ -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); } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 67330b414..28bb1f9e2 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -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 (plan->data)); - free (data); + plan->finish (); + + free (plan); }