[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
+*