src/Makefile.sources | 1 src/hb-cache.hh | 75 +++++++++++++++++++++++++++++++++++ src/hb-ft.cc | 44 ++++++++++++++++++++ src/hb-ot-font.cc | 109 +++++++++++++++++++++++++++++++++++---------------- util/helper-cairo.cc | 2 util/options.cc | 6 ++ util/options.hh | 2 7 files changed, 203 insertions(+), 36 deletions(-)
New commits: commit f90bab8560816b60b4b3f2379b36c08756b21e6c Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 14:21:15 2018 +0200 [util] Add --ft-load-flags Useful for performance testing. Not hooked to cairo yet. Just changes shaping, not rasterization. diff --git a/util/helper-cairo.cc b/util/helper-cairo.cc index 3eaf90a7..5914ab74 100644 --- a/util/helper-cairo.cc +++ b/util/helper-cairo.cc @@ -125,7 +125,7 @@ helper_cairo_create_scaled_font (const font_options_t *font_opts) } #endif - cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0); + cairo_face = cairo_ft_font_face_create_for_ft_face (ft_face, font_opts->ft_load_flags); } cairo_matrix_t ctm, font_matrix; cairo_font_options_t *font_options; diff --git a/util/options.cc b/util/options.cc index 29028070..0ab16d62 100644 --- a/util/options.cc +++ b/util/options.cc @@ -556,6 +556,7 @@ font_options_t::add_options (option_parser_t *parser) {"font-ppem", 0, 0, G_OPTION_ARG_CALLBACK, (gpointer) &parse_font_ppem, "Set x,y pixels per EM (default: 0; disabled)", "1/2 integers"}, {"font-ptem", 0, 0, G_OPTION_ARG_DOUBLE, &this->ptem, "Set font point-size (default: 0; disabled)", "point-size"}, {"font-funcs", 0, 0, G_OPTION_ARG_STRING, &this->font_funcs, text, "impl"}, + {"ft-load-flags", 0, 0, G_OPTION_ARG_INT, &this->ft_load_flags, "Set FreeType load-flags (default: 2)", "integer"}, {nullptr} }; parser->add_group (entries, @@ -717,6 +718,9 @@ font_options_t::get_font (void) const } } set_font_funcs (font); +#ifdef HAVE_FREETYPE + hb_ft_font_set_load_flags (font, ft_load_flags); +#endif return font; } diff --git a/util/options.hh b/util/options.hh index 34579094..456e0a0f 100644 --- a/util/options.hh +++ b/util/options.hh @@ -454,6 +454,7 @@ struct font_options_t : option_group_t face_index = 0; font_size_x = font_size_y = default_font_size; font_funcs = nullptr; + ft_load_flags = 2; blob = nullptr; font = nullptr; @@ -484,6 +485,7 @@ struct font_options_t : option_group_t mutable double font_size_x; mutable double font_size_y; char *font_funcs; + int ft_load_flags; private: mutable hb_font_t *font; commit 93f7596254808d567b9e1e01fb4855efcd34677c Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 14:11:10 2018 +0200 [util] Add -n shorthand for --num-iterations Meh. diff --git a/util/options.cc b/util/options.cc index 57cc4aa8..29028070 100644 --- a/util/options.cc +++ b/util/options.cc @@ -419,7 +419,7 @@ shape_options_t::add_options (option_parser_t *parser) {"cluster-level", 0, 0, G_OPTION_ARG_INT, &this->cluster_level, "Cluster merging level (default: 0)", "0/1/2"}, {"normalize-glyphs",0, 0, G_OPTION_ARG_NONE, &this->normalize_glyphs, "Rearrange glyph clusters in nominal order", nullptr}, {"verify", 0, 0, G_OPTION_ARG_NONE, &this->verify, "Perform sanity checks on shaping results", nullptr}, - {"num-iterations", 0, 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, + {"num-iterations", 'n', 0, G_OPTION_ARG_INT, &this->num_iterations, "Run shaper N times (default: 1)", "N"}, {nullptr} }; parser->add_group (entries, commit 047a84c5dd76cdfc072de25c572e30866f87a1f7 Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 14:05:16 2018 +0200 [ft] Towards caching slow get_h_advance results Related to https://github.com/harfbuzz/harfbuzz/pull/1082 diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 5d78cdfb..856a9f79 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -239,14 +239,30 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, { const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; FT_Face ft_face = ft_font->ft_face; - int load_flags = ft_font->load_flags; + int load_flags; int mult = font->x_scale < 0 ? -1 : +1; - FT_Fixed v; - for (unsigned int i = 0; i < count; i++) + unsigned int i = 0; + + load_flags = ft_font->load_flags | FT_ADVANCE_FLAG_FAST_ONLY; + for (; i < count; i++) + { + FT_Fixed v = 0; + if (unlikely (FT_Get_Advance (ft_face, *first_glyph, load_flags, &v))) + goto slow; + *first_advance = (v * mult + (1<<9)) >> 10; + first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride); + first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride); + } + return; + +slow: + /* TODO Prepare and use cache. */ + load_flags = ft_font->load_flags;// & ~FT_ADVANCE_FLAG_FAST_ONLY; + for (; i < count; i++) { - v = 0; + FT_Fixed v = 0; FT_Get_Advance (ft_face, *first_glyph, load_flags, &v); *first_advance = (v * mult + (1<<9)) >> 10; first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride); commit 237f21537842e6b471cdd6c86b98edfc0da0756c Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 13:05:47 2018 +0200 [ft] Add advances() callback diff --git a/src/hb-ft.cc b/src/hb-ft.cc index ef38c743..5d78cdfb 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -228,6 +228,32 @@ hb_ft_get_glyph_h_advance (hb_font_t *font, return (v + (1<<9)) >> 10; } +static void +hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data, + unsigned count, + hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) +{ + const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data; + FT_Face ft_face = ft_font->ft_face; + int load_flags = ft_font->load_flags; + + int mult = font->x_scale < 0 ? -1 : +1; + FT_Fixed v; + + for (unsigned int i = 0; i < count; i++) + { + v = 0; + FT_Get_Advance (ft_face, *first_glyph, load_flags, &v); + *first_advance = (v * mult + (1<<9)) >> 10; + first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride); + first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride); + } +} + static hb_position_t hb_ft_get_glyph_v_advance (hb_font_t *font, void *font_data, @@ -433,6 +459,7 @@ static struct hb_ft_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ft hb_font_funcs_set_nominal_glyph_func (funcs, hb_ft_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ft_get_variation_glyph, nullptr, nullptr); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ft_get_glyph_h_advances, nullptr, nullptr); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, nullptr, nullptr); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, nullptr, nullptr); commit cbea7d49ab8d4765a2d72dcbf608d326bdf9af3d Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 12:56:17 2018 +0200 [ot-font] Rename diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 86aeb411..faacecb9 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -47,8 +47,8 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return ot_font->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return ot_face->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph); } static hb_bool_t @@ -59,8 +59,8 @@ hb_ot_get_variation_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return ot_font->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return ot_face->cmap.get_relaxed ()->get_variation_glyph (unicode, variation_selector, glyph); } static hb_position_t @@ -69,8 +69,8 @@ hb_ot_get_glyph_h_advance (hb_font_t *font, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return font->em_scale_x (ot_font->hmtx.get_relaxed ()->get_advance (glyph, font)); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return font->em_scale_x (ot_face->hmtx.get_relaxed ()->get_advance (glyph, font)); } static void @@ -82,8 +82,8 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, unsigned advance_stride, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - const OT::hmtx_accelerator_t &hmtx = *ot_font->hmtx.get_relaxed (); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx.get_relaxed (); for (unsigned int i = 0; i < count; i++) { @@ -99,8 +99,8 @@ hb_ot_get_glyph_v_advance (hb_font_t *font, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return font->em_scale_y (-(int) ot_font->vmtx.get_relaxed ()->get_advance (glyph, font)); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return font->em_scale_y (-(int) ot_face->vmtx.get_relaxed ()->get_advance (glyph, font)); } static void @@ -112,8 +112,8 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, unsigned advance_stride, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - const OT::vmtx_accelerator_t &vmtx = *ot_font->vmtx.get_relaxed (); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get_relaxed (); for (unsigned int i = 0; i < count; i++) { @@ -130,8 +130,8 @@ hb_ot_get_glyph_h_kerning (hb_font_t *font, hb_codepoint_t right_glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return font->em_scale_x (ot_font->kern->get_h_kerning (left_glyph, right_glyph)); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return font->em_scale_x (ot_face->kern->get_h_kerning (left_glyph, right_glyph)); } static hb_bool_t @@ -141,10 +141,10 @@ hb_ot_get_glyph_extents (hb_font_t *font, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - bool ret = ot_font->glyf->get_extents (glyph, extents); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + bool ret = ot_face->glyf->get_extents (glyph, extents); if (!ret) - ret = ot_font->CBDT->get_extents (glyph, extents); + ret = ot_face->CBDT->get_extents (glyph, extents); // TODO Hook up side-bearings variations. extents->x_bearing = font->em_scale_x (extents->x_bearing); extents->y_bearing = font->em_scale_y (extents->y_bearing); @@ -160,8 +160,8 @@ hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, char *name, unsigned int size, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return ot_font->post->get_glyph_name (glyph, name, size); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return ot_face->post->get_glyph_name (glyph, name, size); } static hb_bool_t @@ -171,8 +171,8 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - return ot_font->post->get_glyph_from_name (name, len, glyph); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + return ot_face->post->get_glyph_from_name (name, len, glyph); } static hb_bool_t @@ -181,12 +181,12 @@ hb_ot_get_font_h_extents (hb_font_t *font, hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - metrics->ascender = font->em_scale_y (ot_font->hmtx.get_relaxed ()->ascender); - metrics->descender = font->em_scale_y (ot_font->hmtx.get_relaxed ()->descender); - metrics->line_gap = font->em_scale_y (ot_font->hmtx.get_relaxed ()->line_gap); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + metrics->ascender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->ascender); + metrics->descender = font->em_scale_y (ot_face->hmtx.get_relaxed ()->descender); + metrics->line_gap = font->em_scale_y (ot_face->hmtx.get_relaxed ()->line_gap); // TODO Hook up variations. - return ot_font->hmtx.get_relaxed ()->has_font_extents; + return ot_face->hmtx.get_relaxed ()->has_font_extents; } static hb_bool_t @@ -195,19 +195,19 @@ hb_ot_get_font_v_extents (hb_font_t *font, hb_font_extents_t *metrics, void *user_data HB_UNUSED) { - const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; - metrics->ascender = font->em_scale_x (ot_font->vmtx.get_relaxed ()->ascender); - metrics->descender = font->em_scale_x (ot_font->vmtx.get_relaxed ()->descender); - metrics->line_gap = font->em_scale_x (ot_font->vmtx.get_relaxed ()->line_gap); + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + metrics->ascender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->ascender); + metrics->descender = font->em_scale_x (ot_face->vmtx.get_relaxed ()->descender); + metrics->line_gap = font->em_scale_x (ot_face->vmtx.get_relaxed ()->line_gap); // TODO Hook up variations. - return ot_font->vmtx.get_relaxed ()->has_font_extents; + return ot_face->vmtx.get_relaxed ()->has_font_extents; } #ifdef HB_USE_ATEXIT static void free_static_ot_funcs (void); #endif -static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_font_funcs_lazy_loader_t> +static struct hb_ot_face_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot_face_funcs_lazy_loader_t> { static inline hb_font_funcs_t *create (void) { @@ -264,15 +264,15 @@ void hb_ot_font_set_funcs (hb_font_t *font) { if (unlikely (!hb_ot_shaper_face_data_ensure (font->face))) return; - hb_ot_face_data_t *ot_font = hb_ot_face_data (font->face); + hb_ot_face_data_t *ot_face = hb_ot_face_data (font->face); /* Load them lazies. We access them with get_relaxed() for performance. */ - ot_font->cmap.get (); - ot_font->hmtx.get (); - ot_font->vmtx.get (); + ot_face->cmap.get (); + ot_face->hmtx.get (); + ot_face->vmtx.get (); hb_font_set_funcs (font, _hb_ot_get_font_funcs (), - ot_font, + ot_face, nullptr); } commit d8a67dac2a673138bb4d41cd7eab97c9ee987958 Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 12:55:54 2018 +0200 [ot-font] Add advances() callbacks diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index a4c5584f..86aeb411 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -46,7 +46,6 @@ hb_ot_get_nominal_glyph (hb_font_t *font HB_UNUSED, hb_codepoint_t unicode, hb_codepoint_t *glyph, void *user_data HB_UNUSED) - { const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; return ot_font->cmap.get_relaxed()->get_nominal_glyph (unicode, glyph); @@ -74,6 +73,26 @@ hb_ot_get_glyph_h_advance (hb_font_t *font, return font->em_scale_x (ot_font->hmtx.get_relaxed ()->get_advance (glyph, font)); } +static void +hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data, + unsigned count, + hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) +{ + const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; + const OT::hmtx_accelerator_t &hmtx = *ot_font->hmtx.get_relaxed (); + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_x (hmtx.get_advance (*first_glyph, font)); + first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride); + first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride); + } +} + static hb_position_t hb_ot_get_glyph_v_advance (hb_font_t *font, void *font_data, @@ -84,6 +103,26 @@ hb_ot_get_glyph_v_advance (hb_font_t *font, return font->em_scale_y (-(int) ot_font->vmtx.get_relaxed ()->get_advance (glyph, font)); } +static void +hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, + unsigned count, + hb_codepoint_t *first_glyph, + unsigned glyph_stride, + hb_position_t *first_advance, + unsigned advance_stride, + void *user_data HB_UNUSED) +{ + const hb_ot_face_data_t *ot_font = (const hb_ot_face_data_t *) font_data; + const OT::vmtx_accelerator_t &vmtx = *ot_font->vmtx.get_relaxed (); + + for (unsigned int i = 0; i < count; i++) + { + *first_advance = font->em_scale_y (-(int) vmtx.get_advance (*first_glyph, font)); + first_glyph = &StructAtOffset<hb_codepoint_t> (first_glyph, glyph_stride); + first_advance = &StructAtOffset<hb_position_t> (first_advance, advance_stride); + } +} + static hb_position_t hb_ot_get_glyph_h_kerning (hb_font_t *font, void *font_data, @@ -179,7 +218,9 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot hb_font_funcs_set_nominal_glyph_func (funcs, hb_ot_get_nominal_glyph, nullptr, nullptr); hb_font_funcs_set_variation_glyph_func (funcs, hb_ot_get_variation_glyph, nullptr, nullptr); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, nullptr, nullptr); + hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr); //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr); //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr); hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, nullptr, nullptr); commit 0ea42e117ba2c76e118974fe114ae5d9ceef5743 Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 12:22:42 2018 +0200 [cache] Minor diff --git a/src/hb-cache.hh b/src/hb-cache.hh index fd6a01e5..0858e11b 100644 --- a/src/hb-cache.hh +++ b/src/hb-cache.hh @@ -44,7 +44,7 @@ struct hb_cache_t inline void clear (void) { memset (values, 255, sizeof (values)); } - inline bool get (unsigned int key, unsigned int *value) + inline bool get (unsigned int key, unsigned int *value) const { unsigned int k = key & ((1u<<cache_bits)-1); unsigned int v = values[k].get_relaxed (); commit 0f520adaacca3c7b6d8e84a7722343184105f612 Author: Behdad Esfahbod <[email protected]> Date: Tue Sep 11 12:02:34 2018 +0200 Revert "Remove unused hb_cache_t" This reverts commit 473b17af4d421f4ce7ac18c769731bb2aa4088f8. Updates to recent changes. diff --git a/src/Makefile.sources b/src/Makefile.sources index 654255e2..46af3ae5 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -7,6 +7,7 @@ HB_BASE_sources = \ hb-buffer.hh \ hb-buffer-serialize.cc \ hb-buffer.cc \ + hb-cache.hh \ hb-common.cc \ hb-debug.hh \ hb-dsalgs.hh \ diff --git a/src/hb-cache.hh b/src/hb-cache.hh new file mode 100644 index 00000000..fd6a01e5 --- /dev/null +++ b/src/hb-cache.hh @@ -0,0 +1,75 @@ +/* + * Copyright © 2012 Google, Inc. + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * Google Author(s): Behdad Esfahbod + */ + +#ifndef HB_CACHE_HH +#define HB_CACHE_HH + +#include "hb.hh" + + +/* Implements a lock-free cache for int->int functions. */ + +template <unsigned int key_bits, unsigned int value_bits, unsigned int cache_bits> +struct hb_cache_t +{ + static_assert ((key_bits >= cache_bits), ""); + static_assert ((key_bits + value_bits - cache_bits < 8 * sizeof (unsigned int)), ""); + + inline void init (void) { clear (); } + inline void fini (void) {} + + inline void clear (void) + { memset (values, 255, sizeof (values)); } + + inline bool get (unsigned int key, unsigned int *value) + { + unsigned int k = key & ((1u<<cache_bits)-1); + unsigned int v = values[k].get_relaxed (); + if ((v >> value_bits) != (key >> cache_bits)) + return false; + *value = v & ((1u<<value_bits)-1); + return true; + } + + inline bool set (unsigned int key, unsigned int value) + { + if (unlikely ((key >> key_bits) || (value >> value_bits))) + return false; /* Overflows */ + unsigned int k = key & ((1u<<cache_bits)-1); + unsigned int v = ((key>>cache_bits)<<value_bits) | value; + values[k].set_relaxed (v); + return true; + } + + private: + hb_atomic_int_t values[1u<<cache_bits]; +}; + +typedef hb_cache_t<21, 16, 8> hb_cmap_cache_t; +typedef hb_cache_t<16, 24, 8> hb_advance_cache_t; + + +#endif /* HB_CACHE_HH */ diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 5d6abb29..ef38c743 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -33,6 +33,7 @@ #include "hb-font.hh" #include "hb-machinery.hh" +#include "hb-cache.hh" #include FT_ADVANCES_H #include FT_MULTIPLE_MASTERS_H _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
