Add intersects() method to GSUB/GPOS lookups
This commit is contained in:
parent
61ce62e554
commit
7c9cfa2b40
|
@ -168,9 +168,8 @@ struct RangeRecord
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs) const {
|
||||
return glyphs->intersects (start, end);
|
||||
}
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return glyphs->intersects (start, end); }
|
||||
|
||||
template <typename set_t>
|
||||
inline bool add_coverage (set_t *glyphs) const {
|
||||
|
@ -767,9 +766,17 @@ struct CoverageFormat1
|
|||
return_trace (glyphArray.sanitize (c));
|
||||
}
|
||||
|
||||
inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
|
||||
return glyphs->has (glyphArray[index]);
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
/* TODO Speed up, using hb_set_next() and bsearch()? */
|
||||
unsigned int count = glyphArray.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (glyphs->has (glyphArray[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{ return glyphs->has (glyphArray[index]); }
|
||||
|
||||
template <typename set_t>
|
||||
inline bool add_coverage (set_t *glyphs) const {
|
||||
|
@ -857,7 +864,17 @@ struct CoverageFormat2
|
|||
return_trace (rangeRecord.sanitize (c));
|
||||
}
|
||||
|
||||
inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const {
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
/* TODO Speed up, using hb_set_next() and bsearch()? */
|
||||
unsigned int count = rangeRecord.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (rangeRecord[i].intersects (glyphs))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int count = rangeRecord.len;
|
||||
for (i = 0; i < count; i++) {
|
||||
|
@ -985,13 +1002,13 @@ struct Coverage
|
|||
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
/* TODO speed this up */
|
||||
for (hb_auto_t<Coverage::Iter> iter (*this); iter.more (); iter.next ())
|
||||
if (glyphs->has (iter.get_glyph ()))
|
||||
return true;
|
||||
return false;
|
||||
switch (u.format)
|
||||
{
|
||||
case 1: return u.format1.intersects (glyphs);
|
||||
case 2: return u.format2.intersects (glyphs);
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool intersects_coverage (const hb_set_t *glyphs, unsigned int index) const
|
||||
{
|
||||
switch (u.format)
|
||||
|
@ -1141,6 +1158,17 @@ struct ClassDefFormat1
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
/* TODO Speed up, using hb_set_next()? */
|
||||
hb_codepoint_t start = startGlyph;
|
||||
hb_codepoint_t end = startGlyph + classValue.len;
|
||||
for (hb_codepoint_t iter = startGlyph - 1;
|
||||
hb_set_next (glyphs, &iter) && iter < end;)
|
||||
if (classValue[iter - start])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
|
||||
unsigned int count = classValue.len;
|
||||
if (klass == 0)
|
||||
|
@ -1191,7 +1219,8 @@ struct ClassDefFormat2
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
inline bool add_coverage (set_t *glyphs) const {
|
||||
inline bool add_coverage (set_t *glyphs) const
|
||||
{
|
||||
unsigned int count = rangeRecord.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (rangeRecord[i].value)
|
||||
|
@ -1201,7 +1230,8 @@ struct ClassDefFormat2
|
|||
}
|
||||
|
||||
template <typename set_t>
|
||||
inline bool add_class (set_t *glyphs, unsigned int klass) const {
|
||||
inline bool add_class (set_t *glyphs, unsigned int klass) const
|
||||
{
|
||||
unsigned int count = rangeRecord.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
|
@ -1212,7 +1242,17 @@ struct ClassDefFormat2
|
|||
return true;
|
||||
}
|
||||
|
||||
inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
/* TODO Speed up, using hb_set_next() and bsearch()? */
|
||||
unsigned int count = rangeRecord.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (rangeRecord[i].intersects (glyphs))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const
|
||||
{
|
||||
unsigned int count = rangeRecord.len;
|
||||
if (klass == 0)
|
||||
{
|
||||
|
@ -1289,6 +1329,13 @@ struct ClassDef
|
|||
}
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs) const {
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.intersects (glyphs);
|
||||
case 2: return u.format2.intersects (glyphs);
|
||||
default:return false;
|
||||
}
|
||||
}
|
||||
inline bool intersects_class (const hb_set_t *glyphs, unsigned int klass) const {
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.intersects_class (glyphs, klass);
|
||||
|
|
|
@ -459,6 +459,9 @@ struct MarkArray : ArrayOf<MarkRecord> /* Array of MarkRecords--in Coverage orde
|
|||
|
||||
struct SinglePosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -466,9 +469,7 @@ struct SinglePosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -507,6 +508,9 @@ struct SinglePosFormat1
|
|||
|
||||
struct SinglePosFormat2
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -514,9 +518,7 @@ struct SinglePosFormat2
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -598,6 +600,24 @@ struct PairSet
|
|||
{
|
||||
friend struct PairPosFormat1;
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
unsigned int len1 = valueFormats[0].get_len ();
|
||||
unsigned int len2 = valueFormats[1].get_len ();
|
||||
unsigned int record_size = HBUINT16::static_size * (1 + len1 + len2);
|
||||
|
||||
const PairValueRecord *record = CastP<PairValueRecord> (arrayZ);
|
||||
unsigned int count = len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (glyphs->has (record->secondGlyph))
|
||||
return true;
|
||||
record = &StructAtOffset<const PairValueRecord> (record, record_size);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c,
|
||||
const ValueFormat *valueFormats) const
|
||||
{
|
||||
|
@ -652,7 +672,8 @@ struct PairSet
|
|||
return_trace (false);
|
||||
}
|
||||
|
||||
struct sanitize_closure_t {
|
||||
struct sanitize_closure_t
|
||||
{
|
||||
const void *base;
|
||||
const ValueFormat *valueFormats;
|
||||
unsigned int len1; /* valueFormats[0].get_len() */
|
||||
|
@ -681,6 +702,20 @@ struct PairSet
|
|||
|
||||
struct PairPosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
unsigned int count = pairSet.len;
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (glyphs->has (iter.get_glyph ()) &&
|
||||
(this+pairSet[iter.get_coverage ()]).intersects (glyphs, valueFormat))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -691,9 +726,7 @@ struct PairPosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -717,7 +750,8 @@ struct PairPosFormat1
|
|||
|
||||
unsigned int len1 = valueFormat[0].get_len ();
|
||||
unsigned int len2 = valueFormat[1].get_len ();
|
||||
PairSet::sanitize_closure_t closure = {
|
||||
PairSet::sanitize_closure_t closure =
|
||||
{
|
||||
this,
|
||||
valueFormat,
|
||||
len1,
|
||||
|
@ -747,6 +781,12 @@ struct PairPosFormat1
|
|||
|
||||
struct PairPosFormat2
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
return (this+coverage).intersects (glyphs) &&
|
||||
(this+classDef2).intersects (glyphs);
|
||||
}
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -755,9 +795,7 @@ struct PairPosFormat2
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -889,6 +927,9 @@ reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direc
|
|||
|
||||
struct CursivePosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -896,9 +937,7 @@ struct CursivePosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1047,6 +1086,10 @@ typedef AnchorMatrix BaseArray; /* base-major--
|
|||
|
||||
struct MarkBasePosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+baseCoverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -1055,9 +1098,7 @@ struct MarkBasePosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+markCoverage;
|
||||
}
|
||||
{ return this+markCoverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1161,6 +1202,10 @@ typedef OffsetListOf<LigatureAttach> LigatureArray;
|
|||
|
||||
struct MarkLigPosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+markCoverage).intersects (glyphs) &&
|
||||
(this+ligatureCoverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -1169,9 +1214,7 @@ struct MarkLigPosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+markCoverage;
|
||||
}
|
||||
{ return this+markCoverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1274,6 +1317,10 @@ typedef AnchorMatrix Mark2Array; /* mark2-major--
|
|||
|
||||
struct MarkMarkPosFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+mark1Coverage).intersects (glyphs) &&
|
||||
(this+mark2Coverage).intersects (glyphs); }
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
@ -1282,9 +1329,7 @@ struct MarkMarkPosFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+mark1Coverage;
|
||||
}
|
||||
{ return this+mark1Coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1467,6 +1512,12 @@ struct PosLookup : Lookup
|
|||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
inline hb_collect_glyphs_context_t::return_t collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
|
|
|
@ -37,6 +37,9 @@ namespace OT {
|
|||
|
||||
struct SingleSubstFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -64,9 +67,7 @@ struct SingleSubstFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -120,6 +121,9 @@ struct SingleSubstFormat1
|
|||
|
||||
struct SingleSubstFormat2
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -147,9 +151,7 @@ struct SingleSubstFormat2
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -160,14 +162,12 @@ struct SingleSubstFormat2
|
|||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (unlikely (index >= substitute.len)) return_trace (false);
|
||||
|
||||
glyph_id = substitute[index];
|
||||
c->replace_glyph (glyph_id);
|
||||
c->replace_glyph (substitute[index]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -325,6 +325,9 @@ struct Sequence
|
|||
|
||||
struct MultipleSubstFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -344,13 +347,11 @@ struct MultipleSubstFormat1
|
|||
if (unlikely (!(this+coverage).add_coverage (c->input))) return;
|
||||
unsigned int count = sequence.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
(this+sequence[i]).collect_glyphs (c);
|
||||
(this+sequence[i]).collect_glyphs (c);
|
||||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -440,12 +441,72 @@ struct MultipleSubst
|
|||
} u;
|
||||
};
|
||||
|
||||
struct AlternateSet
|
||||
{
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
unsigned int count = alternates.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->out->add (alternates[i]);
|
||||
}
|
||||
|
||||
typedef ArrayOf<GlyphID> AlternateSet; /* Array of alternate GlyphIDs--in
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
{
|
||||
TRACE_COLLECT_GLYPHS (this);
|
||||
c->output->add_array (alternates.arrayZ, alternates.len);
|
||||
}
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
unsigned int count = alternates.len;
|
||||
|
||||
if (unlikely (!count)) return_trace (false);
|
||||
|
||||
hb_mask_t glyph_mask = c->buffer->cur().mask;
|
||||
hb_mask_t lookup_mask = c->lookup_mask;
|
||||
|
||||
/* Note: This breaks badly if two features enabled this lookup together. */
|
||||
unsigned int shift = hb_ctz (lookup_mask);
|
||||
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
|
||||
|
||||
if (unlikely (alt_index > count || alt_index == 0)) return_trace (false);
|
||||
|
||||
c->replace_glyph (alternates[alt_index - 1]);
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
Supplier<GlyphID> &glyphs,
|
||||
unsigned int num_glyphs)
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
if (unlikely (!c->extend_min (*this))) return_trace (false);
|
||||
if (unlikely (!alternates.serialize (c, glyphs, num_glyphs))) return_trace (false);
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (alternates.sanitize (c));
|
||||
}
|
||||
|
||||
protected:
|
||||
ArrayOf<GlyphID>
|
||||
alternates; /* Array of alternate GlyphIDs--in
|
||||
* arbitrary order */
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (2, alternates);
|
||||
};
|
||||
|
||||
struct AlternateSubstFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{ return (this+coverage).intersects (glyphs); }
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -454,12 +515,8 @@ struct AlternateSubstFormat1
|
|||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (c->glyphs->has (iter.get_glyph ())) {
|
||||
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
|
||||
unsigned int count = alt_set.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->out->add (alt_set[i]);
|
||||
}
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
(this+alternateSet[iter.get_coverage ()]).closure (c);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,15 +529,12 @@ struct AlternateSubstFormat1
|
|||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
const AlternateSet &alt_set = this+alternateSet[iter.get_coverage ()];
|
||||
c->output->add_array (alt_set.arrayZ, alt_set.len);
|
||||
(this+alternateSet[iter.get_coverage ()]).collect_glyphs (c);
|
||||
}
|
||||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -491,29 +545,11 @@ struct AlternateSubstFormat1
|
|||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
const AlternateSet &alt_set = this+alternateSet[index];
|
||||
|
||||
if (unlikely (!alt_set.len)) return_trace (false);
|
||||
|
||||
hb_mask_t glyph_mask = c->buffer->cur().mask;
|
||||
hb_mask_t lookup_mask = c->lookup_mask;
|
||||
|
||||
/* Note: This breaks badly if two features enabled this lookup together. */
|
||||
unsigned int shift = hb_ctz (lookup_mask);
|
||||
unsigned int alt_index = ((lookup_mask & glyph_mask) >> shift);
|
||||
|
||||
if (unlikely (alt_index > alt_set.len || alt_index == 0)) return_trace (false);
|
||||
|
||||
glyph_id = alt_set[alt_index - 1];
|
||||
|
||||
c->replace_glyph (glyph_id);
|
||||
|
||||
return_trace (true);
|
||||
return_trace ((this+alternateSet[index]).apply (c));
|
||||
}
|
||||
|
||||
inline bool serialize (hb_serialize_context_t *c,
|
||||
|
@ -591,6 +627,15 @@ struct AlternateSubst
|
|||
|
||||
struct Ligature
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
unsigned int count = component.len;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (!glyphs->has (component[i]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -694,6 +739,15 @@ struct Ligature
|
|||
|
||||
struct LigatureSet
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
unsigned int num_ligs = ligature.len;
|
||||
for (unsigned int i = 0; i < num_ligs; i++)
|
||||
if ((this+ligature[i]).intersects (glyphs))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -771,6 +825,20 @@ struct LigatureSet
|
|||
|
||||
struct LigatureSubstFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
unsigned int count = ligatureSet.len;
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (glyphs->has (iter.get_glyph ()) &&
|
||||
(this+ligatureSet[iter.get_coverage ()]).intersects (glyphs))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -798,9 +866,7 @@ struct LigatureSubstFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -815,9 +881,8 @@ struct LigatureSubstFormat1
|
|||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_codepoint_t glyph_id = c->buffer->cur().codepoint;
|
||||
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
unsigned int index = (this+coverage).get_coverage (c->buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
const LigatureSet &lig_set = this+ligatureSet[index];
|
||||
|
@ -923,6 +988,28 @@ struct ExtensionSubst : Extension<ExtensionSubst>
|
|||
|
||||
struct ReverseChainSingleSubstFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (!(this+coverage).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
||||
|
||||
unsigned int count;
|
||||
|
||||
count = backtrack.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!(this+backtrack[i]).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
count = lookahead.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!(this+lookahead[i]).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -973,9 +1060,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool would_apply (hb_would_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1035,7 +1120,7 @@ struct ReverseChainSingleSubstFormat1
|
|||
* beginning of table */
|
||||
OffsetArrayOf<Coverage>
|
||||
backtrack; /* Array of coverage tables
|
||||
* in backtracking sequence, in glyph
|
||||
* in backtracking sequence, in glyph
|
||||
* sequence order */
|
||||
OffsetArrayOf<Coverage>
|
||||
lookaheadX; /* Array of coverage tables
|
||||
|
@ -1146,6 +1231,12 @@ struct SubstLookup : Lookup
|
|||
return_trace (dispatch (c));
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
hb_intersects_context_t c (glyphs);
|
||||
return dispatch (&c);
|
||||
}
|
||||
|
||||
inline hb_closure_context_t::return_t closure (hb_closure_context_t *c, unsigned int this_index) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1311,11 +1402,11 @@ struct GSUB : GSUBGPOS
|
|||
inline bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
struct GSUB *out = c->serializer->start_embed<GSUB> ();
|
||||
//struct GSUB *out = c->serializer->start_embed<GSUB> ();
|
||||
if (unlikely (!GSUBGPOS::subset (c))) return_trace (false);
|
||||
/* TODO Replace following with c->iter_copy_and_subset()ish. */
|
||||
unsigned int count = get_lookup_count ();
|
||||
LookupList &outLookupList = out+out->lookupList;
|
||||
//LookupList &outLookupList = out+out->lookupList;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
//XXX if (unlikely (!outLookupList.arrayZ[i].subset (c, get_lookup (i), &outLookupList)))
|
||||
return_trace (false);
|
||||
|
|
|
@ -40,6 +40,23 @@
|
|||
namespace OT {
|
||||
|
||||
|
||||
struct hb_intersects_context_t :
|
||||
hb_dispatch_context_t<hb_intersects_context_t, bool, 0>
|
||||
{
|
||||
inline const char *get_name (void) { return "INTERSECTS"; }
|
||||
template <typename T>
|
||||
inline return_t dispatch (const T &obj) { return obj.intersects (this->glyphs); }
|
||||
static return_t default_return_value (void) { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
const hb_set_t *glyphs;
|
||||
unsigned int debug_depth;
|
||||
|
||||
hb_intersects_context_t (const hb_set_t *glyphs_) :
|
||||
glyphs (glyphs_),
|
||||
debug_depth (0) {}
|
||||
};
|
||||
|
||||
struct hb_closure_context_t :
|
||||
hb_dispatch_context_t<hb_closure_context_t, hb_void_t, HB_DEBUG_CLOSURE>
|
||||
{
|
||||
|
@ -49,15 +66,14 @@ struct hb_closure_context_t :
|
|||
inline return_t dispatch (const T &obj) { obj.closure (this); return HB_VOID; }
|
||||
static return_t default_return_value (void) { return HB_VOID; }
|
||||
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
|
||||
return_t recurse (unsigned int lookup_index)
|
||||
void recurse (unsigned int lookup_index)
|
||||
{
|
||||
if (unlikely (nesting_level_left == 0 || !recurse_func))
|
||||
return default_return_value ();
|
||||
return;
|
||||
|
||||
nesting_level_left--;
|
||||
recurse_func (this, lookup_index);
|
||||
nesting_level_left++;
|
||||
return HB_VOID;
|
||||
}
|
||||
|
||||
bool should_visit_lookup (unsigned int lookup_index)
|
||||
|
@ -146,10 +162,10 @@ struct hb_collect_glyphs_context_t :
|
|||
inline return_t dispatch (const T &obj) { obj.collect_glyphs (this); return HB_VOID; }
|
||||
static return_t default_return_value (void) { return HB_VOID; }
|
||||
bool stop_sublookup_iteration (return_t r HB_UNUSED) const { return false; }
|
||||
return_t recurse (unsigned int lookup_index)
|
||||
void recurse (unsigned int lookup_index)
|
||||
{
|
||||
if (unlikely (nesting_level_left == 0 || !recurse_func))
|
||||
return default_return_value ();
|
||||
return;
|
||||
|
||||
/* Note that GPOS sets recurse_func to nullptr already, so it doesn't get
|
||||
* past the previous check. For GSUB, we only want to collect the output
|
||||
|
@ -162,11 +178,11 @@ struct hb_collect_glyphs_context_t :
|
|||
*/
|
||||
|
||||
if (output == hb_set_get_empty ())
|
||||
return HB_VOID;
|
||||
return;
|
||||
|
||||
/* Return if new lookup was recursed to before. */
|
||||
if (recursed_lookups->has (lookup_index))
|
||||
return HB_VOID;
|
||||
return;
|
||||
|
||||
hb_set_t *old_before = before;
|
||||
hb_set_t *old_input = input;
|
||||
|
@ -183,7 +199,7 @@ struct hb_collect_glyphs_context_t :
|
|||
|
||||
recursed_lookups->add (lookup_index);
|
||||
|
||||
return HB_VOID;
|
||||
return;
|
||||
}
|
||||
|
||||
hb_face_t *face;
|
||||
|
@ -208,24 +224,16 @@ struct hb_collect_glyphs_context_t :
|
|||
after (glyphs_after ? glyphs_after : hb_set_get_empty ()),
|
||||
output (glyphs_output ? glyphs_output : hb_set_get_empty ()),
|
||||
recurse_func (nullptr),
|
||||
recursed_lookups (nullptr),
|
||||
recursed_lookups (hb_set_create ()),
|
||||
nesting_level_left (nesting_level_left_),
|
||||
debug_depth (0)
|
||||
{
|
||||
recursed_lookups = hb_set_create ();
|
||||
}
|
||||
~hb_collect_glyphs_context_t (void)
|
||||
{
|
||||
hb_set_destroy (recursed_lookups);
|
||||
}
|
||||
debug_depth (0) {}
|
||||
~hb_collect_glyphs_context_t (void) { hb_set_destroy (recursed_lookups); }
|
||||
|
||||
void set_recurse_func (recurse_func_t func) { recurse_func = func; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* XXX Can we remove this? */
|
||||
|
||||
template <typename set_t>
|
||||
struct hb_add_coverage_context_t :
|
||||
hb_dispatch_context_t<hb_add_coverage_context_t<set_t>, const Coverage &, HB_DEBUG_GET_COVERAGE>
|
||||
|
@ -599,7 +607,7 @@ struct hb_ot_apply_context_t :
|
|||
|
||||
|
||||
|
||||
typedef bool (*intersects_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
|
||||
typedef bool (*intersects_func_t) (const hb_set_t *glyphs, const HBUINT16 &value, const void *data);
|
||||
typedef void (*collect_glyphs_func_t) (hb_set_t *glyphs, const HBUINT16 &value, const void *data);
|
||||
typedef bool (*match_func_t) (hb_codepoint_t glyph_id, const HBUINT16 &value, const void *data);
|
||||
|
||||
|
@ -617,29 +625,29 @@ struct ContextApplyFuncs
|
|||
};
|
||||
|
||||
|
||||
static inline bool intersects_glyph (hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
|
||||
static inline bool intersects_glyph (const hb_set_t *glyphs, const HBUINT16 &value, const void *data HB_UNUSED)
|
||||
{
|
||||
return glyphs->has (value);
|
||||
}
|
||||
static inline bool intersects_class (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
|
||||
static inline bool intersects_class (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
|
||||
{
|
||||
const ClassDef &class_def = *reinterpret_cast<const ClassDef *>(data);
|
||||
return class_def.intersects_class (glyphs, value);
|
||||
}
|
||||
static inline bool intersects_coverage (hb_set_t *glyphs, const HBUINT16 &value, const void *data)
|
||||
static inline bool intersects_coverage (const hb_set_t *glyphs, const HBUINT16 &value, const void *data)
|
||||
{
|
||||
const OffsetTo<Coverage> &coverage = (const OffsetTo<Coverage>&)value;
|
||||
return (data+coverage).intersects (glyphs);
|
||||
}
|
||||
|
||||
static inline bool intersects_array (hb_closure_context_t *c,
|
||||
static inline bool intersects_array (const hb_set_t *glyphs,
|
||||
unsigned int count,
|
||||
const HBUINT16 values[],
|
||||
intersects_func_t intersects_func,
|
||||
const void *intersects_data)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (likely (!intersects_func (c->glyphs, values[i], intersects_data)))
|
||||
if (likely (!intersects_func (glyphs, values[i], intersects_data)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -1140,6 +1148,16 @@ struct ContextApplyLookupContext
|
|||
const void *match_data;
|
||||
};
|
||||
|
||||
static inline bool context_intersects (const hb_set_t *glyphs,
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT16 input[], /* Array of input values--start with second glyph */
|
||||
ContextClosureLookupContext &lookup_context)
|
||||
{
|
||||
return intersects_array (glyphs,
|
||||
inputCount ? inputCount - 1 : 0, input,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data);
|
||||
}
|
||||
|
||||
static inline void context_closure_lookup (hb_closure_context_t *c,
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT16 input[], /* Array of input values--start with second glyph */
|
||||
|
@ -1147,9 +1165,9 @@ static inline void context_closure_lookup (hb_closure_context_t *c,
|
|||
const LookupRecord lookupRecord[],
|
||||
ContextClosureLookupContext &lookup_context)
|
||||
{
|
||||
if (intersects_array (c,
|
||||
inputCount ? inputCount - 1 : 0, input,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data))
|
||||
if (context_intersects (c->glyphs,
|
||||
inputCount, input,
|
||||
lookup_context))
|
||||
recurse_lookups (c,
|
||||
lookupCount, lookupRecord);
|
||||
}
|
||||
|
@ -1201,6 +1219,13 @@ static inline bool context_apply_lookup (hb_ot_apply_context_t *c,
|
|||
|
||||
struct Rule
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
return context_intersects (glyphs,
|
||||
inputCount, inputZ,
|
||||
lookup_context);
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1261,6 +1286,15 @@ struct Rule
|
|||
|
||||
struct RuleSet
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs, ContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
unsigned int num_rules = rule.len;
|
||||
for (unsigned int i = 0; i < num_rules; i++)
|
||||
if ((this+rule[i]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c, ContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1318,23 +1352,42 @@ struct RuleSet
|
|||
|
||||
struct ContextFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
struct ContextClosureLookupContext lookup_context = {
|
||||
{intersects_glyph},
|
||||
nullptr
|
||||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (glyphs->has (iter.get_glyph ()) &&
|
||||
(this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
||||
const Coverage &cov = (this+coverage);
|
||||
|
||||
struct ContextClosureLookupContext lookup_context = {
|
||||
{intersects_glyph},
|
||||
nullptr
|
||||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (cov.intersects_coverage (c->glyphs, i)) {
|
||||
const RuleSet &rule_set = this+ruleSet[i];
|
||||
rule_set.closure (c, lookup_context);
|
||||
}
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
|
||||
}
|
||||
}
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
|
@ -1365,9 +1418,7 @@ struct ContextFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1405,6 +1456,27 @@ struct ContextFormat1
|
|||
|
||||
struct ContextFormat2
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (!(this+coverage).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
const ClassDef &class_def = this+classDef;
|
||||
|
||||
struct ContextClosureLookupContext lookup_context = {
|
||||
{intersects_class},
|
||||
&class_def
|
||||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (class_def.intersects_class (glyphs, i) &&
|
||||
(this+ruleSet[i]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1457,9 +1529,7 @@ struct ContextFormat2
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1501,6 +1571,20 @@ struct ContextFormat2
|
|||
|
||||
struct ContextFormat3
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (!(this+coverageZ[0]).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
struct ContextClosureLookupContext lookup_context = {
|
||||
{intersects_coverage},
|
||||
this
|
||||
};
|
||||
return context_intersects (glyphs,
|
||||
glyphCount, (const HBUINT16 *) (coverageZ + 1),
|
||||
lookup_context);
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1548,9 +1632,7 @@ struct ContextFormat3
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverageZ[0];
|
||||
}
|
||||
{ return this+coverageZ[0]; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1638,6 +1720,26 @@ struct ChainContextApplyLookupContext
|
|||
const void *match_data[3];
|
||||
};
|
||||
|
||||
static inline bool chain_context_intersects (const hb_set_t *glyphs,
|
||||
unsigned int backtrackCount,
|
||||
const HBUINT16 backtrack[],
|
||||
unsigned int inputCount, /* Including the first glyph (not matched) */
|
||||
const HBUINT16 input[], /* Array of input values--start with second glyph */
|
||||
unsigned int lookaheadCount,
|
||||
const HBUINT16 lookahead[],
|
||||
ChainContextClosureLookupContext &lookup_context)
|
||||
{
|
||||
return intersects_array (glyphs,
|
||||
backtrackCount, backtrack,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[0])
|
||||
&& intersects_array (glyphs,
|
||||
inputCount ? inputCount - 1 : 0, input,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[1])
|
||||
&& intersects_array (glyphs,
|
||||
lookaheadCount, lookahead,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[2]);
|
||||
}
|
||||
|
||||
static inline void chain_context_closure_lookup (hb_closure_context_t *c,
|
||||
unsigned int backtrackCount,
|
||||
const HBUINT16 backtrack[],
|
||||
|
@ -1649,15 +1751,11 @@ static inline void chain_context_closure_lookup (hb_closure_context_t *c,
|
|||
const LookupRecord lookupRecord[],
|
||||
ChainContextClosureLookupContext &lookup_context)
|
||||
{
|
||||
if (intersects_array (c,
|
||||
backtrackCount, backtrack,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[0])
|
||||
&& intersects_array (c,
|
||||
inputCount ? inputCount - 1 : 0, input,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[1])
|
||||
&& intersects_array (c,
|
||||
lookaheadCount, lookahead,
|
||||
lookup_context.funcs.intersects, lookup_context.intersects_data[2]))
|
||||
if (chain_context_intersects (c->glyphs,
|
||||
backtrackCount, backtrack,
|
||||
inputCount, input,
|
||||
lookaheadCount, lookahead,
|
||||
lookup_context))
|
||||
recurse_lookups (c,
|
||||
lookupCount, lookupRecord);
|
||||
}
|
||||
|
@ -1737,6 +1835,17 @@ static inline bool chain_context_apply_lookup (hb_ot_apply_context_t *c,
|
|||
|
||||
struct ChainRule
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
const HeadlessArrayOf<HBUINT16> &input = StructAfter<HeadlessArrayOf<HBUINT16> > (backtrack);
|
||||
const ArrayOf<HBUINT16> &lookahead = StructAfter<ArrayOf<HBUINT16> > (input);
|
||||
return chain_context_intersects (glyphs,
|
||||
backtrack.len, backtrack.arrayZ,
|
||||
input.len, input.arrayZ,
|
||||
lookahead.len, lookahead.arrayZ,
|
||||
lookup_context);
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1823,6 +1932,14 @@ struct ChainRule
|
|||
|
||||
struct ChainRuleSet
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs, ChainContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
unsigned int num_rules = rule.len;
|
||||
for (unsigned int i = 0; i < num_rules; i++)
|
||||
if ((this+rule[i]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
inline void closure (hb_closure_context_t *c, ChainContextClosureLookupContext &lookup_context) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -1877,10 +1994,28 @@ struct ChainRuleSet
|
|||
|
||||
struct ChainContextFormat1
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
struct ChainContextClosureLookupContext lookup_context = {
|
||||
{intersects_glyph},
|
||||
{nullptr, nullptr, nullptr}
|
||||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (glyphs->has (iter.get_glyph ()) &&
|
||||
(this+ruleSet[iter.get_coverage ()]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
const Coverage &cov = (this+coverage);
|
||||
|
||||
struct ChainContextClosureLookupContext lookup_context = {
|
||||
{intersects_glyph},
|
||||
|
@ -1888,11 +2023,13 @@ struct ChainContextFormat1
|
|||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (cov.intersects_coverage (c->glyphs, i)) {
|
||||
const ChainRuleSet &rule_set = this+ruleSet[i];
|
||||
rule_set.closure (c, lookup_context);
|
||||
}
|
||||
for (hb_auto_t<Coverage::Iter> iter (this+coverage); iter.more (); iter.next ())
|
||||
{
|
||||
if (unlikely (iter.get_coverage () >= count))
|
||||
break; /* Work around malicious fonts. https://github.com/harfbuzz/harfbuzz/issues/363 */
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
(this+ruleSet[iter.get_coverage ()]).closure (c, lookup_context);
|
||||
}
|
||||
}
|
||||
|
||||
inline void collect_glyphs (hb_collect_glyphs_context_t *c) const
|
||||
|
@ -1923,9 +2060,7 @@ struct ChainContextFormat1
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -1961,6 +2096,30 @@ struct ChainContextFormat1
|
|||
|
||||
struct ChainContextFormat2
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
if (!(this+coverage).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
const ClassDef &backtrack_class_def = this+backtrackClassDef;
|
||||
const ClassDef &input_class_def = this+inputClassDef;
|
||||
const ClassDef &lookahead_class_def = this+lookaheadClassDef;
|
||||
|
||||
struct ChainContextClosureLookupContext lookup_context = {
|
||||
{intersects_class},
|
||||
{&backtrack_class_def,
|
||||
&input_class_def,
|
||||
&lookahead_class_def}
|
||||
};
|
||||
|
||||
unsigned int count = ruleSet.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (input_class_def.intersects_class (glyphs, i) &&
|
||||
(this+ruleSet[i]).intersects (glyphs, lookup_context))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
@ -2027,9 +2186,7 @@ struct ChainContextFormat2
|
|||
}
|
||||
|
||||
inline const Coverage &get_coverage (void) const
|
||||
{
|
||||
return this+coverage;
|
||||
}
|
||||
{ return this+coverage; }
|
||||
|
||||
inline bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
|
@ -2088,6 +2245,25 @@ struct ChainContextFormat2
|
|||
|
||||
struct ChainContextFormat3
|
||||
{
|
||||
inline bool intersects (const hb_set_t *glyphs) const
|
||||
{
|
||||
const OffsetArrayOf<Coverage> &input = StructAfter<OffsetArrayOf<Coverage> > (backtrack);
|
||||
|
||||
if (!(this+input[0]).intersects (glyphs))
|
||||
return false;
|
||||
|
||||
const OffsetArrayOf<Coverage> &lookahead = StructAfter<OffsetArrayOf<Coverage> > (input);
|
||||
struct ChainContextClosureLookupContext lookup_context = {
|
||||
{intersects_coverage},
|
||||
{this, this, this}
|
||||
};
|
||||
return chain_context_intersects (glyphs,
|
||||
backtrack.len, (const HBUINT16 *) backtrack.arrayZ,
|
||||
input.len, (const HBUINT16 *) input.arrayZ + 1,
|
||||
lookahead.len, (const HBUINT16 *) lookahead.arrayZ,
|
||||
lookup_context);
|
||||
}
|
||||
|
||||
inline void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE (this);
|
||||
|
|
Loading…
Reference in New Issue