From bede30df0baea7e8e1e2f6d108a73e051cd64fc3 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Tue, 18 Dec 2007 14:33:32 +0000 Subject: - moved to XUL Runner and updated to 3.0b3pre - removed firefox-devel package, gecko-libs is provided by xulrunner-devel now. --- firefox-2.0-pango-ligatures.patch | 1932 ------------------------------------- 1 file changed, 1932 deletions(-) delete mode 100644 firefox-2.0-pango-ligatures.patch (limited to 'firefox-2.0-pango-ligatures.patch') diff --git a/firefox-2.0-pango-ligatures.patch b/firefox-2.0-pango-ligatures.patch deleted file mode 100644 index cfd1da7..0000000 --- a/firefox-2.0-pango-ligatures.patch +++ /dev/null @@ -1,1932 +0,0 @@ ---- 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 -+ * Behdad Esfahbod - * - * 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 - #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 -+#include -+ -+#include -+#include -+ -+#ifdef PSPANGO -+#include -+#include "nsRenderingContextPS.h" -+#include "nsDeviceContextPS.h" -+#include "nsType1.h" -+#else - #include - #include --#include -+#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 - 1) * 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 - --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 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 -- cgit