summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/hb-ot-layout-common.hh')
-rw-r--r--thirdparty/harfbuzz/src/hb-ot-layout-common.hh266
1 files changed, 150 insertions, 116 deletions
diff --git a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
index f2a58028e3..b644df708d 100644
--- a/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
+++ b/thirdparty/harfbuzz/src/hb-ot-layout-common.hh
@@ -91,12 +91,12 @@ template<typename Iterator>
static inline void ClassDef_serialize (hb_serialize_context_t *c,
Iterator it);
-static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
- const hb_set_t &klasses,
- bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/);
+static void ClassDef_remap_and_serialize (
+ hb_serialize_context_t *c,
+ const hb_set_t &klasses,
+ bool use_class_zero,
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/);
struct hb_prune_langsys_context_t
@@ -1470,7 +1470,8 @@ struct CoverageFormat1
void next () { i++; }
hb_codepoint_t get_glyph () const { return c->glyphArray[i]; }
bool operator != (const iter_t& o) const
- { return i != o.i || c != o.c; }
+ { return i != o.i; }
+ iter_t __end__ () const { iter_t it; it.init (*c); it.i = c->glyphArray.len; return it; }
private:
const struct CoverageFormat1 *c;
@@ -1506,12 +1507,6 @@ struct CoverageFormat2
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (this))) return_trace (false);
- if (unlikely (!glyphs))
- {
- rangeRecord.len = 0;
- return_trace (true);
- }
-
/* TODO(iter) Write more efficiently? */
unsigned num_ranges = 0;
@@ -1524,6 +1519,7 @@ struct CoverageFormat2
}
if (unlikely (!rangeRecord.serialize (c, num_ranges))) return_trace (false);
+ if (!num_ranges) return_trace (true);
unsigned count = 0;
unsigned range = (unsigned) -1;
@@ -1552,25 +1548,26 @@ struct CoverageFormat2
bool intersects (const hb_set_t *glyphs) const
{
- /* TODO Speed up, using hb_set_next() and bsearch()? */
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
- if (range.intersects (glyphs))
- return true;
- return false;
+ return hb_any (+ hb_iter (rangeRecord.as_array ())
+ | hb_map ([glyphs] (const RangeRecord &range) { return range.intersects (glyphs); }));
}
bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
{
- /* TODO(iter) Rewrite as dagger. */
- for (const auto& range : rangeRecord.as_array ())
+ auto cmp = [] (const void *pk, const void *pr) -> int
{
- if (range.value <= index &&
- index < (unsigned int) range.value + (range.last - range.first) &&
- range.intersects (glyphs))
- return true;
- else if (index < range.value)
- return false;
- }
+ unsigned index = * (const unsigned *) pk;
+ const RangeRecord &range = * (const RangeRecord *) pr;
+ if (index < range.value) return -1;
+ if (index > (unsigned int) range.value + (range.last - range.first)) return +1;
+ return 0;
+ };
+
+ auto arr = rangeRecord.as_array ();
+ unsigned idx;
+ if (hb_bsearch_impl (&idx, index,
+ arr.arrayZ, arr.length, sizeof (arr[0]),
+ (int (*)(const void *_key, const void *_item)) cmp))
+ return arr.arrayZ[idx].intersects (glyphs);
return false;
}
@@ -1579,8 +1576,10 @@ struct CoverageFormat2
for (const auto& range : rangeRecord.as_array ())
{
if (!range.intersects (glyphs)) continue;
- for (hb_codepoint_t g = range.first; g <= range.last; g++)
- if (glyphs->has (g)) intersect_glyphs->add (g);
+ unsigned last = range.last;
+ for (hb_codepoint_t g = range.first - 1;
+ glyphs->next (&g) && g <= last;)
+ intersect_glyphs->add (g);
}
}
@@ -1632,6 +1631,8 @@ struct CoverageFormat2
return;
}
}
+ else
+ j = 0;
return;
}
coverage++;
@@ -1639,7 +1640,15 @@ struct CoverageFormat2
}
hb_codepoint_t get_glyph () const { return j; }
bool operator != (const iter_t& o) const
- { return i != o.i || j != o.j || c != o.c; }
+ { return i != o.i || j != o.j; }
+ iter_t __end__ () const
+ {
+ iter_t it;
+ it.init (*c);
+ it.i = c->rangeRecord.len;
+ it.j = 0;
+ return it;
+ }
private:
const struct CoverageFormat2 *c;
@@ -1708,18 +1717,17 @@ struct Coverage
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
-
auto it =
+ iter ()
- | hb_filter (glyphset)
- | hb_map_retains_sorting (glyph_map)
+ | hb_filter (c->plan->glyph_map_gsub)
+ | hb_map_retains_sorting (c->plan->glyph_map_gsub)
;
- bool ret = bool (it);
- Coverage_serialize (c->serializer, it);
- return_trace (ret);
+ // Cache the iterator result as it will be iterated multiple times
+ // by the serialize code below.
+ hb_sorted_vector_t<hb_codepoint_t> glyphs (it);
+ Coverage_serialize (c->serializer, glyphs.iter ());
+ return_trace (bool (glyphs));
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -1822,7 +1830,7 @@ struct Coverage
}
bool operator != (const iter_t& o) const
{
- if (format != o.format) return true;
+ if (unlikely (format != o.format)) return true;
switch (format)
{
case 1: return u.format1 != o.u.format1;
@@ -1830,6 +1838,18 @@ struct Coverage
default:return false;
}
}
+ iter_t __end__ () const
+ {
+ iter_t it = {};
+ it.format = format;
+ switch (format)
+ {
+ case 1: it.u.format1 = u.format1.__end__ (); break;
+ case 2: it.u.format2 = u.format2.__end__ (); break;
+ default: break;
+ }
+ return it;
+ }
private:
unsigned int format;
@@ -1857,16 +1877,14 @@ Coverage_serialize (hb_serialize_context_t *c,
{ c->start_embed<Coverage> ()->serialize (c, it); }
static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
- const hb_map_t &gid_klass_map,
- hb_sorted_vector_t<HBGlyphID16> &glyphs,
const hb_set_t &klasses,
bool use_class_zero,
- hb_map_t *klass_map /*INOUT*/)
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
+ hb_map_t *klass_map /*IN/OUT*/)
{
if (!klass_map)
{
- ClassDef_serialize (c, hb_zip (glyphs.iter (), + glyphs.iter ()
- | hb_map (gid_klass_map)));
+ ClassDef_serialize (c, glyph_and_klass.iter ());
return;
}
@@ -1883,17 +1901,15 @@ static void ClassDef_remap_and_serialize (hb_serialize_context_t *c,
idx++;
}
- auto it =
- + glyphs.iter ()
- | hb_map_retains_sorting ([&] (const HBGlyphID16& gid) -> hb_pair_t<hb_codepoint_t, unsigned>
- {
- unsigned new_klass = klass_map->get (gid_klass_map[gid]);
- return hb_pair ((hb_codepoint_t)gid, new_klass);
- })
- ;
- c->propagate_error (glyphs, klasses);
- ClassDef_serialize (c, it);
+ for (unsigned i = 0; i < glyph_and_klass.length; i++)
+ {
+ hb_codepoint_t klass = glyph_and_klass[i].second;
+ glyph_and_klass[i].second = klass_map->get (klass);
+ }
+
+ c->propagate_error (glyph_and_klass, klasses);
+ ClassDef_serialize (c, glyph_and_klass.iter ());
}
/*
@@ -1949,36 +1965,37 @@ struct ClassDefFormat1
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
hb_codepoint_t start = startGlyph;
hb_codepoint_t end = start + classValue.len;
- for (const hb_codepoint_t gid : + hb_range (start, end)
- | hb_filter (glyphset))
+ for (const hb_codepoint_t gid : + hb_range (start, end))
{
+ hb_codepoint_t new_gid = glyph_map[gid];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has(gid)) continue;
unsigned klass = classValue[gid - start];
if (!klass) continue;
- glyphs.push (glyph_map[gid]);
- gid_org_klass_map.set (glyph_map[gid], klass);
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
unsigned glyph_count = glyph_filter
- ? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ ? hb_len (hb_iter (glyph_map.keys()) | hb_filter (glyph_filter))
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2044,10 +2061,9 @@ struct ClassDefFormat1
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const HBUINT16 *arr = classValue.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i] == k && glyphs->has (startGlyph + i))
+ if (arr[i] == klass && glyphs->has (startGlyph + i))
return true;
return false;
}
@@ -2057,17 +2073,32 @@ struct ClassDefFormat1
unsigned count = classValue.len;
if (klass == 0)
{
- hb_codepoint_t endGlyph = startGlyph + count -1;
- for (hb_codepoint_t g : glyphs->iter ())
- if (g < startGlyph || g > endGlyph)
- intersect_glyphs->add (g);
+ unsigned start_glyph = startGlyph;
+ for (unsigned g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g) && g < start_glyph;)
+ intersect_glyphs->add (g);
+
+ for (unsigned g = startGlyph + count - 1;
+ hb_set_next (glyphs, &g);)
+ intersect_glyphs->add (g);
return;
}
for (unsigned i = 0; i < count; i++)
if (classValue[i] == klass && glyphs->has (startGlyph + i))
- intersect_glyphs->add (startGlyph + i);
+ intersect_glyphs->add (startGlyph + i);
+
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ unsigned start_glyph = startGlyph;
+ unsigned end_glyph = start_glyph + count;
+ for (unsigned g = startGlyph - 1;
+ hb_set_next (glyphs, &g) && g < end_glyph;)
+ if (classValue.arrayZ[g - start_glyph] == klass)
+ intersect_glyphs->add (g);
+#endif
}
void intersected_classes (const hb_set_t *glyphs, hb_set_t *intersect_classes) const
@@ -2167,12 +2198,10 @@ struct ClassDefFormat2
const Coverage* glyph_filter = nullptr) const
{
TRACE_SUBSET (this);
- const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
- const hb_map_t &glyph_map = *c->plan->glyph_map;
+ const hb_map_t &glyph_map = *c->plan->glyph_map_gsub;
- hb_sorted_vector_t<HBGlyphID16> glyphs;
+ hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> glyph_and_klass;
hb_set_t orig_klasses;
- hb_map_t gid_org_klass_map;
unsigned count = rangeRecord.len;
for (unsigned i = 0; i < count; i++)
@@ -2183,21 +2212,26 @@ struct ClassDefFormat2
hb_codepoint_t end = rangeRecord[i].last + 1;
for (hb_codepoint_t g = start; g < end; g++)
{
- if (!glyphset.has (g)) continue;
+ hb_codepoint_t new_gid = glyph_map[g];
+ if (new_gid == HB_MAP_VALUE_INVALID) continue;
if (glyph_filter && !glyph_filter->has (g)) continue;
- glyphs.push (glyph_map[g]);
- gid_org_klass_map.set (glyph_map[g], klass);
+
+ glyph_and_klass.push (hb_pair (new_gid, klass));
orig_klasses.add (klass);
}
}
+ const hb_set_t& glyphset = *c->plan->glyphset_gsub ();
unsigned glyph_count = glyph_filter
? hb_len (hb_iter (glyphset) | hb_filter (glyph_filter))
- : glyphset.get_population ();
- use_class_zero = use_class_zero && glyph_count <= gid_org_klass_map.get_population ();
- ClassDef_remap_and_serialize (c->serializer, gid_org_klass_map,
- glyphs, orig_klasses, use_class_zero, klass_map);
- return_trace (keep_empty_table || (bool) glyphs);
+ : glyph_map.get_population ();
+ use_class_zero = use_class_zero && glyph_count <= glyph_and_klass.length;
+ ClassDef_remap_and_serialize (c->serializer,
+ orig_klasses,
+ use_class_zero,
+ glyph_and_klass,
+ klass_map);
+ return_trace (keep_empty_table || (bool) glyph_and_klass);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2263,10 +2297,9 @@ struct ClassDefFormat2
}
/* TODO Speed up, using set overlap first? */
/* TODO(iter) Rewrite as dagger. */
- HBUINT16 k {klass};
const RangeRecord *arr = rangeRecord.arrayZ;
for (unsigned int i = 0; i < count; i++)
- if (arr[i].value == k && arr[i].intersects (glyphs))
+ if (arr[i].value == klass && arr[i].intersects (glyphs))
return true;
return false;
}
@@ -2279,43 +2312,44 @@ struct ClassDefFormat2
hb_codepoint_t g = HB_SET_VALUE_INVALID;
for (unsigned int i = 0; i < count; i++)
{
- if (!hb_set_next (glyphs, &g))
- break;
- while (g != HB_SET_VALUE_INVALID && g < rangeRecord[i].first)
- {
- intersect_glyphs->add (g);
- hb_set_next (glyphs, &g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
+ while (g < rangeRecord[i].first)
+ {
+ intersect_glyphs->add (g);
+ if (!hb_set_next (glyphs, &g))
+ goto done;
}
g = rangeRecord[i].last;
}
- while (g != HB_SET_VALUE_INVALID && hb_set_next (glyphs, &g))
- intersect_glyphs->add (g);
+ while (hb_set_next (glyphs, &g))
+ intersect_glyphs->add (g);
+ done:
return;
}
- hb_codepoint_t g = HB_SET_VALUE_INVALID;
+#if 0
+ /* The following implementation is faster asymptotically, but slower
+ * in practice. */
+ if ((count >> 3) > glyphs->get_population ())
+ {
+ for (hb_codepoint_t g = HB_SET_VALUE_INVALID;
+ hb_set_next (glyphs, &g);)
+ if (rangeRecord.as_array ().bfind (g))
+ intersect_glyphs->add (g);
+ return;
+ }
+#endif
+
for (unsigned int i = 0; i < count; i++)
{
if (rangeRecord[i].value != klass) continue;
- if (g != HB_SET_VALUE_INVALID)
- {
- if (g >= rangeRecord[i].first &&
- g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- if (g > rangeRecord[i].last)
- continue;
- }
-
- g = rangeRecord[i].first - 1;
- while (hb_set_next (glyphs, &g))
- {
- if (g >= rangeRecord[i].first && g <= rangeRecord[i].last)
- intersect_glyphs->add (g);
- else if (g > rangeRecord[i].last)
- break;
- }
+ unsigned end = rangeRecord[i].last + 1;
+ for (hb_codepoint_t g = rangeRecord[i].first - 1;
+ hb_set_next (glyphs, &g) && g < end;)
+ intersect_glyphs->add (g);
}
}