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 {
|
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;
|
||||||
|
@ -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;
|
||||||
|
for (unsigned int i = 1; i < count; i++)
|
||||||
|
if (!c->glyphs->has (component[i]))
|
||||||
return false;
|
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 ());
|
||||||
|
@ -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 */
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user