From c64ddab3c34897cd520d4d73a054866e649e8793 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 23 Apr 2012 15:28:35 -0400 Subject: [PATCH] Flesh out closure() for GSUB The GSUBGPOS part still missing. --- src/hb-ot-layout-common-private.hh | 61 +++++++++++----- src/hb-ot-layout-gsub-table.hh | 112 ++++++++++++++++++++++------- src/hb-ot-layout-private.hh | 34 +++++++++ src/hb-ot-layout.h | 2 +- 4 files changed, 165 insertions(+), 44 deletions(-) diff --git a/src/hb-ot-layout-common-private.hh b/src/hb-ot-layout-common-private.hh index c41010ac5..410c933e7 100644 --- a/src/hb-ot-layout-common-private.hh +++ b/src/hb-ot-layout-common-private.hh @@ -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; diff --git a/src/hb-ot-layout-gsub-table.hh b/src/hb-ot-layout-gsub-table.hh index f0db228eb..1feb3c87a 100644 --- a/src/hb-ot-layout-gsub-table.hh +++ b/src/hb-ot-layout-gsub-table.hh @@ -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 (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 &lookahead = StructAfter > (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 &substitute = StructAfter > (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 ()); diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh index bf7e43b6e..acc1d18eb 100644 --- a/src/hb-ot-layout-private.hh +++ b/src/hb-ot-layout-private.hh @@ -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 */ diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h index 16addc68d..a9db04f67 100644 --- a/src/hb-ot-layout.h +++ b/src/hb-ot-layout.h @@ -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,