From 28b68cffe4e5ebf82217ebf439f428431d672af3 Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Tue, 30 Oct 2018 23:33:30 -0700 Subject: [PATCH] [mort] Implement / adjust Contextual substitution --- src/hb-aat-layout-morx-table.hh | 70 ++++++++++++++++++++++++--------- src/hb-open-type.hh | 7 ++++ 2 files changed, 59 insertions(+), 18 deletions(-) diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index dba352f9..c3a74835 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -213,10 +213,13 @@ struct ContextualSubtable Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ }; - inline driver_context_t (const ContextualSubtable *table) : + inline driver_context_t (const ContextualSubtable *table_, + hb_aat_apply_context_t *c_) : ret (false), + c (c_), mark_set (false), mark (0), + table (table_), subs (table+table->substitutionTables) {} inline bool is_actionable (StateTableDriver *driver, @@ -239,30 +242,57 @@ struct ContextualSubtable if (buffer->idx == buffer->len && !mark_set) return true; - if (entry->data.markIndex != 0xFFFF) + const GlyphID *replacement; + + replacement = nullptr; + if (Types::extended) { - const Lookup &lookup = subs[entry->data.markIndex]; - hb_glyph_info_t *info = buffer->info; - const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs); - if (replacement) + if (entry->data.markIndex != 0xFFFF) { - buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); - info[mark].codepoint = *replacement; - ret = true; + const Lookup &lookup = subs[entry->data.markIndex]; + replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs); } } - if (entry->data.currentIndex != 0xFFFF) + else + { + unsigned int offset = 2 * (entry->data.markIndex + buffer->info[mark].codepoint); + replacement = &StructAtOffset (table, offset); + if ((const void *) replacement < (const void *) subs || + !replacement->sanitize (&c->sanitizer) || + !*replacement) + replacement = nullptr; + } + if (replacement) + { + buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); + buffer->info[mark].codepoint = *replacement; + ret = true; + } + + replacement = nullptr; + unsigned int idx = MIN (buffer->idx, buffer->len - 1); + if (Types::extended) { - unsigned int idx = MIN (buffer->idx, buffer->len - 1); - const Lookup &lookup = subs[entry->data.currentIndex]; - hb_glyph_info_t *info = buffer->info; - const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs); - if (replacement) + if (entry->data.currentIndex != 0xFFFF) { - info[idx].codepoint = *replacement; - ret = true; + const Lookup &lookup = subs[entry->data.currentIndex]; + replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs); } } + else + { + unsigned int offset = 2 * (entry->data.currentIndex + buffer->info[idx].codepoint); + replacement = &StructAtOffset (table, offset); + if ((const void *) replacement < (const void *) subs || + !replacement->sanitize (&c->sanitizer) || + !*replacement) + replacement = nullptr; + } + if (replacement) + { + buffer->info[idx].codepoint = *replacement; + ret = true; + } if (entry->flags & SetMark) { @@ -276,8 +306,10 @@ struct ContextualSubtable public: bool ret; private: + hb_aat_apply_context_t *c; bool mark_set; unsigned int mark; + const ContextualSubtable *table; const UnsizedOffsetListOf, HBUINT, false> &subs; }; @@ -285,7 +317,7 @@ struct ContextualSubtable { TRACE_APPLY (this); - driver_context_t dc (this); + driver_context_t dc (this, c); StateTableDriver driver (machine, c->buffer, c->face); driver.drive (&dc); @@ -300,6 +332,8 @@ struct ContextualSubtable unsigned int num_entries = 0; if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); + if (!Types::extended) return_trace (true); + unsigned int num_lookups = 0; const Entry *entries = machine.get_entries (); diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index e9f99b10..00bd134d 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -340,6 +340,9 @@ struct UnsizedArrayOf inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } inline Type& operator [] (unsigned int i) { return arrayZ[i]; } + template inline operator T * (void) { return arrayZ; } + template inline operator const T * (void) const { return arrayZ; } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); @@ -450,6 +453,10 @@ struct ArrayOf if (unlikely (i >= len)) return Crap(Type); return arrayZ[i]; } + + template inline operator T * (void) { return arrayZ; } + template inline operator const T * (void) const { return arrayZ; } + inline unsigned int get_size (void) const { return len.static_size + len * Type::static_size; } -- GitLab