[morx] Add stub for InsertionChain
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index e4774c4..82e1d13 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -50,7 +50,8 @@
struct driver_context_t
{
static const bool in_place = true;
- enum Flags {
+ enum Flags
+ {
MarkFirst = 0x8000, /* If set, make the current glyph the first
* glyph to be rearranged. */
DontAdvance = 0x4000, /* If set, don't advance to the next glyph
@@ -196,7 +197,8 @@
struct driver_context_t
{
static const bool in_place = true;
- enum Flags {
+ 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. */
@@ -329,7 +331,8 @@
struct driver_context_t
{
static const bool in_place = false;
- enum Flags {
+ enum Flags
+ {
SetComponent = 0x8000, /* Push this glyph onto the component stack for
* eventual processing. */
DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
@@ -338,7 +341,8 @@
* group. */
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
};
- enum LigActionFlags {
+ enum LigActionFlags
+ {
LigActionLast = 0x80000000, /* This is the last action in the list. This also
* implies storage. */
LigActionStore = 0x40000000, /* Store the ligature at the current cumulated index
@@ -517,19 +521,205 @@
struct InsertionSubtable
{
+ struct EntryData
+ {
+ HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table.
+ * The number of glyphs to be inserted is contained
+ * in the currentInsertCount field in the flags.
+ * A value of 0xFFFF indicates no insertion is to
+ * be done. */
+ HBUINT16 markedInsertIndex; /* Zero-based index into the insertion glyph table.
+ * The number of glyphs to be inserted is contained
+ * in the markedInsertCount field in the flags.
+ * A value of 0xFFFF indicates no insertion is to
+ * be done. */
+ public:
+ DEFINE_SIZE_STATIC (4);
+ };
+
+ struct driver_context_t
+ {
+ static const bool in_place = false;
+ enum Flags
+ {
+ SetMark = 0x8000, /* If set, mark the current glyph. */
+ DontAdvance = 0x4000, /* If set, don't advance to the next glyph before
+ * going to the new state. This does not mean
+ * that the glyph pointed to is the same one as
+ * before. If you've made insertions immediately
+ * downstream of the current glyph, the next glyph
+ * processed would in fact be the first one
+ * inserted. */
+ CurrentIsKashidaLike= 0x2000, /* If set, and the currentInsertList is nonzero,
+ * then the specified glyph list will be inserted
+ * as a kashida-like insertion, either before or
+ * after the current glyph (depending on the state
+ * of the currentInsertBefore flag). If clear, and
+ * the currentInsertList is nonzero, then the
+ * specified glyph list will be inserted as a
+ * split-vowel-like insertion, either before or
+ * after the current glyph (depending on the state
+ * of the currentInsertBefore flag). */
+ MarkedIsKashidaLike= 0x1000, /* If set, and the markedInsertList is nonzero,
+ * then the specified glyph list will be inserted
+ * as a kashida-like insertion, either before or
+ * after the marked glyph (depending on the state
+ * of the markedInsertBefore flag). If clear, and
+ * the markedInsertList is nonzero, then the
+ * specified glyph list will be inserted as a
+ * split-vowel-like insertion, either before or
+ * after the marked glyph (depending on the state
+ * of the markedInsertBefore flag). */
+ CurrentInsertBefore= 0x0800, /* If set, specifies that insertions are to be made
+ * to the left of the current glyph. If clear,
+ * they're made to the right of the current glyph. */
+ MarkedInsertBefore= 0x0400, /* If set, specifies that insertions are to be
+ * made to the left of the marked glyph. If clear,
+ * they're made to the right of the marked glyph. */
+ CurrentInsertCount= 0x3E0, /* This 5-bit field is treated as a count of the
+ * number of glyphs to insert at the current
+ * position. Since zero means no insertions, the
+ * largest number of insertions at any given
+ * current location is 31 glyphs. */
+ MarkedInsertCount= 0x001F, /* This 5-bit field is treated as a count of the
+ * number of glyphs to insert at the marked
+ * position. Since zero means no insertions, the
+ * largest number of insertions at any given
+ * marked location is 31 glyphs. */
+ };
+
+ inline driver_context_t (const InsertionSubtable *table,
+ hb_aat_apply_context_t *c_) :
+ ret (false),
+ c (c_),
+ mark_set (false),
+ mark (0),
+ insertionAction (table+table->insertionAction) {}
+
+ inline bool is_actionable (StateTableDriver<EntryData> *driver,
+ const Entry<EntryData> *entry)
+ {
+ return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
+ (entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
+ }
+ inline bool transition (StateTableDriver<EntryData> *driver,
+ const Entry<EntryData> *entry)
+ {
+ hb_buffer_t *buffer = driver->buffer;
+ unsigned int flags = entry->flags;
+
+#if 0
+ if (flags & SetComponent)
+ {
+ if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
+ return false;
+
+ /* Never mark same index twice, in case DontAdvance was used... */
+ if (match_length && match_positions[match_length - 1] == buffer->out_len)
+ match_length--;
+
+ match_positions[match_length++] = buffer->out_len;
+ }
+
+ if (flags & PerformAction)
+ {
+ unsigned int end = buffer->out_len;
+ unsigned int action_idx = entry->data.ligActionIndex;
+ unsigned int action;
+ unsigned int ligature_idx = 0;
+ do
+ {
+ if (unlikely (!match_length))
+ return false;
+
+ buffer->move_to (match_positions[--match_length]);
+
+ const HBUINT32 &actionData = ligAction[action_idx];
+ if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
+ action = actionData;
+
+ uint32_t uoffset = action & LigActionOffset;
+ if (uoffset & 0x20000000)
+ uoffset += 0xC0000000;
+ int32_t offset = (int32_t) uoffset;
+ unsigned int component_idx = buffer->cur().codepoint + offset;
+
+ const HBUINT16 &componentData = component[component_idx];
+ if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
+ ligature_idx += componentData;
+
+ if (action & (LigActionStore | LigActionLast))
+ {
+ const GlyphID &ligatureData = ligature[ligature_idx];
+ if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
+ hb_codepoint_t lig = ligatureData;
+
+ match_positions[match_length++] = buffer->out_len;
+ buffer->replace_glyph (lig);
+
+ //ligature_idx = 0; // XXX Yes or no?
+ }
+ else
+ {
+ buffer->skip_glyph ();
+ end--;
+ }
+ /* TODO merge_clusters / unsafe_to_break */
+
+ action_idx++;
+ }
+ while (!(action & LigActionLast));
+ buffer->move_to (end);
+ }
+#endif
+
+ if (flags & SetMark)
+ {
+ mark_set = true;
+ mark = buffer->idx;
+ }
+
+
+ return true;
+ }
+
+ public:
+ bool ret;
+ private:
+ hb_aat_apply_context_t *c;
+ bool mark_set;
+ unsigned int mark;
+ const UnsizedArrayOf<GlyphID> &insertionAction;
+ };
+
inline bool apply (hb_aat_apply_context_t *c) const
{
TRACE_APPLY (this);
- /* TODO */
- return_trace (false);
+
+ driver_context_t dc (this, c);
+
+ StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+ driver.drive (&dc);
+
+ return_trace (dc.ret);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- /* TODO */
- return_trace (true);
+ /* The rest of array sanitizations are done at run-time. */
+ return_trace (c->check_struct (this) && machine.sanitize (c) &&
+ insertionAction);
}
+
+ protected:
+ StateTable<EntryData>
+ machine;
+ LOffsetTo<UnsizedArrayOf<GlyphID> >
+ insertionAction; /* Byte offset from stateHeader to the start of
+ * the insertion glyph table. */
+ public:
+ DEFINE_SIZE_STATIC (20);
};
@@ -561,7 +751,8 @@
inline unsigned int get_size (void) const { return length; }
inline unsigned int get_type (void) const { return coverage & 0xFF; }
- enum Type {
+ enum Type
+ {
Rearrangement = 0,
Contextual = 1,
Ligature = 2,