[subset] ChainContext subsetting fix: add lookup index remapping
diff --git a/src/hb-ot-layout-gsubgpos.hh b/src/hb-ot-layout-gsubgpos.hh
index 62b3b0a..2c06312 100644
--- a/src/hb-ot-layout-gsubgpos.hh
+++ b/src/hb-ot-layout-gsubgpos.hh
@@ -2323,6 +2323,7 @@
   }
 
   ChainRule* copy (hb_serialize_context_t *c,
+		   const hb_map_t *lookup_map,
 		   const hb_map_t *backtrack_map,
 		   const hb_map_t *input_map = nullptr,
 		   const hb_map_t *lookahead_map = nullptr) const
@@ -2345,13 +2346,19 @@
     serialize_array (c, lookahead.len, + lookahead.iter ()
 				       | hb_map (mapping));
 
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-    c->copy (lookup);
+    const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    HBUINT16 lookupCount;
+    lookupCount = lookupRecord.len;
+    if (!c->copy (lookupCount)) return_trace (nullptr);
+
+    for (unsigned i = 0; i < (unsigned) lookupCount; i++)
+      if (!c->copy (lookupRecord[i], lookup_map)) return_trace (nullptr);
 
     return_trace (out);
   }
 
   bool subset (hb_subset_context_t *c,
+	       const hb_map_t *lookup_map,
 	       const hb_map_t *backtrack_map = nullptr,
 	       const hb_map_t *input_map = nullptr,
 	       const hb_map_t *lookahead_map = nullptr) const
@@ -2369,7 +2376,7 @@
 	  !hb_all (lookahead, glyphset))
 	return_trace (false);
 
-      copy (c->serializer, c->plan->glyph_map);
+      copy (c->serializer, lookup_map, c->plan->glyph_map);
     }
     else
     {
@@ -2378,7 +2385,7 @@
 	  !hb_all (lookahead, lookahead_map))
 	return_trace (false);
 
-      copy (c->serializer, backtrack_map, input_map, lookahead_map);
+      copy (c->serializer, lookup_map, backtrack_map, input_map, lookahead_map);
     }
 
     return_trace (true);
@@ -2479,6 +2486,7 @@
   }
 
   bool subset (hb_subset_context_t *c,
+	       const hb_map_t *lookup_map,
 	       const hb_map_t *backtrack_klass_map = nullptr,
 	       const hb_map_t *input_klass_map = nullptr,
 	       const hb_map_t *lookahead_klass_map = nullptr) const
@@ -2497,6 +2505,7 @@
 
       auto o_snap = c->serializer->snapshot ();
       if (!o->serialize_subset (c, _, this,
+				lookup_map,
 				backtrack_klass_map,
 				input_klass_map,
 				lookahead_klass_map))
@@ -2621,10 +2630,11 @@
     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), hb_second)
+    | 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)
@@ -2795,8 +2805,9 @@
     hb_map_t lookahead_klass_map;
     out->lookaheadClassDef.serialize_subset (c, lookaheadClassDef, this, &lookahead_klass_map);
 
-    hb_vector_t<unsigned> rulesets;
+    unsigned non_zero_index = 0, index = 0;
     bool ret = true;
+    const hb_map_t *lookup_map = c->table_tag == HB_OT_TAG_GSUB ? c->plan->gsub_lookups : c->plan->gpos_lookups;
     for (const OffsetTo<ChainRuleSet>& _ : + hb_enumerate (ruleSet)
 					   | hb_filter (input_klass_map, hb_first)
 					   | hb_map (hb_second))
@@ -2807,24 +2818,24 @@
 	ret = false;
 	break;
       }
-      if (!o->serialize_subset (c, _, this,
-				&backtrack_klass_map,
-				&input_klass_map,
-				&lookahead_klass_map))
-      {
-	rulesets.push (0);
-      }
-      else rulesets.push (1);
+      if (o->serialize_subset (c, _, this,
+			       lookup_map,
+			       &backtrack_klass_map,
+			       &input_klass_map,
+			       &lookahead_klass_map))
+        non_zero_index = index;
+
+      index++;
     }
 
     if (!ret) return_trace (ret);
 
     //prune empty trailing ruleSets
-    unsigned count = rulesets.length;
-    while (count > 0 && rulesets[count-1] == 0)
+    --index;
+    while (index > non_zero_index)
     {
       out->ruleSet.pop ();
-      count--;
+      index--;
     }
 
     return_trace (bool (out->ruleSet));
@@ -3014,8 +3025,16 @@
     if (!serialize_coverage_offsets (c, lookahead.iter (), this))
       return_trace (false);
 
-    const ArrayOf<LookupRecord> &lookup = StructAfter<ArrayOf<LookupRecord>> (lookahead);
-    return_trace (c->serializer->copy (lookup));
+    const ArrayOf<LookupRecord> &lookupRecord = StructAfter<ArrayOf<LookupRecord>> (lookahead);
+    HBUINT16 lookupCount;
+    lookupCount = lookupRecord.len;
+    if (!c->serializer->copy (lookupCount)) return_trace (false);
+
+    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++)
+      if (!c->serializer->copy (lookupRecord[i], lookup_map)) return_trace (false);
+    
+    return_trace (true);
   }
 
   bool sanitize (hb_sanitize_context_t *c) const
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index 61e5594..ef915b1 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -18,6 +18,7 @@
 	expected/layout.gpos3 \
 	expected/layout.gpos4 \
 	expected/layout.gpos6 \
+	expected/layout.gpos8 \
 	expected/layout.gsub3 \
 	expected/layout.gsub6 \
 	expected/layout.gdef \
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index a42321f..5a63081 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -18,6 +18,7 @@
 	tests/layout.gpos3.tests \
 	tests/layout.gpos4.tests \
 	tests/layout.gpos6.tests \
+	tests/layout.gpos8.tests \
 	tests/layout.gsub3.tests \
 	tests/layout.gsub6.tests \
 	tests/layout.gdef.tests \
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf
new file mode 100644
index 0000000..61f41df
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..3190942
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..3fabe71
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.30,31,32,33.otf
new file mode 100644
index 0000000..34966da
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..206062b
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..3fabe71
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining1_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf
new file mode 100644
index 0000000..4c3af13
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..4a10c76
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..53dccf9
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.30,31,32,33.otf
new file mode 100644
index 0000000..7130a4c
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..b64fb14
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..53dccf9
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining2_multiple_subrules_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.30,31,32,33.otf
new file mode 100644
index 0000000..9bc50e5
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..66b1941
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..e7cc68d
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.30,31,32,33.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.30,31,32,33.otf
new file mode 100644
index 0000000..55f3f66
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.30,31,32,33.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..5f69d87
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..e7cc68d
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos8/gpos_chaining3_simple_f1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_chaining1_multiple_subrules_f1.otf b/test/subset/data/fonts/gpos_chaining1_multiple_subrules_f1.otf
new file mode 100644
index 0000000..721115e
--- /dev/null
+++ b/test/subset/data/fonts/gpos_chaining1_multiple_subrules_f1.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_chaining2_multiple_subrules_f1.otf b/test/subset/data/fonts/gpos_chaining2_multiple_subrules_f1.otf
new file mode 100644
index 0000000..ef7f635
--- /dev/null
+++ b/test/subset/data/fonts/gpos_chaining2_multiple_subrules_f1.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos_chaining3_simple_f1.otf b/test/subset/data/fonts/gpos_chaining3_simple_f1.otf
new file mode 100644
index 0000000..b6f1863
--- /dev/null
+++ b/test/subset/data/fonts/gpos_chaining3_simple_f1.otf
Binary files differ
diff --git a/test/subset/data/tests/layout.gpos8.tests b/test/subset/data/tests/layout.gpos8.tests
new file mode 100644
index 0000000..1e05791
--- /dev/null
+++ b/test/subset/data/tests/layout.gpos8.tests
@@ -0,0 +1,13 @@
+FONTS:
+gpos_chaining1_multiple_subrules_f1.otf
+gpos_chaining2_multiple_subrules_f1.otf
+gpos_chaining3_simple_f1.otf
+
+PROFILES:
+keep-layout.txt
+keep-layout-retain-gids.txt
+
+SUBSETS:
+0123
+ABC
+*