From 198612c1c83d3b19b953a2fcc73406287104e5a2 Mon Sep 17 00:00:00 2001 From: Qunxin Liu Date: Fri, 28 Jul 2023 15:41:54 -0700 Subject: [PATCH] [instancer] add decompile_glyph_variations () for gvar --- src/hb-ot-var-common.hh | 1 + src/hb-ot-var-gvar-table.hh | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/hb-ot-var-common.hh b/src/hb-ot-var-common.hh index caddfe416..2c8f21309 100644 --- a/src/hb-ot-var-common.hh +++ b/src/hb-ot-var-common.hh @@ -1488,6 +1488,7 @@ struct TupleVariationData bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); } unsigned int get_count () const { return (*this) & CountMask; } TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; } + explicit operator bool () const { return get_count (); } protected: enum Flags diff --git a/src/hb-ot-var-gvar-table.hh b/src/hb-ot-var-gvar-table.hh index 180d9058c..0cb7939ba 100644 --- a/src/hb-ot-var-gvar-table.hh +++ b/src/hb-ot-var-gvar-table.hh @@ -58,6 +58,50 @@ struct glyph_variations_t unsigned compiled_shared_tuples_count () const { return shared_tuples_count; } + bool create_from_glyphs_var_data (unsigned axis_count, + const hb_array_t shared_tuples, + const hb_subset_plan_t *plan, + const hb_hashmap_t& new_gid_var_data_map) + { + if (unlikely (!glyph_variations.alloc (plan->new_to_old_gid_list.length, true))) + return false; + + auto it = hb_iter (plan->new_to_old_gid_list); + for (auto &_ : it) + { + hb_codepoint_t new_gid = _.first; + contour_point_vector_t *all_contour_points; + if (!new_gid_var_data_map.has (new_gid) || + !plan->new_gid_contour_points_map.has (new_gid, &all_contour_points)) + return false; + hb_bytes_t var_data = new_gid_var_data_map.get (new_gid); + + const GlyphVariationData* p = reinterpret_cast (var_data.arrayZ); + hb_vector_t shared_indices; + GlyphVariationData::tuple_iterator_t iterator; + tuple_variations_t tuple_vars; + + /* in case variation data is empty, push an empty struct into the vector, + * keep the vector in sync with the new_to_old_gid_list */ + if (!var_data || ! p->has_data () || !all_contour_points->length || + !GlyphVariationData::get_tuple_iterator (var_data, axis_count, + var_data.arrayZ, + shared_indices, &iterator)) + { + glyph_variations.push (std::move (tuple_vars)); + continue; + } + + if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */, + iterator, &(plan->axes_old_index_tag_map), + shared_indices, shared_tuples, + tuple_vars /* OUT */)) + return false; + glyph_variations.push (std::move (tuple_vars)); + } + return !glyph_variations.in_error () && glyph_variations.length == plan->new_to_old_gid_list.length; + } + bool compile_shared_tuples (const hb_map_t& axes_index_map, const hb_map_t& axes_old_index_tag_map) { @@ -165,6 +209,32 @@ struct gvar bool sanitize (hb_sanitize_context_t *c) const { return sanitize_shallow (c); } + bool decompile_glyph_variations (const hb_subset_plan_t *plan, + glyph_variations_t& glyph_vars /* OUT */) const + { + + hb_hashmap_t new_gid_var_data_map; + auto it = hb_iter (plan->new_to_old_gid_list); + if (it->first == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) + { + new_gid_var_data_map.set (0, hb_bytes_t ()); + it++; + } + + for (auto &_ : it) + { + hb_codepoint_t new_gid = _.first; + hb_codepoint_t old_gid = _.second; + hb_bytes_t var_data_bytes = get_glyph_var_data_bytes (old_gid); + new_gid_var_data_map.set (new_gid, var_data_bytes); + } + + if (new_gid_var_data_map.in_error ()) return false; + + hb_array_t shared_tuples = (this+sharedTuples).as_array ((unsigned) sharedTupleCount * (unsigned) axisCount); + return glyph_vars.create_from_glyphs_var_data (axisCount, shared_tuples, plan, new_gid_var_data_map); + } + bool subset (hb_subset_context_t *c) const { TRACE_SUBSET (this); @@ -282,6 +352,17 @@ struct gvar return likely (var_data.length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t (); } + const hb_bytes_t get_glyph_var_data_bytes (hb_codepoint_t gid) const + { + unsigned start_offset = get_offset (glyphCountX, gid); + unsigned end_offset = get_offset (glyphCountX, gid+1); + if (unlikely (end_offset < start_offset)) return hb_bytes_t (); + unsigned length = end_offset - start_offset; + const char *p = (const char*) this + (unsigned) dataZ + start_offset; + hb_bytes_t var_data{p, length}; + return likely (length >= GlyphVariationData::min_size) ? var_data : hb_bytes_t (); + } + bool is_long_offset () const { return flags & 1; } unsigned get_offset (unsigned glyph_count, unsigned i) const