[instancer] apply cvar deltas

This commit is contained in:
Qunxin Liu 2023-02-14 13:26:59 -08:00 committed by Behdad Esfahbod
parent 8b0c7b9554
commit a975ec4842
10 changed files with 44 additions and 11 deletions

View File

@ -93,6 +93,7 @@ HB_OT_ACCELERATOR (OT, cff2)
#ifndef HB_NO_VAR #ifndef HB_NO_VAR
HB_OT_CORE_TABLE (OT, fvar) HB_OT_CORE_TABLE (OT, fvar)
HB_OT_CORE_TABLE (OT, avar) HB_OT_CORE_TABLE (OT, avar)
HB_OT_CORE_TABLE (OT, cvar)
HB_OT_ACCELERATOR (OT, gvar) HB_OT_ACCELERATOR (OT, gvar)
HB_OT_CORE_TABLE (OT, MVAR) HB_OT_CORE_TABLE (OT, MVAR)
#endif #endif

View File

@ -48,18 +48,22 @@ struct cvar
tupleVariationData.sanitize (c)); tupleVariationData.sanitize (c));
} }
bool calculate_cvt_deltas (unsigned axis_count, const TupleVariationData* get_tuple_var_data (void) const
hb_array_t<int> coords, { return &tupleVariationData; }
unsigned num_cvt_item,
hb_vector_t<float>& cvt_deltas /* OUT */) const static bool calculate_cvt_deltas (unsigned axis_count,
hb_array_t<int> coords,
unsigned num_cvt_item,
const TupleVariationData *tuple_var_data,
const void *base,
hb_vector_t<float>& cvt_deltas /* OUT */)
{ {
if (!coords) return true; if (!coords) return true;
hb_vector_t<unsigned> shared_indices; hb_vector_t<unsigned> shared_indices;
TupleVariationData::tuple_iterator_t iterator; TupleVariationData::tuple_iterator_t iterator;
unsigned var_data_length = tupleVariationData.get_size (axis_count); unsigned var_data_length = tuple_var_data->get_size (axis_count);
hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (&tupleVariationData), var_data_length); hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (tuple_var_data), var_data_length);
if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
this,
shared_indices, &iterator)) shared_indices, &iterator))
return true; /* isn't applied at all */ return true; /* isn't applied at all */
@ -101,7 +105,9 @@ struct cvar
return true; return true;
} }
bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan) const static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
const TupleVariationData *tuple_var_data,
const void *base)
{ {
const hb_tag_t cvt = HB_TAG('c','v','t',' '); const hb_tag_t cvt = HB_TAG('c','v','t',' ');
hb_blob_t *cvt_blob = hb_face_reference_table (plan->source, cvt); hb_blob_t *cvt_blob = hb_face_reference_table (plan->source, cvt);
@ -122,7 +128,8 @@ struct cvar
} }
hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ()); hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ());
if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (), num_cvt_item, cvt_deltas)) if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (),
num_cvt_item, tuple_var_data, base, cvt_deltas))
{ {
hb_blob_destroy (cvt_prime_blob); hb_blob_destroy (cvt_prime_blob);
return false; return false;

View File

@ -71,7 +71,6 @@ hb_subset_input_t::hb_subset_input_t ()
hb_tag_t default_no_subset_tables[] = { hb_tag_t default_no_subset_tables[] = {
HB_TAG ('a', 'v', 'a', 'r'), HB_TAG ('a', 'v', 'a', 'r'),
HB_TAG ('g', 'a', 's', 'p'), HB_TAG ('g', 'a', 's', 'p'),
HB_TAG ('c', 'v', 't', ' '),
HB_TAG ('f', 'p', 'g', 'm'), HB_TAG ('f', 'p', 'g', 'm'),
HB_TAG ('p', 'r', 'e', 'p'), HB_TAG ('p', 'r', 'e', 'p'),
HB_TAG ('V', 'D', 'M', 'X'), HB_TAG ('V', 'D', 'M', 'X'),

View File

@ -50,6 +50,7 @@
#include "hb-ot-name-table.hh" #include "hb-ot-name-table.hh"
#include "hb-ot-layout-gsub-table.hh" #include "hb-ot-layout-gsub-table.hh"
#include "hb-ot-layout-gpos-table.hh" #include "hb-ot-layout-gpos-table.hh"
#include "hb-ot-var-cvar-table.hh"
#include "hb-ot-var-fvar-table.hh" #include "hb-ot-var-fvar-table.hh"
#include "hb-ot-var-gvar-table.hh" #include "hb-ot-var-gvar-table.hh"
#include "hb-ot-var-hvar-table.hh" #include "hb-ot-var-hvar-table.hh"
@ -478,6 +479,16 @@ _subset_table (hb_subset_plan_t *plan,
if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf); if (plan->all_axes_pinned) return _subset<const OT::STAT> (plan, buf);
else return _passthrough (plan, tag); else return _passthrough (plan, tag);
case HB_TAG ('c', 'v', 't', ' '):
#ifndef HB_NO_VAR
if (_is_table_present (plan->source, HB_OT_TAG_cvar) &&
plan->normalized_coords && !plan->pinned_at_default)
{
auto &cvar = *plan->source->table.cvar;
return OT::cvar::add_cvt_and_apply_deltas (plan, cvar.get_tuple_var_data (), &cvar);
}
#endif
return _passthrough (plan, tag);
default: default:
if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED) if (plan->flags & HB_SUBSET_FLAGS_PASSTHROUGH_UNRECOGNIZED)
return _passthrough (plan, tag); return _passthrough (plan, tag);

View File

@ -66,6 +66,7 @@ EXTRA_DIST += \
expected/mvar_full_instance \ expected/mvar_full_instance \
expected/instance_comp_glyph_empty_child \ expected/instance_comp_glyph_empty_child \
expected/post_apply_mvar_delta \ expected/post_apply_mvar_delta \
expected/apply_cvar_delta \
fonts \ fonts \
profiles \ profiles \
$(NULL) $(NULL)

View File

@ -57,6 +57,7 @@ TESTS = \
tests/mvar_full_instance.tests \ tests/mvar_full_instance.tests \
tests/instance_comp_glyph_empty_child.tests \ tests/instance_comp_glyph_empty_child.tests \
tests/post_apply_mvar_delta.tests \ tests/post_apply_mvar_delta.tests \
tests/apply_cvar_delta.tests \
$(NULL) $(NULL)
# TODO: re-enable once colrv1 subsetting is stabilized. # TODO: re-enable once colrv1 subsetting is stabilized.

View File

@ -0,0 +1,12 @@
FONTS:
Comfortaa-Regular-new.ttf
PROFILES:
default.txt
SUBSETS:
*
INSTANCES:
wght=700
wght=300

View File

@ -59,6 +59,7 @@ tests = [
'mvar_full_instance', 'mvar_full_instance',
'instance_comp_glyph_empty_child', 'instance_comp_glyph_empty_child',
'post_apply_mvar_delta', 'post_apply_mvar_delta',
'apply_cvar_delta',
] ]
repack_tests = [ repack_tests = [