public:
+ struct feature_map_t {
+ hb_tag_t tag; /* should be first for our bsearch to work */
+ unsigned int index[2]; /* GSUB/GPOS */
+ unsigned int stage[2]; /* GSUB/GPOS */
+ unsigned int shift;
+ hb_mask_t mask;
+ hb_mask_t _1_mask; /* mask for value=1, for quick access */
+
+ static int cmp (const feature_map_t *a, const feature_map_t *b)
+ { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
+ };
+
+ struct lookup_map_t {
+ unsigned int index;
+ hb_mask_t mask;
+
+ static int cmp (const lookup_map_t *a, const lookup_map_t *b)
+ { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
+ };
+
+ typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, hb_buffer_t *buffer, void *user_data);
+ typedef struct {
+ pause_func_t func;
+ void *user_data;
+ } pause_callback_t;
+
+ struct pause_map_t {
+ unsigned int num_lookups; /* Cumulative */
+ 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);
return map ? map->_1_mask : 0;
}
- inline hb_mask_t get_feature_index (unsigned int table_index, hb_tag_t feature_tag) const {
+ 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]; }
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 */
- unsigned int stage[2]; /* GSUB/GPOS */
- unsigned int shift;
- hb_mask_t mask;
- hb_mask_t _1_mask; /* mask for value=1, for quick access */
-
- static int cmp (const feature_map_t *a, const feature_map_t *b)
- { return a->tag < b->tag ? -1 : a->tag > b->tag ? 1 : 0; }
- };
-
- struct lookup_map_t {
- unsigned int index;
- hb_mask_t mask;
-
- static int cmp (const lookup_map_t *a, const lookup_map_t *b)
- { return a->index < b->index ? -1 : a->index > b->index ? 1 : 0; }
- };
- typedef void (*pause_func_t) (const hb_ot_map_t *map, void *face_or_font, hb_buffer_t *buffer, void *user_data);
- typedef struct {
- pause_func_t func;
- void *user_data;
- } pause_callback_t;
-
- struct pause_map_t {
- unsigned int num_lookups; /* Cumulative */
- pause_callback_t callback;
- };
+ private:
HB_INTERNAL void add_lookups (hb_face_t *face,
unsigned int table_index,
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 < 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++)
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]++;
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;
-
- 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);
-
- 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;
-
- offset += len;
- } while (len == ARRAY_LENGTH (lookup_indices));
-
- return false;
-}
+ 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);
+ }
+
+ 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;
+ };
+
+ 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')) {}
+
+ 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. */
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;
}
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;
if ((FLAG (cat) & CONSONANT_FLAGS))
{
- pos = consonant_position (u, map, font);
+ pos = consonant_position (u, closure, font);
if (is_ra (u))
cat = OT_Ra;
}
/* 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