src/hb-aat-layout-ankr-table.hh | 25 +++++- src/hb-aat-layout-common.hh | 11 ++ src/hb-aat-layout-kerx-table.hh | 154 ++++++++++++++++++++++++++++++++++++++-- src/hb-aat-layout.cc | 20 ++++- src/hb-ot-layout-gpos-table.hh | 4 - 5 files changed, 198 insertions(+), 16 deletions(-)
New commits: commit fbbd926dba163d9a2a6a62f380951f03363c2b14 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Oct 11 01:22:29 2018 -0400 [kerx] Implement Format4 action_type=1 contour-point-based attachment Untested. This concludes kerx table support! diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index a54e2978..cd112912 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -354,7 +354,22 @@ struct KerxSubTableFormat4 return false; HB_UNUSED unsigned int markControlPoint = *data++; HB_UNUSED unsigned int currControlPoint = *data++; - /* TODO */ + hb_position_t markX = 0; + hb_position_t markY = 0; + hb_position_t currX = 0; + hb_position_t currY = 0; + if (!c->font->get_glyph_contour_point_for_origin (c->buffer->info[mark].codepoint, + markControlPoint, + HB_DIRECTION_LTR /*XXX*/, + &markX, &markY) || + !c->font->get_glyph_contour_point_for_origin (c->buffer->cur ().codepoint, + currControlPoint, + HB_DIRECTION_LTR /*XXX*/, + &currX, &currY)) + return true; /* True, such that the machine continues. */ + + o.x_offset = markX - currX; + o.y_offset = markY - currY; } break; commit b6bc0d4ff62e4509643db3b304306a72bbcb2c38 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Oct 11 01:17:57 2018 -0400 [kerx] Implement Format4 action_type=2 coordinate-based attachment Untested. diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 019efd57..a54e2978 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -343,6 +343,7 @@ struct KerxSubTableFormat4 if (mark_set && entry->data.ankrActionIndex != 0xFFFF) { + hb_glyph_position_t &o = buffer->cur_pos(); switch (action_type) { case 0: /* Control Point Actions.*/ @@ -373,12 +374,9 @@ struct KerxSubTableFormat4 currAnchorPoint, c->face->get_num_glyphs (), c->ankr_end); - hb_glyph_position_t &o = buffer->cur_pos(); + o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate); o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate); - o.attach_type() = ATTACH_TYPE_MARK; - o.attach_chain() = (int) mark - (int) buffer->idx; - buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; } break; @@ -387,14 +385,19 @@ struct KerxSubTableFormat4 const FWORD *data = (const FWORD *) &ankrData[entry->data.ankrActionIndex]; if (!c->sanitizer.check_array (data, 4)) return false; - HB_UNUSED int markX = *data++; - HB_UNUSED int markY = *data++; - HB_UNUSED int currX = *data++; - HB_UNUSED int currY = *data++; - /* TODO */ + int markX = *data++; + int markY = *data++; + int currX = *data++; + int currY = *data++; + + o.x_offset = c->font->em_scale_x (markX) - c->font->em_scale_x (currX); + o.y_offset = c->font->em_scale_y (markY) - c->font->em_scale_y (currY); } break; } + o.attach_type() = ATTACH_TYPE_MARK; + o.attach_chain() = (int) mark - (int) buffer->idx; + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; } if (flags & Mark) commit 1622ba5943d14b2d50d45dc17fb723f4c9ddb0bb Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Oct 11 01:14:18 2018 -0400 [kerx] Implement Format4 'ankr'-based mark attachment Tested with Kannada MN: $ HB_OPTIONS=aat ./hb-shape Kannada\ MN.ttc -u 0CCD,0C95,0CD6 [kn_ka.vattu=0+230|kn_ai_length_mark=1@326,0+607] diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index dada9c7a..78de04fa 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -531,6 +531,7 @@ struct hb_aat_apply_context_t : hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; const ankr &ankr_table; + const char *ankr_end; /* Unused. For debug tracing only. */ unsigned int lookup_index; @@ -540,9 +541,12 @@ struct hb_aat_apply_context_t : hb_font_t *font_, hb_buffer_t *buffer_, hb_blob_t *table, - const ankr &ankr_table_ = Null(ankr)) : + const ankr &ankr_table_ = Null(ankr), + const char *ankr_end_ = nullptr) : plan (plan_), font (font_), face (font->face), buffer (buffer_), - sanitizer (), ankr_table (ankr_table_), lookup_index (0), debug_depth (0) + sanitizer (), + ankr_table (ankr_table_), ankr_end (ankr_end_), + lookup_index (0), debug_depth (0) { sanitizer.init (table); sanitizer.set_num_glyphs (face->get_num_glyphs ()); diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index c109d003..019efd57 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -30,6 +30,7 @@ #include "hb-open-type.hh" #include "hb-aat-layout-common.hh" +#include "hb-ot-layout-gpos-table.hh" #include "hb-ot-kern-table.hh" /* @@ -362,9 +363,22 @@ struct KerxSubTableFormat4 const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex]; if (!c->sanitizer.check_array (data, 2)) return false; - HB_UNUSED unsigned int markAnchorPoint = *data++; - HB_UNUSED unsigned int currAnchorPoint = *data++; - /* TODO */ + unsigned int markAnchorPoint = *data++; + unsigned int currAnchorPoint = *data++; + const Anchor markAnchor = c->ankr_table.get_anchor (c->buffer->info[mark].codepoint, + markAnchorPoint, + c->face->get_num_glyphs (), + c->ankr_end); + const Anchor currAnchor = c->ankr_table.get_anchor (c->buffer->cur ().codepoint, + currAnchorPoint, + c->face->get_num_glyphs (), + c->ankr_end); + hb_glyph_position_t &o = buffer->cur_pos(); + o.x_offset = c->font->em_scale_x (markAnchor.xCoordinate) - c->font->em_scale_x (currAnchor.xCoordinate); + o.y_offset = c->font->em_scale_y (markAnchor.yCoordinate) - c->font->em_scale_y (currAnchor.yCoordinate); + o.attach_type() = ATTACH_TYPE_MARK; + o.attach_chain() = (int) mark - (int) buffer->idx; + buffer->scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT; } break; diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 47462ad7..73ab06d3 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -69,10 +69,18 @@ _get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr) return kerx; } static inline const AAT::ankr& -_get_ankr (hb_face_t *face) +_get_ankr (hb_face_t *face, hb_blob_t **blob = nullptr) { - if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::ankr); - return *(hb_ot_face_data (face)->ankr.get ()); + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) + { + if (blob) + *blob = hb_blob_get_empty (); + return Null(AAT::ankr); + } + const AAT::ankr& ankr = *(hb_ot_face_data (face)->ankr.get ()); + if (blob) + *blob = hb_ot_face_data (face)->ankr.get_blob (); + return ankr; } @@ -109,6 +117,10 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan, hb_blob_t *blob; const AAT::kerx& kerx = _get_kerx (font->face, &blob); - AAT::hb_aat_apply_context_t c (plan, font, buffer, blob, _get_ankr (font->face)); + hb_blob_t *ankr_blob; + const AAT::ankr& ankr = _get_ankr (font->face, &ankr_blob); + + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob, + ankr, ankr_blob->data + ankr_blob->length); kerx.apply (&c); } diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 1a96609d..746c2462 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -1755,10 +1755,6 @@ template <typename context_t> struct GPOS_accelerator_t : GPOS::accelerator_t {}; -#undef attach_chain -#undef attach_type - - } /* namespace OT */ commit 7bb4da7d9538f3d4b1d28030d43e0c3d720d821b Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Oct 11 00:52:07 2018 -0400 [aat] Wire up 'ankr' table to apply context diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 37ab5353..dada9c7a 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -514,6 +514,7 @@ struct StateTableDriver }; +struct ankr; struct hb_aat_apply_context_t : hb_dispatch_context_t<hb_aat_apply_context_t, bool, HB_DEBUG_APPLY> @@ -529,6 +530,7 @@ struct hb_aat_apply_context_t : hb_face_t *face; hb_buffer_t *buffer; hb_sanitize_context_t sanitizer; + const ankr &ankr_table; /* Unused. For debug tracing only. */ unsigned int lookup_index; @@ -537,9 +539,10 @@ struct hb_aat_apply_context_t : inline hb_aat_apply_context_t (hb_ot_shape_plan_t *plan_, hb_font_t *font_, hb_buffer_t *buffer_, - hb_blob_t *table) : + hb_blob_t *table, + const ankr &ankr_table_ = Null(ankr)) : plan (plan_), font (font_), face (font->face), buffer (buffer_), - sanitizer (), lookup_index (0), debug_depth (0) + sanitizer (), ankr_table (ankr_table_), lookup_index (0), debug_depth (0) { sanitizer.init (table); sanitizer.set_num_glyphs (face->get_num_glyphs ()); diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc index 3fd4f9f8..47462ad7 100644 --- a/src/hb-aat-layout.cc +++ b/src/hb-aat-layout.cc @@ -68,6 +68,12 @@ _get_kerx (hb_face_t *face, hb_blob_t **blob = nullptr) *blob = hb_ot_face_data (face)->kerx.get_blob (); return kerx; } +static inline const AAT::ankr& +_get_ankr (hb_face_t *face) +{ + if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::ankr); + return *(hb_ot_face_data (face)->ankr.get ()); +} hb_bool_t @@ -103,6 +109,6 @@ hb_aat_layout_position (hb_ot_shape_plan_t *plan, hb_blob_t *blob; const AAT::kerx& kerx = _get_kerx (font->face, &blob); - AAT::hb_aat_apply_context_t c (plan, font, buffer, blob); + AAT::hb_aat_apply_context_t c (plan, font, buffer, blob, _get_ankr (font->face)); kerx.apply (&c); } commit 28f0367aab648c486d6e8d0e13dbbb2af1b65dcc Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu Oct 11 00:12:49 2018 -0400 [kerx] Flesh out Format4 Doesn't apply actions yet. diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index a96bad17..c109d003 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -293,11 +293,121 @@ struct KerxSubTableFormat2 struct KerxSubTableFormat4 { + struct EntryData + { + HBUINT16 ankrActionIndex;/* Either 0xFFFF (for no action) or the index of + * the action to perform. */ + public: + DEFINE_SIZE_STATIC (2); + }; + + struct driver_context_t + { + static const bool in_place = true; + enum Flags + { + Mark = 0x8000, /* If set, remember this glyph as the marked glyph. */ + DontAdvance = 0x4000, /* If set, don't advance to the next glyph before + * going to the new state. */ + Reserved = 0x3FFF, /* Not used; set to 0. */ + }; + + enum SubTableFlags + { + ActionType = 0xC0000000, /* A two-bit field containing the action type. */ + Unused = 0x3F000000, /* Unused - must be zero. */ + Offset = 0x00FFFFFF, /* Masks the offset in bytes from the beginning + * of the subtable to the beginning of the control + * point table. */ + }; + + inline driver_context_t (const KerxSubTableFormat4 *table, + hb_aat_apply_context_t *c_) : + c (c_), + action_type ((table->flags & ActionType) >> 30), + ankrData ((HBUINT16 *) ((const char *) &table->machine + (table->flags & Offset))), + mark_set (false), + mark (0) {} + + inline bool is_actionable (StateTableDriver<EntryData> *driver, + const Entry<EntryData> *entry) + { + return entry->data.ankrActionIndex != 0xFFFF; + } + inline bool transition (StateTableDriver<EntryData> *driver, + const Entry<EntryData> *entry) + { + hb_buffer_t *buffer = driver->buffer; + unsigned int flags = entry->flags; + + if (mark_set && entry->data.ankrActionIndex != 0xFFFF) + { + switch (action_type) + { + case 0: /* Control Point Actions.*/ + { + /* indexed into glyph outline. */ + const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex]; + if (!c->sanitizer.check_array (data, 2)) + return false; + HB_UNUSED unsigned int markControlPoint = *data++; + HB_UNUSED unsigned int currControlPoint = *data++; + /* TODO */ + } + break; + + case 1: /* Anchor Point Actions. */ + { + /* Indexed into 'ankr' table. */ + const HBUINT16 *data = &ankrData[entry->data.ankrActionIndex]; + if (!c->sanitizer.check_array (data, 2)) + return false; + HB_UNUSED unsigned int markAnchorPoint = *data++; + HB_UNUSED unsigned int currAnchorPoint = *data++; + /* TODO */ + } + break; + + case 2: /* Control Point Coordinate Actions. */ + { + const FWORD *data = (const FWORD *) &ankrData[entry->data.ankrActionIndex]; + if (!c->sanitizer.check_array (data, 4)) + return false; + HB_UNUSED int markX = *data++; + HB_UNUSED int markY = *data++; + HB_UNUSED int currX = *data++; + HB_UNUSED int currY = *data++; + /* TODO */ + } + break; + } + } + + if (flags & Mark) + { + mark_set = true; + mark = buffer->idx; + } + + return true; + } + + private: + hb_aat_apply_context_t *c; + unsigned int action_type; + const HBUINT16 *ankrData; + bool mark_set; + unsigned int mark; + }; + inline bool apply (hb_aat_apply_context_t *c) const { TRACE_APPLY (this); - /* TODO */ + driver_context_t dc (this, c); + + StateTableDriver<EntryData> driver (machine, c->buffer, c->font->face); + driver.drive (&dc); return_trace (true); } @@ -306,14 +416,18 @@ struct KerxSubTableFormat4 { TRACE_SANITIZE (this); - /* TODO */ - return_trace (likely (c->check_struct (this))); + /* The rest of array sanitizations are done at run-time. */ + return_trace (c->check_struct (this) && + machine.sanitize (c) && + flags.sanitize (c)); } protected: KerxSubTableHeader header; + StateTable<EntryData> machine; + HBUINT32 flags; public: - DEFINE_SIZE_STATIC (12); + DEFINE_SIZE_STATIC (32); }; struct KerxSubTableFormat6 commit 947962a287d9aca2cb509c11f44cb5150aa6daf1 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Oct 10 23:07:03 2018 -0400 [ankr] Implement table access diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh index cc92ee29..3eac473a 100644 --- a/src/hb-aat-layout-ankr-table.hh +++ b/src/hb-aat-layout-ankr-table.hh @@ -45,16 +45,32 @@ struct Anchor return_trace (c->check_struct (this)); } + public: FWORD xCoordinate; FWORD yCoordinate; public: DEFINE_SIZE_STATIC (4); }; +typedef LArrayOf<Anchor> GlyphAnchors; + struct ankr { static const hb_tag_t tableTag = HB_AAT_TAG_ankr; + inline const Anchor &get_anchor (hb_codepoint_t glyph_id, + unsigned int i, + unsigned int num_glyphs, + const char *end) const + { + unsigned int offset = (this+lookupTable).get_value_or_null (glyph_id, num_glyphs); + const GlyphAnchors &anchors = StructAtOffset<GlyphAnchors> (&(this+anchorData), offset); + /* TODO Use sanitizer; to avoid overflows and more. */ + if (unlikely ((const char *) &anchors + anchors.get_size () > end)) + return Null(Anchor); + return anchors[i]; + } + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); commit 7281cb3eeb00091c6e6085895afd4a38a0516f35 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Oct 10 22:56:52 2018 -0400 [ankr] Start fixing diff --git a/src/hb-aat-layout-ankr-table.hh b/src/hb-aat-layout-ankr-table.hh index a197cec8..cc92ee29 100644 --- a/src/hb-aat-layout-ankr-table.hh +++ b/src/hb-aat-layout-ankr-table.hh @@ -60,17 +60,16 @@ struct ankr TRACE_SANITIZE (this); return_trace (likely (c->check_struct (this) && version == 0 && - lookupTable.sanitize (c, this) && - anchors.sanitize (c, this))); + lookupTable.sanitize (c, this))); } protected: HBUINT16 version; /* Version number (set to zero) */ HBUINT16 flags; /* Flags (currently unused; set to zero) */ - LOffsetTo<Lookup<HBUINT16> > + LOffsetTo<Lookup<Offset<HBUINT16, false> > > lookupTable; /* Offset to the table's lookup table */ - LOffsetTo<LArrayOf<Anchor> > - anchors; /* Offset to the glyph data table */ + LOffsetTo<HBUINT8> + anchorData; /* Offset to the glyph data table */ public: DEFINE_SIZE_STATIC (12); _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz