[mort] Implement / adjust Contextual substitution

This commit is contained in:
Behdad Esfahbod 2018-10-30 23:33:30 -07:00
parent 11dbf0f129
commit 28b68cffe4
2 changed files with 59 additions and 18 deletions

View File

@ -213,10 +213,13 @@ struct ContextualSubtable
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */ 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), ret (false),
c (c_),
mark_set (false), mark_set (false),
mark (0), mark (0),
table (table_),
subs (table+table->substitutionTables) {} subs (table+table->substitutionTables) {}
inline bool is_actionable (StateTableDriver<Types, EntryData> *driver, inline bool is_actionable (StateTableDriver<Types, EntryData> *driver,
@ -239,30 +242,57 @@ struct ContextualSubtable
if (buffer->idx == buffer->len && !mark_set) if (buffer->idx == buffer->len && !mark_set)
return true; return true;
const GlyphID *replacement;
replacement = nullptr;
if (Types::extended)
{
if (entry->data.markIndex != 0xFFFF) if (entry->data.markIndex != 0xFFFF)
{ {
const Lookup<GlyphID> &lookup = subs[entry->data.markIndex]; const Lookup<GlyphID> &lookup = subs[entry->data.markIndex];
hb_glyph_info_t *info = buffer->info; replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs); }
}
else
{
unsigned int offset = 2 * (entry->data.markIndex + buffer->info[mark].codepoint);
replacement = &StructAtOffset<GlyphID> (table, offset);
if ((const void *) replacement < (const void *) subs ||
!replacement->sanitize (&c->sanitizer) ||
!*replacement)
replacement = nullptr;
}
if (replacement) if (replacement)
{ {
buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len)); buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
info[mark].codepoint = *replacement; buffer->info[mark].codepoint = *replacement;
ret = true; ret = true;
} }
}
replacement = nullptr;
unsigned int idx = MIN (buffer->idx, buffer->len - 1);
if (Types::extended)
{
if (entry->data.currentIndex != 0xFFFF) if (entry->data.currentIndex != 0xFFFF)
{ {
unsigned int idx = MIN (buffer->idx, buffer->len - 1);
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex]; const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
hb_glyph_info_t *info = buffer->info; replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs); }
}
else
{
unsigned int offset = 2 * (entry->data.currentIndex + buffer->info[idx].codepoint);
replacement = &StructAtOffset<GlyphID> (table, offset);
if ((const void *) replacement < (const void *) subs ||
!replacement->sanitize (&c->sanitizer) ||
!*replacement)
replacement = nullptr;
}
if (replacement) if (replacement)
{ {
info[idx].codepoint = *replacement; buffer->info[idx].codepoint = *replacement;
ret = true; ret = true;
} }
}
if (entry->flags & SetMark) if (entry->flags & SetMark)
{ {
@ -276,8 +306,10 @@ struct ContextualSubtable
public: public:
bool ret; bool ret;
private: private:
hb_aat_apply_context_t *c;
bool mark_set; bool mark_set;
unsigned int mark; unsigned int mark;
const ContextualSubtable *table;
const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs; const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false> &subs;
}; };
@ -285,7 +317,7 @@ struct ContextualSubtable
{ {
TRACE_APPLY (this); TRACE_APPLY (this);
driver_context_t dc (this); driver_context_t dc (this, c);
StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face); StateTableDriver<Types, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc); driver.drive (&dc);
@ -300,6 +332,8 @@ struct ContextualSubtable
unsigned int num_entries = 0; unsigned int num_entries = 0;
if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false); if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
if (!Types::extended) return_trace (true);
unsigned int num_lookups = 0; unsigned int num_lookups = 0;
const Entry<EntryData> *entries = machine.get_entries (); const Entry<EntryData> *entries = machine.get_entries ();

View File

@ -340,6 +340,9 @@ struct UnsizedArrayOf
inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
inline Type& operator [] (unsigned int i) { return arrayZ[i]; } inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
template <typename T> inline operator T * (void) { return arrayZ; }
template <typename T> inline operator const T * (void) const { return arrayZ; }
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{ {
TRACE_SANITIZE (this); TRACE_SANITIZE (this);
@ -450,6 +453,10 @@ struct ArrayOf
if (unlikely (i >= len)) return Crap(Type); if (unlikely (i >= len)) return Crap(Type);
return arrayZ[i]; return arrayZ[i];
} }
template <typename T> inline operator T * (void) { return arrayZ; }
template <typename T> inline operator const T * (void) const { return arrayZ; }
inline unsigned int get_size (void) const inline unsigned int get_size (void) const
{ return len.static_size + len * Type::static_size; } { return len.static_size + len * Type::static_size; }