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

Behdad Esfahbod behdad at kemper.freedesktop.org
Wed Feb 7 17:41:26 UTC 2018


 src/Makefile.sources                |    5 +
 src/hb-aat-layout-common-private.hh |    2 
 src/hb-aat-layout-morx-table.hh     |    3 
 src/hb-debug.hh                     |   13 ++++
 src/hb-open-type-private.hh         |    4 -
 src/hb-subset-glyf.cc               |   52 +++++++++++++++++
 src/hb-subset-glyf.hh               |   37 ++++++++++++
 src/hb-subset-plan.cc               |  109 ++++++++++++++++++++++++++++++++++++
 src/hb-subset-plan.hh               |   58 +++++++++++++++++++
 src/hb-subset-private.hh            |   54 +++++++++++++++++
 src/hb-subset.cc                    |   74 ++++++++++++++++--------
 src/hb-subset.h                     |    2 
 test/api/test-subset.c              |    2 
 util/hb-subset.cc                   |   17 +++++
 14 files changed, 405 insertions(+), 27 deletions(-)

New commits:
commit b95aa204ee284c47e63dc1e34b3c5b4bdf9e7ab7
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 7 09:37:06 2018 -0800

    glyph ids to retain should most likely keep the glyph id not the codepoint

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 6bb0513c..470fa03e 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -55,7 +55,7 @@ glyph_ids_to_retain (hb_subset_face_t *face,
     hb_codepoint_t gid;
     if (face->cmap.get_nominal_glyph(cp, &gid)) {
       DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d", cp, gid);
-      hb_set_add(gids, cp);
+      hb_set_add(gids, gid);
     } else {
       DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X", cp);
     }
commit 91428713bd6975b3bbfbdce54701f6aef5457121
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 7 09:35:59 2018 -0800

    Remove \ns leftover from fprintf

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index a9e11fc0..6bb0513c 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -54,10 +54,10 @@ glyph_ids_to_retain (hb_subset_face_t *face,
   while (hb_set_next(codepoints, &cp)) {
     hb_codepoint_t gid;
     if (face->cmap.get_nominal_glyph(cp, &gid)) {
-      DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d\n", cp, gid);
+      DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d", cp, gid);
       hb_set_add(gids, cp);
     } else {
-      DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X\n", cp);
+      DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X", cp);
     }
   }
 
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index dc0d4925..5849efd2 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -155,9 +155,9 @@ hb_subset (hb_subset_profile_t *profile,
   while (hb_set_next(plan->glyphs_to_retain, &old_gid)) {
     hb_codepoint_t new_gid;
     if (hb_subset_plan_new_gid_for_old_id(plan, old_gid, &new_gid)) {
-      DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d\n", old_gid, new_gid);
+      DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d", old_gid, new_gid);
     } else {
-      DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID\n", old_gid);
+      DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID", old_gid);
     }
   }
   // TODO:
commit eb485bb9e90017abaf7dcdd7e39a82125d6807c3
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 7 09:32:36 2018 -0800

    Horrid hack to assign new gids. Use DEBUG_MSG over fprintf

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 5d23f88b..a9e11fc0 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -27,7 +27,24 @@
 #include "hb-subset-plan.hh"
 #include "hb-subset-private.hh"
 
-// TODO(Q1) map from old:new gid
+hb_bool_t
+hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan,
+                                  hb_codepoint_t old_gid,
+                                  hb_codepoint_t *new_gid) {
+  // TODO(Q1) lookup in map from old:new gid
+  // TEMPORARY: just loop over ids to retain and count up
+  hb_codepoint_t current = -1;
+  hb_codepoint_t count = 0;
+  while (hb_set_next(plan->glyphs_to_retain, &current)) {
+    if (old_gid == current) {
+      *new_gid = count;
+      return true;
+    }
+    count++;
+  }
+  return false;
+}
+
 hb_set_t *
 glyph_ids_to_retain (hb_subset_face_t *face,
                      hb_set_t  *codepoints)
@@ -37,13 +54,15 @@ glyph_ids_to_retain (hb_subset_face_t *face,
   while (hb_set_next(codepoints, &cp)) {
     hb_codepoint_t gid;
     if (face->cmap.get_nominal_glyph(cp, &gid)) {
-      // TODO(Q1) a nice way to turn on/off logs
-      fprintf(stderr, "gid for U+%04X is %d\n", cp, gid);
+      DEBUG_MSG(SUBSET, nullptr, "gid for U+%04X is %d\n", cp, gid);
       hb_set_add(gids, cp);
     } else {
-      fprintf(stderr, "Unable to resolve gid for U+%04X\n", cp);
+      DEBUG_MSG(SUBSET, nullptr, "Unable to resolve gid for U+%04X\n", cp);
     }
   }
+
+  // TODO(Q1) expand with glyphs that make up complex glyphs
+  // TODO expand with glyphs reached by G*
   return gids;
 }
 
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 6e94a76f..549c87e2 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -44,6 +44,11 @@ hb_subset_plan_create (hb_subset_face_t    *face,
                        hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
+hb_bool_t
+hb_subset_plan_new_gid_for_old_id(hb_subset_plan_t *plan,
+                                  hb_codepoint_t old_gid,
+                                  hb_codepoint_t *new_gid /* OUT */);
+
 hb_subset_plan_t *
 hb_subset_plan_get_empty ();
 
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index e8b87ca3..dc0d4925 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -151,6 +151,15 @@ hb_subset (hb_subset_profile_t *profile,
 
   hb_subset_plan_t *plan = hb_subset_plan_create (face, profile, input);
 
+  hb_codepoint_t old_gid = -1;
+  while (hb_set_next(plan->glyphs_to_retain, &old_gid)) {
+    hb_codepoint_t new_gid;
+    if (hb_subset_plan_new_gid_for_old_id(plan, old_gid, &new_gid)) {
+      DEBUG_MSG(SUBSET, nullptr, "Remap %d : %d\n", old_gid, new_gid);
+    } else {
+      DEBUG_MSG(SUBSET, nullptr, "Remap %d : DOOM! No new ID\n", old_gid);
+    }
+  }
   // TODO:
   // - Create initial header + table directory
   // - Loop through the set of tables to be kept:
commit 8b80cbb1dd13e2870a956825f5dafc4419b44200
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 7 09:31:31 2018 -0800

    Add a subset debug category

diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index 6c425f7b..c244347b 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -396,6 +396,18 @@ struct hb_no_trace_t {
 #define TRACE_SERIALIZE(this) hb_no_trace_t<bool> trace
 #endif
 
+#ifndef HB_DEBUG_SUBSET
+#define HB_DEBUG_SUBSET (HB_DEBUG+0)
+#endif
+#if HB_DEBUG_SUBSET
+#define TRACE_SUBSET(this) \
+  hb_auto_trace_t<HB_DEBUG_SUBSET, bool> trace \
+  (&c->debug_depth, c->get_name (), this, HB_FUNC, \
+   " ");
+#else
+#define TRACE_SUBSET(this) hb_no_trace_t<bool> trace
+#endif
+
 #ifndef HB_DEBUG_WOULD_APPLY
 #define HB_DEBUG_WOULD_APPLY (HB_DEBUG+0)
 #endif
@@ -415,6 +427,7 @@ struct hb_no_trace_t {
 	HB_DEBUG_COLLECT_GLYPHS + \
 	HB_DEBUG_SANITIZE + \
 	HB_DEBUG_SERIALIZE + \
+  HB_DEBUG_SUBSET + \
 	HB_DEBUG_WOULD_APPLY + \
 	0)
 #endif
commit ee433d36fa544c3138718cc3f796b29e6df8a195
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Wed Feb 7 12:30:18 2018 -0500

    [aat] Set debug lookup_index

diff --git a/src/hb-aat-layout-common-private.hh b/src/hb-aat-layout-common-private.hh
index a421a4cf..e0f59a4a 100644
--- a/src/hb-aat-layout-common-private.hh
+++ b/src/hb-aat-layout-common-private.hh
@@ -713,6 +713,8 @@ struct hb_aat_apply_context_t :
     sanitizer.start_processing ();
   }
 
+  inline void set_lookup_index (unsigned int i) { lookup_index = i; }
+
   inline ~hb_aat_apply_context_t (void)
   {
     sanitizer.end_processing ();
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index f16f6a4a..f8209a60 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -617,6 +617,8 @@ struct Chain
     {
       subtable->apply (c);
       subtable = &StructAfter<ChainSubtable> (*subtable);
+
+      c->set_lookup_index (c->lookup_index + 1);
     }
   }
 
@@ -670,6 +672,7 @@ struct morx
 
   inline void apply (hb_aat_apply_context_t *c) const
   {
+    c->set_lookup_index (0);
     const Chain *chain = chains;
     unsigned int count = chainCount;
     for (unsigned int i = 0; i < count; i++)
commit 38df1ec8e0b457be9140c67e2c5c19153714d90e
Author: Rod Sheeter <rsheeter at google.com>
Date:   Wed Feb 7 07:58:58 2018 -0800

    TEMPORARY: remove HB_INTERNAL from null pool so subset builds again

diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh
index 04e4a4e1..959f743b 100644
--- a/src/hb-open-type-private.hh
+++ b/src/hb-open-type-private.hh
@@ -134,7 +134,9 @@ static inline Type& StructAfter(TObject &X)
 
 #define HB_NULL_POOL_SIZE 264
 static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE.");
-extern HB_INTERNAL const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)];
+// TODO add back HB_INTERNAL once we figure out how to not have that break
+// subset compile
+extern const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)];
 
 /* Generic nul-content Null objects. */
 template <typename Type>
commit 53aa0e95420c5c3bfe8af21cf7956535d35b06e6
Author: Garret Rieger <grieger at google.com>
Date:   Tue Feb 6 17:05:22 2018 -0800

    Add an instance of glyf::accelerator_t to hb-subset-glyf.

diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
index 099f506c..5a3dff6d 100644
--- a/src/hb-subset-glyf.cc
+++ b/src/hb-subset-glyf.cc
@@ -24,6 +24,7 @@
  * Google Author(s): Garret Rieger
  */
 
+#include "hb-ot-glyf-table.hh"
 #include "hb-subset-glyf.hh"
 
 /**
@@ -36,10 +37,16 @@
  **/
 bool
 hb_subset_glyf (hb_subset_plan_t *plan,
-                hb_blob_t *glyf,
-                hb_blob_t **glyf_prime /* OUT */)
+                hb_face_t        *face,
+                hb_blob_t       **glyf_prime /* OUT */)
 {
-  *glyf_prime = hb_blob_get_empty ();
+  OT::glyf::accelerator_t glyf_accelerator;
+  glyf_accelerator.init(face);
+
+  // TODO
 
+  glyf_accelerator.fini();
+
+  *glyf_prime = hb_blob_get_empty ();
   return true;
 }
diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh
index 8bb0d864..fd217e79 100644
--- a/src/hb-subset-glyf.hh
+++ b/src/hb-subset-glyf.hh
@@ -31,7 +31,7 @@
 
 bool
 hb_subset_glyf (hb_subset_plan_t *plan,
-                hb_blob_t        *glyf,
+                hb_face_t        *face,
                 hb_blob_t       **glyf_prime /* OUT */);
 
 #endif /* HB_SUBSET_GLYF_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 7108eb87..e8b87ca3 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -160,15 +160,13 @@ hb_subset (hb_subset_profile_t *profile,
 
   bool success = true;
 
-  hb_blob_t *glyf = hb_face_reference_table (face->face, HB_OT_TAG_glyf);
   hb_blob_t *glyf_prime = nullptr;
-  if (hb_subset_glyf (plan, glyf, &glyf_prime)) {
+  if (hb_subset_glyf (plan, face->face, &glyf_prime)) {
     // TODO: write new glyf to new face.
   } else {
     success = false;
   }
   hb_blob_destroy (glyf_prime);
-  hb_blob_destroy (glyf);
 
   *result = hb_face_reference_blob(face->face);
   hb_subset_plan_destroy (plan);
commit ef62dfed3fc7cfad7f7ce9292cb3bd1616f09384
Author: Rod Sheeter <rsheeter at google.com>
Date:   Tue Feb 6 17:12:17 2018 -0800

    add back assert_pod

diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index eb4147dc..31fceb47 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -45,6 +45,7 @@ struct hb_subset_input_t {
 
 struct hb_subset_face_t {
   hb_object_header_t header;
+  ASSERT_POD ();
 
   hb_face_t *face;
   OT::cmap::accelerator_t cmap;
commit d0ce3c66e2af2785203f7bbb1d4abca5c226045d
Author: Rod Sheeter <rsheeter at google.com>
Date:   Tue Feb 6 16:58:35 2018 -0800

    Resolve codepoints:glyph ids. Does not compile; undefined reference to OT::_hb_NullPool

diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 8111d519..5d23f88b 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -21,17 +21,30 @@
  * 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-subset-plan.hh"
 #include "hb-subset-private.hh"
 
+// TODO(Q1) map from old:new gid
 hb_set_t *
-get_glyph_ids_from_cmap (hb_face_t *face,
-                         hb_set_t  *codepoints)
+glyph_ids_to_retain (hb_subset_face_t *face,
+                     hb_set_t  *codepoints)
 {
-  return hb_set_get_empty ();
+  hb_codepoint_t cp = -1;
+  hb_set_t *gids = hb_set_create();
+  while (hb_set_next(codepoints, &cp)) {
+    hb_codepoint_t gid;
+    if (face->cmap.get_nominal_glyph(cp, &gid)) {
+      // TODO(Q1) a nice way to turn on/off logs
+      fprintf(stderr, "gid for U+%04X is %d\n", cp, gid);
+      hb_set_add(gids, cp);
+    } else {
+      fprintf(stderr, "Unable to resolve gid for U+%04X\n", cp);
+    }
+  }
+  return gids;
 }
 
 /**
@@ -45,12 +58,12 @@ get_glyph_ids_from_cmap (hb_face_t *face,
  * Since: 1.7.5
  **/
 hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t           *face,
+hb_subset_plan_create (hb_subset_face_t    *face,
                        hb_subset_profile_t *profile,
                        hb_subset_input_t   *input)
 {
   hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
-  plan->glyphs_to_retain = get_glyph_ids_from_cmap (face, input->codepoints);
+  plan->glyphs_to_retain = glyph_ids_to_retain (face, input->codepoints);
   return plan;
 }
 
diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh
index 54b1e651..6e94a76f 100644
--- a/src/hb-subset-plan.hh
+++ b/src/hb-subset-plan.hh
@@ -40,7 +40,7 @@ struct hb_subset_plan_t {
 typedef struct hb_subset_plan_t hb_subset_plan_t;
 
 hb_subset_plan_t *
-hb_subset_plan_create (hb_face_t           *face,
+hb_subset_plan_create (hb_subset_face_t    *face,
                        hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
index b38ab0b2..eb4147dc 100644
--- a/src/hb-subset-private.hh
+++ b/src/hb-subset-private.hh
@@ -21,15 +21,21 @@
  * 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
  */
 
 #ifndef HB_SUBSET_PRIVATE_HH
 #define HB_SUBSET_PRIVATE_HH
 
-#include "hb-object-private.hh"
+
 #include "hb-private.hh"
 
+#include "hb-ot.h"
+
+#include "hb-font-private.hh"
+
+#include "hb-ot-cmap-table.hh"
+
 struct hb_subset_input_t {
   hb_object_header_t header;
   ASSERT_POD ();
@@ -37,4 +43,11 @@ struct hb_subset_input_t {
   hb_set_t *codepoints;
 };
 
+struct hb_subset_face_t {
+  hb_object_header_t header;
+
+  hb_face_t *face;
+  OT::cmap::accelerator_t cmap;
+};
+
 #endif /* HB_SUBSET_PRIVATE_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 7b44d516..7108eb87 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -27,6 +27,7 @@
 
 #include "hb-object-private.hh"
 #include "hb-private.hh"
+
 #include "hb-subset-glyf.hh"
 #include "hb-subset-private.hh"
 #include "hb-subset-plan.hh"
@@ -38,14 +39,6 @@ struct hb_subset_profile_t {
   ASSERT_POD ();
 };
 
-struct hb_subset_face_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_face_t *face;
-};
-
-
 /**
  * hb_subset_profile_create:
  *
@@ -119,6 +112,7 @@ hb_subset_face_create (hb_face_t *face)
 
   hb_subset_face_t *subset_face = hb_object_create<hb_subset_face_t> ();
   subset_face->face = hb_face_reference (face);
+  subset_face->cmap.init(face);
 
   return subset_face;
 }
@@ -133,6 +127,7 @@ hb_subset_face_destroy (hb_subset_face_t *subset_face)
 {
   if (!hb_object_destroy (subset_face)) return;
 
+  subset_face->cmap.fini();
   hb_face_destroy(subset_face->face);
   free (subset_face);
 }
@@ -154,7 +149,7 @@ hb_subset (hb_subset_profile_t *profile,
 {
   if (!profile || !input || !face) return false;
 
-  hb_subset_plan_t *plan = hb_subset_plan_create (face->face, profile, input);
+  hb_subset_plan_t *plan = hb_subset_plan_create (face, profile, input);
 
   // TODO:
   // - Create initial header + table directory
commit 6a45e5df24ccc59c5a39bf42323c9b550f49e16d
Author: Garret Rieger <grieger at google.com>
Date:   Tue Feb 6 16:04:09 2018 -0800

    Add skeleton of hb-subset-glyf, call if from hb_subset(...)

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0d5af324..f2821e3d 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -184,11 +184,13 @@ HB_ICU_headers = hb-icu.h
 # Sources for libharfbuzz-subset
 HB_SUBSET_sources = \
 	hb-subset.cc \
+	hb-subset-glyf.cc \
 	hb-subset-plan.cc \
 	$(NULL)
 
 HB_SUBSET_headers = \
 	hb-subset.h \
+	hb-subset-glyf.hh \
 	hb-subset-plan.hh \
 	hb-subset-private.hh \
 	$(NULL)
diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc
new file mode 100644
index 00000000..099f506c
--- /dev/null
+++ b/src/hb-subset-glyf.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2018  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): Garret Rieger
+ */
+
+#include "hb-subset-glyf.hh"
+
+/**
+ * hb_subset_glyf:
+ * Subsets the glyph table according to a provided plan.
+ *
+ * Return value: subsetted glyf table.
+ *
+ * Since: 1.7.5
+ **/
+bool
+hb_subset_glyf (hb_subset_plan_t *plan,
+                hb_blob_t *glyf,
+                hb_blob_t **glyf_prime /* OUT */)
+{
+  *glyf_prime = hb_blob_get_empty ();
+
+  return true;
+}
diff --git a/src/hb-subset-glyf.hh b/src/hb-subset-glyf.hh
new file mode 100644
index 00000000..8bb0d864
--- /dev/null
+++ b/src/hb-subset-glyf.hh
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2018  Google
+ *
+ *  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): Garret Rieger
+ */
+
+#ifndef HB_SUBSET_GLYF_H
+#define HB_SUBSET_GLYF_H
+
+#include "hb-subset-plan.hh"
+
+bool
+hb_subset_glyf (hb_subset_plan_t *plan,
+                hb_blob_t        *glyf,
+                hb_blob_t       **glyf_prime /* OUT */);
+
+#endif /* HB_SUBSET_GLYF_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 6ae3ed7a..7b44d516 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -27,9 +27,12 @@
 
 #include "hb-object-private.hh"
 #include "hb-private.hh"
+#include "hb-subset-glyf.hh"
 #include "hb-subset-private.hh"
 #include "hb-subset-plan.hh"
 
+#include "hb-ot-glyf-table.hh"
+
 struct hb_subset_profile_t {
   hb_object_header_t header;
   ASSERT_POD ();
@@ -160,8 +163,19 @@ hb_subset (hb_subset_profile_t *profile,
   //   - copy the table into the output.
   // - Fix header + table directory.
 
-  *result = hb_face_reference_blob(face->face);
+  bool success = true;
 
+  hb_blob_t *glyf = hb_face_reference_table (face->face, HB_OT_TAG_glyf);
+  hb_blob_t *glyf_prime = nullptr;
+  if (hb_subset_glyf (plan, glyf, &glyf_prime)) {
+    // TODO: write new glyf to new face.
+  } else {
+    success = false;
+  }
+  hb_blob_destroy (glyf_prime);
+  hb_blob_destroy (glyf);
+
+  *result = hb_face_reference_blob(face->face);
   hb_subset_plan_destroy (plan);
-  return true;
+  return success;
 }
commit 31ec3c2ec41161c6ae75bc91d1c237bf2d245e37
Author: Garret Rieger <grieger at google.com>
Date:   Tue Feb 6 15:37:34 2018 -0800

    Create a subset plan in hb_subset.

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index fe821e0a..6ae3ed7a 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -28,6 +28,7 @@
 #include "hb-object-private.hh"
 #include "hb-private.hh"
 #include "hb-subset-private.hh"
+#include "hb-subset-plan.hh"
 
 struct hb_subset_profile_t {
   hb_object_header_t header;
@@ -150,6 +151,17 @@ hb_subset (hb_subset_profile_t *profile,
 {
   if (!profile || !input || !face) return false;
 
+  hb_subset_plan_t *plan = hb_subset_plan_create (face->face, profile, input);
+
+  // TODO:
+  // - Create initial header + table directory
+  // - Loop through the set of tables to be kept:
+  //   - Perform table specific subsetting if defined.
+  //   - copy the table into the output.
+  // - Fix header + table directory.
+
   *result = hb_face_reference_blob(face->face);
+
+  hb_subset_plan_destroy (plan);
   return true;
 }
commit 6c52d94fd11915b76e858bc45633ee60b8c1d8f4
Author: Rod Sheeter <rsheeter at google.com>
Date:   Tue Feb 6 15:31:14 2018 -0800

    capture the set of codepoints passed by --unicodes

diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 2ec0efe3..67cfed19 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -43,6 +43,7 @@ struct subset_consumer_t
              const font_options_t *font_opts)
   {
     font = hb_font_reference (font_opts->get_font ());
+    codepoints = hb_set_create();
   }
 
   void consume_line (const char   *text,
@@ -50,6 +51,16 @@ struct subset_consumer_t
                      const char   *text_before,
                      const char   *text_after)
   {
+    // text appears to be a g_string when set by --unicodes
+    // TODO(Q1) are gunichar and hbcodepoint_t interchangeable?
+    // TODO(Q1) does this only get called with at least 1 codepoint?
+    gchar *c = (gchar *)text;
+    do {
+      gunichar cp = g_utf8_get_char(c);
+      hb_codepoint_t hb_cp = cp; // TODO(Q1) is this safe?
+      hb_set_add(codepoints, hb_cp);
+      g_print ("  U+%04X %" G_GINT32_FORMAT "\n", cp, cp);
+    } while ((c = g_utf8_find_next_char(c, text + text_len)) != nullptr);
   }
 
   hb_bool_t
@@ -80,16 +91,19 @@ struct subset_consumer_t
   {
     // TODO(Q1) check for errors from creates and such
     hb_subset_profile_t *subset_profile = hb_subset_profile_create();
-    hb_subset_input_t *subset_input = hb_subset_input_create (hb_set_get_empty ());
+    hb_subset_input_t *subset_input = hb_subset_input_create (codepoints);
     hb_face_t *face = hb_font_get_face (font);
     hb_subset_face_t *subset_face = hb_subset_face_create(face);
 
+
+
     hb_blob_t *result = nullptr;
     failed = !(hb_subset(subset_profile, subset_input, subset_face, &result)
                && write_file(options.output_file, result));
 
     hb_subset_profile_destroy (subset_profile);
     hb_subset_input_destroy (subset_input);
+    hb_set_destroy (codepoints);
     hb_subset_face_destroy (subset_face);
     hb_blob_destroy (result);
     hb_font_destroy (font);
@@ -101,6 +115,7 @@ struct subset_consumer_t
   private:
   output_options_t options;
   hb_font_t *font;
+  hb_set_t *codepoints;
 };
 
 int
commit 25e9173fe8446735f7e36ec963c7d3554c85631b
Author: Garret Rieger <grieger at google.com>
Date:   Mon Feb 5 17:26:25 2018 -0800

    Make hb-subset-plan private.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 5e1c4e4f..0d5af324 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -189,7 +189,7 @@ HB_SUBSET_sources = \
 
 HB_SUBSET_headers = \
 	hb-subset.h \
-	hb-subset-plan.h \
+	hb-subset-plan.hh \
 	hb-subset-private.hh \
 	$(NULL)
 
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 7da9dae8..8111d519 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -24,15 +24,15 @@
  * Google Author(s): Garret Rieger
  */
 
-#include "hb-private.hh"
+#include "hb-subset-plan.hh"
+#include "hb-subset-private.hh"
 
-#include "hb-object-private.hh"
-
-
-struct hb_subset_plan_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-};
+hb_set_t *
+get_glyph_ids_from_cmap (hb_face_t *face,
+                         hb_set_t  *codepoints)
+{
+  return hb_set_get_empty ();
+}
 
 /**
  * hb_subset_plan_create:
@@ -49,13 +49,17 @@ hb_subset_plan_create (hb_face_t           *face,
                        hb_subset_profile_t *profile,
                        hb_subset_input_t   *input)
 {
-  return hb_object_create<hb_subset_plan_t>();
+  hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
+  plan->glyphs_to_retain = get_glyph_ids_from_cmap (face, input->codepoints);
+  return plan;
 }
 
 hb_subset_plan_t *
-hb_subset_plan_create_empty ()
+hb_subset_plan_get_empty ()
 {
-  return hb_object_create<hb_subset_plan_t>();
+  hb_subset_plan_t *plan = hb_object_create<hb_subset_plan_t> ();
+  plan->glyphs_to_retain = hb_set_get_empty();
+  return plan;
 }
 
 /**
@@ -68,5 +72,6 @@ hb_subset_plan_destroy (hb_subset_plan_t *plan)
 {
   if (!hb_object_destroy (plan)) return;
 
+  hb_set_destroy (plan->glyphs_to_retain);
   free (plan);
 }
diff --git a/src/hb-subset-plan.h b/src/hb-subset-plan.hh
similarity index 86%
rename from src/hb-subset-plan.h
rename to src/hb-subset-plan.hh
index 2fd46ae2..54b1e651 100644
--- a/src/hb-subset-plan.h
+++ b/src/hb-subset-plan.hh
@@ -24,26 +24,30 @@
  * Google Author(s): Garret Rieger
  */
 
-#ifndef HB_H_IN
-#error "Include <hb.h> instead."
-#endif
-
 #ifndef HB_SUBSET_PLAN_H
 #define HB_SUBSET_PLAN_H
 
-HB_BEGIN_DECLS
+#include "hb-private.hh"
+#include "hb-object-private.hh"
+
+struct hb_subset_plan_t {
+  hb_object_header_t header;
+  ASSERT_POD ();
+
+  hb_set_t *glyphs_to_retain;
+};
 
 typedef struct hb_subset_plan_t hb_subset_plan_t;
 
-HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_t *
 hb_subset_plan_create (hb_face_t           *face,
                        hb_subset_profile_t *profile,
                        hb_subset_input_t   *input);
 
-HB_EXTERN hb_subset_plan_t *
-hb_subset_plan_create_empty ();
+hb_subset_plan_t *
+hb_subset_plan_get_empty ();
 
-HB_EXTERN void
+void
 hb_subset_plan_destroy (hb_subset_plan_t *plan);
 
 #endif /* HB_SUBSET_PLAN_PRIVATE_HH */
commit af46a4da5a47dd6e0dd98e1740f18e93c337e689
Author: Garret Rieger <grieger at google.com>
Date:   Mon Feb 5 17:14:46 2018 -0800

    Move definition of hb_subset_input into hb-subset-private.hh.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index eb9cd36a..5e1c4e4f 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -190,6 +190,7 @@ HB_SUBSET_sources = \
 HB_SUBSET_headers = \
 	hb-subset.h \
 	hb-subset-plan.h \
+	hb-subset-private.hh \
 	$(NULL)
 
 HB_GOBJECT_sources = hb-gobject-structs.cc
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
index 705c17f1..7da9dae8 100644
--- a/src/hb-subset-plan.cc
+++ b/src/hb-subset-plan.cc
@@ -40,7 +40,7 @@ struct hb_subset_plan_t {
  * to a provide profile and input. The plan describes
  * which tables and glyphs should be retained.
  *
- * Return value: New plan with default settings.
+ * Return value: New subset plan.
  *
  * Since: 1.7.5
  **/
diff --git a/src/hb-subset-private.hh b/src/hb-subset-private.hh
new file mode 100644
index 00000000..b38ab0b2
--- /dev/null
+++ b/src/hb-subset-private.hh
@@ -0,0 +1,40 @@
+/*
+ * Copyright © 2018  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): Garret Rieger
+ */
+
+#ifndef HB_SUBSET_PRIVATE_HH
+#define HB_SUBSET_PRIVATE_HH
+
+#include "hb-object-private.hh"
+#include "hb-private.hh"
+
+struct hb_subset_input_t {
+  hb_object_header_t header;
+  ASSERT_POD ();
+
+  hb_set_t *codepoints;
+};
+
+#endif /* HB_SUBSET_PRIVATE_HH */
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index f56217f6..fe821e0a 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -25,23 +25,15 @@
  * Google Author(s): Garret Rieger, Rod Sheeter
  */
 
-#include "hb-private.hh"
-
 #include "hb-object-private.hh"
-
+#include "hb-private.hh"
+#include "hb-subset-private.hh"
 
 struct hb_subset_profile_t {
   hb_object_header_t header;
   ASSERT_POD ();
 };
 
-struct hb_subset_input_t {
-  hb_object_header_t header;
-  ASSERT_POD ();
-
-  hb_set_t *codepoints;
-};
-
 struct hb_subset_face_t {
   hb_object_header_t header;
   ASSERT_POD ();
commit 7481f0ce21489d2b19b2e33d05358736ddee20bf
Author: Garret Rieger <grieger at google.com>
Date:   Mon Feb 5 16:05:12 2018 -0800

    Add codepoints to subset input.

diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 62f7f0ad..f56217f6 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -38,6 +38,8 @@ struct hb_subset_profile_t {
 struct hb_subset_input_t {
   hb_object_header_t header;
   ASSERT_POD ();
+
+  hb_set_t *codepoints;
 };
 
 struct hb_subset_face_t {
@@ -82,9 +84,14 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile)
  * Since: 1.7.5
  **/
 hb_subset_input_t *
-hb_subset_input_create()
+hb_subset_input_create (hb_set_t *codepoints)
 {
-  return hb_object_create<hb_subset_input_t>();
+  if (unlikely (!codepoints))
+    codepoints = hb_set_get_empty();
+
+  hb_subset_input_t *input = hb_object_create<hb_subset_input_t>();
+  input->codepoints = hb_set_reference(codepoints);
+  return input;
 }
 
 /**
@@ -97,6 +104,7 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
 {
   if (!hb_object_destroy (subset_input)) return;
 
+  hb_set_destroy (subset_input->codepoints);
   free (subset_input);
 }
 
@@ -108,7 +116,7 @@ hb_subset_input_destroy(hb_subset_input_t *subset_input)
  * Since: 1.7.5
  **/
 hb_subset_face_t *
-hb_subset_face_create(hb_face_t *face)
+hb_subset_face_create (hb_face_t *face)
 {
   if (unlikely (!face))
     face = hb_face_get_empty();
@@ -125,7 +133,7 @@ hb_subset_face_create(hb_face_t *face)
  * Since: 1.7.5
  **/
 void
-hb_subset_face_destroy(hb_subset_face_t *subset_face)
+hb_subset_face_destroy (hb_subset_face_t *subset_face)
 {
   if (!hb_object_destroy (subset_face)) return;
 
@@ -143,10 +151,10 @@ hb_subset_face_destroy(hb_subset_face_t *subset_face)
  * Subsets a font according to provided profile and input.
  **/
 hb_bool_t
-hb_subset(hb_subset_profile_t *profile,
-          hb_subset_input_t *input,
-          hb_subset_face_t *face,
-          hb_blob_t **result /* OUT */)
+hb_subset (hb_subset_profile_t *profile,
+           hb_subset_input_t *input,
+           hb_subset_face_t *face,
+           hb_blob_t **result /* OUT */)
 {
   if (!profile || !input || !face) return false;
 
diff --git a/src/hb-subset.h b/src/hb-subset.h
index 969cf5d2..47127e03 100644
--- a/src/hb-subset.h
+++ b/src/hb-subset.h
@@ -53,7 +53,7 @@ hb_subset_profile_destroy (hb_subset_profile_t *profile);
 typedef struct hb_subset_input_t hb_subset_input_t;
 
 HB_EXTERN hb_subset_input_t *
-hb_subset_input_create ();
+hb_subset_input_create (hb_set_t *codepoints);
 
 HB_EXTERN void
 hb_subset_input_destroy (hb_subset_input_t *subset_input);
diff --git a/test/api/test-subset.c b/test/api/test-subset.c
index 33a1ef29..4841af62 100644
--- a/test/api/test-subset.c
+++ b/test/api/test-subset.c
@@ -42,7 +42,7 @@ test_subset (void)
   hb_face_t *face = hb_face_create(font_blob, 0);
 
   hb_subset_profile_t *profile = hb_subset_profile_create();
-  hb_subset_input_t *input = hb_subset_input_create();
+  hb_subset_input_t *input = hb_subset_input_create (hb_set_get_empty ());
   hb_subset_face_t *subset_face = hb_subset_face_create(face);
 
   hb_blob_t *output;
diff --git a/util/hb-subset.cc b/util/hb-subset.cc
index 27398ab0..2ec0efe3 100644
--- a/util/hb-subset.cc
+++ b/util/hb-subset.cc
@@ -80,7 +80,7 @@ struct subset_consumer_t
   {
     // TODO(Q1) check for errors from creates and such
     hb_subset_profile_t *subset_profile = hb_subset_profile_create();
-    hb_subset_input_t *subset_input = hb_subset_input_create();
+    hb_subset_input_t *subset_input = hb_subset_input_create (hb_set_get_empty ());
     hb_face_t *face = hb_font_get_face (font);
     hb_subset_face_t *subset_face = hb_subset_face_create(face);
 
commit 1cfe650f020cf440bf157daa9907bffd6e35bd7a
Author: Garret Rieger <grieger at google.com>
Date:   Mon Feb 5 15:22:30 2018 -0800

    Add a basic sketch of hb-subset-plan.

diff --git a/src/Makefile.sources b/src/Makefile.sources
index 0b9beb96..eb9cd36a 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -184,10 +184,12 @@ HB_ICU_headers = hb-icu.h
 # Sources for libharfbuzz-subset
 HB_SUBSET_sources = \
 	hb-subset.cc \
+	hb-subset-plan.cc \
 	$(NULL)
 
 HB_SUBSET_headers = \
 	hb-subset.h \
+	hb-subset-plan.h \
 	$(NULL)
 
 HB_GOBJECT_sources = hb-gobject-structs.cc
diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc
new file mode 100644
index 00000000..705c17f1
--- /dev/null
+++ b/src/hb-subset-plan.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright © 2018  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): Garret Rieger
+ */
+
+#include "hb-private.hh"
+
+#include "hb-object-private.hh"
+
+
+struct hb_subset_plan_t {
+  hb_object_header_t header;
+  ASSERT_POD ();
+};
+
+/**
+ * hb_subset_plan_create:
+ * Computes a plan for subsetting the supplied face according
+ * to a provide profile and input. The plan describes
+ * which tables and glyphs should be retained.
+ *
+ * Return value: New plan with default settings.
+ *
+ * Since: 1.7.5
+ **/
+hb_subset_plan_t *
+hb_subset_plan_create (hb_face_t           *face,
+                       hb_subset_profile_t *profile,
+                       hb_subset_input_t   *input)
+{
+  return hb_object_create<hb_subset_plan_t>();
+}
+
+hb_subset_plan_t *
+hb_subset_plan_create_empty ()
+{
+  return hb_object_create<hb_subset_plan_t>();
+}
+
+/**
+ * hb_subset_plan_destroy:
+ *
+ * Since: 1.7.5
+ **/
+void
+hb_subset_plan_destroy (hb_subset_plan_t *plan)
+{
+  if (!hb_object_destroy (plan)) return;
+
+  free (plan);
+}
diff --git a/src/hb-subset-plan.h b/src/hb-subset-plan.h
new file mode 100644
index 00000000..2fd46ae2
--- /dev/null
+++ b/src/hb-subset-plan.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2018  Google
+ *
+ *  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): Garret Rieger
+ */
+
+#ifndef HB_H_IN
+#error "Include <hb.h> instead."
+#endif
+
+#ifndef HB_SUBSET_PLAN_H
+#define HB_SUBSET_PLAN_H
+
+HB_BEGIN_DECLS
+
+typedef struct hb_subset_plan_t hb_subset_plan_t;
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_create (hb_face_t           *face,
+                       hb_subset_profile_t *profile,
+                       hb_subset_input_t   *input);
+
+HB_EXTERN hb_subset_plan_t *
+hb_subset_plan_create_empty ();
+
+HB_EXTERN void
+hb_subset_plan_destroy (hb_subset_plan_t *plan);
+
+#endif /* HB_SUBSET_PLAN_PRIVATE_HH */


More information about the HarfBuzz mailing list