summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBehdad Esfahbod <behdad@behdad.org>2015-08-25 20:24:59 +0100
committerBehdad Esfahbod <behdad@behdad.org>2015-08-25 20:29:36 +0100
commit6578575cc8aeb05341f2053039acfcd735707674 (patch)
treed13b4da5a5bff4ea5afb969ef957d9a2339d6032
parent7368da67244ea53195cd9b95a5c57485df695732 (diff)
downloadharfbuzz-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.hh34
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();