[aat] Add StateTableDriver and convert ContextualSubtable to it
This commit is contained in:
parent
0d39ac224c
commit
117cfe7bb7
|
@ -605,6 +605,57 @@ struct StateTable
|
||||||
DEFINE_SIZE_UNION (2, format);
|
DEFINE_SIZE_UNION (2, format);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename EntryData>
|
||||||
|
struct StateTableDriver
|
||||||
|
{
|
||||||
|
inline StateTableDriver (const StateTable<EntryData> &machine_,
|
||||||
|
hb_buffer_t *buffer_,
|
||||||
|
hb_face_t *face_) :
|
||||||
|
machine (machine_),
|
||||||
|
buffer (buffer_),
|
||||||
|
num_glyphs (face_->get_num_glyphs ()),
|
||||||
|
state (0),
|
||||||
|
last_zero (0) {}
|
||||||
|
|
||||||
|
template <typename context_t>
|
||||||
|
inline void drive (context_t *c)
|
||||||
|
{
|
||||||
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
unsigned int count = buffer->len;
|
||||||
|
|
||||||
|
for (buffer->idx = 0; buffer->idx <= count; buffer->idx++)
|
||||||
|
{
|
||||||
|
if (!state)
|
||||||
|
last_zero = buffer->idx;
|
||||||
|
|
||||||
|
unsigned int klass = buffer->idx < count ?
|
||||||
|
machine.get_class (info[buffer->idx].codepoint, num_glyphs) :
|
||||||
|
0 /* End of text */;
|
||||||
|
const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
|
||||||
|
if (unlikely (!entry))
|
||||||
|
break;
|
||||||
|
|
||||||
|
c->transition (this, entry);
|
||||||
|
|
||||||
|
if (entry->flags & context_t::Flags::DontAdvance)
|
||||||
|
buffer->idx--; /* TODO Detect infinite loop. */
|
||||||
|
|
||||||
|
state = entry->newState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX finish if not in-place */
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
const StateTable<EntryData> &machine;
|
||||||
|
hb_buffer_t *buffer;
|
||||||
|
|
||||||
|
unsigned int num_glyphs;
|
||||||
|
|
||||||
|
unsigned int state;
|
||||||
|
unsigned int last_zero;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
} /* namespace AAT */
|
} /* namespace AAT */
|
||||||
|
|
||||||
|
|
|
@ -176,14 +176,6 @@ struct RearrangementSubtable
|
||||||
|
|
||||||
struct ContextualSubtable
|
struct ContextualSubtable
|
||||||
{
|
{
|
||||||
enum Flags {
|
|
||||||
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
|
||||||
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
|
||||||
* going to the new state. */
|
|
||||||
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* XXX the following is different in mort: it's directly index to sublookups. */
|
|
||||||
struct EntryData
|
struct EntryData
|
||||||
{
|
{
|
||||||
HBUINT16 markIndex; /* Index of the substitution table for the
|
HBUINT16 markIndex; /* Index of the substitution table for the
|
||||||
|
@ -194,50 +186,40 @@ struct ContextualSubtable
|
||||||
DEFINE_SIZE_STATIC (4);
|
DEFINE_SIZE_STATIC (4);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool apply (hb_apply_context_t *c) const
|
struct driver_context_t
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
enum Flags {
|
||||||
|
SetMark = 0x8000, /* If set, make the current glyph the marked glyph. */
|
||||||
|
DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
|
||||||
|
* going to the new state. */
|
||||||
|
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
|
||||||
|
};
|
||||||
|
|
||||||
bool ret = false;
|
inline driver_context_t (const ContextualSubtable *table) :
|
||||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
ret (false),
|
||||||
|
mark (0),
|
||||||
|
last_zero_before_mark (0),
|
||||||
|
subs (table+table->substitutionTables) {}
|
||||||
|
|
||||||
const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs = this+substitutionTables;
|
inline void transition (StateTableDriver<EntryData> *driver,
|
||||||
|
const Entry<EntryData> *entry)
|
||||||
unsigned int state = 0;
|
|
||||||
unsigned int last_zero = 0;
|
|
||||||
unsigned int last_zero_before_mark = 0;
|
|
||||||
unsigned int mark = 0;
|
|
||||||
|
|
||||||
hb_glyph_info_t *info = c->buffer->info;
|
|
||||||
unsigned int count = c->buffer->len;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i <= count; i++)
|
|
||||||
{
|
{
|
||||||
if (!state)
|
hb_buffer_t *buffer = driver->buffer;
|
||||||
last_zero = i;
|
|
||||||
|
|
||||||
unsigned int klass = i < count ?
|
if (entry->flags & SetMark)
|
||||||
machine.get_class (info[i].codepoint, num_glyphs) :
|
|
||||||
0 /* End of text */;
|
|
||||||
const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
|
|
||||||
if (unlikely (!entry))
|
|
||||||
break;
|
|
||||||
|
|
||||||
unsigned int flags = entry->flags;
|
|
||||||
|
|
||||||
if (flags & SetMark)
|
|
||||||
{
|
{
|
||||||
mark = i;
|
mark = buffer->idx;
|
||||||
last_zero_before_mark = last_zero;
|
last_zero_before_mark = driver->last_zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
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];
|
||||||
const GlyphID *replacement = lookup.get_value (info[mark].codepoint, num_glyphs);
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs);
|
||||||
if (replacement)
|
if (replacement)
|
||||||
{
|
{
|
||||||
c->buffer->unsafe_to_break (last_zero_before_mark, MIN (i + 1, count));
|
buffer->unsafe_to_break (last_zero_before_mark, MIN (buffer->idx + 1, buffer->len));
|
||||||
info[mark].codepoint = *replacement;
|
info[mark].codepoint = *replacement;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
|
@ -245,22 +227,35 @@ struct ContextualSubtable
|
||||||
if (entry->data.currentIndex != 0xFFFF)
|
if (entry->data.currentIndex != 0xFFFF)
|
||||||
{
|
{
|
||||||
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
|
const Lookup<GlyphID> &lookup = subs[entry->data.currentIndex];
|
||||||
const GlyphID *replacement = lookup.get_value (info[i].codepoint, num_glyphs);
|
hb_glyph_info_t *info = buffer->info;
|
||||||
|
const GlyphID *replacement = lookup.get_value (info[buffer->idx].codepoint, driver->num_glyphs);
|
||||||
if (replacement)
|
if (replacement)
|
||||||
{
|
{
|
||||||
c->buffer->unsafe_to_break (last_zero, MIN (i + 1, count));
|
buffer->unsafe_to_break (driver->last_zero, MIN (buffer->idx + 1, buffer->len));
|
||||||
info[i].codepoint = *replacement;
|
info[buffer->idx].codepoint = *replacement;
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DontAdvance)
|
|
||||||
i--; /* TODO Detect infinite loop. */
|
|
||||||
|
|
||||||
state = entry->newState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (ret);
|
public:
|
||||||
|
bool ret;
|
||||||
|
private:
|
||||||
|
unsigned int mark;
|
||||||
|
unsigned int last_zero_before_mark;
|
||||||
|
const UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32> &subs;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool apply (hb_apply_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_APPLY (this);
|
||||||
|
|
||||||
|
driver_context_t dc (this);
|
||||||
|
|
||||||
|
StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
|
||||||
|
driver.drive (&dc);
|
||||||
|
|
||||||
|
return_trace (dc.ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
|
Loading…
Reference in New Issue