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 {
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;

View File

@ -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 ());

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 */

View File

@ -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,