[Indic] Streamline feature would_apply()
Comes with some 10% speedup for Devanagari even!
This commit is contained in:
parent
1d002048d5
commit
610e5e8f71
|
@ -42,46 +42,6 @@ struct hb_ot_map_t
|
||||||
|
|
||||||
public:
|
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 {
|
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 */
|
||||||
|
@ -113,6 +73,67 @@ struct hb_ot_map_t
|
||||||
pause_callback_t callback;
|
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,
|
HB_INTERNAL void add_lookups (hb_face_t *face,
|
||||||
unsigned int table_index,
|
unsigned int table_index,
|
||||||
unsigned int feature_index,
|
unsigned int feature_index,
|
||||||
|
|
|
@ -89,7 +89,8 @@ void hb_ot_map_t::substitute (hb_face_t *face, hb_buffer_t *buffer) const
|
||||||
|
|
||||||
buffer->clear_output ();
|
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++)
|
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++)
|
for (; i < pause->num_lookups; i++)
|
||||||
hb_ot_layout_position_lookup_fast (font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask);
|
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++)
|
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)
|
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 ();
|
||||||
pause_info_t *p = pauses[table_index].push ();
|
if (likely (p)) {
|
||||||
if (likely (p)) {
|
p->stage = current_stage[table_index];
|
||||||
p->stage = current_stage[table_index];
|
p->callback.func = pause_func;
|
||||||
p->callback.func = pause_func;
|
p->callback.user_data = user_data;
|
||||||
p->callback.user_data = user_data;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_stage[table_index]++;
|
current_stage[table_index]++;
|
||||||
|
|
|
@ -106,39 +106,48 @@ compare_codepoint (const void *pa, const void *pb)
|
||||||
return a < b ? -1 : a == b ? 0 : +1;
|
return a < b ? -1 : a == b ? 0 : +1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
struct consonant_position_closure_t
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
unsigned int lookup_indices[32];
|
struct feature_t
|
||||||
unsigned int offset, len;
|
{
|
||||||
|
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;
|
inline bool would_substitute (hb_codepoint_t *glyphs,
|
||||||
do {
|
unsigned int glyphs_count,
|
||||||
len = ARRAY_LENGTH (lookup_indices);
|
hb_face_t *face) const
|
||||||
hb_ot_layout_feature_get_lookup_indexes (face, HB_OT_TAG_GSUB,
|
{
|
||||||
map->get_feature_index (0/*GSUB*/, feature_tag),
|
for (unsigned int i = 0; i < count; i++)
|
||||||
offset,
|
if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookups[i].index))
|
||||||
&len,
|
return true;
|
||||||
lookup_indices);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (unsigned int i = 0; i < len; i++)
|
private:
|
||||||
if (hb_ot_layout_would_substitute_lookup_fast (face, glyphs, glyphs_count, lookup_indices[i]))
|
const hb_ot_map_t::lookup_map_t *lookups;
|
||||||
return true;
|
unsigned int count;
|
||||||
|
};
|
||||||
|
|
||||||
offset += len;
|
consonant_position_closure_t (const hb_ot_map_t *map_) :
|
||||||
} while (len == ARRAY_LENGTH (lookup_indices));
|
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
|
static indic_position_t
|
||||||
consonant_position (hb_codepoint_t u,
|
consonant_position (hb_codepoint_t u,
|
||||||
const hb_ot_map_t *map,
|
const consonant_position_closure_t *closure,
|
||||||
hb_font_t *font)
|
hb_font_t *font)
|
||||||
{
|
{
|
||||||
if ((u & ~0x007F) == 0x1780)
|
if ((u & ~0x007F) == 0x1780)
|
||||||
return POS_BELOW_C; /* In Khmer coeng model, post and below forms should not be reordered. */
|
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 */
|
if ((u & ~0x007F) == 0x1780) virama = 0x17D2; /* Khmaer */
|
||||||
hb_codepoint_t glyphs[2];
|
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 (virama, 0, &glyphs[virama_pos]);
|
||||||
font->get_glyph (u, 0, &glyphs[1-virama_pos]);
|
font->get_glyph (u, 0, &glyphs[1-virama_pos]);
|
||||||
|
|
||||||
hb_face_t *face = font->face;
|
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 (closure->pref.would_substitute (glyphs, ARRAY_LENGTH (glyphs), 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 (closure->blwf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), 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->pstf.would_substitute (glyphs, ARRAY_LENGTH (glyphs), face)) return POS_POST_C;
|
||||||
return POS_BASE_C;
|
return POS_BASE_C;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +269,7 @@ is_halant_or_coeng (const hb_glyph_info_t &info)
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
set_indic_properties (hb_glyph_info_t &info,
|
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_font_t *font)
|
||||||
{
|
{
|
||||||
hb_codepoint_t u = info.codepoint;
|
hb_codepoint_t u = info.codepoint;
|
||||||
|
@ -322,7 +331,7 @@ set_indic_properties (hb_glyph_info_t &info,
|
||||||
|
|
||||||
if ((FLAG (cat) & CONSONANT_FLAGS))
|
if ((FLAG (cat) & CONSONANT_FLAGS))
|
||||||
{
|
{
|
||||||
pos = consonant_position (u, map, font);
|
pos = consonant_position (u, closure, font);
|
||||||
if (is_ra (u))
|
if (is_ra (u))
|
||||||
cat = OT_Ra;
|
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
|
/* We cannot setup masks here. We save information about characters
|
||||||
* and setup masks later on in a pause-callback. */
|
* and setup masks later on in a pause-callback. */
|
||||||
|
|
||||||
|
consonant_position_closure_t closure (map);
|
||||||
|
|
||||||
unsigned int count = buffer->len;
|
unsigned int count = buffer->len;
|
||||||
for (unsigned int i = 0; i < count; i++)
|
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
|
static int
|
||||||
|
|
Loading…
Reference in New Issue