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

Behdad Esfahbod behdad at kemper.freedesktop.org
Mon Feb 26 03:06:46 UTC 2018


 .ci/fail.sh                     |   10 +++-
 .circleci/config.yml            |   16 +++++++
 .travis.yml                     |    4 -
 CMakeLists.txt                  |   36 ++++++++--------
 src/Makefile.am                 |    8 +--
 src/Makefile.sources            |    6 --
 src/hb-aat-layout-ankr-table.hh |   86 ++++++++++++++++++++++++++++++++++++++
 src/hb-aat-layout-kerx-table.hh |    7 +++
 src/hb-aat-layout-private.hh    |    3 +
 src/hb-aat-layout-trak-table.hh |   90 +++++++++++++++++++++++++++++++++++++---
 src/hb-aat-layout.cc            |   83 ++++++++++++++++++++++++++++++++----
 src/hb-open-file-private.hh     |   51 +++++++++++++++++-----
 src/hb-open-type-private.hh     |    9 ++--
 src/hb-ot-cmap-table.hh         |    8 ++-
 src/hb-ot-head-table.hh         |    2 
 src/hb-ot-hmtx-table.hh         |    8 ++-
 src/hb-ot-layout-private.hh     |   28 +++++++++++-
 src/hb-ot-layout.cc             |    6 ++
 src/hb-ot-shape.cc              |    2 
 src/hb-subset-glyf.cc           |    2 
 src/hb-subset-plan.cc           |    1 
 src/hb-subset.cc                |   12 +++--
 src/hb-version.h                |   66 +++++++++++++++++++++++++++++
 test/api/test-set.c             |   19 ++++----
 24 files changed, 479 insertions(+), 84 deletions(-)

New commits:
commit df1c7d5b60520d2b3c756b700d5ac41668fc0983
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 25 19:06:25 2018 -0800

    Minor

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index e4657887..5d33199e 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -740,8 +740,6 @@ template <typename Type>
 struct Offset : Type
 {
   inline bool is_null (void) const { return 0 == *this; }
-  public:
-  DEFINE_SIZE_STATIC (sizeof(Type));
 
   inline void *serialize (hb_serialize_context_t *c, const void *base)
   {
@@ -749,6 +747,9 @@ struct Offset : Type
     this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */
     return t;
   }
+
+  public:
+  DEFINE_SIZE_STATIC (sizeof(Type));
 };
 
 typedef Offset<HBUINT16> Offset16;
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 12cdb1d2..77ce8c97 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -136,7 +136,7 @@ _hb_subset_face_data_destroy (void *user_data)
 {
   hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
 
-  for (int i = 0; i < data->tables.len; i++)
+  for (unsigned int i = 0; i < data->tables.len; i++)
     hb_blob_destroy (data->tables[i].blob);
 
   data->tables.finish ();
commit 6dd46fa598cacdd046ba4548bc6ddf7f37c46dee
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sun Feb 25 18:54:52 2018 -0800

    [aat/trak] Minor
    
    Maybe we should make DEFINE_* make structs uncopyable.

diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index a5dc3ffd..b248db2f 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -42,6 +42,7 @@ struct TrackTableEntry
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+    /* XXX Sanitize values */
     return_trace (c->check_struct (this));
   }
 
@@ -81,9 +82,12 @@ struct TrackData
     Fixed fixed_size;
     fixed_size.set_float (csspx);
 
+    /* TODO Clean this up. */
+
     // TODO: Make indexing work and use only an entry with zero track
-    const TrackTableEntry trackTableEntry = trackTable[0];
+    const TrackTableEntry &trackTableEntry = trackTable[0];
 
+    /* TODO bfind() */
     unsigned int size_index;
     for (size_index = 0; size_index < nSizes; ++size_index)
       if ((base+sizeTable)[size_index] >= fixed_size)
@@ -127,42 +131,46 @@ struct trak
   inline bool apply (hb_aat_apply_context_t *c) const
   {
     TRACE_APPLY (this);
+
     const float ptem = c->font->ptem;
-    if (ptem > 0.f)
+    if (ptem <= 0.f)
+      return_trace (false);
+
+    hb_buffer_t *buffer = c->buffer;
+    if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction))
     {
-      hb_buffer_t *buffer = c->buffer;
-      if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction))
+      const TrackData &trackData = this+horizData;
+      float tracking = trackData.get_tracking (this, ptem);
+      hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
+      foreach_grapheme (buffer, start, end)
       {
-        const TrackData trackData = this+horizOffset;
-        float tracking = trackData.get_tracking (this, ptem);
-        hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
-        foreach_grapheme (buffer, start, end)
-        {
-          buffer->pos[start].x_advance += advance_to_add;
-          buffer->pos[end].x_advance += advance_to_add;
-        }
+	/* TODO This is wrong. */
+	buffer->pos[start].x_advance += advance_to_add;
+	buffer->pos[end].x_advance += advance_to_add;
       }
-      else
+    }
+    else
+    {
+      const TrackData &trackData = this+vertData;
+      float tracking = trackData.get_tracking (this, ptem);
+      hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
+      foreach_grapheme (buffer, start, end)
       {
-        const TrackData trackData = this+vertOffset;
-        float tracking = trackData.get_tracking (this, ptem);
-        hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
-        foreach_grapheme (buffer, start, end)
-        {
-          buffer->pos[start].y_advance += advance_to_add;
-          buffer->pos[end].y_advance += advance_to_add;
-        }
+	/* TODO This is wrong. */
+	buffer->pos[start].y_advance += advance_to_add;
+	buffer->pos[end].y_advance += advance_to_add;
       }
     }
-    return_trace (false);
+
+    return_trace (true);
   }
 
   protected:
   FixedVersion<>	version;	/* Version of the tracking table--currently
 					 * 0x00010000u for version 1.0. */
   HBUINT16		format; 	/* Format of the tracking table */
-  OffsetTo<TrackData>	horizOffset;	/* TrackData for horizontal text */
-  OffsetTo<TrackData>	vertOffset;	/* TrackData for vertical text */
+  OffsetTo<TrackData>	horizData;	/* TrackData for horizontal text */
+  OffsetTo<TrackData>	vertData;	/* TrackData for vertical text */
   HBUINT16		reserved;	/* Reserved. Set to 0. */
 
   public:
commit ae14dd0fb0a176f6f0143690907b51626999d248
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Mon Feb 26 00:31:09 2018 +0330

    [aat] Implement ankr

diff --git a/src/Makefile.sources b/src/Makefile.sources
index c07189d1..7883412c 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -80,8 +80,9 @@ HB_FALLBACK_sources = \
 HB_OT_sources = \
 	hb-aat-layout.cc \
 	hb-aat-layout-common-private.hh \
-	hb-aat-layout-morx-table.hh \
+	hb-aat-layout-ankr-table.hh \
 	hb-aat-layout-kerx-table.hh \
+	hb-aat-layout-morx-table.hh \
 	hb-aat-layout-trak-table.hh \
 	hb-aat-layout-private.hh \
 	hb-ot-font.cc \
diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh
new file mode 100644
index 00000000..2a903fda
--- /dev/null
+++ b/src/hb-aat-layout-ankr-table.hh
@@ -0,0 +1,86 @@
+/*
+ * Copyright © 2018  Ebrahim Byagowi
+ *
+ *  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_AAT_LAYOUT_ANKR_TABLE_HH
+#define HB_AAT_LAYOUT_ANKR_TABLE_HH
+
+#include "hb-aat-layout-common-private.hh"
+
+#define HB_AAT_TAG_ankr HB_TAG('a','n','k','r')
+
+
+namespace AAT {
+
+
+/*
+ * ankr -- Anchor point
+ */
+
+struct GlyphDataTable
+{
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      (numPoints == 0) &&
+      (anchorPoints.sanitize (c, numPoints)));
+  }
+
+  protected:
+  HBUINT32			numPoints;	/* Number of anchor points for this glyph */
+  UnsizedArrayOf<HBUINT32>	anchorPoints;	/* Individual anchor points. Each anchor point is a two-byte
+						 * signed x-coordinate followed by a two-byte signed y-coordinate */
+
+  public:
+  DEFINE_SIZE_ARRAY (4, anchorPoints);
+};
+
+struct ankr
+{
+  static const hb_tag_t tableTag = HB_AAT_TAG_ankr;
+
+  inline bool sanitize (hb_sanitize_context_t *c) const
+  {
+    TRACE_SANITIZE (this);
+    return_trace (c->check_struct (this) &&
+      (version == 0) &&
+      (flags == 0) &&
+      (lookupTableOffset == 0x0000000C) &&
+      (glyphDataTableOffset.sanitize (c, this)));
+  }
+
+  protected:
+  HBUINT16			version; 		/* Version number (set to zero) */
+  HBUINT16			flags;			/* Flags (currently unused; set to zero) */
+  LOffsetTo<const void*>	lookupTableOffset;	/* Offset to the table's lookup table */
+  LOffsetTo<GlyphDataTable>	glyphDataTableOffset;	/* Offset to the glyph data table */
+
+  public:
+  DEFINE_SIZE_MIN (12);
+};
+
+} /* namespace AAT */
+
+
+#endif /* HB_AAT_LAYOUT_ANKR_TABLE_HH */
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 06282e2c..505e5084 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -263,7 +263,7 @@ struct kerx
 {
   static const hb_tag_t tableTag = HB_AAT_TAG_kerx;
 
-  inline bool apply (hb_aat_apply_context_t *c) const
+  inline bool apply (hb_aat_apply_context_t *c, const AAT::ankr *ankr) const
   {
     TRACE_APPLY (this);
     /* TODO */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 652ed54b..bdbe41f9 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -30,29 +30,29 @@
 #include "hb-ot-layout-gsubgpos-private.hh"
 
 #include "hb-aat-layout-private.hh"
-#include "hb-aat-layout-morx-table.hh"
+#include "hb-aat-layout-ankr-table.hh"
 #include "hb-aat-layout-kerx-table.hh"
+#include "hb-aat-layout-morx-table.hh"
 #include "hb-aat-layout-trak-table.hh"
 
 /*
  * mort/morx
  */
 
-static inline const AAT::morx&
-_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
+static inline const AAT::ankr&
+_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr)
 {
   if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
   {
     if (blob)
       *blob = hb_blob_get_empty ();
-    return OT::Null(AAT::morx);
+    return OT::Null(AAT::ankr);
   }
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  /* XXX this doesn't call set_num_glyphs on sanitizer. */
-  const AAT::morx& morx = *(layout->morx.get ());
+  const AAT::ankr& ankr = *(layout->ankr.get ());
   if (blob)
-    *blob = layout->morx.blob;
-  return morx;
+    *blob = layout->ankr.blob;
+  return ankr;
 }
 
 static inline const AAT::kerx&
@@ -72,6 +72,23 @@ _get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
   return kerx;
 }
 
+static inline const AAT::morx&
+_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  {
+    if (blob)
+      *blob = hb_blob_get_empty ();
+    return OT::Null(AAT::morx);
+  }
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  /* XXX this doesn't call set_num_glyphs on sanitizer. */
+  const AAT::morx& morx = *(layout->morx.get ());
+  if (blob)
+    *blob = layout->morx.blob;
+  return morx;
+}
+
 static inline const AAT::trak&
 _get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
 {
@@ -82,7 +99,6 @@ _get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
     return OT::Null(AAT::trak);
   }
   hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
-  /* XXX this doesn't call set_num_glyphs on sanitizer. */
   const AAT::trak& trak = *(layout->trak.get ());
   if (blob)
     *blob = layout->trak.blob;
@@ -117,10 +133,11 @@ void
 hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer)
 {
   hb_blob_t *blob;
+  const AAT::ankr& ankr = _get_ankr (font->face, &blob);
   const AAT::kerx& kerx = _get_kerx (font->face, &blob);
   const AAT::trak& trak = _get_trak (font->face, &blob);
 
   AAT::hb_aat_apply_context_t c (font, buffer, blob);
-  kerx.apply (&c);
+  kerx.apply (&c, &ankr);
   trak.apply (&c);
 }
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index ce1f6a8e..683ed7ba 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -131,8 +131,9 @@ namespace OT {
 }
 
 namespace AAT {
-  struct morx;
+  struct ankr;
   struct kerx;
+  struct morx;
   struct trak;
 }
 
@@ -171,8 +172,9 @@ struct hb_ot_layout_t
   OT::hb_lazy_table_loader_t<struct OT::MATH> math;
   OT::hb_lazy_table_loader_t<struct OT::fvar> fvar;
   OT::hb_lazy_table_loader_t<struct OT::avar> avar;
-  OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
+  OT::hb_lazy_table_loader_t<struct AAT::ankr> ankr;
   OT::hb_lazy_table_loader_t<struct AAT::kerx> kerx;
+  OT::hb_lazy_table_loader_t<struct AAT::morx> morx;
   OT::hb_lazy_table_loader_t<struct AAT::trak> trak;
 
   unsigned int gsub_lookup_count;
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index b92ba05f..3273ecce 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -64,8 +64,9 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->math.init (face);
   layout->fvar.init (face);
   layout->avar.init (face);
-  layout->morx.init (face);
+  layout->ankr.init (face);
   layout->kerx.init (face);
+  layout->morx.init (face);
   layout->trak.init (face);
 
   {
@@ -216,8 +217,9 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   layout->math.fini ();
   layout->fvar.fini ();
   layout->avar.fini ();
-  layout->morx.fini ();
+  layout->ankr.fini ();
   layout->kerx.fini ();
+  layout->morx.fini ();
   layout->trak.fini ();
 
   free (layout);
commit a8d3c2c030d2c21c70e0b8bd43f7d05ff4818b75
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sat Feb 24 16:42:12 2018 +0330

    [ci] Add clang O3/O0 testers (#834)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index e30b5b45..d804afce 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -37,6 +37,21 @@ jobs:
       - run: make
       - run: make check || .ci/fail.sh
 
+  clang-O3-O0:
+    docker:
+      - image: multiarch/crossbuild
+    steps:
+      - checkout
+      - run: apt update && apt install -y ragel libfreetype6-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
+      - run: pip install fonttools
+      - run: wget http://download.savannah.gnu.org/releases/freetype/freetype-2.9.tar.bz2 && tar xf freetype-2.9.tar.bz2 && cd freetype-2.9 && ./autogen.sh && ./configure && make -j4 && cd ..
+      - run: CFLAGS="-O3" CXXFLAGS="-O3" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2
+      - run: make
+      - run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
+      - run: CFLAGS="-O0" CXXFLAGS="-O0" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2
+      - run: make
+      - run: LD_LIBRARY_PATH="$PWD/freetype-2.9/objs/.libs" make check || .ci/fail.sh
+
   fedora-outoftreebuild:
     docker:
       - image: fedora
@@ -153,6 +168,7 @@ workflows:
       # autotools based builds
       - alpine-O3
       - archlinux-debug-O0
+      - clang-O3-O0
       - fedora-outoftreebuild
 
       # cmake based builds
commit c73255f3eb2f060ec72d18790b374f6b6e4032aa
Author: Khaled Hosny <khaledhosny at eglug.org>
Date:   Sat Feb 24 00:44:07 2018 +0200

    Workaround for old automake on Travis Linux images
    
    https://github.com/harfbuzz/harfbuzz/pull/821#issuecomment-368116538

diff --git a/.ci/fail.sh b/.ci/fail.sh
index 91701d33..4e0069e3 100755
--- a/.ci/fail.sh
+++ b/.ci/fail.sh
@@ -2,11 +2,17 @@
 
 for f in $(find . -name '*.log' -not -name 'config.log'); do
     last=$(tail -1 $f)
-    if [[ $last = FAIL* || $last = *failed* ]]; then
+    if [[ $last = FAIL* ]]; then
         echo '====' $f '===='
         cat $f
+    elif [[ $last = PASS* ]]; then
+        # Do nothing.
+        true
+    else
+	# Travis Linux images has an old automake that does not match the
+	# patterns above, so in case of doubt just print the file.
+        cat $f
     fi
 done
 
-# Intentionally exiting with non-zero.
 exit 1
commit cd28eb9f5dc237325c64380d9d87e673b8e94985
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sat Feb 24 14:17:54 2018 +0330

    Add -Werror=unused-function check to Travis (#832)

diff --git a/.travis.yml b/.travis.yml
index 662fab59..02accdc9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,8 +6,8 @@ language: cpp
 env:
   global:
     - CPPFLAGS=""
-    - CFLAGS="-Werror --coverage"
-    - CXXFLAGS="-Werror -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
+    - CFLAGS="-Werror -Werror=unused-function --coverage"
+    - CXXFLAGS="-Werror -Werror=unused-function -Wno-deprecated-register --coverage" # glib uses register and clang raises a warning
     - LDFLAGS="--coverage"
     - CONFIGURE_OPTS="--with-freetype --with-glib --with-gobject --with-cairo --with-icu --with-graphite2"
     - NOCONFIGURE=1
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 2b67bf36..652ed54b 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -89,19 +89,19 @@ _get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
   return trak;
 }
 
-static inline void
-_hb_aat_layout_create (hb_face_t *face)
-{
-  OT::Sanitizer<AAT::morx> sanitizer;
-  sanitizer.set_num_glyphs (face->get_num_glyphs ());
-  hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_MORX));
-  OT::Sanitizer<AAT::morx>::lock_instance (morx_blob);
+// static inline void
+// _hb_aat_layout_create (hb_face_t *face)
+// {
+//   OT::Sanitizer<AAT::morx> sanitizer;
+//   sanitizer.set_num_glyphs (face->get_num_glyphs ());
+//   hb_blob_t *morx_blob = sanitizer.sanitize (face->reference_table (HB_AAT_TAG_MORX));
+//   OT::Sanitizer<AAT::morx>::lock_instance (morx_blob);
 
-  if (0)
-  {
-    OT::Sanitizer<AAT::Lookup<OT::GlyphID> >::lock_instance (morx_blob)->get_value (1, face->get_num_glyphs ());
-  }
-}
+//   if (0)
+//   {
+//     OT::Sanitizer<AAT::Lookup<OT::GlyphID> >::lock_instance (morx_blob)->get_value (1, face->get_num_glyphs ());
+//   }
+// }
 
 void
 hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
diff --git a/test/api/test-set.c b/test/api/test-set.c
index 60e11d98..1c51e846 100644
--- a/test/api/test-set.c
+++ b/test/api/test-set.c
@@ -121,15 +121,16 @@ test_set_basic (void)
   hb_set_destroy (s);
 }
 
-static inline void
-print_set (hb_set_t *s)
-{
-  hb_codepoint_t next;
-  printf ("{");
-  for (next = HB_SET_VALUE_INVALID; hb_set_next (s, &next); )
-    printf ("%d, ", next);
-  printf ("}\n");
-}
+
+// static inline void
+// print_set (hb_set_t *s)
+// {
+//   hb_codepoint_t next;
+//   printf ("{");
+//   for (next = HB_SET_VALUE_INVALID; hb_set_next (s, &next); )
+//     printf ("%d, ", next);
+//   printf ("}\n");
+// }
 
 static void
 test_set_algebra (void)
commit 1ab16f4556ef3e54a40b63cf4570c0ae986894e7
Author: Ebrahim Byagowi <ebrahim at gnu.org>
Date:   Sat Feb 24 12:49:42 2018 +0330

    [aat] Implement trak logic (#816)

diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index b061f11d..06282e2c 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -263,6 +263,13 @@ struct kerx
 {
   static const hb_tag_t tableTag = HB_AAT_TAG_kerx;
 
+  inline bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    /* TODO */
+    return_trace (false);
+  }
+
   struct SubTableWrapper
   {
     enum coverage_flags_t {
diff --git a/src/hb-aat-layout-private.hh b/src/hb-aat-layout-private.hh
index c1c607a2..ce75c8e7 100644
--- a/src/hb-aat-layout-private.hh
+++ b/src/hb-aat-layout-private.hh
@@ -37,4 +37,7 @@
 HB_INTERNAL void
 hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer);
 
+HB_INTERNAL void
+hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer);
+
 #endif /* HB_AAT_LAYOUT_PRIVATE_HH */
diff --git a/src/hb-aat-layout-trak-table.hh b/src/hb-aat-layout-trak-table.hh
index 6dbd05ab..a5dc3ffd 100644
--- a/src/hb-aat-layout-trak-table.hh
+++ b/src/hb-aat-layout-trak-table.hh
@@ -1,6 +1,6 @@
 /*
- * Copyright © 2018  Google, Inc.
  * Copyright © 2018  Ebrahim Byagowi
+ * Copyright © 2018  Google, Inc.
  *
  *  This is part of HarfBuzz, a text shaping library.
  *
@@ -45,10 +45,15 @@ struct TrackTableEntry
     return_trace (c->check_struct (this));
   }
 
+  inline float get_value (const void *base, unsigned int index) const
+  {
+    return (base+values)[index];
+  }
+
   protected:
   Fixed			track;		/* Track value for this record. */
   HBUINT16		trackNameID;	/* The 'name' table index for this track */
-  OffsetTo<UnsizedArrayOf<Fixed> >
+  OffsetTo<UnsizedArrayOf<HBINT16> >
 			values;		/* Offset from start of tracking table to
 					 * per-size tracking values for this track. */
 
@@ -61,15 +66,48 @@ struct TrackData
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+    /* TODO */
     return_trace (c->check_struct (this));
   }
 
+  inline float get_tracking (const void *base, float ptem) const
+  {
+    /* CoreText points are CSS pixels (96 per inch),
+     * NOT typographic points (72 per inch).
+     *
+     * https://developer.apple.com/library/content/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html
+     */
+    float csspx = ptem * 96.f / 72.f;
+    Fixed fixed_size;
+    fixed_size.set_float (csspx);
+
+    // TODO: Make indexing work and use only an entry with zero track
+    const TrackTableEntry trackTableEntry = trackTable[0];
+
+    unsigned int size_index;
+    for (size_index = 0; size_index < nSizes; ++size_index)
+      if ((base+sizeTable)[size_index] >= fixed_size)
+        break;
+
+    // We don't attempt to extrapolate to larger or smaller values
+    if (size_index == nSizes)
+      return trackTableEntry.get_value (base, nSizes - 1);
+    if (size_index == 0 || (base+sizeTable)[size_index] == fixed_size)
+      return trackTableEntry.get_value (base, size_index);
+
+    float s0 = (base+sizeTable)[size_index - 1].to_float ();
+    float s1 = (base+sizeTable)[size_index].to_float ();
+    float t = (csspx - s0) / (s1 - s0);
+    return t * trackTableEntry.get_value (base, size_index) +
+      (1.0 - t) * trackTableEntry.get_value (base, size_index - 1);
+  }
+
   protected:
   HBUINT16		nTracks;	/* Number of separate tracks included in this table. */
   HBUINT16		nSizes;		/* Number of point sizes included in this table. */
   LOffsetTo<UnsizedArrayOf<Fixed> >
 			sizeTable;
-  TrackTableEntry	trackTable[VAR];/* Array[nSizes] of size values. */
+  UnsizedArrayOf<TrackTableEntry>	trackTable;/* Array[nSizes] of size values. */
 
   public:
   DEFINE_SIZE_ARRAY (8, trackTable);
@@ -82,9 +120,43 @@ struct trak
   inline bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
+    /* TODO */
     return_trace (c->check_struct (this));
   }
 
+  inline bool apply (hb_aat_apply_context_t *c) const
+  {
+    TRACE_APPLY (this);
+    const float ptem = c->font->ptem;
+    if (ptem > 0.f)
+    {
+      hb_buffer_t *buffer = c->buffer;
+      if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction))
+      {
+        const TrackData trackData = this+horizOffset;
+        float tracking = trackData.get_tracking (this, ptem);
+        hb_position_t advance_to_add = c->font->em_scalef_x (tracking / 2);
+        foreach_grapheme (buffer, start, end)
+        {
+          buffer->pos[start].x_advance += advance_to_add;
+          buffer->pos[end].x_advance += advance_to_add;
+        }
+      }
+      else
+      {
+        const TrackData trackData = this+vertOffset;
+        float tracking = trackData.get_tracking (this, ptem);
+        hb_position_t advance_to_add = c->font->em_scalef_y (tracking / 2);
+        foreach_grapheme (buffer, start, end)
+        {
+          buffer->pos[start].y_advance += advance_to_add;
+          buffer->pos[end].y_advance += advance_to_add;
+        }
+      }
+    }
+    return_trace (false);
+  }
+
   protected:
   FixedVersion<>	version;	/* Version of the tracking table--currently
 					 * 0x00010000u for version 1.0. */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 3b967c6b..2b67bf36 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -55,6 +55,40 @@ _get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
   return morx;
 }
 
+static inline const AAT::kerx&
+_get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  {
+    if (blob)
+      *blob = hb_blob_get_empty ();
+    return OT::Null(AAT::kerx);
+  }
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  /* XXX this doesn't call set_num_glyphs on sanitizer. */
+  const AAT::kerx& kerx = *(layout->kerx.get ());
+  if (blob)
+    *blob = layout->kerx.blob;
+  return kerx;
+}
+
+static inline const AAT::trak&
+_get_trak (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+  if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+  {
+    if (blob)
+      *blob = hb_blob_get_empty ();
+    return OT::Null(AAT::trak);
+  }
+  hb_ot_layout_t * layout = hb_ot_layout_from_face (face);
+  /* XXX this doesn't call set_num_glyphs on sanitizer. */
+  const AAT::trak& trak = *(layout->trak.get ());
+  if (blob)
+    *blob = layout->trak.blob;
+  return trak;
+}
+
 static inline void
 _hb_aat_layout_create (hb_face_t *face)
 {
@@ -78,3 +112,15 @@ hb_aat_layout_substitute (hb_font_t *font, hb_buffer_t *buffer)
   AAT::hb_aat_apply_context_t c (font, buffer, blob);
   morx.apply (&c);
 }
+
+void
+hb_aat_layout_position (hb_font_t *font, hb_buffer_t *buffer)
+{
+  hb_blob_t *blob;
+  const AAT::kerx& kerx = _get_kerx (font->face, &blob);
+  const AAT::trak& trak = _get_trak (font->face, &blob);
+
+  AAT::hb_aat_apply_context_t c (font, buffer, blob);
+  kerx.apply (&c);
+  trak.apply (&c);
+}
diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index f5c20bcb..e4657887 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -692,8 +692,8 @@ struct F2DOT14 : HBINT16
 /* 32-bit signed fixed-point number (16.16). */
 struct Fixed: HBINT32
 {
-  //inline float to_float (void) const { return ???; }
-  //inline void set_float (float f) { v.set (f * ???); }
+  inline float to_float (void) const { return ((int32_t) v) / 65536.0; }
+  inline void set_float (float f) { v.set (round (f * 65536.0)); }
   public:
   DEFINE_SIZE_STATIC (4);
 };
diff --git a/src/hb-ot-layout-private.hh b/src/hb-ot-layout-private.hh
index 0c3bcbc5..ce1f6a8e 100644
--- a/src/hb-ot-layout-private.hh
+++ b/src/hb-ot-layout-private.hh
@@ -363,6 +363,28 @@ _hb_glyph_info_get_modified_combining_class (const hb_glyph_info_t *info)
   return _hb_glyph_info_is_unicode_mark (info) ? info->unicode_props()>>8 : 0;
 }
 
+
+/* Loop over grapheme. Based on foreach_cluster(). */
+#define foreach_grapheme(buffer, start, end) \
+  for (unsigned int \
+       _count = buffer->len, \
+       start = 0, end = _count ? _next_grapheme (buffer, 0) : 0; \
+       start < _count; \
+       start = end, end = _next_grapheme (buffer, start))
+
+static inline unsigned int
+_next_grapheme (hb_buffer_t *buffer, unsigned int start)
+{
+  hb_glyph_info_t *info = buffer->info;
+  unsigned int count = buffer->len;
+
+  while (++start < count && _hb_glyph_info_is_unicode_mark (&info[start]))
+    ;
+
+  return start;
+}
+
+
 #define info_cc(info) (_hb_glyph_info_get_modified_combining_class (&(info)))
 
 static inline bool
diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc
index 4cf6c722..b92ba05f 100644
--- a/src/hb-ot-layout.cc
+++ b/src/hb-ot-layout.cc
@@ -65,6 +65,8 @@ _hb_ot_layout_create (hb_face_t *face)
   layout->fvar.init (face);
   layout->avar.init (face);
   layout->morx.init (face);
+  layout->kerx.init (face);
+  layout->trak.init (face);
 
   {
     /*
@@ -215,6 +217,8 @@ _hb_ot_layout_destroy (hb_ot_layout_t *layout)
   layout->fvar.fini ();
   layout->avar.fini ();
   layout->morx.fini ();
+  layout->kerx.fini ();
+  layout->trak.fini ();
 
   free (layout);
 }
diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc
index d9ba0f6b..d2d8012d 100644
--- a/src/hb-ot-shape.cc
+++ b/src/hb-ot-shape.cc
@@ -787,6 +787,8 @@ hb_ot_position (hb_ot_shape_context_t *c)
     _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);
 
   _hb_buffer_deallocate_gsubgpos_vars (c->buffer);
+
+  //hb_aat_layout_position (c->font, c->buffer);
 }
 
 static inline void
commit b91e8da36e164168cd532fd6e6950c5d743a14dd
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 23 22:51:17 2018 -0800

    Include hb-version.h in git (#825)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6b4e1089..f7a5d830 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -137,7 +137,7 @@ set (IN_HB_DIST FALSE)
 if (EXISTS "${PROJECT_SOURCE_DIR}/ChangeLog")
   # perhaps we are on dist directory
   set (IN_HB_DIST TRUE)
-  set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
+  #set (HB_VERSION_H "${PROJECT_SOURCE_DIR}/src/hb-version.h")
 endif ()
 
 
@@ -180,13 +180,13 @@ add_prefix_to_list(HB_SUBSET_headers "${PROJECT_SOURCE_DIR}/src/")
 
 extract_make_variable(HB_BASE_RAGEL_GENERATED_sources ${SRCSOURCES})
 extract_make_variable(HB_OT_RAGEL_GENERATED_sources ${SRCSOURCES})
-if (IN_HB_DIST)
+#if (IN_HB_DIST)
   add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
   add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_SOURCE_DIR}/src/")
-else ()
-  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
-  add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
-endif ()
+#else ()
+#  add_prefix_to_list(HB_BASE_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
+#  add_prefix_to_list(HB_OT_RAGEL_GENERATED_sources "${PROJECT_BINARY_DIR}/src/")
+#endif ()
 
 extract_make_variable(HB_VIEW_sources ${UTILSOURCES})
 add_prefix_to_list(HB_VIEW_sources "${PROJECT_SOURCE_DIR}/util/")
@@ -234,17 +234,17 @@ endif ()
 
 
 ## Generate hb-version.h
-if (NOT IN_HB_DIST)
-  set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in")
-  set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h")
-  set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true)
-  configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY)
-  execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different
-    "${HB_VERSION_H}.tmp"
-    "${HB_VERSION_H}"
-  )
-  file(REMOVE "${HB_VERSION_H}.tmp")
-endif ()
+#if (NOT IN_HB_DIST)
+#  set (HB_VERSION_H_IN "${PROJECT_SOURCE_DIR}/src/hb-version.h.in")
+#  set (HB_VERSION_H "${PROJECT_BINARY_DIR}/src/hb-version.h")
+#  set_source_files_properties("${HB_VERSION_H}" PROPERTIES GENERATED true)
+#  configure_file("${HB_VERSION_H_IN}" "${HB_VERSION_H}.tmp" @ONLY)
+#  execute_process(COMMAND "${CMAKE_COMMAND}" -E copy_if_different
+#    "${HB_VERSION_H}.tmp"
+#    "${HB_VERSION_H}"
+#  )
+#  file(REMOVE "${HB_VERSION_H}.tmp")
+#endif ()
 
 
 ## Define sources and headers of the project
@@ -264,7 +264,7 @@ set (subset_project_sources
 set (project_extra_sources)
 
 set (project_headers
-  ${HB_VERSION_H}
+  #${HB_VERSION_H}
 
   ${HB_BASE_headers}
   ${HB_OT_headers}
diff --git a/src/Makefile.am b/src/Makefile.am
index c4d5fb85..3f98e1db 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -30,7 +30,6 @@ HBDEPS =
 HBSOURCES =  $(HB_BASE_sources)
 HBSOURCES += $(HB_BASE_RAGEL_GENERATED_sources)
 HBHEADERS = $(HB_BASE_headers)
-HBNODISTHEADERS = $(HB_NODIST_headers)
 
 if WITH_LIBSTDCXX
 HBNOLIBCXXCFLAGS =
@@ -147,13 +146,13 @@ endif
 
 base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined
 libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS)
-libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) $(HBNODISTHEADERS)
+libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS)
 libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(HBNOLIBCXXFLAGS)
 libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols)
 libharfbuzz_la_LIBADD = $(HBLIBS)
 EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency)
 pkginclude_HEADERS = $(HBHEADERS)
-nodist_pkginclude_HEADERS = $(HBNODISTHEADERS)
+nodist_pkginclude_HEADERS =
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = harfbuzz.pc
 cmakedir = $(libdir)/cmake/harfbuzz
@@ -392,7 +391,7 @@ TESTS_ENVIRONMENT = \
 	srcdir="$(srcdir)" \
 	MAKE="$(MAKE) $(AM_MAKEFLAGS)" \
 	HBSOURCES="$(HBSOURCES)" \
-	HBHEADERS="$(HBHEADERS) $(HBNODISTHEADERS)" \
+	HBHEADERS="$(HBHEADERS)" \
 	$(NULL)
 
 if HAVE_INTROSPECTION
@@ -422,7 +421,6 @@ HarfBuzz_0_0_gir_LIBS = \
 	$(NULL)
 HarfBuzz_0_0_gir_FILES = \
 	$(HBHEADERS) \
-	$(HBNODISTHEADERS) \
 	$(HBSOURCES) \
 	$(HB_GOBJECT_sources) \
 	$(HB_GOBJECT_headers) \
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 2bb56b4f..c07189d1 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -70,9 +70,6 @@ HB_BASE_headers = \
 	hb-shape.h \
 	hb-shape-plan.h \
 	hb-unicode.h \
-	$(NULL)
-
-HB_NODIST_headers = \
 	hb-version.h \
 	$(NULL)
 
diff --git a/src/hb-version.h b/src/hb-version.h
new file mode 100644
index 00000000..f0f5a181
--- /dev/null
+++ b/src/hb-version.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2011  Google, Inc.
+ *
+ *  This is part of HarfBuzz, a text shaping library.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and its documentation for any purpose, provided that the
+ * above copyright notice and the following two paragraphs appear in
+ * all copies of this software.
+ *
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+ * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ *
+ * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ *
+ * Google Author(s): Behdad Esfahbod
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_VERSION_H
+#define HB_VERSION_H
+
+#include "hb-common.h"
+
+HB_BEGIN_DECLS
+
+
+#define HB_VERSION_MAJOR 1
+#define HB_VERSION_MINOR 7
+#define HB_VERSION_MICRO 5
+
+#define HB_VERSION_STRING "1.7.5"
+
+#define HB_VERSION_ATLEAST(major,minor,micro) \
+	((major)*10000+(minor)*100+(micro) <= \
+	 HB_VERSION_MAJOR*10000+HB_VERSION_MINOR*100+HB_VERSION_MICRO)
+
+
+HB_EXTERN void
+hb_version (unsigned int *major,
+	    unsigned int *minor,
+	    unsigned int *micro);
+
+HB_EXTERN const char *
+hb_version_string (void);
+
+HB_EXTERN hb_bool_t
+hb_version_atleast (unsigned int major,
+		    unsigned int minor,
+		    unsigned int micro);
+
+
+HB_END_DECLS
+
+#endif /* HB_VERSION_H */
commit 83af6c237f2bfd66af76a8647a62b3d1ab996744
Merge: 7e5e1feb dc5c7927
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 18:33:25 2018 -0700

    Merge pull request #829 from googlefonts/test-checksum
    
    [subset] Caclculate head table checksum adjustment

commit dc5c7927e75ea09461e46fe6e56897091b4b4f00
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Feb 23 16:42:06 2018 -0800

    [subset] Caclculate head table checksum adjustment
    
    Test still fails, because we do not serialize tables in the same
    order that fonttools subsetter does.

diff --git a/src/hb-open-file-private.hh b/src/hb-open-file-private.hh
index 701935b7..e2644eaf 100644
--- a/src/hb-open-file-private.hh
+++ b/src/hb-open-file-private.hh
@@ -30,6 +30,7 @@
 #define HB_OPEN_FILE_PRIVATE_HH
 
 #include "hb-open-type-private.hh"
+#include "hb-ot-head-table.hh"
 
 
 namespace OT {
@@ -135,13 +136,15 @@ typedef struct OffsetTable
     TRACE_SERIALIZE (this);
     /* Alloc 12 for the OTHeader. */
     if (unlikely (!c->extend_min (*this))) return_trace (false);
-    /* Write sfntVersion (bytes 0..3) */
+    /* Write sfntVersion (bytes 0..3). */
     sfnt_version.set (sfnt_tag);
     /* Take space for numTables, searchRange, entrySelector, RangeShift
-     * and the TableRecords themselves
-     */
+     * and the TableRecords themselves.  */
     if (unlikely (!tables.serialize (c, table_count))) return_trace (false);
 
+    const char *dir_end = (const char *) c->head;
+    HBUINT32 *checksum_adjustment = nullptr;
+
     /* Write OffsetTables, alloc for and write actual table blobs. */
     for (unsigned int i = 0; i < table_count; i++)
     {
@@ -150,24 +153,48 @@ typedef struct OffsetTable
       rec.tag.set (tags[i]);
       rec.length.set (hb_blob_get_length (blob));
       rec.offset.serialize (c, this);
-      /* Allocate room for the table. */
-      void *p = c->allocate_size<void> (rec.length);
-      const char *start = (const char *) p;
-      if (unlikely (!p)) {return false;}
-      /* copy the actual table. */
-      memcpy (p, hb_blob_get_data (blob, nullptr), rec.length);
+
+      /* Allocate room for the table and copy it. */
+      char *start = (char *) c->allocate_size<void> (rec.length);
+      if (unlikely (!start)) {return false;}
+
+      memcpy (start, hb_blob_get_data (blob, nullptr), rec.length);
+
       /* 4-byte allignment. */
       if (rec.length % 4)
-	p = c->allocate_size<void> (4 - rec.length % 4);
+	c->allocate_size<void> (4 - rec.length % 4);
       const char *end = (const char *) c->head;
+
+      if (tags[i] == HB_OT_TAG_head && end - start >= head::static_size)
+      {
+	head *h = (head *) start;
+	checksum_adjustment = &h->checkSumAdjustment;
+	checksum_adjustment->set (0);
+      }
+
       rec.checkSum.set_for_data (start, end - start);
     }
     tags += table_count;
     blobs += table_count;
 
-    /* TODO: update head table checkSumAdjustment. */
-
     tables.qsort ();
+
+    if (checksum_adjustment)
+    {
+      CheckSum checksum;
+
+      /* The following line is a slower version of the following block. */
+      //checksum.set_for_data (this, (const char *) c->head - (const char *) this);
+      checksum.set_for_data (this, dir_end - (const char *) this);
+      for (unsigned int i = 0; i < table_count; i++)
+      {
+	TableRecord &rec = tables.array[i];
+	checksum.set (checksum + rec.checkSum);
+      }
+
+      checksum_adjustment->set (0xB1B0AFBAu - checksum);
+    }
+
     return_trace (true);
   }
 
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 2024cea7..1d458404 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -43,6 +43,8 @@ namespace OT {
 
 struct head
 {
+  friend struct OffsetTable;
+
   static const hb_tag_t tableTag	= HB_OT_TAG_head;
 
   inline unsigned int get_upem (void) const
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 3a0ddb03..12cdb1d2 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -198,6 +198,8 @@ _hb_subset_face_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
   return nullptr;
 }
 
+/* TODO: Move this to hb-face.h and rename to hb_face_builder_create()
+ * with hb_face_builder_add_table(). */
 hb_face_t *
 hb_subset_face_create (void)
 {
commit 7e5e1feb666d6a861b5cd64bf29a16e3854fb812
Merge: ec2538c8 99967e21
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 17:59:08 2018 -0700

    Merge pull request #828 from googlefonts/mem-fixes
    
    [subset] Fix several memory leaks in subsetting.

commit 99967e21c6e3f6882d6eadf5c22f4120684b1fc5
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:45:45 2018 -0800

    [subset] Fix memory leak in hb-subset-glyf.

diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index d57b4115..d29efe9d 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -234,6 +234,8 @@ hb_subset_glyf_and_loca (hb_subset_plan_t *plan,
                                           use_short_loca,
                                           glyf_prime,
                                           loca_prime);
+
+  hb_blob_destroy (glyf_blob);
   glyf.fini();
 
   return result;
commit e61f360dc828bfd46477b7ddff56874da9f03538
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:44:21 2018 -0800

    [subset] Fix memory leak in hb-subset-plan.

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index b9e299ad..27c2c7f0 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -165,6 +165,7 @@ _populate_gids_to_retain (hb_face_t *face,
   while (hb_set_next (all_gids_to_retain, &gid))
     *(old_gids_sorted.push ()) = gid;
 
+  hb_set_destroy (all_gids_to_retain);
   glyf.fini ();
   cmap.fini ();
 }
commit 66b0a390793ab06692dd49e67baef52a6a7d82aa
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:41:52 2018 -0800

    [subset] Fix memory leak in hb-subset.

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index aff3aecc..3a0ddb03 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -263,14 +263,11 @@ _subset_table (hb_subset_plan_t *plan,
       break;
     default:
       hb_blob_t *source_table = hb_face_reference_table(plan->source, tag);
-      if (likely(source_table))
-      {
+      if (likely (source_table))
         result = hb_subset_plan_add_table(plan, tag, source_table);
-      }
       else
-      {
         result = false;
-      }
+      hb_blob_destroy (source_table);
       break;
   }
   DEBUG_MSG(SUBSET, nullptr, "subset %c%c%c%c %s", HB_UNTAG(tag), result ? "ok" : "FAILED");
commit 0fb8a5ce192025ffd83ae714db932e4b86594ae1
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:37:43 2018 -0800

    [subset] Fix memory leak in cmap subsetting.

diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index 4593152b..02079898 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -602,7 +602,7 @@ struct cmap
                    + 8 // 1 EncodingRecord
                    + 16 // Format 12 header
                    + 12 * groups.len; // SequentialMapGroup records
-    void *dest = calloc (dest_sz, 1);
+    void *dest = malloc (dest_sz);
     if (unlikely (!dest)) {
       DEBUG_MSG(SUBSET, nullptr, "Unable to alloc %lu for cmap subset output", (unsigned long) dest_sz);
       return false;
@@ -618,9 +618,11 @@ struct cmap
     hb_blob_t *cmap_prime = hb_blob_create ((const char *)dest,
                                             dest_sz,
                                             HB_MEMORY_MODE_READONLY,
-                                            /* userdata */ nullptr,
+                                            dest,
                                             free);
-    return hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime);
+    bool result =  hb_subset_plan_add_table (plan, HB_OT_TAG_cmap, cmap_prime);
+    hb_blob_destroy (cmap_prime);
+    return result;
   }
 
   struct accelerator_t
commit 4665aaa19304bdf0362bdfcebcae65feb19a8964
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:36:14 2018 -0800

    [subset] Fix memory leak in hmtx subsetting.

diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh
index 11cc9279..3cd48a62 100644
--- a/src/hb-ot-hmtx-table.hh
+++ b/src/hb-ot-hmtx-table.hh
@@ -105,7 +105,7 @@ struct hmtxvmtx
     /* alloc the new table */
     size_t dest_sz = num_advances * 4
                   + (gids.len - num_advances) * 2;
-    void *dest = (void *) calloc (dest_sz, 1);
+    void *dest = (void *) malloc (dest_sz);
     if (unlikely (!dest))
     {
       return false;
@@ -166,9 +166,11 @@ struct hmtxvmtx
     hb_blob_t *result = hb_blob_create ((const char *)dest,
                                         dest_sz,
                                         HB_MEMORY_MODE_READONLY,
-                                        /* userdata */ nullptr,
+                                        dest,
                                         free);
-    return hb_subset_plan_add_table (plan, T::tableTag, result);
+    bool success = hb_subset_plan_add_table (plan, T::tableTag, result);
+    hb_blob_destroy (result);
+    return success;
   }
 
   struct accelerator_t
commit 5a36b55fba03cd07c9b101f0222b8d189bcd3bbf
Author: Garret Rieger <grieger at google.com>
Date:   Fri Feb 23 15:30:14 2018 -0800

    [subset] Fix memory leak in subset face destroy.

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index b7d3e371..aff3aecc 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -136,6 +136,9 @@ _hb_subset_face_data_destroy (void *user_data)
 {
   hb_subset_face_data_t *data = (hb_subset_face_data_t *) user_data;
 
+  for (int i = 0; i < data->tables.len; i++)
+    hb_blob_destroy (data->tables[i].blob);
+
   data->tables.finish ();
 
   free (data);


More information about the HarfBuzz mailing list