src/hb-font-private.hh | 97 ++++++++++++--------- src/hb-font.cc | 220 +++++++++++++++++++++++++++++++++---------------- src/hb-ft.cc | 70 ++++++++------- src/hb-ot-font.cc | 120 +++++++------------------- src/hb-ot-shape.cc | 38 ++++---- test/api/test-font.c | 2 6 files changed, 302 insertions(+), 245 deletions(-)
New commits: commit 5bc28b5f688ee90d103d052e98bc15d6e0e7e0b1 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 21:53:16 2015 -0800 Optimize positioning for when h_origin is nil diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 455ebab..e0331cd 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -654,22 +654,22 @@ hb_ot_position_default (hb_ot_shape_context_t *c) if (HB_DIRECTION_IS_HORIZONTAL (direction)) { for (unsigned int i = 0; i < count; i++) - { pos[i].x_advance = c->font->get_glyph_h_advance (info[i].codepoint); - c->font->subtract_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - } + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); } else { for (unsigned int i = 0; i < count; i++) - { pos[i].y_advance = c->font->get_glyph_v_advance (info[i].codepoint); - c->font->subtract_glyph_v_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); - } + if (c->font->has_glyph_v_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_v_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); } if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK) _hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer); @@ -719,17 +719,19 @@ hb_ot_position_complex (hb_ot_shape_context_t *c) /* Change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */ - for (unsigned int i = 0; i < count; i++) - c->font->add_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->add_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); c->plan->position (c->font, c->buffer); - for (unsigned int i = 0; i < count; i++) - c->font->subtract_glyph_h_origin (info[i].codepoint, - &pos[i].x_offset, - &pos[i].y_offset); + if (c->font->has_glyph_h_origin_func ()) + for (unsigned int i = 0; i < count; i++) + c->font->subtract_glyph_h_origin (info[i].codepoint, + &pos[i].x_offset, + &pos[i].y_offset); ret = true; } commit 762770c964f9f0591bf4c44427f73ea3e1c51733 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 21:42:55 2015 -0800 Add font->has_...() to check for individual nil font funcs Hopefully this wouldn't break any compiler. There was some magic moments to getting this to compile... diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 421bd02..efc12a8 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -63,12 +63,13 @@ struct hb_font_funcs_t { /* Don't access these directly. Call font->get_*() instead. */ - union { - struct { + union get_t { + struct get_funcs_t { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT } f; + void (*array[]) (void); } get; struct { @@ -146,6 +147,20 @@ struct hb_font_t { /* Public getters */ + HB_INTERNAL bool has_func (unsigned int i); + + /* has_* ... */ +#define HB_FONT_FUNC_IMPLEMENT(name) \ + bool \ + has_##name##_func (void) \ + { \ + hb_font_funcs_t *funcs = this->klass; \ + unsigned int i = offsetof (hb_font_funcs_t::get_t::get_funcs_t, name) / sizeof (funcs->get.array[0]); \ + return has_func (i); \ + } + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + inline hb_bool_t has_glyph (hb_codepoint_t unicode) { hb_codepoint_t glyph; diff --git a/src/hb-font.cc b/src/hb-font.cc index 9df71c0..33c644b 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -487,6 +487,13 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT +bool +hb_font_t::has_func (unsigned int i) +{ + if (parent && parent != hb_font_get_empty () && parent->has_func (i)) + return true; + return this->klass->get.array[i] != _hb_font_funcs_parent.get.array[i]; +} /* Public getters */ commit 88e9a9bcae61421d9dd65715d25e5f20b2847c03 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 21:16:26 2015 -0800 Minor reshaping of hb_font_funcs_t implementation In anticipation of further changes. No functional changes. diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index b969143..421bd02 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -63,10 +63,12 @@ struct hb_font_funcs_t { /* Don't access these directly. Call font->get_*() instead. */ - struct { + union { + struct { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS #undef HB_FONT_FUNC_IMPLEMENT + } f; } get; struct { @@ -154,85 +156,85 @@ struct hb_font_t { hb_codepoint_t *glyph) { *glyph = 0; - return klass->get.glyph (this, user_data, - unicode, variation_selector, glyph, - klass->user_data.glyph); + return klass->get.f.glyph (this, user_data, + unicode, variation_selector, glyph, + klass->user_data.glyph); } inline hb_position_t get_glyph_h_advance (hb_codepoint_t glyph) { - return klass->get.glyph_h_advance (this, user_data, - glyph, - klass->user_data.glyph_h_advance); + return klass->get.f.glyph_h_advance (this, user_data, + glyph, + klass->user_data.glyph_h_advance); } inline hb_position_t get_glyph_v_advance (hb_codepoint_t glyph) { - return klass->get.glyph_v_advance (this, user_data, - glyph, - klass->user_data.glyph_v_advance); + return klass->get.f.glyph_v_advance (this, user_data, + glyph, + klass->user_data.glyph_v_advance); } inline hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_h_origin (this, user_data, - glyph, x, y, - klass->user_data.glyph_h_origin); + return klass->get.f.glyph_h_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_h_origin); } inline hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_v_origin (this, user_data, - glyph, x, y, - klass->user_data.glyph_v_origin); + return klass->get.f.glyph_v_origin (this, user_data, + glyph, x, y, + klass->user_data.glyph_v_origin); } inline hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph, hb_codepoint_t right_glyph) { - return klass->get.glyph_h_kerning (this, user_data, - left_glyph, right_glyph, - klass->user_data.glyph_h_kerning); + return klass->get.f.glyph_h_kerning (this, user_data, + left_glyph, right_glyph, + klass->user_data.glyph_h_kerning); } inline hb_position_t get_glyph_v_kerning (hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph) { - return klass->get.glyph_v_kerning (this, user_data, - top_glyph, bottom_glyph, - klass->user_data.glyph_v_kerning); + return klass->get.f.glyph_v_kerning (this, user_data, + top_glyph, bottom_glyph, + klass->user_data.glyph_v_kerning); } inline hb_bool_t get_glyph_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) { memset (extents, 0, sizeof (*extents)); - return klass->get.glyph_extents (this, user_data, - glyph, - extents, - klass->user_data.glyph_extents); + return klass->get.f.glyph_extents (this, user_data, + glyph, + extents, + klass->user_data.glyph_extents); } inline hb_bool_t get_glyph_contour_point (hb_codepoint_t glyph, unsigned int point_index, hb_position_t *x, hb_position_t *y) { *x = *y = 0; - return klass->get.glyph_contour_point (this, user_data, - glyph, point_index, - x, y, - klass->user_data.glyph_contour_point); + return klass->get.f.glyph_contour_point (this, user_data, + glyph, point_index, + x, y, + klass->user_data.glyph_contour_point); } inline hb_bool_t get_glyph_name (hb_codepoint_t glyph, char *name, unsigned int size) { if (size) *name = '\0'; - return klass->get.glyph_name (this, user_data, - glyph, - name, size, - klass->user_data.glyph_name); + return klass->get.f.glyph_name (this, user_data, + glyph, + name, size, + klass->user_data.glyph_name); } inline hb_bool_t get_glyph_from_name (const char *name, int len, /* -1 means nul-terminated */ @@ -240,10 +242,10 @@ struct hb_font_t { { *glyph = 0; if (len == -1) len = strlen (name); - return klass->get.glyph_from_name (this, user_data, - name, len, - glyph, - klass->user_data.glyph_from_name); + return klass->get.f.glyph_from_name (this, user_data, + name, len, + glyph, + klass->user_data.glyph_from_name); } diff --git a/src/hb-font.cc b/src/hb-font.cc index a1f227c..9df71c0 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -474,11 +474,11 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ ffuncs->destroy.name (ffuncs->user_data.name); \ \ if (func) { \ - ffuncs->get.name = func; \ + ffuncs->get.f.name = func; \ ffuncs->user_data.name = user_data; \ ffuncs->destroy.name = destroy; \ } else { \ - ffuncs->get.name = hb_font_get_##name##_parent; \ + ffuncs->get.f.name = hb_font_get_##name##_parent; \ ffuncs->user_data.name = NULL; \ ffuncs->destroy.name = NULL; \ } \ commit a6a7715bac8b0c8f5473b84bc649c315ad4d2d51 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:51:21 2015 -0800 Comments diff --git a/src/hb-font-private.hh b/src/hb-font-private.hh index 952682d..b969143 100644 --- a/src/hb-font-private.hh +++ b/src/hb-font-private.hh @@ -61,7 +61,7 @@ struct hb_font_funcs_t { hb_bool_t immutable; - /* Don't access these directly. Call hb_font_get_*() instead. */ + /* Don't access these directly. Call font->get_*() instead. */ struct { #define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_func_t name; commit 6c48ec830ffac00a920d047ed77acd1b05549074 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:47:42 2015 -0800 [ot] Remove font funcs that do nothing diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index e68217d..8d33300 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -305,52 +305,6 @@ hb_ot_get_glyph_v_advance (hb_font_t *font HB_UNUSED, } static hb_bool_t -hb_ot_get_glyph_h_origin (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_position_t *x HB_UNUSED, - hb_position_t *y HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* We always work in the horizontal coordinates. */ - return true; -} - -static hb_bool_t -hb_ot_get_glyph_v_origin (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) -{ - /* TODO */ - return false; -} - -static hb_position_t -hb_ot_get_glyph_h_kerning (hb_font_t *font, - void *font_data, - hb_codepoint_t left_glyph, - hb_codepoint_t right_glyph, - void *user_data HB_UNUSED) -{ - /* TODO */ - return 0; -} - -static hb_position_t -hb_ot_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph HB_UNUSED, - hb_codepoint_t bottom_glyph HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* OpenType doesn't have vertical-kerning other than GPOS. */ - return 0; -} - -static hb_bool_t hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, void *font_data, hb_codepoint_t glyph, @@ -366,41 +320,6 @@ hb_ot_get_glyph_extents (hb_font_t *font HB_UNUSED, return ret; } -static hb_bool_t -hb_ot_get_glyph_contour_point (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - unsigned int point_index, - hb_position_t *x, - hb_position_t *y, - void *user_data HB_UNUSED) -{ - /* TODO */ - return false; -} - -static hb_bool_t -hb_ot_get_glyph_name (hb_font_t *font HB_UNUSED, - void *font_data, - hb_codepoint_t glyph, - char *name, unsigned int size, - void *user_data HB_UNUSED) -{ - /* TODO */ - return false; -} - -static hb_bool_t -hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, - void *font_data, - const char *name, int len, /* -1 means nul-terminated */ - hb_codepoint_t *glyph, - void *user_data HB_UNUSED) -{ - /* TODO */ - return false; -} - static hb_font_funcs_t *static_ot_funcs = NULL; @@ -425,14 +344,14 @@ retry: hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); - hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); - hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); - hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); - hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); + //hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); + //hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); TODO + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); - hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); - hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); - hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); + //hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); TODO + //hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); TODO + //hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); TODO hb_font_funcs_make_immutable (funcs); commit 75ea2daa1d9bbe235cd4a8570efb1913d58c3c62 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:43:59 2015 -0800 [ot] Port ot font funcs to allocated object diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 94c31b3..e68217d 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -402,22 +402,51 @@ hb_ot_get_glyph_from_name (hb_font_t *font HB_UNUSED, } +static hb_font_funcs_t *static_ot_funcs = NULL; + +#ifdef HB_USE_ATEXIT +static +void free_static_ot_funcs (void) +{ + hb_font_funcs_destroy (static_ot_funcs); +} +#endif + static hb_font_funcs_t * _hb_ot_get_font_funcs (void) { - static const hb_font_funcs_t ot_ffuncs = { - HB_OBJECT_HEADER_STATIC, +retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ot_funcs); - true, /* immutable */ - - { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_ot_get_##name, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); + + hb_font_funcs_set_glyph_func (funcs, hb_ot_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ot_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ot_get_glyph_v_advance, NULL, NULL); + hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ot_get_glyph_h_kerning, NULL, NULL); + hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ot_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ot_get_glyph_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ot_get_glyph_contour_point, NULL, NULL); + hb_font_funcs_set_glyph_name_func (funcs, hb_ot_get_glyph_name, NULL, NULL); + hb_font_funcs_set_glyph_from_name_func (funcs, hb_ot_get_glyph_from_name, NULL, NULL); + + hb_font_funcs_make_immutable (funcs); + + if (!hb_atomic_ptr_cmpexch (&static_ot_funcs, NULL, funcs)) { + hb_font_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_ot_funcs); /* First person registers atexit() callback. */ +#endif }; - return const_cast<hb_font_funcs_t *> (&ot_ffuncs); + return funcs; } commit 44f82750807475aa5b16099ccccd917d488df703 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:40:05 2015 -0800 [ft] Remove font funcs that do nothing diff --git a/src/hb-ft.cc b/src/hb-ft.cc index fc33b19..5630964 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -217,18 +217,6 @@ hb_ft_get_glyph_v_advance (hb_font_t *font HB_UNUSED, } static hb_bool_t -hb_ft_get_glyph_h_origin (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t glyph HB_UNUSED, - hb_position_t *x HB_UNUSED, - hb_position_t *y HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* We always work in the horizontal coordinates. */ - return true; -} - -static hb_bool_t hb_ft_get_glyph_v_origin (hb_font_t *font HB_UNUSED, void *font_data, hb_codepoint_t glyph, @@ -272,17 +260,6 @@ hb_ft_get_glyph_h_kerning (hb_font_t *font, return kerningv.x; } -static hb_position_t -hb_ft_get_glyph_v_kerning (hb_font_t *font HB_UNUSED, - void *font_data HB_UNUSED, - hb_codepoint_t top_glyph HB_UNUSED, - hb_codepoint_t bottom_glyph HB_UNUSED, - void *user_data HB_UNUSED) -{ - /* FreeType API doesn't support vertical kerning */ - return 0; -} - static hb_bool_t hb_ft_get_glyph_extents (hb_font_t *font HB_UNUSED, void *font_data, @@ -403,15 +380,17 @@ retry: hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); - hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); + //hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); - hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); + //hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL); hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL); hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL); + hb_font_funcs_make_immutable (funcs); + if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { hb_font_funcs_destroy (funcs); goto retry; commit 7918c261efd283e0428ce7836e9e42768a6aa05c Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:37:49 2015 -0800 [ft] Port ft font funcs to allocated object diff --git a/src/hb-ft.cc b/src/hb-ft.cc index 2b11882..fc33b19 100644 --- a/src/hb-ft.cc +++ b/src/hb-ft.cc @@ -380,23 +380,50 @@ hb_ft_get_glyph_from_name (hb_font_t *font HB_UNUSED, } +static hb_font_funcs_t *static_ft_funcs = NULL; + +#ifdef HB_USE_ATEXIT +static +void free_static_ft_funcs (void) +{ + hb_font_funcs_destroy (static_ft_funcs); +} +#endif + static void _hb_ft_font_set_funcs (hb_font_t *font, FT_Face ft_face, bool unref) { - static const hb_font_funcs_t ft_ffuncs = { - HB_OBJECT_HEADER_STATIC, - - true, /* immutable */ +retry: + hb_font_funcs_t *funcs = (hb_font_funcs_t *) hb_atomic_ptr_get (&static_ft_funcs); - { -#define HB_FONT_FUNC_IMPLEMENT(name) hb_ft_get_##name, - HB_FONT_FUNCS_IMPLEMENT_CALLBACKS -#undef HB_FONT_FUNC_IMPLEMENT + if (unlikely (!funcs)) + { + funcs = hb_font_funcs_create (); + + hb_font_funcs_set_glyph_func (funcs, hb_ft_get_glyph, NULL, NULL); + hb_font_funcs_set_glyph_h_advance_func (funcs, hb_ft_get_glyph_h_advance, NULL, NULL); + hb_font_funcs_set_glyph_v_advance_func (funcs, hb_ft_get_glyph_v_advance, NULL, NULL); + hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ft_get_glyph_h_origin, NULL, NULL); + hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ft_get_glyph_v_origin, NULL, NULL); + hb_font_funcs_set_glyph_h_kerning_func (funcs, hb_ft_get_glyph_h_kerning, NULL, NULL); + hb_font_funcs_set_glyph_v_kerning_func (funcs, hb_ft_get_glyph_v_kerning, NULL, NULL); + hb_font_funcs_set_glyph_extents_func (funcs, hb_ft_get_glyph_extents, NULL, NULL); + hb_font_funcs_set_glyph_contour_point_func (funcs, hb_ft_get_glyph_contour_point, NULL, NULL); + hb_font_funcs_set_glyph_name_func (funcs, hb_ft_get_glyph_name, NULL, NULL); + hb_font_funcs_set_glyph_from_name_func (funcs, hb_ft_get_glyph_from_name, NULL, NULL); + + if (!hb_atomic_ptr_cmpexch (&static_ft_funcs, NULL, funcs)) { + hb_font_funcs_destroy (funcs); + goto retry; } + +#ifdef HB_USE_ATEXIT + atexit (free_static_ft_funcs); /* First person registers atexit() callback. */ +#endif }; hb_font_set_funcs (font, - const_cast<hb_font_funcs_t *> (&ft_ffuncs), + funcs, _hb_ft_font_create (ft_face, unref), (hb_destroy_func_t) _hb_ft_font_destroy); } commit da29b43794cfa3f9a602c34b33c5d8a9c36f87b5 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Nov 4 20:22:44 2015 -0800 Separate nil font-funcs from parent-peeking font-funcs API change: all fonts created with hb_font_create() now inherit from (ie have parent) hb_font_get_empty(). diff --git a/src/hb-font.cc b/src/hb-font.cc index 6a69cae..a1f227c 100644 --- a/src/hb-font.cc +++ b/src/hb-font.cc @@ -45,130 +45,176 @@ */ static hb_bool_t -hb_font_get_glyph_nil (hb_font_t *font, +hb_font_get_glyph_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t unicode, hb_codepoint_t variation_selector, hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph (unicode, variation_selector, glyph); - *glyph = 0; return false; } +static hb_bool_t +hb_font_get_glyph_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t unicode, + hb_codepoint_t variation_selector, + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph (unicode, variation_selector, glyph); +} static hb_position_t -hb_font_get_glyph_h_advance_nil (hb_font_t *font, +hb_font_get_glyph_h_advance_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); - return font->x_scale; } +static hb_position_t +hb_font_get_glyph_h_advance_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_x_distance (font->parent->get_glyph_h_advance (glyph)); +} static hb_position_t -hb_font_get_glyph_v_advance_nil (hb_font_t *font, +hb_font_get_glyph_v_advance_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); - return font->y_scale; } +static hb_position_t +hb_font_get_glyph_v_advance_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_y_distance (font->parent->get_glyph_v_advance (glyph)); +} static hb_bool_t -hb_font_get_glyph_h_origin_nil (hb_font_t *font, +hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; return false; } +static hb_bool_t +hb_font_get_glyph_h_origin_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; +} static hb_bool_t -hb_font_get_glyph_v_origin_nil (hb_font_t *font, +hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; return false; } +static hb_bool_t +hb_font_get_glyph_v_origin_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; +} static hb_position_t -hb_font_get_glyph_h_kerning_nil (hb_font_t *font, +hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t left_glyph, hb_codepoint_t right_glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); - return 0; } +static hb_position_t +hb_font_get_glyph_h_kerning_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t left_glyph, + hb_codepoint_t right_glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_x_distance (font->parent->get_glyph_h_kerning (left_glyph, right_glyph)); +} static hb_position_t -hb_font_get_glyph_v_kerning_nil (hb_font_t *font, +hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t top_glyph, hb_codepoint_t bottom_glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); - return 0; } +static hb_position_t +hb_font_get_glyph_v_kerning_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t top_glyph, + hb_codepoint_t bottom_glyph, + void *user_data HB_UNUSED) +{ + return font->parent_scale_y_distance (font->parent->get_glyph_v_kerning (top_glyph, bottom_glyph)); +} static hb_bool_t -hb_font_get_glyph_extents_nil (hb_font_t *font, +hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, hb_glyph_extents_t *extents, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); - if (ret) { - font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); - font->parent_scale_distance (&extents->width, &extents->height); - } - return ret; - } - memset (extents, 0, sizeof (*extents)); return false; } +static hb_bool_t +hb_font_get_glyph_extents_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + hb_glyph_extents_t *extents, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_extents (glyph, extents); + if (ret) { + font->parent_scale_position (&extents->x_bearing, &extents->y_bearing); + font->parent_scale_distance (&extents->width, &extents->height); + } + return ret; +} static hb_bool_t -hb_font_get_glyph_contour_point_nil (hb_font_t *font, +hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, unsigned int point_index, @@ -176,44 +222,63 @@ hb_font_get_glyph_contour_point_nil (hb_font_t *font, hb_position_t *y, void *user_data HB_UNUSED) { - if (font->parent) { - hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); - if (ret) - font->parent_scale_position (x, y); - return ret; - } - *x = *y = 0; return false; } +static hb_bool_t +hb_font_get_glyph_contour_point_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + unsigned int point_index, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + hb_bool_t ret = font->parent->get_glyph_contour_point (glyph, point_index, x, y); + if (ret) + font->parent_scale_position (x, y); + return ret; +} static hb_bool_t -hb_font_get_glyph_name_nil (hb_font_t *font, +hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, hb_codepoint_t glyph, char *name, unsigned int size, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph_name (glyph, name, size); - if (size) *name = '\0'; return false; } +static hb_bool_t +hb_font_get_glyph_name_parent (hb_font_t *font, + void *font_data HB_UNUSED, + hb_codepoint_t glyph, + char *name, unsigned int size, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph_name (glyph, name, size); +} static hb_bool_t -hb_font_get_glyph_from_name_nil (hb_font_t *font, +hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED, void *font_data HB_UNUSED, const char *name, int len, /* -1 means nul-terminated */ hb_codepoint_t *glyph, void *user_data HB_UNUSED) { - if (font->parent) - return font->parent->get_glyph_from_name (name, len, glyph); - *glyph = 0; return false; } +static hb_bool_t +hb_font_get_glyph_from_name_parent (hb_font_t *font, + void *font_data HB_UNUSED, + const char *name, int len, /* -1 means nul-terminated */ + hb_codepoint_t *glyph, + void *user_data HB_UNUSED) +{ + return font->parent->get_glyph_from_name (name, len, glyph); +} static const hb_font_funcs_t _hb_font_funcs_nil = { @@ -227,6 +292,17 @@ static const hb_font_funcs_t _hb_font_funcs_nil = { #undef HB_FONT_FUNC_IMPLEMENT } }; +static const hb_font_funcs_t _hb_font_funcs_parent = { + HB_OBJECT_HEADER_STATIC, + + true, /* immutable */ + + { +#define HB_FONT_FUNC_IMPLEMENT(name) hb_font_get_##name##_parent, + HB_FONT_FUNCS_IMPLEMENT_CALLBACKS +#undef HB_FONT_FUNC_IMPLEMENT + } +}; /** @@ -246,7 +322,7 @@ hb_font_funcs_create (void) if (!(ffuncs = hb_object_create<hb_font_funcs_t> ())) return hb_font_funcs_get_empty (); - ffuncs->get = _hb_font_funcs_nil.get; + ffuncs->get = _hb_font_funcs_parent.get; return ffuncs; } @@ -263,7 +339,7 @@ hb_font_funcs_create (void) hb_font_funcs_t * hb_font_funcs_get_empty (void) { - return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_nil); + return const_cast<hb_font_funcs_t *> (&_hb_font_funcs_parent); } /** @@ -402,7 +478,7 @@ hb_font_funcs_set_##name##_func (hb_font_funcs_t *ffuncs, \ ffuncs->user_data.name = user_data; \ ffuncs->destroy.name = destroy; \ } else { \ - ffuncs->get.name = hb_font_get_##name##_nil; \ + ffuncs->get.name = hb_font_get_##name##_parent; \ ffuncs->user_data.name = NULL; \ ffuncs->destroy.name = NULL; \ } \ @@ -858,6 +934,7 @@ hb_font_create (hb_face_t *face) return hb_font_get_empty (); hb_face_make_immutable (face); + font->parent = hb_font_get_empty (); font->face = hb_face_reference (face); font->klass = hb_font_funcs_get_empty (); @@ -917,8 +994,8 @@ hb_font_get_empty (void) NULL, /* parent */ const_cast<hb_face_t *> (&_hb_face_nil), - 0, /* x_scale */ - 0, /* y_scale */ + 1000, /* x_scale */ + 1000, /* y_scale */ 0, /* x_ppem */ 0, /* y_ppem */ diff --git a/test/api/test-font.c b/test/api/test-font.c index ef5b08f..34f6c74 100644 --- a/test/api/test-font.c +++ b/test/api/test-font.c @@ -386,7 +386,7 @@ test_font_properties (void) g_assert (hb_font_get_face (font) == face); - g_assert (hb_font_get_parent (font) == NULL); + g_assert (hb_font_get_parent (font) == hb_font_get_empty ()); subfont = hb_font_create_sub_font (font); g_assert (hb_font_get_parent (subfont) == font); hb_font_set_parent(subfont, NULL); _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/harfbuzz