[kerx] Implement variation-kerning tables (without the variation part)

SFSNDisplay uses these.  We just apply the default kern without
variations right now.  But at least makes the default kern work.
This commit is contained in:
Behdad Esfahbod 2018-10-19 16:06:54 -07:00
parent f7c0b4319c
commit 29d877518f
1 changed files with 29 additions and 8 deletions

View File

@ -45,6 +45,21 @@ namespace AAT {
using namespace OT; using namespace OT;
static inline int
kerxTupleKern (int value,
unsigned int tupleCount,
const void *base,
hb_aat_apply_context_t *c)
{
if (likely (!tupleCount)) return value;
unsigned int offset = value;
const FWORD *pv = &StructAtOffset<FWORD> (base, offset);
if (unlikely (!pv->sanitize (&c->sanitizer))) return 0;
return *pv;
}
struct KerxSubTableHeader struct KerxSubTableHeader
{ {
inline bool sanitize (hb_sanitize_context_t *c) const inline bool sanitize (hb_sanitize_context_t *c) const
@ -65,6 +80,7 @@ struct KerxSubTableFormat0
{ {
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{ {
if (header.tupleCount) return 0; /* TODO kerxTupleKern */
hb_glyph_pair_t pair = {left, right}; hb_glyph_pair_t pair = {left, right};
int i = pairs.bsearch (pair); int i = pairs.bsearch (pair);
return i == -1 ? 0 : pairs[i].get_kerning (); return i == -1 ? 0 : pairs[i].get_kerning ();
@ -201,6 +217,9 @@ struct KerxSubTableFormat1
if (!c->plan->requested_kerning) if (!c->plan->requested_kerning)
return false; return false;
if (header.tupleCount)
return_trace (false); /* TODO kerxTupleKern */
driver_context_t dc (this, c); driver_context_t dc (this, c);
StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face);
@ -236,7 +255,7 @@ struct KerxSubTableFormat2
unsigned int offset = l + r; unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset); const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset);
if (unlikely (!v->sanitize (&c->sanitizer))) return 0; if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v; return kerxTupleKern (*v, header.tupleCount, this, c);
} }
inline bool apply (hb_aat_apply_context_t *c) const inline bool apply (hb_aat_apply_context_t *c) const
@ -482,7 +501,7 @@ struct KerxSubTableFormat6
if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0; if (unlikely (hb_unsigned_mul_overflows (offset, sizeof (FWORD32)))) return 0;
const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32)); const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32));
if (unlikely (!v->sanitize (&c->sanitizer))) return 0; if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v; return kerxTupleKern (*v, header.tupleCount, &(this+vector), c);
} }
else else
{ {
@ -492,7 +511,7 @@ struct KerxSubTableFormat6
unsigned int offset = l + r; unsigned int offset = l + r;
const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD)); const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD));
if (unlikely (!v->sanitize (&c->sanitizer))) return 0; if (unlikely (!v->sanitize (&c->sanitizer))) return 0;
return *v; return kerxTupleKern (*v, header.tupleCount, &(this+vector), c);
} }
} }
@ -523,7 +542,9 @@ struct KerxSubTableFormat6
u.s.rowIndexTable.sanitize (c, this) && u.s.rowIndexTable.sanitize (c, this) &&
u.s.columnIndexTable.sanitize (c, this) && u.s.columnIndexTable.sanitize (c, this) &&
c->check_range (this, u.s.array) c->check_range (this, u.s.array)
)))); )) &&
(header.tupleCount == 0 ||
c->check_range (this, vector))));
} }
struct accelerator_t struct accelerator_t
@ -559,8 +580,9 @@ struct KerxSubTableFormat6
LOffsetTo<UnsizedArrayOf<FWORD>, false> array; LOffsetTo<UnsizedArrayOf<FWORD>, false> array;
} s; } s;
} u; } u;
LOffsetTo<UnsizedArrayOf<FWORD>, false> vector;
public: public:
DEFINE_SIZE_STATIC (32); DEFINE_SIZE_STATIC (36);
}; };
struct KerxTable struct KerxTable
@ -642,9 +664,8 @@ struct kerx
{ {
bool reverse; bool reverse;
if (table->u.header.coverage & (KerxTable::CrossStream | KerxTable::Variation) || if (table->u.header.coverage & (KerxTable::CrossStream))
table->u.header.tupleCount) goto skip; /* We do NOT handle cross-stream. */
goto skip; /* We do NOT handle cross-stream or variation kerning. */
if (HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) != if (HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
bool (table->u.header.coverage & KerxTable::Vertical)) bool (table->u.header.coverage & KerxTable::Vertical))