[aat] Implement LigatureSubtable
We form the Zapfino ligature now. Yay! No further testing done.
This commit is contained in:
parent
f07ce661a2
commit
e6f283ed7d
@ -627,23 +627,26 @@ struct StateTableDriver
|
||||
inline void drive (context_t *c)
|
||||
{
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int count = buffer->len;
|
||||
|
||||
if (!c->in_place)
|
||||
buffer->clear_output ();
|
||||
|
||||
unsigned int state = 0;
|
||||
bool last_was_dont_advance = false;
|
||||
for (buffer->idx = 0; buffer->idx <= count;)
|
||||
for (buffer->idx = 0;;)
|
||||
{
|
||||
if (!state)
|
||||
last_zero = buffer->idx;
|
||||
|
||||
unsigned int klass = buffer->idx < count ?
|
||||
unsigned int klass = buffer->idx < buffer->len ?
|
||||
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 (unlikely (!c->transition (this, entry)))
|
||||
break;
|
||||
|
||||
if (entry->flags & context_t::DontAdvance)
|
||||
{
|
||||
@ -655,7 +658,7 @@ struct StateTableDriver
|
||||
dont_advance_set = hb_set_create ();
|
||||
}
|
||||
|
||||
unsigned int key = info[buffer->idx].codepoint | (state << 16);
|
||||
unsigned int key = info[buffer->idx].codepoint ^ (state << 16);
|
||||
if (likely (!dont_advance_set->has (key)))
|
||||
{
|
||||
dont_advance_set->add (key);
|
||||
@ -667,16 +670,20 @@ struct StateTableDriver
|
||||
else
|
||||
last_was_dont_advance = false;
|
||||
|
||||
state = entry->newState;
|
||||
|
||||
if (buffer->idx == buffer->len)
|
||||
break;
|
||||
|
||||
if (!last_was_dont_advance)
|
||||
buffer->next_glyph ();
|
||||
|
||||
state = entry->newState;
|
||||
}
|
||||
|
||||
if (!c->in_place)
|
||||
{
|
||||
for (buffer->idx = 0; buffer->idx <= count;)
|
||||
for (; buffer->idx < buffer->len;)
|
||||
buffer->next_glyph ();
|
||||
buffer->swap_buffers ();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ struct RearrangementSubtable
|
||||
start (0), end (0),
|
||||
last_zero_before_start (0) {}
|
||||
|
||||
inline void transition (StateTableDriver<void> *driver,
|
||||
inline bool transition (StateTableDriver<void> *driver,
|
||||
const Entry<void> *entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
@ -138,6 +138,8 @@ struct RearrangementSubtable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -200,7 +202,7 @@ struct ContextualSubtable
|
||||
last_zero_before_mark (0),
|
||||
subs (table+table->substitutionTables) {}
|
||||
|
||||
inline void transition (StateTableDriver<EntryData> *driver,
|
||||
inline bool transition (StateTableDriver<EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
@ -235,6 +237,8 @@ struct ContextualSubtable
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -309,28 +313,113 @@ struct LigatureSubtable
|
||||
* group. */
|
||||
Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
|
||||
};
|
||||
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
|
||||
* in the ligature table in place of the marked
|
||||
* (i.e. currently-popped) glyph. */
|
||||
LigActionOffset = 0x3FFFFFFF, /* A 30-bit value which is sign-extended to 32-bits
|
||||
* and added to the glyph ID, resulting in an index
|
||||
* into the component table. */
|
||||
};
|
||||
|
||||
inline driver_context_t (const LigatureSubtable *table) :
|
||||
ret (false) {}
|
||||
inline driver_context_t (const LigatureSubtable *table,
|
||||
hb_aat_apply_context_t *c_) :
|
||||
ret (false),
|
||||
c (c_),
|
||||
ligAction (table+table->ligAction),
|
||||
component (table+table->component),
|
||||
ligature (table+table->ligature),
|
||||
match_length (0) {}
|
||||
|
||||
inline void transition (StateTableDriver<EntryData> *driver,
|
||||
inline bool transition (StateTableDriver<EntryData> *driver,
|
||||
const Entry<EntryData> *entry)
|
||||
{
|
||||
hb_buffer_t *buffer = driver->buffer;
|
||||
unsigned int flags = entry->flags;
|
||||
|
||||
/* TODO */
|
||||
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 - 1]);
|
||||
|
||||
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;
|
||||
|
||||
buffer->replace_glyph (lig);
|
||||
|
||||
//ligature_idx = 0; // XXX Yes or no?
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->skip_glyph ();
|
||||
end--;
|
||||
}
|
||||
|
||||
match_length--;
|
||||
action_idx++;
|
||||
}
|
||||
while (!(action & LigActionLast));
|
||||
buffer->move_to (end);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool ret;
|
||||
private:
|
||||
hb_aat_apply_context_t *c;
|
||||
const UnsizedArrayOf<HBUINT32> &ligAction;
|
||||
const UnsizedArrayOf<HBUINT16> &component;
|
||||
const UnsizedArrayOf<GlyphID> &ligature;
|
||||
unsigned int match_length;
|
||||
unsigned int match_positions[HB_MAX_CONTEXT_LENGTH];
|
||||
};
|
||||
|
||||
inline bool apply (hb_aat_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
||||
driver_context_t dc (this);
|
||||
driver_context_t dc (this, c);
|
||||
|
||||
StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
|
||||
driver.drive (&dc);
|
||||
@ -341,8 +430,9 @@ struct LigatureSubtable
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
/* The main sanitization is done at run-time. */
|
||||
return machine.sanitize (c);
|
||||
/* The rest of array sanitizations are done at run-time. */
|
||||
return c->check_struct (this) && machine.sanitize (c) &&
|
||||
ligAction && component && ligature;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user