[aat] Implement RearrangementSubtable
This commit is contained in:
parent
5dbbd0fdb9
commit
ca42d96129
@ -164,7 +164,7 @@ struct UnsizedArrayOf
|
||||
return_trace (c->check_array (arrayZ, arrayZ[0].static_size, count));
|
||||
}
|
||||
|
||||
protected:
|
||||
public:
|
||||
Type arrayZ[VAR];
|
||||
public:
|
||||
DEFINE_SIZE_ARRAY (0, arrayZ);
|
||||
@ -221,7 +221,7 @@ struct LookupSegmentSingle
|
||||
GlyphID first; /* First GlyphID in this segment */
|
||||
T value; /* The lookup value (only one) */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + sizeof (T));
|
||||
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -323,7 +323,7 @@ struct LookupSingle
|
||||
GlyphID glyph; /* Last GlyphID */
|
||||
T value; /* The lookup value (only one) */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + sizeof (T));
|
||||
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -424,7 +424,7 @@ struct Lookup
|
||||
};
|
||||
|
||||
|
||||
struct Class
|
||||
struct ClassTable
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
@ -448,6 +448,87 @@ struct Class
|
||||
DEFINE_SIZE_ARRAY (4, classArrayZ);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* (Extended) State Table
|
||||
*/
|
||||
|
||||
template <typename T>
|
||||
struct Entry
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) && data.sanitize (c));
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
|
||||
HBUINT16 flags; /* Table specific. */
|
||||
T data; /* Optional offsets to per-glyph tables. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4 + T::static_size);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Entry<void>
|
||||
{
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT16 newState; /* Byte offset from beginning of state table to the new state. */
|
||||
HBUINT16 flags; /* Table specific. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
|
||||
template <typename Types, typename Extra>
|
||||
struct StateTable
|
||||
{
|
||||
typedef typename Types::HBUINT HBUINT;
|
||||
typedef typename Types::HBUSHORT HBUSHORT;
|
||||
typedef typename Types::ClassType ClassType;
|
||||
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||
{ return (this+classTable).get_class (glyph_id, num_glyphs); }
|
||||
|
||||
|
||||
inline const Entry<Extra> *get_entry (unsigned int state, unsigned int klass) const
|
||||
{
|
||||
const HBUSHORT *states = (this+stateArrayTable).arrayZ;
|
||||
const Entry<Extra> *entries = (this+entryTable).arrayZ;
|
||||
|
||||
unsigned int entry = states[state * nClasses + klass]; /* XXX bound check. */
|
||||
|
||||
return &entries[entry]; /* XXX bound check. */
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (true);
|
||||
return_trace (c->check_struct (this)); /* XXX */
|
||||
}
|
||||
|
||||
protected:
|
||||
HBUINT nClasses; /* Number of classes, which is the number of indices
|
||||
* in a single line in the state array. */
|
||||
OffsetTo<ClassType, HBUINT>
|
||||
classTable; /* Offset to the class table. */
|
||||
OffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT>
|
||||
stateArrayTable;/* Offset to the state array. */
|
||||
OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT>
|
||||
entryTable; /* Offset to the entry array. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_UNION (2, format);
|
||||
};
|
||||
|
||||
|
||||
} /* namespace AAT */
|
||||
|
||||
|
||||
|
@ -39,21 +39,124 @@ namespace AAT {
|
||||
using namespace OT;
|
||||
|
||||
|
||||
template <typename Types>
|
||||
struct RearrangementSubtable
|
||||
{
|
||||
enum {
|
||||
MarkFirst = 0x8000,
|
||||
DontAdvance = 0x4000,
|
||||
MarkLast = 0x2000,
|
||||
Verb = 0x000F,
|
||||
};
|
||||
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
/* TODO */
|
||||
return_trace (false);
|
||||
|
||||
bool ret = false;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
unsigned int state = 0;
|
||||
unsigned int start = 0;
|
||||
unsigned int end = 0;
|
||||
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
unsigned int count = c->buffer->len;
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
unsigned int klass = machine.get_class (info[i].codepoint, num_glyphs);
|
||||
const Entry<void> *entry = machine.get_entry (state, klass);
|
||||
if (unlikely (!entry))
|
||||
break;
|
||||
|
||||
unsigned int flags = entry->flags;
|
||||
|
||||
if (flags & MarkFirst)
|
||||
start = i;
|
||||
|
||||
if (flags & MarkLast)
|
||||
end = i + 1;
|
||||
|
||||
if ((flags & Verb) && start < end)
|
||||
{
|
||||
/* The following map has two nibbles, for start-side
|
||||
* and end-side. Values of 0,1,2 mean move that many
|
||||
* to the other side. Value of 3 means move 2 and
|
||||
* flip them. */
|
||||
static const unsigned char map[16] =
|
||||
{
|
||||
0x00, /* 0 no change */
|
||||
0x10, /* 1 Ax => xA */
|
||||
0x01, /* 2 xD => Dx */
|
||||
0x11, /* 3 AxD => DxA */
|
||||
0x20, /* 4 ABx => xAB */
|
||||
0x30, /* 5 ABx => xBA */
|
||||
0x02, /* 6 xCD => CDx */
|
||||
0x03, /* 7 xCD => DCx */
|
||||
0x12, /* 8 AxCD => CDxA */
|
||||
0x13, /* 9 AxCD => DCxA */
|
||||
0x21, /* 10 ABxD => DxAB */
|
||||
0x31, /* 11 ABxD => DxBA */
|
||||
0x22, /* 12 ABxCD => CDxAB */
|
||||
0x32, /* 13 ABxCD => CDxBA */
|
||||
0x23, /* 14 ABxCD => DCxAB */
|
||||
0x33, /* 15 ABxCD => DCxBA */
|
||||
};
|
||||
|
||||
unsigned int m = map[flags & Verb];
|
||||
unsigned int l = MIN<unsigned int> (2, m >> 4);
|
||||
unsigned int r = MIN<unsigned int> (2, m & 0x0F);
|
||||
bool reverse_l = 3 == (m >> 4);
|
||||
bool reverse_r = 3 == (m & 0x0F);
|
||||
|
||||
if (end - start >= l + r)
|
||||
{
|
||||
c->buffer->merge_clusters (start, end);
|
||||
|
||||
hb_glyph_info_t buf[4];
|
||||
memcpy (buf, info + start, l * sizeof (buf[0]));
|
||||
memcpy (buf + 2, info + end - r, r * sizeof (buf[0]));
|
||||
|
||||
if (l != r)
|
||||
memmove (info + start + r - l, info + start + l, (end - start - l - r) * sizeof (buf[0]));
|
||||
|
||||
memcpy (info + start, buf + 2, r * sizeof (buf[0]));
|
||||
memcpy (info + end - l, buf, l * sizeof (buf[0]));
|
||||
if (reverse_l)
|
||||
{
|
||||
buf[0] = info[end - 1];
|
||||
info[end - 1] = info[end - 2];
|
||||
info[end - 2] = buf[0];
|
||||
}
|
||||
if (reverse_r)
|
||||
{
|
||||
buf[0] = info[start];
|
||||
info[start] = info[start + 1];
|
||||
info[start + 1] = buf[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (false/* XXX*/ && flags & DontAdvance)
|
||||
i--; /* XXX Detect infinite loop. */
|
||||
|
||||
state = entry->newState;
|
||||
}
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
inline bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
/* TODO */
|
||||
return_trace (false);
|
||||
return_trace (machine.sanitize (c, 0/*XXX*/));
|
||||
}
|
||||
|
||||
protected:
|
||||
StateTable<Types, void> machine;
|
||||
public:
|
||||
DEFINE_SIZE_MIN (2);
|
||||
};
|
||||
|
||||
struct ContextualSubtable
|
||||
@ -95,11 +198,12 @@ struct NoncontextualSubtable
|
||||
inline bool apply (hb_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
hb_glyph_info_t *info = buffer->info;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
bool ret = false;
|
||||
unsigned int count = buffer->len;
|
||||
unsigned int num_glyphs = c->face->get_num_glyphs ();
|
||||
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
unsigned int count = c->buffer->len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
const GlyphID *replacement = substitute.get_value (info[i].codepoint, num_glyphs);
|
||||
@ -109,6 +213,7 @@ struct NoncontextualSubtable
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
@ -163,11 +268,13 @@ struct Feature
|
||||
};
|
||||
|
||||
|
||||
template <typename HBUINT>
|
||||
template <typename Types>
|
||||
struct ChainSubtable
|
||||
{
|
||||
template <typename> struct Chain;
|
||||
friend struct Chain<HBUINT>;
|
||||
friend struct Chain<Types>;
|
||||
|
||||
typedef typename Types::HBUINT HBUINT;
|
||||
|
||||
inline unsigned int get_size (void) const { return length; }
|
||||
inline unsigned int get_type (void) const { return coverage & 0xFF; }
|
||||
@ -214,9 +321,10 @@ struct ChainSubtable
|
||||
protected:
|
||||
HBUINT length; /* Total subtable length, including this header. */
|
||||
HBUINT coverage; /* Coverage flags and subtable type. */
|
||||
HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
|
||||
HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
|
||||
union {
|
||||
RearrangementSubtable rearrangement;
|
||||
RearrangementSubtable<Types>
|
||||
rearrangement;
|
||||
ContextualSubtable contextual;
|
||||
LigatureSubtable ligature;
|
||||
NoncontextualSubtable noncontextual;
|
||||
@ -226,17 +334,19 @@ struct ChainSubtable
|
||||
DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
|
||||
};
|
||||
|
||||
template <typename HBUINT>
|
||||
template <typename Types>
|
||||
struct Chain
|
||||
{
|
||||
typedef typename Types::HBUINT HBUINT;
|
||||
|
||||
inline void apply (hb_apply_context_t *c) const
|
||||
{
|
||||
const ChainSubtable<HBUINT> *subtable = &StructAtOffset<ChainSubtable<HBUINT> > (featureZ, featureZ[0].static_size * featureCount);
|
||||
const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (featureZ, featureZ[0].static_size * featureCount);
|
||||
unsigned int count = subtableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
subtable->apply (c);
|
||||
subtable = &StructAfter<ChainSubtable<HBUINT> > (*subtable);
|
||||
subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
|
||||
}
|
||||
}
|
||||
|
||||
@ -253,13 +363,13 @@ struct Chain
|
||||
if (!c->check_array (featureZ, featureZ[0].static_size, featureCount))
|
||||
return_trace (false);
|
||||
|
||||
const ChainSubtable<HBUINT> *subtable = &StructAtOffset<ChainSubtable<HBUINT> > (featureZ, featureZ[0].static_size * featureCount);
|
||||
const ChainSubtable<Types> *subtable = &StructAtOffset<ChainSubtable<Types> > (featureZ, featureZ[0].static_size * featureCount);
|
||||
unsigned int count = subtableCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!subtable->sanitize (c))
|
||||
return_trace (false);
|
||||
subtable = &StructAfter<ChainSubtable<HBUINT> > (*subtable);
|
||||
subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
@ -272,7 +382,7 @@ struct Chain
|
||||
HBUINT subtableCount; /* The number of subtables in the chain. */
|
||||
|
||||
Feature featureZ[VAR]; /* Features. */
|
||||
ChainSubtable<HBUINT> subtableX[VAR]; /* Subtables. */
|
||||
ChainSubtable<Types> subtableX[VAR]; /* Subtables. */
|
||||
// subtableGlyphCoverageArray if major == 3
|
||||
|
||||
public:
|
||||
@ -284,20 +394,22 @@ struct Chain
|
||||
* The 'mort'/'morx' Tables
|
||||
*/
|
||||
|
||||
template <typename HBUINT>
|
||||
template <typename Types>
|
||||
struct mortmorx
|
||||
{
|
||||
static const hb_tag_t mortTag = HB_AAT_TAG_MORT;
|
||||
static const hb_tag_t morxTag = HB_AAT_TAG_MORX;
|
||||
|
||||
typedef typename Types::HBUINT HBUINT;
|
||||
|
||||
inline void apply (hb_apply_context_t *c) const
|
||||
{
|
||||
const Chain<HBUINT> *chain = chains;
|
||||
const Chain<Types> *chain = chains;
|
||||
unsigned int count = chainCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
chain->apply (c);
|
||||
chain = &StructAfter<Chain<HBUINT> > (*chain);
|
||||
chain = &StructAfter<Chain<Types> > (*chain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -305,17 +417,17 @@ struct mortmorx
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
if (!version.sanitize (c) ||
|
||||
version.major >> (sizeof (HBUINT) == 4) != 1 ||
|
||||
(version.major >> (sizeof (HBUINT) == 4 ? 1 : 0)) != 1 ||
|
||||
!chainCount.sanitize (c))
|
||||
return_trace (false);
|
||||
|
||||
const Chain<HBUINT> *chain = chains;
|
||||
const Chain<Types> *chain = chains;
|
||||
unsigned int count = chainCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (!chain->sanitize (c, version.major))
|
||||
return_trace (false);
|
||||
chain = &StructAfter<Chain<HBUINT> > (*chain);
|
||||
chain = &StructAfter<Chain<Types> > (*chain);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
@ -326,18 +438,44 @@ struct mortmorx
|
||||
* 1 for mort, 2 or 3 for morx. */
|
||||
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
|
||||
* table. */
|
||||
Chain<HBUINT> chains[VAR]; /* Chains. */
|
||||
Chain<Types> chains[VAR]; /* Chains. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
struct mort : mortmorx<HBUINT16>
|
||||
struct MorxTypes
|
||||
{
|
||||
typedef HBUINT32 HBUINT;
|
||||
typedef HBUINT16 HBUSHORT;
|
||||
struct ClassType : Lookup<HBUINT16>
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
|
||||
{
|
||||
const HBUINT16 *v = get_value (glyph_id, num_glyphs);
|
||||
return v ? *v : 1;
|
||||
}
|
||||
};
|
||||
};
|
||||
struct MortTypes
|
||||
{
|
||||
typedef HBUINT16 HBUINT;
|
||||
typedef HBUINT8 HBUSHORT;
|
||||
struct ClassType : ClassTable
|
||||
{
|
||||
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs HB_UNUSED) const
|
||||
{
|
||||
return ClassTable::get_class (glyph_id);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct mort : mortmorx<MortTypes>
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_AAT_TAG_MORT;
|
||||
};
|
||||
|
||||
struct morx : mortmorx<HBUINT32>
|
||||
struct morx : mortmorx<MorxTypes>
|
||||
{
|
||||
static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
|
||||
};
|
||||
|
@ -527,8 +527,6 @@ struct Supplier
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* The OpenType Font File: Data Types
|
||||
|
@ -298,9 +298,10 @@ static_assert ((sizeof (hb_var_int_t) == 4), "");
|
||||
|
||||
/* Misc */
|
||||
|
||||
/* Void! */
|
||||
struct _hb_void_t {};
|
||||
typedef const _hb_void_t *hb_void_t;
|
||||
/*
|
||||
* Void!
|
||||
*/
|
||||
typedef const struct _hb_void_t *hb_void_t;
|
||||
#define HB_VOID ((const _hb_void_t *) nullptr)
|
||||
|
||||
/* Return the number of 1 bits in mask. */
|
||||
|
Loading…
Reference in New Issue
Block a user