Flesh out closure() for GSUB

The GSUBGPOS part still missing.
This commit is contained in:
Behdad Esfahbod 2012-04-23 15:28:35 -04:00
parent 0da132bde4
commit c64ddab3c3
4 changed files with 165 additions and 44 deletions

View File

@ -355,10 +355,11 @@ struct CoverageFormat1
} }
struct Iter { struct Iter {
void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; }; inline void init (const struct CoverageFormat1 &c_) { c = &c_; i = 0; };
bool more (void) { return i < c->glyphArray.len; } inline bool more (void) { return i < c->glyphArray.len; }
void next (void) { i++; } inline void next (void) { i++; }
uint16_t get (void) { return c->glyphArray[i]; } inline uint16_t get_glyph (void) { return c->glyphArray[i]; }
inline uint16_t get_coverage (void) { return i; }
private: private:
const struct CoverageFormat1 *c; const struct CoverageFormat1 *c;
@ -394,9 +395,15 @@ struct CoverageFormat2
} }
struct Iter { struct Iter {
void init (const CoverageFormat2 &c_) { c = &c_; i = 0; j = c->rangeRecord.len ? c_.rangeRecord[0].start : 0; } inline void init (const CoverageFormat2 &c_) {
bool more (void) { return i < c->rangeRecord.len; } c = &c_;
void next (void) { 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) { if (j == c->rangeRecord[i].end) {
i++; i++;
if (more ()) if (more ())
@ -405,13 +412,12 @@ struct CoverageFormat2
} }
j++; j++;
} }
uint16_t get (void) { inline uint16_t get_glyph (void) { return j; }
return j; inline uint16_t get_coverage (void) { return coverage; }
}
private: private:
const struct CoverageFormat2 *c; const struct CoverageFormat2 *c;
unsigned int i, j; unsigned int i, j, coverage;
}; };
private: 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 { struct Iter {
void init (const Coverage &c_) { Iter (void) : format (0) {};
inline void init (const Coverage &c_) {
format = c_.u.format; format = c_.u.format;
switch (format) { switch (format) {
case 1: return u.format1.init (c_.u.format1); case 1: return u.format1.init (c_.u.format1);
@ -456,30 +474,37 @@ struct Coverage
default:return; default:return;
} }
} }
bool more (void) { inline bool more (void) {
switch (format) { switch (format) {
case 1: return u.format1.more (); case 1: return u.format1.more ();
case 2: return u.format2.more (); case 2: return u.format2.more ();
default:return true; default:return true;
} }
} }
void next (void) { inline void next (void) {
switch (format) { switch (format) {
case 1: u.format1.next (); break; case 1: u.format1.next (); break;
case 2: u.format2.next (); break; case 2: u.format2.next (); break;
default: break; default: break;
} }
} }
uint16_t get (void) { inline uint16_t get_glyph (void) {
switch (format) { switch (format) {
case 1: return u.format1.get (); case 1: return u.format1.get_glyph ();
case 2: return u.format2.get (); 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; default:return true;
} }
} }
private: private:
USHORT format; unsigned int format;
union { union {
CoverageFormat1::Iter format1; CoverageFormat1::Iter format1;
CoverageFormat2::Iter format2; CoverageFormat2::Iter format2;

View File

@ -42,8 +42,14 @@ struct SingleSubstFormat1
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ bool ret = false;
return 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 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 inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ bool ret = false;
return 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 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 inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ unsigned int count = substitute.len;
return false; 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 inline bool apply (hb_apply_context_t *c) const
@ -239,8 +253,13 @@ struct MultipleSubstFormat1
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ bool ret = false;
return 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 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 inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ bool ret = false;
return 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 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 inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ unsigned int count = component.len;
return false; 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 inline bool would_apply (hb_codepoint_t second) const
@ -556,8 +587,14 @@ struct LigatureSet
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); TRACE_CLOSURE ();
/* TODO FILLME */ bool ret = false;
return 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 inline bool would_apply (hb_codepoint_t second) const
@ -609,7 +646,13 @@ struct LigatureSubstFormat1
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); 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; return false;
} }
@ -755,13 +798,7 @@ struct ExtensionSubst : Extension
return StructAtOffset<SubstLookupSubTable> (this, offset); return StructAtOffset<SubstLookupSubTable> (this, offset);
} }
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const;
{
TRACE_CLOSURE ();
/* TODO FILLME */
return false;
}
inline bool would_apply (hb_codepoint_t glyph_id) const; inline bool would_apply (hb_codepoint_t glyph_id) const;
inline bool would_apply (hb_codepoint_t first, hb_codepoint_t second) 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 inline bool closure (hb_closure_context_t *c) const
{ {
TRACE_CLOSURE (); 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; return false;
} }
@ -1014,8 +1071,8 @@ struct SubstLookup : Lookup
inline bool closure (hb_closure_context_t *c) const inline bool closure (hb_closure_context_t *c) const
{ {
unsigned int lookup_type = get_type (); unsigned int lookup_type = get_type ();
unsigned int count = get_subtable_count ();
bool ret = false; bool ret = false;
unsigned int count = get_subtable_count ();
for (unsigned int i = 0; i < count; i++) for (unsigned int i = 0; i < count; i++)
ret = get_subtable (i).closure (c, lookup_type) || ret; ret = get_subtable (i).closure (c, lookup_type) || ret;
return ret; return ret;
@ -1054,8 +1111,8 @@ struct SubstLookup : Lookup
* *
* This is rather slow to do this here for every glyph, * This is rather slow to do this here for every glyph,
* but it's easiest, and who uses extension lookups anyway?!*/ * 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 type = get_subtable(0).u.extension.get_type ();
unsigned int count = get_subtable_count ();
for (unsigned int i = 1; i < count; i++) for (unsigned int i = 1; i < count; i++)
if (get_subtable(i).u.extension.get_type () != type) if (get_subtable(i).u.extension.get_type () != type)
return false; return false;
@ -1174,6 +1231,11 @@ GSUB::substitute_finish (hb_buffer_t *buffer)
/* Out-of-class implementation for methods recursing */ /* 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 inline bool ExtensionSubst::would_apply (hb_codepoint_t glyph_id) const
{ {
return get_subtable ().would_apply (glyph_id, get_type ()); return get_subtable ().would_apply (glyph_id, get_type ());

View File

@ -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 */ #endif /* HB_OT_LAYOUT_PRIVATE_HH */

View File

@ -183,7 +183,7 @@ void
hb_ot_layout_substitute_finish (hb_buffer_t *buffer); 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_bool_t
hb_ot_layout_substitute_closure_lookup (hb_face_t *face, hb_ot_layout_substitute_closure_lookup (hb_face_t *face,