[HarfBuzz] harfbuzz-ng: Branch 'master' - 2 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Fri May 28 15:31:29 PDT 2010
src/hb-buffer-private.hh | 18 ++--
src/hb-buffer.cc | 17 ++--
src/hb-ot-shape.cc | 196 ++++++++++++++++++++++++++++++++---------------
3 files changed, 155 insertions(+), 76 deletions(-)
New commits:
commit 81c5e8724b740c6e42ed3a45e0574c7c5f3ad8e6
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Fri May 28 18:31:16 2010 -0400
Allow disabling default features
Patch from Jonathan Kew
diff --git a/src/hb-buffer-private.hh b/src/hb-buffer-private.hh
index d05322b..0232dc3 100644
--- a/src/hb-buffer-private.hh
+++ b/src/hb-buffer-private.hh
@@ -98,10 +98,11 @@ 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);
+_hb_buffer_set_masks (hb_buffer_t *buffer,
+ hb_mask_t value,
+ hb_mask_t mask,
+ unsigned int cluster_start,
+ unsigned int cluster_end);
struct _hb_buffer_t {
@@ -158,10 +159,11 @@ struct _hb_buffer_t {
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); }
+ inline void set_masks (hb_mask_t value,
+ hb_mask_t mask,
+ unsigned int cluster_start,
+ unsigned int cluster_end)
+ { _hb_buffer_set_masks (this, value, mask, cluster_start, cluster_end); }
};
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index a393b6b..b04466a 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -466,15 +466,18 @@ _hb_buffer_clear_masks (hb_buffer_t *buffer)
}
void
-_hb_buffer_or_masks (hb_buffer_t *buffer,
- hb_mask_t mask,
- unsigned int cluster_start,
- unsigned int cluster_end)
+_hb_buffer_set_masks (hb_buffer_t *buffer,
+ hb_mask_t value,
+ hb_mask_t mask,
+ unsigned int cluster_start,
+ unsigned int cluster_end)
{
+ hb_mask_t not_mask = ~mask;
+
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;
+ buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
return;
}
@@ -490,7 +493,7 @@ _hb_buffer_or_masks (hb_buffer_t *buffer,
}
unsigned int count = buffer->len;
for (unsigned int i = min; i < count && buffer->info[i].cluster < cluster_end; i++)
- buffer->info[i].mask |= mask;
+ buffer->info[i].mask = (buffer->info[i].mask & not_mask) | value;
}
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index 7343578..f998759 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -83,28 +83,6 @@ add_feature (hb_face_t *face,
}
}
-static hb_bool_t
-maybe_add_feature (hb_face_t *face,
- hb_tag_t table_tag,
- unsigned int script_index,
- unsigned int language_index,
- hb_tag_t feature_tag,
- hb_mask_t mask,
- lookup_map *lookups,
- unsigned int *num_lookups,
- unsigned int room_lookups)
-{
- unsigned int feature_index;
- if (hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
- feature_tag,
- &feature_index))
- {
- add_feature (face, table_tag, feature_index, mask, lookups, num_lookups, room_lookups);
- return TRUE;
- }
- return FALSE;
-}
-
static int
cmp_lookups (const void *p1, const void *p2)
{
@@ -114,6 +92,106 @@ cmp_lookups (const void *p1, const void *p2)
return a->index - b->index;
}
+
+#define MAX_FEATURES 100
+
+struct feature_info {
+ hb_tag_t tag;
+ unsigned int index;
+ unsigned int value;
+ hb_mask_t mask;
+};
+
+struct feature_setup_state {
+ hb_mask_t global_mask;
+ unsigned int next_bit;
+ unsigned int count;
+ feature_info info[MAX_FEATURES];
+};
+
+static void
+collect_feature_info(hb_buffer_t *buffer,
+ hb_face_t *face,
+ hb_tag_t table_tag,
+ unsigned int script_index,
+ unsigned int language_index,
+ const hb_feature_t &feature,
+ feature_setup_state &fss,
+ const hb_feature_t *features,
+ unsigned int num_features)
+{
+ if (fss.count == MAX_FEATURES)
+ return; // FIXME - make the feature_info array growable?
+
+ unsigned int i, feature_index;
+ if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
+ feature.tag, &feature_index))
+ return;
+
+ fss.info[fss.count].tag = feature.tag;
+ fss.info[fss.count].index = feature_index;
+
+ // check if we have already allocated mask bits for this feature tag
+ for (i = 0; i < fss.count; ++i)
+ {
+ if (fss.info[i].tag == feature.tag)
+ {
+ fss.info[fss.count].mask = fss.info[i].mask;
+ fss.info[fss.count].value = feature.value << _hb_ctz(fss.info[fss.count].mask);
+ if (feature.start == 0 && feature.end == (unsigned int) -1)
+ fss.global_mask |= fss.info[fss.count].value;
+ else
+ buffer->set_masks(fss.info[fss.count].value, fss.info[fss.count].mask, feature.start, feature.end);
+ ++fss.count;
+ return;
+ }
+ }
+
+ // check if the feature occurs in remaining user features, as it might have a larger value there
+ hb_bool_t always_on = (feature.value == 1 && feature.start == 0 && feature.end == (unsigned int)-1);
+ unsigned int max_value = feature.value;
+ for (i = 0; i < num_features; ++i)
+ {
+ if (features[i].tag != feature.tag)
+ continue;
+ if (features[i].value > max_value)
+ max_value = features[i].value;
+ else if (features[i].value == 0 && features[i].start == 0 && features[i].end == (unsigned int)-1)
+ max_value = 0;
+ }
+
+ if (always_on && max_value == 1)
+ {
+ fss.info[fss.count].value = 1;
+ fss.info[fss.count].mask = 1;
+ fss.global_mask |= 1;
+ ++fss.count;
+ return;
+ }
+
+ // need to allocate specific mask bit(s) for this feature
+ unsigned int bits_needed = _hb_bit_storage(max_value);
+ if (!bits_needed || fss.next_bit + bits_needed > 8 * sizeof (hb_mask_t))
+ {
+ fss.info[fss.count].value = 0;
+ fss.info[fss.count].mask = 0;
+ ++fss.count;
+ return; // feature is disabled, just omit it; or
+ // not enough bits available in the mask, ignore this feature :(
+ }
+
+ // store the newly-allocated mask (in case further feature requests use the same tag)
+ // and shift the value into the right position
+ fss.info[fss.count].value = feature.value << fss.next_bit;
+ fss.info[fss.count].mask = (1 << (fss.next_bit + bits_needed)) - (1 << fss.next_bit);
+ if (feature.start == 0 && feature.end == (unsigned int) -1)
+ fss.global_mask |= fss.info[fss.count].value;
+ else
+ buffer->set_masks(fss.info[fss.count].value, fss.info[fss.count].mask, feature.start, feature.end);
+ fss.next_bit += bits_needed;
+ ++fss.count;
+}
+
static void
setup_lookups (hb_face_t *face,
hb_buffer_t *buffer,
@@ -140,16 +218,29 @@ setup_lookups (hb_face_t *face,
&feature_index))
add_feature (face, table_tag, feature_index, 1, lookups, num_lookups, room_lookups);
- for (i = 0; i < ARRAY_LENGTH (default_features); i++)
- maybe_add_feature (face, table_tag, script_index, language_index, default_features[i], 1, lookups, num_lookups, room_lookups);
+ // for features that may be turned on/off or have value > 1,
+ // we need to allocate bits in the mask
+
+ feature_setup_state fss;
+ fss.global_mask = 0;
+ fss.next_bit = MASK_BITS_USED;
+ fss.count = 0;
+
+ hb_feature_t feature = { 0, 1, 0, (unsigned int)-1 };
switch (original_direction) {
case HB_DIRECTION_LTR:
- maybe_add_feature (face, table_tag, script_index, language_index, HB_TAG ('l','t','r','a'), 1, lookups, num_lookups, room_lookups);
- maybe_add_feature (face, table_tag, script_index, language_index, HB_TAG ('l','t','r','m'), 1, lookups, num_lookups, room_lookups);
+ feature.tag = HB_TAG ('l','t','r','a');
+ collect_feature_info(buffer, face, table_tag, script_index, language_index,
+ feature, fss, features, num_features);
+ feature.tag = HB_TAG ('l','t','r','m');
+ collect_feature_info(buffer, face, table_tag, script_index, language_index,
+ feature, fss, features, num_features);
break;
case HB_DIRECTION_RTL:
- maybe_add_feature (face, table_tag, script_index, language_index, HB_TAG ('r','t','l','a'), 1, lookups, num_lookups, room_lookups);
+ feature.tag = HB_TAG ('r','t','l','a');
+ collect_feature_info(buffer, face, table_tag, script_index, language_index,
+ feature, fss, features, num_features);
break;
case HB_DIRECTION_TTB:
case HB_DIRECTION_BTT:
@@ -157,44 +248,25 @@ setup_lookups (hb_face_t *face,
break;
}
- unsigned int next_bit = MASK_BITS_USED;
- hb_mask_t global_mask = 0;
- for (i = 0; i < num_features; i++)
+ for (i = 0; i < ARRAY_LENGTH (default_features); i++)
{
- hb_feature_t *feature = &features[i];
- if (!hb_ot_layout_language_find_feature (face, table_tag, script_index, language_index,
- feature->tag,
- &feature_index))
- continue;
-
- 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;
- }
-
- /* 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);
+ feature.tag = default_features[i];
+ collect_feature_info(buffer, face, table_tag, script_index, language_index,
+ feature, fss, features, num_features);
+ }
- if (feature->start == 0 && feature->end == (unsigned int) -1)
- global_mask |= value;
- else
- buffer->or_masks (mask, feature->start, feature->end);
+ for (i = 0; i < num_features; i++)
+ {
+ collect_feature_info(buffer, face, table_tag, script_index, language_index,
+ features[i], fss, features + i + 1, num_features - i - 1);
}
- if (global_mask)
- buffer->or_masks (global_mask, 0, (unsigned int) -1);
+ for (i = 0; i < fss.count; ++i)
+ if (fss.info[i].mask)
+ add_feature (face, table_tag, fss.info[i].index, fss.info[i].mask, lookups, num_lookups, room_lookups);
+
+ if (fss.global_mask > 1) // the 0x01 bit was set by clear_masks()
+ buffer->set_masks (fss.global_mask, fss.global_mask, 0, (unsigned int) -1);
qsort (lookups, *num_lookups, sizeof (lookups[0]), cmp_lookups);
@@ -219,7 +291,7 @@ hb_ot_substitute_complex (hb_font_t *font HB_UNUSED,
unsigned int num_features,
hb_direction_t original_direction)
{
- lookup_map lookups[1000];
+ lookup_map lookups[1000]; /* FIXME */
unsigned int num_lookups = ARRAY_LENGTH (lookups);
unsigned int i;
commit 2163afbf35044f59dbf449254e65b8c9feb6cdeb
Author: Behdad Esfahbod <behdad at behdad.org>
Date: Thu May 27 14:04:15 2010 -0400
Add note about UTF-8 decoder
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index c20de77..a393b6b 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -607,6 +607,8 @@ hb_utf8_next (const uint8_t *text,
uint8_t c = *text;
unsigned int mask, len;
+ /* TODO check for overlong sequences? also: optimize? */
+
UTF8_COMPUTE (c, mask, len);
if (unlikely (!len || (unsigned int) (end - text) < len)) {
*unicode = -1;
More information about the HarfBuzz
mailing list