Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 158138 Details for
Bug 221703
Ligatures displayed incorrectly in Firefox
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
backported changes from ff 1.5
firefox-2.0-pango-ligatures.patch (text/plain), 65.14 KB, created by
Martin Stransky
on 2007-06-28 16:21:39 UTC
(
hide
)
Description:
backported changes from ff 1.5
Filename:
MIME Type:
Creator:
Martin Stransky
Created:
2007-06-28 16:21:39 UTC
Size:
65.14 KB
patch
obsolete
>--- 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
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 221703
: 158138