From a51958819fcf51ade3f8eb38001e680a419ebbba Mon Sep 17 00:00:00 2001 From: Behdad Esfahbod Date: Mon, 8 Oct 2018 23:57:45 -0400 Subject: [PATCH] Apply TrueType/OpenType kern table when GPOS kern feature is not available Fixes https://github.com/harfbuzz/harfbuzz/issues/250 --- src/hb-ot-kern-table.hh | 24 +++++++++------- src/hb-ot-layout.cc | 57 ++++++++++++++++--------------------- src/hb-ot-layout.hh | 13 +++++++++ src/hb-ot-shape-fallback.cc | 4 +-- src/hb-ot-shape.cc | 10 +++++-- src/hb-ot-shape.hh | 1 + 6 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index 6033bcce5..0af188e7c 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -37,14 +37,11 @@ struct hb_kern_machine_t { hb_kern_machine_t (const Driver &driver_) : driver (driver_) {} - inline void kern (const hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) const + inline void kern (hb_font_t *font, + hb_buffer_t *buffer, + hb_mask_t kern_mask) const { - if (!plan->kerning_requested) return; - OT::hb_ot_apply_context_t c (1, font, buffer); - hb_mask_t kern_mask = plan->kern_mask; c.set_lookup_mask (kern_mask); c.set_lookup_props (OT::LookupFlag::IgnoreMarks); OT::hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c.iter_input; @@ -411,6 +408,9 @@ struct kern { static const hb_tag_t tableTag = HB_OT_TAG_kern; + inline bool has_data (void) const + { return u.version32 != 0; } + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int table_length) const { switch (u.major) { @@ -444,22 +444,25 @@ struct kern hb_blob_destroy (blob); } + inline bool has_data (void) const + { return table->has_data (); } + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const { return table->get_h_kerning (left, right, table_length); } inline int get_kerning (hb_codepoint_t first, hb_codepoint_t second) const { return get_h_kerning (first, second); } - inline void apply (hb_ot_shape_plan_t *plan, - hb_font_t *font, - hb_buffer_t *buffer) const + inline void apply (hb_font_t *font, + hb_buffer_t *buffer, + hb_mask_t kern_mask) const { if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) return; hb_kern_machine_t machine (*this); - machine.kern (plan, font, buffer); + machine.kern (font, buffer, kern_mask); } private: @@ -471,6 +474,7 @@ struct kern protected: union { HBUINT16 major; + HBUINT32 version32; KernOT ot; KernAAT aat; } u; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 51c119858..975b7f8d4 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -45,17 +45,15 @@ #include "hb-ot-color-cpal-table.hh" #include "hb-ot-color-sbix-table.hh" #include "hb-ot-color-svg-table.hh" +#include "hb-ot-kern-table.hh" #include "hb-ot-name-table.hh" -// static inline const OT::BASE& -// _get_base (hb_face_t *face) -// { -// if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::BASE); -// hb_ot_face_data_t *data = hb_ot_face_data (face); -// return *(data->base.get ()); -// } - +static const OT::kern::accelerator_t& _get_kern (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::kern::accelerator_t); + return *hb_ot_face_data (face)->kern; +} const OT::GDEF& _get_gdef (hb_face_t *face) { if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::GDEF); @@ -91,6 +89,25 @@ const OT::GPOS& _get_gpos_relaxed (hb_face_t *face) } +/* + * kern + */ + +hb_bool_t +hb_ot_layout_has_kerning (hb_face_t *face) +{ + return _get_kern (face).has_data (); +} + +void +hb_ot_layout_kern (hb_font_t *font, + hb_buffer_t *buffer, + hb_mask_t kern_mask) +{ + _get_kern (font->face).apply (font, buffer, kern_mask); +} + + /* * GDEF */ @@ -1306,27 +1323,3 @@ hb_ot_layout_substitute_lookup (OT::hb_ot_apply_context_t *c, { apply_string (c, lookup, accel); } - - - - -/* - * OT::BASE - */ - -// /** -// * hb_ot_base_has_data: -// * @face: #hb_face_t to test -// * -// * This function allows to verify the presence of an OpenType BASE table on the -// * face. -// * -// * Return value: true if face has a BASE table, false otherwise -// * -// * Since: XXX -// **/ -// hb_bool_t -// hb_ot_base_has_data (hb_face_t *face) -// { -// return _get_base (face).has_data (); -// } diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index ac55459b6..f5ffe3112 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -49,6 +49,19 @@ HB_INTERNAL const OT::GSUB& _get_gsub_relaxed (hb_face_t *face); HB_INTERNAL const OT::GPOS& _get_gpos_relaxed (hb_face_t *face); +/* + * kern + */ + +HB_INTERNAL hb_bool_t +hb_ot_layout_has_kerning (hb_face_t *face); + +HB_INTERNAL void +hb_ot_layout_kern (hb_font_t *font, + hb_buffer_t *buffer, + hb_mask_t kern_mask); + + /* Private API corresponding to hb-ot-layout.h: */ HB_INTERNAL hb_bool_t diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index e1dd603ad..bf1fc8fbb 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -439,7 +439,7 @@ _hb_ot_shape_fallback_mark_position (const hb_ot_shape_plan_t *plan, void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, - hb_buffer_t *buffer) + hb_buffer_t *buffer) { struct driver_t { @@ -462,7 +462,7 @@ _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_kern_machine_t machine (driver); - machine.kern (plan, font, buffer); + machine.kern (font, buffer, plan->kern_mask); } diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index b8136b4ba..a9c0844e8 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -69,8 +69,8 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, bool disable_gpos = plan.shaper->gpos_tag && plan.shaper->gpos_tag != plan.map.chosen_script[1]; plan.apply_gpos = !disable_gpos && hb_ot_layout_has_positioning (face); - - plan.fallback_kerning = !plan.apply_gpos; + plan.apply_kern = !plan.apply_gpos && hb_ot_layout_has_kerning (face); + plan.fallback_kerning = !plan.apply_gpos && !plan.apply_kern; plan.fallback_mark_positioning = !plan.apply_gpos; plan.fallback_glyph_classes = !hb_ot_layout_has_glyph_classes (face); } @@ -835,7 +835,11 @@ hb_ot_position (const hb_ot_shape_context_t *c) /* Visual fallback goes here. */ - if (c->plan->fallback_kerning) + if (!c->plan->kerning_requested) + ; + else if (c->plan->apply_kern) + hb_ot_layout_kern (c->font, c->buffer, c->plan->kern_mask); + else if (c->plan->fallback_kerning) _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer); _hb_buffer_deallocate_gsubgpos_vars (c->buffer); diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 7a1e38542..43852d8ff 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -51,6 +51,7 @@ struct hb_ot_shape_plan_t bool fallback_mark_positioning : 1; bool apply_morx : 1; + bool apply_kern : 1; bool apply_gpos : 1;