Merge pull request #4271 from googlefonts/change_axis_limits

[instancer] change tuple variations' axis limits
pull/4277/head
Behdad Esfahbod 1 year ago committed by GitHub
commit 39dd777a12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Makefile.am
  2. 47
      src/hb-ot-var-common.hh
  3. 2
      src/hb-ot-var-cvar-table.hh
  4. 18
      src/hb-subset-instancer-solver.hh
  5. 2
      src/meson.build
  6. 46
      src/test-tuple-varstore.cc

@ -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_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_instancer_solver_LDADD = $(COMPILED_TESTS_LDADD) 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_CPPFLAGS = $(COMPILED_TESTS_CPPFLAGS)
test_tuple_varstore_LDADD = $(COMPILED_TESTS_LDADD) test_tuple_varstore_LDADD = $(COMPILED_TESTS_LDADD)

@ -251,7 +251,8 @@ struct TupleVariationHeader
bool unpack_axis_tuples (unsigned axis_count, bool unpack_axis_tuples (unsigned axis_count,
const hb_array_t<const F2DOT14> shared_tuples, const hb_array_t<const F2DOT14> shared_tuples,
hb_hashmap_t<unsigned, Triple>& axis_tuples /* OUT */) const const hb_map_t *axes_old_index_tag_map,
hb_hashmap_t<hb_tag_t, Triple>& axis_tuples /* OUT */) const
{ {
const F2DOT14 *peak_tuple = nullptr; const F2DOT14 *peak_tuple = nullptr;
if (has_peak ()) if (has_peak ())
@ -279,6 +280,10 @@ struct TupleVariationHeader
float peak = peak_tuple[i].to_float (); float peak = peak_tuple[i].to_float ();
if (peak == 0.f) continue; 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; float start, end;
if (has_interm) if (has_interm)
{ {
@ -290,7 +295,7 @@ struct TupleVariationHeader
start = hb_min (peak, 0.f); start = hb_min (peak, 0.f);
end = hb_max (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; return true;
@ -414,7 +419,7 @@ struct TupleVariationHeader
struct tuple_delta_t struct tuple_delta_t
{ {
public: public:
hb_hashmap_t<unsigned, Triple> axis_tuples; hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
/* indices_length = point_count, indice[i] = 1 means point i is referenced */ /* indices_length = point_count, indice[i] = 1 means point i is referenced */
hb_vector_t<bool> indices; hb_vector_t<bool> indices;
@ -562,6 +567,7 @@ struct TupleVariationData
unsigned tuple_var_count, unsigned tuple_var_count,
unsigned point_count, unsigned point_count,
bool is_gvar, bool is_gvar,
const hb_map_t *axes_old_index_tag_map,
const hb_vector_t<unsigned> &shared_indices, const hb_vector_t<unsigned> &shared_indices,
const hb_array_t<const F2DOT14> shared_tuples) const hb_array_t<const F2DOT14> shared_tuples)
{ {
@ -572,8 +578,8 @@ struct TupleVariationData
if (unlikely (!iterator.var_data_bytes.check_range (p, length))) if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
{ fini (); return false; } { fini (); return false; }
hb_hashmap_t<unsigned, Triple> axis_tuples; hb_hashmap_t<hb_tag_t, Triple> axis_tuples;
if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, 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 ()) || axis_tuples.is_empty ())
{ fini (); return false; } { fini (); return false; }
@ -636,7 +642,7 @@ struct TupleVariationData
if (!out) continue; if (!out) continue;
unsigned new_len = new_vars.length + out.length; 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;} { fini (); return;}
for (unsigned i = 0; i < out.length; i++) for (unsigned i = 0; i < out.length; i++)
@ -646,6 +652,33 @@ struct TupleVariationData
tuple_vars = std::move (new_vars); tuple_vars = std::move (new_vars);
} }
} }
/* merge tuple variations with overlapping tents */
void merge_tuple_variations ()
{
hb_vector_t<tuple_delta_t> new_vars;
hb_hashmap_t<hb_hashmap_t<hb_tag_t, Triple>, 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 struct tuple_iterator_t
@ -822,12 +855,14 @@ struct TupleVariationData
bool decompile_tuple_variations (unsigned point_count, bool decompile_tuple_variations (unsigned point_count,
bool is_gvar, bool is_gvar,
tuple_iterator_t iterator, tuple_iterator_t iterator,
const hb_map_t *axes_old_index_tag_map,
const hb_vector_t<unsigned> &shared_indices, const hb_vector_t<unsigned> &shared_indices,
const hb_array_t<const F2DOT14> shared_tuples, const hb_array_t<const F2DOT14> shared_tuples,
tuple_variations_t& tuple_variations /* OUT */) const tuple_variations_t& tuple_variations /* OUT */) const
{ {
return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount, return tuple_variations.create_from_tuple_var_data (iterator, tupleVarCount,
point_count, is_gvar, point_count, is_gvar,
axes_old_index_tag_map,
shared_indices, shared_indices,
shared_tuples); shared_tuples);
} }

@ -54,6 +54,7 @@ struct cvar
bool decompile_tuple_variations (unsigned axis_count, bool decompile_tuple_variations (unsigned axis_count,
unsigned point_count, unsigned point_count,
bool is_gvar, bool is_gvar,
const hb_map_t *axes_old_index_tag_map,
TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const TupleVariationData::tuple_variations_t& tuple_variations /* OUT */) const
{ {
hb_vector_t<unsigned> shared_indices; hb_vector_t<unsigned> shared_indices;
@ -65,6 +66,7 @@ struct cvar
return false; return false;
return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator, return tupleVariationData.decompile_tuple_variations (point_count, is_gvar, iterator,
axes_old_index_tag_map,
shared_indices, shared_indices,
hb_array<const F2DOT14> (), hb_array<const F2DOT14> (),
tuple_variations); tuple_variations);

@ -42,12 +42,30 @@ struct Triple {
maximum == o.maximum; maximum == o.maximum;
} }
bool operator != (const Triple o) const
{ return !(*this == o); }
bool is_point () const bool is_point () const
{ return minimum == middle && middle == maximum; } { return minimum == middle && middle == maximum; }
bool contains (float point) const bool contains (float point) const
{ return minimum <= point && point <= maximum; } { 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 minimum;
float middle; float middle;
float maximum; float maximum;

@ -723,7 +723,7 @@ if get_option('tests').enabled()
'test-vector': ['test-vector.cc', 'hb-static.cc'], 'test-vector': ['test-vector.cc', 'hb-static.cc'],
'test-bimap': ['test-bimap.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-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 foreach name, source : compiled_tests
if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc') if cpp.get_argument_syntax() == 'msvc' and source.contains('hb-static.cc')

@ -33,8 +33,13 @@ test_decompile_cvar ()
const OT::cvar* cvar_table = reinterpret_cast<const OT::cvar*> (cvar_data); const OT::cvar* cvar_table = reinterpret_cast<const OT::cvar*> (cvar_data);
unsigned point_count = 65; unsigned point_count = 65;
unsigned axis_count = 1; 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; 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 (result);
assert (tuple_variations.tuple_vars.length == 2); assert (tuple_variations.tuple_vars.length == 2);
for (unsigned i = 0; i < 2; i++) 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 == 65);
assert (tuple_variations.tuple_vars[i].indices.length == tuple_variations.tuple_vars[i].deltas_x.length); 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[0].axis_tuples.get (axis_tag) == 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[1].axis_tuples.get (axis_tag) == Triple (0.f, 1.f, 1.f));
hb_vector_t<float> 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}; hb_vector_t<float> 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++) for (unsigned i = 0; i < 65; i++)
@ -70,6 +75,41 @@ test_decompile_cvar ()
assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]); assert (tuple_variations.tuple_vars[1].deltas_x[i] == deltas_2[i]);
} }
} }
/* partial instancing wght=300:800 */
hb_hashmap_t<hb_tag_t, Triple> 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<float> 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<float> 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 int

Loading…
Cancel
Save