mirror of
https://github.com/harfbuzz/harfbuzz.git
synced 2025-04-13 08:42:59 +00:00
[VARC] Reduce malloc overhead
This commit is contained in:
parent
2099db378a
commit
76c3beaf36
7 changed files with 116 additions and 36 deletions
|
@ -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<unsigned> axisIndices;
|
||||
hb_vector_t<float> 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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 <typename accelerator_t>
|
||||
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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -206,21 +206,16 @@ struct glyf_accelerator_t
|
|||
protected:
|
||||
template<typename T>
|
||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
|
||||
hb_array_t<const int> coords = hb_array_t<const int> ()) const
|
||||
hb_array_t<const int> 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<const int> coords) const
|
||||
{ return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session), coords); }
|
||||
hb_array_t<const int> 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;
|
||||
|
|
|
@ -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<int> x_deltas;
|
||||
hb_vector_t<int> y_deltas;
|
||||
contour_point_vector_t deltas_vec;
|
||||
hb_vector_t<unsigned int> private_indices;
|
||||
hb_vector_t<unsigned> end_points;
|
||||
hb_vector_t<unsigned> axisIndices;
|
||||
hb_vector_t<float> 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<const GlyphVariationData*> (var_data.arrayZ);
|
||||
hb_vector_t<unsigned> shared_indices;
|
||||
GlyphVariationData::tuple_iterator_t iterator;
|
||||
tuple_variations_t tuple_vars;
|
||||
|
||||
hb_vector_t<unsigned> 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<const int> coords,
|
||||
const hb_array_t<contour_point_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<unsigned> end_points; // Populated lazily
|
||||
auto &end_points = scratch.end_points;
|
||||
end_points.clear (); // Populated lazily
|
||||
|
||||
unsigned num_coords = table->axisCount;
|
||||
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * num_coords);
|
||||
|
||||
hb_vector_t<unsigned int> private_indices;
|
||||
hb_vector_t<int> x_deltas;
|
||||
hb_vector_t<int> 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
|
||||
|
|
|
@ -60,6 +60,15 @@ struct hb_vector_t
|
|||
alloc (hb_len (iter), true);
|
||||
hb_copy (iter, *this);
|
||||
}
|
||||
template <typename Iterable,
|
||||
hb_requires (hb_is_iterable (Iterable))>
|
||||
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_;
|
||||
|
|
Loading…
Add table
Reference in a new issue