[kern] Refactor to include header in each subtable type

This commit is contained in:
Behdad Esfahbod 2018-11-06 12:07:15 -05:00
parent b0da2cd0b9
commit 213fa3bf71
1 changed files with 91 additions and 98 deletions

View File

@ -155,6 +155,7 @@ struct KernPair
DEFINE_SIZE_STATIC (6);
};
template <typename KernSubTableHeader>
struct KernSubTableFormat0
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
@ -186,11 +187,13 @@ struct KernSubTableFormat0
}
protected:
BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */
KernSubTableHeader header;
BinSearchArrayOf<KernPair> pairs; /* Array of kerning pairs. */
public:
DEFINE_SIZE_ARRAY (8, pairs);
DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 8, pairs);
};
template <typename KernSubTableHeader>
struct KernSubTableFormat1
{
typedef void EntryData;
@ -309,10 +312,11 @@ struct KernSubTableFormat1
}
protected:
KernSubTableHeader header;
AAT::StateTable<AAT::MortTypes, EntryData> machine;
OffsetTo<UnsizedArrayOf<FWORD>, HBUINT16, false> kernAction;
public:
DEFINE_SIZE_STATIC (10);
DEFINE_SIZE_STATIC (KernSubTableHeader::static_size + 10);
};
struct KernClassTable
@ -333,6 +337,7 @@ struct KernClassTable
DEFINE_SIZE_ARRAY (4, classes);
};
template <typename KernSubTableHeader>
struct KernSubTableFormat2
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right,
@ -393,20 +398,19 @@ struct KernSubTableFormat2
}
protected:
HBUINT16 rowWidth; /* The width, in bytes, of a row in the table. */
OffsetTo<KernClassTable>
leftClassTable; /* Offset from beginning of this subtable to
* left-hand class table. */
OffsetTo<KernClassTable>
rightClassTable;/* Offset from beginning of this subtable to
* right-hand class table. */
OffsetTo<FWORD>
array; /* Offset from beginning of this subtable to
* the start of the kerning array. */
KernSubTableHeader header;
HBUINT16 rowWidth; /* The width, in bytes, of a row in the table. */
OffsetTo<KernClassTable> leftClassTable; /* Offset from beginning of this subtable to
* left-hand class table. */
OffsetTo<KernClassTable> rightClassTable;/* Offset from beginning of this subtable to
* right-hand class table. */
OffsetTo<FWORD> array; /* Offset from beginning of this subtable to
* the start of the kerning array. */
public:
DEFINE_SIZE_MIN (8);
DEFINE_SIZE_MIN (KernSubTableHeader::static_size + 8);
};
template <typename KernSubTableHeader>
struct KernSubTableFormat3
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
@ -448,44 +452,52 @@ struct KernSubTableFormat3
}
protected:
HBUINT16 glyphCount; /* The number of glyphs in this font. */
HBUINT8 kernValueCount; /* The number of kerning values. */
HBUINT8 leftClassCount; /* The number of left-hand classes. */
HBUINT8 rightClassCount;/* The number of right-hand classes. */
HBUINT8 flags; /* Set to zero (reserved for future use). */
UnsizedArrayOf<FWORD>
kernValueZ; /* The kerning values.
* Length kernValueCount. */
KernSubTableHeader header;
HBUINT16 glyphCount; /* The number of glyphs in this font. */
HBUINT8 kernValueCount; /* The number of kerning values. */
HBUINT8 leftClassCount; /* The number of left-hand classes. */
HBUINT8 rightClassCount;/* The number of right-hand classes. */
HBUINT8 flags; /* Set to zero (reserved for future use). */
UnsizedArrayOf<FWORD> kernValueZ; /* The kerning values.
* Length kernValueCount. */
#if 0
UnsizedArrayOf<HBUINT8>
leftClass; /* The left-hand classes.
* Length glyphCount. */
UnsizedArrayOf<HBUINT8>
RightClass; /* The right-hand classes.
* Length glyphCount. */
UnsizedArrayOf<HBUINT8>
kernIndex; /* The indices into the kernValue array.
* Length leftClassCount * rightClassCount */
UnsizedArrayOf<HBUINT8>leftClass; /* The left-hand classes.
* Length glyphCount. */
UnsizedArrayOf<HBUINT8>rightClass; /* The right-hand classes.
* Length glyphCount. */
UnsizedArrayOf<HBUINT8>kernIndex; /* The indices into the kernValue array.
* Length leftClassCount * rightClassCount */
#endif
public:
DEFINE_SIZE_ARRAY (6, kernValueZ);
DEFINE_SIZE_ARRAY (KernSubTableHeader::static_size + 6, kernValueZ);
};
template <typename KernSubTableHeader>
struct KernSubTable
{
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int format) const
inline unsigned int get_size (void) const { return u.header.length; }
inline bool is_simple (void) const
{ return !(u.header.coverage & (u.header.CrossStream | u.header.Variation)); }
inline bool is_horizontal (void) const
{ return (u.header.coverage & u.header.Direction) == u.header.DirectionHorizontal; }
inline bool is_override (void) const
{ return bool (u.header.coverage & u.header.Override); }
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
switch (format) {
switch (u.header.format) {
/* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */
case 0: return u.format0.get_kerning (left, right);
default:return 0;
}
}
inline void apply (AAT::hb_aat_apply_context_t *c, unsigned int format) const
inline void apply (AAT::hb_aat_apply_context_t *c) const
{
/* TODO Switch to dispatch(). */
switch (format) {
switch (u.header.format) {
case 0: u.format0.apply (c); return;
case 1: u.format1.apply (c); return;
case 2: u.format2.apply (c); return;
@ -494,10 +506,13 @@ struct KernSubTable
}
}
inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
switch (format) {
if (unlikely (!u.header.sanitize (c) ||
u.header.length < u.header.min_size ||
!c->check_range (this, u.header.length))) return_trace (false);
switch (u.header.format) {
case 0: return_trace (u.format0.sanitize (c));
case 1: return_trace (u.format1.sanitize (c));
case 2: return_trace (u.format2.sanitize (c));
@ -508,49 +523,17 @@ struct KernSubTable
protected:
union {
KernSubTableFormat0 format0;
KernSubTableFormat1 format1;
KernSubTableFormat2 format2;
KernSubTableFormat3 format3;
KernSubTableHeader header;
KernSubTableFormat0<KernSubTableHeader> format0;
KernSubTableFormat1<KernSubTableHeader> format1;
KernSubTableFormat2<KernSubTableHeader> format2;
KernSubTableFormat3<KernSubTableHeader> format3;
} u;
public:
DEFINE_SIZE_MIN (0);
};
template <typename T>
struct KernSubTableWrapper
{
/* https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern */
inline const T* thiz (void) const { return static_cast<const T *> (this); }
inline bool is_simple (void) const
{ return !(thiz()->coverage & (T::CrossStream | T::Variation)); }
inline bool is_horizontal (void) const
{ return (thiz()->coverage & T::Direction) == T::DirectionHorizontal; }
inline bool is_override (void) const
{ return bool (thiz()->coverage & T::Override); }
inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{ return thiz()->subtable.get_kerning (left, right, thiz()->format); }
inline void apply (AAT::hb_aat_apply_context_t *c) const
{ thiz()->subtable.apply (c, thiz()->format); }
inline unsigned int get_size (void) const { return thiz()->length; }
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (thiz()) &&
thiz()->length >= T::min_size &&
c->check_range (thiz(), thiz()->length) &&
thiz()->subtable.sanitize (c, thiz()->format));
}
};
template <typename T>
struct KernTable
{
@ -559,8 +542,10 @@ struct KernTable
inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const
{
typedef KernSubTable<typename T::SubTableHeader> SubTable;
int v = 0;
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
const SubTable *st = CastP<SubTable> (&thiz()->dataZ);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
@ -569,15 +554,17 @@ struct KernTable
if (st->is_override ())
v = 0;
v += st->get_kerning (left, right);
st = &StructAfter<typename T::SubTableWrapper> (*st);
st = &StructAfter<SubTable> (*st);
}
return v;
}
inline void apply (AAT::hb_aat_apply_context_t *c) const
{
typedef KernSubTable<typename T::SubTableHeader> SubTable;
c->set_lookup_index (0);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
const SubTable *st = CastP<SubTable> (&thiz()->dataZ);
unsigned int count = thiz()->nTables;
/* If there's an override subtable, skip subtables before that. */
unsigned int last_override = 0;
@ -585,9 +572,9 @@ struct KernTable
{
if (st->is_simple () && st->is_override ())
last_override = i;
st = &StructAfter<typename T::SubTableWrapper> (*st);
st = &StructAfter<SubTable> (*st);
}
st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
st = CastP<SubTable> (&thiz()->dataZ);
for (unsigned int i = 0; i < count; i++)
{
if (!st->is_simple ())
@ -609,7 +596,7 @@ struct KernTable
(void) c->buffer->message (c->font, "end kern subtable %d", c->lookup_index);
skip:
st = &StructAfter<typename T::SubTableWrapper> (*st);
st = &StructAfter<SubTable> (*st);
}
}
@ -620,13 +607,15 @@ struct KernTable
thiz()->version != T::VERSION))
return_trace (false);
const typename T::SubTableWrapper *st = CastP<typename T::SubTableWrapper> (&thiz()->dataZ);
typedef KernSubTable<typename T::SubTableHeader> SubTable;
const SubTable *st = CastP<SubTable> (&thiz()->dataZ);
unsigned int count = thiz()->nTables;
for (unsigned int i = 0; i < count; i++)
{
if (unlikely (!st->sanitize (c)))
return_trace (false);
st = &StructAfter<typename T::SubTableWrapper> (*st);
st = &StructAfter<SubTable> (*st);
}
return_trace (true);
@ -639,11 +628,8 @@ struct KernOT : KernTable<KernOT>
static const uint16_t VERSION = 0x0000u;
struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
struct SubTableHeader
{
friend struct KernTable<KernOT>;
friend struct KernSubTableWrapper<SubTableWrapper>;
enum Coverage
{
Direction = 0x01u,
@ -656,14 +642,19 @@ struct KernOT : KernTable<KernOT>
DirectionHorizontal= 0x01u
};
protected:
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
public:
HBUINT16 versionZ; /* Unused. */
HBUINT16 length; /* Length of the subtable (including this header). */
HBUINT8 format; /* Subtable format. */
HBUINT8 coverage; /* Coverage bits. */
KernSubTable subtable; /* Subtable data. */
public:
DEFINE_SIZE_MIN (6);
DEFINE_SIZE_STATIC (6);
};
protected:
@ -680,11 +671,8 @@ struct KernAAT : KernTable<KernAAT>
static const uint32_t VERSION = 0x00010000u;
struct SubTableWrapper : KernSubTableWrapper<SubTableWrapper>
struct SubTableHeader
{
friend struct KernTable<KernAAT>;
friend struct KernSubTableWrapper<SubTableWrapper>;
enum Coverage
{
Direction = 0x80u,
@ -696,15 +684,20 @@ struct KernAAT : KernTable<KernAAT>
DirectionHorizontal= 0x00u
};
protected:
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
}
public:
HBUINT32 length; /* Length of the subtable (including this header). */
HBUINT8 coverage; /* Coverage bits. */
HBUINT8 format; /* Subtable format. */
HBUINT16 tupleIndex; /* The tuple index (used for variations fonts).
* This value specifies which tuple this subtable covers. */
KernSubTable subtable; /* Subtable data. */
public:
DEFINE_SIZE_MIN (8);
DEFINE_SIZE_STATIC (8);
};
protected: