[aat] Start implementing Apple AAT morx table
authorBehdad Esfahbod <behdad@behdad.org>
Tue, 15 Aug 2017 00:24:36 +0000 (17:24 -0700)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 10 Jan 2018 01:50:49 +0000 (02:50 +0100)
src/Makefile.sources
src/hb-aat-layout-morx-table.hh [new file with mode: 0644]
src/hb-aat-layout.cc [new file with mode: 0644]
src/hb-open-type-private.hh
src/hb-ot-layout-private.hh
src/hb-ot-layout.cc

index 63e0ddc..a728fc0 100644 (file)
@@ -82,6 +82,8 @@ HB_FALLBACK_sources = \
        $(NULL)
 
 HB_OT_sources = \
+       hb-aat-layout.cc \
+       hb-aat-layout-morx-table.hh \
        hb-ot-font.cc \
        hb-ot-layout.cc \
        hb-ot-layout-common-private.hh \
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
new file mode 100644 (file)
index 0000000..d3a694b
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * 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 */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
new file mode 100644 (file)
index 0000000..c5277ed
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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 ());
+}
index 2f4e1b9..a8c3ee2 100644 (file)
@@ -160,6 +160,11 @@ static_assert (Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small.
  * Dispatch
  */
 
+#define TRACE_DISPATCH(this, format) \
+       hb_auto_trace_t<context_t::max_debug_depth, typename context_t::return_t> trace \
+       (&c->debug_depth, c->get_name (), this, HB_FUNC, \
+        "format %d", (int) format);
+
 template <typename Context, typename Return, unsigned int MaxDebugDepth>
 struct hb_dispatch_context_t
 {
index be5695d..39d1a67 100644 (file)
@@ -130,6 +130,10 @@ namespace OT {
   struct avar;
 }
 
+namespace AAT {
+  struct morx;
+}
+
 struct hb_ot_layout_lookup_accelerator_t
 {
   template <typename TLookup>
@@ -165,6 +169,7 @@ struct hb_ot_layout_t
   OT::hb_lazy_table_loader_t<struct OT::MATH> math;
   OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
   OT::hb_lazy_table_loader_t<struct OT::avar> avar;
+  OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
 
   unsigned int gsub_lookup_count;
   unsigned int gpos_lookup_count;
index 8845889..d473739 100644 (file)
@@ -62,6 +62,7 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->math.init (face);
   layout->fvar.init (face);
   layout->avar.init (face);
+  layout->morx.init (face);
 
   {
     /*
@@ -209,6 +210,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   layout->math.fini ();
   layout->fvar.fini ();
   layout->avar.fini ();
+  layout->morx.fini ();
 
   free (layout);
 }