[pango/harfbuzz-ng] [GPOS] CursivePosFormat1



commit 852a03873cf0266cc1acadafc60ef2f4132b2019
Author: Behdad Esfahbod <behdad behdad org>
Date:   Tue May 19 23:25:41 2009 -0400

    [GPOS] CursivePosFormat1
---
 pango/opentype/hb-ot-layout-gpos-private.h |  174 +++++++++++++++++++++++++++-
 pango/opentype/hb-ot-layout-private.h      |    2 +-
 2 files changed, 169 insertions(+), 7 deletions(-)

diff --git a/pango/opentype/hb-ot-layout-gpos-private.h b/pango/opentype/hb-ot-layout-gpos-private.h
index 65a1a49..b4b6b3b 100644
--- a/pango/opentype/hb-ot-layout-gpos-private.h
+++ b/pango/opentype/hb-ot-layout-gpos-private.h
@@ -532,9 +532,6 @@ ASSERT_SIZE (PairPos, 2);
 
 
 struct EntryExitRecord {
-  /* TODO */
-
-  private:
   OffsetTo<Anchor>
 		entryAnchor;		/* Offset to EntryAnchor table--from
 					 * beginning of CursivePos
@@ -551,9 +548,174 @@ struct CursivePosFormat1 {
   friend struct CursivePos;
 
   private:
-  inline bool apply (APPLY_ARG_DEF) const {
-    /* TODO */
-    return false;
+  inline bool apply (APPLY_ARG_DEF) const
+  {
+    struct hb_ot_layout_t::gpos_info_t *gpi = &layout->gpos_info;
+    hb_codepoint_t last_pos = gpi->last;
+    gpi->last = 0xFFFF;
+
+    /* We don't handle mark glyphs here. */
+    if (property == HB_OT_LAYOUT_GLYPH_CLASS_MARK)
+      return false;
+
+    unsigned int index = (this+coverage) (IN_CURGLYPH ());
+    if (HB_LIKELY (index == NOT_COVERED))
+      return false;
+
+    /* 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.        */
+
+    const EntryExitRecord &record = entryExitRecord[index];
+
+    hb_position_t entry_x, entry_y, exit_x, exit_y;
+
+    if (last_pos == 0xFFFF || !record.entryAnchor)
+      goto end;
+
+    (this+record.entryAnchor).get_anchor (layout, IN_CURGLYPH (), &entry_x, &entry_y);
+
+    if (gpi->r2l)
+    {
+      POSITION (buffer->in_pos)->x_advance   = entry_x - gpi->anchor_x;
+      POSITION (buffer->in_pos)->new_advance = TRUE;
+    }
+    else
+    {
+      POSITION (gpi->last)->x_advance   = gpi->anchor_x - entry_x;
+      POSITION (gpi->last)->new_advance = TRUE;
+    }
+
+    if  (lookup_flag & LookupFlag::RightToLeft)
+    {
+      POSITION (gpi->last)->cursive_chain = gpi->last - buffer->in_pos;
+      POSITION (gpi->last)->y_pos = entry_y - gpi->anchor_y;
+    }
+    else
+    {
+      POSITION (buffer->in_pos)->cursive_chain = buffer->in_pos - gpi->last;
+      POSITION (buffer->in_pos)->y_pos = gpi->anchor_y - entry_y;
+    }
+
+  end:
+    if (record.exitAnchor)
+      (this+record.exitAnchor).get_anchor (layout, IN_CURGLYPH (), &gpi->anchor_x, &gpi->anchor_y);
+
+    buffer->in_pos++;
+    return true;
   }
 
   private:
diff --git a/pango/opentype/hb-ot-layout-private.h b/pango/opentype/hb-ot-layout-private.h
index 540145b..43ea247 100644
--- a/pango/opentype/hb-ot-layout-private.h
+++ b/pango/opentype/hb-ot-layout-private.h
@@ -47,7 +47,7 @@ struct _hb_ot_layout_t {
   } new_gdef;
 
   /* TODO full-matrix transformation? */
-  struct {
+  struct gpos_info_t {
     unsigned int x_ppem, y_ppem;
     hb_16dot16_t x_scale, y_scale;
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]