diff options
author | Behdad Esfahbod <behdad@behdad.org> | 2015-08-25 20:24:59 +0100 |
---|---|---|
committer | Behdad Esfahbod <behdad@behdad.org> | 2015-08-25 20:29:36 +0100 |
commit | 6578575cc8aeb05341f2053039acfcd735707674 (patch) | |
tree | d13b4da5a5bff4ea5afb969ef957d9a2339d6032 | |
parent | 7368da67244ea53195cd9b95a5c57485df695732 (diff) | |
download | harfbuzz-6578575cc8aeb05341f2053039acfcd735707674.tar.gz |
[GPOS] Fix cursive connection with mix of RTL and non-RTL lookups
See thread "Issue with cursive attachment" started by Khaled.
Turned out fixing this wasn't as bad as I had assumed. I like the
new code better; we now have a theoretical model of cursive
connections that is easier to reason about.
-rw-r--r-- | src/hb-ot-layout-gpos-table.hh | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index 6dcada6d..996f8b59 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -883,6 +883,9 @@ struct EntryExitRecord DEFINE_SIZE_STATIC (4); }; +static void +reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent); + struct CursivePosFormat1 { inline void collect_glyphs (hb_collect_glyphs_context_t *c) const @@ -980,6 +983,13 @@ struct CursivePosFormat1 y_offset = -y_offset; } + /* If child was already connected to someone else, walk through its old + * chain and reverse the link direction, such that the whole tree of its + * previous connection now attaches to new parent. Watch out for case + * where new parent is on the path from old chain... + */ + reverse_cursive_minor_offset (pos, child, c->direction, parent); + pos[child].cursive_chain() = parent - child; if (likely (HB_DIRECTION_IS_HORIZONTAL (c->direction))) pos[child].y_offset = y_offset; @@ -1495,6 +1505,30 @@ struct GPOS : GSUBGPOS static void +reverse_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction, unsigned int new_parent) +{ + unsigned int j = pos[i].cursive_chain(); + if (likely (!j)) + return; + + j += i; + + pos[i].cursive_chain() = 0; + + /* Stop if we see new parent in the chain. */ + if (j == new_parent) + return; + + reverse_cursive_minor_offset (pos, j, direction, new_parent); + + if (HB_DIRECTION_IS_HORIZONTAL (direction)) + pos[j].y_offset = -pos[i].y_offset; + else + pos[j].x_offset = -pos[i].x_offset; + + pos[j].cursive_chain() = i - j; +} +static void fix_cursive_minor_offset (hb_glyph_position_t *pos, unsigned int i, hb_direction_t direction) { unsigned int j = pos[i].cursive_chain(); |