summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Stransky <stransky@fedoraproject.org>2007-07-09 10:15:21 +0000
committerMartin Stransky <stransky@fedoraproject.org>2007-07-09 10:15:21 +0000
commit4a48addf3bb0492afd28b1d2c4a057f5c977c1d5 (patch)
tree78dc7a1b808fc229e4a44d0f7f4992f047cf8e4f
parent- Properly clean up threads with newer NSPR (diff)
downloadlibrewolf-fedora-ff-4a48addf3bb0492afd28b1d2c4a057f5c977c1d5.tar.gz
librewolf-fedora-ff-4a48addf3bb0492afd28b1d2c4a057f5c977c1d5.tar.bz2
librewolf-fedora-ff-4a48addf3bb0492afd28b1d2c4a057f5c977c1d5.zip
backported pango patches from FC6
-rw-r--r--firefox-1.5-pango-cursor-position-more.patch19
-rw-r--r--firefox-1.5-pango-justified-range.patch53
-rw-r--r--firefox-1.5-pango-underline.patch39
-rw-r--r--firefox-1.5-xft-rangewidth.patch283
-rw-r--r--firefox-2.0-pango-ligatures.patch1932
-rw-r--r--firefox.spec16
6 files changed, 2341 insertions, 1 deletions
diff --git a/firefox-1.5-pango-cursor-position-more.patch b/firefox-1.5-pango-cursor-position-more.patch
new file mode 100644
index 0000000..ef5b967
--- /dev/null
+++ b/firefox-1.5-pango-cursor-position-more.patch
@@ -0,0 +1,19 @@
+diff -pruN -x '.moz*' -x .deps -x 'firefox*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp 2006-08-26 13:33:35.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp 2006-12-13 20:54:32.000000000 +0900
+@@ -4261,12 +4261,10 @@ nsTextFrame::GetPointFromOffset(nsPresCo
+ if (tc) {
+ totalLength = tc->Text()->GetLength(); // raw value which includes whitespace
+ }
+- if ((hitLength == textLength) && (inOffset = mContentLength) &&
+- (mContentOffset + mContentLength == totalLength)) {
+- // no need to re-measure when at the end of the last-in-flow
+- }
++ if (hitLength > 0)
++ inRendContext->GetRangeWidth(paintBuffer.mBuffer, textLength, 0, hitLength, (PRUint32&)width);
+ else
+- inRendContext->GetWidth(paintBuffer.mBuffer, hitLength, width);
++ width = 0;
+ }
+ if ((hitLength == textLength) && (TEXT_TRIMMED_WS & mState)) {
+ //
diff --git a/firefox-1.5-pango-justified-range.patch b/firefox-1.5-pango-justified-range.patch
new file mode 100644
index 0000000..7614d0e
--- /dev/null
+++ b/firefox-1.5-pango-justified-range.patch
@@ -0,0 +1,53 @@
+diff -pruN -x '.moz*' -x .deps -x 'thunderbird*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' -x 'firefox*' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp 2006-12-20 12:15:38.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp 2006-12-20 21:29:39.000000000 +0900
+@@ -2973,15 +2973,16 @@ nsTextFrame::RenderString(nsIRenderingCo
+
+ nsIFontMetrics* lastFont = aTextStyle.mLastFont;
+ PRInt32 pendingCount;
+- PRUnichar* runStart = bp;
++ PRUnichar* runStart = bp, *top = aBuffer;
+ nscoord charWidth, width = 0;
+ PRInt32 countSoFar = 0;
++ PRUint32 offset;
+ // Save the color we want to use for the text, since calls to
+ // PaintTextDecorations in this method will call SetColor() on the rendering
+ // context.
+ nscolor textColor;
+ aRenderingContext.GetColor(textColor);
+- for (; --aLength >= 0; aBuffer++) {
++ for (offset = 0; offset < aLength; aBuffer++, offset++) {
+ nsIFontMetrics* nextFont;
+ nscoord glyphWidth = 0;
+ PRUnichar ch = *aBuffer;
+@@ -3038,7 +3039,7 @@ nsTextFrame::RenderString(nsIRenderingCo
+ else if (ch == ' ') {
+ glyphWidth += aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing;
+ }
+- else if (IS_HIGH_SURROGATE(ch) && aLength > 0 &&
++ else if (IS_HIGH_SURROGATE(ch) && (offset + 1) < aLength &&
+ IS_LOW_SURROGATE(*(aBuffer+1))) {
+
+ // special handling for surrogate pair
+@@ -3046,7 +3047,7 @@ nsTextFrame::RenderString(nsIRenderingCo
+ glyphWidth += charWidth + aTextStyle.mLetterSpacing;
+ // copy the surrogate low
+ *bp++ = ch;
+- --aLength;
++ offset++;
+ aBuffer++;
+ ch = *aBuffer;
+ // put the width into the space buffer
+@@ -3058,10 +3059,10 @@ nsTextFrame::RenderString(nsIRenderingCo
+ glyphWidth = 0;
+ }
+ else {
+- aRenderingContext.GetWidth(ch, charWidth);
++ aRenderingContext.GetRangeWidth(top, aLength, offset, offset + 1, (PRUint32&)charWidth);
+ glyphWidth += charWidth + aTextStyle.mLetterSpacing;
+ }
+- if (justifying && (!isEndOfLine || aLength > 0)
++ if (justifying && (!isEndOfLine || (offset + 1) < aLength)
+ && IsJustifiableCharacter(ch, isCJ)) {
+ glyphWidth += aTextStyle.mExtraSpacePerJustifiableCharacter;
+ if ((PRUint32)--aTextStyle.mNumJustifiableCharacterToRender
diff --git a/firefox-1.5-pango-underline.patch b/firefox-1.5-pango-underline.patch
new file mode 100644
index 0000000..260be89
--- /dev/null
+++ b/firefox-1.5-pango-underline.patch
@@ -0,0 +1,39 @@
+diff -pruN -x '.moz*' -x .deps -x 'thunderbird*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp 2006-12-20 12:53:26.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp 2006-12-20 15:43:14.000000000 +0900
+@@ -2097,11 +2097,11 @@ nsTextFrame::PaintTextDecorations(nsIRen
+ nsRect rect = GetRect();
+ while(aDetails){
+ const nscoord* sp= aSpacing;
+- PRInt32 startOffset = 0;
+- PRInt32 textWidth = 0;
+- PRInt32 start = PR_MAX(0,(aDetails->mStart - (PRInt32)aIndex));
+- PRInt32 end = PR_MIN((PRInt32)aLength,(aDetails->mEnd - (PRInt32)aIndex));
+- PRInt32 i;
++ PRUint32 startOffset = 0;
++ PRUint32 textWidth = 0;
++ PRUint32 start = PR_MAX(0,(aDetails->mStart - (PRInt32)aIndex));
++ PRUint32 end = PR_MIN((PRInt32)aLength,(aDetails->mEnd - (PRInt32)aIndex));
++ PRUint32 i;
+ if ((start < end) && ((aLength - start) > 0))
+ {
+ //aDetails allready processed to have offsets from frame start not content offsets
+@@ -2117,7 +2117,7 @@ nsTextFrame::PaintTextDecorations(nsIRen
+ }
+ }
+ else
+- aRenderingContext.GetWidth(aText, start, startOffset);
++ aRenderingContext.GetRangeWidth(aText, aLength, 0, start, startOffset);
+ }
+ if (sp){
+ for (i = start; i < end;i ++){
+@@ -2125,8 +2125,7 @@ nsTextFrame::PaintTextDecorations(nsIRen
+ }
+ }
+ else
+- aRenderingContext.GetWidth(aText + start,
+- PRUint32(end - start), textWidth);
++ aRenderingContext.GetRangeWidth(aText, aLength, start, end, textWidth);
+
+ }
+ nscoord offset, size;
diff --git a/firefox-1.5-xft-rangewidth.patch b/firefox-1.5-xft-rangewidth.patch
new file mode 100644
index 0000000..1ecc5f2
--- /dev/null
+++ b/firefox-1.5-xft-rangewidth.patch
@@ -0,0 +1,283 @@
+diff -pruN -x '.moz*' -x .libs -x .deps -x dist -x 'config*' -x 'firefox*' -x '*a' -x '*so' -x '*o' -x build -x '*html' mozilla.orig/gfx/src/gtk/nsFontMetricsXft.cpp mozilla/gfx/src/gtk/nsFontMetricsXft.cpp
+--- mozilla.orig/gfx/src/gtk/nsFontMetricsXft.cpp 2006-04-25 08:58:36.000000000 +0900
++++ mozilla/gfx/src/gtk/nsFontMetricsXft.cpp 2007-02-08 01:50:05.000000000 +0900
+@@ -227,10 +227,14 @@ static nsresult EnumFontsXft (nsIAto
+
+ static void ConvertCharToUCS4 (const char *aString,
+ PRUint32 aLength,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ nsAutoFcChar32Buffer &aOutBuffer,
+ PRUint32 *aOutLen);
+ static void ConvertUnicharToUCS4 (const PRUnichar *aString,
+ PRUint32 aLength,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ nsAutoFcChar32Buffer &aOutBuffer,
+ PRUint32 *aOutLen);
+ static nsresult ConvertUCS4ToCustom (FcChar32 *aSrc, PRUint32 aSrcLen,
+@@ -507,7 +511,7 @@ nsFontMetricsXft::GetWidth(const PRUnich
+ return NS_OK;
+ }
+
+- gint rawWidth = RawGetWidth(aString, aLength);
++ gint rawWidth = RawGetWidth(aString, aLength, 0, aLength);
+
+ float f;
+ f = mDeviceContext->DevUnitsToAppUnits();
+@@ -533,7 +537,7 @@ nsFontMetricsXft::GetTextDimensions(cons
+ return NS_OK;
+
+ nsresult rv;
+- rv = EnumerateGlyphs(aString, aLength,
++ rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+ &nsFontMetricsXft::TextDimensionsCallback,
+ &aDimensions);
+
+@@ -608,7 +612,7 @@ nsFontMetricsXft::DrawString(const char
+ nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
+ data.drawBuffer = &drawBuffer;
+
+- return EnumerateGlyphs(aString, aLength,
++ return EnumerateGlyphs(aString, aLength, 0, aLength,
+ &nsFontMetricsXft::DrawStringCallback, &data);
+ }
+
+@@ -638,7 +642,7 @@ nsFontMetricsXft::DrawString(const PRUni
+ nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
+ data.drawBuffer = &drawBuffer;
+
+- return EnumerateGlyphs(aString, aLength,
++ return EnumerateGlyphs(aString, aLength, 0, aLength,
+ &nsFontMetricsXft::DrawStringCallback, &data);
+ }
+
+@@ -662,7 +666,7 @@ nsFontMetricsXft::GetBoundingMetrics(con
+ data.firstTime = PR_TRUE;
+
+ nsresult rv;
+- rv = EnumerateGlyphs(aString, aLength,
++ rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+ &nsFontMetricsXft::BoundingMetricsCallback, &data);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+@@ -700,7 +704,7 @@ nsFontMetricsXft::GetBoundingMetrics(con
+ data.firstTime = PR_TRUE;
+
+ nsresult rv;
+- rv = EnumerateGlyphs(aString, aLength,
++ rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+ &nsFontMetricsXft::BoundingMetricsCallback, &data);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+@@ -758,7 +762,17 @@ nsFontMetricsXft::GetRangeWidth(const PR
+ PRUint32 aEnd,
+ PRUint32 &aWidth)
+ {
+- return NS_ERROR_NOT_IMPLEMENTED;
++ if (!aLength) {
++ aWidth = 0;
++ return NS_OK;
++ }
++
++ gint rawWidth = RawGetWidth(aText, aLength, aStart, aEnd);
++ float f = mDeviceContext->DevUnitsToAppUnits();
++
++ aWidth = NSToCoordRound(rawWidth * f);
++
++ return NS_OK;
+ }
+
+ nsresult
+@@ -768,7 +782,17 @@ nsFontMetricsXft::GetRangeWidth(const ch
+ PRUint32 aEnd,
+ PRUint32 &aWidth)
+ {
+- return NS_ERROR_NOT_IMPLEMENTED;
++ if (!aLength) {
++ aWidth = 0;
++ return NS_OK;
++ }
++
++ gint rawWidth = RawGetWidth(aText, aLength, aStart, aEnd);
++ float f = mDeviceContext->DevUnitsToAppUnits();
++
++ aWidth = NSToCoordRound(rawWidth * f);
++
++ return NS_OK;
+ }
+
+ PRUint32
+@@ -850,12 +874,12 @@ nsFontMetricsXft::CacheFontMetrics(void)
+ // mSpaceWidth (width of a space)
+ gint rawWidth;
+ PRUnichar unispace(' ');
+- rawWidth = RawGetWidth(&unispace, 1);
++ rawWidth = RawGetWidth(&unispace, 1, 0, 1);
+ mSpaceWidth = NSToCoordRound(rawWidth * f);
+
+ // mAveCharWidth (width of an 'average' char)
+ PRUnichar xUnichar('x');
+- rawWidth = RawGetWidth(&xUnichar, 1);
++ rawWidth = RawGetWidth(&xUnichar, 1, 0, 1);
+ mAveCharWidth = NSToCoordRound(rawWidth * f);
+
+ // mXHeight (height of an 'x' character)
+@@ -1226,12 +1250,27 @@ nsFontMetricsXft::DoMatch(PRBool aMatchA
+ }
+
+ gint
+-nsFontMetricsXft::RawGetWidth(const PRUnichar* aString, PRUint32 aLength)
++nsFontMetricsXft::RawGetWidth(const PRUnichar* aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd)
++{
++ nscoord width = 0;
++ nsresult rv;
++
++ rv = EnumerateGlyphs(aString, aLength, aStart, aEnd,
++ &nsFontMetricsXft::GetWidthCallback, &width);
++
++ if (NS_FAILED(rv))
++ width = 0;
++
++ return width;
++}
++
++gint
++nsFontMetricsXft::RawGetWidth(const char* aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd)
+ {
+ nscoord width = 0;
+ nsresult rv;
+
+- rv = EnumerateGlyphs(aString, aLength,
++ rv = EnumerateGlyphs(aString, aLength, aStart, aEnd,
+ &nsFontMetricsXft::GetWidthCallback, &width);
+
+ if (NS_FAILED(rv))
+@@ -1457,6 +1496,8 @@ nsFontMetricsXft::EnumerateXftGlyphs(con
+ nsresult
+ nsFontMetricsXft::EnumerateGlyphs(const PRUnichar *aString,
+ PRUint32 aLen,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ GlyphEnumeratorCallback aCallback,
+ void *aCallbackData)
+ {
+@@ -1465,7 +1506,7 @@ nsFontMetricsXft::EnumerateGlyphs(const
+
+ NS_ENSURE_TRUE(aLen, NS_OK);
+
+- ConvertUnicharToUCS4(aString, aLen, charBuffer, &len);
++ ConvertUnicharToUCS4(aString, aLen, aStart, aEnd, charBuffer, &len);
+ if (!len)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+@@ -1475,6 +1516,8 @@ nsFontMetricsXft::EnumerateGlyphs(const
+ nsresult
+ nsFontMetricsXft::EnumerateGlyphs(const char *aString,
+ PRUint32 aLen,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ GlyphEnumeratorCallback aCallback,
+ void *aCallbackData)
+ {
+@@ -1484,7 +1527,7 @@ nsFontMetricsXft::EnumerateGlyphs(const
+ NS_ENSURE_TRUE(aLen, NS_OK);
+
+ // Convert the incoming string into an array of UCS4 chars
+- ConvertCharToUCS4(aString, aLen, charBuffer, &len);
++ ConvertCharToUCS4(aString, aLen, aStart, aEnd, charBuffer, &len);
+ if (!len)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+@@ -2343,7 +2386,7 @@ EnumFontsXft(nsIAtom* aLangGroup, const
+
+ /* static */
+ void
+-ConvertCharToUCS4(const char *aString, PRUint32 aLength,
++ConvertCharToUCS4(const char *aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd,
+ nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
+ {
+ *aOutLen = 0;
+@@ -2352,19 +2395,21 @@ ConvertCharToUCS4(const char *aString, P
+ if (!aOutBuffer.EnsureElemCapacity(aLength))
+ return;
+ outBuffer = aOutBuffer.get();
++ if (aEnd > aLength)
++ aEnd = aLength;
+
+- for (PRUint32 i = 0; i < aLength; ++i) {
+- outBuffer[i] = PRUint8(aString[i]); // to convert char >= 0x80 correctly
++ for (PRUint32 i = aStart; i < aLength && i < aEnd; ++i) {
++ outBuffer[i - aStart] = PRUint8(aString[i]); // to convert char >= 0x80 correctly
+ }
+
+- *aOutLen = aLength;
++ *aOutLen = aEnd - aStart;
+ }
+
+ // Convert the incoming string into an array of UCS4 chars
+
+ /* static */
+ void
+-ConvertUnicharToUCS4(const PRUnichar *aString, PRUint32 aLength,
++ConvertUnicharToUCS4(const PRUnichar *aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd,
+ nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
+ {
+ *aOutLen = 0;
+@@ -2378,7 +2423,7 @@ ConvertUnicharToUCS4(const PRUnichar *aS
+
+ // Walk the passed in string looking for surrogates to convert to
+ // their full ucs4 representation.
+- for (PRUint32 i = 0; i < aLength; ++i) {
++ for (PRUint32 i = aStart; i < aLength && i < aEnd; ++i) {
+ PRUnichar c = aString[i];
+
+ // Optimized for the non-surrogate case
+@@ -2693,12 +2738,12 @@ ConvertUCS4ToCustom(FcChar32 *aSrc, PRU
+ #endif
+ // Convert 16bit custom font codes to UCS4
+ ConvertUnicharToUCS4(NS_REINTERPRET_CAST(PRUnichar *, med),
+- medLen >> 1, aResult, &aDestLen);
++ medLen >> 1, 0, medLen >> 1, aResult, &aDestLen);
+ rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
+ }
+ else {
+ // Convert 8bit custom font codes to UCS4
+- ConvertCharToUCS4(med, medLen, aResult, &aDestLen);
++ ConvertCharToUCS4(med, medLen, 0, medLen, aResult, &aDestLen);
+ rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
+ }
+
+diff -pruN -x '.moz*' -x .libs -x .deps -x dist -x 'config*' -x 'firefox*' -x '*a' -x '*so' -x '*o' -x build -x '*html' mozilla.orig/gfx/src/gtk/nsFontMetricsXft.h mozilla/gfx/src/gtk/nsFontMetricsXft.h
+--- mozilla.orig/gfx/src/gtk/nsFontMetricsXft.h 2005-05-03 05:48:30.000000000 +0900
++++ mozilla/gfx/src/gtk/nsFontMetricsXft.h 2007-02-08 01:38:27.000000000 +0900
+@@ -259,7 +259,13 @@ private:
+ void DoMatch (PRBool aMatchAll);
+
+ gint RawGetWidth (const PRUnichar* aString,
+- PRUint32 aLength);
++ PRUint32 aLength,
++ PRUint32 aStart,
++ PRUint32 aEnd);
++ gint RawGetWidth (const char* aString,
++ PRUint32 aLength,
++ PRUint32 aStart,
++ PRUint32 aEnd);
+ nsresult SetupMiniFont (void);
+ nsresult DrawUnknownGlyph (FcChar32 aChar,
+ nscoord aX,
+@@ -272,10 +278,14 @@ private:
+ void *aCallbackData);
+ nsresult EnumerateGlyphs (const char *aString,
+ PRUint32 aLen,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ GlyphEnumeratorCallback aCallback,
+ void *aCallbackData);
+ nsresult EnumerateGlyphs (const PRUnichar *aString,
+ PRUint32 aLen,
++ PRUint32 aStart,
++ PRUint32 aEnd,
+ GlyphEnumeratorCallback aCallback,
+ void *aCallbackData);
+ void PrepareToDraw (nsRenderingContextGTK *aContext,
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
diff --git a/firefox.spec b/firefox.spec
index b3fffdc..dab7fc9 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -12,7 +12,7 @@
Summary: Mozilla Firefox Web browser.
Name: firefox
Version: 2.0.0.4
-Release: 2%{?dist}
+Release: 3%{?dist}
URL: http://www.mozilla.org/projects/firefox/
License: MPL/LGPL
Group: Applications/Internet
@@ -60,6 +60,12 @@ Patch81: firefox-1.5-nopangoxft.patch
Patch82: firefox-1.5-pango-mathml.patch
Patch83: firefox-1.5-pango-cursor-position.patch
Patch84: firefox-2.0-pango-printing.patch
+Patch85: firefox-2.0-pango-ligatures.patch
+Patch86: firefox-1.5-pango-cursor-position-more.patch
+Patch87: firefox-1.5-pango-justified-range.patch
+Patch88: firefox-1.5-pango-underline.patch
+Patch89: firefox-1.5-xft-rangewidth.patch
+
# Other
Patch100: firefox-1.5-thread-cleanup.patch
@@ -157,6 +163,11 @@ removed in favor of xulrunner-devel.
#%patch82 -p1 -b .pango-mathml
%patch83 -p1 -b .pango-cursor-position
%patch84 -p0 -b .pango-printing
+%patch85 -p1 -b .pango-ligatures
+%patch86 -p1 -b .pango-cursor-position-more
+%patch87 -p1 -b .pango-justified-range
+%patch88 -p1 -b .pango-underline
+%patch89 -p1 -b .nopangoxft2
%patch100 -p1 -b .thread-cleanup
%patch102 -p0 -b .theme-change
@@ -418,6 +429,9 @@ fi
#---------------------------------------------------------------------
%changelog
+* Fri Jun 29 2007 Martin Stransky <stransky@redhat.com> 2.0.0.4-3
+- backported pango patches from FC6 (1.5.0.12)
+
* Sun Jun 3 2007 Christopher Aillon <caillon@redhat.com> 2.0.0.4-2
- Properly clean up threads with newer NSPR
bgstack15