src/hb-aat-layout-kerx-table.hh | 128 +++++++++++++++++++++++++++++++++------- src/hb-aat-layout-morx-table.hh | 4 - src/hb-ot-shape.cc | 50 ++++++++------- 3 files changed, 136 insertions(+), 46 deletions(-)
New commits: commit 9f450f07b0a1593962e3b45d00f2cf93916f3466 Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 21:46:58 2018 -0400 [kerx] Make Format1 work Tested using Kannada MN: $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD [kn_ka.virama=0+1299|kn_ka.vattu=0+115|_blank=0@-115,0+385] $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0C95,0CCd,C95,CCD --features=-kern [kn_ka.virama=0+1799|kn_ka.vattu=0+230|_blank=0+0] I don't see the GPOS table in the font do the same. ¯\_(ツ)_/¯ diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 552bb065..cc99868d 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -123,7 +123,7 @@ struct KerxSubTableFormat1 inline driver_context_t (const KerxSubTableFormat1 *table, hb_aat_apply_context_t *c_) : c (c_), - kernAction (table+table->kernAction), + kernAction (&table->machine + table->kernAction), depth (0) {} inline bool is_actionable (StateTableDriver<EntryData> *driver, @@ -159,16 +159,21 @@ struct KerxSubTableFormat1 return false; } - for (; depth; depth--) + for (unsigned int i = 0; i < depth; i++) { - unsigned int idx = stack[depth - 1]; + /* Apparently, when spec says "Each pops one glyph from the kerning stack + * and applies the kerning value to it.", it doesn't mean it in that order. + * The deepest item in the stack corresponds to the first item in the action + * list. Discovered by testing. */ + unsigned int idx = stack[i]; int v = *actions++; /* XXX Non-forward direction... */ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) - buffer->pos[idx].x_advance += v; + buffer->pos[idx].x_advance += c->font->em_scale_x (v); else - buffer->pos[idx].y_advance += v; + buffer->pos[idx].y_advance += c->font->em_scale_y (v); } + depth = 0; } return true; commit 504cb68fc972c7f606bf9fc62015376382f78f45 Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 21:29:46 2018 -0400 Disable mark advance zeroing as well as mark fallback positioning if doing kerx diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 3b1c93db..e2405237 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -114,7 +114,7 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, } plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); - if (!plan.apply_gpos) + if (!plan.apply_gpos && !plan.apply_kerx) plan.fallback_mark_positioning = true; } @@ -820,34 +820,36 @@ hb_ot_position_complex (const hb_ot_shape_context_t *c) hb_ot_layout_position_start (c->font, c->buffer); - switch (c->plan->shaper->zero_width_marks) - { - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: - zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); - break; - - default: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: - break; - } + if (!c->plan->apply_kerx) + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: + zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); + break; + + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: + break; + } if (c->plan->apply_gpos) - c->plan->position (c->font, c->buffer); + ;//c->plan->position (c->font, c->buffer); else if (c->plan->apply_kerx) hb_aat_layout_position (c->plan, c->font, c->buffer); - switch (c->plan->shaper->zero_width_marks) - { - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: - zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); - break; - - default: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: - case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: - break; - } + if (!c->plan->apply_kerx) + switch (c->plan->shaper->zero_width_marks) + { + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_LATE: + zero_mark_widths_by_gdef (c->buffer, adjust_offsets_when_zeroing); + break; + + default: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_NONE: + case HB_OT_SHAPE_ZERO_WIDTH_MARKS_BY_GDEF_EARLY: + break; + } /* Finishing off GPOS has to follow a certain order. */ hb_ot_layout_position_finish_advances (c->font, c->buffer); commit 84967537966a76297c89460d95e7336f1bfc332d Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 21:18:37 2018 -0400 [kerx] Implement Format1 Untested. diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index edc17a39..552bb065 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -101,9 +101,9 @@ struct KerxSubTableFormat1 { struct EntryData { - HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry - * for processing this group, if indicated - * by the flags. */ + HBUINT16 kernActionIndex;/* Index into the kerning value array. If + * this index is 0xFFFF, then no kerning + * is to be performed. */ public: DEFINE_SIZE_STATIC (2); }; @@ -120,25 +120,65 @@ struct KerxSubTableFormat1 Reserved = 0x1FFF, /* Not used; set to 0. */ }; - inline driver_context_t (const KerxSubTableFormat1 *table) - {} + inline driver_context_t (const KerxSubTableFormat1 *table, + hb_aat_apply_context_t *c_) : + c (c_), + kernAction (table+table->kernAction), + depth (0) {} inline bool is_actionable (StateTableDriver<EntryData> *driver, const Entry<EntryData> *entry) { - return false; // XXX return (entry->flags & Verb) && start < end; + return entry->data.kernActionIndex != 0xFFFF; } inline bool transition (StateTableDriver<EntryData> *driver, const Entry<EntryData> *entry) { - //hb_buffer_t *buffer = driver->buffer; - //unsigned int flags = entry->flags; + hb_buffer_t *buffer = driver->buffer; + unsigned int flags = entry->flags; + + if (flags & Reset) + { + depth = 0; + } + + if (flags & Push) + { + if (likely (depth < ARRAY_LENGTH (stack))) + stack[depth++] = buffer->idx; + else + depth = 0; /* Probably not what CoreText does, but better? */ + } + + if (entry->data.kernActionIndex != 0xFFFF) + { + const FWORD *actions = &kernAction[entry->data.kernActionIndex]; + if (!c->sanitizer.check_array (actions, depth)) + { + depth = 0; + return false; + } + + for (; depth; depth--) + { + unsigned int idx = stack[depth - 1]; + int v = *actions++; + /* XXX Non-forward direction... */ + if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) + buffer->pos[idx].x_advance += v; + else + buffer->pos[idx].y_advance += v; + } + } return true; } - public: private: + hb_aat_apply_context_t *c; + const UnsizedArrayOf<FWORD> &kernAction; + unsigned int stack[8]; + unsigned int depth; }; inline bool apply (hb_aat_apply_context_t *c) const @@ -148,7 +188,7 @@ struct KerxSubTableFormat1 if (!c->plan->requested_kerning) return false; - driver_context_t dc (this); + driver_context_t dc (this, c); StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); driver.drive (&dc); @@ -165,7 +205,7 @@ struct KerxSubTableFormat1 protected: KerxSubTableHeader header; StateTable<EntryData> machine; - LOffsetTo<UnsizedArrayOf<FWORD>, false> values; + LOffsetTo<UnsizedArrayOf<FWORD>, false> kernAction; public: DEFINE_SIZE_STATIC (32); }; diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 5de85126..b902fd79 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -365,7 +365,7 @@ struct LigatureSubtable inline bool is_actionable (StateTableDriver<EntryData> *driver, const Entry<EntryData> *entry) { - return !!(entry->flags & PerformAction); + return entry->flags & PerformAction; } inline bool transition (StateTableDriver<EntryData> *driver, const Entry<EntryData> *entry) commit c9165f5450b99e6d93e2a168b198384a221eef58 Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 20:43:21 2018 -0400 [kerx] More UnsizedArrayOf<> diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 0d3b330a..edc17a39 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -205,8 +205,7 @@ struct KerxSubTableFormat2 TRACE_SANITIZE (this); return_trace (likely (rowWidth.sanitize (c) && leftClassTable.sanitize (c, this) && - rightClassTable.sanitize (c, this) && - array.sanitize (c, this))); + rightClassTable.sanitize (c, this))); } struct accelerator_t @@ -233,7 +232,8 @@ struct KerxSubTableFormat2 LOffsetTo<Lookup<HBUINT16> > rightClassTable;/* Offset from beginning of this subtable to * right-hand class table. */ - LOffsetTo<FWORD> array; /* Offset from beginning of this subtable to + LOffsetTo<UnsizedArrayOf<FWORD>, false> + array; /* Offset from beginning of this subtable to * the start of the kerning array. */ public: DEFINE_SIZE_STATIC (28); @@ -324,12 +324,10 @@ struct KerxSubTableFormat6 is_long () ? ( u.l.rowIndexTable.sanitize (c, this) && - u.l.columnIndexTable.sanitize (c, this) && - u.l.array.sanitize (c, this) + u.l.columnIndexTable.sanitize (c, this) ) : ( u.s.rowIndexTable.sanitize (c, this) && - u.s.columnIndexTable.sanitize (c, this) && - u.s.array.sanitize (c, this) + u.s.columnIndexTable.sanitize (c, this) ))); } @@ -359,13 +357,15 @@ struct KerxSubTableFormat6 { LOffsetTo<Lookup<HBUINT32> > rowIndexTable; LOffsetTo<Lookup<HBUINT32> > columnIndexTable; - LOffsetTo<FWORD32> array; + LOffsetTo<UnsizedArrayOf<FWORD32>, false> + array; } l; struct Short { LOffsetTo<Lookup<HBUINT16> > rowIndexTable; LOffsetTo<Lookup<HBUINT16> > columnIndexTable; - LOffsetTo<FWORD> array; + LOffsetTo<UnsizedArrayOf<FWORD>, false> + array; } s; } u; public: commit ca54eba4846d0afda4601929556617a7ebe51714 Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 20:41:16 2018 -0400 [kerx] Fix bound-checking error introduced a couple commits past diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 4118d8ee..0d3b330a 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -180,7 +180,7 @@ struct KerxSubTableFormat2 unsigned int offset = l + r; const FWORD *v = &StructAtOffset<FWORD> (&(this+array), offset); if (unlikely ((const char *) v < (const char *) &array || - (const char *) v + v->static_size - (const char *) this <= header.length)) + (const char *) v + v->static_size - (const char *) this > header.length)) return 0; return *v; } @@ -284,7 +284,7 @@ struct KerxSubTableFormat6 unsigned int offset = l + r; const FWORD32 *v = &StructAtOffset<FWORD32> (&(this+t.array), offset * sizeof (FWORD32)); if (unlikely ((const char *) v < (const char *) &t.array || - (const char *) v + v->static_size - (const char *) this <= header.length)) + (const char *) v + v->static_size - (const char *) this > header.length)) return 0; return *v; } @@ -296,7 +296,7 @@ struct KerxSubTableFormat6 unsigned int offset = l + r; const FWORD *v = &StructAtOffset<FWORD> (&(this+t.array), offset * sizeof (FWORD)); if (unlikely ((const char *) v < (const char *) &t.array || - (const char *) v + v->static_size - (const char *) this <= header.length)) + (const char *) v + v->static_size - (const char *) this > header.length)) return 0; return *v; } commit 339036dd970625e03696b4533ced1e25fc4fd131 Author: Behdad Esfahbod <[email protected]> Date: Wed Oct 10 20:37:22 2018 -0400 [kerx] Start fleshing out Format1 diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 3cff334a..4118d8ee 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -99,6 +99,48 @@ struct KerxSubTableFormat0 struct KerxSubTableFormat1 { + struct EntryData + { + HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry + * for processing this group, if indicated + * by the flags. */ + public: + DEFINE_SIZE_STATIC (2); + }; + + struct driver_context_t + { + static const bool in_place = true; + enum Flags + { + Push = 0x8000, /* If set, push this glyph on the kerning stack. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph + * before going to the new state. */ + Reset = 0x2000, /* If set, reset the kerning data (clear the stack) */ + Reserved = 0x1FFF, /* Not used; set to 0. */ + }; + + inline driver_context_t (const KerxSubTableFormat1 *table) + {} + + inline bool is_actionable (StateTableDriver<EntryData> *driver, + const Entry<EntryData> *entry) + { + return false; // XXX return (entry->flags & Verb) && start < end; + } + inline bool transition (StateTableDriver<EntryData> *driver, + const Entry<EntryData> *entry) + { + //hb_buffer_t *buffer = driver->buffer; + //unsigned int flags = entry->flags; + + return true; + } + + public: + private: + }; + inline bool apply (hb_aat_apply_context_t *c) const { TRACE_APPLY (this); @@ -106,7 +148,10 @@ struct KerxSubTableFormat1 if (!c->plan->requested_kerning) return false; - /* TODO */ + driver_context_t dc (this); + + StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); + driver.drive (&dc); return_trace (true); } @@ -114,14 +159,13 @@ struct KerxSubTableFormat1 inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - stateHeader.sanitize (c))); + return_trace (likely (machine.sanitize (c))); } protected: - KerxSubTableHeader header; - StateTable<HBUINT16> stateHeader; - LOffsetTo<ArrayOf<HBUINT16> > valueTable; + KerxSubTableHeader header; + StateTable<EntryData> machine; + LOffsetTo<UnsizedArrayOf<FWORD>, false> values; public: DEFINE_SIZE_STATIC (32); }; @@ -159,8 +203,7 @@ struct KerxSubTableFormat2 inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (c->check_struct (this) && - rowWidth.sanitize (c) && + return_trace (likely (rowWidth.sanitize (c) && leftClassTable.sanitize (c, this) && rightClassTable.sanitize (c, this) && array.sanitize (c, this))); diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index 0020750c..5de85126 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -164,7 +164,7 @@ struct RearrangementSubtable driver_context_t dc (this); - StateTableDriver<void> driver (machine, c->buffer, c->face); + StateTableDriver<EntryData> driver (machine, c->buffer, c->face); driver.drive (&dc); return_trace (dc.ret); _______________________________________________ HarfBuzz mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/harfbuzz
