? pango/obj
? pango/update.log
? pango/fonts/Makefile.in
? pango/modules/arabic/t
Index: pango/ChangeLog
===================================================================
RCS file: /cvs/gnome/pango/ChangeLog,v
retrieving revision 1.431
diff -u -r1.431 ChangeLog
--- pango/ChangeLog	2002/01/21 21:22:36	1.431
+++ pango/ChangeLog	2002/01/22 00:00:57
@@ -298,6 +298,13 @@
 
 	* pango/pango-fontset.c: Documentation fixes.
 	
+2001-12-01  Elliot Lee  <sopwith@redhat.com>
+
+	* pango/opentype/pango-ot-ruleset.c, pango/pango-ot.h (pango_ot_ruleset_shape):
+	Function now attempts to do glyph positioning. Handle OpenType GPOS tables for layout,
+	or fall back to a basic routine if not.
+	* modules/arabic/arabic-xft.c: Use above API, and handle non-spacing marks.
+
 2001-11-29  Matthias Clasen  <matthiasc@poet.de>
 
 	* pango/pango-fontset.c: Documentation updates.
Index: pango/modules/arabic/arabic-xft.c
===================================================================
RCS file: /cvs/gnome/pango/modules/arabic/arabic-xft.c,v
retrieving revision 1.6
diff -u -r1.6 arabic-xft.c
--- pango/modules/arabic/arabic-xft.c	2001/06/14 20:38:20	1.6
+++ pango/modules/arabic/arabic-xft.c	2002/01/22 00:00:57
@@ -140,13 +140,13 @@
 
 static void 
 arabic_engine_shape (PangoFont        *font,
-		    const char       *text,
-		    gint              length,
-		    PangoAnalysis    *analysis,
-		    PangoGlyphString *glyphs)
+		     const char       *text,
+		     gint              length,
+		     PangoAnalysis    *analysis,
+		     PangoGlyphString *glyphs)
 {
   int n_chars;
-  int i;
+  int i, prev_i;
   const char *p;
   gulong *properties = NULL;
   gunichar *wcs = NULL;
@@ -165,9 +165,10 @@
   pango_glyph_string_set_size (glyphs, n_chars);
 
   ruleset = get_ruleset (font);
+
+  wcs = g_utf8_to_ucs4_fast (text, length, NULL);
   if (ruleset)
     {
-      wcs = g_utf8_to_ucs4_fast (text, length, NULL);
       properties = g_new0 (gulong, n_chars);
       
       Assign_Arabic_Properties (wcs, properties, n_chars);
@@ -246,34 +247,35 @@
       
       p = g_utf8_next_char (p);
     }
-
-  ruleset = get_ruleset (font);
-
-  if (ruleset)
-    {
-      pango_ot_ruleset_shape (ruleset, glyphs, properties);
-
-      g_free (wcs);
-      g_free (properties);
-
-    }
 
+  pango_ot_ruleset_shape_2 (ruleset, font, glyphs, properties);
+  g_assert(glyphs->num_glyphs == n_chars);
+  prev_i = -1;
   for (i = 0; i < glyphs->num_glyphs; i++)
     {
+      int x = 0;
 
-      if (glyphs->glyphs[i].glyph)
+      if (g_unichar_type(wcs[i]) != G_UNICODE_NON_SPACING_MARK)
 	{
-	  PangoRectangle logical_rect;
-	  
-	  pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
-	  glyphs->glyphs[i].geometry.width = logical_rect.width;
+	  prev_i = i; /* Need to know what the last 'normal' character was, in case of multiple marks */
 	}
-      else
-	glyphs->glyphs[i].geometry.width = 0;
-  
-      glyphs->glyphs[i].geometry.x_offset = 0;
-      glyphs->glyphs[i].geometry.y_offset = 0;
+      else if (glyphs->glyphs[i].geometry.width && prev_i >= 0)
+	{
+	  glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[prev_i].geometry.width; /* Position the mark over the tail of the
+											       previous 'normal' character... */
+	  x = glyphs->glyphs[prev_i].geometry.width - glyphs->glyphs[i].geometry.width;
+	  if (x > 0)
+	    /* ... then if it is shorter than the previous char, back
+	       the mark up so it is centered over the last quarter of the
+	       previous glyph. Or something. */
+	    glyphs->glyphs[i].geometry.x_offset += x / 4;
+
+	  glyphs->glyphs[i].geometry.width = 0;
+	}
     }
+
+  g_free (wcs);
+  g_free (properties);
 
   /* Simple bidi support */
 
Index: pango/pango/pango-ot.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-ot.h,v
retrieving revision 1.3
diff -u -r1.3 pango-ot.h
--- pango/pango/pango-ot.h	2001/10/30 22:09:19	1.3
+++ pango/pango/pango-ot.h	2002/01/22 00:00:57
@@ -78,6 +78,7 @@
 					      guint             feature_index,
 					      gulong            property_bit);
 void            pango_ot_ruleset_shape       (PangoOTRuleset   *ruleset,
+					      PangoFont        *font,
 					      PangoGlyphString *glyphs,
 					      gulong           *properties);
 
Index: pango/pango/opentype/pango-ot-ruleset.c
===================================================================
RCS file: /cvs/gnome/pango/pango/opentype/pango-ot-ruleset.c,v
retrieving revision 1.3
diff -u -r1.3 pango-ot-ruleset.c
--- pango/pango/opentype/pango-ot-ruleset.c	2001/10/30 22:09:20	1.3
+++ pango/pango/opentype/pango-ot-ruleset.c	2002/01/22 00:00:57
@@ -21,9 +21,21 @@
 
 #include <freetype/internal/ftmemory.h>
 
+#include <pango/pango-font.h>
+#include <pango/pango-utils.h>
+#include <pango/pangoft2.h>
 #include <pango/pango-ot.h>
 #include "pango-ot-private.h"
 
+#ifndef PANGO_UNITS_26_6
+#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6))
+#define PANGO_PIXELS_26_6(d)				\
+  (((d) >= 0) ?						\
+   ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 :	\
+   ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6)
+#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
+#endif
+
 typedef struct _PangoOTRule PangoOTRule;
 
 struct _PangoOTRule 
@@ -136,20 +148,12 @@
   g_array_append_val (ruleset->rules, tmp_rule);
 }
 
-/**
- * pango_ot_ruleset_shape:
- * @ruleset: a #PangoOTRuleset.
- * @glyphs: a pointer to a #PangoGlyphString.
- * @properties: an array containing one #gulong bitfield for each glyph,
- *   which gives the glyph's properties: If a certain bit is set for a glyph, 
- *   the feature which has the same bit set in its property value is applied.
- *
- * Shapes a string of glyphs with the given properties according to @ruleset.
- **/
-void
-pango_ot_ruleset_shape (PangoOTRuleset   *ruleset,
-			PangoGlyphString *glyphs,
-			gulong           *properties)
+/* Returns true if the GPOS table was found to allow positioning the glyphs */
+static gboolean
+pango_ot_ruleset_shape_internal(PangoOTRuleset *ruleset,
+				PangoFont *font,
+				PangoGlyphString *glyphs,
+				gulong *properties)
 {
   int i;
   int last_cluster;
@@ -162,9 +166,9 @@
   TTO_GSUB_String *result_string = NULL;
 
   gboolean need_gsub = FALSE;
-  gboolean need_gpos = FALSE;
+  gboolean need_gpos = FALSE, did_gpos = FALSE;
 
-  g_return_if_fail (PANGO_OT_IS_RULESET (ruleset));
+  g_return_val_if_fail (PANGO_OT_IS_RULESET (ruleset), FALSE);
 
   for (i = 0; i < ruleset->rules->len; i++)
     {
@@ -209,7 +213,7 @@
     }
 
   if (!gsub && !gpos)
-    return;
+    return FALSE;
 
   g_assert (TT_GSUB_String_New (ruleset->info->face->memory,
 				&in_string) == FT_Err_Ok);
@@ -233,7 +237,38 @@
     }
   else
     result_string = in_string;
-  
+
+  if (gpos && font)
+    {
+      TTO_GPOS_Data *outgpos = NULL;
+
+      if (!TT_GPOS_Apply_String (pango_ft2_font_get_face(font), gpos, 0, result_string, &outgpos,
+				 FALSE /* enable device-dependant values */,
+				 FALSE /* Even though this might be r2l text, RTL is handled elsewhere afaik */))
+	{
+
+	  for (i = 0; i < result_string->length; i++)
+	    {
+	      int j;
+	      glyphs->glyphs[i].geometry.x_offset = PANGO_UNITS_26_6(outgpos[i].x_pos);
+	      glyphs->glyphs[i].geometry.y_offset = PANGO_UNITS_26_6(outgpos[i].y_pos);
+
+	      for(j = 0; j < outgpos[i].back; j++)
+		glyphs->glyphs[i].geometry.x_offset -= glyphs->glyphs[i-j].geometry.width;
+	    
+	      if (outgpos[i].new_advance)
+		/* Can't set new x offset for marks, so just make sure not to increase it.
+		   Can do better than this by playing with ->x_offset. */
+		glyphs->glyphs[i].geometry.width = 0;
+	      else
+		glyphs->glyphs[i].geometry.width = PANGO_UNITS_26_6(outgpos[i].x_advance);
+	    }
+
+	  FT_Free(gpos->memory, (void *)outgpos);
+	  did_gpos = TRUE;
+	}
+    }
+
   pango_glyph_string_set_size (glyphs, result_string->length);
 
   last_cluster = -1;
@@ -255,4 +290,50 @@
     TT_GSUB_String_Done (in_string);
   if (out_string)
     TT_GSUB_String_Done (out_string);
+
+  return did_gpos;
+}
+
+/**
+ * pango_ot_ruleset_shape:
+ * @ruleset: a #PangoOTRuleset.
+ * @glyphs: a pointer to a #PangoGlyphString.
+ * @properties: an array containing one #gulong bitfield for each glyph,
+ *   which gives the glyph's properties: If a certain bit is set for a glyph, 
+ *   the feature which has the same bit set in its property value is applied.
+ *
+ * Shapes a string of glyphs with the given properties according to @ruleset.
+ **/
+void
+pango_ot_ruleset_shape (PangoOTRuleset   *ruleset,
+			PangoFont        *font,
+			PangoGlyphString *glyphs,
+			gulong           *properties)
+{
+  int i;
+
+  if(pango_ot_ruleset_shape_internal(ruleset, font, glyphs, properties))
+    return;
+
+  if(!font)
+    return;
+
+  g_return_if_fail (PANGO_IS_FONT (font));
+
+  /* Fall back to some basic shaping */
+  for (i = 0; i < glyphs->num_glyphs; i++)
+    {
+      if (glyphs->glyphs[i].glyph)
+	{
+	  PangoRectangle logical_rect;
+	  
+	  pango_font_get_glyph_extents (font, glyphs->glyphs[i].glyph, NULL, &logical_rect);
+	  glyphs->glyphs[i].geometry.width = logical_rect.width;
+	}
+      else
+	  glyphs->glyphs[i].geometry.width = 0;
+  
+      glyphs->glyphs[i].geometry.x_offset = 0;
+      glyphs->glyphs[i].geometry.y_offset = 0;
+    }
 }
