[kern] Implement CrossStream kerning
This commit is contained in:
parent
b11830c09e
commit
01bf43ac01
|
@ -62,6 +62,20 @@ kerxTupleKern (int value,
|
|||
|
||||
struct KerxSubTableHeader
|
||||
{
|
||||
enum Coverage
|
||||
{
|
||||
Vertical = 0x80000000, /* Set if table has vertical kerning values. */
|
||||
CrossStream = 0x40000000, /* Set if table has cross-stream kerning values. */
|
||||
Variation = 0x20000000, /* Set if table has variation kerning values. */
|
||||
Backwards = 0x10000000, /* If clear, process the glyphs forwards, that
|
||||
* is, from first to last in the glyph stream.
|
||||
* If we, process them from last to first.
|
||||
* This flag only applies to state-table based
|
||||
* 'kerx' subtables (types 1 and 4). */
|
||||
Reserved = 0x0FFFFF00, /* Reserved, set to zero. */
|
||||
SubtableType = 0x000000FF, /* Subtable type. */
|
||||
};
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -95,6 +109,9 @@ struct KerxSubTableFormat0
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -161,7 +178,8 @@ struct KerxSubTableFormat1
|
|||
* similar to offsets in morx table, NOT from beginning of this table, like
|
||||
* other subtables in kerx. Discovered via testing. */
|
||||
kernAction (&table->machine + table->kernAction),
|
||||
depth (0) {}
|
||||
depth (0),
|
||||
crossStream (table->header.coverage & table->header.CrossStream) {}
|
||||
|
||||
inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
|
||||
const Entry<EntryData> *entry)
|
||||
|
@ -209,15 +227,25 @@ struct KerxSubTableFormat1
|
|||
{
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
buffer->pos[idx].x_advance += c->font->em_scale_x (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
if (crossStream)
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].x_advance += c->font->em_scale_x (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].y_advance += c->font->em_scale_y (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
if (crossStream)
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].y_advance += c->font->em_scale_y (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -232,6 +260,7 @@ struct KerxSubTableFormat1
|
|||
const UnsizedArrayOf<FWORD> &kernAction;
|
||||
unsigned int stack[8];
|
||||
unsigned int depth;
|
||||
bool crossStream;
|
||||
};
|
||||
|
||||
inline bool apply (hb_aat_apply_context_t *c) const
|
||||
|
@ -241,6 +270,9 @@ struct KerxSubTableFormat1
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
if (header.tupleCount)
|
||||
return_trace (false); /* TODO kerxTupleKern */
|
||||
|
||||
|
@ -289,6 +321,9 @@ struct KerxSubTableFormat2
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -547,6 +582,9 @@ struct KerxSubTableFormat6
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -615,21 +653,7 @@ struct KerxTable
|
|||
friend struct kerx;
|
||||
|
||||
inline unsigned int get_size (void) const { return u.header.length; }
|
||||
inline unsigned int get_type (void) const { return u.header.coverage & SubtableType; }
|
||||
|
||||
enum Coverage
|
||||
{
|
||||
Vertical = 0x80000000, /* Set if table has vertical kerning values. */
|
||||
CrossStream = 0x40000000, /* Set if table has cross-stream kerning values. */
|
||||
Variation = 0x20000000, /* Set if table has variation kerning values. */
|
||||
Backwards = 0x10000000, /* If clear, process the glyphs forwards, that
|
||||
* is, from first to last in the glyph stream.
|
||||
* If we, process them from last to first.
|
||||
* This flag only applies to state-table based
|
||||
* 'kerx' subtables (types 1 and 4). */
|
||||
Reserved = 0x0FFFFF00, /* Reserved, set to zero. */
|
||||
SubtableType = 0x000000FF, /* Subtable type. */
|
||||
};
|
||||
inline unsigned int get_type (void) const { return u.header.coverage & u.header.SubtableType; }
|
||||
|
||||
template <typename context_t>
|
||||
inline typename context_t::return_t dispatch (context_t *c) const
|
||||
|
@ -689,14 +713,11 @@ struct kerx
|
|||
{
|
||||
bool reverse;
|
||||
|
||||
if (table->u.header.coverage & (KerxTable::CrossStream))
|
||||
goto skip; /* We do NOT handle cross-stream. */
|
||||
|
||||
if (HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
|
||||
bool (table->u.header.coverage & KerxTable::Vertical))
|
||||
bool (table->u.header.coverage & table->u.header.Vertical))
|
||||
goto skip;
|
||||
|
||||
reverse = bool (table->u.header.coverage & KerxTable::Backwards) !=
|
||||
reverse = bool (table->u.header.coverage & table->u.header.Backwards) !=
|
||||
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
|
||||
|
||||
if (!c->buffer->message (c->font, "start kerx subtable %d", c->lookup_index))
|
||||
|
|
|
@ -174,6 +174,9 @@ struct KernSubTableFormat0
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
hb_kern_machine_t<KernSubTableFormat0> machine (*this);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
||||
|
@ -218,7 +221,9 @@ struct KernSubTableFormat1
|
|||
* similar to offsets in morx table, NOT from beginning of this table, like
|
||||
* other subtables in kerx. Discovered via testing. */
|
||||
kernAction (&table->machine + table->kernAction),
|
||||
depth (0) {}
|
||||
depth (0),
|
||||
crossStream (table->header.coverage & table->header.CrossStream),
|
||||
crossOffset (0) {}
|
||||
|
||||
inline bool is_actionable (AAT::StateTableDriver<AAT::MortTypes, EntryData> *driver HB_UNUSED,
|
||||
const AAT::Entry<EntryData> *entry)
|
||||
|
@ -241,7 +246,9 @@ struct KernSubTableFormat1
|
|||
|
||||
if (entry->flags & Offset)
|
||||
{
|
||||
unsigned int kernIndex = AAT::MortTypes::offsetToIndex (entry->flags & Offset, &table->machine, kernAction.arrayZ);
|
||||
unsigned int kernIndex = AAT::MortTypes::offsetToIndex (entry->flags & Offset,
|
||||
&table->machine,
|
||||
kernAction.arrayZ);
|
||||
const FWORD *actions = &kernAction[kernIndex];
|
||||
if (!c->sanitizer.check_array (actions, depth))
|
||||
{
|
||||
|
@ -258,21 +265,50 @@ struct KernSubTableFormat1
|
|||
* list. Discovered by testing. */
|
||||
unsigned int idx = stack[i];
|
||||
int v = *actions++;
|
||||
|
||||
/* The following two flags are undocumented in the spec, but described
|
||||
* in the example. */
|
||||
bool last = v & 1;
|
||||
v = v & ~1;
|
||||
if (v == 0x8000)
|
||||
{
|
||||
crossOffset = 0;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
if (idx < buffer->len && buffer->info[idx].mask & kern_mask)
|
||||
{
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
|
||||
{
|
||||
buffer->pos[idx].x_advance += c->font->em_scale_x (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
if (crossStream)
|
||||
{
|
||||
crossOffset += v;
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (crossOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].x_advance += c->font->em_scale_x (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (v);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].y_advance += c->font->em_scale_y (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
if (crossStream)
|
||||
{
|
||||
crossOffset += v;
|
||||
buffer->pos[idx].x_offset += c->font->em_scale_x (crossOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer->pos[idx].y_advance += c->font->em_scale_y (v);
|
||||
if (HB_DIRECTION_IS_BACKWARD (buffer->props.direction))
|
||||
buffer->pos[idx].y_offset += c->font->em_scale_y (v);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last)
|
||||
break;
|
||||
}
|
||||
depth = 0;
|
||||
}
|
||||
|
@ -286,6 +322,8 @@ struct KernSubTableFormat1
|
|||
const UnsizedArrayOf<FWORD> &kernAction;
|
||||
unsigned int stack[8];
|
||||
unsigned int depth;
|
||||
bool crossStream;
|
||||
int crossOffset;
|
||||
};
|
||||
|
||||
inline bool apply (AAT::hb_aat_apply_context_t *c) const
|
||||
|
@ -344,6 +382,9 @@ struct KernSubTableFormat2
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
accelerator_t accel (*this, c);
|
||||
hb_kern_machine_t<accelerator_t> machine (accel);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
@ -412,6 +453,9 @@ struct KernSubTableFormat3
|
|||
if (!c->plan->requested_kerning)
|
||||
return false;
|
||||
|
||||
if (header.coverage & header.CrossStream)
|
||||
return false;
|
||||
|
||||
hb_kern_machine_t<KernSubTableFormat3> machine (*this);
|
||||
machine.kern (c->font, c->buffer, c->plan->kern_mask);
|
||||
|
||||
|
@ -547,8 +591,7 @@ struct KernTable
|
|||
st = CastP<SubTable> (&thiz()->dataZ);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (st->u.header.coverage &
|
||||
(st->u.header.Variation | st->u.header.CrossStream))
|
||||
if (st->u.header.coverage & st->u.header.Variation)
|
||||
goto skip;
|
||||
|
||||
if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) !=
|
||||
|
|
Loading…
Reference in New Issue