From 7b8ae3d067c5f026bb313943651ece71d704ee2a Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Thu, 13 Mar 2025 10:44:40 -0600 Subject: [PATCH] [kern/kerx] Make zero-malloc --- src/hb-aat-layout-common.hh | 52 +++++++++++++++++++++++++++++---- src/hb-aat-layout-kerx-table.hh | 27 ++++++++++------- src/hb-aat-layout-morx-table.hh | 1 + src/hb-aat-layout.cc | 6 ++++ src/hb-ot-kern-table.hh | 2 ++ src/hb-ot-layout.cc | 8 +++-- 6 files changed, 77 insertions(+), 19 deletions(-) diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 407372de7..a9064213d 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -50,6 +50,46 @@ struct ankr; using hb_aat_class_cache_t = hb_cache_t<15, 8, 7>; static_assert (sizeof (hb_aat_class_cache_t) == 256, ""); +struct hb_aat_scratch_t +{ + hb_aat_scratch_t () = default; + + hb_aat_scratch_t (hb_aat_scratch_t &&o) + { + buffer_glyph_set = o.buffer_glyph_set; + o.buffer_glyph_set = nullptr; + } + hb_aat_scratch_t & operator = (hb_aat_scratch_t &&o) + { + buffer_glyph_set = o.buffer_glyph_set; + o.buffer_glyph_set = nullptr; + return *this; + } + + hb_bit_set_t *create_buffer_glyph_set () const + { + hb_bit_set_t *s = buffer_glyph_set.get_acquire (); + if (s && buffer_glyph_set.cmpexch (s, nullptr)) + return s; + + s = (hb_bit_set_t *) hb_calloc (1, sizeof (hb_bit_set_t)); + if (unlikely (!s)) + return nullptr; + s->init (); + + return s; + } + void destroy_buffer_glyph_set (hb_bit_set_t *s) const + { + if (buffer_glyph_set.cmpexch (nullptr, s)) + return; + s->fini (); + hb_free (s); + } + + mutable hb_atomic_t buffer_glyph_set; +}; + enum { DELETED_GLYPH = 0xFFFF }; #define HB_BUFFER_SCRATCH_FLAG_AAT_HAS_DELETED HB_BUFFER_SCRATCH_FLAG_SHAPER0 @@ -74,7 +114,7 @@ struct hb_aat_apply_context_t : bool has_glyph_classes; const hb_sorted_vector_t *range_flags = nullptr; bool using_buffer_glyph_set = false; - hb_bit_set_t buffer_glyph_set; + hb_bit_set_t *buffer_glyph_set = nullptr; const hb_bit_set_t *left_set = nullptr; const hb_bit_set_t *right_set = nullptr; const hb_bit_set_t *machine_glyph_set = nullptr; @@ -100,12 +140,12 @@ struct hb_aat_apply_context_t : using_buffer_glyph_set = buffer->len >= 4; if (using_buffer_glyph_set) - buffer->collect_codepoints (buffer_glyph_set); + buffer->collect_codepoints (*buffer_glyph_set); } bool buffer_intersects_machine () const { if (using_buffer_glyph_set) - return buffer_glyph_set.intersects (*machine_glyph_set); + return buffer_glyph_set->intersects (*machine_glyph_set); // Faster for shorter buffers. for (unsigned i = 0; i < buffer->len; i++) @@ -118,7 +158,7 @@ struct hb_aat_apply_context_t : HB_NODISCARD bool output_glyphs (unsigned int count, const T *glyphs) { - buffer_glyph_set.add_array (glyphs, count); + buffer_glyph_set->add_array (glyphs, count); for (unsigned int i = 0; i < count; i++) { if (glyphs[i] == DELETED_GLYPH) @@ -144,7 +184,7 @@ struct hb_aat_apply_context_t : if (glyph == DELETED_GLYPH) return delete_glyph (); - buffer_glyph_set.add (glyph); + buffer_glyph_set->add (glyph); #ifndef HB_NO_OT_LAYOUT if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->cur(), @@ -163,7 +203,7 @@ struct hb_aat_apply_context_t : void replace_glyph_inplace (unsigned i, hb_codepoint_t glyph) { buffer->info[i].codepoint = glyph; - buffer_glyph_set.add (glyph); + buffer_glyph_set->add (glyph); #ifndef HB_NO_OT_LAYOUT if (has_glyph_classes) _hb_glyph_info_set_glyph_props (&buffer->info[i], diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 96f5ed6fd..e5b17ba1d 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -928,7 +928,11 @@ struct kern_subtable_accelerator_data_t mutable hb_aat_class_cache_t class_cache; }; -using kern_accelerator_data_t = hb_vector_t; +struct kern_accelerator_data_t +{ + hb_vector_t subtable_accels; + hb_aat_scratch_t scratch; +}; template struct KerxTable @@ -1005,16 +1009,18 @@ struct KerxTable { bool reverse; + auto &subtable_accel = accel_data.subtable_accels[i]; + if (!T::Types::extended && (st->u.header.coverage & st->u.header.Variation)) goto skip; if (HB_DIRECTION_IS_HORIZONTAL (c->buffer->props.direction) != st->u.header.is_horizontal ()) goto skip; - c->left_set = &accel_data[i].left_set; - c->right_set = &accel_data[i].right_set; - c->machine_glyph_set = &accel_data[i].left_set; - c->machine_class_cache = &accel_data[i].class_cache; + c->left_set = &subtable_accel.left_set; + c->right_set = &subtable_accel.right_set; + c->machine_glyph_set = &subtable_accel.left_set; + c->machine_class_cache = &subtable_accel.class_cache; if (!c->buffer_intersects_machine ()) { @@ -1123,12 +1129,12 @@ struct KerxTable unsigned int count = thiz()->tableCount; for (unsigned int i = 0; i < count; i++) { - kern_subtable_accelerator_data_t *accel = accel_data.push (); - if (unlikely (accel_data.in_error ())) - return accel_data; + auto &subtable_accel = *accel_data.subtable_accels.push (); + if (unlikely (accel_data.subtable_accels.in_error ())) + return accel_data; - st->collect_glyphs (accel->left_set, accel->right_set, num_glyphs); - accel->class_cache.clear (); + st->collect_glyphs (subtable_accel.left_set, subtable_accel.right_set, num_glyphs); + subtable_accel.class_cache.clear (); st = &StructAfter (*st); } @@ -1158,6 +1164,7 @@ struct KerxTable hb_blob_ptr_t table; kern_accelerator_data_t accel_data; + hb_aat_scratch_t scratch; }; }; diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 7aa820e33..663e47991 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -1375,6 +1375,7 @@ struct mortmorx hb_blob_ptr_t table; unsigned int chain_count; hb_atomic_t *accels; + hb_aat_scratch_t scratch; }; diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index b49614b3e..374554466 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -304,7 +304,10 @@ hb_aat_layout_substitute (const hb_ot_shape_plan_t *plan, { AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table morx")) return; + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); morx.apply (&c, num_features ? map : plan->aat_map, accel); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table morx"); return; } @@ -365,8 +368,11 @@ hb_aat_layout_position (const hb_ot_shape_plan_t *plan, AAT::hb_aat_apply_context_t c (plan, font, buffer, accel.get_blob ()); if (!buffer->message (font, "start table kerx")) return; + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); c.set_ankr_table (font->face->table.ankr.get ()); accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); + c.buffer_glyph_set = nullptr; (void) buffer->message (font, "end table kerx"); } diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index d11a913c7..338654501 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -27,6 +27,7 @@ #ifndef HB_OT_KERN_TABLE_HH #define HB_OT_KERN_TABLE_HH +#include "hb-aat-layout-common.hh" #include "hb-aat-layout-kerx-table.hh" @@ -400,6 +401,7 @@ struct kern hb_blob_ptr_t table; AAT::kern_accelerator_data_t accel_data; + AAT::hb_aat_scratch_t scratch; }; protected: diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index f7ad72fd4..3aca40eb7 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -131,13 +131,15 @@ hb_ot_layout_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - hb_blob_t *blob = font->face->table.kern.get_blob (); - const auto& kern = *font->face->table.kern; + auto &accel = *font->face->table.kern; + hb_blob_t *blob = accel.get_blob (); AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); if (!buffer->message (font, "start table kern")) return; - kern.apply (&c); + c.buffer_glyph_set = accel.scratch.create_buffer_glyph_set (); + accel.apply (&c); + accel.scratch.destroy_buffer_glyph_set (c.buffer_glyph_set); (void) buffer->message (font, "end table kern"); } #endif