ccd8a32
--- mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp.orig	2007-06-28 14:44:31.000000000 +0200
ccd8a32
+++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp	2007-06-28 15:48:04.000000000 +0200
ccd8a32
@@ -21,6 +21,8 @@
ccd8a32
  * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
ccd8a32
  *
ccd8a32
  * Contributor(s):
ccd8a32
+ *   Christopher Blizzard <blizzard@mozilla.org>
ccd8a32
+ *   Behdad Esfahbod <behdad@behdad.org>
ccd8a32
  *
ccd8a32
  * Alternatively, the contents of this file may be used under the terms of
ccd8a32
  * either the GNU General Public License Version 2 or later (the "GPL"), or
ccd8a32
@@ -36,6 +38,10 @@
ccd8a32
  *
ccd8a32
  * ***** END LICENSE BLOCK ***** */
ccd8a32
 
ccd8a32
+#define PANGO_ENABLE_BACKEND
ccd8a32
+
ccd8a32
+#include "nsFontMetricsPango.h"
ccd8a32
+
ccd8a32
 #include <strings.h>
ccd8a32
 #include "nsFont.h"
ccd8a32
 #include "nsIDeviceContext.h"
ccd8a32
@@ -43,27 +49,37 @@
ccd8a32
 #include "nsIPref.h"
ccd8a32
 #include "nsServiceManagerUtils.h"
ccd8a32
 
ccd8a32
-#define PANGO_ENABLE_BACKEND
ccd8a32
-#define PANGO_ENABLE_ENGINE
ccd8a32
-
ccd8a32
-#include "nsFontMetricsPango.h"
ccd8a32
-#include "nsRenderingContextGTK.h"
ccd8a32
-#include "nsDeviceContextGTK.h"
ccd8a32
 #include "nsFontConfigUtils.h"
ccd8a32
 
ccd8a32
 #include "nsUnicharUtils.h"
ccd8a32
 #include "nsQuickSort.h"
ccd8a32
 #include "nsFontConfigUtils.h"
ccd8a32
+#include "mozilla-decoder.h"
ccd8a32
+
ccd8a32
+#define FORCE_PR_LOG
ccd8a32
+#include "prlog.h"
ccd8a32
+
ccd8a32
 
ccd8a32
 #include <fontconfig/fontconfig.h>
ccd8a32
+#include <freetype/tttables.h>
ccd8a32
+
ccd8a32
+#include <pango/pango.h>
ccd8a32
+#include <pango/pangofc-font.h>
ccd8a32
+
ccd8a32
+#ifdef PSPANGO
ccd8a32
+#include <pango/pangoft2.h>
ccd8a32
+#include "nsRenderingContextPS.h"
ccd8a32
+#include "nsDeviceContextPS.h"
ccd8a32
+#include "nsType1.h"
ccd8a32
+#else
ccd8a32
 #include <gdk/gdk.h>
ccd8a32
 #include <gdk/gdkx.h>
ccd8a32
-#include <freetype/tttables.h>
ccd8a32
+#include "nsRenderingContextGTK.h"
ccd8a32
+#include "nsDeviceContextGTK.h"
ccd8a32
+#endif
ccd8a32
+
ccd8a32
 
ccd8a32
-#include "mozilla-decoder.h"
ccd8a32
 
ccd8a32
-#define FORCE_PR_LOG
ccd8a32
-#include "prlog.h"
ccd8a32
 
ccd8a32
 // Globals
ccd8a32
 
ccd8a32
@@ -108,6 +124,49 @@ static nsresult    EnumFontsPango   (nsI
ccd8a32
                                      PRUint32* aCount, PRUnichar*** aResult);
ccd8a32
 static int         CompareFontNames (const void* aArg1, const void* aArg2,
ccd8a32
                                      void* aClosure);
ccd8a32
+static void  utf16_to_utf8 (const PRUnichar* aString, PRUint32 aLength,
ccd8a32
+                            char *&text, gint &text_len);
ccd8a32
+
ccd8a32
+#ifdef PSPANGO
ccd8a32
+static void
ccd8a32
+default_substitute (FcPattern *pattern,
ccd8a32
+                    gpointer   data)
ccd8a32
+{
ccd8a32
+  FcPatternDel (pattern, FC_HINTING);
ccd8a32
+  FcPatternAddBool (pattern, FC_HINTING, 0);
ccd8a32
+}
ccd8a32
+#endif
ccd8a32
+
ccd8a32
+static PangoFontMap *
ccd8a32
+get_fontmap (void)
ccd8a32
+{
ccd8a32
+  static PangoFontMap               *fontmap = NULL;
ccd8a32
+
ccd8a32
+  if (!fontmap) {
ccd8a32
+#ifdef PSPANGO
ccd8a32
+    fontmap = pango_ft2_font_map_new ();
ccd8a32
+    pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.);
ccd8a32
+    pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL);
ccd8a32
+#else
ccd8a32
+    PangoContext* context = gdk_pango_context_get ();
ccd8a32
+    fontmap = pango_context_get_font_map (context);
ccd8a32
+    g_object_unref (context);
ccd8a32
+#endif
ccd8a32
+  }
ccd8a32
+
ccd8a32
+  return fontmap;
ccd8a32
+}
ccd8a32
+
ccd8a32
+static PangoContext *
ccd8a32
+get_context (void)
ccd8a32
+{
ccd8a32
+#ifdef PSPANGO
ccd8a32
+  return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
ccd8a32
+#else
ccd8a32
+  return gdk_pango_context_get();
ccd8a32
+#endif
ccd8a32
+}
ccd8a32
+
ccd8a32
 
ccd8a32
 nsFontMetricsPango::nsFontMetricsPango()
ccd8a32
 {
e21fcd7
@@ -169,15 +228,21 @@ nsFontMetricsPango::Init(const nsFont& a
ccd8a32
     mLangGroup = aLangGroup;
ccd8a32
 
ccd8a32
     // Hang on to the device context
ccd8a32
+#ifdef PSPANGO
ccd8a32
+    mDeviceContext = (nsDeviceContextPS *)aContext;
ccd8a32
+#else
ccd8a32
     mDeviceContext = aContext;
ccd8a32
+#endif
ccd8a32
     
ccd8a32
     mPointSize = NSTwipsToFloatPoints(mFont.size);
ccd8a32
 
ccd8a32
+#ifndef PSPANGO
ccd8a32
     // Make sure to clamp the pixel size to something reasonable so we
ccd8a32
     // don't make the X server blow up.
ccd8a32
     nscoord screenPixels = gdk_screen_height();
e21fcd7
     mPointSize = PR_MIN((screenPixels - 1) * FONT_MAX_FONT_SCALE, mPointSize);
e21fcd7
     mPointSize = PR_MIN(2000, mPointSize);
ccd8a32
+#endif
ccd8a32
 
ccd8a32
     // enumerate over the font names passed in
ccd8a32
     mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
ccd8a32
@@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
ccd8a32
 
ccd8a32
     // mPangoSpaceWidth
ccd8a32
     PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
-    pango_layout_set_text(layout, " ", 1);
ccd8a32
+    pango_layout_set_text(layout, " ", -1);
ccd8a32
     int pswidth, psheight;
ccd8a32
     pango_layout_get_size(layout, &pswidth, &psheight);
ccd8a32
     mPangoSpaceWidth = pswidth;
ccd8a32
@@ -337,14 +402,14 @@ nsFontMetricsPango::CacheFontMetrics(voi
ccd8a32
 
ccd8a32
     // mSpaceWidth (width of a space)
ccd8a32
     nscoord tmpWidth;
ccd8a32
-    GetWidth(" ", 1, tmpWidth, NULL);
ccd8a32
+    GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL);
ccd8a32
     mSpaceWidth = tmpWidth;
ccd8a32
 
ccd8a32
     // mAveCharWidth (width of an 'average' char)
ccd8a32
     //    XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
ccd8a32
     //rawWidth = extents.width;
ccd8a32
     //mAveCharWidth = NSToCoordRound(rawWidth * f);
ccd8a32
-    GetWidth("x", 1, tmpWidth, NULL);
ccd8a32
+    GetWidth("x", 1, tmpWidth CONTEXT_ARG_NULL);
ccd8a32
     mAveCharWidth = tmpWidth;
ccd8a32
 
ccd8a32
     // mXHeight (height of an 'x' character)
ccd8a32
@@ -460,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont
ccd8a32
 
ccd8a32
 // nsIFontMetricsPango impl
ccd8a32
 
ccd8a32
-nsresult
ccd8a32
-nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
ccd8a32
-                             nscoord& aWidth,
ccd8a32
-                             nsRenderingContextGTK *aContext)
ccd8a32
+#ifdef PSPANGO
ccd8a32
+NS_IMETHODIMP
ccd8a32
+nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
ccd8a32
 {
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
-
ccd8a32
-    pango_layout_set_text(layout, aString, aLength);
ccd8a32
+    return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL);
ccd8a32
+}
ccd8a32
 
ccd8a32
-    if (mPangoSpaceWidth)
ccd8a32
-        FixupSpaceWidths(layout, aString);
ccd8a32
+NS_IMETHODIMP
ccd8a32
+nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
ccd8a32
+{
ccd8a32
+    return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
ccd8a32
+}
ccd8a32
+#endif
ccd8a32
 
ccd8a32
+nsresult
ccd8a32
+nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
ccd8a32
+                             nscoord& aWidth
ccd8a32
+                             CONTEXT_ARG_DEF)
ccd8a32
+{
ccd8a32
     int width, height;
ccd8a32
-
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
     pango_layout_get_size(layout, &width, &height);
ccd8a32
-
ccd8a32
     g_object_unref(layout);
ccd8a32
 
ccd8a32
-    float f;
ccd8a32
-    f = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
+    float f = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
     aWidth = NSToCoordRound(width * f / PANGO_SCALE);
ccd8a32
 
ccd8a32
-    //    printf("GetWidth (char *) %d\n", aWidth);
ccd8a32
-
ccd8a32
     return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
 nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
-                             nscoord& aWidth, PRInt32 *aFontID,
ccd8a32
-                             nsRenderingContextGTK *aContext)
ccd8a32
+                             nscoord& aWidth, PRInt32 *aFontID
ccd8a32
+                             CONTEXT_ARG_DEF)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
-
ccd8a32
-    gchar *text = g_utf16_to_utf8(aString, aLength,
ccd8a32
-                                  NULL, NULL, NULL);
ccd8a32
-
ccd8a32
-    if (!text) {
ccd8a32
-        aWidth = 0;
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aString, aLength)
ccd8a32
-#endif
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-
ccd8a32
     gint width, height;
ccd8a32
-
ccd8a32
-    pango_layout_set_text(layout, text, strlen(text));
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
     pango_layout_get_size(layout, &width, &height);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
-    float f;
ccd8a32
-    f = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
+    float f = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
     aWidth = NSToCoordRound(width * f / PANGO_SCALE);
ccd8a32
 
ccd8a32
-    //    printf("GetWidth %d\n", aWidth);
ccd8a32
-
ccd8a32
- loser:
ccd8a32
-    g_free(text);
ccd8a32
-    g_object_unref(layout);
ccd8a32
-
ccd8a32
-    return rv;
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
-nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
ccd8a32
+nsFontMetricsPango::GetTextDimensions(const char* aString,
ccd8a32
                                       PRUint32 aLength,
ccd8a32
-                                      nsTextDimensions& aDimensions, 
ccd8a32
-                                      PRInt32* aFontID,
ccd8a32
-                                      nsRenderingContextGTK *aContext)
ccd8a32
+                                      nsTextDimensions& aDimensions
ccd8a32
+                                      CONTEXT_ARG_DEF)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
-
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
ccd8a32
 
ccd8a32
-    gchar *text = g_utf16_to_utf8(aString, aLength,
ccd8a32
-                                  NULL, NULL, NULL);
ccd8a32
-
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aString, aLength)
ccd8a32
-#endif
ccd8a32
-        aDimensions.width = 0;
ccd8a32
-        aDimensions.ascent = 0;
ccd8a32
-        aDimensions.descent = 0;
ccd8a32
-
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-        
ccd8a32
+    PangoRectangle logical;
ccd8a32
+    pango_layout_line_get_extents(line, NULL, &logical);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
-    pango_layout_set_text(layout, text, strlen(text));
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+    float P2T = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
 
ccd8a32
-    // Get the logical extents
ccd8a32
-    PangoLayoutLine *line;
ccd8a32
-    if (pango_layout_get_line_count(layout) != 1) {
ccd8a32
-        printf("Warning: more than one line!\n");
ccd8a32
-    }
ccd8a32
-    line = pango_layout_get_line(layout, 0);
ccd8a32
+    aDimensions.ascent  = NSToCoordRound(PANGO_ASCENT(logical)  * P2T / PANGO_SCALE);
ccd8a32
+    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
ccd8a32
+    aDimensions.width   = NSToCoordRound(logical.width          * P2T / PANGO_SCALE);
ccd8a32
 
ccd8a32
-    PangoRectangle rect;
ccd8a32
-    pango_layout_line_get_extents(line, NULL, &rect);
ccd8a32
+    return NS_OK;
ccd8a32
+}
ccd8a32
 
ccd8a32
-    float P2T;
ccd8a32
-    P2T = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
+nsresult
ccd8a32
+nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
ccd8a32
+                                      PRUint32 aLength,
ccd8a32
+                                      nsTextDimensions& aDimensions, 
ccd8a32
+                                      PRInt32* aFontID
ccd8a32
+                                      CONTEXT_ARG_DEF)
ccd8a32
+{
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
ccd8a32
 
ccd8a32
-    aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
ccd8a32
-    aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
ccd8a32
-    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
ccd8a32
+    PangoRectangle logical;
ccd8a32
+    pango_layout_line_get_extents(line, NULL, &logical);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
-    //    printf("GetTextDimensions %d %d %d\n", aDimensions.width,
ccd8a32
-    //aDimensions.ascent, aDimensions.descent);
ccd8a32
+    float P2T = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    g_free(text);
ccd8a32
-    g_object_unref(layout);
ccd8a32
+    aDimensions.ascent  = NSToCoordRound(PANGO_ASCENT(logical)  * P2T / PANGO_SCALE);
ccd8a32
+    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
ccd8a32
+    aDimensions.width   = NSToCoordRound(logical.width          * P2T / PANGO_SCALE);
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
@@ -595,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
                                       nsTextDimensions&   aDimensions,
ccd8a32
                                       PRInt32&            aNumCharsFit,
ccd8a32
                                       nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                      PRInt32*            aFontID,
ccd8a32
-                                      nsRenderingContextGTK *aContext)
ccd8a32
+                                      PRInt32*            aFontID
ccd8a32
+                                      CONTEXT_ARG_DEF)
ccd8a32
 {
ccd8a32
 
ccd8a32
     return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
ccd8a32
                                      aNumBreaks, aDimensions, aNumCharsFit,
ccd8a32
-                                     aLastWordDimensions, aContext);
ccd8a32
+                                     aLastWordDimensions CONTEXT_ARG_PASS);
ccd8a32
 
ccd8a32
 }
ccd8a32
 
ccd8a32
@@ -614,8 +645,8 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
                                       nsTextDimensions&   aDimensions,
ccd8a32
                                       PRInt32&            aNumCharsFit,
ccd8a32
                                       nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                      PRInt32*            aFontID,
ccd8a32
-                                      nsRenderingContextGTK *aContext)
ccd8a32
+                                      PRInt32*            aFontID
ccd8a32
+                                      CONTEXT_ARG_DEF)
ccd8a32
 {
ccd8a32
     nsresult rv = NS_OK;
ccd8a32
     PRInt32 curBreak = 0;
ccd8a32
@@ -623,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
 
ccd8a32
     PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
ccd8a32
 
ccd8a32
-    gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
ccd8a32
-                                  NULL, NULL, NULL);
ccd8a32
+    gchar* text;
ccd8a32
+    gint text_len;
ccd8a32
+    utf16_to_utf8 (aString, aLength, text, text_len);
ccd8a32
 
ccd8a32
     curChar = text;
ccd8a32
 
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aString, (PRUint32)aLength)
ccd8a32
-#endif
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-
ccd8a32
     // Covert the utf16 break offsets to utf8 break offsets
ccd8a32
     for (PRInt32 curOffset=0; curOffset < aLength;
ccd8a32
-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
ccd8a32
+         curOffset++, curChar = g_utf8_next_char(curChar)) {
ccd8a32
         if (aBreaks[curBreak] == curOffset) {
ccd8a32
             utf8Breaks[curBreak] = curChar - text;
ccd8a32
             curBreak++;
ccd8a32
@@ -653,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
     utf8Breaks[curBreak] = curChar - text;
ccd8a32
 
ccd8a32
 #if 0
ccd8a32
-    if (strlen(text) != aLength) {
ccd8a32
-        printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
ccd8a32
+    if (text_len != aLength) {
ccd8a32
+        printf("Different lengths for utf16 %d and utf8 %d\n", aLength, text_len);
ccd8a32
         DUMP_PRUNICHAR(aString, aLength)
ccd8a32
-        DUMP_PRUNICHAR(text, strlen(text))
ccd8a32
+        DUMP_PRUNICHAR(text, text_len)
ccd8a32
         for (PRInt32 i = 0; i < aNumBreaks; ++i) {
ccd8a32
             printf("  break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
ccd8a32
         }
ccd8a32
@@ -666,9 +689,9 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
     // We'll use curBreak to indicate which of the breaks end up being
ccd8a32
     // used for the break point for this line.
ccd8a32
     curBreak = 0;
ccd8a32
-    rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
ccd8a32
+    rv = GetTextDimensionsInternal(text, text_len, aAvailWidth, utf8Breaks,
ccd8a32
                                    aNumBreaks, aDimensions, aNumCharsFit,
ccd8a32
-                                   aLastWordDimensions, aContext);
ccd8a32
+                                   aLastWordDimensions CONTEXT_ARG_PASS);
ccd8a32
 
ccd8a32
     // Figure out which of the breaks we ended up using to convert
ccd8a32
     // back to utf16 - start from the end.
ccd8a32
@@ -681,200 +704,365 @@ nsFontMetricsPango::GetTextDimensions(co
ccd8a32
         }
ccd8a32
     }
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    if (text)
ccd8a32
-        g_free(text);
ccd8a32
+    g_free(text);
ccd8a32
 
ccd8a32
     delete[] utf8Breaks;
ccd8a32
 
ccd8a32
     return rv;
ccd8a32
 }
ccd8a32
 
ccd8a32
-nsresult
ccd8a32
-nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
ccd8a32
-                               nscoord aX, nscoord aY,
ccd8a32
-                               const nscoord* aSpacing,
ccd8a32
-                               nsRenderingContextGTK *aContext,
ccd8a32
-                               nsDrawingSurfaceGTK *aSurface)
ccd8a32
+#ifdef PSPANGO
ccd8a32
+
ccd8a32
+typedef struct _nsPSPangoRenderer        nsPSPangoRenderer;
ccd8a32
+typedef struct _nsPSPangoRendererClass   nsPSPangoRendererClass;
ccd8a32
+
ccd8a32
+struct _nsPSPangoRenderer
ccd8a32
 {
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+  PangoRenderer parent_instance;
ccd8a32
+  nsRenderingContextPS *psContext;
ccd8a32
+  nsFontMetricsPSPango *psPangoFontMetrics;
ccd8a32
+  float zoom;
ccd8a32
+};
ccd8a32
 
ccd8a32
-    pango_layout_set_text(layout, aString, aLength);
ccd8a32
-    FixupSpaceWidths(layout, aString);
ccd8a32
+struct _nsPSPangoRendererClass
ccd8a32
+{
ccd8a32
+  PangoRendererClass parent_class;
ccd8a32
+};
ccd8a32
 
ccd8a32
-    int x = aX;
ccd8a32
-    int y = aY;
ccd8a32
+#define _PS_TYPE_PANGO_RENDERER            (_ps_pango_renderer_get_type())
ccd8a32
+#define _PS_PANGO_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
ccd8a32
+#define _PS_IS_PANGO_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
ccd8a32
+#define _PS_PANGO_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
ccd8a32
+#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
ccd8a32
+#define _PS_PANGO_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
ccd8a32
 
ccd8a32
-    aContext->GetTranMatrix()->TransformCoord(&x, &y);
ccd8a32
+G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
ccd8a32
 
ccd8a32
-    PangoLayoutLine *line;
ccd8a32
-    if (pango_layout_get_line_count(layout) != 1) {
ccd8a32
-        printf("Warning: more than one line!\n");
ccd8a32
-    }
ccd8a32
-    line = pango_layout_get_line(layout, 0);
ccd8a32
+static PangoRenderer *
ccd8a32
+get_renderer (void)
ccd8a32
+{
ccd8a32
+  static PangoRenderer               *renderer = NULL;
ccd8a32
 
ccd8a32
-    aContext->UpdateGC();
ccd8a32
-    GdkGC *gc = aContext->GetGC();
ccd8a32
+  if (!renderer)
ccd8a32
+    renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
ccd8a32
 
ccd8a32
-    if (aSpacing && *aSpacing) {
ccd8a32
-        DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
ccd8a32
-                         gc, x, y, line, aSpacing);
ccd8a32
-    }
ccd8a32
-    else {
ccd8a32
-        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
ccd8a32
-                             x, y,
ccd8a32
-                             line);
ccd8a32
-    }
ccd8a32
+  return renderer;
ccd8a32
+}
ccd8a32
 
ccd8a32
-    g_object_unref(gc);
ccd8a32
-    g_object_unref(layout);
ccd8a32
+static void
ccd8a32
+_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
ccd8a32
+                              PangoFont        *font,
ccd8a32
+                              PangoGlyphString *glyphs,
ccd8a32
+                              int               x,
ccd8a32
+                              int               y);
ccd8a32
 
ccd8a32
-    //    printf("DrawString (char *)\n");
ccd8a32
+static void
ccd8a32
+_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
ccd8a32
+{
ccd8a32
+  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
ccd8a32
+  
ccd8a32
+  renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
ccd8a32
+}
ccd8a32
 
ccd8a32
-    return NS_OK;
ccd8a32
+static void
ccd8a32
+_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
ccd8a32
+{
ccd8a32
+}
ccd8a32
+
ccd8a32
+class nsPangoType1Generator : public nsPSFontGenerator {
ccd8a32
+public:
ccd8a32
+  nsPangoType1Generator();
ccd8a32
+  ~nsPangoType1Generator();
ccd8a32
+  nsresult Init(PangoFont *aFont);
ccd8a32
+  void  GeneratePSFont(FILE* aFile);
ccd8a32
+
ccd8a32
+protected:
ccd8a32
+  PangoFont *mFont;
ccd8a32
+};
ccd8a32
+
ccd8a32
+nsPangoType1Generator::nsPangoType1Generator()
ccd8a32
+{
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
-nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
-                               nscoord aX, nscoord aY,
ccd8a32
-                               PRInt32 aFontID,
ccd8a32
-                               const nscoord* aSpacing,
ccd8a32
-                               nsRenderingContextGTK *aContext,
ccd8a32
-                               nsDrawingSurfaceGTK *aSurface)
ccd8a32
+nsPangoType1Generator::Init(PangoFont *aFont)
ccd8a32
+  {
ccd8a32
+  NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
ccd8a32
+  mFont = aFont;
ccd8a32
+  g_object_ref (mFont);
ccd8a32
+  return NS_OK;
ccd8a32
+}
ccd8a32
+
ccd8a32
+nsPangoType1Generator::~nsPangoType1Generator()
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
-    int x = aX;
ccd8a32
-    int y = aY;
ccd8a32
+  g_object_unref (mFont);
ccd8a32
+  mFont = nsnull;
ccd8a32
+}
ccd8a32
 
ccd8a32
-    aContext->UpdateGC();
ccd8a32
-    GdkGC *gc = aContext->GetGC();
ccd8a32
+void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
ccd8a32
+{
ccd8a32
+  FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
ccd8a32
 
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+  if (face == nsnull)
ccd8a32
+    return;
ccd8a32
 
ccd8a32
-    gchar *text = g_utf16_to_utf8(aString, aLength,
ccd8a32
-                                  NULL, NULL, NULL);
ccd8a32
+  int wmode = 0;
ccd8a32
+  if (mGlyphSubset->Count())
ccd8a32
+    FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
ccd8a32
 
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aString, aLength)
ccd8a32
-#endif
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
+ pango_fc_font_unlock_face ((PangoFcFont *) mFont);
ccd8a32
+}
ccd8a32
 
ccd8a32
-    pango_layout_set_text(layout, text, strlen(text));
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+typedef struct
ccd8a32
+{
ccd8a32
+  nsCString    *FontNameBase;
ccd8a32
+  nsCStringKey *key;
ccd8a32
+  int           font_size;
ccd8a32
+} PSPangoFontData;
ccd8a32
 
ccd8a32
-    aContext->GetTranMatrix()->TransformCoord(&x, &y);
ccd8a32
+static void
ccd8a32
+ps_pango_font_data_destroy (PSPangoFontData *data)
ccd8a32
+{
ccd8a32
+  delete data->key;
ccd8a32
+  delete data->FontNameBase;
ccd8a32
+  g_free (data);
ccd8a32
+}
ccd8a32
 
ccd8a32
-    PangoLayoutLine *line;
ccd8a32
-    if (pango_layout_get_line_count(layout) != 1) {
ccd8a32
-        printf("Warning: more than one line!\n");
ccd8a32
-    }
ccd8a32
-    line = pango_layout_get_line(layout, 0);
ccd8a32
+static void
ccd8a32
+_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
ccd8a32
+                              PangoFont        *font,
ccd8a32
+                              PangoGlyphString *glyphs,
ccd8a32
+                              int               x,
ccd8a32
+                              int               y)
ccd8a32
+{
ccd8a32
+  if (!glyphs->num_glyphs)
ccd8a32
+    return;
ccd8a32
 
ccd8a32
-    if (aSpacing && *aSpacing) {
ccd8a32
-        DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
ccd8a32
-                         gc, x, y, line, aSpacing);
ccd8a32
-    }
ccd8a32
-    else {
ccd8a32
-        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
ccd8a32
-                             x, y,
ccd8a32
-                             line);
ccd8a32
-    }
ccd8a32
+  static GQuark data_quark = 0;
ccd8a32
+  if (!data_quark)
ccd8a32
+    data_quark = g_quark_from_static_string ("ps-pango-font-data");
ccd8a32
 
ccd8a32
- loser:
ccd8a32
+  PSPangoFontData *data;
ccd8a32
+  if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
ccd8a32
+    {
ccd8a32
+      data = g_new (PSPangoFontData, 1);
ccd8a32
 
ccd8a32
-    g_free(text);
ccd8a32
-    g_object_unref(gc);
ccd8a32
-    g_object_unref(layout);
ccd8a32
+      FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
ccd8a32
+      if (face == nsnull)
ccd8a32
+        return;
ccd8a32
+      int wmode = 0;
ccd8a32
+      data->FontNameBase = new nsCString ();
ccd8a32
+      if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
ccd8a32
+        g_free (data);
ccd8a32
+        pango_fc_font_unlock_face ((PangoFcFont *) font);
ccd8a32
+        return;
ccd8a32
+      }
ccd8a32
+      pango_fc_font_unlock_face ((PangoFcFont *) font);
ccd8a32
 
ccd8a32
-    //    printf("DrawString\n");
ccd8a32
+      PangoFontDescription *desc = pango_font_describe (font);
ccd8a32
+      data->font_size = pango_font_description_get_size (desc);
ccd8a32
+      pango_font_description_free (desc);
ccd8a32
+
ccd8a32
+      data->key = new nsCStringKey (*data->FontNameBase);
ccd8a32
+
ccd8a32
+      g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
ccd8a32
+    }
ccd8a32
+
ccd8a32
+  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
ccd8a32
+  nsRenderingContextPS *aContext = ps_renderer->psContext;
ccd8a32
+  nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
ccd8a32
+  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
ccd8a32
+  nsPostScriptObj* psObj = aContext->GetPostScriptObj();
ccd8a32
+  nsHashtable *psFGList = dc->GetPSFontGeneratorList();
ccd8a32
+  g_return_if_fail (psFGList);
ccd8a32
+  nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
ccd8a32
+  if (!psFontGen) {
ccd8a32
+    nsresult rv;
ccd8a32
+    psFontGen = new nsPangoType1Generator;
ccd8a32
+    g_return_if_fail (psFontGen);
ccd8a32
+    rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
ccd8a32
+    if (NS_FAILED(rv)) {
ccd8a32
+      delete psFontGen;
ccd8a32
+      return;
ccd8a32
+    }
ccd8a32
+    psFGList->Put(data->key, (void *) psFontGen);
ccd8a32
+  }
ccd8a32
+  nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
ccd8a32
+
ccd8a32
+  g_return_if_fail (aContext);
ccd8a32
+  g_return_if_fail (psObj);
ccd8a32
+
ccd8a32
+  nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
ccd8a32
+  nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
ccd8a32
+  psObj->moveto(aX, aY);
ccd8a32
+
ccd8a32
+  PRInt32 currSubFont, prevSubFont = -1;
ccd8a32
+  PRUint32 i;
ccd8a32
+  PangoGlyphString gl;
ccd8a32
+
ccd8a32
+  gl.glyphs = glyphs->glyphs;
ccd8a32
+  gl.num_glyphs = 0;
ccd8a32
+  currSubFont = prevSubFont;
ccd8a32
+  for (i = 0; i < glyphs->num_glyphs; ++i) {
ccd8a32
+    PangoGlyph glyph = glyphs->glyphs[i].glyph;
ccd8a32
+
ccd8a32
+    if (glyph != PANGO_GLYPH_EMPTY)
ccd8a32
+      currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph);
ccd8a32
+
ccd8a32
+    if (prevSubFont != currSubFont) {
ccd8a32
+      if (prevSubFont != -1)
ccd8a32
+        psObj->show(&gl, ps_renderer->zoom,  psFontGen, prevSubFont);
ccd8a32
+
ccd8a32
+      psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
ccd8a32
+      prevSubFont = currSubFont;
ccd8a32
+      gl.glyphs = glyphs->glyphs + i;
ccd8a32
+      gl.num_glyphs = 0;
ccd8a32
+    }
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+    gl.num_glyphs++;
ccd8a32
+  }
ccd8a32
+
ccd8a32
+  if (prevSubFont != -1)
ccd8a32
+    psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
ccd8a32
 }
ccd8a32
+#endif
ccd8a32
+
ccd8a32
+static void
ccd8a32
+draw_layout_line (int x, int y,
ccd8a32
+                  PangoLayoutLine *line,
ccd8a32
+                  nsFontMetricsPango *fm
ccd8a32
+                  CONTEXT_AND_SURFACE_ARG_DEF)
ccd8a32
+{
ccd8a32
+#ifdef PSPANGO
ccd8a32
+  PangoRenderer *renderer = get_renderer ();
ccd8a32
+  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
ccd8a32
+  ps_renderer->psContext = aContext;
ccd8a32
+  ps_renderer->psPangoFontMetrics = fm;
ccd8a32
+  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, fm->GetDeviceContext());
ccd8a32
+  ps_renderer->zoom = dc->DevUnitsToAppUnits();
ccd8a32
+
ccd8a32
+  pango_renderer_draw_layout_line (renderer, line,
ccd8a32
+                                   NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
ccd8a32
+                                   NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
ccd8a32
+#else
ccd8a32
+    aContext->UpdateGC();
ccd8a32
+    GdkGC *gc = aContext->GetGC();
ccd8a32
+    gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line);
ccd8a32
+    g_object_unref(gc);
ccd8a32
+#endif
ccd8a32
+}
ccd8a32
+
ccd8a32
 
ccd8a32
-#ifdef MOZ_MATHML
ccd8a32
 nsresult
ccd8a32
-nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
ccd8a32
-                                       nsBoundingMetrics &aBoundingMetrics,
ccd8a32
-                                       nsRenderingContextGTK *aContext)
ccd8a32
+nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
ccd8a32
+                               nscoord aX, nscoord aY,
ccd8a32
+                               const nscoord* aSpacing
ccd8a32
+                               CONTEXT_AND_SURFACE_ARG_DEF)
ccd8a32
 {
ccd8a32
-    printf("GetBoundingMetrics (char *)\n");
ccd8a32
-    return NS_ERROR_FAILURE;
ccd8a32
+    int x = aX;
ccd8a32
+    int y = aY;
ccd8a32
+
ccd8a32
+    aContext->GetTranMatrix()->TransformCoord(&x, &y);
ccd8a32
+
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
ccd8a32
+
ccd8a32
+    ApplySpacing(aString, aLength, line, aSpacing);
ccd8a32
+    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
ccd8a32
+
ccd8a32
+    g_object_unref(layout);
ccd8a32
+
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
-nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
ccd8a32
-                                       PRUint32 aLength,
ccd8a32
-                                       nsBoundingMetrics &aBoundingMetrics,
ccd8a32
-                                       PRInt32 *aFontID,
ccd8a32
-                                       nsRenderingContextGTK *aContext)
ccd8a32
+nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
+                               nscoord aX, nscoord aY,
ccd8a32
+                               PRInt32 aFontID,
ccd8a32
+                               const nscoord* aSpacing
ccd8a32
+                               CONTEXT_AND_SURFACE_ARG_DEF)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+    int x = aX;
ccd8a32
+    int y = aY;
ccd8a32
 
ccd8a32
-    gchar *text = g_utf16_to_utf8(aString, aLength,
ccd8a32
-                                  NULL, NULL, NULL);
ccd8a32
+    aContext->GetTranMatrix()->TransformCoord(&x, &y);
ccd8a32
 
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aString, aLength)
ccd8a32
-#endif
ccd8a32
-        aBoundingMetrics.Clear();
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
ccd8a32
 
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
+    ApplySpacing(aString, aLength, line, aSpacing);
ccd8a32
+    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
ccd8a32
 
ccd8a32
-    pango_layout_set_text(layout, text, -1);
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+    g_object_unref(layout);
ccd8a32
+
ccd8a32
+    return NS_OK;
ccd8a32
+}
ccd8a32
 
ccd8a32
-    PangoLayoutLine *line;
ccd8a32
-    if (pango_layout_get_line_count(layout) != 1) {
ccd8a32
-        printf("Warning: more than one line!\n");
ccd8a32
-    }
ccd8a32
-    line = pango_layout_get_line(layout, 0);
ccd8a32
+
ccd8a32
+#ifdef MOZ_MATHML
ccd8a32
+void
ccd8a32
+nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
ccd8a32
+                                               nsBoundingMetrics &aBoundingMetrics
ccd8a32
+                                               CONTEXT_ARG_DEF)
ccd8a32
+{
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
ccd8a32
 
ccd8a32
     // Get the ink and logical extents
ccd8a32
     PangoRectangle ink, logical;
ccd8a32
     pango_layout_line_get_extents(line, &ink, &logical);
ccd8a32
 
ccd8a32
-    float P2T;
ccd8a32
-    P2T = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
+    float P2T = mDeviceContext->DevUnitsToAppUnits();
ccd8a32
 
ccd8a32
     aBoundingMetrics.leftBearing  = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
ccd8a32
     aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
ccd8a32
     aBoundingMetrics.ascent       = NSToCoordRound(PANGO_ASCENT(ink)   * P2T / PANGO_SCALE);
ccd8a32
     aBoundingMetrics.descent      = NSToCoordRound(PANGO_DESCENT(ink)  * P2T / PANGO_SCALE);
ccd8a32
     aBoundingMetrics.width        = NSToCoordRound(logical.width       * P2T / PANGO_SCALE);
ccd8a32
+}
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    g_free(text);
ccd8a32
+nsresult
ccd8a32
+nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
ccd8a32
+                                       nsBoundingMetrics &aBoundingMetrics
ccd8a32
+                                       CONTEXT_ARG_DEF)
ccd8a32
+{
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
ccd8a32
     g_object_unref(layout);
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+   return NS_OK;
ccd8a32
+}
ccd8a32
+
ccd8a32
+nsresult
ccd8a32
+nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
ccd8a32
+                                       PRUint32 aLength,
ccd8a32
+                                       nsBoundingMetrics &aBoundingMetrics,
ccd8a32
+                                       PRInt32 *aFontID
ccd8a32
+                                       CONTEXT_ARG_DEF)
ccd8a32
+{
ccd8a32
+    PangoLayout *layout = GetLayout(aString, aLength);
ccd8a32
+    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
ccd8a32
+    g_object_unref(layout);
ccd8a32
+
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 #endif /* MOZ_MATHML */
ccd8a32
 
ccd8a32
+#ifndef PSPANGO
ccd8a32
 GdkFont*
ccd8a32
 nsFontMetricsPango::GetCurrentGDKFont(void)
ccd8a32
 {
ccd8a32
     return nsnull;
ccd8a32
 }
ccd8a32
+#endif
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
 nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
ccd8a32
 {
ccd8a32
     if (aIsRTL) {
ccd8a32
         if (!mRTLPangoContext) {
ccd8a32
-            mRTLPangoContext = gdk_pango_context_get();
ccd8a32
+            mRTLPangoContext = get_context();
ccd8a32
             pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
ccd8a32
-
ccd8a32
-            gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
ccd8a32
             pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
ccd8a32
             pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
ccd8a32
         }
ccd8a32
@@ -899,34 +1087,18 @@ nsFontMetricsPango::GetClusterInfo(const
ccd8a32
                                    PRUint32 aLength,
ccd8a32
                                    PRUint8 *aClusterStarts)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
     PangoLogAttr *attrs = NULL;
ccd8a32
     gint n_attrs = 0;
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
-    
ccd8a32
-    // Convert the incoming UTF-16 to UTF-8
ccd8a32
-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
ccd8a32
 
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aText, aLength)
ccd8a32
-#endif
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-
ccd8a32
-    // Set up the pango layout
ccd8a32
-    pango_layout_set_text(layout, text, strlen(text));
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+    PangoLayout *layout = GetLayout(aText, aLength);
ccd8a32
+    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
     // Convert back to UTF-16 while filling in the cluster info
ccd8a32
     // structure.
ccd8a32
-    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
ccd8a32
-
ccd8a32
     for (PRUint32 pos = 0; pos < aLength; pos++) {
ccd8a32
         if (IS_HIGH_SURROGATE(aText[pos])) {
ccd8a32
-            aClusterStarts[pos] = 1;
ccd8a32
+            aClusterStarts[pos] = 1;//FIXME: shouldn't this be zero?! --be
ccd8a32
             pos++;
ccd8a32
         }
ccd8a32
         else {
ccd8a32
@@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
ccd8a32
         }
ccd8a32
     }
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    if (attrs)
ccd8a32
-        g_free(attrs);
ccd8a32
-    if (text)
ccd8a32
-        g_free(text);
ccd8a32
-    if (layout)
ccd8a32
-        g_object_unref(layout);
ccd8a32
+    g_free(attrs);
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 PRInt32
ccd8a32
-nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
ccd8a32
-                                nsPoint aPt)
ccd8a32
+nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
ccd8a32
 {
ccd8a32
     int trailing = 0;
ccd8a32
     int inx = 0;
ccd8a32
-    const gchar *curChar;
ccd8a32
     PRInt32 retval = 0;
ccd8a32
 
ccd8a32
     float f = mDeviceContext->AppUnitsToDevUnits();
ccd8a32
     
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
     PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
ccd8a32
     PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
ccd8a32
 
ccd8a32
-    // Convert the incoming UTF-16 to UTF-8
ccd8a32
-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
ccd8a32
-
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aText, aLength)
ccd8a32
-#endif
ccd8a32
-        retval = -1;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-
ccd8a32
-    // Set up the pango layout
ccd8a32
-    pango_layout_set_text(layout, text, strlen(text));
ccd8a32
-    FixupSpaceWidths(layout, text);
ccd8a32
+    PangoLayout *layout = GetLayout(aText, aLength);
ccd8a32
     
ccd8a32
     pango_layout_xy_to_index(layout, localX, localY,
ccd8a32
                              &inx, &trailing);
ccd8a32
 
ccd8a32
     // Convert the index back to the utf-16 index
ccd8a32
-    curChar = text;
ccd8a32
+    const gchar *text = pango_layout_get_text (layout);
ccd8a32
+    const gchar *curChar = text;
ccd8a32
 
ccd8a32
     for (PRUint32 curOffset=0; curOffset < aLength;
ccd8a32
-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
ccd8a32
+         curOffset++, curChar = g_utf8_next_char(curChar)) {
ccd8a32
 
ccd8a32
         // Check for a match before checking for a surrogate pair
ccd8a32
         if (curChar - text == inx) {
ccd8a32
@@ -1006,13 +1156,9 @@ nsFontMetricsPango::GetPosition(const PR
ccd8a32
         trailing--;
ccd8a32
     }
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    if (text)
ccd8a32
-        g_free(text);
ccd8a32
-    if (layout)
ccd8a32
-        g_object_unref(layout);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
-    return retval;
ccd8a32
+    return retval; 
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
@@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const 
ccd8a32
                                   PRUint32 aEnd,
ccd8a32
                                   PRUint32 &aWidth)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
     PRUint32 utf8Start = 0;
ccd8a32
     PRUint32 utf8End = 0;
ccd8a32
 
ccd8a32
     aWidth = 0;
ccd8a32
 
ccd8a32
     // Convert the incoming UTF-16 to UTF-8
ccd8a32
-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
ccd8a32
-    gchar *curChar = text;
ccd8a32
 
ccd8a32
-    if (!text) {
ccd8a32
-#ifdef DEBUG
ccd8a32
-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
ccd8a32
-        DUMP_PRUNICHAR(aText, aLength)
ccd8a32
-#endif
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
+    gchar* text;
ccd8a32
+    gint text_len;
ccd8a32
+    utf16_to_utf8 (aText, aLength, text, text_len);
ccd8a32
+    gchar *curChar = text;
ccd8a32
 
ccd8a32
     // Convert the utf16 offsets into utf8 offsets
ccd8a32
     for (PRUint32 curOffset = 0; curOffset < aLength;
ccd8a32
-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
ccd8a32
+         curOffset++, curChar = g_utf8_next_char(curChar)) {
ccd8a32
 
ccd8a32
         if (curOffset == aStart)
ccd8a32
             utf8Start = curChar - text;
ccd8a32
@@ -1057,15 +1196,13 @@ nsFontMetricsPango::GetRangeWidth(const 
ccd8a32
 
ccd8a32
     // Special case where the end index is the same as the length
ccd8a32
     if (aLength == aEnd)
ccd8a32
-        utf8End = strlen(text);
ccd8a32
+        utf8End = text_len;
ccd8a32
 
ccd8a32
-    rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
ccd8a32
+    GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth);
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    if (text)
ccd8a32
-        g_free(text);
ccd8a32
+    g_free(text);
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
@@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const 
ccd8a32
                                   PRUint32 aEnd,
ccd8a32
                                   PRUint32 &aWidth)
ccd8a32
 {
ccd8a32
-    nsresult rv = NS_OK;
ccd8a32
     int *ranges = NULL;
ccd8a32
     int n_ranges = 0;
ccd8a32
     float f;
ccd8a32
 
ccd8a32
     aWidth = 0;
ccd8a32
 
ccd8a32
-    PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
-
ccd8a32
-    if (!aText) {
ccd8a32
-        rv = NS_ERROR_FAILURE;
ccd8a32
-        goto loser;
ccd8a32
-    }
ccd8a32
-
ccd8a32
-    pango_layout_set_text(layout, aText, aLength);
ccd8a32
-    FixupSpaceWidths(layout, aText);
ccd8a32
-
ccd8a32
-    PangoLayoutLine *line;
ccd8a32
-    if (pango_layout_get_line_count(layout) != 1) {
ccd8a32
-        printf("Warning: more than one line!\n");
ccd8a32
-    }
ccd8a32
-    line = pango_layout_get_line(layout, 0);
ccd8a32
+    PangoLayout *layout = GetLayout(aText, aLength);
ccd8a32
+    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
ccd8a32
 
ccd8a32
     pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
ccd8a32
 
ccd8a32
     aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
ccd8a32
 
ccd8a32
     f = mDeviceContext-> DevUnitsToAppUnits();
ccd8a32
-    aWidth = nscoord(aWidth * f / PANGO_SCALE);
ccd8a32
+    aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE);
ccd8a32
 
ccd8a32
- loser:
ccd8a32
-    if (ranges)
ccd8a32
-        g_free(ranges);
ccd8a32
-    if (layout)
ccd8a32
-        g_object_unref(layout);
ccd8a32
+    g_free(ranges);
ccd8a32
+    g_object_unref(layout);
ccd8a32
 
ccd8a32
-    return rv;
ccd8a32
+    return NS_OK;
ccd8a32
 }
ccd8a32
 
ccd8a32
 /* static */
ccd8a32
@@ -1134,7 +1254,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi
ccd8a32
     NS_ConvertUTF16toUTF8 name(aName);
ccd8a32
 
ccd8a32
     nsresult rv = NS_ERROR_FAILURE;
ccd8a32
-    PangoContext *context = gdk_pango_context_get();
ccd8a32
+    PangoContext *context = get_context();
ccd8a32
     PangoFontFamily **familyList;
ccd8a32
     int n;
ccd8a32
 
ccd8a32
@@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
ccd8a32
 
ccd8a32
     // Now that we have the font description set up, create the
ccd8a32
     // context.
ccd8a32
-    mLTRPangoContext = gdk_pango_context_get();
ccd8a32
+    mLTRPangoContext = get_context();
ccd8a32
     mPangoContext = mLTRPangoContext;
ccd8a32
 
ccd8a32
     // Make sure to set the base direction to LTR - if layout needs to
ccd8a32
     // render RTL text it will use ::SetRightToLeftText()
ccd8a32
     pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
ccd8a32
 
ccd8a32
-    // Set the color map so we can draw later.
ccd8a32
-    gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
ccd8a32
-
ccd8a32
     // Set the pango language now that we have a context
ccd8a32
     pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
ccd8a32
 
ccd8a32
@@ -1280,79 +1397,268 @@ nsFontMetricsPango::EnumFontCallback(con
ccd8a32
  * This is only used when there's per-character spacing happening.
ccd8a32
  * Well, really it can be either line or character spacing but it's
ccd8a32
  * just turtles all the way down!
ccd8a32
+ *
ccd8a32
+ * To do it correctly (ligatures, etc) we need machinery that is private
ccd8a32
+ * in Pango.  IMPORT IT:
ccd8a32
+ */
ccd8a32
+
ccd8a32
+#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter
ccd8a32
+#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter
ccd8a32
+
ccd8a32
+#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
ccd8a32
+
ccd8a32
+/* Structure holding state when we're iterating over a GlyphItem.
ccd8a32
+ * start_index/cluster_end (and range_start/range_end in
ccd8a32
+ * apply_attrs()) are offsets into the text, so note the difference
ccd8a32
+ * of glyph_item->item->offset between them and clusters in the
ccd8a32
+ * log_clusters[] array.
ccd8a32
  */
ccd8a32
+typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
ccd8a32
+
ccd8a32
+struct _PangoGlyphItemIter
ccd8a32
+{
ccd8a32
+  PangoGlyphItem *glyph_item;
ccd8a32
+  const gchar *text;
ccd8a32
+  
ccd8a32
+  int start_glyph;
ccd8a32
+  int start_index;
ccd8a32
+  int start_char;
ccd8a32
+
ccd8a32
+  int end_glyph;
ccd8a32
+  int end_index;
ccd8a32
+  int end_char;
ccd8a32
+};
ccd8a32
+
ccd8a32
+/**
ccd8a32
+ * _pango_glyph_item_iter_next_cluster:
ccd8a32
+ * @iter: a #PangoGlyphItemIter
ccd8a32
+ * 
ccd8a32
+ * Advances the iterator to the next cluster in the glyph item.
ccd8a32
+ * 
ccd8a32
+ * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
ccd8a32
+ *  last cluster.
ccd8a32
+ **/
ccd8a32
+static gboolean
ccd8a32
+_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
ccd8a32
+{
ccd8a32
+  int glyph_index = iter->end_glyph;
ccd8a32
+  PangoGlyphString *glyphs = iter->glyph_item->glyphs;
ccd8a32
+  PangoItem *item = iter->glyph_item->item;
ccd8a32
+
ccd8a32
+  if (LTR (iter->glyph_item))
ccd8a32
+    {
ccd8a32
+      if (glyph_index == glyphs->num_glyphs)
ccd8a32
+	return FALSE;
ccd8a32
+    }
ccd8a32
+  else
ccd8a32
+    {
ccd8a32
+      if (glyph_index < 0)
ccd8a32
+	return FALSE;
ccd8a32
+    }
ccd8a32
+      
ccd8a32
+  iter->start_glyph = iter->end_glyph;
ccd8a32
+  iter->start_index = iter->end_index;
ccd8a32
+  iter->start_char = iter->end_char;
ccd8a32
+  
ccd8a32
+  if (LTR (iter->glyph_item))
ccd8a32
+    {
ccd8a32
+      while (TRUE)
ccd8a32
+	{
ccd8a32
+	  glyph_index++;
ccd8a32
+	  
ccd8a32
+	  if (glyph_index == glyphs->num_glyphs)
ccd8a32
+	    {
ccd8a32
+	      iter->end_index = item->offset + item->length;
ccd8a32
+	      iter->end_char = item->num_chars;
ccd8a32
+	      break;
ccd8a32
+	    }
ccd8a32
+	  
ccd8a32
+	  if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
ccd8a32
+	    {
ccd8a32
+	      iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
ccd8a32
+	      iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
ccd8a32
+					       iter->end_index - iter->start_index);
ccd8a32
+	      break; 
ccd8a32
+	    }
ccd8a32
+	}
ccd8a32
+    }
ccd8a32
+  else			/* RTL */
ccd8a32
+    {
ccd8a32
+      while (TRUE)
ccd8a32
+	{
ccd8a32
+	  glyph_index--;
ccd8a32
+	  
ccd8a32
+	  if (glyph_index < 0)
ccd8a32
+	    {
ccd8a32
+	      iter->end_index = item->offset + item->length;
ccd8a32
+	      iter->end_char = item->num_chars;
ccd8a32
+	      break;
ccd8a32
+	    }
ccd8a32
+	  
ccd8a32
+	  if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
ccd8a32
+	    {
ccd8a32
+	      iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
ccd8a32
+	      iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
ccd8a32
+					       iter->end_index - iter->start_index);
ccd8a32
+	      break; 
ccd8a32
+	    }
ccd8a32
+	}
ccd8a32
+    }
ccd8a32
+
ccd8a32
+  iter->end_glyph = glyph_index;
ccd8a32
+  return TRUE;
ccd8a32
+}
ccd8a32
+
ccd8a32
+/**
ccd8a32
+ * _pango_glyph_item_iter_init_start:
ccd8a32
+ * @iter: pointer to a #PangoGlyphItemIter structure
ccd8a32
+ * @glyph_item: the glyph item that the iter points into
ccd8a32
+ * @text: text corresponding to the glyph item
ccd8a32
+ * 
ccd8a32
+ * Initializes a #PangoGlyphItemIter structure to point to the
ccd8a32
+ * first cluster in a glyph item.
ccd8a32
+ * 
ccd8a32
+ * Return value: %FALSE if there are no clusters in the glyph item;
ccd8a32
+ *  in this case, the state of the iter is undefined.
ccd8a32
+ **/
ccd8a32
+static gboolean
ccd8a32
+_pango_glyph_item_iter_init_start (PangoGlyphItemIter  *iter,
ccd8a32
+				   PangoGlyphItem      *glyph_item,
ccd8a32
+				   const char          *text)
ccd8a32
+{
ccd8a32
+  iter->glyph_item = glyph_item;
ccd8a32
+  iter->text = text;
ccd8a32
+  
ccd8a32
+  if (LTR (glyph_item))
ccd8a32
+    iter->end_glyph = 0;
ccd8a32
+  else
ccd8a32
+    iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
ccd8a32
+
ccd8a32
+  iter->end_index = glyph_item->item->offset;
ccd8a32
+  iter->end_char = 0;
ccd8a32
+
ccd8a32
+  /* Advance onto the first cluster of the glyph item */
ccd8a32
+  return _pango_glyph_item_iter_next_cluster (iter);
ccd8a32
+}
ccd8a32
+
ccd8a32
 
ccd8a32
 void
ccd8a32
-nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
ccd8a32
-                                     const PRUnichar *aOrigString,
ccd8a32
-                                     PRUint32 aLength,
ccd8a32
-                                     GdkDrawable *aDrawable,
ccd8a32
-                                     GdkGC *aGC, gint aX, gint aY,
ccd8a32
-                                     PangoLayoutLine *aLine,
ccd8a32
-                                     const nscoord *aSpacing)
ccd8a32
-{
ccd8a32
-    float app2dev;
ccd8a32
-    app2dev = mDeviceContext->AppUnitsToDevUnits();
ccd8a32
-    gint offset = 0;
ccd8a32
+nsFontMetricsPango::ApplySpacing(const gchar *aText,
ccd8a32
+                                 PRUint32 aLength,
ccd8a32
+                                 PangoLayoutLine *aLine,
ccd8a32
+                                 const nscoord *aSpacing)
ccd8a32
+{
ccd8a32
+    if (!(aSpacing && *aSpacing))
ccd8a32
+      return;
ccd8a32
+
ccd8a32
+    float app2dev = mDeviceContext->AppUnitsToDevUnits();
ccd8a32
 
ccd8a32
     /*
ccd8a32
      * We walk the list of glyphs returned in each layout run,
ccd8a32
      * matching up the glyphs with the characters in the source text.
ccd8a32
      * We use the aSpacing argument to figure out where to place those
ccd8a32
-     * glyphs.  It's important to note that since the string we're
ccd8a32
-     * working with is in UTF-8 while the spacing argument assumes
ccd8a32
-     * that offset will be part of the UTF-16 string.  Logical
ccd8a32
-     * attributes in pango are in byte offsets in the UTF-8 string, so
ccd8a32
-     * we need to store the offsets based on the UTF-8 string.
ccd8a32
+     * glyphs.
ccd8a32
      */
ccd8a32
-    nscoord *utf8spacing = new nscoord[strlen(aText)];
ccd8a32
+    for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
ccd8a32
+         tmpList = tmpList->next) {
ccd8a32
+        PangoGlyphItem *glyph_item = (PangoGlyphItem *)tmpList->data;
ccd8a32
+        PangoGlyphItemIter iter;
ccd8a32
+        gboolean have_cluster;
ccd8a32
+        PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs;
ccd8a32
+        int residualWidth = 0;
ccd8a32
+
ccd8a32
+        for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, aText);
ccd8a32
+             have_cluster;
ccd8a32
+             have_cluster = _pango_glyph_item_iter_next_cluster (&iter))
ccd8a32
+        {
ccd8a32
+          int clusterOldWidth = 0;
ccd8a32
+          int clusterNewWidth = 0;
ccd8a32
+          int dir = iter.start_glyph < iter.end_glyph ? +1 : -1;
ccd8a32
+          gboolean has_zero_width = FALSE;
ccd8a32
+
ccd8a32
+          for (const char *p = iter.text + iter.start_index;
ccd8a32
+               p < iter.text + iter.end_index;
ccd8a32
+               p = g_utf8_next_char (p))
ccd8a32
+            clusterNewWidth += aSpacing[p - iter.text];
ccd8a32
+
ccd8a32
+          clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE);
ccd8a32
+
ccd8a32
+          for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) {
ccd8a32
+            if (!glyphs[i].geometry.width)
ccd8a32
+              has_zero_width = TRUE;
ccd8a32
+            clusterOldWidth += glyphs[i].geometry.width;
ccd8a32
+          }
ccd8a32
+            
ccd8a32
+          /* if a zero-width glyph exists, don't touch the glyph widths.
ccd8a32
+           * required for combining marks.  ff thinks they have a width.
ccd8a32
+           * instead, we charge the difference to the next space glyph. */
ccd8a32
+          if (has_zero_width) {
ccd8a32
+            residualWidth += clusterNewWidth - clusterOldWidth;
ccd8a32
+            continue;
ccd8a32
+          }
ccd8a32
 
ccd8a32
-    if (aOrigString) {
ccd8a32
-        const gchar *curChar = aText;
ccd8a32
-        bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
ccd8a32
-
ccd8a32
-        // Covert the utf16 spacing offsets to utf8 spacing offsets
ccd8a32
-        for (PRUint32 curOffset=0; curOffset < aLength;
ccd8a32
-             curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
ccd8a32
-            utf8spacing[curChar - aText] = aSpacing[curOffset];
ccd8a32
+          /* If a space glyph is found, charge it whatever residual we
ccd8a32
+           * have accumulated so far. */
ccd8a32
+          if (iter.end_index - iter.start_index == 1 &&
ccd8a32
+              *(iter.text + iter.start_index) == ' ') {
ccd8a32
+            clusterNewWidth += residualWidth;
ccd8a32
+            residualWidth = 0;
ccd8a32
+          }
ccd8a32
+          
ccd8a32
+#ifndef PSPANGO
ccd8a32
+          /* do some hinting for display */
ccd8a32
+
ccd8a32
+          if (clusterOldWidth % PANGO_SCALE == 0 && clusterNewWidth % PANGO_SCALE != 0) {
ccd8a32
+            int tmp = clusterNewWidth;
ccd8a32
+            clusterNewWidth = PANGO_PIXELS (clusterNewWidth) * PANGO_SCALE;
ccd8a32
+            residualWidth += tmp - clusterNewWidth;
ccd8a32
+          }
ccd8a32
+#endif
ccd8a32
 
ccd8a32
-            if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
ccd8a32
-                curOffset++;
ccd8a32
+          /* find the first non-zero-width glyph and adjust its width */
ccd8a32
+          for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir)
ccd8a32
+            if (glyphs[i].geometry.width) {
ccd8a32
+              glyphs[i].geometry.width += clusterNewWidth - clusterOldWidth;
ccd8a32
+              break;
ccd8a32
+            }
ccd8a32
         }
ccd8a32
     }
ccd8a32
-    else {
ccd8a32
-        memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
ccd8a32
-    }
ccd8a32
+}
ccd8a32
 
ccd8a32
-    gint curRun = 0;
ccd8a32
+void
ccd8a32
+nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
ccd8a32
+                                 PRUint32 aLength,
ccd8a32
+                                 PangoLayoutLine *aLine,
ccd8a32
+                                 const nscoord *aSpacing)
ccd8a32
+{
ccd8a32
+    if (!(aSpacing && *aSpacing))
ccd8a32
+      return;
ccd8a32
 
ccd8a32
-    for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
ccd8a32
-         tmpList = tmpList->next, curRun++) {
ccd8a32
-        PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
ccd8a32
-        gint tmpOffset = 0;
ccd8a32
+    const char *utf8Text = pango_layout_get_text (aLine->layout);
ccd8a32
+    int utf8Text_len = aLine->start_index + aLine->length;
ccd8a32
 
ccd8a32
-        /*        printf("    Rendering run %d: \"%s\"\n", curRun,
ccd8a32
-                  &aText[layoutRun->item->offset]); */
ccd8a32
+    /* Since the string we're
ccd8a32
+     * working with is in UTF-8 while the spacing argument assumes
ccd8a32
+     * that offset will be part of the UTF-16 string.  Logical
ccd8a32
+     * attributes in pango are in byte offsets in the UTF-8 string, so
ccd8a32
+     * we need to store the offsets based on the UTF-8 string.
ccd8a32
+     */
ccd8a32
+    nscoord *utf8spacing = g_new0 (nscoord, utf8Text_len);
ccd8a32
 
ccd8a32
-        for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
ccd8a32
-            /* printf("glyph %d offset %d orig width %d new width %d\n", i,
ccd8a32
-             *        layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
ccd8a32
-             *        layoutRun->glyphs->glyphs[i].geometry.width,
ccd8a32
-             *       (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
ccd8a32
-             */
ccd8a32
-            gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
ccd8a32
-                                     * app2dev * PANGO_SCALE);
ccd8a32
-            layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
ccd8a32
-            tmpOffset += thisOffset;
ccd8a32
-        }
ccd8a32
+    const gchar *curChar = utf8Text + aLine->start_index;
ccd8a32
 
ccd8a32
-        /*        printf("    rendering at X coord %d\n", aX + offset); */
ccd8a32
-        offset += tmpOffset;
ccd8a32
+    // Covert the utf16 spacing offsets to utf8 spacing offsets
ccd8a32
+    for (PRUint32 curOffset=0; curOffset < aLength;
ccd8a32
+         curOffset++, curChar = g_utf8_next_char(curChar)) {
ccd8a32
+        utf8spacing[curChar - utf8Text] = aSpacing[curOffset];
ccd8a32
+
ccd8a32
+        if (IS_HIGH_SURROGATE(aText[curOffset]))
ccd8a32
+            curOffset++;
ccd8a32
     }
ccd8a32
 
ccd8a32
-    gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
ccd8a32
+    ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing);
ccd8a32
 
ccd8a32
-    delete[] utf8spacing;
ccd8a32
+    g_free (utf8spacing);
ccd8a32
 }
ccd8a32
 
ccd8a32
 nsresult
ccd8a32
@@ -1363,8 +1669,8 @@ nsFontMetricsPango::GetTextDimensionsInt
ccd8a32
                                               PRInt32             aNumBreaks,
ccd8a32
                                               nsTextDimensions&   aDimensions,
ccd8a32
                                               PRInt32&            aNumCharsFit,
ccd8a32
-                                              nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                              nsRenderingContextGTK *aContext)
ccd8a32
+                                              nsTextDimensions&   aLastWordDimensions
ccd8a32
+                                              CONTEXT_ARG_DEF)
ccd8a32
 {
ccd8a32
     NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
ccd8a32
 
ccd8a32
@@ -1410,7 +1716,7 @@ nsFontMetricsPango::GetTextDimensionsInt
ccd8a32
             // All the characters should fit
ccd8a32
             numChars = aLength - start;
ccd8a32
             breakIndex = aNumBreaks - 1;
ccd8a32
-        } 
ccd8a32
+        }
ccd8a32
         else {
ccd8a32
             breakIndex = prevBreakState_BreakIndex;
ccd8a32
             while (((breakIndex + 1) < aNumBreaks) &&
ccd8a32
@@ -1431,7 +1737,7 @@ nsFontMetricsPango::GetTextDimensionsInt
ccd8a32
         if ((1 == numChars) && (aString[start] == ' '))
ccd8a32
             GetSpaceWidth(twWidth);
ccd8a32
         else if (numChars > 0)
ccd8a32
-            GetWidth(&aString[start], numChars, twWidth, aContext);
ccd8a32
+            GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
ccd8a32
 
ccd8a32
         // See if the text fits
ccd8a32
         PRBool  textFits = (twWidth + width) <= aAvailWidth;
ccd8a32
@@ -1481,8 +1787,7 @@ nsFontMetricsPango::GetTextDimensionsInt
ccd8a32
                 if ((1 == numChars) && (aString[start] == ' '))
ccd8a32
                     GetSpaceWidth(twWidth);
ccd8a32
                 else if (numChars > 0)
ccd8a32
-                    GetWidth(&aString[start], numChars, twWidth,
ccd8a32
-                             aContext);
ccd8a32
+                    GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
ccd8a32
                 width -= twWidth;
ccd8a32
                 aNumCharsFit = start;
ccd8a32
                 breakIndex--;
ccd8a32
@@ -1504,9 +1809,16 @@ nsFontMetricsPango::GetTextDimensionsInt
ccd8a32
 }
ccd8a32
 
ccd8a32
 void
ccd8a32
-nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
ccd8a32
-                                      const char *aString)
ccd8a32
+nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
ccd8a32
 {
ccd8a32
+    if (!mPangoSpaceWidth)
ccd8a32
+      return;
ccd8a32
+
ccd8a32
+    const char *aString = pango_layout_get_text (aLayout);
ccd8a32
+
ccd8a32
+    if (pango_layout_get_line_count(aLayout) != 1) {
ccd8a32
+        printf("Warning: more than one line!\n");
ccd8a32
+    }
ccd8a32
     PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
ccd8a32
 
ccd8a32
     gint curRun = 0;
ccd8a32
@@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
ccd8a32
     }
ccd8a32
 }
ccd8a32
 
ccd8a32
+PangoLayout*
ccd8a32
+nsFontMetricsPango::GetLayout (const PRUnichar* aText,
ccd8a32
+                               PRUint32         aLength)
ccd8a32
+{
ccd8a32
+  gchar* text;
ccd8a32
+  gint length;
ccd8a32
+  utf16_to_utf8 (aText, aLength, text, length);
ccd8a32
+
ccd8a32
+  PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+  pango_layout_set_text (layout, text, length);
ccd8a32
+  FixupSpaceWidths (layout);
ccd8a32
+
ccd8a32
+  g_free ((gpointer) text);
ccd8a32
+
ccd8a32
+  return layout;
ccd8a32
+}
ccd8a32
+
ccd8a32
+PangoLayout*
ccd8a32
+nsFontMetricsPango::GetLayout (const gchar*     aText,
ccd8a32
+                               PRInt32          aLength)
ccd8a32
+{
ccd8a32
+  gboolean has_nul = FALSE;
ccd8a32
+  int i;
ccd8a32
+
ccd8a32
+  for (i = 0; i < aLength; i++)
ccd8a32
+    if (!aText[i]) {
ccd8a32
+      has_nul = TRUE;
ccd8a32
+      break;
ccd8a32
+    }
ccd8a32
+
ccd8a32
+  if (has_nul) {
ccd8a32
+    /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
ccd8a32
+
ccd8a32
+    char *p = (char *) g_memdup (aText, aLength);
ccd8a32
+
ccd8a32
+    /* don't need to reset i */
ccd8a32
+    for (; i < aLength; i++)
ccd8a32
+      if (!p[i])
ccd8a32
+        p[i] = (char) 0xff;
ccd8a32
+
ccd8a32
+    aText = p;
ccd8a32
+  }
ccd8a32
+
ccd8a32
+  PangoLayout *layout = pango_layout_new(mPangoContext);
ccd8a32
+  pango_layout_set_text (layout, aText, aLength);
ccd8a32
+  FixupSpaceWidths (layout);
ccd8a32
+
ccd8a32
+  if (has_nul)
ccd8a32
+    g_free ((gpointer) aText);
ccd8a32
+
ccd8a32
+  return layout;
ccd8a32
+}
ccd8a32
+
ccd8a32
+static void
ccd8a32
+utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
ccd8a32
+{
ccd8a32
+  gboolean need_copy = FALSE;
ccd8a32
+  int i;
ccd8a32
+
ccd8a32
+  for (i = 0; i < aLength; i++) {
ccd8a32
+    if (!aText[i] || IS_LOW_SURROGATE (aText[i]))
ccd8a32
+      need_copy = TRUE;
ccd8a32
+    else if (IS_HIGH_SURROGATE (aText[i])) {
ccd8a32
+      if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
ccd8a32
+        i++;
ccd8a32
+      else
ccd8a32
+        need_copy = TRUE;
ccd8a32
+    }
ccd8a32
+  }
ccd8a32
+
ccd8a32
+  if (need_copy) {
ccd8a32
+
ccd8a32
+    /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
ccd8a32
+    /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
ccd8a32
+
ccd8a32
+    PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0]));
ccd8a32
+
ccd8a32
+    /* don't need to reset i */
ccd8a32
+    for (i = 0; i < aLength; i++) {
ccd8a32
+      if (!p[i] || IS_LOW_SURROGATE (p[i]))
ccd8a32
+        p[i] = 0xFFFD;
ccd8a32
+      else if (IS_HIGH_SURROGATE (p[i])) {
ccd8a32
+        if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
ccd8a32
+          i++;
ccd8a32
+        else
ccd8a32
+          p[i] = 0xFFFD;
ccd8a32
+      }
ccd8a32
+    }
ccd8a32
+
ccd8a32
+    aText = p;
ccd8a32
+  }
ccd8a32
+
ccd8a32
+  glong items_written;
ccd8a32
+  text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
ccd8a32
+  length = items_written;
ccd8a32
+
ccd8a32
+  if (need_copy)
ccd8a32
+    g_free ((gpointer) aText);
ccd8a32
+
ccd8a32
+}
ccd8a32
+
ccd8a32
 /* static */
ccd8a32
 PangoLanguage *
ccd8a32
 GetPangoLanguage(nsIAtom *aLangGroup)
ccd8a32
--- mozilla.back/gfx/src/gtk/nsFontMetricsPango.h.orig	2006-06-30 01:18:34.000000000 +0200
ccd8a32
+++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.h	2007-06-28 15:16:39.000000000 +0200
ccd8a32
@@ -37,17 +37,53 @@
ccd8a32
  *
ccd8a32
  * ***** END LICENSE BLOCK ***** */
ccd8a32
 
ccd8a32
+
ccd8a32
 #include "nsIFontMetrics.h"
ccd8a32
 #include "nsIFontEnumerator.h"
ccd8a32
 #include "nsCRT.h"
ccd8a32
 #include "nsIAtom.h"
ccd8a32
 #include "nsString.h"
ccd8a32
 #include "nsVoidArray.h"
ccd8a32
+
ccd8a32
+#ifdef PSPANGO
ccd8a32
+#include "nsFontMetricsPS.h"
ccd8a32
+#else
ccd8a32
 #include "nsIFontMetricsGTK.h"
ccd8a32
+#endif
ccd8a32
 
ccd8a32
 #include <pango/pango.h>
ccd8a32
 
ccd8a32
-class nsFontMetricsPango : public nsIFontMetricsGTK
ccd8a32
+#ifdef PSPANGO
ccd8a32
+
ccd8a32
+#define CONTEXT_ARG_DEF
ccd8a32
+#define CONTEXT_ARG_PASS
ccd8a32
+#define CONTEXT_ARG_NULL
ccd8a32
+#define CONTEXT_AND_SURFACE_ARG_DEF  , nsRenderingContextPS *aContext
ccd8a32
+#define CONTEXT_AND_SURFACE_ARG_PASS , aContext
ccd8a32
+
ccd8a32
+#else
ccd8a32
+
ccd8a32
+#define CONTEXT_ARG_DEF              , nsRenderingContextGTK *aContext
ccd8a32
+#define CONTEXT_ARG_PASS             , aContext
ccd8a32
+#define CONTEXT_ARG_NULL             , NULL
ccd8a32
+#define CONTEXT_AND_SURFACE_ARG_DEF  , nsRenderingContextGTK *aContext, nsDrawingSurfaceGTK *aSurface
ccd8a32
+#define CONTEXT_AND_SURFACE_ARG_PASS , aContext, aSurface
ccd8a32
+
ccd8a32
+#endif
ccd8a32
+
ccd8a32
+
ccd8a32
+#ifdef PSPANGO
ccd8a32
+
ccd8a32
+#define nsFontMetricsPango   nsFontMetricsPSPango
ccd8a32
+#define PSPANGO_PARENT_CLASS nsFontMetricsPS
ccd8a32
+
ccd8a32
+#else
ccd8a32
+
ccd8a32
+#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
ccd8a32
+
ccd8a32
+#endif
ccd8a32
+
ccd8a32
+class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
ccd8a32
 {
ccd8a32
 public:
ccd8a32
     nsFontMetricsPango();
ccd8a32
@@ -136,20 +172,30 @@ public:
ccd8a32
 
ccd8a32
     PRInt32 GetMaxStringLength() { return mMaxStringLength; }
ccd8a32
 
ccd8a32
-    // nsIFontMetricsGTK (calls from the font rendering layer)
ccd8a32
-    virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
ccd8a32
-                              nscoord& aWidth,
ccd8a32
-                              nsRenderingContextGTK *aContext);
ccd8a32
-    virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
-                              nscoord& aWidth, PRInt32 *aFontID,
ccd8a32
-                              nsRenderingContextGTK *aContext);
ccd8a32
+    // nsIFontMetrics (calls from the font rendering layer)
ccd8a32
 
ccd8a32
-    virtual nsresult GetTextDimensions(const PRUnichar* aString,
ccd8a32
+#ifdef PSPANGO
ccd8a32
+    NS_IMETHOD  GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
ccd8a32
+    NS_IMETHOD  GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
ccd8a32
+#endif
ccd8a32
+
ccd8a32
+    NS_METHOD        GetWidth(const char* aString, PRUint32 aLength,
ccd8a32
+                              nscoord& aWidth
ccd8a32
+                              CONTEXT_ARG_DEF);
ccd8a32
+    NS_METHOD        GetWidth(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
+                              nscoord& aWidth, PRInt32 *aFontID
ccd8a32
+                              CONTEXT_ARG_DEF);
ccd8a32
+
ccd8a32
+    NS_METHOD        GetTextDimensions(const char* aString,
ccd8a32
+                                       PRUint32 aLength,
ccd8a32
+                                       nsTextDimensions& aDimensions
ccd8a32
+                                       CONTEXT_ARG_DEF);
ccd8a32
+    NS_METHOD        GetTextDimensions(const PRUnichar* aString,
ccd8a32
                                        PRUint32 aLength,
ccd8a32
                                        nsTextDimensions& aDimensions, 
ccd8a32
-                                       PRInt32* aFontID,
ccd8a32
-                                       nsRenderingContextGTK *aContext);
ccd8a32
-    virtual nsresult GetTextDimensions(const char*         aString,
ccd8a32
+                                       PRInt32* aFontID
ccd8a32
+                                       CONTEXT_ARG_DEF);
ccd8a32
+    NS_METHOD        GetTextDimensions(const char*         aString,
ccd8a32
                                        PRInt32             aLength,
ccd8a32
                                        PRInt32             aAvailWidth,
ccd8a32
                                        PRInt32*            aBreaks,
ccd8a32
@@ -157,9 +203,9 @@ public:
ccd8a32
                                        nsTextDimensions&   aDimensions,
ccd8a32
                                        PRInt32&            aNumCharsFit,
ccd8a32
                                        nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                       PRInt32*            aFontID,
ccd8a32
-                                       nsRenderingContextGTK *aContext);
ccd8a32
-    virtual nsresult GetTextDimensions(const PRUnichar*    aString,
ccd8a32
+                                       PRInt32*            aFontID
ccd8a32
+                                       CONTEXT_ARG_DEF);
ccd8a32
+    NS_METHOD        GetTextDimensions(const PRUnichar*    aString,
ccd8a32
                                        PRInt32             aLength,
ccd8a32
                                        PRInt32             aAvailWidth,
ccd8a32
                                        PRInt32*            aBreaks,
ccd8a32
@@ -167,38 +213,37 @@ public:
ccd8a32
                                        nsTextDimensions&   aDimensions,
ccd8a32
                                        PRInt32&            aNumCharsFit,
ccd8a32
                                        nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                       PRInt32*            aFontID,
ccd8a32
-                                       nsRenderingContextGTK *aContext);
ccd8a32
+                                       PRInt32*            aFontID
ccd8a32
+                                       CONTEXT_ARG_DEF);
ccd8a32
 
ccd8a32
-    virtual nsresult DrawString(const char *aString, PRUint32 aLength,
ccd8a32
+    NS_METHOD        DrawString(const char *aString, PRUint32 aLength,
ccd8a32
                                 nscoord aX, nscoord aY,
ccd8a32
-                                const nscoord* aSpacing,
ccd8a32
-                                nsRenderingContextGTK *aContext,
ccd8a32
-                                nsDrawingSurfaceGTK *aSurface);
ccd8a32
-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
+                                const nscoord* aSpacing  
ccd8a32
+                                CONTEXT_AND_SURFACE_ARG_DEF);
ccd8a32
+
ccd8a32
+    NS_METHOD        DrawString(const PRUnichar* aString, PRUint32 aLength,
ccd8a32
                                 nscoord aX, nscoord aY,
ccd8a32
                                 PRInt32 aFontID,
ccd8a32
-                                const nscoord* aSpacing,
ccd8a32
-                                nsRenderingContextGTK *aContext,
ccd8a32
-                                nsDrawingSurfaceGTK *aSurface);
ccd8a32
+                                const nscoord* aSpacing  
ccd8a32
+                                CONTEXT_AND_SURFACE_ARG_DEF);
ccd8a32
 
ccd8a32
 #ifdef MOZ_MATHML
ccd8a32
-    virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
ccd8a32
-                                        nsBoundingMetrics &aBoundingMetrics,
ccd8a32
-                                        nsRenderingContextGTK *aContext);
ccd8a32
-    virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
ccd8a32
+    NS_METHOD        GetBoundingMetrics(const char *aString, PRUint32 aLength,
ccd8a32
+                                        nsBoundingMetrics &aBoundingMetrics
ccd8a32
+                                        CONTEXT_ARG_DEF);
ccd8a32
+    NS_METHOD        GetBoundingMetrics(const PRUnichar *aString,
ccd8a32
                                         PRUint32 aLength,
ccd8a32
                                         nsBoundingMetrics &aBoundingMetrics,
ccd8a32
-                                        PRInt32 *aFontID,
ccd8a32
-                                        nsRenderingContextGTK *aContext);
ccd8a32
+                                        PRInt32 *aFontID
ccd8a32
+                                        CONTEXT_ARG_DEF);
ccd8a32
 #endif /* MOZ_MATHML */
ccd8a32
-
ccd8a32
+#ifndef PSPANGO
ccd8a32
     virtual GdkFont* GetCurrentGDKFont(void);
ccd8a32
-
ccd8a32
-    virtual nsresult SetRightToLeftText(PRBool aIsRTL);
ccd8a32
+#endif
ccd8a32
     virtual PRBool GetRightToLeftText();
ccd8a32
-
ccd8a32
-    virtual nsresult GetClusterInfo(const PRUnichar *aText,
ccd8a32
+    NS_METHOD        SetRightToLeftText(PRBool aIsRTL);
ccd8a32
+    
ccd8a32
+    NS_METHOD        GetClusterInfo(const PRUnichar *aText,
ccd8a32
                                     PRUint32 aLength,
ccd8a32
                                     PRUint8 *aClusterStarts);
ccd8a32
 
ccd8a32
@@ -206,32 +251,35 @@ public:
ccd8a32
                                 PRUint32 aLength,
ccd8a32
                                 nsPoint aPt);
ccd8a32
 
ccd8a32
-    virtual nsresult GetRangeWidth(const PRUnichar *aText,
ccd8a32
+    NS_METHOD        GetRangeWidth(const PRUnichar *aText,
ccd8a32
                                    PRUint32 aLength,
ccd8a32
                                    PRUint32 aStart,
ccd8a32
                                    PRUint32 aEnd,
ccd8a32
                                    PRUint32 &aWidth);
ccd8a32
 
ccd8a32
-    virtual nsresult GetRangeWidth(const char *aText,
ccd8a32
+    NS_METHOD        GetRangeWidth(const char *aText,
ccd8a32
                                    PRUint32 aLength,
ccd8a32
                                    PRUint32 aStart,
ccd8a32
                                    PRUint32 aEnd,
ccd8a32
                                    PRUint32 &aWidth);
ccd8a32
 
ccd8a32
     // get hints for the font
ccd8a32
-    static PRUint32    GetHints     (void);
ccd8a32
+#ifndef PSPANGO
ccd8a32
+    static
ccd8a32
+#endif
ccd8a32
+    PRUint32    GetHints     (void);
ccd8a32
 
ccd8a32
     // drawing surface methods
ccd8a32
     static nsresult FamilyExists    (nsIDeviceContext *aDevice,
ccd8a32
                                      const nsString &aName);
ccd8a32
 
ccd8a32
+
ccd8a32
 private:
ccd8a32
 
ccd8a32
     // generic font metrics class bits
ccd8a32
     nsCStringArray       mFontList;
ccd8a32
     nsAutoVoidArray      mFontIsGeneric;
ccd8a32
 
ccd8a32
-    nsIDeviceContext    *mDeviceContext;
ccd8a32
     nsCOMPtr<nsIAtom>    mLangGroup;
ccd8a32
     nsCString           *mGenericFont;
ccd8a32
     float                mPointSize;
ccd8a32
@@ -246,6 +294,9 @@ private:
ccd8a32
     PangoAttrList        *mPangoAttrList;
ccd8a32
     PRBool                mIsRTL;
ccd8a32
 
ccd8a32
+#ifndef PSPANGO
ccd8a32
+    nsIDeviceContext    *mDeviceContext; 
ccd8a32
+
ccd8a32
     // Cached font metrics
ccd8a32
     nscoord                  mXHeight;
ccd8a32
     nscoord                  mSuperscriptOffset;
ccd8a32
@@ -263,6 +314,7 @@ private:
ccd8a32
     nscoord                  mMaxDescent;
ccd8a32
     nscoord                  mMaxAdvance;
ccd8a32
     nscoord                  mSpaceWidth;
ccd8a32
+#endif
ccd8a32
     nscoord                  mPangoSpaceWidth;
ccd8a32
     nscoord                  mAveCharWidth;
ccd8a32
     PRInt32                  mMaxStringLength;
ccd8a32
@@ -274,13 +326,14 @@ private:
ccd8a32
     static PRBool EnumFontCallback(const nsString &aFamily,
ccd8a32
                                    PRBool aIsGeneric, void *aData);
ccd8a32
 
ccd8a32
-    void     DrawStringSlowly(const gchar *aText,
ccd8a32
-                              const PRUnichar *aOrigString,
ccd8a32
-                              PRUint32 aLength,
ccd8a32
-                              GdkDrawable *aDrawable,
ccd8a32
-                              GdkGC *aGC, gint aX, gint aY,
ccd8a32
-                              PangoLayoutLine *aLine,
ccd8a32
-                              const nscoord *aSpacing);
ccd8a32
+    void ApplySpacing(const gchar *aText,
ccd8a32
+                      PRUint32 aLength,
ccd8a32
+                      PangoLayoutLine *aLine,
ccd8a32
+                      const nscoord *aSpacing);
ccd8a32
+    void ApplySpacing(const PRUnichar *aText,
ccd8a32
+                      PRUint32 aLength,
ccd8a32
+                      PangoLayoutLine *aLine,
ccd8a32
+                      const nscoord *aSpacing);
ccd8a32
 
ccd8a32
     nsresult GetTextDimensionsInternal(const gchar*        aString,
ccd8a32
                                        PRInt32             aLength,
ccd8a32
@@ -289,10 +342,20 @@ private:
ccd8a32
                                        PRInt32             aNumBreaks,
ccd8a32
                                        nsTextDimensions&   aDimensions,
ccd8a32
                                        PRInt32&            aNumCharsFit,
ccd8a32
-                                       nsTextDimensions&   aLastWordDimensions,
ccd8a32
-                                       nsRenderingContextGTK *aContext);
ccd8a32
+                                       nsTextDimensions&   aLastWordDimensions
ccd8a32
+                                       CONTEXT_ARG_DEF);
ccd8a32
+#ifdef MOZ_MATHML
ccd8a32
+    void GetBoundingMetricsInternal(PangoLayout *aLayout,
ccd8a32
+                                    nsBoundingMetrics &aBoundingMetrics
ccd8a32
+                                    CONTEXT_ARG_DEF);
ccd8a32
+#endif /* MOZ_MATHML */
ccd8a32
+
ccd8a32
+    void FixupSpaceWidths (PangoLayout *aLayout);
ccd8a32
 
ccd8a32
-    void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
ccd8a32
+    PangoLayout* GetLayout (const PRUnichar* aText,
ccd8a32
+                            PRUint32         aLength);
ccd8a32
+    PangoLayout* GetLayout (const gchar*     aText,
ccd8a32
+                            PRInt32          aLength);
ccd8a32
 };
ccd8a32
 
ccd8a32
 class nsFontEnumeratorPango : public nsIFontEnumerator