[morx] Add stub for InsertionChain

This commit is contained in:
Behdad Esfahbod 2018-09-15 14:47:18 +02:00
parent f8ccb545c4
commit 29c2bd1795
1 changed files with 200 additions and 9 deletions

View File

@ -50,7 +50,8 @@ struct RearrangementSubtable
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 ContextualSubtable
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 LigatureSubtable
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 @@ struct LigatureSubtable
* 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 NoncontextualSubtable
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 @@ struct ChainSubtable
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,