DEFINE_SIZE_STATIC (4);
};
-template <typename Extra>
+template <typename Types, typename Extra>
struct StateTable
{
+ typedef typename Types::HBUINT HBUINT;
+ typedef typename Types::HBUSHORT HBUSHORT;
+ typedef typename Types::ClassType ClassType;
+
enum State
{
STATE_START_OF_TEXT = 0,
}
protected:
- HBUINT32 nClasses; /* Number of classes, which is the number of indices
+ HBUINT nClasses; /* Number of classes, which is the number of indices
* in a single line in the state array. */
- LOffsetTo<Lookup<HBUINT16>, false>
+ OffsetTo<ClassType, HBUINT, false>
classTable; /* Offset to the class table. */
- LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
+ OffsetTo<UnsizedArrayOf<HBUSHORT>, HBUINT, false>
stateArrayTable;/* Offset to the state array. */
- LOffsetTo<UnsizedArrayOf<Entry<Extra> >, false>
+ OffsetTo<UnsizedArrayOf<Entry<Extra> >, HBUINT, false>
entryTable; /* Offset to the entry array. */
public:
DEFINE_SIZE_STATIC (16);
};
-template <typename EntryData>
+struct ClassTable
+{
+ inline unsigned int get_class (hb_codepoint_t glyph_id) const
+ {
+ return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? classArrayZ[glyph_id - firstGlyph] : 1;
+ }
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && classArrayZ.sanitize (c, glyphCount));
+ }
+ protected:
+ GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
+ * glyph minus the value of firstGlyph plus 1). */
+ UnsizedArrayOf<HBUINT8>
+ classArrayZ; /* The class codes (indexed by glyph index minus
+ * firstGlyph). */
+ public:
+ DEFINE_SIZE_ARRAY (4, classArrayZ);
+};
+
+struct MortTypes
+{
+ static const bool extended = false;
+ 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 MorxTypes
+{
+ static const bool extended = true;
+ 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;
+ }
+ };
+};
+
+template <typename Types, typename EntryData>
struct StateTableDriver
{
- inline StateTableDriver (const StateTable<EntryData> &machine_,
+ inline StateTableDriver (const StateTable<Types, EntryData> &machine_,
hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
if (!c->in_place)
buffer->clear_output ();
- unsigned int state = StateTable<EntryData>::STATE_START_OF_TEXT;
+ unsigned int state = StateTable<Types, EntryData>::STATE_START_OF_TEXT;
bool last_was_dont_advance = false;
for (buffer->idx = 0; buffer->successful;)
{
unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
- (unsigned) StateTable<EntryData>::CLASS_END_OF_TEXT;
+ (unsigned) StateTable<Types, EntryData>::CLASS_END_OF_TEXT;
const Entry<EntryData> *entry = machine.get_entryZ (state, klass);
if (unlikely (!entry))
break;
/* If there's no action and we're just epsilon-transitioning to state 0,
* safe to break. */
if (c->is_actionable (this, entry) ||
- !(entry->newState == StateTable<EntryData>::STATE_START_OF_TEXT &&
+ !(entry->newState == StateTable<Types, EntryData>::STATE_START_OF_TEXT &&
entry->flags == context_t::DontAdvance))
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
}
}
public:
- const StateTable<EntryData> &machine;
+ const StateTable<Types, EntryData> &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
};
/*
* morx -- Extended Glyph Metamorphosis
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
*/
#define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
namespace AAT {
using namespace OT;
-
+template <typename Types>
struct RearrangementSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
typedef void EntryData;
struct driver_context_t
ret (false),
start (0), end (0) {}
- inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+ inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
const Entry<EntryData> *entry)
{
return (entry->flags & Verb) && start < end;
}
- inline bool transition (StateTableDriver<EntryData> *driver,
+ inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
driver_context_t dc (this);
- StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
}
protected:
- StateTable<EntryData> machine;
+ StateTable<Types, EntryData> machine;
public:
DEFINE_SIZE_STATIC (16);
};
+template <typename Types>
struct ContextualSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
struct EntryData
{
HBUINT16 markIndex; /* Index of the substitution table for the
mark (0),
subs (table+table->substitutionTables) {}
- inline bool is_actionable (StateTableDriver<EntryData> *driver,
+ inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
}
- inline bool transition (StateTableDriver<EntryData> *driver,
+ inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
driver_context_t dc (this);
- StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
}
protected:
- StateTable<EntryData>
+ StateTable<Types, EntryData>
machine;
- LOffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT32, false>, false>
+ OffsetTo<UnsizedOffsetListOf<Lookup<GlyphID>, HBUINT, false>, HBUINT, false>
substitutionTables;
public:
DEFINE_SIZE_STATIC (20);
};
+template <typename Types>
struct LigatureSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
struct EntryData
{
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
ligature (table+table->ligature),
match_length (0) {}
- inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+ inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
const Entry<EntryData> *entry)
{
return entry->flags & PerformAction;
}
- inline bool transition (StateTableDriver<EntryData> *driver,
+ inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
driver_context_t dc (this, c);
- StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
}
protected:
- StateTable<EntryData>
+ StateTable<Types, EntryData>
machine;
- LOffsetTo<UnsizedArrayOf<HBUINT32>, false>
+ OffsetTo<UnsizedArrayOf<HBUINT32>, HBUINT, false>
ligAction; /* Offset to the ligature action table. */
- LOffsetTo<UnsizedArrayOf<HBUINT16>, false>
+ OffsetTo<UnsizedArrayOf<HBUINT16>, HBUINT, false>
component; /* Offset to the component table. */
- LOffsetTo<UnsizedArrayOf<GlyphID>, false>
+ OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
ligature; /* Offset to the actual ligature lists. */
public:
DEFINE_SIZE_STATIC (28);
};
+template <typename Types>
struct NoncontextualSubtable
{
inline bool apply (hb_aat_apply_context_t *c) const
DEFINE_SIZE_MIN (2);
};
+template <typename Types>
struct InsertionSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
struct EntryData
{
HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table.
mark (0),
insertionAction (table+table->insertionAction) {}
- inline bool is_actionable (StateTableDriver<EntryData> *driver HB_UNUSED,
+ inline bool is_actionable (StateTableDriver<MorxTypes, EntryData> *driver HB_UNUSED,
const Entry<EntryData> *entry)
{
return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
(entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
}
- inline bool transition (StateTableDriver<EntryData> *driver,
+ inline bool transition (StateTableDriver<MorxTypes, EntryData> *driver,
const Entry<EntryData> *entry)
{
hb_buffer_t *buffer = driver->buffer;
driver_context_t dc (this, c);
- StateTableDriver<EntryData> driver (machine, c->buffer, c->face);
+ StateTableDriver<MorxTypes, EntryData> driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
}
protected:
- StateTable<EntryData>
+ StateTable<Types, EntryData>
machine;
- LOffsetTo<UnsizedArrayOf<GlyphID>, false>
+ OffsetTo<UnsizedArrayOf<GlyphID>, HBUINT, false>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
DEFINE_SIZE_STATIC (12);
};
-
+template <typename Types>
struct ChainSubtable
{
+ template <typename T>
friend struct Chain;
inline unsigned int get_size (void) const { return length; }
HBUINT32 coverage; /* Coverage flags and subtable type. */
HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
union {
- RearrangementSubtable rearrangement;
- ContextualSubtable contextual;
- LigatureSubtable ligature;
- NoncontextualSubtable noncontextual;
- InsertionSubtable insertion;
+ RearrangementSubtable<Types> rearrangement;
+ ContextualSubtable<Types> contextual;
+ LigatureSubtable<Types> ligature;
+ NoncontextualSubtable<Types> noncontextual;
+ InsertionSubtable<Types> insertion;
} u;
public:
- DEFINE_SIZE_MIN (12);
+ DEFINE_SIZE_MIN (2 * sizeof (HBUINT32) + 4);
};
+template <typename Types>
struct Chain
{
+ typedef typename Types::HBUINT HBUINT;
+
inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
{
hb_mask_t flags = defaultFlags;
inline void apply (hb_aat_apply_context_t *c,
hb_mask_t flags) const
{
- const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&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->subFeatureFlags & flags))
goto skip;
- if (!(subtable->coverage & ChainSubtable::AllDirections) &&
+ if (!(subtable->coverage & ChainSubtable<Types>::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
- bool (subtable->coverage & ChainSubtable::Vertical))
+ bool (subtable->coverage & ChainSubtable<Types>::Vertical))
goto skip;
/* Buffer contents is always in logical direction. Determine if
(the order opposite that of the characters, which
may be right-to-left or left-to-right).
*/
- reverse = subtable->coverage & ChainSubtable::Logical ?
- bool (subtable->coverage & ChainSubtable::Backwards) :
- bool (subtable->coverage & ChainSubtable::Backwards) !=
+ reverse = subtable->coverage & ChainSubtable<Types>::Logical ?
+ bool (subtable->coverage & ChainSubtable<Types>::Backwards) :
+ bool (subtable->coverage & ChainSubtable<Types>::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
if (unlikely (!c->buffer->successful)) return;
skip:
- subtable = &StructAfter<ChainSubtable> (*subtable);
+ subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
c->set_lookup_index (c->lookup_index + 1);
}
}
if (!c->check_array (featureZ.arrayZ, featureCount))
return_trace (false);
- const ChainSubtable *subtable = &StructAtOffset<ChainSubtable> (&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> (*subtable);
+ subtable = &StructAfter<ChainSubtable<Types> > (*subtable);
}
return_trace (true);
}
protected:
- HBUINT32 defaultFlags; /* The default specification for subtables. */
- HBUINT32 length; /* Total byte count, including this header. */
- HBUINT32 featureCount; /* Number of feature subtable entries. */
- HBUINT32 subtableCount; /* The number of subtables in the chain. */
+ HBUINT defaultFlags; /* The default specification for subtables. */
+ HBUINT length; /* Total byte count, including this header. */
+ HBUINT featureCount; /* Number of feature subtable entries. */
+ HBUINT subtableCount; /* The number of subtables in the chain. */
UnsizedArrayOf<Feature> featureZ; /* Features. */
/*ChainSubtable firstSubtable;*//* Subtables. */
/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
public:
- DEFINE_SIZE_MIN (16);
+ DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
};
/*
- * The 'morx' Table
+ * The 'mort'/'morx' Table
*/
-struct morx
+template <typename Types>
+struct mortmorx
{
static const hb_tag_t tableTag = HB_AAT_TAG_morx;
inline void compile_flags (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map) const
{
- const Chain *chain = &firstChain;
+ const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
map->chain_flags.push (chain->compile_flags (mapper));
- chain = &StructAfter<Chain> (*chain);
+ chain = &StructAfter<Chain<Types> > (*chain);
}
}
{
if (unlikely (!c->buffer->successful)) return;
c->set_lookup_index (0);
- const Chain *chain = &firstChain;
+ const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
chain->apply (c, c->plan->aat_map.chain_flags[i]);
if (unlikely (!c->buffer->successful)) return;
- chain = &StructAfter<Chain> (*chain);
+ chain = &StructAfter<Chain<Types> > (*chain);
}
remove_deleted_glyphs (c->buffer);
}
!chainCount.sanitize (c))
return_trace (false);
- const Chain *chain = &firstChain;
+ const Chain<Types> *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
if (!chain->sanitize (c, version))
return_trace (false);
- chain = &StructAfter<Chain> (*chain);
+ chain = &StructAfter<Chain<Types> > (*chain);
}
return_trace (true);
HBUINT16 unused; /* Set to 0. */
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
* table. */
- Chain firstChain; /* Chains. */
+ Chain<Types> firstChain; /* Chains. */
public:
DEFINE_SIZE_MIN (8);
};
+struct morx : mortmorx<MorxTypes>
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx<MortTypes>
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_mort;
+};
+
+
} /* namespace AAT */