[kern] Refactor to include header in each subtable type
This commit is contained in:
parent
b0da2cd0b9
commit
213fa3bf71
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue