Flesh out closure() for GSUB
The GSUBGPOS part still missing.
This commit is contained in:
parent
0da132bde4
commit
c64ddab3c3
@ -355,10 +355,11 @@ struct CoverageFormat1
|
||||
}
|
||||
|
||||
struct Iter {
|
||||
void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
|
||||
bool more (void) { return i < c->glyphArray.len; }
|
||||
void next (void) { i++; }
|
||||
uint16_t get (void) { return c->glyphArray[i]; }
|
||||
inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
|
||||
inline bool more (void) { return i < c->glyphArray.len; }
|
||||
inline void next (void) { i++; }
|
||||
inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
|
||||
inline uint16_t get_coverage (void) { return i; }
|
||||
|
||||
private:
|
||||
const struct CoverageFormat1 *c;
|
||||
@ -394,9 +395,15 @@ struct CoverageFormat2
|
||||
}
|
||||
|
||||
struct Iter {
|
||||
void init (const CoverageFormat2 &c_) { c = &c_; i = 0; j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; }
|
||||
bool more (void) { return i < c->rangeRecord.len; }
|
||||
void next (void) {
|
||||
inline void init (const CoverageFormat2 &c_) {
|
||||
c = &c_;
|
||||
coverage = 0;
|
||||
i = 0;
|
||||
j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0;
|
||||
}
|
||||
inline bool more (void) { return i < c->rangeRecord.len; }
|
||||
inline void next (void) {
|
||||
coverage++;
|
||||
if (j == c->rangeRecord[i].end) {
|
||||
i++;
|
||||
if (more ())
|
||||
@ -405,13 +412,12 @@ struct CoverageFormat2
|
||||
}
|
||||
j++;
|
||||
}
|
||||
uint16_t get (void) {
|
||||
return j;
|
||||
}
|
||||
inline uint16_t get_glyph (void) { return j; }
|
||||
inline uint16_t get_coverage (void) { return coverage; }
|
||||
|
||||
private:
|
||||
const struct CoverageFormat2 *c;
|
||||
unsigned int i, j;
|
||||
unsigned int i, j, coverage;
|
||||
};
|
||||
|
||||
private:
|
||||
@ -447,8 +453,20 @@ struct Coverage
|
||||
}
|
||||
}
|
||||
|
||||
inline bool intersects (const hb_glyph_map_t *glyphs) const {
|
||||
/* TODO speed this up */
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (*this); iter.more (); iter.next ()) {
|
||||
if (glyphs->has (iter.get_glyph ()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
struct Iter {
|
||||
void init (const Coverage &c_) {
|
||||
Iter (void) : format (0) {};
|
||||
inline void init (const Coverage &c_) {
|
||||
format = c_.u.format;
|
||||
switch (format) {
|
||||
case 1: return u.format1.init (c_.u.format1);
|
||||
@ -456,30 +474,37 @@ struct Coverage
|
||||
default:return;
|
||||
}
|
||||
}
|
||||
bool more (void) {
|
||||
inline bool more (void) {
|
||||
switch (format) {
|
||||
case 1: return u.format1.more ();
|
||||
case 2: return u.format2.more ();
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
void next (void) {
|
||||
inline void next (void) {
|
||||
switch (format) {
|
||||
case 1: u.format1.next (); break;
|
||||
case 2: u.format2.next (); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
uint16_t get (void) {
|
||||
inline uint16_t get_glyph (void) {
|
||||
switch (format) {
|
||||
case 1: return u.format1.get ();
|
||||
case 2: return u.format2.get ();
|
||||
case 1: return u.format1.get_glyph ();
|
||||
case 2: return u.format2.get_glyph ();
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
inline uint16_t get_coverage (void) {
|
||||
switch (format) {
|
||||
case 1: return u.format1.get_coverage ();
|
||||
case 2: return u.format2.get_coverage ();
|
||||
default:return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
USHORT format;
|
||||
unsigned int format;
|
||||
union {
|
||||
CoverageFormat1::Iter format1;
|
||||
CoverageFormat2::Iter format2;
|
||||
|
@ -42,8 +42,14 @@ struct SingleSubstFormat1
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
hb_codepoint_t glyph_id = iter.get_glyph ();
|
||||
if (c->glyphs->has (glyph_id))
|
||||
ret = c->glyphs->add ((glyph_id + deltaGlyphID) & 0xFFFF) || ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t glyph_id) const
|
||||
@ -93,8 +99,13 @@ struct SingleSubstFormat2
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
ret = c->glyphs->add (substitute[iter.get_coverage ()]) || ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t glyph_id) const
|
||||
@ -200,8 +211,11 @@ struct Sequence
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
unsigned int count = substitute.len;
|
||||
bool ret = false;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
ret = c->glyphs->add (substitute[i]) || ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
@ -239,8 +253,13 @@ struct MultipleSubstFormat1
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
ret = (this+sequence[iter.get_coverage ()]).closure (c) || ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t glyph_id) const
|
||||
@ -338,8 +357,17 @@ struct AlternateSubstFormat1
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
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++)
|
||||
ret = c->glyphs->add (alt_set[i]) || ret;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t glyph_id) const
|
||||
@ -454,8 +482,11 @@ struct Ligature
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
unsigned int count = component.len;
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (!c->glyphs->has (component[i]))
|
||||
return false;
|
||||
return c->glyphs->add (ligGlyph);
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t second) const
|
||||
@ -556,8 +587,14 @@ struct LigatureSet
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
bool ret = false;
|
||||
unsigned int num_ligs = ligature.len;
|
||||
for (unsigned int i = 0; i < num_ligs; i++)
|
||||
{
|
||||
const Ligature &lig = this+ligature[i];
|
||||
ret = lig.closure (c) || ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool would_apply (hb_codepoint_t second) const
|
||||
@ -609,7 +646,13 @@ struct LigatureSubstFormat1
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
ret = (this+ligatureSet[iter.get_coverage ()]).closure (c) || ret;
|
||||
}
|
||||
return ret;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -755,13 +798,7 @@ struct ExtensionSubst : Extension
|
||||
return StructAtOffset<SubstLookupSubTable> (this, offset);
|
||||
}
|
||||
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool closure (hb_closure_context_t *c) const;
|
||||
inline bool would_apply (hb_codepoint_t glyph_id) const;
|
||||
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) const;
|
||||
|
||||
@ -782,7 +819,27 @@ struct ReverseChainSingleSubstFormat1
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
TRACE_CLOSURE ();
|
||||
/* TODO FILLME */
|
||||
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 (c->glyphs))
|
||||
return false;
|
||||
|
||||
count = lookahead.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
if (!(this+lookahead[i]).intersects (c->glyphs))
|
||||
return false;
|
||||
|
||||
const ArrayOf<GlyphID> &substitute = StructAfter<ArrayOf<GlyphID> > (lookahead);
|
||||
bool ret = false;
|
||||
Coverage::Iter iter;
|
||||
for (iter.init (this+coverage); iter.more (); iter.next ()) {
|
||||
if (c->glyphs->has (iter.get_glyph ()))
|
||||
ret = c->glyphs->add (substitute[iter.get_coverage ()]) || ret;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1014,8 +1071,8 @@ struct SubstLookup : Lookup
|
||||
inline bool closure (hb_closure_context_t *c) const
|
||||
{
|
||||
unsigned int lookup_type = get_type ();
|
||||
unsigned int count = get_subtable_count ();
|
||||
bool ret = false;
|
||||
unsigned int count = get_subtable_count ();
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
ret = get_subtable (i).closure (c, lookup_type) || ret;
|
||||
return ret;
|
||||
@ -1054,8 +1111,8 @@ struct SubstLookup : Lookup
|
||||
*
|
||||
* This is rather slow to do this here for every glyph,
|
||||
* but it's easiest, and who uses extension lookups anyway?!*/
|
||||
unsigned int count = get_subtable_count ();
|
||||
unsigned int type = get_subtable(0).u.extension.get_type ();
|
||||
unsigned int count = get_subtable_count ();
|
||||
for (unsigned int i = 1; i < count; i++)
|
||||
if (get_subtable(i).u.extension.get_type () != type)
|
||||
return false;
|
||||
@ -1174,6 +1231,11 @@ GSUB::substitute_finish (hb_buffer_t *buffer)
|
||||
|
||||
/* Out-of-class implementation for methods recursing */
|
||||
|
||||
inline bool ExtensionSubst::closure (hb_closure_context_t *c) const
|
||||
{
|
||||
return get_subtable ().closure (c, get_type ());
|
||||
}
|
||||
|
||||
inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
return get_subtable ().would_apply (glyph_id, get_type ());
|
||||
|
@ -95,4 +95,38 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout);
|
||||
|
||||
|
||||
|
||||
struct _hb_glyph_map_t
|
||||
{
|
||||
void clear (void) {
|
||||
memset (elts, 0, sizeof elts);
|
||||
}
|
||||
bool has (hb_codepoint_t g) const {
|
||||
if (unlikely (g > MAX_G)) return false;
|
||||
return !!(elt (g) & mask (g));
|
||||
}
|
||||
bool add (hb_codepoint_t g) {
|
||||
if (unlikely (g > MAX_G)) return false;
|
||||
elt_t &e = elt (g);
|
||||
elt_t m = mask (g);
|
||||
bool ret = !!(e & m);
|
||||
e |= m;
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef uint32_t elt_t;
|
||||
static const unsigned int MAX_G = 65536 - 1;
|
||||
static const unsigned int SHIFT = 5;
|
||||
static const unsigned int BITS = (1 << SHIFT);
|
||||
static const unsigned int MASK = BITS - 1;
|
||||
|
||||
elt_t &elt (hb_codepoint_t g) { return elts[g >> SHIFT]; }
|
||||
elt_t elt (hb_codepoint_t g) const { return elts[g >> SHIFT]; }
|
||||
elt_t mask (hb_codepoint_t g) const { return elt_t (1) << (g & MASK); }
|
||||
|
||||
elt_t elts[(MAX_G + 1 + (BITS - 1)) / BITS]; /* 8kb */
|
||||
ASSERT_STATIC (sizeof (elt_t) * 8 == BITS);
|
||||
ASSERT_STATIC (sizeof (elts) * 8 > MAX_G);
|
||||
};
|
||||
|
||||
#endif /* HB_OT_LAYOUT_PRIVATE_HH */
|
||||
|
@ -183,7 +183,7 @@ void
|
||||
hb_ot_layout_substitute_finish (hb_buffer_t *buffer);
|
||||
|
||||
|
||||
typedef uint32_t hb_glyph_map_t[65536 / 32]; /* 8kb */
|
||||
typedef struct _hb_glyph_map_t hb_glyph_map_t;
|
||||
|
||||
hb_bool_t
|
||||
hb_ot_layout_substitute_closure_lookup (hb_face_t *face,
|
||||
|
Loading…
Reference in New Issue
Block a user