[HarfBuzz] harfbuzz: Branch 'master' - 28 commits

Behdad Esfahbod behdad at kemper.freedesktop.org
Tue Feb 27 18:50:41 UTC 2018


 src/Makefile.sources                         |    2 
 src/hb-ot-base.h                             |   56 +
 src/hb-ot-glyf-table.hh                      |  131 ++++
 src/hb-ot-layout-base-table.hh               |  799 +++++++++++++++++++++++++++
 src/hb-ot-layout-private.hh                  |    2 
 src/hb-ot-layout.cc                          |   35 +
 src/hb-ot-layout.h                           |    1 
 src/hb-ot.h                                  |    1 
 src/hb-subset-glyf.cc                        |   89 ++-
 src/hb-subset-input.cc                       |   16 
 src/hb-subset-plan.cc                        |    4 
 src/hb-subset-plan.hh                        |    2 
 src/hb-subset-private.hh                     |    1 
 src/hb-subset.cc                             |   18 
 src/hb-subset.h                              |    2 
 test/api/fonts/Roboto-Regular.ac.nohints.ttf |binary
 test/api/hb-subset-test.h                    |   16 
 test/api/test-subset-cmap.c                  |    4 
 test/api/test-subset-glyf.c                  |   51 +
 test/api/test-subset-hdmx.c                  |    4 
 test/api/test-subset-hmtx.c                  |   10 
 test/api/test-subset-os2.c                   |    2 
 util/hb-subset.cc                            |    6 
 util/options.cc                              |   15 
 util/options.hh                              |   14 
 25 files changed, 1231 insertions(+), 50 deletions(-)

New commits:
commit f110c0c8866c853c0d5a930564a2b69231a33322
Merge: 4a1d51ef 0ad8c663
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Tue Feb 27 11:41:12 2018 +0330

    Merge pull request #838 from harfbuzz/BASE
    
    BASE table

diff --cc src/hb-ot-layout.cc
index 3273ecce,e02ff115..42802e2b
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@@ -62,12 -63,10 +63,13 @@@ _hb_ot_layout_create (hb_face_t *face
    layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
  
    layout->math.init (face);
+   layout->base.init (face);
    layout->fvar.init (face);
    layout->avar.init (face);
 +  layout->ankr.init (face);
 +  layout->kerx.init (face);
    layout->morx.init (face);
 +  layout->trak.init (face);
  
    {
      /*
@@@ -215,12 -214,10 +217,13 @@@ _hb_ot_layout_destroy (hb_ot_layout_t *
    hb_blob_destroy (layout->gpos_blob);
  
    layout->math.fini ();
+   layout->base.fini ();
    layout->fvar.fini ();
    layout->avar.fini ();
 +  layout->ankr.fini ();
 +  layout->kerx.fini ();
    layout->morx.fini ();
 +  layout->trak.fini ();
  
    free (layout);
  }
commit 0ad8c663e0b4602e2a413e77a8158bf8a46755d5
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Feb 26 12:45:08 2018 +0330

    Remove public API of the branch

diff --git a/src/hb-ot-base.h b/src/hb-ot-base.h
index 9d82d228..0437c168 100644
--- a/src/hb-ot-base.h
+++ b/src/hb-ot-base.h
@@ -48,8 +48,8 @@ HB_BEGIN_DECLS
 
 /* Methods */
 
-HB_EXTERN hb_bool_t
-hb_ot_base_has_data (hb_face_t *face);
+// HB_EXTERN hb_bool_t
+// hb_ot_base_has_data (hb_face_t *face);
 
 HB_END_DECLS
 
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 169a13f3..3c3d3ade 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -23,8 +23,8 @@
  *
  */
 
-#ifndef HB_OT_BASE_TABLE_HH
-#define HB_OT_BASE_TABLE_HH
+#ifndef HB_OT_LAYOUT_BASE_TABLE_HH
+#define HB_OT_LAYOUT_BASE_TABLE_HH
 
 #include "hb-open-type-private.hh"
 #include "hb-ot-layout-common-private.hh"
@@ -312,7 +312,7 @@ struct BaseScript {
       return (this+defaultMinMax).get_min_value(featureTableTagIndex);
     }
     if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD;
-    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); 
+    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
   }
 
   inline HBINT16 get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
@@ -401,7 +401,7 @@ struct BaseScriptList {
   }
 
   inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
-  { 
+  {
     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
     return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
   }
@@ -449,7 +449,7 @@ struct BaseScriptList {
 
   public:
   DEFINE_SIZE_ARRAY (4, baseScriptRecords);
-  
+
 };
 
 struct BaseTagList
@@ -487,7 +487,7 @@ struct Axis
   }
 
   inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  { 
+  {
     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
     return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
   }
@@ -546,7 +546,7 @@ struct BASEFormat1_1
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
       horizAxis.sanitize (c, this) &&
-      vertAxis.sanitize (c, this) && 
+      vertAxis.sanitize (c, this) &&
       itemVarStore.sanitize (c, this));
   }
 
@@ -578,7 +578,7 @@ struct BASEFormat1_0
   }
 
   inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  { 
+  {
     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
@@ -598,7 +598,7 @@ struct BASEFormat1_0
   }
 
   inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
-  { 
+  {
     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
     return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
   }
@@ -796,4 +796,4 @@ struct BASE
 } /* namespace OT */
 
 
-#endif /* HB_OT_BASE_TABLE_HH */
+#endif /* HB_OT_LAYOUT_BASE_TABLE_HH */
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3a133212..e02ff115 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -222,13 +222,13 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   free (layout);
 }
 
-static inline const OT::BASE&
-_get_base (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->base.get ());
-}
+// static inline const OT::BASE&
+// _get_base (hb_face_t *face)
+// {
+//   if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
+//   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+//   return *(layout->base.get ());
+// }
 
 static inline const OT::GDEF&
 _get_gdef (hb_face_t *face)
@@ -1283,21 +1283,19 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
  * OT::BASE
  */
 
-#if 0
-/**
- * hb_ot_base_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of an OpenType BASE table on the
- * face.
- *
- * Return value: true if face has a BASE table, false otherwise
- *
- * Since: XXX
- **/
-hb_bool_t
-hb_ot_base_has_data (hb_face_t *face)
-{
-  return &_get_base (face) != &OT::Null(OT::BASE);
-}
-#endif
+// /**
+//  * hb_ot_base_has_data:
+//  * @face: #hb_face_t to test
+//  *
+//  * This function allows to verify the presence of an OpenType BASE table on the
+//  * face.
+//  *
+//  * Return value: true if face has a BASE table, false otherwise
+//  *
+//  * Since: XXX
+//  **/
+// hb_bool_t
+// hb_ot_base_has_data (hb_face_t *face)
+// {
+//   return &_get_base (face) != &OT::Null(OT::BASE);
+// }
commit 4a1d51ef15a423706406f784a146078073147885
Merge: d0caf7e5 903771b6
Author: rsheeter <rsheeter at google.com>
Date:   Mon Feb 26 20:23:41 2018 -0800

    Merge pull request #818 from googlefonts/drophints
    
    [subset] Drop hints

commit 903771b6c7689b9eee9a11bac128c42f39833b2e
Author: Rod Sheeter <rsheeter at google.com>
Date:   Mon Feb 26 19:50:06 2018 -0800

    [subset] clearer name for trim() and better comment about composite handling, per review feedback

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 3d030977..441d4b9e 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -276,8 +276,8 @@ struct glyf
     }
 
     /* based on FontTools _g_l_y_f.py::trim */
-    inline bool trim(unsigned int start_offset,
-                     unsigned int *end_offset) const
+    inline bool remove_padding(unsigned int start_offset,
+                               unsigned int *end_offset) const
     {
       static const int FLAG_X_SHORT = 0x02;
       static const int FLAG_Y_SHORT = 0x04;
@@ -294,7 +294,9 @@ struct glyf
       int16_t num_contours = (int16_t) glyph_header.numberOfContours;
 
       if (num_contours < 0)
-        return true; /* no trimming for composites just yet */
+        /* Trimming for composites not implemented.
+         * If removing hints it falls out of that. */
+        return true;
       else if (num_contours > 0)
       {
         unsigned int glyph_len = *end_offset - start_offset;
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index a97e1b76..696a74de 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -43,12 +43,14 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     hb_codepoint_t next_glyph = glyph_ids[i];
-    *(instruction_ranges->push()) = 0;
-    *(instruction_ranges->push()) = 0;
+    unsigned int *instruction_start = instruction_ranges->push();
+    unsigned int *instruction_end = instruction_ranges->push();
+    *instruction_start = 0;
+    *instruction_end = 0;
 
     unsigned int start_offset, end_offset;
     if (unlikely (!(glyf.get_offsets(next_glyph, &start_offset, &end_offset)
-                    && glyf.trim(start_offset, &end_offset))))
+                    && glyf.remove_padding(start_offset, &end_offset))))
     {
       DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
       continue;
@@ -56,20 +58,17 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
     if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
       continue; /* 0-length glyph */
 
-    unsigned int instruction_start = 0, instruction_end = 0;
     if (drop_hints)
     {
       if (unlikely (!glyf.get_instruction_offsets(start_offset, end_offset,
-                                                  &instruction_start, &instruction_end)))
+                                                  instruction_start, instruction_end)))
       {
         DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
         return false;
       }
-      instruction_ranges->array[i * 2] = instruction_start;
-      instruction_ranges->array[i * 2 + 1] = instruction_end;
     }
 
-    total += end_offset - start_offset - (instruction_end - instruction_start);
+    total += end_offset - start_offset - (*instruction_end - *instruction_start);
     /* round2 so short loca will work */
     total += total % 2;
   }
@@ -156,7 +155,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
   {
     unsigned int start_offset, end_offset;
     if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)
-                    && glyf.trim(start_offset, &end_offset))))
+                    && glyf.remove_padding(start_offset, &end_offset))))
       end_offset = start_offset = 0;
     unsigned int instruction_start = instruction_ranges[i * 2];
     unsigned int instruction_end = instruction_ranges[i * 2 + 1];
commit 551fa2d200a06d00d054f2c8e7aad1cb4d25249b
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 25 16:32:17 2018 -0800

    [BASE] Minor

diff --git a/src/Makefile.sources b/src/Makefile.sources
index cecd6447..49685008 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -87,7 +87,6 @@ HB_OT_sources = \
 	hb-aat-layout-kerx-table.hh \
 	hb-aat-layout-trak-table.hh \
 	hb-aat-layout-private.hh \
-	hb-ot-base.cc \
 	hb-ot-font.cc \
 	hb-ot-layout.cc \
 	hb-ot-layout-base-table.hh \
diff --git a/src/hb-ot-base.cc b/src/hb-ot-base.cc
deleted file mode 100644
index 27e0b208..00000000
--- a/src/hb-ot-base.cc
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright © 2017 Elie Roux<elie.roux at telecom-bretagne.eu>
- *
- *  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.
- *
- */
-
-#include "hb-open-type-private.hh"
-
-#include "hb-ot-layout-private.hh"
-#include "hb-ot-layout-base-table.hh"
-
-static inline const OT::BASE&
-_get_base (hb_face_t *face)
-{
-  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
-  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  return *(layout->base.get ());
-}
-
-/*
- * OT::BASE
- */
-
-/**
- * hb_ot_base_has_data:
- * @face: #hb_face_t to test
- *
- * This function allows to verify the presence of an OpenType BASE table on the
- * face.
- *
- * Return value: true if face has a BASE table, false otherwise
- *
- * Since: XXX
- **/
-hb_bool_t
-hb_ot_base_has_data (hb_face_t *face)
-{
-  return &_get_base (face) != &OT::Null(OT::BASE);
-}
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 78018604..169a13f3 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -221,40 +221,39 @@ struct MinMax {
 
 };
 
-struct BaseLangSysRecord {
-
+struct BaseLangSysRecord
+{
   inline Tag get_tag(void) const
   { return baseLangSysTag; }
 
   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
-  { (this+minMax).get_feature_tag_index(featureTableTag); }
+  { return (this+minMax).get_feature_tag_index(featureTableTag); }
 
   inline HBINT16 get_min_value (unsigned int featureTableTagIndex) const
-  { (this+minMax).get_min_value(featureTableTagIndex); }
+  { return (this+minMax).get_min_value(featureTableTagIndex); }
 
   inline HBINT16 get_max_value (unsigned int featureTableTagIndex) const
-  { (this+minMax).get_max_value(featureTableTagIndex); }
+  { return (this+minMax).get_max_value(featureTableTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      minMax != Null(OffsetTo<MinMax>) &&
-      minMax.sanitize (c, base));
+		  minMax != Null(OffsetTo<MinMax>) &&
+		  minMax.sanitize (c, base));
   }
 
   protected:
-  Tag               baseLangSysTag;
-  OffsetTo<MinMax>  minMax; // not supposed to be NULL
-
+  Tag			baseLangSysTag;
+  OffsetTo<MinMax>	minMax;
   public:
-  DEFINE_SIZE_STATIC (6); 
+  DEFINE_SIZE_STATIC (6);
 
 };
 
-struct BaseValues {
-
-  inline const unsigned int get_default_base_tag_index (void) const
+struct BaseValues
+{
+  inline unsigned int get_default_base_tag_index (void) const
   { return defaultIndex; }
 
   inline HBINT16 get_base_coord (unsigned int baselineTagIndex) const
@@ -272,10 +271,9 @@ struct BaseValues {
   }
 
   protected:
-  Index                     defaultIndex;
-  HBUINT16                    baseCoordCount;
-  OffsetArrayOf<BaseCoord>  baseCoords;
-
+  Index				defaultIndex;
+  HBUINT16			baseCoordCount;
+  OffsetArrayOf<BaseCoord>	baseCoords;
   public:
   DEFINE_SIZE_ARRAY (6, baseCoords);
 
@@ -711,26 +709,66 @@ struct BASE
   inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
   { return u.format1_0.get_horiz_lang_tag_index(baseScriptIndex, baseLangSysTag); }
 
-  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return u.format1_0.get_horiz_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex,
+						   unsigned int baseLangSysIndex,
+						   Tag featureTableTag) const
+  {
+    return u.format1_0.get_horiz_feature_tag_index (baseScriptIndex,
+						    baseLangSysIndex,
+						    featureTableTag);
+  }
 
-  inline HBINT16 get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return u.format1_0.get_horiz_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+  inline HBINT16 get_horiz_max_value (unsigned int baseScriptIndex,
+				      unsigned int baseLangSysIndex,
+				      unsigned int featureTableTagIndex) const
+  {
+    return u.format1_0.get_horiz_max_value (baseScriptIndex,
+					    baseLangSysIndex,
+					    featureTableTagIndex);
+  }
 
-  inline HBINT16 get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return u.format1_0.get_horiz_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+  inline HBINT16 get_horiz_min_value (unsigned int baseScriptIndex,
+				      unsigned int baseLangSysIndex,
+				      unsigned int featureTableTagIndex) const
+  {
+    return u.format1_0.get_horiz_min_value (baseScriptIndex,
+					    baseLangSysIndex,
+					    featureTableTagIndex);
+  }
 
-  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
-  { return u.format1_0.get_vert_lang_tag_index(baseScriptIndex, baseLangSysTag); }
+  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex,
+					       Tag baseLangSysTag) const
+  {
+    return u.format1_0.get_vert_lang_tag_index (baseScriptIndex,
+						baseLangSysTag);
+  }
 
-  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
-  { return u.format1_0.get_vert_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex,
+						  unsigned int baseLangSysIndex,
+						  Tag featureTableTag) const
+  {
+    return u.format1_0.get_vert_feature_tag_index (baseScriptIndex,
+						   baseLangSysIndex,
+						   featureTableTag);
+  }
 
-  inline HBINT16 get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return u.format1_0.get_vert_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+  inline HBINT16 get_vert_max_value (unsigned int baseScriptIndex,
+				     unsigned int baseLangSysIndex,
+				     unsigned int featureTableTagIndex) const
+  {
+    return u.format1_0.get_vert_max_value (baseScriptIndex,
+					   baseLangSysIndex,
+					   featureTableTagIndex);
+  }
 
-  inline HBINT16 get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
-  { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+  inline HBINT16 get_vert_min_value (unsigned int baseScriptIndex,
+				     unsigned int baseLangSysIndex,
+				     unsigned int featureTableTagIndex) const
+  {
+    return u.format1_0.get_vert_min_value (baseScriptIndex,
+					   baseLangSysIndex,
+					   featureTableTagIndex);
+  }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -750,7 +788,6 @@ struct BASE
     BASEFormat1_0   format1_0;
     BASEFormat1_1   format1_1;
   } u;
-
   public:
   DEFINE_SIZE_UNION (4, version);
 };
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 68eb125d..3a133212 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -222,6 +222,14 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   free (layout);
 }
 
+static inline const OT::BASE&
+_get_base (hb_face_t *face)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  return *(layout->base.get ());
+}
+
 static inline const OT::GDEF&
 _get_gdef (hb_face_t *face)
 {
@@ -1267,3 +1275,29 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c,
 {
   apply_string<GSUBProxy> (c, lookup, accel);
 }
+
+
+
+
+/*
+ * OT::BASE
+ */
+
+#if 0
+/**
+ * hb_ot_base_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType BASE table on the
+ * face.
+ *
+ * Return value: true if face has a BASE table, false otherwise
+ *
+ * Since: XXX
+ **/
+hb_bool_t
+hb_ot_base_has_data (hb_face_t *face)
+{
+  return &_get_base (face) != &OT::Null(OT::BASE);
+}
+#endif
diff --git a/src/hb-ot-layout.h b/src/hb-ot-layout.h
index 9861f0fc..077644c5 100644
--- a/src/hb-ot-layout.h
+++ b/src/hb-ot-layout.h
@@ -38,6 +38,7 @@
 HB_BEGIN_DECLS
 
 
+#define HB_OT_TAG_BASE HB_TAG('B','A','S','E')
 #define HB_OT_TAG_GDEF HB_TAG('G','D','E','F')
 #define HB_OT_TAG_GSUB HB_TAG('G','S','U','B')
 #define HB_OT_TAG_GPOS HB_TAG('G','P','O','S')
commit 05699fd996ed9c0e5dde8918388ac188e58df1a7
Merge: 83af6c23 3ebcd5a3
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Feb 24 12:01:54 2018 -0800

    Merge remote-tracking branch 'eroux/add-base'

diff --cc src/Makefile.sources
index 2bb56b4f,db730565..cecd6447
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@@ -76,19 -65,13 +76,21 @@@ HB_NODIST_headers = 
  	hb-version.h \
  	$(NULL)
  
 -HB_FALLBACK_sources = hb-fallback-shape.cc
 +HB_FALLBACK_sources = \
 +	hb-fallback-shape.cc	\
 +	$(NULL)
  
  HB_OT_sources = \
 +	hb-aat-layout.cc \
 +	hb-aat-layout-common-private.hh \
 +	hb-aat-layout-morx-table.hh \
 +	hb-aat-layout-kerx-table.hh \
 +	hb-aat-layout-trak-table.hh \
 +	hb-aat-layout-private.hh \
+ 	hb-ot-base.cc \
  	hb-ot-font.cc \
  	hb-ot-layout.cc \
+ 	hb-ot-layout-base-table.hh \
  	hb-ot-layout-common-private.hh \
  	hb-ot-layout-gdef-table.hh \
  	hb-ot-layout-gpos-table.hh \
diff --cc src/hb-ot-layout-base-table.hh
index 00000000,0d1e197e..78018604
mode 000000,100644..100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@@ -1,0 -1,762 +1,762 @@@
+ /*
+  * Copyright © 2016 Elie Roux <elie.roux at telecom-bretagne.eu>
+  *
+  *  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.
+  *
+  */
+ 
+ #ifndef HB_OT_BASE_TABLE_HH
+ #define HB_OT_BASE_TABLE_HH
+ 
+ #include "hb-open-type-private.hh"
+ #include "hb-ot-layout-common-private.hh"
+ #include "hb-ot-base.h"
+ 
+ namespace OT {
+ 
 -#define NO_COORD Null(SHORT)//SHORT((short int) -32767)
++#define NO_COORD Null(HBINT16)//HBINT16((short int) -32767)
+ 
+ #define NOT_INDEXED   ((unsigned int) -1)
+ 
+ /*
+  * BASE -- The BASE Table
+  */
+ 
+ struct BaseCoordFormat1 {
+ 
 -  inline SHORT get_coord (void) const
++  inline HBINT16 get_coord (void) const
+   { return coordinate; }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this));
+   }
+ 
+   protected:
 -  USHORT    baseCoordFormat;
 -  SHORT     coordinate;
++  HBUINT16    baseCoordFormat;
++  HBINT16     coordinate;
+ 
+   public:
+   DEFINE_SIZE_STATIC (4);
+ };
+ 
+ struct BaseCoordFormat2 {
+ 
 -  inline SHORT get_coord (void) const
++  inline HBINT16 get_coord (void) const
+   { return coordinate; }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this));
+   }
+ 
+   protected:
 -  USHORT    baseCoordFormat;
 -  SHORT     coordinate;
 -  USHORT    referenceGlyph;
 -  USHORT    baseCoordPoint;
++  HBUINT16    baseCoordFormat;
++  HBINT16     coordinate;
++  HBUINT16    referenceGlyph;
++  HBUINT16    baseCoordPoint;
+ 
+   public:
+   DEFINE_SIZE_STATIC (8);
+ };
+ 
+ struct BaseCoordFormat3 {
+ 
 -  inline SHORT get_coord (void) const
++  inline HBINT16 get_coord (void) const
+   { return coordinate; }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+   }
+ 
+   protected:
 -  USHORT           baseCoordFormat;
 -  SHORT            coordinate;
++  HBUINT16           baseCoordFormat;
++  HBINT16            coordinate;
+   OffsetTo<Device> deviceTable;
+ 
+   public:
+   DEFINE_SIZE_STATIC (6);
+ };
+ 
+ struct BaseCoord {
+ 
 -  inline SHORT get_coord (void) const
++  inline HBINT16 get_coord (void) const
+   { return u.format1.get_coord(); }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     if (!u.baseCoordFormat.sanitize (c)) return_trace (false);
+     switch (u.baseCoordFormat) {
+     case 1: return_trace (u.format1.sanitize (c));
+     case 2: return_trace (u.format2.sanitize (c));
+     case 3: return_trace (u.format3.sanitize (c));
+     default:return_trace (false);
+     }
+   }
+ 
+   protected:
+   union {
 -    USHORT            baseCoordFormat;
++    HBUINT16            baseCoordFormat;
+     BaseCoordFormat1  format1;
+     BaseCoordFormat2  format2;
+     BaseCoordFormat3  format3;
+   } u;
+ 
+   public:
+   DEFINE_SIZE_MIN (4);
+ };
+ 
+ struct FeatMinMaxRecord {
+ 
 -  inline SHORT get_min_value (void) const
++  inline HBINT16 get_min_value (void) const
+   {
+     if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+       return (this+minCoord).get_coord();
+   }
+ 
 -  inline SHORT get_max_value (void) const
++  inline HBINT16 get_max_value (void) const
+   {
+     if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+       return (this+maxCoord).get_coord();
+   }
+ 
+   inline Tag get_tag () const
+   { return featureTableTag; }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       minCoord.sanitize (c, base) &&
+       maxCoord.sanitize (c, base));
+   }
+ 
+   protected:
+   Tag                   featureTableTag;
+   OffsetTo<BaseCoord>   minCoord;
+   OffsetTo<BaseCoord>   maxCoord;
+ 
+   public:
+   DEFINE_SIZE_STATIC (8);
+ 
+ };
+ 
+ struct MinMax {
+ 
+   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+   {
+     Tag tag;
+     int cmp;
+     // taking advantage of alphabetical order
+     for (unsigned int i = 0; i < featMinMaxCount; i++) {
+       tag = featMinMaxRecords[i].get_tag();
+       cmp = tag.cmp(featureTableTag);
+       if (cmp == 0) return i;
+       if (cmp > 0)  return NOT_INDEXED;
+     }
+     return NOT_INDEXED;
+   }
+ 
 -  inline SHORT get_min_value (unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int featureTableTagIndex) const
+   {
+     if (featureTableTagIndex == NOT_INDEXED) {
+       if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+       return (this+minCoord).get_coord();
+     }
+     if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD;
+     return featMinMaxRecords[featureTableTagIndex].get_min_value();
+   }
+ 
 -  inline SHORT get_max_value (unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int featureTableTagIndex) const
+   {
+     if (featureTableTagIndex == NOT_INDEXED) {
+       if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+       return (this+maxCoord).get_coord();
+     }
+     if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD;
+     return featMinMaxRecords[featureTableTagIndex].get_max_value();
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       minCoord.sanitize (c, this) &&
+       maxCoord.sanitize (c, this) &&
+       featMinMaxRecords.sanitize (c, this));
+     // TODO: test alphabetical order?
+   }
+ 
+   protected:
+   OffsetTo<BaseCoord>       minCoord;
+   OffsetTo<BaseCoord>       maxCoord;
 -  USHORT                    featMinMaxCount;
++  HBUINT16                    featMinMaxCount;
+   ArrayOf<FeatMinMaxRecord> featMinMaxRecords;
+ 
+   public:
+   DEFINE_SIZE_ARRAY (8, featMinMaxRecords);
+ 
+ };
+ 
+ struct BaseLangSysRecord {
+ 
+   inline Tag get_tag(void) const
+   { return baseLangSysTag; }
+ 
+   inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+   { (this+minMax).get_feature_tag_index(featureTableTag); }
+ 
 -  inline SHORT get_min_value (unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int featureTableTagIndex) const
+   { (this+minMax).get_min_value(featureTableTagIndex); }
+ 
 -  inline SHORT get_max_value (unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int featureTableTagIndex) const
+   { (this+minMax).get_max_value(featureTableTagIndex); }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       minMax != Null(OffsetTo<MinMax>) &&
+       minMax.sanitize (c, base));
+   }
+ 
+   protected:
+   Tag               baseLangSysTag;
+   OffsetTo<MinMax>  minMax; // not supposed to be NULL
+ 
+   public:
+   DEFINE_SIZE_STATIC (6); 
+ 
+ };
+ 
+ struct BaseValues {
+ 
+   inline const unsigned int get_default_base_tag_index (void) const
+   { return defaultIndex; }
+ 
 -  inline SHORT get_base_coord (unsigned int baselineTagIndex) const
++  inline HBINT16 get_base_coord (unsigned int baselineTagIndex) const
+   {
+     if (unlikely(baselineTagIndex >= baseCoordCount)) return NO_COORD;
+     return (this+baseCoords[baselineTagIndex]).get_coord();
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       defaultIndex <= baseCoordCount &&
+       baseCoords.sanitize (c, this));
+   }
+ 
+   protected:
+   Index                     defaultIndex;
 -  USHORT                    baseCoordCount;
++  HBUINT16                    baseCoordCount;
+   OffsetArrayOf<BaseCoord>  baseCoords;
+ 
+   public:
+   DEFINE_SIZE_ARRAY (6, baseCoords);
+ 
+ };
+ 
+ struct BaseScript {
+ 
+   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
+   {
+     Tag tag;
+     int cmp;
+     for (unsigned int i = 0; i < baseLangSysCount; i++) {
+       tag = baseLangSysRecords[i].get_tag();
+       // taking advantage of alphabetical order
+       cmp = tag.cmp(baseLangSysTag);
+       if (cmp == 0) return i;
+       if (cmp > 0)  return NOT_INDEXED;
+     }
+     return NOT_INDEXED;
+   }
+ 
+   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
+   {
+     if (baseLangSysIndex == NOT_INDEXED) {
+       if (unlikely(defaultMinMax)) return NOT_INDEXED;
+       return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
+     }
+     if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
+     return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
+   }
+ 
 -  inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (baseLangSysIndex == NOT_INDEXED) {
+       if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+       return (this+defaultMinMax).get_min_value(featureTableTagIndex);
+     }
+     if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD;
+     return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); 
+   }
+ 
 -  inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (baseLangSysIndex == NOT_INDEXED) {
+       if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+       return (this+defaultMinMax).get_min_value(featureTableTagIndex);
+     }
+     if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD;
+     return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
+   }
+ 
+   inline unsigned int get_default_base_tag_index (void) const
+   { return (this+baseValues).get_default_base_tag_index(); }
+ 
 -  inline SHORT get_base_coord (unsigned int baselineTagIndex) const
++  inline HBINT16 get_base_coord (unsigned int baselineTagIndex) const
+   { return (this+baseValues).get_base_coord(baselineTagIndex); }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       baseValues.sanitize (c, this) &&
+       defaultMinMax.sanitize (c, this) &&
+       baseLangSysRecords.sanitize (c, this));
+   }
+ 
+   protected:
+   OffsetTo<BaseValues>        baseValues;
+   OffsetTo<MinMax>            defaultMinMax;
 -  USHORT                      baseLangSysCount;
++  HBUINT16                      baseLangSysCount;
+   ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
+ 
+   public:
+     DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
+ };
+ 
+ 
+ struct BaseScriptRecord {
+ 
+   inline bool get_tag (void) const
+   { return baseScriptTag; }
+ 
+   inline unsigned int get_default_base_tag_index(void) const
+   { return (this+baseScript).get_default_base_tag_index(); }
+ 
 -  inline SHORT get_base_coord(unsigned int baselineTagIndex) const
++  inline HBINT16 get_base_coord(unsigned int baselineTagIndex) const
+   { return (this+baseScript).get_base_coord(baselineTagIndex); }
+ 
+   inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
+   { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
+ 
+   inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
+   { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+ 
 -  inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+ 
 -  inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       baseScript != Null(OffsetTo<BaseScript>) &&
+       baseScript.sanitize (c, base));
+   }
+ 
+   protected:
+   Tag                   baseScriptTag;
+   OffsetTo<BaseScript>  baseScript;
+ 
+   public:
+     DEFINE_SIZE_STATIC (6);
+ };
+ 
+ struct BaseScriptList {
+ 
+   inline unsigned int get_base_script_index (Tag baseScriptTag) const
+   {
+     for (unsigned int i = 0; i < baseScriptCount; i++)
+       if (baseScriptRecords[i].get_tag() == baseScriptTag)
+         return i;
+     return NOT_INDEXED;
+   }
+ 
+   inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
+   { 
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+     return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
+   }
+ 
 -  inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   {
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+     return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
+   }
+ 
+   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   {
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+     return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
+   }
+ 
+   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   {
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+     return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
+   }
+ 
 -  inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+     return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
+   }
+ 
 -  inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+     return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       baseScriptRecords.sanitize (c, this));
+   }
+ 
+   protected:
 -  USHORT                    baseScriptCount;
++  HBUINT16                    baseScriptCount;
+   ArrayOf<BaseScriptRecord> baseScriptRecords;
+ 
+   public:
+   DEFINE_SIZE_ARRAY (4, baseScriptRecords);
+   
+ };
+ 
+ struct BaseTagList
+ {
+ 
+   inline unsigned int get_tag_index(Tag baselineTag) const
+   {
+     for (unsigned int i = 0; i < baseTagCount; i++)
+       if (baselineTags[i] == baselineTag)
+         return i;
+     return NOT_INDEXED;
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this));
+   }
+ 
+   protected:
 -  USHORT        baseTagCount;
++  HBUINT16        baseTagCount;
+   SortedArrayOf<Tag>  baselineTags;
+ 
+   public:
+   DEFINE_SIZE_ARRAY (4, baselineTags);
+ };
+ 
+ struct Axis
+ {
+ 
+   inline unsigned int get_base_tag_index(Tag baselineTag) const
+   {
+     if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
+     return (this+baseTagList).get_tag_index(baselineTag);
+   }
+ 
+   inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+   { 
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+     return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
+   }
+ 
 -  inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   {
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+     return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
+   }
+ 
+   inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   {
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+     return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
+   }
+ 
+   inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   {
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+     return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
+   }
+ 
 -  inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+     return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
 -  inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+     return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       baseTagList.sanitize (c, this) &&
+       baseScriptList.sanitize (c, this));
+   }
+ 
+   protected:
+   OffsetTo<BaseTagList>     baseTagList;
+   OffsetTo<BaseScriptList>  baseScriptList;
+ 
+   public:
+   DEFINE_SIZE_STATIC (4);
+ };
+ 
+ struct BASEFormat1_1
+ {
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       horizAxis.sanitize (c, this) &&
+       vertAxis.sanitize (c, this) && 
+       itemVarStore.sanitize (c, this));
+   }
+ 
+   protected:
+   FixedVersion<>            version;
+   OffsetTo<Axis>            horizAxis;
+   OffsetTo<Axis>            vertAxis;
+   LOffsetTo<VariationStore> itemVarStore;
+ 
+   public:
+   DEFINE_SIZE_STATIC (12);
+ };
+ 
+ struct BASEFormat1_0
+ {
+ 
+   inline bool has_vert_axis(void)
+   { return vertAxis != Null(OffsetTo<Axis>); }
+ 
+   inline bool has_horiz_axis(void)
+   { return horizAxis != Null(OffsetTo<Axis>); }
+ 
+   // horizontal axis base coords:
+ 
+   inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+horizAxis).get_base_tag_index(baselineTag);
+   }
+ 
+   inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+   { 
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+   }
+ 
 -  inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+     return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+   }
+ 
+   // vertical axis base coords:
+ 
+   inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+   {
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+vertAxis).get_base_tag_index(baselineTag);
+   }
+ 
+   inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+   { 
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+   }
+ 
 -  inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   {
+     if (vertAxis == Null(OffsetTo<Axis>)) return NO_COORD;
+     return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+   }
+ 
+   // horizontal axis min/max coords:
+ 
+   inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+   }
+ 
+   inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+   }
+ 
 -  inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+     return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
 -  inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+     return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
+     // vertical axis min/max coords:
+ 
+   inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   {
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+   }
+ 
+   inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   {
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+     return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+   }
+ 
 -  inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+     return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
 -  inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   {
+     if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+     return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+   }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     return_trace (c->check_struct (this) &&
+       horizAxis.sanitize (c, this) &&
+       vertAxis.sanitize (c, this));
+   }
+ 
+   protected:
+   FixedVersion<>  version;
+   OffsetTo<Axis>  horizAxis;
+   OffsetTo<Axis>  vertAxis;
+ 
+   public:
+   DEFINE_SIZE_STATIC (8);
+ };
+ 
+ struct BASE
+ {
+   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
+ 
+   inline bool has_vert_axis(void)
+   { return u.format1_0.has_vert_axis(); }
+ 
+   inline bool has_horiz_axis(void)
+   { return u.format1_0.has_horiz_axis(); }
+ 
+   inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+   { return u.format1_0.get_horiz_base_tag_index(baselineTag); }
+ 
+   inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+   { return u.format1_0.get_horiz_default_base_tag_index_for_script_index(baseScriptIndex); }
+ 
 -  inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   { return u.format1_0.get_horiz_base_coord(baseScriptIndex, baselineTagIndex); }
+ 
+   inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+   { return u.format1_0.get_vert_base_tag_index(baselineTag); }
+ 
+   inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+   { return u.format1_0.get_vert_default_base_tag_index_for_script_index(baseScriptIndex); }
+ 
 -  inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
++  inline HBINT16 get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+   { return u.format1_0.get_vert_base_coord(baseScriptIndex, baselineTagIndex); }
+ 
+   inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   { return u.format1_0.get_horiz_lang_tag_index(baseScriptIndex, baseLangSysTag); }
+ 
+   inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   { return u.format1_0.get_horiz_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+ 
 -  inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return u.format1_0.get_horiz_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+ 
 -  inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return u.format1_0.get_horiz_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+ 
+   inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+   { return u.format1_0.get_vert_lang_tag_index(baseScriptIndex, baseLangSysTag); }
+ 
+   inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+   { return u.format1_0.get_vert_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+ 
 -  inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return u.format1_0.get_vert_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+ 
 -  inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
++  inline HBINT16 get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+   { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+ 
+   inline bool sanitize (hb_sanitize_context_t *c) const
+   {
+     TRACE_SANITIZE (this);
+     if (!u.version.sanitize (c)) return_trace (false);
+     if (!likely(u.version.major == 1)) return_trace (false);
+     switch (u.version.minor) {
+     case 0: return_trace (u.format1_0.sanitize (c));
+     case 1: return_trace (u.format1_1.sanitize (c));
+     default:return_trace (false);
+     }
+   }
+ 
+   protected:
+   union {
+     FixedVersion<>  version;    /* Version of the BASE table: 1.0 or 1.1 */
+     BASEFormat1_0   format1_0;
+     BASEFormat1_1   format1_1;
+   } u;
+ 
+   public:
+   DEFINE_SIZE_UNION (4, version);
+ };
+ 
+ 
+ } /* namespace OT */
+ 
+ 
+ #endif /* HB_OT_BASE_TABLE_HH */
diff --cc src/hb-ot-layout.cc
index 4cf6c722,d393f5ca..68eb125d
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@@ -62,9 -57,9 +63,10 @@@ _hb_ot_layout_create (hb_face_t *face
    layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
  
    layout->math.init (face);
+   layout->base.init (face);
    layout->fvar.init (face);
    layout->avar.init (face);
 +  layout->morx.init (face);
  
    {
      /*
@@@ -212,9 -186,9 +214,10 @@@ _hb_ot_layout_destroy (hb_ot_layout_t *
    hb_blob_destroy (layout->gpos_blob);
  
    layout->math.fini ();
+   layout->base.fini ();
    layout->fvar.fini ();
    layout->avar.fini ();
 +  layout->morx.fini ();
  
    free (layout);
  }
commit 5267520e078ed413df78f3a6781fd5370b6da63a
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 18:36:22 2018 -0800

    [subset] update hdmx test to create input explicitly

diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c
index 291eb793..5211dbc4 100644
--- a/test/api/test-subset-hdmx.c
+++ b/test/api/test-subset-hdmx.c
@@ -41,7 +41,7 @@ test_subset_hdmx_simple_subset (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('h','d','m','x'));
@@ -60,7 +60,7 @@ test_subset_hdmx_noop (void)
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('h','d','m','x'));
commit 2e3ee489f8374227fa94a8d8684e839e643888ea
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 18:18:54 2018 -0800

    [subset] format tweak, doc string

diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index 69aa9d61..c4003dd3 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -53,9 +53,9 @@ hb_subset_input_create_or_fail (void)
  * hb_subset_input_reference: (skip)
  * @subset_input: a subset_input.
  *
- * 
  *
- * Return value: 
+ *
+ * Return value:
  *
  * Since: 1.8.0
  **/
@@ -106,8 +106,14 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
   return subset_input->glyphs;
 }
 
+/**
+ * hb_subset_input_drop_hints:
+ * @subset_input: a subset_input.
+ *
+ * Since: 1.8.0
+ **/
 HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints(hb_subset_input_t *subset_input)
+hb_subset_input_drop_hints (hb_subset_input_t *subset_input)
 {
   return &subset_input->drop_hints;
 }
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 1af7cba5..55ce25b0 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -69,7 +69,7 @@ HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
 HB_EXTERN hb_bool_t *
-hb_subset_input_drop_hints(hb_subset_input_t *subset_input);
+hb_subset_input_drop_hints (hb_subset_input_t *subset_input);
 
 /* hb_subset() */
 
commit d78393b5547135b8db0356b0ec14d5ed0d334768
Merge: 1454d82a 83af6c23
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 17:53:26 2018 -0800

    Merge branch 'master' of https://github.com/harfbuzz/harfbuzz into drophints

diff --cc src/hb-subset.cc
index c708e193,12cdb1d2..cba05176
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@@ -229,9 -238,11 +238,12 @@@ _subset_table (hb_subset_plan_t *plan
      case HB_OT_TAG_glyf:
        result = _subset<const OT::glyf> (plan);
        break;
+     case HB_OT_TAG_hdmx:
+       result = _subset<const OT::hdmx> (plan);
+       break;
      case HB_OT_TAG_head:
 -      // SKIP head, it's handled by glyf
 +      // TODO that won't work well if there is no glyf
 +      DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
        result = true;
        break;
      case HB_OT_TAG_hhea:
commit 1454d82a9d3d9a47901b3d92ff7f2c05c596c0d5
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 17:49:23 2018 -0800

    [subset] keep glyph trim separate of more general get_offset

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index c92f63f4..3d030977 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -267,7 +267,7 @@ struct glyf
 			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
       unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, /* trim */ false, &start_offset, &end_offset))
+      if (!get_offsets (glyph, &start_offset, &end_offset))
         return false; /* glyph not found */
 
       return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
@@ -276,8 +276,8 @@ struct glyf
     }
 
     /* based on FontTools _g_l_y_f.py::trim */
-    inline bool trim_glyph(unsigned int start_offset,
-                           unsigned int *end_offset) const
+    inline bool trim(unsigned int start_offset,
+                     unsigned int *end_offset) const
     {
       static const int FLAG_X_SHORT = 0x02;
       static const int FLAG_Y_SHORT = 0x04;
@@ -359,7 +359,6 @@ struct glyf
     }
 
     inline bool get_offsets (hb_codepoint_t  glyph,
-                             bool trim,
                              unsigned int   *start_offset /* OUT */,
                              unsigned int   *end_offset   /* OUT */) const
     {
@@ -383,9 +382,6 @@ struct glyf
       if (*start_offset > *end_offset || *end_offset > glyf_len)
 	return false;
 
-      if (trim)
-        return trim_glyph(*start_offset, end_offset);
-
       return true;
     }
 
@@ -438,7 +434,7 @@ struct glyf
 			     hb_glyph_extents_t *extents) const
     {
       unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, /* trim */ false, &start_offset, &end_offset))
+      if (!get_offsets (glyph, &start_offset, &end_offset))
         return false;
 
       if (end_offset - start_offset < GlyphHeader::static_size)
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index ce7c99fe..654566af 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -47,7 +47,8 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
     *(instruction_ranges->push()) = 0;
 
     unsigned int start_offset, end_offset;
-    if (unlikely (!glyf.get_offsets(next_glyph, /* trim */ true, &start_offset, &end_offset)))
+    if (unlikely (!(glyf.get_offsets(next_glyph, &start_offset, &end_offset)
+                    && glyf.trim(start_offset, &end_offset))))
     {
       DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
       continue;
@@ -154,7 +155,8 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     unsigned int start_offset, end_offset;
-    if (unlikely (!glyf.get_offsets (glyph_ids[i], /* trim */ true, &start_offset, &end_offset)))
+    if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)
+                    && glyf.trim(start_offset, &end_offset))))
       end_offset = start_offset = 0;
     unsigned int instruction_start = instruction_ranges[i * 2];
     unsigned int instruction_end = instruction_ranges[i * 2 + 1];
commit 0ac8c0c1e6a6c076ce33b16baa173ff8763ac04e
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 17:43:00 2018 -0800

    [subset] zero glyf and loca memory before writing so pads are clean. Test just the part of maxp we care about

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 4b938017..c92f63f4 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -286,7 +286,7 @@ struct glyf
       static const int FLAG_Y_SAME = 0x20;
 
       if (*end_offset - start_offset < GlyphHeader::static_size)
-        return false;
+        return true;
 
       const char *glyph = ((const char *) glyf_table) + start_offset;
       const char * const glyph_end = glyph + (*end_offset - start_offset);
@@ -313,7 +313,7 @@ struct glyf
         while (glyph < glyph_end)
         {
           uint8_t flag = (uint8_t) *glyph;
-          glyph++; i++;
+          glyph++;
 
           unsigned int repeat = 1;
           if (flag & FLAG_REPEAT)
@@ -324,7 +324,7 @@ struct glyf
               return false;
             }
             repeat = ((uint8_t) *glyph) + 1;
-            glyph++; i++;
+            glyph++;
           }
 
           unsigned int xBytes, yBytes;
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 052af3f4..ce7c99fe 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -230,8 +230,8 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
     return false;
   }
 
-  char *glyf_prime_data = (char *) malloc (glyf_prime_size);
-  char *loca_prime_data = (char *) malloc (loca_prime_size);
+  char *glyf_prime_data = (char *) calloc (1, glyf_prime_size);
+  char *loca_prime_data = (char *) calloc (1, loca_prime_size);
   if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
                                              *use_short_loca,
                                              instruction_ranges,
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index 2f266d07..f5fdf32d 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -31,6 +31,18 @@
 
 /* Unit tests for hb-subset-glyf.h */
 
+static void check_maxp_num_glyphs (hb_face_t *face, uint16_t expected_num_glyphs)
+{
+  hb_blob_t *maxp_blob = hb_face_reference_table (face, HB_TAG ('m','a','x', 'p'));
+
+  unsigned int maxp_len;
+  uint8_t *raw_maxp = (uint8_t *) hb_blob_get_data(maxp_blob, &maxp_len);
+  uint16_t num_glyphs = (raw_maxp[4] << 8) + raw_maxp[5];
+  g_assert_cmpuint(expected_num_glyphs, ==, num_glyphs);
+
+  hb_blob_destroy (maxp_blob);
+}
+
 static void
 test_subset_glyf (void)
 {
@@ -45,7 +57,7 @@ test_subset_glyf (void)
 
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('m','a','x', 'p'));
+  check_maxp_num_glyphs(face_abc_subset, 3);
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
@@ -65,7 +77,7 @@ test_subset_glyf_with_components (void)
 
   hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('l','o','c', 'a'));
-  hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('m','a','x', 'p'));
+  check_maxp_num_glyphs(face_generated_subset, 4);
 
   hb_face_destroy (face_generated_subset);
   hb_face_destroy (face_subset);
@@ -86,6 +98,7 @@ test_subset_glyf_noop (void)
 
   hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  check_maxp_num_glyphs(face_abc_subset, 4);
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
@@ -107,7 +120,7 @@ test_subset_glyf_strip_hints (void)
 
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('m','a','x', 'p'));
+  check_maxp_num_glyphs(face_abc_subset, 3);
 
   hb_face_destroy (face_abc_subset);
   hb_face_destroy (face_abc);
commit 9bd6d25254d9bfc612004982dba286a3751d1d29
Author: Rod Sheeter <rsheeter at google.com>
Date:   Fri Feb 23 13:05:58 2018 -0800

    [subset] clone trim logic from fonttools glyf handling

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 667dfb52..4b938017 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -267,7 +267,7 @@ struct glyf
 			       CompositeGlyphHeader::Iterator *composite /* OUT */) const
     {
       unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
+      if (!get_offsets (glyph, /* trim */ false, &start_offset, &end_offset))
         return false; /* glyph not found */
 
       return CompositeGlyphHeader::get_iterator ((const char*) this->glyf_table + start_offset,
@@ -275,7 +275,91 @@ struct glyf
 						 composite);
     }
 
+    /* based on FontTools _g_l_y_f.py::trim */
+    inline bool trim_glyph(unsigned int start_offset,
+                           unsigned int *end_offset) const
+    {
+      static const int FLAG_X_SHORT = 0x02;
+      static const int FLAG_Y_SHORT = 0x04;
+      static const int FLAG_REPEAT = 0x08;
+      static const int FLAG_X_SAME = 0x10;
+      static const int FLAG_Y_SAME = 0x20;
+
+      if (*end_offset - start_offset < GlyphHeader::static_size)
+        return false;
+
+      const char *glyph = ((const char *) glyf_table) + start_offset;
+      const char * const glyph_end = glyph + (*end_offset - start_offset);
+      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyph, 0);
+      int16_t num_contours = (int16_t) glyph_header.numberOfContours;
+
+      if (num_contours < 0)
+        return true; /* no trimming for composites just yet */
+      else if (num_contours > 0)
+      {
+        unsigned int glyph_len = *end_offset - start_offset;
+        /* simple glyph w/contours, possibly trimmable */
+        glyph += GlyphHeader::static_size + 2 * num_contours;
+
+        if (unlikely (glyph + 2 >= glyph_end)) return false;
+        uint16_t nCoordinates = (uint16_t) StructAtOffset<HBUINT16>(glyph - 2, 0) + 1;
+        uint16_t nInstructions = (uint16_t) StructAtOffset<HBUINT16>(glyph, 0);
+
+        glyph += 2 + nInstructions;
+        if (unlikely (glyph + 2 >= glyph_end)) return false;
+
+        unsigned int coordBytes = 0;
+        unsigned int coordsWithFlags = 0;
+        while (glyph < glyph_end)
+        {
+          uint8_t flag = (uint8_t) *glyph;
+          glyph++; i++;
+
+          unsigned int repeat = 1;
+          if (flag & FLAG_REPEAT)
+          {
+            if (glyph >= glyph_end)
+            {
+              DEBUG_MSG(SUBSET, nullptr, "Bad flag");
+              return false;
+            }
+            repeat = ((uint8_t) *glyph) + 1;
+            glyph++; i++;
+          }
+
+          unsigned int xBytes, yBytes;
+          xBytes = yBytes = 0;
+          if (flag & FLAG_X_SHORT)
+            xBytes = 1;
+          else if ((flag & FLAG_X_SAME) == 0)
+            xBytes = 2;
+
+          if (flag & FLAG_Y_SHORT)
+            yBytes = 1;
+          else if ((flag & FLAG_Y_SAME) == 0)
+            yBytes = 2;
+
+          coordBytes += (xBytes + yBytes) * repeat;
+          coordsWithFlags += repeat;
+          if (coordsWithFlags >= nCoordinates)
+            break;
+        }
+
+        if (coordsWithFlags != nCoordinates)
+        {
+          DEBUG_MSG(SUBSET, nullptr, "Expect %d coords to have flags, got flags for %d", nCoordinates, coordsWithFlags);
+          return false;
+        }
+        glyph += coordBytes;
+
+        if (glyph < glyph_end)
+          *end_offset -= glyph_end - glyph;
+      }
+      return true;
+    }
+
     inline bool get_offsets (hb_codepoint_t  glyph,
+                             bool trim,
                              unsigned int   *start_offset /* OUT */,
                              unsigned int   *end_offset   /* OUT */) const
     {
@@ -291,6 +375,7 @@ struct glyf
       else
       {
         const HBUINT32 *offsets = (const HBUINT32 *) loca_table->dataX;
+
 	*start_offset = offsets[glyph];
 	*end_offset   = offsets[glyph + 1];
       }
@@ -298,6 +383,9 @@ struct glyf
       if (*start_offset > *end_offset || *end_offset > glyf_len)
 	return false;
 
+      if (trim)
+        return trim_glyph(*start_offset, end_offset);
+
       return true;
     }
 
@@ -350,7 +438,7 @@ struct glyf
 			     hb_glyph_extents_t *extents) const
     {
       unsigned int start_offset, end_offset;
-      if (!get_offsets (glyph, &start_offset, &end_offset))
+      if (!get_offsets (glyph, /* trim */ false, &start_offset, &end_offset))
         return false;
 
       if (end_offset - start_offset < GlyphHeader::static_size)
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 867810fb..052af3f4 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -43,12 +43,18 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     hb_codepoint_t next_glyph = glyph_ids[i];
+    *(instruction_ranges->push()) = 0;
+    *(instruction_ranges->push()) = 0;
+
     unsigned int start_offset, end_offset;
-    if (unlikely (!glyf.get_offsets(next_glyph, &start_offset, &end_offset)))
+    if (unlikely (!glyf.get_offsets(next_glyph, /* trim */ true, &start_offset, &end_offset)))
     {
       DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
       continue;
     }
+    if (end_offset - start_offset < OT::glyf::GlyphHeader::static_size)
+      continue; /* 0-length glyph */
+
     unsigned int instruction_start = 0, instruction_end = 0;
     if (drop_hints)
     {
@@ -58,12 +64,13 @@ _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
         DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
         return false;
       }
+      instruction_ranges->array[i * 2] = instruction_start;
+      instruction_ranges->array[i * 2 + 1] = instruction_end;
     }
-    *(instruction_ranges->push()) = instruction_start;
-    *(instruction_ranges->push()) = instruction_end;
 
     total += end_offset - start_offset - (instruction_end - instruction_start);
-    fprintf(stderr, "  %d ends at %d (was %d to %d, remove %d)\n", next_glyph, total, start_offset, end_offset, instruction_end - instruction_start);
+    /* round2 so short loca will work */
+    total += total % 2;
   }
 
   *glyf_size = total;
@@ -147,12 +154,13 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     unsigned int start_offset, end_offset;
-    if (unlikely (!glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)))
+    if (unlikely (!glyf.get_offsets (glyph_ids[i], /* trim */ true, &start_offset, &end_offset)))
       end_offset = start_offset = 0;
     unsigned int instruction_start = instruction_ranges[i * 2];
     unsigned int instruction_end = instruction_ranges[i * 2 + 1];
 
     int length = end_offset - start_offset - (instruction_end - instruction_start);
+    length += length % 2;
 
     if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
     {
@@ -164,21 +172,17 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
     }
 
     if (instruction_start == instruction_end)
-    {
-      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, length, start_offset, glyf_prime_data_next - glyf_prime_data);
       memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
-    }
     else
     {
-      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, instruction_start - start_offset, start_offset, glyf_prime_data_next - glyf_prime_data);
-      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, end_offset - instruction_end, instruction_end, glyf_prime_data_next + instruction_start - start_offset - glyf_prime_data);
       memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
       memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
       /* if the instructions end at the end this was a composite glyph */
       if (instruction_end == end_offset)
         ; // TODO(rsheeter) remove WE_HAVE_INSTRUCTIONS from last flags
       else
-        ; // TODO(rsheeter) zero instructionLength
+        /* zero instruction length, which is just before instruction_start */
+        memset (glyf_prime_data_next + instruction_start - start_offset - 2, 0, 2);
     }
 
     success = success && _write_loca_entry (i,
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 0f653ff3..8dfa660d 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -79,6 +79,9 @@ hb_subset_plan_add_table (hb_subset_plan_t *plan,
                           hb_tag_t tag,
                           hb_blob_t *contents)
 {
+  hb_blob_t *source_blob = plan->source->reference_table (tag);
+  DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %d bytes, source %d bytes", HB_UNTAG(tag), hb_blob_get_length (contents), hb_blob_get_length (source_blob));
+  hb_blob_destroy (source_blob);
   return hb_subset_face_add_table(plan->dest, tag, contents);
 }
 
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index b46b07fc..c708e193 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -230,11 +230,12 @@ _subset_table (hb_subset_plan_t *plan,
       result = _subset<const OT::glyf> (plan);
       break;
     case HB_OT_TAG_head:
-      // SKIP head, it's handled by glyf
+      // TODO that won't work well if there is no glyf
+      DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
       result = true;
       break;
     case HB_OT_TAG_hhea:
-      // SKIP hhea, it's handled by hmtx
+      DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
       return true;
     case HB_OT_TAG_hmtx:
       result = _subset<const OT::hmtx> (plan);
@@ -243,7 +244,7 @@ _subset_table (hb_subset_plan_t *plan,
       result = _subset<const OT::maxp> (plan);
       break;
     case HB_OT_TAG_loca:
-      // SKIP loca, it's handle by glyf
+      DEBUG_MSG(SUBSET, nullptr, "skip loca handled by glyf");
       return true;
     case HB_OT_TAG_cmap:
       result = _subset<const OT::cmap> (plan);
@@ -254,16 +255,12 @@ _subset_table (hb_subset_plan_t *plan,
     default:
       hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
       if (likely(source_table))
-      {
         result = hb_subset_plan_add_table(plan, tag, source_table);
-      }
       else
-      {
         result = false;
-      }
+      DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED");
       break;
   }
-  DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED");
   return result;
 }
 
diff --git a/test/api/fonts/Roboto-Regular.ac.nohints.ttf b/test/api/fonts/Roboto-Regular.ac.nohints.ttf
index b7cdffed..b7339178 100644
Binary files a/test/api/fonts/Roboto-Regular.ac.nohints.ttf and b/test/api/fonts/Roboto-Regular.ac.nohints.ttf differ
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 8f7fe393..8e579a6c 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -122,6 +122,7 @@ hb_subset_test_check (hb_face_t *expected,
                       hb_face_t *actual,
                       hb_tag_t   table)
 {
+  fprintf(stderr, "compare %c%c%c%c\n", HB_UNTAG(table));
   hb_blob_t *expected_blob = hb_face_reference_table (expected, table);
   hb_blob_t *actual_blob = hb_face_reference_table (actual, table);
   hb_test_assert_blobs_equal (expected_blob, actual_blob);
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index a4b4295f..2f266d07 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -105,8 +105,8 @@ test_subset_glyf_strip_hints (void)
   hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, input);
   hb_set_destroy (codepoints);
 
-  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('m','a','x', 'p'));
 
   hb_face_destroy (face_abc_subset);
@@ -123,10 +123,10 @@ main (int argc, char **argv)
 {
   hb_test_init (&argc, &argv);
 
-  hb_test_add (test_subset_glyf);
-  hb_test_add (test_subset_glyf_with_components);
   hb_test_add (test_subset_glyf_noop);
+  hb_test_add (test_subset_glyf);
   hb_test_add (test_subset_glyf_strip_hints);
+  hb_test_add (test_subset_glyf_with_components);
 
   return hb_test_run();
 }
commit 4f07437dfebd3dc5923f40154c6f1b7e1dce1bd4
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 21 22:23:05 2018 -0800

    [subset] sketch out dropping in-glyf instructions. Sometimes yields differnet size glyphs than fonttools, possibly due to padding not being corrected

diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh
index 50a71115..667dfb52 100644
--- a/src/hb-ot-glyf-table.hh
+++ b/src/hb-ot-glyf-table.hh
@@ -301,6 +301,51 @@ struct glyf
       return true;
     }
 
+    inline bool get_instruction_offsets(unsigned int start_offset,
+                                        unsigned int end_offset,
+                                        unsigned int *instruction_start /* OUT */,
+                                        unsigned int *instruction_end /* OUT */) const
+    {
+      if (end_offset - start_offset < GlyphHeader::static_size)
+      {
+        *instruction_start = 0;
+        *instruction_end = 0;
+        return true; /* Empty glyph; no instructions. */
+      }
+      const GlyphHeader &glyph_header = StructAtOffset<GlyphHeader> (glyf_table, start_offset);
+      int16_t num_contours = (int16_t) glyph_header.numberOfContours;
+      if (num_contours < 0)
+      {
+        CompositeGlyphHeader::Iterator *composite_it;
+        if (unlikely (!CompositeGlyphHeader::get_iterator (
+            (const char*) this->glyf_table + start_offset,
+             end_offset - start_offset, composite_it))) return false;
+        const CompositeGlyphHeader *last;
+        do {
+          last = composite_it->current;
+        } while (composite_it->move_to_next());
+
+        if ( (uint16_t) last->flags & CompositeGlyphHeader::WE_HAVE_INSTRUCTIONS)
+          *instruction_start = start_offset + ((char *) last - (char *) glyf_table->dataX) + last->get_size();
+        else
+          *instruction_start = end_offset;
+        *instruction_end = end_offset;
+        if (unlikely (*instruction_start > *instruction_end))
+        {
+          DEBUG_MSG(SUBSET, nullptr, "Invalid instruction offset, %d is outside [%d, %d]", *instruction_start, start_offset, end_offset);
+          return false;
+        }
+      }
+      else
+      {
+        unsigned int instruction_length_offset = start_offset + GlyphHeader::static_size + 2 * num_contours;
+        const HBUINT16 &instruction_length = StructAtOffset<HBUINT16> (glyf_table, instruction_length_offset);
+        *instruction_start = instruction_length_offset + 2;
+        *instruction_end = *instruction_start + (uint16_t) instruction_length;
+      }
+      return true;
+    }
+
     inline bool get_extents (hb_codepoint_t glyph,
 			     hb_glyph_extents_t *extents) const
     {
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index d57b4115..867810fb 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -21,7 +21,7 @@
  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
- * Google Author(s): Garret Rieger
+ * Google Author(s): Garret Rieger, Roderick Sheeter
  */
 
 #include "hb-open-type-private.hh"
@@ -33,26 +33,42 @@
 static bool
 _calculate_glyf_and_loca_prime_size (const OT::glyf::accelerator_t &glyf,
                                      hb_prealloced_array_t<hb_codepoint_t> &glyph_ids,
-                                     bool *use_short_loca, /* OUT */
-                                     unsigned int *glyf_size, /* OUT */
-                                     unsigned int *loca_size /* OUT */)
+                                     hb_bool_t drop_hints,
+                                     bool *use_short_loca /* OUT */,
+                                     unsigned int *glyf_size /* OUT */,
+                                     unsigned int *loca_size /* OUT */,
+                                     hb_prealloced_array_t<unsigned int> *instruction_ranges /* OUT */)
 {
   unsigned int total = 0;
-  unsigned int count = 0;
   for (unsigned int i = 0; i < glyph_ids.len; i++)
   {
     hb_codepoint_t next_glyph = glyph_ids[i];
     unsigned int start_offset, end_offset;
-    if (unlikely (!glyf.get_offsets (next_glyph, &start_offset, &end_offset)))
-      end_offset = start_offset = 0;
+    if (unlikely (!glyf.get_offsets(next_glyph, &start_offset, &end_offset)))
+    {
+      DEBUG_MSG(SUBSET, nullptr, "Invalid gid %d", next_glyph);
+      continue;
+    }
+    unsigned int instruction_start = 0, instruction_end = 0;
+    if (drop_hints)
+    {
+      if (unlikely (!glyf.get_instruction_offsets(start_offset, end_offset,
+                                                  &instruction_start, &instruction_end)))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "Unable to get instruction offsets for %d", next_glyph);
+        return false;
+      }
+    }
+    *(instruction_ranges->push()) = instruction_start;
+    *(instruction_ranges->push()) = instruction_end;
 
-    total += end_offset - start_offset;
-    count++;
+    total += end_offset - start_offset - (instruction_end - instruction_start);
+    fprintf(stderr, "  %d ends at %d (was %d to %d, remove %d)\n", next_glyph, total, start_offset, end_offset, instruction_end - instruction_start);
   }
 
   *glyf_size = total;
   *use_short_loca = (total <= 131070);
-  *loca_size = (count + 1)
+  *loca_size = (glyph_ids.len + 1)
       * (*use_short_loca ? sizeof(OT::HBUINT16) : sizeof(OT::HBUINT32));
 
   DEBUG_MSG(SUBSET, nullptr, "preparing to subset glyf: final size %d, loca size %d, using %s loca",
@@ -118,6 +134,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
 			    const OT::glyf::accelerator_t &glyf,
                             const char                    *glyf_data,
                             bool                           use_short_loca,
+                            hb_prealloced_array_t<unsigned int> &instruction_ranges,
                             unsigned int                   glyf_prime_size,
                             char                          *glyf_prime_data /* OUT */,
                             unsigned int                   loca_prime_size,
@@ -132,25 +149,44 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
     unsigned int start_offset, end_offset;
     if (unlikely (!glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset)))
       end_offset = start_offset = 0;
+    unsigned int instruction_start = instruction_ranges[i * 2];
+    unsigned int instruction_end = instruction_ranges[i * 2 + 1];
 
-    int length = end_offset - start_offset;
+    int length = end_offset - start_offset - (instruction_end - instruction_start);
 
     if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size)
     {
       DEBUG_MSG (SUBSET,
                  nullptr,
-                 "WARNING: Attempted to write an out of bounds glyph entry for gid %d",
-                 i);
+                 "WARNING: Attempted to write an out of bounds glyph entry for gid %d (length %d)",
+                 i, length);
       return false;
     }
-    memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
+
+    if (instruction_start == instruction_end)
+    {
+      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, length, start_offset, glyf_prime_data_next - glyf_prime_data);
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, length);
+    }
+    else
+    {
+      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, instruction_start - start_offset, start_offset, glyf_prime_data_next - glyf_prime_data);
+      fprintf(stderr, "i=%d copy %d bytes from %d to %ld\n", i, end_offset - instruction_end, instruction_end, glyf_prime_data_next + instruction_start - start_offset - glyf_prime_data);
+      memcpy (glyf_prime_data_next, glyf_data + start_offset, instruction_start - start_offset);
+      memcpy (glyf_prime_data_next + instruction_start - start_offset, glyf_data + instruction_end, end_offset - instruction_end);
+      /* if the instructions end at the end this was a composite glyph */
+      if (instruction_end == end_offset)
+        ; // TODO(rsheeter) remove WE_HAVE_INSTRUCTIONS from last flags
+      else
+        ; // TODO(rsheeter) zero instructionLength
+    }
 
     success = success && _write_loca_entry (i,
                                             glyf_prime_data_next - glyf_prime_data,
                                             use_short_loca,
                                             loca_prime_data,
                                             loca_prime_size);
-    _update_components (plan, glyf_prime_data_next, end_offset - start_offset);
+    _update_components (plan, glyf_prime_data_next, length);
 
     glyf_prime_data_next += length;
   }
@@ -166,7 +202,7 @@ _write_glyf_and_loca_prime (hb_subset_plan_t              *plan,
 static bool
 _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
                           const char                     *glyf_data,
-			  hb_subset_plan_t               *plan,
+                          hb_subset_plan_t               *plan,
                           bool                           *use_short_loca,
                           hb_blob_t                     **glyf_prime /* OUT */,
                           hb_blob_t                     **loca_prime /* OUT */)
@@ -176,12 +212,17 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
 
   unsigned int glyf_prime_size;
   unsigned int loca_prime_size;
+  hb_prealloced_array_t<unsigned int> instruction_ranges;
+  instruction_ranges.init();
 
   if (unlikely (!_calculate_glyf_and_loca_prime_size (glyf,
                                                       glyphs_to_retain,
+                                                      plan->drop_hints,
                                                       use_short_loca,
                                                       &glyf_prime_size,
-                                                      &loca_prime_size))) {
+                                                      &loca_prime_size,
+                                                      &instruction_ranges))) {
+    instruction_ranges.finish();
     return false;
   }
 
@@ -189,12 +230,15 @@ _hb_subset_glyf_and_loca (const OT::glyf::accelerator_t  &glyf,
   char *loca_prime_data = (char *) malloc (loca_prime_size);
   if (unlikely (!_write_glyf_and_loca_prime (plan, glyf, glyf_data,
                                              *use_short_loca,
+                                             instruction_ranges,
                                              glyf_prime_size, glyf_prime_data,
                                              loca_prime_size, loca_prime_data))) {
     free (glyf_prime_data);
     free (loca_prime_data);
+    instruction_ranges.finish();
     return false;
   }
+  instruction_ranges.finish();
 
   *glyf_prime = hb_blob_create (glyf_prime_data,
                                 glyf_prime_size,
diff --git a/src/hb-subset-input.cc b/src/hb-subset-input.cc
index d41cff60..69aa9d61 100644
--- a/src/hb-subset-input.cc
+++ b/src/hb-subset-input.cc
@@ -105,3 +105,9 @@ hb_subset_input_glyph_set (hb_subset_input_t *subset_input)
 {
   return subset_input->glyphs;
 }
+
+HB_EXTERN hb_bool_t *
+hb_subset_input_drop_hints(hb_subset_input_t *subset_input)
+{
+  return &subset_input->drop_hints;
+}
diff --git a/src/hb-subset.h b/src/hb-subset.h
index de7759b2..1af7cba5 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -68,6 +68,8 @@ hb_subset_input_unicode_set (hb_subset_input_t *subset_input);
 HB_EXTERN hb_set_t *
 hb_subset_input_glyph_set (hb_subset_input_t *subset_input);
 
+HB_EXTERN hb_bool_t *
+hb_subset_input_drop_hints(hb_subset_input_t *subset_input);
 
 /* hb_subset() */
 
diff --git a/test/api/fonts/Roboto-Regular.ac.nohints.ttf b/test/api/fonts/Roboto-Regular.ac.nohints.ttf
new file mode 100644
index 00000000..b7cdffed
Binary files /dev/null and b/test/api/fonts/Roboto-Regular.ac.nohints.ttf differ
diff --git a/test/api/hb-subset-test.h b/test/api/hb-subset-test.h
index 12f7868a..8f7fe393 100644
--- a/test/api/hb-subset-test.h
+++ b/test/api/hb-subset-test.h
@@ -95,17 +95,20 @@ hb_subset_test_open_font (const char *font_path)
   return NULL; /* Shut up, compiler! */
 }
 
-static inline hb_face_t *
-hb_subset_test_create_subset (hb_face_t *source,
-                              const hb_set_t  *codepoints)
+static inline hb_subset_input_t *
+hb_subset_test_create_input(const hb_set_t  *codepoints)
 {
-  hb_subset_profile_t *profile = hb_subset_profile_create();
   hb_subset_input_t *input = hb_subset_input_create_or_fail ();
-
   hb_set_t * input_codepoints = hb_subset_input_unicode_set (input);
-
   hb_set_union (input_codepoints, codepoints);
+  return input;
+}
 
+static inline hb_face_t *
+hb_subset_test_create_subset (hb_face_t *source,
+                              hb_subset_input_t *input)
+{
+  hb_subset_profile_t *profile = hb_subset_profile_create();
   hb_face_t *subset = hb_subset (source, profile, input);
   g_assert (subset);
 
diff --git a/test/api/test-subset-cmap.c b/test/api/test-subset-cmap.c
index 8798475f..07715791 100644
--- a/test/api/test-subset-cmap.c
+++ b/test/api/test-subset-cmap.c
@@ -40,7 +40,7 @@ test_subset_cmap (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 97);
   hb_set_add (codepoints, 99);
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('c','m','a','p'));
@@ -59,7 +59,7 @@ test_subset_cmap_noop (void)
   hb_set_add (codepoints, 97);
   hb_set_add (codepoints, 98);
   hb_set_add (codepoints, 99);
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('c','m','a','p'));
diff --git a/test/api/test-subset-glyf.c b/test/api/test-subset-glyf.c
index 96e37bbc..a4b4295f 100644
--- a/test/api/test-subset-glyf.c
+++ b/test/api/test-subset-glyf.c
@@ -40,7 +40,7 @@ test_subset_glyf (void)
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 97);
   hb_set_add (codepoints, 99);
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
@@ -60,7 +60,7 @@ test_subset_glyf_with_components (void)
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 0x1fc);
-  hb_face_t *face_generated_subset = hb_subset_test_create_subset (face_components, codepoints);
+  hb_face_t *face_generated_subset = hb_subset_test_create_subset (face_components, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_subset, face_generated_subset, HB_TAG ('g','l','y','f'));
@@ -81,7 +81,7 @@ test_subset_glyf_noop (void)
   hb_set_add (codepoints, 97);
   hb_set_add (codepoints, 98);
   hb_set_add (codepoints, 99);
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_abc, face_abc_subset, HB_TAG ('g','l','y','f'));
@@ -91,6 +91,31 @@ test_subset_glyf_noop (void)
   hb_face_destroy (face_abc);
 }
 
+static void
+test_subset_glyf_strip_hints (void)
+{
+  hb_face_t *face_abc = hb_subset_test_open_font ("fonts/Roboto-Regular.abc.ttf");
+  hb_face_t *face_ac = hb_subset_test_open_font ("fonts/Roboto-Regular.ac.nohints.ttf");
+
+  hb_set_t *codepoints = hb_set_create();
+  hb_set_add (codepoints, 'a');
+  hb_set_add (codepoints, 'c');
+  hb_subset_input_t *input = hb_subset_test_create_input (codepoints);
+  *hb_subset_input_drop_hints(input) = true;
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, input);
+  hb_set_destroy (codepoints);
+
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('g','l','y','f'));
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('l','o','c', 'a'));
+  hb_subset_test_check (face_ac, face_abc_subset, HB_TAG ('m','a','x', 'p'));
+
+  hb_face_destroy (face_abc_subset);
+  hb_face_destroy (face_abc);
+  hb_face_destroy (face_ac);
+}
+
+// TODO(rsheeter): test strip hints from composite
+
 // TODO(grieger): test for long loca generation.
 
 int
@@ -101,6 +126,7 @@ main (int argc, char **argv)
   hb_test_add (test_subset_glyf);
   hb_test_add (test_subset_glyf_with_components);
   hb_test_add (test_subset_glyf_noop);
+  hb_test_add (test_subset_glyf_strip_hints);
 
   return hb_test_run();
 }
diff --git a/test/api/test-subset-hmtx.c b/test/api/test-subset-hmtx.c
index 36d7d9e8..2b764526 100644
--- a/test/api/test-subset-hmtx.c
+++ b/test/api/test-subset-hmtx.c
@@ -55,7 +55,7 @@ test_subset_hmtx_simple_subset (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_hmetrics(face_abc_subset, 3); /* nothing has same width */
@@ -76,7 +76,7 @@ test_subset_hmtx_monospace (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_hmetrics(face_abc_subset, 1); /* everything has same width */
@@ -97,7 +97,7 @@ test_subset_hmtx_keep_num_metrics (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_hmetrics(face_abc_subset, 3); /* c is wider */
@@ -117,7 +117,7 @@ test_subset_hmtx_decrease_num_metrics (void)
   hb_set_t *codepoints = hb_set_create ();
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_hmetrics(face_abc_subset, 1); /* everything left has same width */
@@ -137,7 +137,7 @@ test_subset_hmtx_noop (void)
   hb_set_add (codepoints, 'a');
   hb_set_add (codepoints, 'b');
   hb_set_add (codepoints, 'c');
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   check_num_hmetrics(face_abc_subset, 4); /* nothing has same width */
diff --git a/test/api/test-subset-os2.c b/test/api/test-subset-os2.c
index e2b96f92..e9db9bed 100644
--- a/test/api/test-subset-os2.c
+++ b/test/api/test-subset-os2.c
@@ -37,7 +37,7 @@ test_subset_os2 (void)
 
   hb_set_t *codepoints = hb_set_create();
   hb_set_add (codepoints, 98);
-  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, codepoints);
+  hb_face_t *face_abc_subset = hb_subset_test_create_subset (face_abc, hb_subset_test_create_input (codepoints));
   hb_set_destroy (codepoints);
 
   hb_subset_test_check (face_b, face_abc_subset, HB_TAG ('O','S','/','2'));
commit 74e0c13a4a55848e797242c02c8f067e587ea603
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 21 11:19:18 2018 -0800

    [subset] drop hint tables if so flagged. Still need to dump glyf instructions.

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index b9e299ad..0f653ff3 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -191,6 +191,7 @@ hb_subset_plan_create (hb_face_t           *face,
   plan->gids_to_retain_sorted.init();
   plan->source = hb_face_reference (face);
   plan->dest = hb_subset_face_create ();
+  plan->drop_hints = input->drop_hints;
 
   _populate_codepoints (input->unicodes, plan->codepoints);
   _populate_gids_to_retain (face,
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index a7415285..d1b66b44 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -37,6 +37,8 @@ struct hb_subset_plan_t {
   hb_object_header_t header;
   ASSERT_POD ();
 
+  hb_bool_t drop_hints;
+
   // TODO(Q1) actual map, drop this crap
   // Look at me ma, I'm a poor mans map codepoint : new gid
   // codepoints is sorted and aligned with gids_to_retain.
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index 55ac6f12..5fa72527 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -43,7 +43,7 @@ struct hb_subset_input_t {
   hb_set_t *unicodes;
   hb_set_t *glyphs;
 
-  hb_bool_t retain_hints;
+  hb_bool_t drop_hints;
   /* TODO
    *
    * features
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index a4794f18..b46b07fc 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -268,9 +268,16 @@ _subset_table (hb_subset_plan_t *plan,
 }
 
 static bool
-_should_drop_table(hb_tag_t tag)
+_should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag)
 {
     switch (tag) {
+      case HB_TAG ('c', 'v', 'a', 'r'): /* hint table, fallthrough */
+      case HB_TAG ('c', 'v', 't', ' '): /* hint table, fallthrough */
+      case HB_TAG ('f', 'p', 'g', 'm'): /* hint table, fallthrough */
+      case HB_TAG ('p', 'r', 'e', 'p'): /* hint table, fallthrough */
+      case HB_TAG ('h', 'd', 'm', 'x'): /* hint table, fallthrough */
+      case HB_TAG ('V', 'D', 'M', 'X'): /* hint table, fallthrough */
+        return plan->drop_hints;
       case HB_TAG ('G', 'D', 'E', 'F'): /* temporary */
       case HB_TAG ('G', 'P', 'O', 'S'): /* temporary */
       case HB_TAG ('G', 'S', 'U', 'B'): /* temporary */
@@ -307,7 +314,7 @@ hb_subset (hb_face_t *source,
     for (unsigned int i = 0; i < count; i++)
     {
       hb_tag_t tag = table_tags[i];
-      if (_should_drop_table(tag))
+      if (_should_drop_table(plan, tag))
       {
         DEBUG_MSG(SUBSET, nullptr, "drop %c%c%c%c", HB_UNTAG(tag));
         continue;
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 3db62598..20617554 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -90,7 +90,7 @@ struct subset_consumer_t
 
   void finish (const font_options_t *font_opts)
   {
-    input->retain_hints = subset_options.hinting;
+    input->drop_hints = subset_options.drop_hints;
 
     hb_subset_profile_t *subset_profile = hb_subset_profile_create();
     hb_face_t *face = hb_font_get_face (font);
diff --git a/util/options.cc b/util/options.cc
index aa8a6a96..7571fe84 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -992,7 +992,7 @@ subset_options_t::add_options (option_parser_t *parser)
 {
   GOptionEntry entries[] =
   {
-    {"hinting", 0, 0, G_OPTION_ARG_NONE,  &this->hinting,   "Whether to retain or drop hints",   nullptr},
+    {"no-hinting", 0, 0, G_OPTION_ARG_NONE,  &this->drop_hints,   "Whether to drop hints",   nullptr},
     {nullptr}
   };
   parser->add_group (entries,
diff --git a/util/options.hh b/util/options.hh
index 80d32d90..cce0eb16 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -653,14 +653,14 @@ struct subset_options_t : option_group_t
 {
   subset_options_t (option_parser_t *parser)
   {
-    hinting = true;
+    drop_hints = false;
 
     add_options (parser);
   }
 
   void add_options (option_parser_t *parser);
 
-  hb_bool_t hinting;
+  hb_bool_t drop_hints;
 };
 
 /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
commit 0bd100e144885ed8144cf23e7e106014858a1724
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 21 10:34:00 2018 -0800

    [subset] add --hinting flag

diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index cf784d72..55ac6f12 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -43,6 +43,7 @@ struct hb_subset_input_t {
   hb_set_t *unicodes;
   hb_set_t *glyphs;
 
+  hb_bool_t retain_hints;
   /* TODO
    *
    * features
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index ea657aff..3db62598 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -29,6 +29,7 @@
 
 #include "main-font-text.hh"
 #include "hb-subset.h"
+#include "hb-subset-private.hh"
 
 /*
  * Command line interface to the harfbuzz font subsetter.
@@ -37,7 +38,7 @@
 struct subset_consumer_t
 {
   subset_consumer_t (option_parser_t *parser)
-      : failed (false), options (parser), font (nullptr), input (nullptr) {}
+      : failed (false), options (parser), subset_options (parser), font (nullptr), input (nullptr) {}
 
   void init (hb_buffer_t  *buffer_,
              const font_options_t *font_opts)
@@ -89,6 +90,8 @@ struct subset_consumer_t
 
   void finish (const font_options_t *font_opts)
   {
+    input->retain_hints = subset_options.hinting;
+
     hb_subset_profile_t *subset_profile = hb_subset_profile_create();
     hb_face_t *face = hb_font_get_face (font);
 
@@ -111,6 +114,7 @@ struct subset_consumer_t
 
   private:
   output_options_t options;
+  subset_options_t subset_options;
   hb_font_t *font;
   hb_subset_input_t *input;
 };
diff --git a/util/options.cc b/util/options.cc
index 6d8064b9..aa8a6a96 100644
--- a/util/options.cc
+++ b/util/options.cc
@@ -986,3 +986,18 @@ format_options_t::serialize_buffer_of_glyphs (hb_buffer_t  *buffer,
   serialize_glyphs (buffer, font, output_format, format_flags, gs);
   g_string_append_c (gs, '\n');
 }
+
+void
+subset_options_t::add_options (option_parser_t *parser)
+{
+  GOptionEntry entries[] =
+  {
+    {"hinting", 0, 0, G_OPTION_ARG_NONE,  &this->hinting,   "Whether to retain or drop hints",   nullptr},
+    {nullptr}
+  };
+  parser->add_group (entries,
+         "subset",
+         "Subset options:",
+         "Options subsetting",
+         this);
+}
diff --git a/util/options.hh b/util/options.hh
index 411165bf..80d32d90 100644
--- a/util/options.hh
+++ b/util/options.hh
@@ -649,6 +649,20 @@ struct format_options_t : option_group_t
   hb_bool_t trace;
 };
 
+struct subset_options_t : option_group_t
+{
+  subset_options_t (option_parser_t *parser)
+  {
+    hinting = true;
+
+    add_options (parser);
+  }
+
+  void add_options (option_parser_t *parser);
+
+  hb_bool_t hinting;
+};
+
 /* fallback implementation for scalbn()/scalbnf() for pre-2013 MSVC */
 #if defined (_MSC_VER) && (_MSC_VER < 1800)
 
commit 7ecca8c0a83a6c71154fcc80887a4f895c0c5a23
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 21 09:42:46 2018 -0800

    [subset] keep the result of _subset

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 418e481f..a4794f18 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -264,7 +264,7 @@ _subset_table (hb_subset_plan_t *plan,
       break;
   }
   DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED");
-  return true;
+  return result;
 }
 
 static bool
commit 3ebcd5a381e2de27a0cfb5af3359331f0b7e7108
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Mar 5 16:26:01 2017 +0100

    first working version!

diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 3511810a..d393f5ca 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -57,6 +57,7 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->gpos = OT::Sanitizer<OT::GPOS>::lock_instance (layout->gpos_blob);
 
   layout->math.init (face);
+  layout->base.init (face);
   layout->fvar.init (face);
   layout->avar.init (face);
 
@@ -185,6 +186,7 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   hb_blob_destroy (layout->gpos_blob);
 
   layout->math.fini ();
+  layout->base.fini ();
   layout->fvar.fini ();
   layout->avar.fini ();
 
diff --git a/src/hb-ot.h b/src/hb-ot.h
index 2120a3ef..272208e3 100644
--- a/src/hb-ot.h
+++ b/src/hb-ot.h
@@ -33,6 +33,7 @@
 #include "hb-ot-font.h"
 #include "hb-ot-layout.h"
 #include "hb-ot-math.h"
+#include "hb-ot-base.h"
 #include "hb-ot-tag.h"
 #include "hb-ot-shape.h"
 #include "hb-ot-var.h"
commit e65aaaa00a3b5ac811b5c73b5186cd7d65731f7b
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Mar 5 14:53:39 2017 +0100

    BASE: start api

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0f83f6eb..db730565 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -68,6 +68,7 @@ HB_NODIST_headers = \
 HB_FALLBACK_sources = hb-fallback-shape.cc
 
 HB_OT_sources = \
+	hb-ot-base.cc \
 	hb-ot-font.cc \
 	hb-ot-layout.cc \
 	hb-ot-layout-base-table.hh \
@@ -121,6 +122,7 @@ HB_OT_headers = \
 	hb-ot-font.h \
 	hb-ot-layout.h \
 	hb-ot-math.h \
+	hb-ot-base.h \
 	hb-ot-shape.h \
 	hb-ot-tag.h \
 	hb-ot-var.h \
diff --git a/src/hb-ot-base.cc b/src/hb-ot-base.cc
new file mode 100644
index 00000000..27e0b208
--- /dev/null
+++ b/src/hb-ot-base.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright © 2017 Elie Roux<elie.roux at telecom-bretagne.eu>
+ *
+ *  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.
+ *
+ */
+
+#include "hb-open-type-private.hh"
+
+#include "hb-ot-layout-private.hh"
+#include "hb-ot-layout-base-table.hh"
+
+static inline const OT::BASE&
+_get_base (hb_face_t *face)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return OT::Null(OT::BASE);
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  return *(layout->base.get ());
+}
+
+/*
+ * OT::BASE
+ */
+
+/**
+ * hb_ot_base_has_data:
+ * @face: #hb_face_t to test
+ *
+ * This function allows to verify the presence of an OpenType BASE table on the
+ * face.
+ *
+ * Return value: true if face has a BASE table, false otherwise
+ *
+ * Since: XXX
+ **/
+hb_bool_t
+hb_ot_base_has_data (hb_face_t *face)
+{
+  return &_get_base (face) != &OT::Null(OT::BASE);
+}
diff --git a/src/hb-ot-base.h b/src/hb-ot-base.h
new file mode 100644
index 00000000..9d82d228
--- /dev/null
+++ b/src/hb-ot-base.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2017 Elie Roux<elie.roux at telecom-bretagne.eu>
+ *
+ *  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.
+ *
+ */
+
+#ifndef HB_OT_H_IN
+#error "Include <hb-ot.h> instead."
+#endif
+
+#ifndef HB_OT_BASE_H
+#define HB_OT_BASE_H
+
+#include "hb.h"
+
+HB_BEGIN_DECLS
+
+#define HB_OT_TAG_BASE      HB_TAG('B','A','S','E')
+
+// https://www.microsoft.com/typography/otspec/baselinetags.htm
+
+#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
+#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
+#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
+#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
+#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
+#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
+#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
+
+/* Methods */
+
+HB_EXTERN hb_bool_t
+hb_ot_base_has_data (hb_face_t *face);
+
+HB_END_DECLS
+
+#endif /* HB_OT_BASE_H */
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index c60ce6de..0d1e197e 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -28,18 +28,7 @@
 
 #include "hb-open-type-private.hh"
 #include "hb-ot-layout-common-private.hh"
-
-#define HB_OT_TAG_BASE      HB_TAG('B','A','S','E')
-
-// https://www.microsoft.com/typography/otspec/baselinetags.htm
-
-#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
-#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
-#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
-#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
-#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
-#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
-#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
+#include "hb-ot-base.h"
 
 namespace OT {
 
@@ -743,7 +732,7 @@ struct BASE
   inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     if (!u.version.sanitize (c)) return_trace (false);
commit f72726c52b104a71ebf5b39fa1e3eb9febd446fc
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Feb 26 15:08:43 2017 +0100

    BASE: add function in main BASE object

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 9be403e5..c60ce6de 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -719,6 +719,30 @@ struct BASE
   inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
   { return u.format1_0.get_vert_base_coord(baseScriptIndex, baselineTagIndex); }
 
+  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  { return u.format1_0.get_horiz_lang_tag_index(baseScriptIndex, baseLangSysTag); }
+
+  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  { return u.format1_0.get_horiz_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+
+  inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return u.format1_0.get_horiz_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+
+  inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return u.format1_0.get_horiz_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+
+  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  { return u.format1_0.get_vert_lang_tag_index(baseScriptIndex, baseLangSysTag); }
+
+  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  { return u.format1_0.get_vert_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag); }
+
+  inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return u.format1_0.get_vert_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+
+  inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return u.format1_0.get_vert_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex); }
+
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
commit 3963315f1b2eae2504bc683760245c827cd1ef16
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Feb 26 15:07:53 2017 +0100

    BASE: first complete version

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index c4d9ad14..9be403e5 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -43,7 +43,9 @@
 
 namespace OT {
 
-#define NO_COORD -32767
+#define NO_COORD Null(SHORT)//SHORT((short int) -32767)
+
+#define NOT_INDEXED   ((unsigned int) -1)
 
 /*
  * BASE -- The BASE Table
@@ -51,7 +53,7 @@ namespace OT {
 
 struct BaseCoordFormat1 {
 
-  inline SHORT get_coord () const
+  inline SHORT get_coord (void) const
   { return coordinate; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -70,7 +72,7 @@ struct BaseCoordFormat1 {
 
 struct BaseCoordFormat2 {
 
-  inline SHORT get_coord () const
+  inline SHORT get_coord (void) const
   { return coordinate; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -91,7 +93,7 @@ struct BaseCoordFormat2 {
 
 struct BaseCoordFormat3 {
 
-  inline SHORT get_coord (void ) const
+  inline SHORT get_coord (void) const
   { return coordinate; }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -111,17 +113,8 @@ struct BaseCoordFormat3 {
 
 struct BaseCoord {
 
-  inline hb_position_t get_value (hb_font_t *font, hb_direction_t dir) const
-  { 
-    SHORT coord;
-    switch (u.baseCoordFormat) {
-    case 1: coord = u.format1.get_coord();
-    case 2: coord = u.format2.get_coord();
-    case 3: coord = u.format3.get_coord();
-    default: return 0;
-    }
-    return font->em_scale (coord, dir); 
-  }
+  inline SHORT get_coord (void) const
+  { return u.format1.get_coord(); }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -131,7 +124,7 @@ struct BaseCoord {
     case 1: return_trace (u.format1.sanitize (c));
     case 2: return_trace (u.format2.sanitize (c));
     case 3: return_trace (u.format3.sanitize (c));
-    default:return_trace (true);
+    default:return_trace (false);
     }
   }
 
@@ -149,16 +142,16 @@ struct BaseCoord {
 
 struct FeatMinMaxRecord {
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
-  { 
-    if (unlikely(minCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
-    return (this+minCoord).get_value(font, dir); 
+  inline SHORT get_min_value (void) const
+  {
+    if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+      return (this+minCoord).get_coord();
   }
 
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
-  { 
-    if (unlikely(maxCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
-    return (this+maxCoord).get_value(font, dir); 
+  inline SHORT get_max_value (void) const
+  {
+    if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+      return (this+maxCoord).get_coord();
   }
 
   inline Tag get_tag () const
@@ -184,41 +177,39 @@ struct FeatMinMaxRecord {
 
 struct MinMax {
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
-  { 
-    if (unlikely(minCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
-    return (this+minCoord).get_value(font, dir);
-  }
-
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
-  { 
-    if (unlikely(maxCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
-    return (this+maxCoord).get_value(font, dir);
+  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+  {
+    Tag tag;
+    int cmp;
+    // taking advantage of alphabetical order
+    for (unsigned int i = 0; i < featMinMaxCount; i++) {
+      tag = featMinMaxRecords[i].get_tag();
+      cmp = tag.cmp(featureTableTag);
+      if (cmp == 0) return i;
+      if (cmp > 0)  return NOT_INDEXED;
+    }
+    return NOT_INDEXED;
   }
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  inline SHORT get_min_value (unsigned int featureTableTagIndex) const
   {
-    for (unsigned int i = 0; i < featMinMaxCount; i++) 
-    {
-      if (featMinMaxRecords[i].get_tag() == featureTableTag)
-        return featMinMaxRecords[i].get_min_value(font, dir);
-      // we could take advantage of alphabetical order by comparing Tags, not currently possible
-      //if (featMinMaxRecords[i].get_tag() > featureTableTag)
-      //  break;
+    if (featureTableTagIndex == NOT_INDEXED) {
+      if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+      return (this+minCoord).get_coord();
     }
-    return get_min_value (font, dir);
+    if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD;
+    return featMinMaxRecords[featureTableTagIndex].get_min_value();
   }
 
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  inline SHORT get_max_value (unsigned int featureTableTagIndex) const
   {
-    for (unsigned int i = 0; i < featMinMaxCount; i++) 
-    {
-      if (featMinMaxRecords[i].get_tag() == featureTableTag)
-        return featMinMaxRecords[i].get_max_value(font, dir);
-      // we could use alphabetical order to break here
+    if (featureTableTagIndex == NOT_INDEXED) {
+      if (minCoord == Null(OffsetTo<BaseCoord>)) return NO_COORD;
+      return (this+maxCoord).get_coord();
     }
-    return get_min_value (font, dir);
-  }  
+    if (unlikely(featureTableTagIndex >= featMinMaxCount)) return NO_COORD;
+    return featMinMaxRecords[featureTableTagIndex].get_max_value();
+  }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -234,7 +225,7 @@ struct MinMax {
   OffsetTo<BaseCoord>       minCoord;
   OffsetTo<BaseCoord>       maxCoord;
   USHORT                    featMinMaxCount;
-  ArrayOf<FeatMinMaxRecord> featMinMaxRecords; /* All FeatMinMaxRecords are listed alphabetically */
+  ArrayOf<FeatMinMaxRecord> featMinMaxRecords;
 
   public:
   DEFINE_SIZE_ARRAY (8, featMinMaxRecords);
@@ -246,17 +237,14 @@ struct BaseLangSysRecord {
   inline Tag get_tag(void) const
   { return baseLangSysTag; }
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
-  { return (this+minMax).get_min_value(font, dir); }
-
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
-  { return (this+minMax).get_max_value(font, dir); }
+  inline unsigned int get_feature_tag_index (Tag featureTableTag) const
+  { (this+minMax).get_feature_tag_index(featureTableTag); }
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
-  { return (this+minMax).get_min_value(font, dir, featureTableTag); }
+  inline SHORT get_min_value (unsigned int featureTableTagIndex) const
+  { (this+minMax).get_min_value(featureTableTagIndex); }
 
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
-  { return (this+minMax).get_max_value(font, dir, featureTableTag); }  
+  inline SHORT get_max_value (unsigned int featureTableTagIndex) const
+  { (this+minMax).get_max_value(featureTableTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
@@ -277,15 +265,25 @@ struct BaseLangSysRecord {
 
 struct BaseValues {
 
+  inline const unsigned int get_default_base_tag_index (void) const
+  { return defaultIndex; }
+
+  inline SHORT get_base_coord (unsigned int baselineTagIndex) const
+  {
+    if (unlikely(baselineTagIndex >= baseCoordCount)) return NO_COORD;
+    return (this+baseCoords[baselineTagIndex]).get_coord();
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+      defaultIndex <= baseCoordCount &&
       baseCoords.sanitize (c, this));
   }
 
   protected:
-  USHORT                    defaultIndex;
+  Index                     defaultIndex;
   USHORT                    baseCoordCount;
   OffsetArrayOf<BaseCoord>  baseCoords;
 
@@ -296,62 +294,56 @@ struct BaseValues {
 
 struct BaseScript {
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const 
+  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
   {
-    if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
-    return (this+defaultMinMax).get_min_value(font, dir);
-  }
-
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const 
-  {
-    if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
-    return (this+defaultMinMax).get_max_value(font, dir);
-  }
-
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const
-  { 
-    for (unsigned int i = 0; i < baseLangSysCount; i++) 
-    {
-      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
-        return baseLangSysRecords[i].get_min_value(font, dir);
-      // we could use alphabetical order to break here
+    Tag tag;
+    int cmp;
+    for (unsigned int i = 0; i < baseLangSysCount; i++) {
+      tag = baseLangSysRecords[i].get_tag();
+      // taking advantage of alphabetical order
+      cmp = tag.cmp(baseLangSysTag);
+      if (cmp == 0) return i;
+      if (cmp > 0)  return NOT_INDEXED;
     }
-    return get_min_value (font, dir);
+    return NOT_INDEXED;
   }
 
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const
+  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    for (unsigned int i = 0; i < baseLangSysCount; i++) 
-    {
-      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
-        return baseLangSysRecords[i].get_max_value(font, dir);
-      // we could use alphabetical order to break here
+    if (baseLangSysIndex == NOT_INDEXED) {
+      if (unlikely(defaultMinMax)) return NOT_INDEXED;
+      return (this+defaultMinMax).get_feature_tag_index(featureTableTag);
     }
-    return get_max_value (font, dir);
+    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NOT_INDEXED;
+    return baseLangSysRecords[baseLangSysIndex].get_feature_tag_index(featureTableTag);
   }
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const
+  inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    for (unsigned int i = 0; i < baseLangSysCount; i++) 
-    {
-      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
-        return baseLangSysRecords[i].get_min_value(font, dir, featureTableTag);
-      // we could use alphabetical order to break here
+    if (baseLangSysIndex == NOT_INDEXED) {
+      if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
     }
-    return get_min_value (font, dir);
+    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD;
+    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex); 
   }
 
-  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const
+  inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
   {
-    for (unsigned int i = 0; i < baseLangSysCount; i++)
-    {
-      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
-        return baseLangSysRecords[i].get_max_value(font, dir);
-      // we could use alphabetical order to break here
+    if (baseLangSysIndex == NOT_INDEXED) {
+      if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+      return (this+defaultMinMax).get_min_value(featureTableTagIndex);
     }
-    return get_max_value (font, dir);
+    if (unlikely(baseLangSysIndex >= baseLangSysCount)) return NO_COORD;
+    return baseLangSysRecords[baseLangSysIndex].get_max_value(featureTableTagIndex);
   }
 
+  inline unsigned int get_default_base_tag_index (void) const
+  { return (this+baseValues).get_default_base_tag_index(); }
+
+  inline SHORT get_base_coord (unsigned int baselineTagIndex) const
+  { return (this+baseValues).get_base_coord(baselineTagIndex); }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -374,20 +366,32 @@ struct BaseScript {
 
 struct BaseScriptRecord {
 
-  inline const BaseScript *get_baseScript (void) const
-  {
-    return &(this+baseScript);
-  }
-
   inline bool get_tag (void) const
-  {
-    return baseScriptTag;
-  }
+  { return baseScriptTag; }
+
+  inline unsigned int get_default_base_tag_index(void) const
+  { return (this+baseScript).get_default_base_tag_index(); }
+
+  inline SHORT get_base_coord(unsigned int baselineTagIndex) const
+  { return (this+baseScript).get_base_coord(baselineTagIndex); }
+
+  inline unsigned int get_lang_tag_index (Tag baseLangSysTag) const
+  { return (this+baseScript).get_lang_tag_index(baseLangSysTag); }
+
+  inline unsigned int get_feature_tag_index (unsigned int baseLangSysIndex, Tag featureTableTag) const
+  { return (this+baseScript).get_feature_tag_index(baseLangSysIndex, featureTableTag); }
+
+  inline SHORT get_max_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return (this+baseScript).get_max_value(baseLangSysIndex, featureTableTagIndex); }
+
+  inline SHORT get_min_value (unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  { return (this+baseScript).get_min_value(baseLangSysIndex, featureTableTagIndex); }
 
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+      baseScript != Null(OffsetTo<BaseScript>) &&
       baseScript.sanitize (c, base));
   }
 
@@ -401,20 +405,48 @@ struct BaseScriptRecord {
 
 struct BaseScriptList {
 
-  inline const BaseScript *get_baseScript_from_tag (Tag baseScriptTag) const
+  inline unsigned int get_base_script_index (Tag baseScriptTag) const
   {
     for (unsigned int i = 0; i < baseScriptCount; i++)
       if (baseScriptRecords[i].get_tag() == baseScriptTag)
-        return baseScriptRecords[i].get_baseScript();
-      // we could use alphabetical order to break here
-    return NULL;
+        return i;
+    return NOT_INDEXED;
+  }
+
+  inline unsigned int get_default_base_tag_index (unsigned int baseScriptIndex) const
+  { 
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+    return baseScriptRecords[baseScriptIndex].get_default_base_tag_index();
+  }
+
+  inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  {
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+    return baseScriptRecords[baseScriptIndex].get_base_coord(baselineTagIndex);
+  }
+
+  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  {
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+    return baseScriptRecords[baseScriptIndex].get_lang_tag_index(baseLangSysTag);
   }
 
-  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseScriptTag) const 
+  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
   {
-    const BaseScript *baseScript = get_baseScript_from_tag (baseScriptTag);
-    if (baseScript == NULL) return NO_COORD;
-    return baseScript->get_min_value(font, dir);
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NOT_INDEXED;
+    return baseScriptRecords[baseScriptIndex].get_feature_tag_index(baseLangSysIndex, featureTableTag);
+  }
+
+  inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+    return baseScriptRecords[baseScriptIndex].get_max_value(baseLangSysIndex, featureTableTagIndex);
+  }
+
+  inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(baseScriptIndex >= baseScriptCount)) return NO_COORD;
+    return baseScriptRecords[baseScriptIndex].get_min_value(baseLangSysIndex, featureTableTagIndex);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -436,12 +468,12 @@ struct BaseScriptList {
 struct BaseTagList
 {
 
-  inline bool hasTag(Tag tag) const
+  inline unsigned int get_tag_index(Tag baselineTag) const
   {
     for (unsigned int i = 0; i < baseTagCount; i++)
-      if (baselineTags[i] == tag)
-        return true;
-    return false;
+      if (baselineTags[i] == baselineTag)
+        return i;
+    return NOT_INDEXED;
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -452,7 +484,7 @@ struct BaseTagList
 
   protected:
   USHORT        baseTagCount;
-  ArrayOf<Tag>  baselineTags; // must be in alphabetical order
+  SortedArrayOf<Tag>  baselineTags;
 
   public:
   DEFINE_SIZE_ARRAY (4, baselineTags);
@@ -461,10 +493,46 @@ struct BaseTagList
 struct Axis
 {
 
-  inline bool hasTag(Tag tag) const
+  inline unsigned int get_base_tag_index(Tag baselineTag) const
+  {
+    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return NOT_INDEXED;
+    return (this+baseTagList).get_tag_index(baselineTag);
+  }
+
+  inline unsigned int get_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  { 
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+    return (this+baseScriptList).get_default_base_tag_index(baseScriptIndex);
+  }
+
+  inline SHORT get_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
   {
-    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return false;
-    return (this+baseTagList).hasTag(tag);
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+    return (this+baseScriptList).get_base_coord(baseScriptIndex, baselineTagIndex);
+  }
+
+  inline unsigned int get_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  {
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+    return (this+baseScriptList).get_lang_tag_index(baseScriptIndex, baseLangSysTag);
+  }
+
+  inline unsigned int get_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  {
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NOT_INDEXED;
+    return (this+baseScriptList).get_feature_tag_index(baseScriptIndex, baseLangSysIndex, featureTableTag);
+  }
+
+  inline SHORT get_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+    return (this+baseScriptList).get_max_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+  }
+
+  inline SHORT get_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(baseScriptList == Null(OffsetTo<BaseScriptList>))) return NO_COORD;
+    return (this+baseScriptList).get_min_value(baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
   }
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -508,6 +576,104 @@ struct BASEFormat1_1
 struct BASEFormat1_0
 {
 
+  inline bool has_vert_axis(void)
+  { return vertAxis != Null(OffsetTo<Axis>); }
+
+  inline bool has_horiz_axis(void)
+  { return horizAxis != Null(OffsetTo<Axis>); }
+
+  // horizontal axis base coords:
+
+  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+horizAxis).get_base_tag_index(baselineTag);
+  }
+
+  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  { 
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+horizAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+  }
+
+  inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+    return (this+horizAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+  }
+
+  // vertical axis base coords:
+
+  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+  {
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+vertAxis).get_base_tag_index(baselineTag);
+  }
+
+  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  { 
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+vertAxis).get_default_base_tag_index_for_script_index(baseScriptIndex);
+  }
+
+  inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  {
+    if (vertAxis == Null(OffsetTo<Axis>)) return NO_COORD;
+    return (this+vertAxis).get_base_coord(baseScriptIndex, baselineTagIndex);
+  }
+
+  // horizontal axis min/max coords:
+
+  inline unsigned int get_horiz_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+horizAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+  }
+
+  inline unsigned int get_horiz_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+horizAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+  }
+
+  inline SHORT get_horiz_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+    return (this+horizAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+  }
+
+  inline SHORT get_horiz_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(horizAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+    return (this+horizAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+  }
+
+    // vertical axis min/max coords:
+
+  inline unsigned int get_vert_lang_tag_index (unsigned int baseScriptIndex, Tag baseLangSysTag) const
+  {
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+vertAxis).get_lang_tag_index (baseScriptIndex, baseLangSysTag);
+  }
+
+  inline unsigned int get_vert_feature_tag_index (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, Tag featureTableTag) const
+  {
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NOT_INDEXED;
+    return (this+vertAxis).get_feature_tag_index (baseScriptIndex, baseLangSysIndex, featureTableTag);
+  }
+
+  inline SHORT get_vert_max_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+    return (this+vertAxis).get_max_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+  }
+
+  inline SHORT get_vert_min_value (unsigned int baseScriptIndex, unsigned int baseLangSysIndex, unsigned int featureTableTagIndex) const
+  {
+    if (unlikely(vertAxis == Null(OffsetTo<Axis>))) return NO_COORD;
+    return (this+vertAxis).get_min_value (baseScriptIndex, baseLangSysIndex, featureTableTagIndex);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -529,6 +695,30 @@ struct BASE
 {
   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
 
+  inline bool has_vert_axis(void)
+  { return u.format1_0.has_vert_axis(); }
+
+  inline bool has_horiz_axis(void)
+  { return u.format1_0.has_horiz_axis(); }
+
+  inline unsigned int get_horiz_base_tag_index(Tag baselineTag) const
+  { return u.format1_0.get_horiz_base_tag_index(baselineTag); }
+
+  inline unsigned int get_horiz_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  { return u.format1_0.get_horiz_default_base_tag_index_for_script_index(baseScriptIndex); }
+
+  inline SHORT get_horiz_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  { return u.format1_0.get_horiz_base_coord(baseScriptIndex, baselineTagIndex); }
+
+  inline unsigned int get_vert_base_tag_index(Tag baselineTag) const
+  { return u.format1_0.get_vert_base_tag_index(baselineTag); }
+
+  inline unsigned int get_vert_default_base_tag_index_for_script_index (unsigned int baseScriptIndex) const
+  { return u.format1_0.get_vert_default_base_tag_index_for_script_index(baseScriptIndex); }
+
+  inline SHORT get_vert_base_coord(unsigned int baseScriptIndex, unsigned int baselineTagIndex) const
+  { return u.format1_0.get_vert_base_coord(baseScriptIndex, baselineTagIndex); }
+
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -537,7 +727,7 @@ struct BASE
     switch (u.version.minor) {
     case 0: return_trace (u.format1_0.sanitize (c));
     case 1: return_trace (u.format1_1.sanitize (c));
-    default:return_trace (true);
+    default:return_trace (false);
     }
   }
 
commit d34e35b47457e757781b1769a1fbaf107ec6e32f
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 25 20:41:05 2017 +0100

    BASE: WIP: more access functions

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 75b3f2e8..c4d9ad14 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -43,12 +43,17 @@
 
 namespace OT {
 
+#define NO_COORD -32767
+
 /*
  * BASE -- The BASE Table
  */
 
 struct BaseCoordFormat1 {
 
+  inline SHORT get_coord () const
+  { return coordinate; }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -65,6 +70,9 @@ struct BaseCoordFormat1 {
 
 struct BaseCoordFormat2 {
 
+  inline SHORT get_coord () const
+  { return coordinate; }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -83,6 +91,9 @@ struct BaseCoordFormat2 {
 
 struct BaseCoordFormat3 {
 
+  inline SHORT get_coord (void ) const
+  { return coordinate; }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -100,6 +111,18 @@ struct BaseCoordFormat3 {
 
 struct BaseCoord {
 
+  inline hb_position_t get_value (hb_font_t *font, hb_direction_t dir) const
+  { 
+    SHORT coord;
+    switch (u.baseCoordFormat) {
+    case 1: coord = u.format1.get_coord();
+    case 2: coord = u.format2.get_coord();
+    case 3: coord = u.format3.get_coord();
+    default: return 0;
+    }
+    return font->em_scale (coord, dir); 
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -126,6 +149,21 @@ struct BaseCoord {
 
 struct FeatMinMaxRecord {
 
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
+  { 
+    if (unlikely(minCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
+    return (this+minCoord).get_value(font, dir); 
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
+  { 
+    if (unlikely(maxCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
+    return (this+maxCoord).get_value(font, dir); 
+  }
+
+  inline Tag get_tag () const
+  { return featureTableTag; }
+
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -146,6 +184,42 @@ struct FeatMinMaxRecord {
 
 struct MinMax {
 
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
+  { 
+    if (unlikely(minCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
+    return (this+minCoord).get_value(font, dir);
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
+  { 
+    if (unlikely(maxCoord == Null(OffsetTo<BaseCoord>))) return NO_COORD;
+    return (this+maxCoord).get_value(font, dir);
+  }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  {
+    for (unsigned int i = 0; i < featMinMaxCount; i++) 
+    {
+      if (featMinMaxRecords[i].get_tag() == featureTableTag)
+        return featMinMaxRecords[i].get_min_value(font, dir);
+      // we could take advantage of alphabetical order by comparing Tags, not currently possible
+      //if (featMinMaxRecords[i].get_tag() > featureTableTag)
+      //  break;
+    }
+    return get_min_value (font, dir);
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  {
+    for (unsigned int i = 0; i < featMinMaxCount; i++) 
+    {
+      if (featMinMaxRecords[i].get_tag() == featureTableTag)
+        return featMinMaxRecords[i].get_max_value(font, dir);
+      // we could use alphabetical order to break here
+    }
+    return get_min_value (font, dir);
+  }  
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -153,13 +227,14 @@ struct MinMax {
       minCoord.sanitize (c, this) &&
       maxCoord.sanitize (c, this) &&
       featMinMaxRecords.sanitize (c, this));
+    // TODO: test alphabetical order?
   }
 
   protected:
   OffsetTo<BaseCoord>       minCoord;
   OffsetTo<BaseCoord>       maxCoord;
   USHORT                    featMinMaxCount;
-  ArrayOf<FeatMinMaxRecord> featMinMaxRecords;
+  ArrayOf<FeatMinMaxRecord> featMinMaxRecords; /* All FeatMinMaxRecords are listed alphabetically */
 
   public:
   DEFINE_SIZE_ARRAY (8, featMinMaxRecords);
@@ -168,16 +243,32 @@ struct MinMax {
 
 struct BaseLangSysRecord {
 
+  inline Tag get_tag(void) const
+  { return baseLangSysTag; }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const
+  { return (this+minMax).get_min_value(font, dir); }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const
+  { return (this+minMax).get_max_value(font, dir); }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  { return (this+minMax).get_min_value(font, dir, featureTableTag); }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag featureTableTag) const
+  { return (this+minMax).get_max_value(font, dir, featureTableTag); }  
+
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
+      minMax != Null(OffsetTo<MinMax>) &&
       minMax.sanitize (c, base));
   }
 
   protected:
   Tag               baseLangSysTag;
-  OffsetTo<MinMax>  minMax;
+  OffsetTo<MinMax>  minMax; // not supposed to be NULL
 
   public:
   DEFINE_SIZE_STATIC (6); 
@@ -205,6 +296,62 @@ struct BaseValues {
 
 struct BaseScript {
 
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir) const 
+  {
+    if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+    return (this+defaultMinMax).get_min_value(font, dir);
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir) const 
+  {
+    if (unlikely(defaultMinMax == Null(OffsetTo<MinMax>))) return NO_COORD;
+    return (this+defaultMinMax).get_max_value(font, dir);
+  }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const
+  { 
+    for (unsigned int i = 0; i < baseLangSysCount; i++) 
+    {
+      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
+        return baseLangSysRecords[i].get_min_value(font, dir);
+      // we could use alphabetical order to break here
+    }
+    return get_min_value (font, dir);
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag) const
+  {
+    for (unsigned int i = 0; i < baseLangSysCount; i++) 
+    {
+      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
+        return baseLangSysRecords[i].get_max_value(font, dir);
+      // we could use alphabetical order to break here
+    }
+    return get_max_value (font, dir);
+  }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const
+  {
+    for (unsigned int i = 0; i < baseLangSysCount; i++) 
+    {
+      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
+        return baseLangSysRecords[i].get_min_value(font, dir, featureTableTag);
+      // we could use alphabetical order to break here
+    }
+    return get_min_value (font, dir);
+  }
+
+  inline hb_position_t get_max_value (hb_font_t *font, hb_direction_t dir, Tag baseLangSysTag, Tag featureTableTag) const
+  {
+    for (unsigned int i = 0; i < baseLangSysCount; i++)
+    {
+      if (baseLangSysRecords[i].get_tag() == baseLangSysTag)
+        return baseLangSysRecords[i].get_max_value(font, dir);
+      // we could use alphabetical order to break here
+    }
+    return get_max_value (font, dir);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -227,6 +374,16 @@ struct BaseScript {
 
 struct BaseScriptRecord {
 
+  inline const BaseScript *get_baseScript (void) const
+  {
+    return &(this+baseScript);
+  }
+
+  inline bool get_tag (void) const
+  {
+    return baseScriptTag;
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
@@ -244,6 +401,22 @@ struct BaseScriptRecord {
 
 struct BaseScriptList {
 
+  inline const BaseScript *get_baseScript_from_tag (Tag baseScriptTag) const
+  {
+    for (unsigned int i = 0; i < baseScriptCount; i++)
+      if (baseScriptRecords[i].get_tag() == baseScriptTag)
+        return baseScriptRecords[i].get_baseScript();
+      // we could use alphabetical order to break here
+    return NULL;
+  }
+
+  inline hb_position_t get_min_value (hb_font_t *font, hb_direction_t dir, Tag baseScriptTag) const 
+  {
+    const BaseScript *baseScript = get_baseScript_from_tag (baseScriptTag);
+    if (baseScript == NULL) return NO_COORD;
+    return baseScript->get_min_value(font, dir);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -260,35 +433,26 @@ struct BaseScriptList {
   
 };
 
-struct BaselineTag {
+struct BaseTagList
+{
 
-  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  inline bool hasTag(Tag tag) const
   {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this));
+    for (unsigned int i = 0; i < baseTagCount; i++)
+      if (baselineTags[i] == tag)
+        return true;
+    return false;
   }
 
-  protected:
-  Tag   tag;
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-
-};
-
-struct BaseTagList
-{
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baselineTags.sanitize (c, this));
+    return_trace (c->check_struct (this));
   }
 
   protected:
-  USHORT                baseTagCount;
-  ArrayOf<BaselineTag>  baselineTags;
+  USHORT        baseTagCount;
+  ArrayOf<Tag>  baselineTags; // must be in alphabetical order
 
   public:
   DEFINE_SIZE_ARRAY (4, baselineTags);
@@ -297,6 +461,12 @@ struct BaseTagList
 struct Axis
 {
 
+  inline bool hasTag(Tag tag) const
+  {
+    if (unlikely(baseTagList == Null(OffsetTo<BaseTagList>))) return false;
+    return (this+baseTagList).hasTag(tag);
+  }
+
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
commit bd15567ed6a3667e6f8332b7374aece6a6f2361b
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 25 17:08:01 2017 +0100

    BASE: align member's names

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index f811c4ab..75b3f2e8 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -57,7 +57,7 @@ struct BaseCoordFormat1 {
 
   protected:
   USHORT    baseCoordFormat;
-  SHORT   coordinate;
+  SHORT     coordinate;
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -73,7 +73,7 @@ struct BaseCoordFormat2 {
 
   protected:
   USHORT    baseCoordFormat;
-  SHORT   coordinate;
+  SHORT     coordinate;
   USHORT    referenceGlyph;
   USHORT    baseCoordPoint;
 
@@ -90,9 +90,9 @@ struct BaseCoordFormat3 {
   }
 
   protected:
-  USHORT    baseCoordFormat;
-  SHORT   coordinate;
-  OffsetTo<Device>    deviceTable;
+  USHORT           baseCoordFormat;
+  SHORT            coordinate;
+  OffsetTo<Device> deviceTable;
 
   public:
   DEFINE_SIZE_STATIC (6);
@@ -114,7 +114,7 @@ struct BaseCoord {
 
   protected:
   union {
-    USHORT    baseCoordFormat;
+    USHORT            baseCoordFormat;
     BaseCoordFormat1  format1;
     BaseCoordFormat2  format2;
     BaseCoordFormat3  format3;
@@ -135,7 +135,7 @@ struct FeatMinMaxRecord {
   }
 
   protected:
-  Tag featureTableTag;
+  Tag                   featureTableTag;
   OffsetTo<BaseCoord>   minCoord;
   OffsetTo<BaseCoord>   maxCoord;
 
@@ -156,9 +156,9 @@ struct MinMax {
   }
 
   protected:
-  OffsetTo<BaseCoord>   minCoord;
-  OffsetTo<BaseCoord>   maxCoord;
-  USHORT    featMinMaxCount;
+  OffsetTo<BaseCoord>       minCoord;
+  OffsetTo<BaseCoord>       maxCoord;
+  USHORT                    featMinMaxCount;
   ArrayOf<FeatMinMaxRecord> featMinMaxRecords;
 
   public:
@@ -176,8 +176,8 @@ struct BaseLangSysRecord {
   }
 
   protected:
-  Tag baseLangSysTag;
-  OffsetTo<MinMax> minMax;
+  Tag               baseLangSysTag;
+  OffsetTo<MinMax>  minMax;
 
   public:
   DEFINE_SIZE_STATIC (6); 
@@ -194,9 +194,9 @@ struct BaseValues {
   }
 
   protected:
-  USHORT    defaultIndex;
-  USHORT    baseCoordCount;
-  OffsetArrayOf<BaseCoord> baseCoords;
+  USHORT                    defaultIndex;
+  USHORT                    baseCoordCount;
+  OffsetArrayOf<BaseCoord>  baseCoords;
 
   public:
   DEFINE_SIZE_ARRAY (6, baseCoords);
@@ -215,10 +215,10 @@ struct BaseScript {
   }
 
   protected:
-  OffsetTo<BaseValues>  baseValues;
-  OffsetTo<MinMax>  defaultMinMax;
-  USHORT    baseLangSysCount;
-  ArrayOf<BaseLangSysRecord> baseLangSysRecords;
+  OffsetTo<BaseValues>        baseValues;
+  OffsetTo<MinMax>            defaultMinMax;
+  USHORT                      baseLangSysCount;
+  ArrayOf<BaseLangSysRecord>  baseLangSysRecords;
 
   public:
     DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
@@ -235,8 +235,8 @@ struct BaseScriptRecord {
   }
 
   protected:
-  Tag baseScriptTag;
-  OffsetTo<BaseScript> baseScript;
+  Tag                   baseScriptTag;
+  OffsetTo<BaseScript>  baseScript;
 
   public:
     DEFINE_SIZE_STATIC (6);
@@ -252,7 +252,7 @@ struct BaseScriptList {
   }
 
   protected:
-  USHORT    baseScriptCount;
+  USHORT                    baseScriptCount;
   ArrayOf<BaseScriptRecord> baseScriptRecords;
 
   public:
@@ -287,8 +287,8 @@ struct BaseTagList
   }
 
   protected:
-  USHORT    baseTagCount;
-  ArrayOf<BaselineTag> baselineTags;
+  USHORT                baseTagCount;
+  ArrayOf<BaselineTag>  baselineTags;
 
   public:
   DEFINE_SIZE_ARRAY (4, baselineTags);
@@ -306,8 +306,8 @@ struct Axis
   }
 
   protected:
-  OffsetTo<BaseTagList> baseTagList;
-  OffsetTo<BaseScriptList> baseScriptList;
+  OffsetTo<BaseTagList>     baseTagList;
+  OffsetTo<BaseScriptList>  baseScriptList;
 
   public:
   DEFINE_SIZE_STATIC (4);
@@ -326,9 +326,9 @@ struct BASEFormat1_1
   }
 
   protected:
-  FixedVersion<>version;
-  OffsetTo<Axis> horizAxis;
-  OffsetTo<Axis> vertAxis;
+  FixedVersion<>            version;
+  OffsetTo<Axis>            horizAxis;
+  OffsetTo<Axis>            vertAxis;
   LOffsetTo<VariationStore> itemVarStore;
 
   public:
@@ -347,9 +347,9 @@ struct BASEFormat1_0
   }
 
   protected:
-  FixedVersion<>version;
-  OffsetTo<Axis> horizAxis;
-  OffsetTo<Axis> vertAxis;
+  FixedVersion<>  version;
+  OffsetTo<Axis>  horizAxis;
+  OffsetTo<Axis>  vertAxis;
 
   public:
   DEFINE_SIZE_STATIC (8);
@@ -373,9 +373,9 @@ struct BASE
 
   protected:
   union {
-    FixedVersion<>version;    /* Version of the BASE table: 1.0 or 1.1 */
-    BASEFormat1_0  format1_0;
-    BASEFormat1_1  format1_1;
+    FixedVersion<>  version;    /* Version of the BASE table: 1.0 or 1.1 */
+    BASEFormat1_0   format1_0;
+    BASEFormat1_1   format1_1;
   } u;
 
   public:
commit 499b4bef2a5b6d49374ab4977509d1fbf7bd6038
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 25 16:48:22 2017 +0100

    BASE: more consistent naming (with spec and Harfbuzz code base)

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 059c8f71..f811c4ab 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -144,7 +144,7 @@ struct FeatMinMaxRecord {
 
 };
 
-struct MinMaxTable {
+struct MinMax {
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -152,17 +152,17 @@ struct MinMaxTable {
     return_trace (c->check_struct (this) &&
       minCoord.sanitize (c, this) &&
       maxCoord.sanitize (c, this) &&
-      featMinMaxRecordTable.sanitize (c, this));
+      featMinMaxRecords.sanitize (c, this));
   }
 
   protected:
   OffsetTo<BaseCoord>   minCoord;
   OffsetTo<BaseCoord>   maxCoord;
   USHORT    featMinMaxCount;
-  ArrayOf<FeatMinMaxRecord> featMinMaxRecordTable;
+  ArrayOf<FeatMinMaxRecord> featMinMaxRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (8, featMinMaxRecordTable);
+  DEFINE_SIZE_ARRAY (8, featMinMaxRecords);
 
 };
 
@@ -177,33 +177,33 @@ struct BaseLangSysRecord {
 
   protected:
   Tag baseLangSysTag;
-  OffsetTo<MinMaxTable> minMax;
+  OffsetTo<MinMax> minMax;
 
   public:
   DEFINE_SIZE_STATIC (6); 
 
 };
 
-struct BaseValuesTable {
+struct BaseValues {
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseCoordTable.sanitize (c, this));
+      baseCoords.sanitize (c, this));
   }
 
   protected:
   USHORT    defaultIndex;
   USHORT    baseCoordCount;
-  OffsetArrayOf<BaseCoord> baseCoordTable;
+  OffsetArrayOf<BaseCoord> baseCoords;
 
   public:
-  DEFINE_SIZE_ARRAY (6, baseCoordTable);
+  DEFINE_SIZE_ARRAY (6, baseCoords);
 
 };
 
-struct BaseScriptTable {
+struct BaseScript {
 
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -211,17 +211,17 @@ struct BaseScriptTable {
     return_trace (c->check_struct (this) &&
       baseValues.sanitize (c, this) &&
       defaultMinMax.sanitize (c, this) &&
-      baseLangSysRecordTable.sanitize (c, this));
+      baseLangSysRecords.sanitize (c, this));
   }
 
   protected:
-  OffsetTo<BaseValuesTable>  baseValues;
-  OffsetTo<MinMaxTable>  defaultMinMax;
+  OffsetTo<BaseValues>  baseValues;
+  OffsetTo<MinMax>  defaultMinMax;
   USHORT    baseLangSysCount;
-  ArrayOf<BaseLangSysRecord> baseLangSysRecordTable;
+  ArrayOf<BaseLangSysRecord> baseLangSysRecords;
 
   public:
-    DEFINE_SIZE_ARRAY (8, baseLangSysRecordTable);
+    DEFINE_SIZE_ARRAY (8, baseLangSysRecords);
 };
 
 
@@ -236,7 +236,7 @@ struct BaseScriptRecord {
 
   protected:
   Tag baseScriptTag;
-  OffsetTo<BaseScriptTable> baseScript;
+  OffsetTo<BaseScript> baseScript;
 
   public:
     DEFINE_SIZE_STATIC (6);
@@ -248,15 +248,15 @@ struct BaseScriptList {
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseScriptRecordTable.sanitize (c, this));
+      baseScriptRecords.sanitize (c, this));
   }
 
   protected:
   USHORT    baseScriptCount;
-  ArrayOf<BaseScriptRecord> baseScriptRecordTable;
+  ArrayOf<BaseScriptRecord> baseScriptRecords;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseScriptRecordTable);
+  DEFINE_SIZE_ARRAY (4, baseScriptRecords);
   
 };
 
@@ -283,15 +283,15 @@ struct BaseTagList
   {
     TRACE_SANITIZE (this);
     return_trace (c->check_struct (this) &&
-      baseTagListTable.sanitize (c, this));
+      baselineTags.sanitize (c, this));
   }
 
   protected:
   USHORT    baseTagCount;
-  ArrayOf<BaselineTag> baseTagListTable;
+  ArrayOf<BaselineTag> baselineTags;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseTagListTable);
+  DEFINE_SIZE_ARRAY (4, baselineTags);
 };
 
 struct Axis
commit a0bdd546c584eb7c7ea3ca7e19a178723e6fe77f
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 25 16:34:58 2017 +0100

    factorize horiz+vertAxis

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 691b9db1..059c8f71 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -100,7 +100,6 @@ struct BaseCoordFormat3 {
 
 struct BaseCoord {
 
-
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -295,7 +294,7 @@ struct BaseTagList
   DEFINE_SIZE_ARRAY (4, baseTagListTable);
 };
 
-struct VertAxis
+struct Axis
 {
 
   inline bool sanitize (hb_sanitize_context_t *c) const
@@ -314,26 +313,6 @@ struct VertAxis
   DEFINE_SIZE_STATIC (4);
 };
 
-struct HorizAxis
-{
-
-  inline bool sanitize (hb_sanitize_context_t *c) const
-  {
-    TRACE_SANITIZE (this);
-    return_trace (c->check_struct (this) &&
-      baseTagList.sanitize (c, this) &&
-      baseScriptList.sanitize (c, this));
-  }
-
-  protected:
-  OffsetTo<HorizAxis> baseTagList;
-  OffsetTo<VertAxis> baseScriptList;
-
-  public:
-  DEFINE_SIZE_STATIC (4);
-};
-
-
 struct BASEFormat1_1
 {
 
@@ -348,8 +327,8 @@ struct BASEFormat1_1
 
   protected:
   FixedVersion<>version;
-  OffsetTo<HorizAxis> horizAxis;
-  OffsetTo<VertAxis> vertAxis;
+  OffsetTo<Axis> horizAxis;
+  OffsetTo<Axis> vertAxis;
   LOffsetTo<VariationStore> itemVarStore;
 
   public:
@@ -369,8 +348,8 @@ struct BASEFormat1_0
 
   protected:
   FixedVersion<>version;
-  OffsetTo<HorizAxis> horizAxis;
-  OffsetTo<VertAxis> vertAxis;
+  OffsetTo<Axis> horizAxis;
+  OffsetTo<Axis> vertAxis;
 
   public:
   DEFINE_SIZE_STATIC (8);
commit 1d30c6d935535743c73b2d18abcc6ae86a1cfc5b
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 25 16:19:35 2017 +0100

    BASE: sanitize

diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index b3c0927b..691b9db1 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -48,6 +48,13 @@ namespace OT {
  */
 
 struct BaseCoordFormat1 {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
   protected:
   USHORT    baseCoordFormat;
   SHORT   coordinate;
@@ -57,6 +64,13 @@ struct BaseCoordFormat1 {
 };
 
 struct BaseCoordFormat2 {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
   protected:
   USHORT    baseCoordFormat;
   SHORT   coordinate;
@@ -68,6 +82,13 @@ struct BaseCoordFormat2 {
 };
 
 struct BaseCoordFormat3 {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) && deviceTable.sanitize (c, this));
+  }
+
   protected:
   USHORT    baseCoordFormat;
   SHORT   coordinate;
@@ -78,6 +99,20 @@ struct BaseCoordFormat3 {
 };
 
 struct BaseCoord {
+
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    if (!u.baseCoordFormat.sanitize (c)) return_trace (false);
+    switch (u.baseCoordFormat) {
+    case 1: return_trace (u.format1.sanitize (c));
+    case 2: return_trace (u.format2.sanitize (c));
+    case 3: return_trace (u.format3.sanitize (c));
+    default:return_trace (true);
+    }
+  }
+
   protected:
   union {
     USHORT    baseCoordFormat;
@@ -91,6 +126,15 @@ struct BaseCoord {
 };
 
 struct FeatMinMaxRecord {
+
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      minCoord.sanitize (c, base) &&
+      maxCoord.sanitize (c, base));
+  }
+
   protected:
   Tag featureTableTag;
   OffsetTo<BaseCoord>   minCoord;
@@ -102,6 +146,16 @@ struct FeatMinMaxRecord {
 };
 
 struct MinMaxTable {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      minCoord.sanitize (c, this) &&
+      maxCoord.sanitize (c, this) &&
+      featMinMaxRecordTable.sanitize (c, this));
+  }
+
   protected:
   OffsetTo<BaseCoord>   minCoord;
   OffsetTo<BaseCoord>   maxCoord;
@@ -114,6 +168,14 @@ struct MinMaxTable {
 };
 
 struct BaseLangSysRecord {
+
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      minMax.sanitize (c, base));
+  }
+
   protected:
   Tag baseLangSysTag;
   OffsetTo<MinMaxTable> minMax;
@@ -124,6 +186,14 @@ struct BaseLangSysRecord {
 };
 
 struct BaseValuesTable {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseCoordTable.sanitize (c, this));
+  }
+
   protected:
   USHORT    defaultIndex;
   USHORT    baseCoordCount;
@@ -135,6 +205,16 @@ struct BaseValuesTable {
 };
 
 struct BaseScriptTable {
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseValues.sanitize (c, this) &&
+      defaultMinMax.sanitize (c, this) &&
+      baseLangSysRecordTable.sanitize (c, this));
+  }
+
   protected:
   OffsetTo<BaseValuesTable>  baseValues;
   OffsetTo<MinMaxTable>  defaultMinMax;
@@ -148,6 +228,13 @@ struct BaseScriptTable {
 
 struct BaseScriptRecord {
 
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseScript.sanitize (c, base));
+  }
+
   protected:
   Tag baseScriptTag;
   OffsetTo<BaseScriptTable> baseScript;
@@ -158,6 +245,13 @@ struct BaseScriptRecord {
 
 struct BaseScriptList {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseScriptRecordTable.sanitize (c, this));
+  }
+
   protected:
   USHORT    baseScriptCount;
   ArrayOf<BaseScriptRecord> baseScriptRecordTable;
@@ -169,6 +263,12 @@ struct BaseScriptList {
 
 struct BaselineTag {
 
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this));
+  }
+
   protected:
   Tag   tag;
 
@@ -180,6 +280,13 @@ struct BaselineTag {
 struct BaseTagList
 {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseTagListTable.sanitize (c, this));
+  }
+
   protected:
   USHORT    baseTagCount;
   ArrayOf<BaselineTag> baseTagListTable;
@@ -191,6 +298,14 @@ struct BaseTagList
 struct VertAxis
 {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseTagList.sanitize (c, this) &&
+      baseScriptList.sanitize (c, this));
+  }
+
   protected:
   OffsetTo<BaseTagList> baseTagList;
   OffsetTo<BaseScriptList> baseScriptList;
@@ -202,6 +317,14 @@ struct VertAxis
 struct HorizAxis
 {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      baseTagList.sanitize (c, this) &&
+      baseScriptList.sanitize (c, this));
+  }
+
   protected:
   OffsetTo<HorizAxis> baseTagList;
   OffsetTo<VertAxis> baseScriptList;
@@ -214,6 +337,15 @@ struct HorizAxis
 struct BASEFormat1_1
 {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      horizAxis.sanitize (c, this) &&
+      vertAxis.sanitize (c, this) && 
+      itemVarStore.sanitize (c, this));
+  }
+
   protected:
   FixedVersion<>version;
   OffsetTo<HorizAxis> horizAxis;
@@ -227,6 +359,14 @@ struct BASEFormat1_1
 struct BASEFormat1_0
 {
 
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      horizAxis.sanitize (c, this) &&
+      vertAxis.sanitize (c, this));
+  }
+
   protected:
   FixedVersion<>version;
   OffsetTo<HorizAxis> horizAxis;
@@ -240,11 +380,16 @@ struct BASE
 {
   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
 
-  inline bool sanitize (hb_sanitize_context_t *c) const
+  inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
   {
     TRACE_SANITIZE (this);
-    return_trace (u.version.sanitize (c) &&
-      likely (u.version.major == 1));
+    if (!u.version.sanitize (c)) return_trace (false);
+    if (!likely(u.version.major == 1)) return_trace (false);
+    switch (u.version.minor) {
+    case 0: return_trace (u.format1_0.sanitize (c));
+    case 1: return_trace (u.format1_1.sanitize (c));
+    default:return_trace (true);
+    }
   }
 
   protected:
commit f131f00b1779b44633223915e17cbce358ad063a
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Feb 19 10:12:22 2017 +0100

    compile, move into hb-ot-layout.cc

diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index acbda8de..009db20a 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -30,7 +30,6 @@
 
 #include "hb-font-private.hh"
 
-#include "hb-ot-layout-base-table.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
diff --git a/src/hb-ot-layout-base-table.hh b/src/hb-ot-layout-base-table.hh
index 8ad01fe3..b3c0927b 100644
--- a/src/hb-ot-layout-base-table.hh
+++ b/src/hb-ot-layout-base-table.hh
@@ -109,7 +109,7 @@ struct MinMaxTable {
   ArrayOf<FeatMinMaxRecord> featMinMaxRecordTable;
 
   public:
-  DEFINE_SIZE_ARRAY (6, featMinMaxRecordTable);
+  DEFINE_SIZE_ARRAY (8, featMinMaxRecordTable);
 
 };
 
@@ -127,10 +127,10 @@ struct BaseValuesTable {
   protected:
   USHORT    defaultIndex;
   USHORT    baseCoordCount;
-  ArrayOf<BaseCoord> baseCoordTable;
+  OffsetArrayOf<BaseCoord> baseCoordTable;
 
   public:
-  DEFINE_SIZE_ARRAY (4, baseCoordTable);
+  DEFINE_SIZE_ARRAY (6, baseCoordTable);
 
 };
 
@@ -142,7 +142,7 @@ struct BaseScriptTable {
   ArrayOf<BaseLangSysRecord> baseLangSysRecordTable;
 
   public:
-    DEFINE_SIZE_ARRAY (6, baseLangSysRecordTable);
+    DEFINE_SIZE_ARRAY (8, baseLangSysRecordTable);
 };
 
 
@@ -153,7 +153,7 @@ struct BaseScriptRecord {
   OffsetTo<BaseScriptTable> baseScript;
 
   public:
-    DEFINE_SIZE_STATIC (4);
+    DEFINE_SIZE_STATIC (6);
 };
 
 struct BaseScriptList {
@@ -163,7 +163,7 @@ struct BaseScriptList {
   ArrayOf<BaseScriptRecord> baseScriptRecordTable;
 
   public:
-  DEFINE_SIZE_ARRAY (2, baseScriptRecordTable);
+  DEFINE_SIZE_ARRAY (4, baseScriptRecordTable);
   
 };
 
@@ -182,10 +182,10 @@ struct BaseTagList
 
   protected:
   USHORT    baseTagCount;
-  ArrayOf<BaselineTag> BaseTagListTable;
+  ArrayOf<BaselineTag> baseTagListTable;
 
   public:
-  DEFINE_SIZE_STATIC (4);
+  DEFINE_SIZE_ARRAY (4, baseTagListTable);
 };
 
 struct VertAxis
@@ -210,6 +210,32 @@ struct HorizAxis
   DEFINE_SIZE_STATIC (4);
 };
 
+
+struct BASEFormat1_1
+{
+
+  protected:
+  FixedVersion<>version;
+  OffsetTo<HorizAxis> horizAxis;
+  OffsetTo<VertAxis> vertAxis;
+  LOffsetTo<VariationStore> itemVarStore;
+
+  public:
+  DEFINE_SIZE_STATIC (12);
+};
+
+struct BASEFormat1_0
+{
+
+  protected:
+  FixedVersion<>version;
+  OffsetTo<HorizAxis> horizAxis;
+  OffsetTo<VertAxis> vertAxis;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
 struct BASE
 {
   static const hb_tag_t tableTag = HB_OT_TAG_BASE;
@@ -217,18 +243,19 @@ struct BASE
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
-    return_trace (version.sanitize (c) &&
-      likely (version.major == 1));
+    return_trace (u.version.sanitize (c) &&
+      likely (u.version.major == 1));
   }
 
   protected:
-  FixedVersion<>version;    /* Version of the BASE table: 1.0 or 1.1 */
-  OffsetTo<HorizAxis> horizAxis;
-  OffsetTo<VertAxis> vertAxis;
-  //LOffsetTo<ItemVarStore> itemVarStore;
+  union {
+    FixedVersion<>version;    /* Version of the BASE table: 1.0 or 1.1 */
+    BASEFormat1_0  format1_0;
+    BASEFormat1_1  format1_1;
+  } u;
 
   public:
-  DEFINE_SIZE_MIN (6);
+  DEFINE_SIZE_UNION (4, version);
 };
 
 
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index a1682a5f..3511810a 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -31,6 +31,7 @@
 #include "hb-open-type-private.hh"
 #include "hb-ot-layout-private.hh"
 
+#include "hb-ot-layout-base-table.hh"
 #include "hb-ot-layout-gdef-table.hh"
 #include "hb-ot-layout-gsub-table.hh"
 #include "hb-ot-layout-gpos-table.hh"
commit d0b97353e930d9b258f42f1cc1ac1a75306b76a8
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sun Feb 19 08:48:22 2017 +0100

    hb-ot-base-table.hh -> hb-ot-layout-base-table.hh
    
    per https://github.com/behdad/harfbuzz/issues/418#issuecomment-280873811

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 20ce77b8..0f83f6eb 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -68,9 +68,9 @@ HB_NODIST_headers = \
 HB_FALLBACK_sources = hb-fallback-shape.cc
 
 HB_OT_sources = \
-	hb-ot-base-table.hh \
 	hb-ot-font.cc \
 	hb-ot-layout.cc \
+	hb-ot-layout-base-table.hh \
 	hb-ot-layout-common-private.hh \
 	hb-ot-layout-gdef-table.hh \
 	hb-ot-layout-gpos-table.hh \
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 9abdc675..acbda8de 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -30,7 +30,7 @@
 
 #include "hb-font-private.hh"
 
-#include "hb-ot-base-table.hh"
+#include "hb-ot-layout-base-table.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
diff --git a/src/hb-ot-base-table.hh b/src/hb-ot-layout-base-table.hh
similarity index 100%
rename from src/hb-ot-base-table.hh
rename to src/hb-ot-layout-base-table.hh
commit f748e11645a3361f94d6fb10ce59febbaa5ba8ca
Author: Elie Roux <elie.roux at telecom-bretagne.eu>
Date:   Sat Feb 18 19:54:33 2017 +0100

    bootstraping structure

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 6363cf93..20ce77b8 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -68,6 +68,7 @@ HB_NODIST_headers = \
 HB_FALLBACK_sources = hb-fallback-shape.cc
 
 HB_OT_sources = \
+	hb-ot-base-table.hh \
 	hb-ot-font.cc \
 	hb-ot-layout.cc \
 	hb-ot-layout-common-private.hh \
diff --git a/src/hb-ot-base-table.hh b/src/hb-ot-base-table.hh
new file mode 100644
index 00000000..8ad01fe3
--- /dev/null
+++ b/src/hb-ot-base-table.hh
@@ -0,0 +1,238 @@
+/*
+ * Copyright © 2016 Elie Roux <elie.roux at telecom-bretagne.eu>
+ *
+ *  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.
+ *
+ */
+
+#ifndef HB_OT_BASE_TABLE_HH
+#define HB_OT_BASE_TABLE_HH
+
+#include "hb-open-type-private.hh"
+#include "hb-ot-layout-common-private.hh"
+
+#define HB_OT_TAG_BASE      HB_TAG('B','A','S','E')
+
+// https://www.microsoft.com/typography/otspec/baselinetags.htm
+
+#define HB_OT_TAG_BASE_HANG HB_TAG('h','a','n','g')
+#define HB_OT_TAG_BASE_ICFB HB_TAG('i','c','f','b')
+#define HB_OT_TAG_BASE_ICFT HB_TAG('i','c','f','t')
+#define HB_OT_TAG_BASE_IDEO HB_TAG('i','d','e','o')
+#define HB_OT_TAG_BASE_IDTB HB_TAG('i','d','t','b')
+#define HB_OT_TAG_BASE_MATH HB_TAG('m','a','t','h')
+#define HB_OT_TAG_BASE_ROMN HB_TAG('r','o','m','n')
+
+namespace OT {
+
+/*
+ * BASE -- The BASE Table
+ */
+
+struct BaseCoordFormat1 {
+  protected:
+  USHORT    baseCoordFormat;
+  SHORT   coordinate;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct BaseCoordFormat2 {
+  protected:
+  USHORT    baseCoordFormat;
+  SHORT   coordinate;
+  USHORT    referenceGlyph;
+  USHORT    baseCoordPoint;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+};
+
+struct BaseCoordFormat3 {
+  protected:
+  USHORT    baseCoordFormat;
+  SHORT   coordinate;
+  OffsetTo<Device>    deviceTable;
+
+  public:
+  DEFINE_SIZE_STATIC (6);
+};
+
+struct BaseCoord {
+  protected:
+  union {
+    USHORT    baseCoordFormat;
+    BaseCoordFormat1  format1;
+    BaseCoordFormat2  format2;
+    BaseCoordFormat3  format3;
+  } u;
+
+  public:
+  DEFINE_SIZE_MIN (4);
+};
+
+struct FeatMinMaxRecord {
+  protected:
+  Tag featureTableTag;
+  OffsetTo<BaseCoord>   minCoord;
+  OffsetTo<BaseCoord>   maxCoord;
+
+  public:
+  DEFINE_SIZE_STATIC (8);
+
+};
+
+struct MinMaxTable {
+  protected:
+  OffsetTo<BaseCoord>   minCoord;
+  OffsetTo<BaseCoord>   maxCoord;
+  USHORT    featMinMaxCount;
+  ArrayOf<FeatMinMaxRecord> featMinMaxRecordTable;
+
+  public:
+  DEFINE_SIZE_ARRAY (6, featMinMaxRecordTable);
+
+};
+
+struct BaseLangSysRecord {
+  protected:
+  Tag baseLangSysTag;
+  OffsetTo<MinMaxTable> minMax;
+
+  public:
+  DEFINE_SIZE_STATIC (6); 
+
+};
+
+struct BaseValuesTable {
+  protected:
+  USHORT    defaultIndex;
+  USHORT    baseCoordCount;
+  ArrayOf<BaseCoord> baseCoordTable;
+
+  public:
+  DEFINE_SIZE_ARRAY (4, baseCoordTable);
+
+};
+
+struct BaseScriptTable {
+  protected:
+  OffsetTo<BaseValuesTable>  baseValues;
+  OffsetTo<MinMaxTable>  defaultMinMax;
+  USHORT    baseLangSysCount;
+  ArrayOf<BaseLangSysRecord> baseLangSysRecordTable;
+
+  public:
+    DEFINE_SIZE_ARRAY (6, baseLangSysRecordTable);
+};
+
+
+struct BaseScriptRecord {
+
+  protected:
+  Tag baseScriptTag;
+  OffsetTo<BaseScriptTable> baseScript;
+
+  public:
+    DEFINE_SIZE_STATIC (4);
+};
+
+struct BaseScriptList {
+
+  protected:
+  USHORT    baseScriptCount;
+  ArrayOf<BaseScriptRecord> baseScriptRecordTable;
+
+  public:
+  DEFINE_SIZE_ARRAY (2, baseScriptRecordTable);
+  
+};
+
+struct BaselineTag {
+
+  protected:
+  Tag   tag;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+
+};
+
+struct BaseTagList
+{
+
+  protected:
+  USHORT    baseTagCount;
+  ArrayOf<BaselineTag> BaseTagListTable;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct VertAxis
+{
+
+  protected:
+  OffsetTo<BaseTagList> baseTagList;
+  OffsetTo<BaseScriptList> baseScriptList;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct HorizAxis
+{
+
+  protected:
+  OffsetTo<HorizAxis> baseTagList;
+  OffsetTo<VertAxis> baseScriptList;
+
+  public:
+  DEFINE_SIZE_STATIC (4);
+};
+
+struct BASE
+{
+  static const hb_tag_t tableTag = HB_OT_TAG_BASE;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (version.sanitize (c) &&
+      likely (version.major == 1));
+  }
+
+  protected:
+  FixedVersion<>version;    /* Version of the BASE table: 1.0 or 1.1 */
+  OffsetTo<HorizAxis> horizAxis;
+  OffsetTo<VertAxis> vertAxis;
+  //LOffsetTo<ItemVarStore> itemVarStore;
+
+  public:
+  DEFINE_SIZE_MIN (6);
+};
+
+
+} /* namespace OT */
+
+
+#endif /* HB_OT_BASE_TABLE_HH */
diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc
index 009db20a..9abdc675 100644
--- a/src/hb-ot-font.cc
+++ b/src/hb-ot-font.cc
@@ -30,6 +30,7 @@
 
 #include "hb-font-private.hh"
 
+#include "hb-ot-base-table.hh"
 #include "hb-ot-cmap-table.hh"
 #include "hb-ot-cbdt-table.hh"
 #include "hb-ot-glyf-table.hh"
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 071a439d..ee8e1373 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -122,6 +122,7 @@ hb_ot_layout_position_finish_offsets (hb_font_t    *font,
  */
 
 namespace OT {
+  struct BASE;
   struct GDEF;
   struct GSUB;
   struct GPOS;
@@ -162,6 +163,7 @@ struct hb_ot_layout_t
   const struct OT::GPOS *gpos;
 
   /* TODO Move the following out of this struct. */
+  OT::hb_lazy_table_loader_t<struct OT::BASE> base;
   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;


More information about the HarfBuzz mailing list