Index: third_party/harfbuzz-ng/src/hb-ot-map.cc |
diff --git a/third_party/harfbuzz-ng/src/hb-ot-map.cc b/third_party/harfbuzz-ng/src/hb-ot-map.cc |
index ca96ba98310a9e1b7230ff74e7459f558b8d3747..a54e306e8cf61a82963581719a7a5f1da6696fda 100644 |
--- a/third_party/harfbuzz-ng/src/hb-ot-map.cc |
+++ b/third_party/harfbuzz-ng/src/hb-ot-map.cc |
@@ -1,6 +1,6 @@ |
/* |
- * Copyright (C) 2009,2010 Red Hat, Inc. |
- * Copyright (C) 2010 Google, Inc. |
+ * Copyright © 2009,2010 Red Hat, Inc. |
+ * Copyright © 2010,2011 Google, Inc. |
* |
* This is part of HarfBuzz, a text shaping library. |
* |
@@ -30,7 +30,6 @@ |
#include "hb-ot-shape-private.hh" |
-HB_BEGIN_DECLS |
void |
@@ -39,76 +38,133 @@ hb_ot_map_t::add_lookups (hb_face_t *face, |
unsigned int feature_index, |
hb_mask_t mask) |
{ |
- unsigned int i = MAX_LOOKUPS - lookup_count[table_index]; |
- lookup_map_t *lookups = lookup_maps[table_index] + lookup_count[table_index]; |
+ 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, |
+ table_tags[table_index], |
+ feature_index, |
+ offset, &len, |
+ lookup_indices); |
+ |
+ for (unsigned int i = 0; i < len; i++) { |
+ hb_ot_map_t::lookup_map_t *lookup = lookups[table_index].push (); |
+ if (unlikely (!lookup)) |
+ return; |
+ lookup->mask = mask; |
+ lookup->index = lookup_indices[i]; |
+ } |
+ |
+ offset += len; |
+ } while (len == ARRAY_LENGTH (lookup_indices)); |
+} |
- unsigned int *lookup_indices = (unsigned int *) lookups; |
- hb_ot_layout_feature_get_lookup_indexes (face, |
- table_tags[table_index], |
- feature_index, |
- 0, &i, |
- lookup_indices); |
+void hb_ot_map_builder_t::add_feature (hb_tag_t tag, unsigned int value, bool global) |
+{ |
+ feature_info_t *info = feature_infos.push(); |
+ if (unlikely (!info)) return; |
+ info->tag = tag; |
+ info->seq = feature_infos.len; |
+ info->max_value = value; |
+ info->global = global; |
+ info->default_value = global ? value : 0; |
+ info->stage[0] = current_stage[0]; |
+ info->stage[1] = current_stage[1]; |
+} |
+ |
+void hb_ot_map_t::apply (unsigned int table_index, |
+ hb_ot_map_t::apply_lookup_func_t apply_lookup_func, |
+ void *face_or_font, |
+ hb_buffer_t *buffer) const |
+{ |
+ unsigned int i = 0; |
- lookup_count[table_index] += i; |
+ for (unsigned int pause_index = 0; pause_index < pauses[table_index].len; pause_index++) { |
+ const pause_map_t *pause = &pauses[table_index][pause_index]; |
+ for (; i < pause->num_lookups; i++) |
+ apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); |
- while (i--) { |
- lookups[i].mask = mask; |
- lookups[i].index = lookup_indices[i]; |
+ pause->callback.func (this, face_or_font, buffer, pause->callback.user_data); |
} |
+ |
+ for (; i < lookups[table_index].len; i++) |
+ apply_lookup_func (face_or_font, buffer, lookups[table_index][i].index, lookups[table_index][i].mask); |
} |
+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; |
+ } |
+ } |
+ |
+ current_stage[table_index]++; |
+} |
+ |
void |
-hb_ot_map_t::compile (hb_face_t *face, |
- const hb_segment_properties_t *props) |
+hb_ot_map_builder_t::compile (hb_face_t *face, |
+ const hb_segment_properties_t *props, |
+ hb_ot_map_t &m) |
{ |
- global_mask = 1; |
- lookup_count[0] = lookup_count[1] = 0; |
+ m.global_mask = 1; |
- if (!feature_count) |
+ if (!feature_infos.len) |
return; |
/* Fetch script/language indices for GSUB/GPOS. We need these later to skip |
* features not available in either table and not waste precious bits for them. */ |
- const hb_tag_t *script_tags; |
+ hb_tag_t script_tags[3] = {HB_TAG_NONE}; |
hb_tag_t language_tag; |
- script_tags = hb_ot_tags_from_script (props->script); |
+ hb_ot_tags_from_script (props->script, &script_tags[0], &script_tags[1]); |
language_tag = hb_ot_tag_from_language (props->language); |
unsigned int script_index[2], language_index[2]; |
for (unsigned int table_index = 0; table_index < 2; table_index++) { |
hb_tag_t table_tag = table_tags[table_index]; |
- hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index]); |
+ hb_ot_layout_table_choose_script (face, table_tag, script_tags, &script_index[table_index], &m.chosen_script[table_index]); |
hb_ot_layout_script_find_language (face, table_tag, script_index[table_index], language_tag, &language_index[table_index]); |
} |
/* Sort features and merge duplicates */ |
- qsort (feature_infos, feature_count, sizeof (feature_infos[0]), (hb_compare_func_t) feature_info_t::cmp); |
- unsigned int j = 0; |
- for (unsigned int i = 1; i < feature_count; i++) |
- if (feature_infos[i].tag != feature_infos[j].tag) |
- feature_infos[++j] = feature_infos[i]; |
- else { |
- if (feature_infos[i].global) |
- feature_infos[j] = feature_infos[i]; |
+ { |
+ feature_infos.sort (); |
+ unsigned int j = 0; |
+ for (unsigned int i = 1; i < feature_infos.len; i++) |
+ if (feature_infos[i].tag != feature_infos[j].tag) |
+ feature_infos[++j] = feature_infos[i]; |
else { |
- feature_infos[j].global = false; |
- feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value); |
+ if (feature_infos[i].global) { |
+ feature_infos[j].global = true; |
+ feature_infos[j].max_value = feature_infos[i].max_value; |
+ feature_infos[j].default_value = feature_infos[i].default_value; |
+ } else { |
+ feature_infos[j].global = false; |
+ feature_infos[j].max_value = MAX (feature_infos[j].max_value, feature_infos[i].max_value); |
+ } |
+ feature_infos[j].stage[0] = MIN (feature_infos[j].stage[0], feature_infos[i].stage[0]); |
+ feature_infos[j].stage[1] = MIN (feature_infos[j].stage[1], feature_infos[i].stage[1]); |
/* Inherit default_value from j */ |
} |
- } |
- feature_count = j + 1; |
+ feature_infos.shrink (j + 1); |
+ } |
/* Allocate bits now */ |
unsigned int next_bit = 1; |
- j = 0; |
- for (unsigned int i = 0; i < feature_count; i++) { |
+ for (unsigned int i = 0; i < feature_infos.len; i++) { |
const feature_info_t *info = &feature_infos[i]; |
unsigned int bits_needed; |
@@ -136,11 +192,15 @@ hb_ot_map_t::compile (hb_face_t *face, |
continue; |
- feature_map_t *map = &feature_maps[j++]; |
+ hb_ot_map_t::feature_map_t *map = m.features.push (); |
+ if (unlikely (!map)) |
+ break; |
map->tag = info->tag; |
map->index[0] = feature_index[0]; |
map->index[1] = feature_index[1]; |
+ map->stage[0] = info->stage[0]; |
+ map->stage[1] = info->stage[1]; |
if (info->global && info->max_value == 1) { |
/* Uses the global bit */ |
map->shift = 0; |
@@ -150,13 +210,16 @@ hb_ot_map_t::compile (hb_face_t *face, |
map->mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); |
next_bit += bits_needed; |
if (info->global) |
- global_mask |= (info->default_value << map->shift) & map->mask; |
+ m.global_mask |= (info->default_value << map->shift) & map->mask; |
} |
map->_1_mask = (1 << map->shift) & map->mask; |
} |
- feature_count = j; |
+ feature_infos.shrink (0); /* Done with these */ |
+ |
+ add_gsub_pause (NULL, NULL); |
+ add_gpos_pause (NULL, NULL); |
for (unsigned int table_index = 0; table_index < 2; table_index++) { |
hb_tag_t table_tag = table_tags[table_index]; |
@@ -169,26 +232,43 @@ hb_ot_map_t::compile (hb_face_t *face, |
script_index[table_index], |
language_index[table_index], |
&required_feature_index)) |
- add_lookups (face, table_index, required_feature_index, 1); |
- |
- for (unsigned i = 0; i < feature_count; i++) |
- add_lookups (face, table_index, feature_maps[i].index[table_index], feature_maps[i].mask); |
+ m.add_lookups (face, table_index, required_feature_index, 1); |
- /* Sort lookups and merge duplicates */ |
- qsort (lookup_maps[table_index], lookup_count[table_index], sizeof (lookup_maps[table_index][0]), (hb_compare_func_t) lookup_map_t::cmp); |
- if (lookup_count[table_index]) |
+ unsigned int pause_index = 0; |
+ unsigned int last_num_lookups = 0; |
+ for (unsigned stage = 0; stage < current_stage[table_index]; stage++) |
{ |
- unsigned int j = 0; |
- for (unsigned int i = 1; i < lookup_count[table_index]; i++) |
- if (lookup_maps[table_index][i].index != lookup_maps[table_index][j].index) |
- lookup_maps[table_index][++j] = lookup_maps[table_index][i]; |
- else |
- lookup_maps[table_index][j].mask |= lookup_maps[table_index][i].mask; |
- j++; |
- lookup_count[table_index] = j; |
+ for (unsigned i = 0; i < m.features.len; i++) |
+ if (m.features[i].stage[table_index] == stage) |
+ m.add_lookups (face, table_index, m.features[i].index[table_index], m.features[i].mask); |
+ |
+ /* Sort lookups and merge duplicates */ |
+ if (last_num_lookups < m.lookups[table_index].len) |
+ { |
+ m.lookups[table_index].sort (last_num_lookups, m.lookups[table_index].len); |
+ |
+ unsigned int j = last_num_lookups; |
+ for (unsigned int i = j + 1; i < m.lookups[table_index].len; i++) |
+ if (m.lookups[table_index][i].index != m.lookups[table_index][j].index) |
+ m.lookups[table_index][++j] = m.lookups[table_index][i]; |
+ else |
+ m.lookups[table_index][j].mask |= m.lookups[table_index][i].mask; |
+ m.lookups[table_index].shrink (j + 1); |
+ } |
+ |
+ last_num_lookups = m.lookups[table_index].len; |
+ |
+ if (pause_index < pauses[table_index].len && pauses[table_index][pause_index].stage == stage) { |
+ hb_ot_map_t::pause_map_t *pause_map = m.pauses[table_index].push (); |
+ if (likely (pause_map)) { |
+ pause_map->num_lookups = last_num_lookups; |
+ pause_map->callback = pauses[table_index][pause_index].callback; |
+ } |
+ |
+ pause_index++; |
+ } |
} |
} |
} |
-HB_END_DECLS |