mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-12 16:23:01 +00:00
Merge pull request #5040 from harfbuzz/aat-set
[aat] Speed up subchain skipping using exact sets
This commit is contained in:
commit
b30c65e271
9 changed files with 75 additions and 33 deletions
|
@ -63,10 +63,10 @@ struct hb_aat_apply_context_t :
|
|||
const ankr *ankr_table;
|
||||
const OT::GDEF *gdef_table;
|
||||
const hb_sorted_vector_t<hb_aat_map_t::range_flags_t> *range_flags = nullptr;
|
||||
hb_set_digest_t buffer_digest = hb_set_digest_t::full ();
|
||||
hb_set_t buffer_digest;
|
||||
const hb_set_t *left_set = nullptr;
|
||||
const hb_set_t *right_set = nullptr;
|
||||
hb_set_digest_t machine_glyph_set = hb_set_digest_t::full ();
|
||||
const hb_set_t *machine_glyph_set = nullptr;
|
||||
hb_aat_class_cache_t *machine_class_cache = nullptr;
|
||||
hb_mask_t subtable_flags = 0;
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ struct RearrangementSubtable
|
|||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.intersects (c->machine_glyph_set))
|
||||
!c->buffer_digest.may_intersect (*c->machine_glyph_set))
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
|
@ -340,7 +340,7 @@ struct ContextualSubtable
|
|||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.intersects (c->machine_glyph_set))
|
||||
!c->buffer_digest.may_intersect (*c->machine_glyph_set))
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
|
@ -606,7 +606,7 @@ struct LigatureSubtable
|
|||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.intersects (c->machine_glyph_set))
|
||||
!c->buffer_digest.may_intersect (*c->machine_glyph_set))
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
|
@ -885,7 +885,7 @@ struct InsertionSubtable
|
|||
StateTableDriver<Types, EntryData> driver (machine, c->face);
|
||||
|
||||
if (driver.is_idempotent_on_all_out_of_bounds (&dc, c) &&
|
||||
!c->buffer_digest.intersects (c->machine_glyph_set))
|
||||
!c->buffer_digest.may_intersect (*c->machine_glyph_set))
|
||||
{
|
||||
(void) c->buffer->message (c->font, "skipped chainsubtable because no glyph matches");
|
||||
return_trace (false);
|
||||
|
@ -947,19 +947,21 @@ struct hb_accelerate_subtables_context_t :
|
|||
friend struct hb_aat_layout_lookup_accelerator_t;
|
||||
|
||||
public:
|
||||
hb_set_digest_t digest;
|
||||
hb_set_t glyph_set;
|
||||
mutable hb_aat_class_cache_t class_cache;
|
||||
|
||||
template <typename T>
|
||||
auto init_ (const T &obj_, unsigned num_glyphs, hb_priority<1>) HB_AUTO_RETURN
|
||||
(
|
||||
obj_.machine.collect_glyphs (this->digest, num_glyphs)
|
||||
)
|
||||
((
|
||||
glyph_set.init (),
|
||||
obj_.machine.collect_glyphs (glyph_set, num_glyphs)
|
||||
))
|
||||
|
||||
template <typename T>
|
||||
void init_ (const T &obj_, unsigned num_glyphs, hb_priority<0>)
|
||||
{
|
||||
digest = digest.full ();
|
||||
glyph_set.init ();
|
||||
glyph_set.invert ();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -972,6 +974,7 @@ struct hb_accelerate_subtables_context_t :
|
|||
void
|
||||
fini ()
|
||||
{
|
||||
glyph_set.fini ();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1185,7 +1188,7 @@ struct Chain
|
|||
hb_map ([subtable_flags] (const hb_aat_map_t::range_flags_t _) -> bool { return subtable_flags & (_.flags); })))
|
||||
goto skip;
|
||||
c->subtable_flags = subtable_flags;
|
||||
c->machine_glyph_set = accel ? accel->subtables[i].digest : hb_set_digest_t::full ();
|
||||
c->machine_glyph_set = accel ? &accel->subtables[i].glyph_set : &Null(hb_set_t);
|
||||
c->machine_class_cache = accel ? &accel->subtables[i].class_cache : nullptr;
|
||||
|
||||
if (!(subtable->get_coverage() & ChainSubtable<Types>::AllDirections) &&
|
||||
|
@ -1416,7 +1419,7 @@ struct mortmorx
|
|||
|
||||
c->buffer->unsafe_to_concat ();
|
||||
|
||||
c->buffer_digest = c->buffer->digest ();
|
||||
c->buffer_digest = c->buffer->set ();
|
||||
|
||||
c->set_lookup_index (0);
|
||||
const Chain<Types> *chain = &firstChain;
|
||||
|
|
|
@ -227,6 +227,13 @@ struct hb_bit_page_t
|
|||
return false;
|
||||
return true;
|
||||
}
|
||||
bool may_intersect (const hb_bit_page_t &other) const
|
||||
{
|
||||
for (unsigned i = 0; i < len (); i++)
|
||||
if (v[i] & other.v[i])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
|
||||
bool is_subset (const hb_bit_page_t &larger_page) const
|
||||
{
|
||||
|
|
|
@ -139,6 +139,9 @@ struct hb_bit_set_invertible_t
|
|||
hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool may_intersect (const hb_bit_set_invertible_t &other) const
|
||||
{ return inverted || other.inverted || s.may_intersect (other.s); }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
|
|
|
@ -297,9 +297,9 @@ struct hb_bit_set_t
|
|||
unsigned int write_index = 0;
|
||||
for (unsigned int i = 0; i < page_map.length; i++)
|
||||
{
|
||||
int m = (int) page_map[i].major;
|
||||
int m = (int) page_map.arrayZ[i].major;
|
||||
if (m < ds || de < m)
|
||||
page_map[write_index++] = page_map[i];
|
||||
page_map.arrayZ[write_index++] = page_map.arrayZ[i];
|
||||
}
|
||||
compact (compact_workspace, write_index);
|
||||
resize (write_index);
|
||||
|
@ -358,6 +358,26 @@ struct hb_bit_set_t
|
|||
hb_bit_set_t& operator << (const hb_codepoint_pair_t& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool may_intersect (const hb_bit_set_t &other) const
|
||||
{
|
||||
unsigned int na = pages.length;
|
||||
unsigned int nb = other.pages.length;
|
||||
|
||||
unsigned int a = 0, b = 0;
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major &&
|
||||
page_at (a).may_intersect (other.page_at (b)))
|
||||
return true;
|
||||
|
||||
if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
|
||||
a++;
|
||||
else
|
||||
b++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{
|
||||
hb_codepoint_t c = first - 1;
|
||||
|
@ -389,7 +409,7 @@ struct hb_bit_set_t
|
|||
{
|
||||
if (page_at (a).is_empty ()) { a++; continue; }
|
||||
if (other.page_at (b).is_empty ()) { b++; continue; }
|
||||
if (page_map[a].major != other.page_map[b].major ||
|
||||
if (page_map.arrayZ[a].major != other.page_map.arrayZ[b].major ||
|
||||
!page_at (a).is_equal (other.page_at (b)))
|
||||
return false;
|
||||
a++;
|
||||
|
@ -412,8 +432,8 @@ struct hb_bit_set_t
|
|||
uint32_t spi = 0;
|
||||
for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
|
||||
{
|
||||
uint32_t spm = page_map[spi].major;
|
||||
uint32_t lpm = larger_set.page_map[lpi].major;
|
||||
uint32_t spm = page_map.arrayZ[spi].major;
|
||||
uint32_t lpm = larger_set.page_map.arrayZ[lpi].major;
|
||||
auto sp = page_at (spi);
|
||||
|
||||
if (spm < lpm && !sp.is_empty ())
|
||||
|
@ -503,7 +523,7 @@ struct hb_bit_set_t
|
|||
|
||||
for (; a < na && b < nb; )
|
||||
{
|
||||
if (page_map[a].major == other.page_map[b].major)
|
||||
if (page_map.arrayZ[a].major == other.page_map.arrayZ[b].major)
|
||||
{
|
||||
if (!passthru_left)
|
||||
{
|
||||
|
@ -512,7 +532,7 @@ struct hb_bit_set_t
|
|||
// passthru_left is set since no left side pages will be removed
|
||||
// in that case.
|
||||
if (write_index < a)
|
||||
page_map[write_index] = page_map[a];
|
||||
page_map.arrayZ[write_index] = page_map.arrayZ[a];
|
||||
write_index++;
|
||||
}
|
||||
|
||||
|
@ -520,7 +540,7 @@ struct hb_bit_set_t
|
|||
a++;
|
||||
b++;
|
||||
}
|
||||
else if (page_map[a].major < other.page_map[b].major)
|
||||
else if (page_map.arrayZ[a].major < other.page_map.arrayZ[b].major)
|
||||
{
|
||||
if (passthru_left)
|
||||
count++;
|
||||
|
@ -765,8 +785,8 @@ struct hb_bit_set_t
|
|||
unsigned int initial_size = size;
|
||||
for (unsigned int i = start_page; i < page_map.length && size; i++)
|
||||
{
|
||||
uint32_t base = major_start (page_map[i].major);
|
||||
unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
|
||||
uint32_t base = major_start (page_map.arrayZ[i].major);
|
||||
unsigned int n = pages[page_map.arrayZ[i].index].write (base, start_page_value, out, size);
|
||||
out += n;
|
||||
size -= n;
|
||||
start_page_value = 0;
|
||||
|
@ -814,8 +834,8 @@ struct hb_bit_set_t
|
|||
hb_codepoint_t next_value = codepoint + 1;
|
||||
for (unsigned int i=start_page; i<page_map.length && size; i++)
|
||||
{
|
||||
uint32_t base = major_start (page_map[i].major);
|
||||
unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
|
||||
uint32_t base = major_start (page_map.arrayZ[i].major);
|
||||
unsigned int n = pages[page_map.arrayZ[i].index].write_inverted (base, start_page_value, out, size, &next_value);
|
||||
out += n;
|
||||
size -= n;
|
||||
start_page_value = 0;
|
||||
|
@ -846,8 +866,8 @@ struct hb_bit_set_t
|
|||
unsigned count = pages.length;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
const auto& map = page_map[i];
|
||||
const auto& page = pages[map.index];
|
||||
const auto& map = page_map.arrayZ[i];
|
||||
const auto& page = pages.arrayZ[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_min ();
|
||||
|
@ -859,8 +879,8 @@ struct hb_bit_set_t
|
|||
unsigned count = pages.length;
|
||||
for (signed i = count - 1; i >= 0; i--)
|
||||
{
|
||||
const auto& map = page_map[(unsigned) i];
|
||||
const auto& page = pages[map.index];
|
||||
const auto& map = page_map.arrayZ[(unsigned) i];
|
||||
const auto& page = pages.arrayZ[map.index];
|
||||
|
||||
if (!page.is_empty ())
|
||||
return map.major * page_t::PAGE_BITS + page.get_max ();
|
||||
|
@ -961,7 +981,7 @@ struct hb_bit_set_t
|
|||
return nullptr;
|
||||
|
||||
last_page_lookup = i;
|
||||
return &pages.arrayZ[page_map[i].index];
|
||||
return &pages.arrayZ[page_map.arrayZ[i].index];
|
||||
}
|
||||
page_t &page_at (unsigned int i)
|
||||
{
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "hb.hh"
|
||||
#include "hb-unicode.hh"
|
||||
#include "hb-set.hh"
|
||||
#include "hb-set-digest.hh"
|
||||
|
||||
|
||||
|
@ -194,7 +195,12 @@ struct hb_buffer_t
|
|||
hb_set_digest_t digest () const
|
||||
{
|
||||
hb_set_digest_t d;
|
||||
d.init ();
|
||||
d.add_array (&info[0].codepoint, len, sizeof (info[0]));
|
||||
return d;
|
||||
}
|
||||
hb_set_t set () const
|
||||
{
|
||||
hb_set_t d;
|
||||
d.add_array (&info[0].codepoint, len, sizeof (info[0]));
|
||||
return d;
|
||||
}
|
||||
|
|
|
@ -2033,7 +2033,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
* (plus some past glyphs).
|
||||
*
|
||||
* Only try applying the lookup if there is any overlap. */
|
||||
if (accel->digest.intersects (c.digest))
|
||||
if (accel->digest.may_intersect (c.digest))
|
||||
{
|
||||
c.set_lookup_index (lookup_index);
|
||||
c.set_lookup_mask (lookup.mask, false);
|
||||
|
|
|
@ -158,7 +158,7 @@ struct hb_set_digest_t
|
|||
return true;
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_digest_t &o) const
|
||||
bool may_intersect (const hb_set_digest_t &o) const
|
||||
{
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
if (!(masks[i] & o.masks[i]))
|
||||
|
|
|
@ -120,6 +120,9 @@ struct hb_sparseset_t
|
|||
hb_sparseset_t& operator << (const hb_codepoint_pair_t& range)
|
||||
{ add_range (range.first, range.second); return *this; }
|
||||
|
||||
bool may_intersect (const hb_sparseset_t &other) const
|
||||
{ return s.may_intersect (other.s); }
|
||||
|
||||
bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
|
||||
{ return s.intersects (first, last); }
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue