diff --git a/src/OT/Var/VARC/VARC.cc b/src/OT/Var/VARC/VARC.cc index d15073f75..137539249 100644 --- a/src/OT/Var/VARC/VARC.cc +++ b/src/OT/Var/VARC/VARC.cc @@ -137,6 +137,7 @@ VarComponent::get_path_at (hb_font_t *font, hb_decycler_t *decycler, signed *edges_left, signed depth_left, + hb_glyf_scratch_t &scratch, VarRegionList::cache_t *cache) const { const unsigned char *end = total_record.arrayZ + total_record.length; @@ -192,14 +193,16 @@ VarComponent::get_path_at (hb_font_t *font, // Axis values - hb_vector_t axisIndices; - hb_vector_t axisValues; + auto &axisIndices = scratch.axisIndices; + axisIndices.clear (); + auto &axisValues = scratch.axisValues; + axisValues.clear (); if (flags & (unsigned) flags_t::HAVE_AXES) { unsigned axisIndicesIndex; READ_UINT32VAR (axisIndicesIndex); - axisIndices = (&VARC+VARC.axisIndicesList)[axisIndicesIndex]; - axisValues.resize (axisIndices.length); + axisIndices.extend ((&VARC+VARC.axisIndicesList)[axisIndicesIndex]); + axisValues.resize (axisIndices.length, false); const HBUINT8 *p = (const HBUINT8 *) record; TupleValues::decompile (p, axisValues, (const HBUINT8 *) end); record += (const unsigned char *) p - record; @@ -319,7 +322,8 @@ VarComponent::get_path_at (hb_font_t *font, VARC.get_path_at (font, gid, draw_session, component_coords, total_transform, parent_gid, - decycler, edges_left, depth_left - 1); + decycler, edges_left, depth_left - 1, + scratch); } #undef PROCESS_TRANSFORM_COMPONENTS @@ -337,7 +341,8 @@ VARC::get_path_at (hb_font_t *font, hb_codepoint_t parent_glyph, hb_decycler_t *decycler, signed *edges_left, - signed depth_left) const + signed depth_left, + hb_glyf_scratch_t &scratch) const { // Don't recurse on the same glyph. unsigned idx = glyph == parent_glyph ? @@ -354,7 +359,7 @@ VARC::get_path_at (hb_font_t *font, hb_draw_session_t transformer_session {transformer_funcs, &context}; hb_draw_session_t &shape_draw_session = transform.is_identity () ? draw_session : transformer_session; - if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords)) + if (!font->face->table.glyf->get_path_at (font, glyph, shape_draw_session, coords, scratch)) #ifndef HB_NO_CFF if (!font->face->table.cff2->get_path_at (font, glyph, shape_draw_session, coords)) if (!font->face->table.cff1->get_path (font, glyph, shape_draw_session)) // Doesn't have variations @@ -386,6 +391,7 @@ VARC::get_path_at (hb_font_t *font, draw_session, coords, transform, record, decycler, edges_left, depth_left, + scratch, cache); (this+varStore).destroy_cache (cache); diff --git a/src/OT/Var/VARC/VARC.hh b/src/OT/Var/VARC/VARC.hh index dbbf59bd4..95f58cfd5 100644 --- a/src/OT/Var/VARC/VARC.hh +++ b/src/OT/Var/VARC/VARC.hh @@ -53,6 +53,7 @@ struct VarComponent hb_decycler_t *decycler, signed *edges_left, signed depth_left, + hb_glyf_scratch_t &scratch, VarRegionList::cache_t *cache = nullptr) const; }; @@ -68,6 +69,7 @@ struct VarCompositeGlyph hb_decycler_t *decycler, signed *edges_left, signed depth_left, + hb_glyf_scratch_t &scratch, VarRegionList::cache_t *cache = nullptr) { while (record) @@ -76,7 +78,7 @@ struct VarCompositeGlyph record = comp.get_path_at (font, glyph, draw_session, coords, transform, record, - decycler, edges_left, depth_left, cache); + decycler, edges_left, depth_left, scratch, cache); } } }; @@ -98,13 +100,16 @@ struct VARC hb_codepoint_t parent_glyph, hb_decycler_t *decycler, signed *edges_left, - signed depth_left) const; + signed depth_left, + hb_glyf_scratch_t &scratch) const; bool get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const { hb_decycler_t decycler; signed edges = HB_MAX_GRAPH_EDGE_COUNT; + hb_glyf_scratch_t scratch; + scratch.warm_up (); return get_path_at (font, gid, @@ -114,7 +119,9 @@ struct VARC HB_CODEPOINT_INVALID, &decycler, &edges, - HB_MAX_NESTING_LEVEL); } + HB_MAX_NESTING_LEVEL, + scratch); + } bool sanitize (hb_sanitize_context_t *c) const { diff --git a/src/OT/glyf/Glyph.hh b/src/OT/glyf/Glyph.hh index 7772597e5..825c7a5b0 100644 --- a/src/OT/glyf/Glyph.hh +++ b/src/OT/glyf/Glyph.hh @@ -251,7 +251,8 @@ struct Glyph composite_contours_p = nullptr; } - if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false)) + hb_glyf_scratch_t scratch; + if (!get_points (font, glyf, all_points, scratch, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false)) return false; // .notdef, set type to empty so we only update metrics and don't compile bytes for @@ -305,6 +306,7 @@ struct Glyph template bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator, contour_point_vector_t &all_points /* OUT */, + hb_glyf_scratch_t &scratch, contour_point_vector_t *points_with_deltas = nullptr, /* OUT */ head_maxp_info_t * head_maxp_info = nullptr, /* OUT */ unsigned *composite_contours = nullptr, /* OUT */ @@ -391,6 +393,7 @@ struct Glyph glyf_accelerator.gvar->apply_deltas_to_points (gid, coords, points.as_array ().sub_array (old_length), + scratch, phantom_only && type == SIMPLE); #endif @@ -426,6 +429,7 @@ struct Glyph .get_points (font, glyf_accelerator, all_points, + scratch, points_with_deltas, head_maxp_info, composite_contours, diff --git a/src/OT/glyf/SimpleGlyph.hh b/src/OT/glyf/SimpleGlyph.hh index 46eb47f68..0a7cc6977 100644 --- a/src/OT/glyf/SimpleGlyph.hh +++ b/src/OT/glyf/SimpleGlyph.hh @@ -190,7 +190,7 @@ struct SimpleGlyph unsigned int num_points = endPtsOfContours[num_contours - 1] + 1; unsigned old_length = points.length; - points.alloc_exact (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy + points.alloc (points.length + num_points + 4); // Allocate for phantom points, to avoid a possible copy if (unlikely (!points.resize (points.length + num_points, false))) return false; auto points_ = points.as_array ().sub_array (old_length); if (!phantom_only) diff --git a/src/OT/glyf/glyf.hh b/src/OT/glyf/glyf.hh index bf1c032b5..395484c02 100644 --- a/src/OT/glyf/glyf.hh +++ b/src/OT/glyf/glyf.hh @@ -206,21 +206,16 @@ struct glyf_accelerator_t protected: template bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer, - hb_array_t coords = hb_array_t ()) const + hb_array_t coords, + hb_glyf_scratch_t &scratch) const { - if (!coords) - coords = hb_array (font->coords, font->num_coords); - if (gid >= num_glyphs) return false; - /* Making this allocfree is not that easy - https://github.com/harfbuzz/harfbuzz/issues/2095 - mostly because of gvar handling in VF fonts, - perhaps a separate path for non-VF fonts can be considered */ - contour_point_vector_t all_points; + auto &all_points = scratch.all_points; + all_points.resize (0); bool phantom_only = !consumer.is_consuming_contour_points (); - if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, nullptr, nullptr, true, true, phantom_only, coords))) + if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords))) return false; unsigned count = all_points.length; @@ -372,7 +367,12 @@ struct glyf_accelerator_t contour_point_t phantoms[glyf_impl::PHANTOM_COUNT]; if (font->num_coords) - success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false)); + { + hb_glyf_scratch_t scratch; + success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false), + hb_array (font->coords, font->num_coords), + scratch); + } if (unlikely (!success)) return @@ -392,9 +392,11 @@ struct glyf_accelerator_t if (unlikely (gid >= num_glyphs)) return false; hb_glyph_extents_t extents; - + hb_glyf_scratch_t scratch; contour_point_t phantoms[glyf_impl::PHANTOM_COUNT]; - if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false)))) + if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false), + hb_array (font->coords, font->num_coords), + scratch))) return false; *lsb = is_vertical @@ -420,7 +422,12 @@ struct glyf_accelerator_t #ifndef HB_NO_VAR if (font->num_coords) - return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true)); + { + hb_glyf_scratch_t scratch; + return get_points (font, gid, points_aggregator_t (font, extents, nullptr, true), + hb_array (font->coords, font->num_coords), + scratch); + } #endif return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents); } @@ -455,12 +462,19 @@ struct glyf_accelerator_t bool get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const - { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session)); } + { + hb_glyf_scratch_t scratch; + return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), + hb_array (font->coords, font->num_coords), + scratch); } bool get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session, - hb_array_t coords) const - { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); } + hb_array_t coords, + hb_glyf_scratch_t &scratch) const + { return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), + coords, + scratch); } #ifndef HB_NO_VAR const gvar_accelerator_t *gvar; diff --git a/src/hb-ot-var-gvar-table.hh b/src/hb-ot-var-gvar-table.hh index ff4fba3d2..0c4c2cd08 100644 --- a/src/hb-ot-var-gvar-table.hh +++ b/src/hb-ot-var-gvar-table.hh @@ -37,6 +37,35 @@ */ #define HB_OT_TAG_gvar HB_TAG('g','v','a','r') +struct hb_glyf_scratch_t +{ + contour_point_vector_t all_points; + contour_point_vector_t orig_points_vec; + hb_vector_t x_deltas; + hb_vector_t y_deltas; + contour_point_vector_t deltas_vec; + hb_vector_t private_indices; + hb_vector_t end_points; + hb_vector_t axisIndices; + hb_vector_t axisValues; + + void warm_up () + { + constexpr unsigned point_count = 64; + all_points.alloc (point_count); + orig_points_vec.alloc (point_count); + x_deltas.alloc (point_count); + y_deltas.alloc (point_count); + deltas_vec.alloc (point_count); + private_indices.alloc (point_count); + end_points.alloc (point_count >> 2); + + constexpr unsigned axis_count = 32; + axisIndices.alloc (axis_count); + axisValues.alloc (axis_count); + } +}; + namespace OT { struct GlyphVariationData : TupleVariationData @@ -86,10 +115,11 @@ struct glyph_variations_t 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; + hb_vector_t shared_indices; + /* 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 || @@ -627,6 +657,7 @@ struct gvar bool apply_deltas_to_points (hb_codepoint_t glyph, hb_array_t coords, const hb_array_t points, + hb_glyf_scratch_t &scratch, bool phantom_only = false) const { if (unlikely (glyph >= glyphCount)) return true; @@ -641,21 +672,25 @@ struct gvar return true; /* so isn't applied at all */ /* Save original points for inferred delta calculation */ - contour_point_vector_t orig_points_vec; // Populated lazily + auto &orig_points_vec = scratch.orig_points_vec; + orig_points_vec.clear (); // Populated lazily auto orig_points = orig_points_vec.as_array (); /* flag is used to indicate referenced point */ - contour_point_vector_t deltas_vec; // Populated lazily + auto &deltas_vec = scratch.deltas_vec; + deltas_vec.clear (); // Populated lazily auto deltas = deltas_vec.as_array (); - hb_vector_t end_points; // Populated lazily + auto &end_points = scratch.end_points; + end_points.clear (); // Populated lazily unsigned num_coords = table->axisCount; hb_array_t shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords); - hb_vector_t private_indices; - hb_vector_t x_deltas; - hb_vector_t y_deltas; + auto &private_indices = scratch.private_indices; + auto &x_deltas = scratch.x_deltas; + auto &y_deltas = scratch.y_deltas; + unsigned count = points.length; bool flush = false; do diff --git a/src/hb-vector.hh b/src/hb-vector.hh index 5d3e12cb0..f8640fd95 100644 --- a/src/hb-vector.hh +++ b/src/hb-vector.hh @@ -60,6 +60,15 @@ struct hb_vector_t alloc (hb_len (iter), true); hb_copy (iter, *this); } + template + void extend (const Iterable &o) + { + auto iter = hb_iter (o); + if (iter.is_random_access_iterator || iter.has_fast_len) + alloc (hb_len (iter), true); + hb_copy (iter, *this); + } hb_vector_t (const hb_vector_t &o) : hb_vector_t () { alloc_exact (o.length); @@ -437,6 +446,11 @@ struct hb_vector_t return alloc (size, true); } + void clear () + { + resize (0); + } + bool resize (int size_, bool initialize = true, bool exact = false) { unsigned int size = size_ < 0 ? 0u : (unsigned int) size_;