--- /dev/null
+/*
+ * Copyright © 2017 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_AAT_LAYOUT_MORX_TABLE_HH
+#define HB_AAT_LAYOUT_MORX_TABLE_HH
+
+#include <hb-open-type-private.hh>
+
+#define HB_AAT_TAG_MORT HB_TAG('m','o','r','t')
+#define HB_AAT_TAG_MORX HB_TAG('m','o','r','x')
+
+
+namespace AAT {
+
+using namespace OT;
+
+
+struct RearrangementSubtable
+{
+ /* TODO */
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* TODO */
+ return_trace (false);
+ }
+};
+
+struct ContextualSubtable
+{
+ /* TODO */
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* TODO */
+ return_trace (false);
+ }
+};
+
+struct LigatureSubtable
+{
+ /* TODO */
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* TODO */
+ return_trace (false);
+ }
+};
+
+struct NoncontextualSubtable
+{
+ /* TODO */
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* TODO */
+ return_trace (false);
+ }
+};
+
+struct InsertionSubtable
+{
+ /* TODO */
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ /* TODO */
+ return_trace (false);
+ }
+};
+
+
+struct Feature
+{
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this));
+ }
+
+ public:
+ USHORT featureType; /* The type of feature. */
+ USHORT featureSetting; /* The feature's setting (aka selector). */
+ ULONG enableFlags; /* Flags for the settings that this feature
+ * and setting enables. */
+ ULONG disableFlags; /* Complement of flags for the settings that this
+ * feature and setting disable. */
+
+ public:
+ DEFINE_SIZE_STATIC (12);
+};
+
+
+template <typename UINT>
+struct ChainSubtable
+{
+ template <typename> struct Chain;
+ friend struct Chain<UINT>;
+
+ inline unsigned int get_size (void) const { return length; }
+ inline unsigned int get_type (void) const { return coverage & 0xFF; }
+
+ enum Type {
+ Rearrangement = 0,
+ Contextual = 1,
+ Ligature = 2,
+ Noncontextual = 4,
+ Insertion = 5
+ };
+
+ template <typename context_t>
+ inline typename context_t::return_t dispatch (context_t *c) const
+ {
+ unsigned int subtable_type = get_type ();
+ TRACE_DISPATCH (this, subtable_type);
+ switch (subtable_type) {
+ case Rearrangement: return_trace (c->dispatch (u.rearrangement));
+ case Contextual: return_trace (c->dispatch (u.contextual));
+ case Ligature: return_trace (c->dispatch (u.ligature));
+ case Noncontextual: return_trace (c->dispatch (u.noncontextual));
+ case Insertion: return_trace (c->dispatch (u.insertion));
+ default: return_trace (c->default_return_value ());
+ }
+ }
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!length.sanitize (c) ||
+ length < min_size ||
+ !c->check_range (this, length))
+ return_trace (false);
+
+ return_trace (dispatch (c));
+ }
+
+ protected:
+ UINT length; /* Total subtable length, including this header. */
+ UINT coverage; /* Coverage flags and subtable type. */
+ ULONG subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
+ union {
+ RearrangementSubtable rearrangement;
+ ContextualSubtable contextual;
+ LigatureSubtable ligature;
+ NoncontextualSubtable noncontextual;
+ InsertionSubtable insertion;
+ } u;
+ public:
+ DEFINE_SIZE_MIN (2 * sizeof (UINT) + 4);
+};
+
+template <typename UINT>
+struct Chain
+{
+
+ inline unsigned int get_size (void) const { return length; }
+
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int major) const
+ {
+ TRACE_SANITIZE (this);
+ if (!length.sanitize (c) ||
+ length < min_size ||
+ !c->check_range (this, length))
+ return_trace (false);
+
+ if (!c->check_array (featureZ, featureZ[0].static_size, featureCount))
+ return_trace (false);
+
+ const ChainSubtable<UINT> *subtable = &StructAtOffset<ChainSubtable<UINT> > (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<UINT> > (*subtable);
+ }
+
+ return_trace (true);
+ }
+
+ protected:
+ ULONG defaultFlags; /* The default specification for subtables. */
+ ULONG length; /* Total byte count, including this header. */
+ UINT featureCount; /* Number of feature subtable entries. */
+ UINT subtableCount; /* The number of subtables in the chain. */
+
+ Feature featureZ[VAR]; /* Features. */
+ ChainSubtable<UINT> subtableX[VAR]; /* Subtables. */
+ // subtableGlyphCoverageArray if major == 3
+
+ public:
+ DEFINE_SIZE_MIN (8 + 2 * sizeof (UINT));
+};
+
+
+/*
+ * The 'mort'/'morx' Tables
+ */
+
+template <typename UINT>
+struct mortmorx
+{
+ static const hb_tag_t mortTag = HB_AAT_TAG_MORT;
+ static const hb_tag_t morxTag = HB_AAT_TAG_MORX;
+
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ if (!version.sanitize (c) ||
+ version.major >> (sizeof (UINT) == 4) != 1 ||
+ !chainCount.sanitize (c))
+ return_trace (false);
+
+ const Chain<UINT> *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<UINT> > (*chain);
+ }
+
+ return_trace (true);
+ }
+
+ protected:
+ FixedVersion<>version; /* Version number of the glyph metamorphosis table.
+ * 1 for mort, 2 or 3 for morx. */
+ ULONG chainCount; /* Number of metamorphosis chains contained in this
+ * table. */
+ Chain<UINT> chains[VAR]; /* Chains. */
+
+ public:
+ DEFINE_SIZE_MIN (8);
+};
+
+struct mort : mortmorx<USHORT>
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_MORT;
+};
+
+struct morx : mortmorx<ULONG>
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_MORX;
+};
+
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_MORX_TABLE_HH */
--- /dev/null
+/*
+ * Copyright © 2017 Google, Inc.
+ *
+ * This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#include "hb-open-type-private.hh"
+#include "hb-ot-layout-private.hh"
+
+#include "hb-aat-layout-morx-table.hh"
+
+/*
+ * mort/morx
+ */
+
+static inline const AAT::morx&
+_get_morx (hb_face_t *face)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(AAT::morx);
+ hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+ return *(layout->morx.get ());
+}