[subset] Keep head when no glyf table
diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh
index d65a86b..c42a125 100644
--- a/src/hb-ot-cff1-table.hh
+++ b/src/hb-ot-cff1-table.hh
@@ -27,7 +27,6 @@
 #ifndef HB_OT_CFF1_TABLE_HH
 #define HB_OT_CFF1_TABLE_HH
 
-#include "hb-ot-head-table.hh"
 #include "hb-ot-cff-common.hh"
 #include "hb-subset-cff1.hh"
 
@@ -1378,16 +1377,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    bool success = true;
-    if (hb_subset_cff1 (c)) {
-      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (c->plan->source);
-      success = success && head_blob && c->plan->add_table (HB_OT_TAG_head, head_blob);
-      hb_blob_destroy (head_blob);
-    } else {
-      success = false;
-    }
-
-    return success;
+    return hb_subset_cff1 (c);
   }
 
   protected:
diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh
index e4663d4..457c99c 100644
--- a/src/hb-ot-cff2-table.hh
+++ b/src/hb-ot-cff2-table.hh
@@ -27,7 +27,6 @@
 #ifndef HB_OT_CFF2_TABLE_HH
 #define HB_OT_CFF2_TABLE_HH
 
-#include "hb-ot-head-table.hh"
 #include "hb-ot-cff-common.hh"
 #include "hb-subset-cff2.hh"
 
@@ -541,16 +540,7 @@
 
   bool subset (hb_subset_context_t *c) const
   {
-    bool success = true;
-    if (hb_subset_cff2 (c)) {
-      hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (c->plan->source);
-      success = success && head_blob && c->plan->add_table (HB_OT_TAG_head, head_blob);
-      hb_blob_destroy (head_blob);
-    } else {
-      success = false;
-    }
-
-    return success;
+    return hb_subset_cff2 (c);
   }
 
   public:
diff --git a/src/hb-ot-head-table.hh b/src/hb-ot-head-table.hh
index 3c0bb3d..5613a96 100644
--- a/src/hb-ot-head-table.hh
+++ b/src/hb-ot-head-table.hh
@@ -54,6 +54,18 @@
     return 16 <= upem && upem <= 16384 ? upem : 1000;
   }
 
+  bool serialize (hb_serialize_context_t *c) const
+  {
+    TRACE_SERIALIZE (this);
+    return_trace ((bool) c->embed (this));
+  }
+
+  bool subset (hb_subset_context_t *c) const
+  {
+    TRACE_SUBSET (this);
+    return_trace (serialize (c->serializer));
+  }
+
   enum mac_style_flag_t {
     BOLD	= 1u<<0,
     ITALIC	= 1u<<1,
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index 5a07bc8..edc14d4 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -134,6 +134,53 @@
 }
 
 static bool
+_is_table_present (hb_face_t *source,
+                   hb_tag_t tag)
+{
+  unsigned tables = hb_face_get_table_tags (source, 0, nullptr, nullptr);
+  hb_vector_t<uint32_t> tags;
+  tags.resize (tables);
+  hb_face_get_table_tags (source, 0, &tables, tags.arrayZ);
+  for (unsigned int i = 0; i < tables; i++) {
+    if (tags[i] == tag)
+      return true;
+  }
+  return false;
+}
+
+static bool
+_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
+{
+  if (plan->drop_tables->has (tag))
+    return true;
+
+  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;
+
+#ifdef HB_NO_SUBSET_LAYOUT
+    // Drop Layout Tables if requested.
+    case HB_OT_TAG_GDEF:
+    case HB_OT_TAG_GPOS:
+    case HB_OT_TAG_GSUB:
+    case HB_TAG ('m', 'o', 'r', 'x'):
+    case HB_TAG ('m', 'o', 'r', 't'):
+    case HB_TAG ('k', 'e', 'r', 'x'):
+    case HB_TAG ('k', 'e', 'r', 'n'):
+      return true;
+#endif
+
+    default:
+      return false;
+  }
+}
+
+static bool
 _subset_table (hb_subset_plan_t *plan,
 	       hb_tag_t          tag)
 {
@@ -149,11 +196,15 @@
     case HB_OT_TAG_name:
       result = _subset<const OT::name> (plan);
       break;
-    case HB_OT_TAG_head:
-      // TODO that won't work well if there is no glyf
-      DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
-      result = true;
+    case HB_OT_TAG_head: {
+      if (_is_table_present (plan->source, HB_OT_TAG_glyf) && !_should_drop_table (plan, HB_OT_TAG_glyf))
+      {
+        DEBUG_MSG(SUBSET, nullptr, "skip head, handled by glyf");
+        return true;
+      }
+      result = _subset<const OT::head> (plan);
       break;
+    }
     case HB_OT_TAG_hhea:
       DEBUG_MSG(SUBSET, nullptr, "skip hhea handled by hmtx");
       return true;
@@ -234,38 +285,6 @@
   return result;
 }
 
-static bool
-_should_drop_table (hb_subset_plan_t *plan, hb_tag_t tag)
-{
-  if (plan->drop_tables->has (tag))
-    return true;
-
-  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;
-
-#ifdef HB_NO_SUBSET_LAYOUT
-    // Drop Layout Tables if requested.
-    case HB_OT_TAG_GDEF:
-    case HB_OT_TAG_GPOS:
-    case HB_OT_TAG_GSUB:
-    case HB_TAG ('m', 'o', 'r', 'x'):
-    case HB_TAG ('m', 'o', 'r', 't'):
-    case HB_TAG ('k', 'e', 'r', 'x'):
-    case HB_TAG ('k', 'e', 'r', 'n'):
-      return true;
-#endif
-
-    default:
-      return false;
-  }
-}
-
 /**
  * hb_subset:
  * @source: font face data to be subset.