From 1ce7b87c4d8d1ab3ec1d5198351d71b7199f7c64 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 21 May 2010 17:31:45 +0100 Subject: [PATCH] Cleanup bitmask allocation --- src/hb-buffer-private.hh | 16 +++++++++++ src/hb-buffer.cc | 36 ++++++++++++++++++++++++ src/hb-ot-shape.cc | 60 +++++++++++++++++----------------------- 3 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh index d89762723..d05322b8d 100644 --- a/src/hb-buffer-private.hh +++ b/src/hb-buffer-private.hh @@ -94,6 +94,15 @@ HB_INTERNAL void _hb_buffer_next_glyph (hb_buffer_t *buffer); +HB_INTERNAL void +_hb_buffer_clear_masks (hb_buffer_t *buffer); + +HB_INTERNAL void +_hb_buffer_or_masks (hb_buffer_t *buffer, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end); + struct _hb_buffer_t { hb_reference_count_t ref_count; @@ -147,6 +156,13 @@ struct _hb_buffer_t { unsigned short ligID = 0xFFFF) { _hb_buffer_add_output_glyph (this, glyph_index, component, ligID); } inline void replace_glyph (hb_codepoint_t glyph_index) { add_output_glyph (glyph_index); } + + inline void clear_masks (void) { _hb_buffer_clear_masks (this); } + inline void or_masks (hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end) + { _hb_buffer_or_masks (this, mask, cluster_start, cluster_end); } + }; diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc index 0b77919be..c20de778e 100644 --- a/src/hb-buffer.cc +++ b/src/hb-buffer.cc @@ -457,6 +457,42 @@ _hb_buffer_next_glyph (hb_buffer_t *buffer) buffer->i++; } +void +_hb_buffer_clear_masks (hb_buffer_t *buffer) +{ + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->info[i].mask = 1; +} + +void +_hb_buffer_or_masks (hb_buffer_t *buffer, + hb_mask_t mask, + unsigned int cluster_start, + unsigned int cluster_end) +{ + if (cluster_start == 0 && cluster_end == (unsigned int)-1) { + unsigned int count = buffer->len; + for (unsigned int i = 0; i < count; i++) + buffer->info[i].mask |= mask; + return; + } + + /* Binary search to find the start position and go from there. */ + unsigned int min = 0, max = buffer->len; + while (min < max) + { + unsigned int mid = min + ((max - min) / 2); + if (buffer->info[mid].cluster < cluster_start) + min = mid + 1; + else + max = mid; + } + unsigned int count = buffer->len; + for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++) + buffer->info[i].mask |= mask; +} + /* Public API again */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 3d8966c33..411087b51 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -117,54 +117,46 @@ setup_lookups (hb_face_t *face, } /* Clear buffer masks. */ - unsigned int count = buffer->len; - for (unsigned int i = 0; i < count; i++) - buffer->info[i].mask = 1; + buffer->clear_masks (); - unsigned int last_bit_used = 1; - unsigned int global_values = 0; + unsigned int next_bit = 1; + hb_mask_t global_mask = 0; for (i = 0; i < num_features; i++) { + hb_feature_t *feature = &features[i]; if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index, - features[i].tag, + feature->tag, &feature_index)) continue; - unsigned int bits_needed = _hb_bit_storage (features[i].value); - if (!bits_needed) + if (feature->value == 1 && feature->start == 0 && feature->end == (unsigned int) -1) { + add_feature (face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups); continue; - unsigned int mask = (1 << (last_bit_used + bits_needed)) - (1 << last_bit_used); - unsigned int value = features[i].value << last_bit_used; - last_bit_used += bits_needed; + } + + /* Allocate bits for the features */ + + unsigned int bits_needed = _hb_bit_storage (feature->value); + if (!bits_needed) + continue; /* Feature disabled */ + + if (next_bit + bits_needed > 8 * sizeof (hb_mask_t)) + continue; /* Oh well... */ + + unsigned int mask = (1 << (next_bit + bits_needed)) - (1 << next_bit); + unsigned int value = feature->value << next_bit; + next_bit += bits_needed; add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups); - if (features[i].start == 0 && features[i].end == (unsigned int)-1) - global_values |= value; + if (feature->start == 0 && feature->end == (unsigned int) -1) + global_mask |= value; else - { - unsigned int start = features[i].start, end = features[i].end; - unsigned int a = 0, b = buffer->len; - while (a < b) - { - unsigned int h = a + ((b - a) / 2); - if (buffer->info[h].cluster < start) - a = h + 1; - else - b = h; - } - unsigned int count = buffer->len; - for (unsigned int j = a; j < count && buffer->info[j].cluster < end; j++) - buffer->info[j].mask |= value; - } + buffer->or_masks (mask, feature->start, feature->end); } - if (global_values) - { - unsigned int count = buffer->len; - for (unsigned int j = 0; j < count; j++) - buffer->info[j].mask |= global_values; - } + if (global_mask) + buffer->or_masks (global_mask, 0, (unsigned int) -1); qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);