[subset] GSUB5/GPOS7 Contextual Subst/Pos Subtbale Subsetting support
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 0bca97f..f52a948 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -1144,7 +1144,7 @@
 struct LookupRecord
 {
   LookupRecord* copy (hb_serialize_context_t *c,
-		      const hb_map_t         *lookup_map)
+		      const hb_map_t         *lookup_map) const
   {
     TRACE_SERIALIZE (this);
     auto *out = c->embed (*this);
@@ -1450,6 +1450,47 @@
     return_trace (context_apply_lookup (c, inputCount, inputZ.arrayZ, lookupCount, lookupRecord.arrayZ, lookup_context));
   }
 
+  bool serialize (hb_serialize_context_t *c,
+		  const hb_map_t *input_mapping, /* old->new glyphid or class mapping */
+		  const hb_map_t *lookup_map) const
+  {
+    TRACE_SERIALIZE (this);
+    auto *out = c->start_embed (this);
+    if (unlikely (!c->extend_min (out))) return_trace (false);
+
+    out->inputCount = inputCount;
+    out->lookupCount = lookupCount;
+
+    const hb_array_t<const HBUINT16> input = inputZ.as_array (inputCount - 1);
+    for (const auto org : input)
+    {
+      HBUINT16 d;
+      d = input_mapping->get (org);
+      c->copy (d);
+    }
+
+    const UnsizedArrayOf<LookupRecord> &lookupRecord = StructAfter<UnsizedArrayOf<LookupRecord>>
+                                                       (inputZ.as_array ((inputCount ? inputCount - 1 : 0)));
+    for (unsigned i = 0; i < (unsigned) lookupCount; i++)
+      c->copy (lookupRecord[i], lookup_map);
+
+    return_trace (true);
+  }
+
+  bool subset (hb_subset_context_t *c,
+	       const hb_map_t *lookup_map,
+	       const hb_map_t *klass_map = nullptr) const
+  {
+    TRACE_SUBSET (this);
+
+    const hb_array_t<const HBUINT16> input = inputZ.as_array ((inputCount ? inputCount - 1 : 0));
+    if (!input.length) return_trace (false);
+
+    const hb_map_t *mapping = klass_map == nullptr ? c->plan->glyph_map : klass_map;
+    if (!hb_all (input, mapping)) return_trace (false);
+    return_trace (serialize (c->serializer, mapping, lookup_map));
+  }
+
   public:
   bool sanitize (hb_sanitize_context_t *c) const
   {
@@ -1546,6 +1587,36 @@
     ;
   }
 
+  bool subset (hb_subset_context_t *c,
+	       const hb_map_t *lookup_map,
+	       const hb_map_t *klass_map = nullptr) const
+  {
+    TRACE_SUBSET (this);
+
+    auto snap = c->serializer->snapshot ();
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    for (const OffsetTo<Rule>& _ : rule)
+    {
+      if (!_) continue;
+      auto *o = out->rule.serialize_append (c->serializer);
+      if (unlikely (!o)) continue;
+
+      auto o_snap = c->serializer->snapshot ();
+      if (!o->serialize_subset (c, _, this, lookup_map, klass_map))
+      {
+        out->rule.pop ();
+        c->serializer->revert (o_snap);
+      }
+    }
+
+    bool ret = bool (out->rule);
+    if (!ret) c->serializer->revert (snap);
+
+    return_trace (ret);
+  }
+
   bool sanitize (hb_sanitize_context_t *c) const
   {
     TRACE_SANITIZE (this);
@@ -1648,8 +1719,26 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    const hb_set_t &glyphset = *c->plan->glyphset ();
+    const hb_map_t &glyph_map = *c->plan->glyph_map;
+
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+
+    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + hb_zip (this+coverage, ruleSet)
+    | hb_filter (glyphset, hb_first)
+    | hb_filter (subset_offset_array (c, out->ruleSet, this, lookup_map), hb_second)
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+
+    out->coverage.serialize (c->serializer, out)
+                 .serialize (c->serializer, new_coverage.iter ());
+    return_trace (bool (new_coverage));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1774,8 +1863,45 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    auto *out = c->serializer->start_embed (*this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+    out->format = format;
+    if (unlikely (!out->coverage.serialize_subset (c, coverage, this)))
+      return_trace (false);
+
+    hb_map_t klass_map;
+    out->classDef.serialize_subset (c, classDef, this, &klass_map);
+
+    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+    bool ret = true;
+    unsigned non_zero_index = 0, index = 0;
+    for (const hb_pair_t<unsigned, const OffsetTo<RuleSet>&>& _ : + hb_enumerate (ruleSet)
+								  | hb_filter (klass_map, hb_first))
+    {
+      auto *o = out->ruleSet.serialize_append (c->serializer);
+      if (unlikely (!o))
+      {
+        ret = false;
+        break;
+      }
+
+      if (o->serialize_subset (c, _.second, this, lookup_map, &klass_map))
+        non_zero_index = index;
+
+      index++;
+    }
+
+    if (!ret) return_trace (ret);
+
+    //prune empty trailing ruleSets
+    --index;
+    while (index > non_zero_index)
+    {
+      out->ruleSet.pop ();
+      index--;
+    }
+
+    return_trace (bool (out->ruleSet));
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
@@ -1886,8 +2012,28 @@
   bool subset (hb_subset_context_t *c) const
   {
     TRACE_SUBSET (this);
-    // TODO(subset)
-    return_trace (false);
+    auto *out = c->serializer->start_embed (this);
+    if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+    out->format = format;
+    out->glyphCount = glyphCount;
+    out->lookupCount = lookupCount;
+
+    const hb_array_t<const OffsetTo<Coverage>> coverages = coverageZ.as_array (glyphCount);
+
+    for (const OffsetTo<Coverage>& offset : coverages)
+    {
+      auto *o = c->serializer->allocate_size<OffsetTo<Coverage>> (OffsetTo<Coverage>::static_size);
+      if (unlikely (!o)) return_trace (false);
+      if (!o->serialize_subset (c, offset, this)) return_trace (false);
+    }
+
+    const LookupRecord *lookupRecord = &StructAfter<LookupRecord> (coverageZ.as_array (glyphCount));
+    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
+    for (unsigned i = 0; i < (unsigned) lookupCount; i++)
+      c->serializer->copy (lookupRecord[i], lookup_map);
+    
+    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/src/hb-subset.cc b/src/hb-subset.cc
index a03b41f..3112739 100644
--- a/src/hb-subset.cc
+++ b/src/hb-subset.cc
@@ -89,7 +89,7 @@
   retry:
     hb_serialize_context_t serializer ((void *) buf, buf_size);
     serializer.start_serialize<TableType> ();
-    hb_subset_context_t c (source_blob, plan, &serializer);
+    hb_subset_context_t c (source_blob, plan, &serializer, tag);
     bool needed = table->subset (&c);
     if (serializer.ran_out_of_room)
     {
diff --git a/src/hb-subset.hh b/src/hb-subset.hh
index a3dfd3b..dc86f15 100644
--- a/src/hb-subset.hh
+++ b/src/hb-subset.hh
@@ -57,14 +57,17 @@
   hb_blob_t *source_blob;
   hb_subset_plan_t *plan;
   hb_serialize_context_t *serializer;
+  hb_tag_t table_tag;
   unsigned int debug_depth;
 
   hb_subset_context_t (hb_blob_t *source_blob_,
 		       hb_subset_plan_t *plan_,
-		       hb_serialize_context_t *serializer_) :
-			source_blob (source_blob_),
+		       hb_serialize_context_t *serializer_,
+		       hb_tag_t table_tag_) :
+		        source_blob (source_blob_),
 			plan (plan_),
 			serializer (serializer_),
+			table_tag (table_tag_),
 			debug_depth (0) {}
 };
 
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 32efc0b..05ad13b 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -21,6 +21,7 @@
 	expected/layout.gsub3 \
 	expected/layout.gsub6 \
 	expected/layout.gdef \
+	expected/layout.context \
 	expected/cmap \
 	expected/cmap14 \
 	expected/sbix \
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index f50e6ae..ea250f3 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -21,6 +21,7 @@
 	tests/layout.gsub3.tests \
 	tests/layout.gsub6.tests \
 	tests/layout.gdef.tests \
+	tests/layout.context.tests \
 	$(NULL)
 
 XFAIL_TESTS = \
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..41f4ff4
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf
new file mode 100644
index 0000000..67e87dc
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf
new file mode 100644
index 0000000..47fe5d0
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41.otf
new file mode 100644
index 0000000..48e0524
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..eff7821
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..b1a0b3c
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42.otf
new file mode 100644
index 0000000..b070e2b
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,43.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,43.otf
new file mode 100644
index 0000000..a2715ef
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41.otf
new file mode 100644
index 0000000..c94a78f
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..eff7821
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..520a373
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf
new file mode 100644
index 0000000..b9e8c99
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf
new file mode 100644
index 0000000..52fcc8c
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41.otf
new file mode 100644
index 0000000..ae6325f
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..339bfe8
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..3deac41
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42.otf
new file mode 100644
index 0000000..5f0ded3
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,43.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,43.otf
new file mode 100644
index 0000000..5c14c1b
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41.otf
new file mode 100644
index 0000000..2152ca7
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..339bfe8
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..ab85997
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42.otf
new file mode 100644
index 0000000..ca3494f
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,43.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,43.otf
new file mode 100644
index 0000000..58c9bf4
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41.otf
new file mode 100644
index 0000000..84bae1a
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..5588fd3
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..7c11995
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42.otf
new file mode 100644
index 0000000..2ee02fe
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,43.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,43.otf
new file mode 100644
index 0000000..6e881ee
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41.otf
new file mode 100644
index 0000000..a4c8c42
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..5588fd3
--- /dev/null
+++ b/test/subset/data/expected/layout.context/gpos_context3_simple_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_context1_multiple_subrules_f1.otf b/test/subset/data/fonts/gpos_context1_multiple_subrules_f1.otf
new file mode 100644
index 0000000..fc84d1f
--- /dev/null
+++ b/test/subset/data/fonts/gpos_context1_multiple_subrules_f1.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_context2_multiple_subrules_f1.otf b/test/subset/data/fonts/gpos_context2_multiple_subrules_f1.otf
new file mode 100644
index 0000000..c5afd3e
--- /dev/null
+++ b/test/subset/data/fonts/gpos_context2_multiple_subrules_f1.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_context3_simple_f1.otf b/test/subset/data/fonts/gpos_context3_simple_f1.otf
new file mode 100644
index 0000000..fad7550
--- /dev/null
+++ b/test/subset/data/fonts/gpos_context3_simple_f1.otf
Binary files differ
diff --git a/test/subset/data/tests/layout.context.tests b/test/subset/data/tests/layout.context.tests
new file mode 100644
index 0000000..9833395
--- /dev/null
+++ b/test/subset/data/tests/layout.context.tests
@@ -0,0 +1,15 @@
+FONTS:
+gpos_context1_multiple_subrules_f1.otf
+gpos_context2_multiple_subrules_f1.otf
+gpos_context3_simple_f1.otf
+
+PROFILES:
+keep-layout.txt
+keep-layout-retain-gids.txt
+
+SUBSETS:
+A
+AB
+AC
+ABC
+*