[subset/cff] Support instancing

This commit is contained in:
Behdad Esfahbod 2023-01-06 11:01:25 -07:00
parent 5153218b41
commit c632a164b9
6 changed files with 55 additions and 4 deletions

View File

@ -38,7 +38,8 @@ typedef biased_subrs_t<CFF1Subrs> cff1_biased_subrs_t;
struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs> struct cff1_cs_interp_env_t : cs_interp_env_t<number_t, CFF1Subrs>
{ {
template <typename ACC> template <typename ACC>
cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd) cff1_cs_interp_env_t (const hb_ubytes_t &str, ACC &acc, unsigned int fd,
const int *coords_=nullptr, unsigned int num_coords_=0)
: SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs) : SUPER (str, acc.globalSubrs, acc.privateDicts[fd].localSubrs)
{ {
processed_width = false; processed_width = false;

View File

@ -169,7 +169,9 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
const CFF2VariationStore *varStore; const CFF2VariationStore *varStore;
unsigned int region_count; unsigned int region_count;
unsigned int ivs; unsigned int ivs;
public:
hb_vector_t<float> scalars; hb_vector_t<float> scalars;
protected:
bool do_blend; bool do_blend;
bool seen_vsindex_; bool seen_vsindex_;
bool seen_blend; bool seen_blend;

View File

@ -223,6 +223,7 @@ struct flatten_param_t
{ {
str_buff_t &flatStr; str_buff_t &flatStr;
bool drop_hints; bool drop_hints;
const hb_subset_plan_t *plan;
}; };
template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid> template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
@ -250,11 +251,15 @@ struct subr_flattener_t
unsigned int fd = acc.fdSelect->get_fd (glyph); unsigned int fd = acc.fdSelect->get_fd (glyph);
if (unlikely (fd >= acc.fdCount)) if (unlikely (fd >= acc.fdCount))
return false; return false;
ENV env (str, acc, fd);
ENV env (str, acc, fd,
plan->normalized_coords.arrayZ, plan->normalized_coords.length);
cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env); cs_interpreter_t<ENV, OPSET, flatten_param_t> interp (env);
flatten_param_t param = { flatten_param_t param = {
flat_charstrings.arrayZ[i], flat_charstrings.arrayZ[i],
(bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING) (bool) (plan->flags & HB_SUBSET_FLAGS_NO_HINTING),
plan
}; };
if (unlikely (!interp.interpret (param))) if (unlikely (!interp.interpret (param)))
return false; return false;

View File

@ -122,8 +122,43 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_t<cff2_cs_opset_flatten_t, flatte
SUPER::flush_args (env, param); SUPER::flush_args (env, param);
} }
static double instantiate_blends (const blend_arg_t &arg, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{
double v = arg.to_real ();
auto &scalars = env.scalars;
auto &deltas = arg.deltas;
if (scalars.length != deltas.length)
return v;
unsigned count = scalars.length;
for (unsigned i = 0; i < count; i++)
v += (double) scalars.arrayZ[i] * deltas.arrayZ[i].to_real ();
return v;
}
static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param) static void flatten_blends (const blend_arg_t &arg, unsigned int i, cff2_cs_interp_env_t<blend_arg_t> &env, flatten_param_t& param)
{ {
if (!param.plan->pinned_at_default)
{
str_encoder_t encoder (param.flatStr);
for (unsigned int j = 0; j < arg.numValues; j++)
{
blend_arg_t arg1 = env.argStack[i + j];
if (unlikely (!((arg1.blending () && (arg.numValues == arg1.numValues) && (arg1.valueIndex == j) &&
(arg1.deltas.length == env.get_region_count ())))))
{
env.set_error ();
return;
}
arg1.set_real (instantiate_blends (arg1, env, param));
encoder.encode_num (arg1);
}
return;
}
/* flatten the default values */ /* flatten the default values */
str_encoder_t encoder (param.flatStr); str_encoder_t encoder (param.flatStr);
for (unsigned int j = 0; j < arg.numValues; j++) for (unsigned int j = 0; j < arg.numValues; j++)
@ -240,7 +275,8 @@ struct cff2_subset_plan {
orig_fdcount = acc.fdArray->count; orig_fdcount = acc.fdArray->count;
drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING; drop_hints = plan->flags & HB_SUBSET_FLAGS_NO_HINTING;
desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE; desubroutinize = plan->flags & HB_SUBSET_FLAGS_DESUBROUTINIZE ||
!plan->pinned_at_default;
if (desubroutinize) if (desubroutinize)
{ {

View File

@ -769,6 +769,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
return; return;
hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes (); hb_array_t<const OT::AxisRecord> axes = face->table.fvar->get_axes ();
plan->normalized_coords.resize (axes.length);
bool has_avar = face->table.avar->has_data (); bool has_avar = face->table.avar->has_data ();
const OT::SegmentMaps *seg_maps = nullptr; const OT::SegmentMaps *seg_maps = nullptr;
@ -777,6 +778,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
bool axis_not_pinned = false; bool axis_not_pinned = false;
unsigned old_axis_idx = 0, new_axis_idx = 0; unsigned old_axis_idx = 0, new_axis_idx = 0;
unsigned int i;
for (const auto& axis : axes) for (const auto& axis : axes)
{ {
hb_tag_t axis_tag = axis.get_axis_tag (); hb_tag_t axis_tag = axis.get_axis_tag ();
@ -798,11 +800,15 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
plan->axes_location->set (axis_tag, normalized_v); plan->axes_location->set (axis_tag, normalized_v);
if (normalized_v != 0) if (normalized_v != 0)
plan->pinned_at_default = false; plan->pinned_at_default = false;
plan->normalized_coords[i] = normalized_v;
} }
if (has_avar) if (has_avar)
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps); seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
old_axis_idx++; old_axis_idx++;
i++;
} }
plan->all_axes_pinned = !axis_not_pinned; plan->all_axes_pinned = !axis_not_pinned;
} }

View File

@ -190,6 +190,7 @@ struct hb_subset_plan_t
hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache; hb_hashmap_t<hb_tag_t, hb::unique_ptr<hb_blob_t>>* sanitized_table_cache;
//normalized axes location map //normalized axes location map
hb_hashmap_t<hb_tag_t, int> *axes_location; hb_hashmap_t<hb_tag_t, int> *axes_location;
hb_vector_t<int> normalized_coords;
//user specified axes location map //user specified axes location map
hb_hashmap_t<hb_tag_t, float> *user_axes_location; hb_hashmap_t<hb_tag_t, float> *user_axes_location;
//retained old axis index -> new axis index mapping in fvar axis array //retained old axis index -> new axis index mapping in fvar axis array