[kerx] Use GPOS attachment facilities for CrossStream kerning

This commit is contained in:
Behdad Esfahbod 2018-11-07 14:38:29 -05:00
parent e10a856eb2
commit b2f687c256
1 changed files with 35 additions and 16 deletions

View File

@ -236,9 +236,7 @@ struct KerxSubTableFormat1
* other subtables in kerx. Discovered via testing. */ * other subtables in kerx. Discovered via testing. */
kernAction (&table->machine + table->kernAction), kernAction (&table->machine + table->kernAction),
depth (0), depth (0),
crossStream (table->header.coverage & table->header.CrossStream), crossStream (table->header.coverage & table->header.CrossStream) {}
crossOffset (0) {}
/* TODO /* TODO
* 'kern' table has this pecularity, we don't currently implement. * 'kern' table has this pecularity, we don't currently implement.
@ -307,21 +305,25 @@ struct KerxSubTableFormat1
/* "The end of the list is marked by an odd value..." Ignore it. */ /* "The end of the list is marked by an odd value..." Ignore it. */
v &= ~1; v &= ~1;
hb_glyph_position_t &o = buffer->pos[idx];
/* The following flag is undocumented in the spec, but described /* The following flag is undocumented in the spec, but described
* in the 'kern' table example. */ * in the 'kern' table example. */
if (v == -0x8000) if (v == -0x8000)
{ {
crossOffset = 0; o.attach_type() = ATTACH_TYPE_NONE;
v = 0; o.attach_chain() = 0;
o.x_offset = o.y_offset = 0;
} }
else if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
{ {
if (crossStream) if (crossStream)
{ {
crossOffset += v; if (buffer->pos[idx].attach_type() && !buffer->pos[idx].y_offset)
if (!buffer->pos[idx].y_offset) {
buffer->pos[idx].y_offset += c->font->em_scale_y (crossOffset); o.y_offset = c->font->em_scale_y (v);
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
} }
else if (buffer->info[idx].mask & kern_mask) else if (buffer->info[idx].mask & kern_mask)
{ {
@ -337,9 +339,11 @@ struct KerxSubTableFormat1
if (crossStream) if (crossStream)
{ {
/* CoreText doesn't do crossStream kerning in vertical. We do. */ /* CoreText doesn't do crossStream kerning in vertical. We do. */
crossOffset += v; if (buffer->pos[idx].attach_type() && !buffer->pos[idx].x_offset)
if (!buffer->pos[idx].x_offset) {
buffer->pos[idx].x_offset = c->font->em_scale_x (crossOffset); o.x_offset = c->font->em_scale_x (v);
buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT;
}
} }
else if (buffer->info[idx].mask & kern_mask) else if (buffer->info[idx].mask & kern_mask)
{ {
@ -353,8 +357,6 @@ struct KerxSubTableFormat1
} }
depth = 0; depth = 0;
} }
else
buffer->pos[buffer->idx].y_offset += c->font->em_scale_y (crossOffset);
return true; return true;
} }
@ -366,7 +368,6 @@ struct KerxSubTableFormat1
unsigned int stack[8]; unsigned int stack[8];
unsigned int depth; unsigned int depth;
bool crossStream; bool crossStream;
int crossOffset;
}; };
inline bool apply (hb_aat_apply_context_t *c) const inline bool apply (hb_aat_apply_context_t *c) const
@ -875,6 +876,7 @@ struct KerxTable
{ {
typedef typename T::SubTable SubTable; typedef typename T::SubTable SubTable;
bool seenCrossStream = false;
c->set_lookup_index (0); c->set_lookup_index (0);
const SubTable *st = &thiz()->firstSubTable; const SubTable *st = &thiz()->firstSubTable;
unsigned int count = thiz()->tableCount; unsigned int count = thiz()->tableCount;
@ -894,6 +896,23 @@ struct KerxTable
if (!c->buffer->message (c->font, "start %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index)) if (!c->buffer->message (c->font, "start %c%c%c%c subtable %d", HB_UNTAG (thiz()->tableTag), c->lookup_index))
goto skip; goto skip;
if (!seenCrossStream &&
(st->u.header.coverage & st->u.header.CrossStream))
{
/* Attach all glyphs into a chain. */
seenCrossStream = true;
hb_glyph_position_t *pos = c->buffer->pos;
unsigned int count = c->buffer->len;
for (unsigned int i = 0; i < count; i++)
{
pos[i].attach_type() = ATTACH_TYPE_CURSIVE;
pos[i].attach_chain() = HB_DIRECTION_IS_FORWARD (c->buffer->props.direction) ? -1 : +1;
/* We intentionally don't set HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT,
* since there needs to be a non-zero attachment for post-positioning to
* be needed. */
}
}
if (reverse) if (reverse)
c->buffer->reverse (); c->buffer->reverse ();