From c632a164b98de695b5cd3366689df8dd45021b6f Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Fri, 6 Jan 2023 11:01:25 -0700 Subject: [PATCH] [subset/cff] Support instancing --- src/hb-cff1-interp-cs.hh | 3 ++- src/hb-cff2-interp-cs.hh | 2 ++ src/hb-subset-cff-common.hh | 9 +++++++-- src/hb-subset-cff2.cc | 38 ++++++++++++++++++++++++++++++++++++- src/hb-subset-plan.cc | 6 ++++++ src/hb-subset-plan.hh | 1 + 6 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh index b306c2ecc..d8868efa5 100644 --- a/src/hb-cff1-interp-cs.hh +++ b/src/hb-cff1-interp-cs.hh @@ -38,7 +38,8 @@ typedef biased_subrs_t cff1_biased_subrs_t; struct cff1_cs_interp_env_t : cs_interp_env_t { template - 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) { processed_width = false; diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh index 51f360ee9..6686ad41f 100644 --- a/src/hb-cff2-interp-cs.hh +++ b/src/hb-cff2-interp-cs.hh @@ -169,7 +169,9 @@ struct cff2_cs_interp_env_t : cs_interp_env_t const CFF2VariationStore *varStore; unsigned int region_count; unsigned int ivs; + public: hb_vector_t scalars; + protected: bool do_blend; bool seen_vsindex_; bool seen_blend; diff --git a/src/hb-subset-cff-common.hh b/src/hb-subset-cff-common.hh index e20de2204..684ac5f65 100644 --- a/src/hb-subset-cff-common.hh +++ b/src/hb-subset-cff-common.hh @@ -223,6 +223,7 @@ struct flatten_param_t { str_buff_t &flatStr; bool drop_hints; + const hb_subset_plan_t *plan; }; template @@ -250,11 +251,15 @@ struct subr_flattener_t unsigned int fd = acc.fdSelect->get_fd (glyph); if (unlikely (fd >= acc.fdCount)) return false; - ENV env (str, acc, fd); + + + ENV env (str, acc, fd, + plan->normalized_coords.arrayZ, plan->normalized_coords.length); cs_interpreter_t interp (env); flatten_param_t param = { 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))) return false; diff --git a/src/hb-subset-cff2.cc b/src/hb-subset-cff2.cc index 60946b028..3cd2fe146 100644 --- a/src/hb-subset-cff2.cc +++ b/src/hb-subset-cff2.cc @@ -122,8 +122,43 @@ struct cff2_cs_opset_flatten_t : cff2_cs_opset_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 &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 */ str_encoder_t encoder (param.flatStr); for (unsigned int j = 0; j < arg.numValues; j++) @@ -240,7 +275,8 @@ struct cff2_subset_plan { orig_fdcount = acc.fdArray->count; 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) { diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index ddeacb2ed..ed021291f 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -769,6 +769,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan) return; hb_array_t axes = face->table.fvar->get_axes (); + plan->normalized_coords.resize (axes.length); bool has_avar = face->table.avar->has_data (); 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; unsigned old_axis_idx = 0, new_axis_idx = 0; + unsigned int i; for (const auto& axis : axes) { 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); if (normalized_v != 0) plan->pinned_at_default = false; + + plan->normalized_coords[i] = normalized_v; } if (has_avar) seg_maps = &StructAfter (*seg_maps); old_axis_idx++; + + i++; } plan->all_axes_pinned = !axis_not_pinned; } diff --git a/src/hb-subset-plan.hh b/src/hb-subset-plan.hh index 1b2aee782..a3cbee41c 100644 --- a/src/hb-subset-plan.hh +++ b/src/hb-subset-plan.hh @@ -190,6 +190,7 @@ struct hb_subset_plan_t hb_hashmap_t>* sanitized_table_cache; //normalized axes location map hb_hashmap_t *axes_location; + hb_vector_t normalized_coords; //user specified axes location map hb_hashmap_t *user_axes_location; //retained old axis index -> new axis index mapping in fvar axis array