[subset] GPOS 5 MarkToLigature subsetting support
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh
index 2217d29..63989ba 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -544,8 +544,7 @@
 	    hb_requires (hb_is_iterator (Iterator))>
   bool serialize (hb_serialize_context_t *c,
 		  unsigned                num_rows,
-		  AnchorMatrix const     *offset_matrix,
-		  const hb_map_t         *layout_variation_idx_map,
+		  const AnchorMatrix     *offset_matrix,
 		  Iterator                index_iter)
   {
     TRACE_SERIALIZE (this);
@@ -566,6 +565,27 @@
     return_trace (true);
   }
 
+  bool subset (hb_subset_context_t *c,
+	       unsigned cols,
+	       const hb_map_t *klass_mapping) const
+  {
+    TRACE_SUBSET (this);
+    auto *out = c->serializer->start_embed (*this);
+
+    hb_vector_t<unsigned> indexes;
+    for (unsigned row : + hb_range ((unsigned) rows))
+    {
+      + hb_range (cols)
+      | hb_filter (klass_mapping)
+      | hb_map ([=] (const unsigned col) { return row * cols + col; })
+      | hb_sink (indexes)
+      ;
+    }
+
+    out->serialize (c->serializer, (unsigned) rows, this, indexes.iter ());
+    return_trace (true);
+  }
+
   bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
   {
     TRACE_SANITIZE (this);
@@ -2025,10 +2045,30 @@
 					 * mark-minor--
 					 * ordered by class--zero-based. */
 
-typedef OffsetListOf<LigatureAttach> LigatureArray;
-					/* Array of LigatureAttach
-					 * tables ordered by
-					 * LigatureCoverage Index */
+/* Array of LigatureAttach tables ordered by LigatureCoverage Index */
+struct LigatureArray : OffsetListOf<LigatureAttach>
+{
+  template <typename Iterator,
+	    hb_requires (hb_is_iterator (Iterator))>
+  bool subset (hb_subset_context_t    *c,
+	       unsigned                cols,
+	       const hb_map_t         *klass_mapping,
+	       const LigatureArray    &src_lig_array,
+	       Iterator                ligature_iter)
+  {
+    TRACE_SERIALIZE (this);
+    if (!ligature_iter.len ()) return_trace (false);
+    if (unlikely (!c->serializer->extend_min ((*this))))  return_trace (false);
+
+    for (unsigned i : ligature_iter)
+    {
+      auto *out = serialize_append (c->serializer);
+      if (unlikely (!out)) break;
+      out->serialize_subset (c, src_lig_array.arrayZ[i], &src_lig_array, this, cols, klass_mapping);
+    }
+    return_trace (this->len);
+  }
+};
 
 struct MarkLigPosFormat1
 {
@@ -2130,8 +2170,61 @@
   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;
+
+    hb_map_t klass_mapping;
+    Markclass_closure_and_remap_indexes (this+markCoverage, this+markArray, glyphset, &klass_mapping);
+    
+    if (!klass_mapping.get_population ()) return_trace (false);
+    out->classCount = klass_mapping.get_population ();
+
+    auto mark_iter =
+    + hb_zip (this+markCoverage, this+markArray)
+    | hb_filter (glyphset, hb_first)
+    ;
+
+    hb_sorted_vector_t<hb_codepoint_t> new_coverage;
+    + mark_iter
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+
+    if (!out->markCoverage.serialize (c->serializer, out)
+			  .serialize (c->serializer, new_coverage.iter ()))
+      return_trace (false);
+
+    out->markArray.serialize (c->serializer, out)
+		  .serialize (c->serializer, &klass_mapping, &(this+markArray), + mark_iter
+										| hb_map (hb_second));
+    
+    unsigned ligcount = (this+ligatureArray).len;
+    auto ligature_iter =
+    + hb_zip (this+ligatureCoverage, hb_range (ligcount))
+    | hb_filter (glyphset, hb_first)
+    ;
+
+    new_coverage.reset ();
+    + ligature_iter
+    | hb_map (hb_first)
+    | hb_map (glyph_map)
+    | hb_sink (new_coverage)
+    ;
+
+    if (!out->ligatureCoverage.serialize (c->serializer, out)
+			      .serialize (c->serializer, new_coverage.iter ()))
+      return_trace (false);
+
+    out->ligatureArray.serialize (c->serializer, out)
+		      .subset (c, (unsigned) classCount, &klass_mapping, this+ligatureArray, + ligature_iter
+											     | hb_map (hb_second));
+
+    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const