[GSUB/GPOS] Use Coverage digests as gatekeeper
Gives me a good 10% speedup for the Devanagari test case. Less so
for less lookup-intensive tests.
For the Devanagari test case, the false positive rate of the GSUB digest
is 4%.
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 3b0b881..34b9723 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -1551,27 +1551,15 @@
c->buffer->idx = 0;
- /* Fast path for lookups with one coverage only (which is most). */
- const Coverage *coverage = get_coverage ();
- if (coverage)
- while (c->buffer->idx < c->buffer->len)
- {
- if ((c->buffer->cur().mask & c->lookup_mask) &&
- coverage->get_coverage (c->buffer->cur().codepoint) != NOT_COVERED &&
- apply_once (c))
- ret = true;
- else
- c->buffer->idx++;
- }
- else
- while (c->buffer->idx < c->buffer->len)
- {
- if ((c->buffer->cur().mask & c->lookup_mask) &&
- apply_once (c))
- ret = true;
- else
- c->buffer->idx++;
- }
+ while (c->buffer->idx < c->buffer->len)
+ {
+ if ((c->buffer->cur().mask & c->lookup_mask) &&
+ c->digest->may_have (c->buffer->cur().codepoint) &&
+ apply_once (c))
+ ret = true;
+ else
+ c->buffer->idx++;
+ }
return ret;
}
diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh
index ca91a25..182f780 100644
--- a/src/hb-ot-layout-gsub-table.hh
+++ b/src/hb-ot-layout-gsub-table.hh
@@ -1219,28 +1219,15 @@
c->buffer->clear_output ();
c->buffer->idx = 0;
- /* Fast path for lookups with one coverage only (which is most). */
- const Coverage *coverage = get_coverage ();
- if (coverage)
- while (c->buffer->idx < c->buffer->len)
- {
- if ((c->buffer->cur().mask & c->lookup_mask) &&
- coverage->get_coverage (c->buffer->cur().codepoint) != NOT_COVERED &&
- apply_once (c))
- ret = true;
- else
- c->buffer->next_glyph ();
- }
- else
- while (c->buffer->idx < c->buffer->len)
- {
- if ((c->buffer->cur().mask & c->lookup_mask) &&
- apply_once (c))
- ret = true;
- else
- c->buffer->next_glyph ();
-
- }
+ while (c->buffer->idx < c->buffer->len)
+ {
+ if ((c->buffer->cur().mask & c->lookup_mask) &&
+ c->digest->may_have (c->buffer->cur().codepoint) &&
+ apply_once (c))
+ ret = true;
+ else
+ c->buffer->next_glyph ();
+ }
if (ret)
c->buffer->swap_buffers ();
}
@@ -1250,7 +1237,9 @@
c->buffer->idx = c->buffer->len - 1;
do
{
- if ((c->buffer->cur().mask & c->lookup_mask) && apply_once (c))
+ if ((c->buffer->cur().mask & c->lookup_mask) &&
+ c->digest->may_have (c->buffer->cur().codepoint) &&
+ apply_once (c))
ret = true;
else
c->buffer->idx--;
diff --git a/src/hb-ot-layout-gsubgpos-private.hh b/src/hb-ot-layout-gsubgpos-private.hh
index 1f20514..7a3f32e 100644
--- a/src/hb-ot-layout-gsubgpos-private.hh
+++ b/src/hb-ot-layout-gsubgpos-private.hh
@@ -31,6 +31,7 @@
#include "hb-buffer-private.hh"
#include "hb-ot-layout-gdef-table.hh"
+#include "hb-set-private.hh"
@@ -109,12 +110,14 @@
unsigned int debug_depth;
const GDEF &gdef;
bool has_glyph_classes;
+ const hb_set_digest_t *digest;
hb_apply_context_t (hb_font_t *font_,
hb_face_t *face_,
hb_buffer_t *buffer_,
- hb_mask_t lookup_mask_) :
+ hb_mask_t lookup_mask_,
+ const hb_set_digest_t *digest_) :
font (font_), face (face_), buffer (buffer_),
direction (buffer_->props.direction),
lookup_mask (lookup_mask_),
@@ -123,7 +126,8 @@
gdef (hb_ot_layout_from_face (face_) &&
!HB_SHAPER_DATA_IS_INVALID (hb_ot_layout_from_face (face_)) ?
*hb_ot_layout_from_face (face_)->gdef : Null(GDEF)),
- has_glyph_classes (gdef.has_glyph_classes ()) {}
+ has_glyph_classes (gdef.has_glyph_classes ()),
+ digest (digest_) {}
void set_lookup (const Lookup &l) {
lookup_props = l.get_props ();
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index fdbeb5b..d87a138 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -35,6 +35,7 @@
#include "hb-font-private.hh"
#include "hb-buffer-private.hh"
+#include "hb-set-private.hh"
/* buffer var allocations, used during the GSUB/GPOS processing */
@@ -168,6 +169,9 @@
const struct GDEF *gdef;
const struct GSUB *gsub;
const struct GPOS *gpos;
+
+ hb_set_digest_t *gsub_digests;
+ hb_set_digest_t *gpos_digests;
};
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 0d0dfa0..b680d9c 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -58,6 +58,24 @@
layout->gpos_blob = Sanitizer<GPOS>::sanitize (hb_face_reference_table (face, HB_OT_TAG_GPOS));
layout->gpos = Sanitizer<GPOS>::lock_instance (layout->gpos_blob);
+ layout->gsub_digests = (hb_set_digest_t *) calloc (layout->gsub->get_lookup_count (), sizeof (hb_set_digest_t));
+ layout->gpos_digests = (hb_set_digest_t *) calloc (layout->gpos->get_lookup_count (), sizeof (hb_set_digest_t));
+
+ if (unlikely ((layout->gsub->get_lookup_count() && !layout->gsub_digests) ||
+ (layout->gpos->get_lookup_count() && !layout->gpos_digests)))
+ {
+ _hb_ot_layout_destroy (layout);
+ return NULL;
+ }
+
+ unsigned int count;
+ count = layout->gsub->get_lookup_count();
+ for (unsigned int i = 0; i < count; i++)
+ layout->gsub->add_coverage (&layout->gsub_digests[i], i);
+ count = layout->gpos->get_lookup_count();
+ for (unsigned int i = 0; i < count; i++)
+ layout->gpos->add_coverage (&layout->gpos_digests[i], i);
+
return layout;
}
@@ -68,6 +86,9 @@
hb_blob_destroy (layout->gsub_blob);
hb_blob_destroy (layout->gpos_blob);
+ free (layout->gsub_digests);
+ free (layout->gpos_digests);
+
free (layout);
}
@@ -412,7 +433,7 @@
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_apply_context_t c (NULL, face, buffer, mask);
+ hb_apply_context_t c (NULL, face, buffer, mask, NULL);
return _get_gsub (face).substitute_lookup (&c, lookup_index);
}
@@ -422,7 +443,7 @@
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_apply_context_t c (NULL, face, buffer, mask);
+ hb_apply_context_t c (NULL, face, buffer, mask, &hb_ot_layout_from_face (face)->gsub_digests[lookup_index]);
return hb_ot_layout_from_face (face)->gsub->substitute_lookup (&c, lookup_index);
}
@@ -463,7 +484,7 @@
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_apply_context_t c (font, font->face, buffer, mask);
+ hb_apply_context_t c (font, font->face, buffer, mask, NULL);
return _get_gpos (font->face).position_lookup (&c, lookup_index);
}
@@ -473,7 +494,7 @@
unsigned int lookup_index,
hb_mask_t mask)
{
- hb_apply_context_t c (font, font->face, buffer, mask);
+ hb_apply_context_t c (font, font->face, buffer, mask, &hb_ot_layout_from_face (font->face)->gpos_digests[lookup_index]);
return hb_ot_layout_from_face (font->face)->gpos->position_lookup (&c, lookup_index);
}