Merge pull request #2701 from googlefonts/Mark-To-Ligature_grieger
[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 131ded2..b2b2f0e 100644
--- a/src/hb-ot-layout-gpos-table.hh
+++ b/src/hb-ot-layout-gpos-table.hh
@@ -566,6 +566,26 @@
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);
+
+ auto indexes =
+ + hb_range (rows * cols)
+ | hb_filter ([=] (unsigned index) { return klass_mapping->has (index % cols); })
+ ;
+
+ out->serialize (c->serializer,
+ (unsigned) rows,
+ this,
+ c->plan->layout_variation_idx_map,
+ indexes);
+ return_trace (true);
+ }
+
bool sanitize (hb_sanitize_context_t *c, unsigned int cols) const
{
TRACE_SANITIZE (this);
@@ -2025,10 +2045,40 @@
* 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,
+ Iterator coverage,
+ unsigned class_count,
+ const hb_map_t *klass_mapping) const
+ {
+ TRACE_SUBSET (this);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+
+ auto *out = c->serializer->start_embed (this);
+ if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
+
+ unsigned ligature_count = 0;
+ for (hb_codepoint_t gid : coverage)
+ {
+ ligature_count++;
+ if (!glyphset.has (gid)) continue;
+
+ auto *matrix = out->serialize_append (c->serializer);
+ if (unlikely (!matrix)) return_trace (false);
+
+ matrix->serialize_subset (c,
+ this->arrayZ[ligature_count - 1],
+ this,
+ class_count,
+ klass_mapping);
+ }
+ return_trace (this->len);
+ }
+};
struct MarkLigPosFormat1
{
@@ -2130,8 +2180,56 @@
bool subset (hb_subset_context_t *c) const
{
TRACE_SUBSET (this);
- // TODO(subset)
- return_trace (false);
+ const hb_set_t &glyphset = *c->plan->glyphset_gsub ();
+ 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)
+ ;
+
+ auto new_mark_coverage =
+ + mark_iter
+ | hb_map_retains_sorting (hb_first)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->markCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_mark_coverage))
+ return_trace (false);
+
+ out->markArray.serialize (c->serializer, out)
+ .serialize (c->serializer,
+ &klass_mapping,
+ c->plan->layout_variation_idx_map,
+ &(this+markArray),
+ + mark_iter
+ | hb_map (hb_second));
+
+ auto new_ligature_coverage =
+ + hb_iter (this + ligatureCoverage)
+ | hb_filter (glyphset)
+ | hb_map_retains_sorting (glyph_map)
+ ;
+
+ if (!out->ligatureCoverage.serialize (c->serializer, out)
+ .serialize (c->serializer, new_ligature_coverage))
+ return_trace (false);
+
+ out->ligatureArray.serialize_subset (c, ligatureArray, this,
+ hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
+
+ return_trace (true);
}
bool sanitize (hb_sanitize_context_t *c) const
@@ -2164,6 +2262,7 @@
DEFINE_SIZE_STATIC (12);
};
+
struct MarkLigPos
{
template <typename context_t, typename ...Ts>
diff --git a/test/subset/data/Makefile.am b/test/subset/data/Makefile.am
index d921f72..133971a 100644
--- a/test/subset/data/Makefile.am
+++ b/test/subset/data/Makefile.am
@@ -17,6 +17,7 @@
expected/layout.gpos2 \
expected/layout.gpos3 \
expected/layout.gpos4 \
+ expected/layout.gpos5 \
expected/layout.gpos6 \
expected/layout.gpos8 \
expected/layout.gpos8.amiri \
diff --git a/test/subset/data/Makefile.sources b/test/subset/data/Makefile.sources
index 58ba108..46680a5 100644
--- a/test/subset/data/Makefile.sources
+++ b/test/subset/data/Makefile.sources
@@ -16,6 +16,7 @@
tests/layout.gpos2.tests \
tests/layout.gpos3.tests \
tests/layout.gpos4.tests \
+ tests/layout.gpos5.tests \
tests/layout.gpos6.tests \
tests/layout.gpos8.tests \
tests/layout.gpos8.amiri.tests \
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,44.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,44.otf
new file mode 100644
index 0000000..13a1fb7
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,44.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,45.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,45.otf
new file mode 100644
index 0000000..5153358
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43,45.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43.otf
new file mode 100644
index 0000000..b7a0bc6
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,44.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,44.otf
new file mode 100644
index 0000000..bb7d74b
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,44.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,45.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,45.otf
new file mode 100644
index 0000000..0da7880
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42,45.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42.otf
new file mode 100644
index 0000000..9b6e158
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,43.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,43.otf
new file mode 100644
index 0000000..c28bed1
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41.otf
new file mode 100644
index 0000000..7878d4b
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.42.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.42.otf
new file mode 100644
index 0000000..f5824e4
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.retain-all-codepoint.otf
new file mode 100644
index 0000000..b7c424e
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout-retain-gids.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,44.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,44.otf
new file mode 100644
index 0000000..3749d35
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,44.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,45.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,45.otf
new file mode 100644
index 0000000..5d4fcee
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43,45.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43.otf
new file mode 100644
index 0000000..54fc068
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,44.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,44.otf
new file mode 100644
index 0000000..d4c95a6
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,44.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,45.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,45.otf
new file mode 100644
index 0000000..656792d
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42,45.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42.otf
new file mode 100644
index 0000000..cc2f5f7
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,43.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,43.otf
new file mode 100644
index 0000000..946c63c
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41,43.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41.otf
new file mode 100644
index 0000000..093f4ee
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.41.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.42.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.42.otf
new file mode 100644
index 0000000..9e1aabf
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.42.otf
Binary files differ
diff --git a/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.retain-all-codepoint.otf b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.retain-all-codepoint.otf
new file mode 100644
index 0000000..b7c424e
--- /dev/null
+++ b/test/subset/data/expected/layout.gpos5/gpos5_font1.keep-layout.retain-all-codepoint.otf
Binary files differ
diff --git a/test/subset/data/fonts/gpos5_font1.otf b/test/subset/data/fonts/gpos5_font1.otf
new file mode 100644
index 0000000..c7e2132
--- /dev/null
+++ b/test/subset/data/fonts/gpos5_font1.otf
Binary files differ
diff --git a/test/subset/data/tests/layout.gpos5.tests b/test/subset/data/tests/layout.gpos5.tests
new file mode 100644
index 0000000..3f5ef0c
--- /dev/null
+++ b/test/subset/data/tests/layout.gpos5.tests
@@ -0,0 +1,18 @@
+FONTS:
+gpos5_font1.otf
+
+PROFILES:
+keep-layout.txt
+keep-layout-retain-gids.txt
+
+SUBSETS:
+A
+B
+AB
+AC
+ABC
+ABE
+ABCE
+ABD
+ABCD
+*
diff --git a/test/subset/meson.build b/test/subset/meson.build
index 8d3d58b..de28fda 100644
--- a/test/subset/meson.build
+++ b/test/subset/meson.build
@@ -9,6 +9,7 @@
'layout.gpos2',
'layout.gpos3',
'layout.gpos4',
+ 'layout.gpos5',
'layout.gpos6',
'layout.gpos8',
'layout.gpos8.amiri',