Fix Cursive positioning
authorBehdad Esfahbod <behdad@behdad.org>
Wed, 27 Oct 2010 15:09:48 +0000 (11:09 -0400)
committerBehdad Esfahbod <behdad@behdad.org>
Wed, 27 Oct 2010 15:09:48 +0000 (11:09 -0400)
Test case: "مرا" rendered using IranNastaliq.

src/hb-ot-layout-gpos-private.hh

index 1860b09..4e08d4f 100644 (file)
@@ -826,123 +826,6 @@ struct CursivePosFormat1
   inline bool apply (hb_apply_context_t *c) const
   {
     TRACE_APPLY ();
-    /* Now comes the messiest part of the whole OpenType
-       specification.  At first glance, cursive connections seem easy
-       to understand, but there are pitfalls!  The reason is that
-       the specs don't mention how to compute the advance values
-       resp. glyph offsets.  I was told it would be an omission, to
-       be fixed in the next OpenType version...  Again many thanks to
-       Andrei Burago <andreib@microsoft.com> for clarifications.
-
-       Consider the following example:
-
-                       |  xadv1    |
-                        +---------+
-                        |         |
-                  +-----+--+ 1    |
-                  |     | .|      |
-                  |    0+--+------+
-                  |   2    |
-                  |        |
-                 0+--------+
-                 |  xadv2   |
-
-        glyph1: advance width = 12
-                anchor point = (3,1)
-
-        glyph2: advance width = 11
-                anchor point = (9,4)
-
-        LSB is 1 for both glyphs (so the boxes drawn above are glyph
-        bboxes).  Writing direction is R2L; `0' denotes the glyph's
-        coordinate origin.
-
-       Now the surprising part: The advance width of the *left* glyph
-       (resp. of the *bottom* glyph) will be modified, no matter
-       whether the writing direction is L2R or R2L (resp. T2B or
-       B2T)!  This assymetry is caused by the fact that the glyph's
-       coordinate origin is always the lower left corner for all
-       writing directions.
-
-       Continuing the above example, we can compute the new
-       (horizontal) advance width of glyph2 as
-
-        9 - 3 = 6  ,
-
-       and the new vertical offset of glyph2 as
-
-        1 - 4 = -3  .
-
-
-       Vertical writing direction is far more complicated:
-
-       a) Assuming that we recompute the advance height of the lower glyph:
-
-                                   --
-                        +---------+
-               --       |         |
-                  +-----+--+ 1    | yadv1
-                  |     | .|      |
-            yadv2 |    0+--+------+        -- BSB1  --
-                  |   2    |       --      --        y_offset
-                  |        |
-     BSB2 --      0+--------+                        --
-         --    --
-
-        glyph1: advance height = 6
-                anchor point = (3,1)
-
-        glyph2: advance height = 7
-                anchor point = (9,4)
-
-        TSB is 1 for both glyphs; writing direction is T2B.
-
-
-          BSB1     = yadv1 - (TSB1 + ymax1)
-          BSB2     = yadv2 - (TSB2 + ymax2)
-          y_offset = y2 - y1
-
-        vertical advance width of glyph2
-          = y_offset + BSB2 - BSB1
-          = (y2 - y1) + (yadv2 - (TSB2 + ymax2)) - (yadv1 - (TSB1 + ymax1))
-          = y2 - y1 + yadv2 - TSB2 - ymax2 - (yadv1 - TSB1 - ymax1)
-          = y2 - y1 + yadv2 - TSB2 - ymax2 - yadv1 + TSB1 + ymax1
-
-
-       b) Assuming that we recompute the advance height of the upper glyph:
-
-                                   --      --
-                        +---------+        -- TSB1
-         --    --       |         |
-     TSB2 --       +-----+--+ 1    | yadv1   ymax1
-                  |     | .|      |
-            yadv2 |    0+--+------+        --       --
-      ymax2        |   2    |       --                y_offset
-                  |        |
-         --      0+--------+                        --
-               --
-
-        glyph1: advance height = 6
-                anchor point = (3,1)
-
-        glyph2: advance height = 7
-                anchor point = (9,4)
-
-        TSB is 1 for both glyphs; writing direction is T2B.
-
-        y_offset = y2 - y1
-
-        vertical advance width of glyph2
-          = TSB1 + ymax1 + y_offset - (TSB2 + ymax2)
-          = TSB1 + ymax1 + y2 - y1 - TSB2 - ymax2
-
-
-       Comparing a) with b) shows that b) is easier to compute.  I'll wait
-       for a reply from Andrei to see what should really be implemented...
-
-       Since horizontal advance widths or vertical advance heights
-       can be used alone but not together, no ambiguity occurs.        */
-
     struct hb_ot_layout_context_t::info_t::gpos_t *gpi = &c->layout->info.gpos;
     hb_codepoint_t last_pos = gpi->last;
     gpi->last = HB_OT_LAYOUT_GPOS_NO_LAST;
@@ -965,15 +848,14 @@ struct CursivePosFormat1
 
     /* TODO vertical */
 
+    /* Align the exit anchor of the left glyph with the entry anchor of the right glyph. */
     if (c->buffer->props.direction == HB_DIRECTION_RTL)
     {
-      /* advance is absolute, not relative */
-      c->buffer->pos[c->buffer->i].x_advance = entry_x - gpi->anchor_x;
+      c->buffer->pos[c->buffer->i].x_advance = c->buffer->pos[c->buffer->i].x_offset + entry_x - gpi->anchor_x;
     }
     else
     {
-      /* advance is absolute, not relative */
-      c->buffer->pos[last_pos].x_advance = gpi->anchor_x - entry_x;
+      c->buffer->pos[last_pos].x_advance = c->buffer->pos[last_pos].x_advance + gpi->anchor_x - entry_x;
     }
 
     if  (c->lookup_flag & LookupFlag::RightToLeft)