diff --git a/src/hb-ot-map-private.hh b/src/hb-ot-map-private.hh index 2ba0f767a..5e3c9670a 100644 --- a/src/hb-ot-map-private.hh +++ b/src/hb-ot-map-private.hh @@ -42,46 +42,6 @@ struct hb_ot_map_t public: - hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); } - - typedef void (*gsub_pause_func_t) (const hb_ot_map_t *map, hb_face_t *face, hb_buffer_t *buffer, void *user_data); - typedef void (*gpos_pause_func_t) (const hb_ot_map_t *map, hb_font_t *font, hb_buffer_t *buffer, void *user_data); - - inline hb_mask_t get_global_mask (void) const { return global_mask; } - - inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) const { - const feature_map_t *map = features.bsearch (&feature_tag); - if (shift) *shift = map ? map->shift : 0; - return map ? map->mask : 0; - } - - inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const { - const feature_map_t *map = features.bsearch (&feature_tag); - return map ? map->_1_mask : 0; - } - - inline hb_mask_t get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const { - const feature_map_t *map = features.bsearch (&feature_tag); - return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX; - } - - inline hb_tag_t get_chosen_script (unsigned int table_index) const - { return chosen_script[table_index]; } - - HB_INTERNAL void substitute_closure (hb_face_t *face, hb_set_t *glyphs) const; - HB_INTERNAL void substitute (hb_face_t *face, hb_buffer_t *buffer) const; - HB_INTERNAL void position (hb_font_t *font, hb_buffer_t *buffer) const; - - inline void finish (void) { - features.finish (); - lookups[0].finish (); - lookups[1].finish (); - pauses[0].finish (); - pauses[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 */ @@ -113,6 +73,67 @@ struct hb_ot_map_t pause_callback_t callback; }; + + hb_ot_map_t (void) { memset (this, 0, sizeof (*this)); } + + typedef void (*gsub_pause_func_t) (const hb_ot_map_t *map, hb_face_t *face, hb_buffer_t *buffer, void *user_data); + typedef void (*gpos_pause_func_t) (const hb_ot_map_t *map, hb_font_t *font, hb_buffer_t *buffer, void *user_data); + + inline hb_mask_t get_global_mask (void) const { return global_mask; } + + inline hb_mask_t get_mask (hb_tag_t feature_tag, unsigned int *shift = NULL) const { + const feature_map_t *map = features.bsearch (&feature_tag); + if (shift) *shift = map ? map->shift : 0; + return map ? map->mask : 0; + } + + inline hb_mask_t get_1_mask (hb_tag_t feature_tag) const { + const feature_map_t *map = features.bsearch (&feature_tag); + return map ? map->_1_mask : 0; + } + + inline unsigned int get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const { + const feature_map_t *map = features.bsearch (&feature_tag); + return map ? map->index[table_index] : HB_OT_LAYOUT_NO_FEATURE_INDEX; + } + + inline unsigned int get_feature_stage (unsigned int table_index, hb_tag_t feature_tag) const { + const feature_map_t *map = features.bsearch (&feature_tag); + return map ? map->stage[table_index] : (unsigned int) -1; + } + + inline void get_stage_lookups (unsigned int table_index, unsigned int stage, + const struct lookup_map_t **plookups, unsigned int *lookup_count) const { + if (unlikely (stage == (unsigned int) -1)) { + *plookups = NULL; + *lookup_count = 0; + return; + } + assert (stage <= pauses[table_index].len); + unsigned int start = stage ? pauses[table_index][stage - 1].num_lookups : 0; + unsigned int end = stage < pauses[table_index].len ? pauses[table_index][stage].num_lookups : lookups[table_index].len; + *plookups = &lookups[table_index][start]; + *lookup_count = end - start; + } + + inline hb_tag_t get_chosen_script (unsigned int table_index) const + { return chosen_script[table_index]; } + + HB_INTERNAL void substitute_closure (hb_face_t *face, hb_set_t *glyphs) const; + HB_INTERNAL void substitute (hb_face_t *face, hb_buffer_t *buffer) const; + HB_INTERNAL void position (hb_font_t *font, hb_buffer_t *buffer) const; + + inline void finish (void) { + features.finish (); + lookups[0].finish (); + lookups[1].finish (); + pauses[0].finish (); + pauses[1].finish (); + } + + + private: + HB_INTERNAL void add_lookups (hb_face_t *face, unsigned int table_index, unsigned int feature_index, diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index 20e8e6f55..ae0cb61c9 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -89,7 +89,8 @@ void hb_ot_map_t::substitute (hb_face_t *face, hb_buffer_t *buffer) const buffer->clear_output (); - pause->callback.func (this, face, buffer, pause->callback.user_data); + if (pause->callback.func) + pause->callback.func (this, face, buffer, pause->callback.user_data); } for (; i < lookups[table_index].len; i++) @@ -106,7 +107,8 @@ void hb_ot_map_t::position (hb_font_t *font, hb_buffer_t *buffer) const for (; i < pause->num_lookups; i++) hb_ot_layout_position_lookup_fast (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); - pause->callback.func (this, font, buffer, pause->callback.user_data); + if (pause->callback.func) + pause->callback.func (this, font, buffer, pause->callback.user_data); } for (; i < lookups[table_index].len; i++) @@ -131,13 +133,11 @@ void hb_ot_map_t::substitute_closure (hb_face_t *face, void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::pause_func_t pause_func, void *user_data) { - if (pause_func) { - pause_info_t *p = pauses[table_index].push (); - if (likely (p)) { - p->stage = current_stage[table_index]; - p->callback.func = pause_func; - p->callback.user_data = user_data; - } + pause_info_t *p = pauses[table_index].push (); + if (likely (p)) { + p->stage = current_stage[table_index]; + p->callback.func = pause_func; + p->callback.user_data = user_data; } current_stage[table_index]++; diff --git a/src/hb-ot-shape-complex-indic.cc b/src/hb-ot-shape-complex-indic.cc index ba4fb4dff..8e3f3e6e8 100644 --- a/src/hb-ot-shape-complex-indic.cc +++ b/src/hb-ot-shape-complex-indic.cc @@ -106,39 +106,48 @@ compare_codepoint (const void *pa, const void *pb) return a < b ? -1 : a == b ? 0 : +1; } -static bool -would_substitute (hb_codepoint_t *glyphs, - unsigned int glyphs_count, - hb_tag_t feature_tag, - const hb_ot_map_t *map, - hb_face_t *face) +struct consonant_position_closure_t { - unsigned int lookup_indices[32]; - unsigned int offset, len; + struct feature_t + { + 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); + } - offset = 0; - do { - len = ARRAY_LENGTH (lookup_indices); - hb_ot_layout_feature_get_lookup_indexes (face, HB_OT_TAG_GSUB, - map->get_feature_index (0/*GSUB*/, feature_tag), - offset, - &len, - lookup_indices); + 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; + } - for (unsigned int i = 0; i < len; i++) - if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookup_indices[i])) - return true; + private: + const hb_ot_map_t::lookup_map_t *lookups; + unsigned int count; + }; - offset += len; - } while (len == ARRAY_LENGTH (lookup_indices)); + consonant_position_closure_t (const hb_ot_map_t *map_) : + map (map_), + pref (map_, HB_TAG('p','r','e','f')), + blwf (map_, HB_TAG('b','l','w','f')), + pstf (map_, HB_TAG('p','s','t','f')) {} - return false; -} + const hb_ot_map_t *map; + feature_t pref; + feature_t blwf; + feature_t pstf; +}; static indic_position_t -consonant_position (hb_codepoint_t u, - const hb_ot_map_t *map, - hb_font_t *font) +consonant_position (hb_codepoint_t u, + const consonant_position_closure_t *closure, + hb_font_t *font) { if ((u & ~0x007F) == 0x1780) return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */ @@ -148,14 +157,14 @@ consonant_position (hb_codepoint_t u, if ((u & ~0x007F) == 0x1780) virama = 0x17D2; /* Khmaer */ hb_codepoint_t glyphs[2]; - unsigned int virama_pos = IS_OLD_INDIC_TAG (map->get_chosen_script (0)) ? 1 : 0; + unsigned int virama_pos = IS_OLD_INDIC_TAG (closure->map->get_chosen_script (0)) ? 1 : 0; font->get_glyph (virama, 0, &glyphs[virama_pos]); font->get_glyph (u, 0, &glyphs[1-virama_pos]); hb_face_t *face = font->face; - if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('p','r','e','f'), map, face)) return POS_BELOW_C; - if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('b','l','w','f'), map, face)) return POS_BELOW_C; - if (would_substitute (glyphs, ARRAY_LENGTH (glyphs), HB_TAG('p','s','t','f'), map, face)) return POS_POST_C; + if (closure->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C; + if (closure->blwf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_BELOW_C; + if (closure->pstf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_POST_C; return POS_BASE_C; } @@ -260,7 +269,7 @@ is_halant_or_coeng (const hb_glyph_info_t &info) static inline void set_indic_properties (hb_glyph_info_t &info, - const hb_ot_map_t *map, + const consonant_position_closure_t *closure, hb_font_t *font) { hb_codepoint_t u = info.codepoint; @@ -322,7 +331,7 @@ set_indic_properties (hb_glyph_info_t &info, if ((FLAG (cat) & CONSONANT_FLAGS)) { - pos = consonant_position (u, map, font); + pos = consonant_position (u, closure, font); if (is_ra (u)) cat = OT_Ra; } @@ -462,9 +471,11 @@ setup_masks_indic (const hb_ot_complex_shaper_t *shaper, /* We cannot setup masks here. We save information about characters * and setup masks later on in a pause-callback. */ + consonant_position_closure_t closure (map); + unsigned int count = buffer->len; for (unsigned int i = 0; i < count; i++) - set_indic_properties (buffer->info[i], map, font); + set_indic_properties (buffer->info[i], &closure, font); } static int