[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%.
This commit is contained in:
Behdad Esfahbod 2012-08-01 21:46:36 -04:00
parent a878c58a8f
commit 1336ecdf8e
5 changed files with 56 additions and 50 deletions

View File

@ -1551,27 +1551,15 @@ struct PosLookup : Lookup
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;
}

View File

@ -1219,28 +1219,15 @@ struct SubstLookup : Lookup
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 @@ struct SubstLookup : Lookup
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--;

View File

@ -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 @@ struct hb_apply_context_t
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 @@ struct hb_apply_context_t
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 ();

View File

@ -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 @@ struct hb_ot_layout_t
const struct GDEF *gdef;
const struct GSUB *gsub;
const struct GPOS *gpos;
hb_set_digest_t *gsub_digests;
hb_set_digest_t *gpos_digests;
};

View File

@ -58,6 +58,24 @@ _hb_ot_layout_create (hb_face_t *face)
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_ot_layout_destroy (hb_ot_layout_t *layout)
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 @@ hb_ot_layout_substitute_lookup (hb_face_t *face,
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 @@ hb_ot_layout_substitute_lookup_fast (hb_face_t *face,
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 @@ hb_ot_layout_position_lookup (hb_font_t *font,
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 @@ hb_ot_layout_position_lookup_fast (hb_font_t *font,
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);
}