From 389446c563f9caab73df6d58a43fc5d1ed991920 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Thu, 8 Jun 2023 09:07:47 -0700 Subject: [PATCH 1/4] [instancer] add merge_tuple_variations () --- src/hb-ot-var-common.hh | 27 +++++++++++++++++++++++++++ src/hb-subset-instancer-solver.hh | 18 ++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index 91898b35b..ae6a0bda8 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -646,6 +646,33 @@ struct TupleVariationData tuple_vars = std::move (new_vars); } } + + /* merge tuple variations with overlapping tents */ + void merge_tuple_variations () + { + hb_vector_t new_vars; + hb_hashmap_t, unsigned> m; + unsigned i = 0; + for (const tuple_delta_t& var : tuple_vars) + { + /* if all axes are pinned, drop the tuple variation */ + if (var.axis_tuples.is_empty ()) continue; + + unsigned *idx; + if (m.has (var.axis_tuples, &idx)) + { + new_vars[*idx] += var; + } + else + { + new_vars.push (var); + m.set (var.axis_tuples, i); + i++; + } + } + tuple_vars.fini (); + tuple_vars = std::move (new_vars); + } }; struct tuple_iterator_t diff --git a/src/hb-subset-instancer-solver.hh b/src/hb-subset-instancer-solver.hh index 911b37f4a..b1f859493 100644 --- a/src/hb-subset-instancer-solver.hh +++ b/src/hb-subset-instancer-solver.hh @@ -42,12 +42,30 @@ struct Triple { maximum == o.maximum; } + bool operator != (const Triple o) const + { return !(*this == o); } + bool is_point () const { return minimum == middle && middle == maximum; } bool contains (float point) const { return minimum <= point && point <= maximum; } + /* from hb_array_t hash ()*/ + uint32_t hash () const + { + uint32_t current = /*cbf29ce4*/0x84222325; + current = current ^ hb_hash (minimum); + current = current * 16777619; + + current = current ^ hb_hash (middle); + current = current * 16777619; + + current = current ^ hb_hash (maximum); + current = current * 16777619; + return current; + } + float minimum; float middle; float maximum; From 8057661f077dbca4f8b1f702771b70a9e1e29dd4 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Thu, 8 Jun 2023 12:10:27 -0700 Subject: [PATCH 2/4] [instancer] use axis tag as hashmap key instead of axis index This makes remove_axis() and set_tent() faster, which are used by change_axis_limits () --- src/hb-ot-var-common.hh | 16 ++++++++++++---- src/hb-ot-var-cvar-table.hh | 2 ++ src/test-tuple-varstore.cc | 11 ++++++++--- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index ae6a0bda8..9a33af299 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -251,7 +251,8 @@ struct TupleVariationHeader bool unpack_axis_tuples (unsigned axis_count, const hb_array_t shared_tuples, - hb_hashmap_t& axis_tuples /* OUT */) const + const hb_map_t *axes_old_index_tag_map, + hb_hashmap_t& axis_tuples /* OUT */) const { const F2DOT14 *peak_tuple = nullptr; if (has_peak ()) @@ -279,6 +280,10 @@ struct TupleVariationHeader float peak = peak_tuple[i].to_float (); if (peak == 0.f) continue; + hb_tag_t *axis_tag; + if (!axes_old_index_tag_map->has (i, &axis_tag)) + return false; + float start, end; if (has_interm) { @@ -290,7 +295,7 @@ struct TupleVariationHeader start = hb_min (peak, 0.f); end = hb_max (peak, 0.f); } - axis_tuples.set (i, Triple (start, peak, end)); + axis_tuples.set (*axis_tag, Triple (start, peak, end)); } return true; @@ -562,6 +567,7 @@ struct TupleVariationData unsigned tuple_var_count, unsigned point_count, bool is_gvar, + const hb_map_t *axes_old_index_tag_map, const hb_vector_t &shared_indices, const hb_array_t shared_tuples) { @@ -572,8 +578,8 @@ struct TupleVariationData if (unlikely (!iterator.var_data_bytes.check_range (p, length))) { fini (); return false; } - hb_hashmap_t axis_tuples; - if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axis_tuples) + hb_hashmap_t axis_tuples; + if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axes_old_index_tag_map, axis_tuples) || axis_tuples.is_empty ()) { fini (); return false; } @@ -849,12 +855,14 @@ struct TupleVariationData bool decompile_tuple_variations (unsigned point_count, bool is_gvar, tuple_iterator_t iterator, + const hb_map_t *axes_old_index_tag_map, const hb_vector_t &shared_indices, const hb_array_t shared_tuples, tuple_variations_t& tuple_variations /* OUT */) const { return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount, point_count, is_gvar, + axes_old_index_tag_map, shared_indices, shared_tuples); } diff --git a/src/hb-ot-var-cvar-table.hh b/src/hb-ot-var-cvar-table.hh index 110a3af40..c85da7adc 100644 --- a/src/hb-ot-var-cvar-table.hh +++ b/src/hb-ot-var-cvar-table.hh @@ -54,6 +54,7 @@ struct cvar bool decompile_tuple_variations (unsigned axis_count, unsigned point_count, bool is_gvar, + const hb_map_t *axes_old_index_tag_map, TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const { hb_vector_t shared_indices; @@ -65,6 +66,7 @@ struct cvar return false; return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator, + axes_old_index_tag_map, shared_indices, hb_array (), tuple_variations); diff --git a/src/test-tuple-varstore.cc b/src/test-tuple-varstore.cc index 569189677..8387d1e88 100644 --- a/src/test-tuple-varstore.cc +++ b/src/test-tuple-varstore.cc @@ -33,8 +33,13 @@ test_decompile_cvar () const OT::cvar* cvar_table = reinterpret_cast (cvar_data); unsigned point_count = 65; unsigned axis_count = 1; + + hb_tag_t axis_tag = HB_TAG ('w', 'g', 'h', 't'); + hb_map_t axis_idx_tag_map; + axis_idx_tag_map.set (0, axis_tag); + OT::TupleVariationData::tuple_variations_t tuple_variations; - bool result = cvar_table->decompile_tuple_variations (axis_count, point_count, false, tuple_variations); + bool result = cvar_table->decompile_tuple_variations (axis_count, point_count, false, &axis_idx_tag_map, tuple_variations); assert (result); assert (tuple_variations.tuple_vars.length == 2); for (unsigned i = 0; i < 2; i++) @@ -44,8 +49,8 @@ test_decompile_cvar () assert (tuple_variations.tuple_vars[i].indices.length == 65); assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length); } - assert (tuple_variations.tuple_vars[0].axis_tuples.get (0) == Triple (-1.f, -1.f, 0.f)); - assert (tuple_variations.tuple_vars[1].axis_tuples.get (0) == Triple (0.f, 1.f, 1.f)); + assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f)); + assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f)); hb_vector_t deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -1.f, 0.f, -3.f, 1.f, 0.f, -37.f, -37.f, -26.f, -26.f, 0.f, 0.f, 0.f, -3.f, 0.f, 0.f, 0.f, 0.f, 0.f, -3.f, 0.f, 2.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f, -29.f, -29.f, -20.f, -20.f, 0.f, 0.f, 0.f, 1.f}; for (unsigned i = 0; i < 65; i++) From 9fd367663a25bbcdcdff958ebc3665ddf8017077 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Thu, 8 Jun 2023 12:27:36 -0700 Subject: [PATCH 3/4] [instancer] add testing code for change_tuple_variation_axis_limits() Also fixed a small bug --- src/Makefile.am | 2 +- src/hb-ot-var-common.hh | 2 +- src/meson.build | 2 +- src/test-tuple-varstore.cc | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 11f4c8cf1..430d44a45 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -532,7 +532,7 @@ test_instancer_solver_SOURCES = test-subset-instancer-solver.cc hb-subset-instan test_instancer_solver_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_instancer_solver_LDADD = $(COMPILED_TESTS_LDADD) -test_tuple_varstore_SOURCES = test-tuple-varstore.cc hb-static.cc +test_tuple_varstore_SOURCES = test-tuple-varstore.cc hb-subset-instancer-solver.cc hb-static.cc test_tuple_varstore_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS) test_tuple_varstore_LDADD = $(COMPILED_TESTS_LDADD) diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index 9a33af299..f28073cf7 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -642,7 +642,7 @@ struct TupleVariationData if (!out) continue; unsigned new_len = new_vars.length + out.length; - if (unlikely (!new_vars.resize (new_len, false))) + if (unlikely (!new_vars.alloc (new_len, false))) { fini (); return;} for (unsigned i = 0; i < out.length; i++) diff --git a/src/meson.build b/src/meson.build index 81ad125e4..d14c3c09e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -723,7 +723,7 @@ if get_option('tests').enabled() 'test-vector': ['test-vector.cc', 'hb-static.cc'], 'test-bimap': ['test-bimap.cc', 'hb-static.cc'], 'test-instancer-solver': ['test-subset-instancer-solver.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'], - 'test-tuple-varstore': ['test-tuple-varstore.cc', 'hb-static.cc'], + 'test-tuple-varstore': ['test-tuple-varstore.cc', 'hb-subset-instancer-solver.cc', 'hb-static.cc'], } foreach name, source : compiled_tests if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc') diff --git a/src/test-tuple-varstore.cc b/src/test-tuple-varstore.cc index 8387d1e88..85cccbfba 100644 --- a/src/test-tuple-varstore.cc +++ b/src/test-tuple-varstore.cc @@ -75,6 +75,41 @@ test_decompile_cvar () assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]); } } + + /* partial instancing wght=300:800 */ + hb_hashmap_t normalized_axes_location; + normalized_axes_location.set (axis_tag, Triple (-0.512817f, 0.f, 0.700012f)); + + tuple_variations.change_tuple_variations_axis_limits (&normalized_axes_location); + tuple_variations.merge_tuple_variations (); + + assert (tuple_variations.tuple_vars[0].indices.length == 65); + assert (tuple_variations.tuple_vars[1].indices.length == 65); + assert (!tuple_variations.tuple_vars[0].deltas_y); + assert (!tuple_variations.tuple_vars[1].deltas_y); + assert (tuple_variations.tuple_vars[0].axis_tuples.get (axis_tag) == Triple (-1.f, -1.f, 0.f)); + assert (tuple_variations.tuple_vars[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f)); + + hb_vector_t rounded_deltas_1 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, -1, 0.f, -2, 1, 0.f, -1, 0.f, -2, 1, 0.f, -19, -19, -13, -13, 0.f, 0.f, 0.f, -2, 0.f, 0.f, 0.f, 0.f, 0.f, -2, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1, -15, -15, -10.f, -10.f, 0.f, 0.f, 0.f, 1}; + + hb_vector_t rounded_deltas_2 {0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1, 0.f, 4, -2, 0.f, 1, 0.f, 4, -2, 0.f, 68, 68, 48, 48, 0.f, 0.f, 0.f, 4, 0.f, 0.f, 1, -1, 1, 5, -1, -4, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1, 51, 51, 37, 37, 0.f, 0.f, 0.f, -1}; + + for (unsigned i = 0; i < 65; i++) + { + if (i < 23) + { + assert (tuple_variations.tuple_vars[0].indices[i] == 0); + assert (tuple_variations.tuple_vars[1].indices[i] == 0); + } + else + { + assert (tuple_variations.tuple_vars[0].indices[i] == 1); + assert (tuple_variations.tuple_vars[1].indices[i] == 1); + assert (roundf (tuple_variations.tuple_vars[0].deltas_x[i]) == rounded_deltas_1[i]); + assert (roundf (tuple_variations.tuple_vars[1].deltas_x[i]) == rounded_deltas_2[i]); + } + } + } int From 3669a6271043912de8d0ee566a4effc3a56927f9 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Thu, 8 Jun 2023 13:26:37 -0700 Subject: [PATCH 4/4] fix bot --- src/hb-ot-var-common.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index f28073cf7..18df261cf 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -419,7 +419,7 @@ struct TupleVariationHeader struct tuple_delta_t { public: - hb_hashmap_t axis_tuples; + hb_hashmap_t axis_tuples; /* indices_length = point_count, indice[i] = 1 means point i is referenced */ hb_vector_t indices;