diff --git a/src/hb-font.hh b/src/hb-font.hh index 4c8d0aeec..8b19dd715 100644 --- a/src/hb-font.hh +++ b/src/hb-font.hh @@ -502,8 +502,8 @@ struct hb_font_t hb_position_t *x, hb_position_t *y) { if (likely (HB_DIRECTION_IS_HORIZONTAL (direction))) { - *x = get_glyph_h_kerning (first_glyph, second_glyph); *y = 0; + *x = get_glyph_h_kerning (first_glyph, second_glyph); } else { *x = 0; *y = get_glyph_v_kerning (first_glyph, second_glyph); diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index e33b17396..f7c2ed380 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -28,6 +28,77 @@ #define HB_OT_KERN_TABLE_HH #include "hb-open-type.hh" +#include "hb-ot-shape.hh" +#include "hb-ot-layout-gsubgpos.hh" + + +template +struct hb_kern_machine_t +{ + hb_kern_machine_t (Driver &driver_) : driver (driver_) {} + + inline void kern (const hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) 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; + skippy_iter.init (&c); + + bool horizontal = HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction); + unsigned int count = buffer->len; + hb_glyph_info_t *info = buffer->info; + hb_glyph_position_t *pos = buffer->pos; + for (unsigned int idx = 0; idx < count;) + { + if (!(info[idx].mask & kern_mask)) + { + idx++; + continue; + } + + skippy_iter.reset (idx, 1); + if (!skippy_iter.next ()) + { + idx++; + continue; + } + + unsigned int i = idx; + unsigned int j = skippy_iter.idx; + hb_position_t kern = driver.get_kerning (info[i].codepoint, + info[j].codepoint); + + hb_position_t kern1 = kern >> 1; + hb_position_t kern2 = kern - kern1; + + if (horizontal) + { + pos[i].x_advance += kern1; + pos[j].x_advance += kern2; + pos[j].x_offset += kern2; + } + else + { + pos[i].y_advance += kern1; + pos[j].y_advance += kern2; + pos[j].y_offset += kern2; + } + + buffer->unsafe_to_break (i, j + 1); + + idx = skippy_iter.idx; + } + } + + Driver &driver; +}; + /* * kern -- Kerning diff --git a/src/hb-ot-shape-fallback.cc b/src/hb-ot-shape-fallback.cc index 6673abd14..920ef22c6 100644 --- a/src/hb-ot-shape-fallback.cc +++ b/src/hb-ot-shape-fallback.cc @@ -25,7 +25,7 @@ */ #include "hb-ot-shape-fallback.hh" -#include "hb-ot-layout-gsubgpos.hh" +#include "hb-ot-kern-table.hh" static unsigned int recategorize_combining_class (hb_codepoint_t u, @@ -435,67 +435,34 @@ _hb_ot_shape_fallback_position (const hb_ot_shape_plan_t *plan, } -/* Performs old-style TrueType kerning. */ +/* Performs font-assisted kerning. */ void _hb_ot_shape_fallback_kern (const hb_ot_shape_plan_t *plan, hb_font_t *font, hb_buffer_t *buffer) { - 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; - skippy_iter.init (&c); - - unsigned int count = buffer->len; - hb_glyph_info_t *info = buffer->info; - hb_glyph_position_t *pos = buffer->pos; - for (unsigned int idx = 0; idx < count;) + struct driver_t { - if (!(info[idx].mask & kern_mask)) + driver_t (hb_font_t *font_, + hb_buffer_t *buffer) : + font (font_), direction (buffer->props.direction) {} + + hb_position_t get_kerning (hb_codepoint_t first, hb_codepoint_t second) { - idx++; - continue; + hb_position_t kern = 0; + font->get_glyph_kerning_for_direction (first, second, + direction, + &kern, &kern); + return kern; } - skippy_iter.reset (idx, 1); - if (!skippy_iter.next ()) - { - idx++; - continue; - } + hb_font_t *font; + hb_direction_t direction; + } driver (font, buffer); - hb_position_t x_kern, y_kern; - font->get_glyph_kerning_for_direction (info[idx].codepoint, - info[skippy_iter.idx].codepoint, - buffer->props.direction, - &x_kern, &y_kern); + hb_kern_machine_t machine (driver); - if (x_kern) - { - hb_position_t kern1 = x_kern >> 1; - hb_position_t kern2 = x_kern - kern1; - pos[idx].x_advance += kern1; - pos[skippy_iter.idx].x_advance += kern2; - pos[skippy_iter.idx].x_offset += kern2; - buffer->unsafe_to_break (idx, skippy_iter.idx + 1); - } - - if (y_kern) - { - hb_position_t kern1 = y_kern >> 1; - hb_position_t kern2 = y_kern - kern1; - pos[idx].y_advance += kern1; - pos[skippy_iter.idx].y_advance += kern2; - pos[skippy_iter.idx].y_offset += kern2; - buffer->unsafe_to_break (idx, skippy_iter.idx + 1); - } - - idx = skippy_iter.idx; - } + machine.kern (plan, font, buffer); }