diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index 8c436f990..311d61d5c 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -30,6 +30,8 @@ #include "hb-open-type.hh" #include "hb-ot-shape.hh" #include "hb-ot-layout-gsubgpos.hh" +#include "hb-aat-layout-ankr-table.hh" // Ugly but needed. +#include "hb-aat-layout-common.hh" template @@ -165,6 +167,19 @@ struct KernSubTableFormat0 return pairs[i].get_kerning (); } + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + hb_kern_machine_t machine (*this); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -196,7 +211,8 @@ struct KernClassTable struct KernSubTableFormat2 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, + AAT::hb_aat_apply_context_t *c) const { /* This subtable is disabled. It's not cleaer to me *exactly* where the offests are * based from. I *think* they should be based from beginning of kern subtable wrapper, @@ -208,12 +224,41 @@ struct KernSubTableFormat2 unsigned int r = (this+rightClassTable).get_class (right); unsigned int offset = l + r; const FWORD *v = &StructAtOffset (&(this+array), offset); +#if 0 if (unlikely ((const char *) v < (const char *) &array || (const char *) v > (const char *) end - 2)) +#endif return 0; return *v; } + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + accelerator_t accel (*this, c); + hb_kern_machine_t machine (accel); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + + struct accelerator_t + { + const KernSubTableFormat2 &table; + AAT::hb_aat_apply_context_t *c; + + inline accelerator_t (const KernSubTableFormat2 &table_, + AAT::hb_aat_apply_context_t *c_) : + table (table_), c (c_) {} + + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return table.get_kerning (left, right, c); } + }; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -241,7 +286,7 @@ struct KernSubTableFormat2 struct KernSubTableFormat3 { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const { hb_array_t kernValue = kernValueZ.as_array (kernValueCount); hb_array_t leftClass = StructAfter > (kernValue).as_array (glyphCount); @@ -252,6 +297,19 @@ struct KernSubTableFormat3 return kernValue[kernIndex[i]]; } + inline bool apply (AAT::hb_aat_apply_context_t *c) const + { + TRACE_APPLY (this); + + if (!c->plan->requested_kerning) + return false; + + hb_kern_machine_t machine (*this); + machine.kern (c->font, c->buffer, c->plan->kern_mask); + + return_trace (true); + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -289,16 +347,26 @@ struct KernSubTableFormat3 struct KernSubTable { - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end, unsigned int format) const + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, unsigned int format) const { switch (format) { + /* This method hooks up to hb_font_t's get_h_kerning. Only support Format0. */ case 0: return u.format0.get_kerning (left, right); - case 2: return u.format2.get_kerning (left, right, end); - case 3: return u.format3.get_kerning (left, right, end); default:return 0; } } + inline void apply (AAT::hb_aat_apply_context_t *c, unsigned int format) const + { + /* TODO Switch to dispatch(). */ + switch (format) { + case 0: u.format0.apply (c); return; + case 2: u.format2.apply (c); return; + case 3: u.format3.apply (c); return; + default: return; + } + } + inline bool sanitize (hb_sanitize_context_t *c, unsigned int format) const { TRACE_SANITIZE (this); @@ -333,11 +401,14 @@ struct KernSubTableWrapper inline bool is_override (void) const { return bool (thiz()->coverage & T::Override); } - inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return thiz()->subtable.get_kerning (left, right, end, thiz()->format); } + inline int get_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return thiz()->subtable.get_kerning (left, right, thiz()->format); } - inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right, const char *end) const - { return is_horizontal () ? get_kerning (left, right, end) : 0; } + inline int get_h_kerning (hb_codepoint_t left, hb_codepoint_t right) const + { return is_horizontal () ? get_kerning (left, right) : 0; } + + inline void apply (AAT::hb_aat_apply_context_t *c) const + { thiz()->subtable.apply (c, thiz()->format); } inline unsigned int get_size (void) const { return thiz()->length; } @@ -366,12 +437,43 @@ struct KernTable { if (st->is_override ()) v = 0; - v += st->get_h_kerning (left, right, st->length + (const char *) st); + v += st->get_h_kerning (left, right); st = &StructAfter (*st); } return v; } + inline void apply (AAT::hb_aat_apply_context_t *c) const + { + c->set_lookup_index (0); + const typename T::SubTableWrapper *st = CastP (&thiz()->dataZ); + unsigned int count = thiz()->nTables; + /* If there's an override subtable, skip subtables before that. */ + unsigned int last_override = 0; + for (unsigned int i = 0; i < count; i++) + { + if (st->is_override ()) + last_override = i; + st = &StructAfter (*st); + } + st = CastP (&thiz()->dataZ); + for (unsigned int i = 0; i < count; i++) + { + if (i < last_override) + goto skip; + + if (!c->buffer->message (c->font, "start kern subtable %d", c->lookup_index)) + goto skip; + + st->apply (c); + + (void) c->buffer->message (c->font, "end kern subtable %d", c->lookup_index); + + skip: + st = &StructAfter (*st); + } + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -492,6 +594,16 @@ struct kern } } + inline void apply (AAT::hb_aat_apply_context_t *c) const + { + /* TODO Switch to dispatch(). */ + switch (u.major) { + case 0: u.ot.apply (c); return; + case 1: u.aat.apply (c); return; + default: return; + } + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -503,27 +615,6 @@ struct kern } } - inline int get_kerning (hb_codepoint_t first, hb_codepoint_t second) const - { return get_h_kerning (first, second); } - - inline void apply (hb_font_t *font, - hb_buffer_t *buffer, - hb_mask_t kern_mask) const - { - /* We only apply horizontal kerning in this table. */ - if (!HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) - return; - - hb_kern_machine_t machine (*this); - - if (!buffer->message (font, "start kern table")) - return; - - machine.kern (font, buffer, kern_mask); - - (void) buffer->message (font, "end kern table"); - } - protected: union { HBUINT32 version32; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index f4ae840b6..b81aabd20 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -55,10 +55,19 @@ **/ -static const OT::kern& _get_kern (hb_face_t *face) +static inline const OT::kern& +_get_kern (hb_face_t *face, hb_blob_t **blob = nullptr) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(OT::kern); - return *hb_ot_face_data (face)->kern; + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) + { + if (blob) + *blob = hb_blob_get_empty (); + return Null(OT::kern); + } + const OT::kern& kern = *(hb_ot_face_data (face)->kern.get ()); + if (blob) + *blob = hb_ot_face_data (face)->kern.get_blob (); + return kern; } const OT::GDEF& _get_gdef (hb_face_t *face) { @@ -106,11 +115,16 @@ hb_ot_layout_has_kerning (hb_face_t *face) } void -hb_ot_layout_kern (hb_font_t *font, - hb_buffer_t *buffer, - hb_mask_t kern_mask) +hb_ot_layout_kern (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer) { - _get_kern (font->face).apply (font, buffer, kern_mask); + hb_blob_t *blob; + const AAT::kern& kern = _get_kern (font->face, &blob); + + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + + kern.apply (&c); } diff --git a/src/hb-ot-layout.hh b/src/hb-ot-layout.hh index 64b3d7480..b29f87c5a 100644 --- a/src/hb-ot-layout.hh +++ b/src/hb-ot-layout.hh @@ -34,6 +34,7 @@ #include "hb-font.hh" #include "hb-buffer.hh" #include "hb-open-type.hh" +#include "hb-ot-shape.hh" #include "hb-set-digest.hh" @@ -48,6 +49,7 @@ HB_INTERNAL const OT::GDEF& _get_gdef (hb_face_t *face); HB_INTERNAL const OT::GSUB& _get_gsub_relaxed (hb_face_t *face); HB_INTERNAL const OT::GPOS& _get_gpos_relaxed (hb_face_t *face); +struct hb_ot_shape_plan_t; /* * kern @@ -57,9 +59,9 @@ 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); +hb_ot_layout_kern (hb_ot_shape_plan_t *plan, + hb_font_t *font, + hb_buffer_t *buffer); /* Private API corresponding to hb-ot-layout.h: */ diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index c55d8dcb8..b687996f6 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -918,7 +918,7 @@ hb_ot_position (const hb_ot_shape_context_t *c) /* Visual fallback goes here. */ if (c->plan->apply_kern) - hb_ot_layout_kern (c->font, c->buffer, c->plan->kern_mask); + hb_ot_layout_kern (c->plan, c->font, c->buffer); else if (c->plan->fallback_kerning) _hb_ot_shape_fallback_kern (c->plan, c->font, c->buffer);