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