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_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)

@ -251,7 +251,8 @@ struct TupleVariationHeader
bool unpack_axis_tuples (unsigned axis_count,
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;
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;
@ -414,7 +419,7 @@ struct TupleVariationHeader
struct tuple_delta_t
{
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 */
hb_vector_t<bool> indices;
@ -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<unsigned> &shared_indices,
const hb_array_t<const F2DOT14> shared_tuples)
{
@ -572,8 +578,8 @@ struct TupleVariationData
if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
{ fini (); return false; }
hb_hashmap_t<unsigned, Triple> axis_tuples;
if (!iterator.current_tuple->unpack_axis_tuples (iterator.get_axis_count (), shared_tuples, axis_tuples)
hb_hashmap_t<hb_tag_t, Triple> 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; }
@ -636,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++)
@ -646,6 +652,33 @@ struct TupleVariationData
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
@ -822,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<unsigned> &shared_indices,
const hb_array_t<const F2DOT14> 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);
}

@ -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<unsigned> 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<const F2DOT14> (),
tuple_variations);

@ -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;

@ -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')

@ -33,8 +33,13 @@ test_decompile_cvar ()
const OT::cvar* cvar_table = reinterpret_cast<const OT::cvar*> (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<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++)
@ -70,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<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

Loading…
Cancel
Save