1 --- mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp.orig 2007-06-28 14:44:31.000000000 +0200
2 +++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp 2007-06-28 15:48:04.000000000 +0200
4 * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
7 + * Christopher Blizzard <blizzard@mozilla.org>
8 + * Behdad Esfahbod <behdad@behdad.org>
10 * Alternatively, the contents of this file may be used under the terms of
11 * either the GNU General Public License Version 2 or later (the "GPL"), or
14 * ***** END LICENSE BLOCK ***** */
16 +#define PANGO_ENABLE_BACKEND
18 +#include "nsFontMetricsPango.h"
22 #include "nsIDeviceContext.h"
25 #include "nsServiceManagerUtils.h"
27 -#define PANGO_ENABLE_BACKEND
28 -#define PANGO_ENABLE_ENGINE
30 -#include "nsFontMetricsPango.h"
31 -#include "nsRenderingContextGTK.h"
32 -#include "nsDeviceContextGTK.h"
33 #include "nsFontConfigUtils.h"
35 #include "nsUnicharUtils.h"
36 #include "nsQuickSort.h"
37 #include "nsFontConfigUtils.h"
38 +#include "mozilla-decoder.h"
44 #include <fontconfig/fontconfig.h>
45 +#include <freetype/tttables.h>
47 +#include <pango/pango.h>
48 +#include <pango/pangofc-font.h>
51 +#include <pango/pangoft2.h>
52 +#include "nsRenderingContextPS.h"
53 +#include "nsDeviceContextPS.h"
58 -#include <freetype/tttables.h>
59 +#include "nsRenderingContextGTK.h"
60 +#include "nsDeviceContextGTK.h"
64 -#include "mozilla-decoder.h"
71 @@ -108,6 +124,49 @@ static nsresult EnumFontsPango (nsI
72 PRUint32* aCount, PRUnichar*** aResult);
73 static int CompareFontNames (const void* aArg1, const void* aArg2,
75 +static void utf16_to_utf8 (const PRUnichar* aString, PRUint32 aLength,
76 + char *&text, gint &text_len);
80 +default_substitute (FcPattern *pattern,
83 + FcPatternDel (pattern, FC_HINTING);
84 + FcPatternAddBool (pattern, FC_HINTING, 0);
88 +static PangoFontMap *
91 + static PangoFontMap *fontmap = NULL;
95 + fontmap = pango_ft2_font_map_new ();
96 + pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.);
97 + pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL);
99 + PangoContext* context = gdk_pango_context_get ();
100 + fontmap = pango_context_get_font_map (context);
101 + g_object_unref (context);
108 +static PangoContext *
112 + return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
114 + return gdk_pango_context_get();
119 nsFontMetricsPango::nsFontMetricsPango()
121 @@ -169,15 +228,21 @@
122 mLangGroup = aLangGroup;
124 // Hang on to the device context
126 + mDeviceContext = (nsDeviceContextPS *)aContext;
128 mDeviceContext = aContext;
132 mPointSize = NSTwipsToFloatPoints(mFont.size);
135 // Make sure to clamp the pixel size to something reasonable so we
136 // don't make the X server blow up.
137 nscoord screenPixels = gdk_screen_height();
138 mPointSize = PR_MIN((screenPixels - 1) * FONT_MAX_FONT_SCALE, mPointSize);
139 mPointSize = PR_MIN(2000, mPointSize);
142 // enumerate over the font names passed in
143 mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
144 @@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
147 PangoLayout *layout = pango_layout_new(mPangoContext);
148 - pango_layout_set_text(layout, " ", 1);
149 + pango_layout_set_text(layout, " ", -1);
150 int pswidth, psheight;
151 pango_layout_get_size(layout, &pswidth, &psheight);
152 mPangoSpaceWidth = pswidth;
153 @@ -337,14 +402,14 @@ nsFontMetricsPango::CacheFontMetrics(voi
155 // mSpaceWidth (width of a space)
157 - GetWidth(" ", 1, tmpWidth, NULL);
158 + GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL);
159 mSpaceWidth = tmpWidth;
161 // mAveCharWidth (width of an 'average' char)
162 // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
163 //rawWidth = extents.width;
164 //mAveCharWidth = NSToCoordRound(rawWidth * f);
165 - GetWidth("x", 1, tmpWidth, NULL);
166 + GetWidth("x", 1, tmpWidth CONTEXT_ARG_NULL);
167 mAveCharWidth = tmpWidth;
169 // mXHeight (height of an 'x' character)
170 @@ -460,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont
172 // nsIFontMetricsPango impl
175 -nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
177 - nsRenderingContextGTK *aContext)
180 +nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
182 - PangoLayout *layout = pango_layout_new(mPangoContext);
184 - pango_layout_set_text(layout, aString, aLength);
185 + return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL);
188 - if (mPangoSpaceWidth)
189 - FixupSpaceWidths(layout, aString);
191 +nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
193 + return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
198 +nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
204 + PangoLayout *layout = GetLayout(aString, aLength);
205 pango_layout_get_size(layout, &width, &height);
207 g_object_unref(layout);
210 - f = mDeviceContext->DevUnitsToAppUnits();
211 + float f = mDeviceContext->DevUnitsToAppUnits();
212 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
214 - // printf("GetWidth (char *) %d\n", aWidth);
220 nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
221 - nscoord& aWidth, PRInt32 *aFontID,
222 - nsRenderingContextGTK *aContext)
223 + nscoord& aWidth, PRInt32 *aFontID
226 - nsresult rv = NS_OK;
227 - PangoLayout *layout = pango_layout_new(mPangoContext);
229 - gchar *text = g_utf16_to_utf8(aString, aLength,
235 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
236 - DUMP_PRUNICHAR(aString, aLength)
238 - rv = NS_ERROR_FAILURE;
244 - pango_layout_set_text(layout, text, strlen(text));
245 - FixupSpaceWidths(layout, text);
246 + PangoLayout *layout = GetLayout(aString, aLength);
247 pango_layout_get_size(layout, &width, &height);
248 + g_object_unref(layout);
251 - f = mDeviceContext->DevUnitsToAppUnits();
252 + float f = mDeviceContext->DevUnitsToAppUnits();
253 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
255 - // printf("GetWidth %d\n", aWidth);
259 - g_object_unref(layout);
267 -nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
268 +nsFontMetricsPango::GetTextDimensions(const char* aString,
270 - nsTextDimensions& aDimensions,
272 - nsRenderingContextGTK *aContext)
273 + nsTextDimensions& aDimensions
276 - nsresult rv = NS_OK;
278 - PangoLayout *layout = pango_layout_new(mPangoContext);
279 + PangoLayout *layout = GetLayout(aString, aLength);
280 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
282 - gchar *text = g_utf16_to_utf8(aString, aLength,
287 - NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
288 - DUMP_PRUNICHAR(aString, aLength)
290 - aDimensions.width = 0;
291 - aDimensions.ascent = 0;
292 - aDimensions.descent = 0;
294 - rv = NS_ERROR_FAILURE;
298 + PangoRectangle logical;
299 + pango_layout_line_get_extents(line, NULL, &logical);
300 + g_object_unref(layout);
302 - pango_layout_set_text(layout, text, strlen(text));
303 - FixupSpaceWidths(layout, text);
304 + float P2T = mDeviceContext->DevUnitsToAppUnits();
306 - // Get the logical extents
307 - PangoLayoutLine *line;
308 - if (pango_layout_get_line_count(layout) != 1) {
309 - printf("Warning: more than one line!\n");
311 - line = pango_layout_get_line(layout, 0);
312 + aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE);
313 + aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
314 + aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
316 - PangoRectangle rect;
317 - pango_layout_line_get_extents(line, NULL, &rect);
322 - P2T = mDeviceContext->DevUnitsToAppUnits();
324 +nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
326 + nsTextDimensions& aDimensions,
330 + PangoLayout *layout = GetLayout(aString, aLength);
331 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
333 - aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
334 - aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
335 - aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
336 + PangoRectangle logical;
337 + pango_layout_line_get_extents(line, NULL, &logical);
338 + g_object_unref(layout);
340 - // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
341 - //aDimensions.ascent, aDimensions.descent);
342 + float P2T = mDeviceContext->DevUnitsToAppUnits();
346 - g_object_unref(layout);
347 + aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE);
348 + aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
349 + aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
356 @@ -595,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co
357 nsTextDimensions& aDimensions,
358 PRInt32& aNumCharsFit,
359 nsTextDimensions& aLastWordDimensions,
361 - nsRenderingContextGTK *aContext)
366 return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
367 aNumBreaks, aDimensions, aNumCharsFit,
368 - aLastWordDimensions, aContext);
369 + aLastWordDimensions CONTEXT_ARG_PASS);
373 @@ -614,8 +645,8 @@ nsFontMetricsPango::GetTextDimensions(co
374 nsTextDimensions& aDimensions,
375 PRInt32& aNumCharsFit,
376 nsTextDimensions& aLastWordDimensions,
378 - nsRenderingContextGTK *aContext)
383 PRInt32 curBreak = 0;
384 @@ -623,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co
386 PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
388 - gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
392 + utf16_to_utf8 (aString, aLength, text, text_len);
398 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
399 - DUMP_PRUNICHAR(aString, (PRUint32)aLength)
401 - rv = NS_ERROR_FAILURE;
405 // Covert the utf16 break offsets to utf8 break offsets
406 for (PRInt32 curOffset=0; curOffset < aLength;
407 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
408 + curOffset++, curChar = g_utf8_next_char(curChar)) {
409 if (aBreaks[curBreak] == curOffset) {
410 utf8Breaks[curBreak] = curChar - text;
412 @@ -653,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co
413 utf8Breaks[curBreak] = curChar - text;
416 - if (strlen(text) != aLength) {
417 - printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
418 + if (text_len != aLength) {
419 + printf("Different lengths for utf16 %d and utf8 %d\n", aLength, text_len);
420 DUMP_PRUNICHAR(aString, aLength)
421 - DUMP_PRUNICHAR(text, strlen(text))
422 + DUMP_PRUNICHAR(text, text_len)
423 for (PRInt32 i = 0; i < aNumBreaks; ++i) {
424 printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
426 @@ -666,9 +689,9 @@ nsFontMetricsPango::GetTextDimensions(co
427 // We'll use curBreak to indicate which of the breaks end up being
428 // used for the break point for this line.
430 - rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
431 + rv = GetTextDimensionsInternal(text, text_len, aAvailWidth, utf8Breaks,
432 aNumBreaks, aDimensions, aNumCharsFit,
433 - aLastWordDimensions, aContext);
434 + aLastWordDimensions CONTEXT_ARG_PASS);
436 // Figure out which of the breaks we ended up using to convert
437 // back to utf16 - start from the end.
438 @@ -681,200 +704,365 @@ nsFontMetricsPango::GetTextDimensions(co
453 -nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
454 - nscoord aX, nscoord aY,
455 - const nscoord* aSpacing,
456 - nsRenderingContextGTK *aContext,
457 - nsDrawingSurfaceGTK *aSurface)
460 +typedef struct _nsPSPangoRenderer nsPSPangoRenderer;
461 +typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass;
463 +struct _nsPSPangoRenderer
465 - PangoLayout *layout = pango_layout_new(mPangoContext);
466 + PangoRenderer parent_instance;
467 + nsRenderingContextPS *psContext;
468 + nsFontMetricsPSPango *psPangoFontMetrics;
472 - pango_layout_set_text(layout, aString, aLength);
473 - FixupSpaceWidths(layout, aString);
474 +struct _nsPSPangoRendererClass
476 + PangoRendererClass parent_class;
481 +#define _PS_TYPE_PANGO_RENDERER (_ps_pango_renderer_get_type())
482 +#define _PS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
483 +#define _PS_IS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
484 +#define _PS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
485 +#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
486 +#define _PS_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
488 - aContext->GetTranMatrix()->TransformCoord(&x, &y);
489 +G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
491 - PangoLayoutLine *line;
492 - if (pango_layout_get_line_count(layout) != 1) {
493 - printf("Warning: more than one line!\n");
495 - line = pango_layout_get_line(layout, 0);
496 +static PangoRenderer *
499 + static PangoRenderer *renderer = NULL;
501 - aContext->UpdateGC();
502 - GdkGC *gc = aContext->GetGC();
504 + renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
506 - if (aSpacing && *aSpacing) {
507 - DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
508 - gc, x, y, line, aSpacing);
511 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
518 - g_object_unref(gc);
519 - g_object_unref(layout);
521 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
523 + PangoGlyphString *glyphs,
527 - // printf("DrawString (char *)\n");
529 +_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
531 + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
533 + renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
538 +_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
542 +class nsPangoType1Generator : public nsPSFontGenerator {
544 + nsPangoType1Generator();
545 + ~nsPangoType1Generator();
546 + nsresult Init(PangoFont *aFont);
547 + void GeneratePSFont(FILE* aFile);
553 +nsPangoType1Generator::nsPangoType1Generator()
558 -nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
559 - nscoord aX, nscoord aY,
561 - const nscoord* aSpacing,
562 - nsRenderingContextGTK *aContext,
563 - nsDrawingSurfaceGTK *aSurface)
564 +nsPangoType1Generator::Init(PangoFont *aFont)
566 + NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
568 + g_object_ref (mFont);
572 +nsPangoType1Generator::~nsPangoType1Generator()
574 - nsresult rv = NS_OK;
577 + g_object_unref (mFont);
581 - aContext->UpdateGC();
582 - GdkGC *gc = aContext->GetGC();
583 +void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
585 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
587 - PangoLayout *layout = pango_layout_new(mPangoContext);
588 + if (face == nsnull)
591 - gchar *text = g_utf16_to_utf8(aString, aLength,
594 + if (mGlyphSubset->Count())
595 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
599 - NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
600 - DUMP_PRUNICHAR(aString, aLength)
602 - rv = NS_ERROR_FAILURE;
605 + pango_fc_font_unlock_face ((PangoFcFont *) mFont);
608 - pango_layout_set_text(layout, text, strlen(text));
609 - FixupSpaceWidths(layout, text);
612 + nsCString *FontNameBase;
617 - aContext->GetTranMatrix()->TransformCoord(&x, &y);
619 +ps_pango_font_data_destroy (PSPangoFontData *data)
622 + delete data->FontNameBase;
626 - PangoLayoutLine *line;
627 - if (pango_layout_get_line_count(layout) != 1) {
628 - printf("Warning: more than one line!\n");
630 - line = pango_layout_get_line(layout, 0);
632 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
634 + PangoGlyphString *glyphs,
638 + if (!glyphs->num_glyphs)
641 - if (aSpacing && *aSpacing) {
642 - DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
643 - gc, x, y, line, aSpacing);
646 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
650 + static GQuark data_quark = 0;
652 + data_quark = g_quark_from_static_string ("ps-pango-font-data");
655 + PSPangoFontData *data;
656 + if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
658 + data = g_new (PSPangoFontData, 1);
661 - g_object_unref(gc);
662 - g_object_unref(layout);
663 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
664 + if (face == nsnull)
667 + data->FontNameBase = new nsCString ();
668 + if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
670 + pango_fc_font_unlock_face ((PangoFcFont *) font);
673 + pango_fc_font_unlock_face ((PangoFcFont *) font);
675 - // printf("DrawString\n");
676 + PangoFontDescription *desc = pango_font_describe (font);
677 + data->font_size = pango_font_description_get_size (desc);
678 + pango_font_description_free (desc);
680 + data->key = new nsCStringKey (*data->FontNameBase);
682 + g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
685 + nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
686 + nsRenderingContextPS *aContext = ps_renderer->psContext;
687 + nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
688 + nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
689 + nsPostScriptObj* psObj = aContext->GetPostScriptObj();
690 + nsHashtable *psFGList = dc->GetPSFontGeneratorList();
691 + g_return_if_fail (psFGList);
692 + nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
695 + psFontGen = new nsPangoType1Generator;
696 + g_return_if_fail (psFontGen);
697 + rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
698 + if (NS_FAILED(rv)) {
702 + psFGList->Put(data->key, (void *) psFontGen);
704 + nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
706 + g_return_if_fail (aContext);
707 + g_return_if_fail (psObj);
709 + nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
710 + nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
711 + psObj->moveto(aX, aY);
713 + PRInt32 currSubFont, prevSubFont = -1;
715 + PangoGlyphString gl;
717 + gl.glyphs = glyphs->glyphs;
719 + currSubFont = prevSubFont;
720 + for (i = 0; i < glyphs->num_glyphs; ++i) {
721 + PangoGlyph glyph = glyphs->glyphs[i].glyph;
723 + if (glyph != PANGO_GLYPH_EMPTY)
724 + currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph);
726 + if (prevSubFont != currSubFont) {
727 + if (prevSubFont != -1)
728 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
730 + psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
731 + prevSubFont = currSubFont;
732 + gl.glyphs = glyphs->glyphs + i;
740 + if (prevSubFont != -1)
741 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
746 +draw_layout_line (int x, int y,
747 + PangoLayoutLine *line,
748 + nsFontMetricsPango *fm
749 + CONTEXT_AND_SURFACE_ARG_DEF)
752 + PangoRenderer *renderer = get_renderer ();
753 + nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
754 + ps_renderer->psContext = aContext;
755 + ps_renderer->psPangoFontMetrics = fm;
756 + nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, fm->GetDeviceContext());
757 + ps_renderer->zoom = dc->DevUnitsToAppUnits();
759 + pango_renderer_draw_layout_line (renderer, line,
760 + NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
761 + NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
763 + aContext->UpdateGC();
764 + GdkGC *gc = aContext->GetGC();
765 + gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line);
766 + g_object_unref(gc);
773 -nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
774 - nsBoundingMetrics &aBoundingMetrics,
775 - nsRenderingContextGTK *aContext)
776 +nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
777 + nscoord aX, nscoord aY,
778 + const nscoord* aSpacing
779 + CONTEXT_AND_SURFACE_ARG_DEF)
781 - printf("GetBoundingMetrics (char *)\n");
782 - return NS_ERROR_FAILURE;
786 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
788 + PangoLayout *layout = GetLayout(aString, aLength);
789 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
791 + ApplySpacing(aString, aLength, line, aSpacing);
792 + draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
794 + g_object_unref(layout);
800 -nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
802 - nsBoundingMetrics &aBoundingMetrics,
804 - nsRenderingContextGTK *aContext)
805 +nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
806 + nscoord aX, nscoord aY,
808 + const nscoord* aSpacing
809 + CONTEXT_AND_SURFACE_ARG_DEF)
811 - nsresult rv = NS_OK;
812 - PangoLayout *layout = pango_layout_new(mPangoContext);
816 - gchar *text = g_utf16_to_utf8(aString, aLength,
818 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
822 - NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
823 - DUMP_PRUNICHAR(aString, aLength)
825 - aBoundingMetrics.Clear();
826 + PangoLayout *layout = GetLayout(aString, aLength);
827 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
829 - rv = NS_ERROR_FAILURE;
832 + ApplySpacing(aString, aLength, line, aSpacing);
833 + draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
835 - pango_layout_set_text(layout, text, -1);
836 - FixupSpaceWidths(layout, text);
837 + g_object_unref(layout);
842 - PangoLayoutLine *line;
843 - if (pango_layout_get_line_count(layout) != 1) {
844 - printf("Warning: more than one line!\n");
846 - line = pango_layout_get_line(layout, 0);
850 +nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
851 + nsBoundingMetrics &aBoundingMetrics
854 + PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
856 // Get the ink and logical extents
857 PangoRectangle ink, logical;
858 pango_layout_line_get_extents(line, &ink, &logical);
861 - P2T = mDeviceContext->DevUnitsToAppUnits();
862 + float P2T = mDeviceContext->DevUnitsToAppUnits();
864 aBoundingMetrics.leftBearing = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
865 aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
866 aBoundingMetrics.ascent = NSToCoordRound(PANGO_ASCENT(ink) * P2T / PANGO_SCALE);
867 aBoundingMetrics.descent = NSToCoordRound(PANGO_DESCENT(ink) * P2T / PANGO_SCALE);
868 aBoundingMetrics.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
874 +nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
875 + nsBoundingMetrics &aBoundingMetrics
878 + PangoLayout *layout = GetLayout(aString, aLength);
879 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
880 g_object_unref(layout);
887 +nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
889 + nsBoundingMetrics &aBoundingMetrics,
893 + PangoLayout *layout = GetLayout(aString, aLength);
894 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
895 + g_object_unref(layout);
900 #endif /* MOZ_MATHML */
904 nsFontMetricsPango::GetCurrentGDKFont(void)
911 nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
914 if (!mRTLPangoContext) {
915 - mRTLPangoContext = gdk_pango_context_get();
916 + mRTLPangoContext = get_context();
917 pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
919 - gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
920 pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
921 pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
923 @@ -899,34 +1087,18 @@ nsFontMetricsPango::GetClusterInfo(const
925 PRUint8 *aClusterStarts)
927 - nsresult rv = NS_OK;
928 PangoLogAttr *attrs = NULL;
930 - PangoLayout *layout = pango_layout_new(mPangoContext);
932 - // Convert the incoming UTF-16 to UTF-8
933 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
937 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
938 - DUMP_PRUNICHAR(aText, aLength)
940 - rv = NS_ERROR_FAILURE;
944 - // Set up the pango layout
945 - pango_layout_set_text(layout, text, strlen(text));
946 - FixupSpaceWidths(layout, text);
947 + PangoLayout *layout = GetLayout(aText, aLength);
948 + pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
949 + g_object_unref(layout);
951 // Convert back to UTF-16 while filling in the cluster info
953 - pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
955 for (PRUint32 pos = 0; pos < aLength; pos++) {
956 if (IS_HIGH_SURROGATE(aText[pos])) {
957 - aClusterStarts[pos] = 1;
958 + aClusterStarts[pos] = 1;//FIXME: shouldn't this be zero?! --be
962 @@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
972 - g_object_unref(layout);
980 -nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
982 +nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
986 - const gchar *curChar;
989 float f = mDeviceContext->AppUnitsToDevUnits();
991 - PangoLayout *layout = pango_layout_new(mPangoContext);
992 PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
993 PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
995 - // Convert the incoming UTF-16 to UTF-8
996 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
1000 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1001 - DUMP_PRUNICHAR(aText, aLength)
1007 - // Set up the pango layout
1008 - pango_layout_set_text(layout, text, strlen(text));
1009 - FixupSpaceWidths(layout, text);
1010 + PangoLayout *layout = GetLayout(aText, aLength);
1012 pango_layout_xy_to_index(layout, localX, localY,
1015 // Convert the index back to the utf-16 index
1017 + const gchar *text = pango_layout_get_text (layout);
1018 + const gchar *curChar = text;
1020 for (PRUint32 curOffset=0; curOffset < aLength;
1021 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1022 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1024 // Check for a match before checking for a surrogate pair
1025 if (curChar - text == inx) {
1026 @@ -1006,13 +1156,9 @@ nsFontMetricsPango::GetPosition(const PR
1034 - g_object_unref(layout);
1035 + g_object_unref(layout);
1042 @@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const
1046 - nsresult rv = NS_OK;
1047 PRUint32 utf8Start = 0;
1048 PRUint32 utf8End = 0;
1052 // Convert the incoming UTF-16 to UTF-8
1053 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
1054 - gchar *curChar = text;
1058 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1059 - DUMP_PRUNICHAR(aText, aLength)
1061 - rv = NS_ERROR_FAILURE;
1066 + utf16_to_utf8 (aText, aLength, text, text_len);
1067 + gchar *curChar = text;
1069 // Convert the utf16 offsets into utf8 offsets
1070 for (PRUint32 curOffset = 0; curOffset < aLength;
1071 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1072 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1074 if (curOffset == aStart)
1075 utf8Start = curChar - text;
1076 @@ -1057,15 +1196,13 @@ nsFontMetricsPango::GetRangeWidth(const
1078 // Special case where the end index is the same as the length
1079 if (aLength == aEnd)
1080 - utf8End = strlen(text);
1081 + utf8End = text_len;
1083 - rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
1084 + GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth);
1096 @@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const
1100 - nsresult rv = NS_OK;
1107 - PangoLayout *layout = pango_layout_new(mPangoContext);
1110 - rv = NS_ERROR_FAILURE;
1114 - pango_layout_set_text(layout, aText, aLength);
1115 - FixupSpaceWidths(layout, aText);
1117 - PangoLayoutLine *line;
1118 - if (pango_layout_get_line_count(layout) != 1) {
1119 - printf("Warning: more than one line!\n");
1121 - line = pango_layout_get_line(layout, 0);
1122 + PangoLayout *layout = GetLayout(aText, aLength);
1123 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
1125 pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
1127 aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
1129 f = mDeviceContext-> DevUnitsToAppUnits();
1130 - aWidth = nscoord(aWidth * f / PANGO_SCALE);
1131 + aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE);
1137 - g_object_unref(layout);
1139 + g_object_unref(layout);
1146 @@ -1134,7 +1254,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi
1147 NS_ConvertUTF16toUTF8 name(aName);
1149 nsresult rv = NS_ERROR_FAILURE;
1150 - PangoContext *context = gdk_pango_context_get();
1151 + PangoContext *context = get_context();
1152 PangoFontFamily **familyList;
1155 @@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
1157 // Now that we have the font description set up, create the
1159 - mLTRPangoContext = gdk_pango_context_get();
1160 + mLTRPangoContext = get_context();
1161 mPangoContext = mLTRPangoContext;
1163 // Make sure to set the base direction to LTR - if layout needs to
1164 // render RTL text it will use ::SetRightToLeftText()
1165 pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
1167 - // Set the color map so we can draw later.
1168 - gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
1170 // Set the pango language now that we have a context
1171 pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
1173 @@ -1280,79 +1397,268 @@ nsFontMetricsPango::EnumFontCallback(con
1174 * This is only used when there's per-character spacing happening.
1175 * Well, really it can be either line or character spacing but it's
1176 * just turtles all the way down!
1178 + * To do it correctly (ligatures, etc) we need machinery that is private
1179 + * in Pango. IMPORT IT:
1182 +#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter
1183 +#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter
1185 +#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
1187 +/* Structure holding state when we're iterating over a GlyphItem.
1188 + * start_index/cluster_end (and range_start/range_end in
1189 + * apply_attrs()) are offsets into the text, so note the difference
1190 + * of glyph_item->item->offset between them and clusters in the
1191 + * log_clusters[] array.
1193 +typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
1195 +struct _PangoGlyphItemIter
1197 + PangoGlyphItem *glyph_item;
1198 + const gchar *text;
1210 + * _pango_glyph_item_iter_next_cluster:
1211 + * @iter: a #PangoGlyphItemIter
1213 + * Advances the iterator to the next cluster in the glyph item.
1215 + * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
1219 +_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
1221 + int glyph_index = iter->end_glyph;
1222 + PangoGlyphString *glyphs = iter->glyph_item->glyphs;
1223 + PangoItem *item = iter->glyph_item->item;
1225 + if (LTR (iter->glyph_item))
1227 + if (glyph_index == glyphs->num_glyphs)
1232 + if (glyph_index < 0)
1236 + iter->start_glyph = iter->end_glyph;
1237 + iter->start_index = iter->end_index;
1238 + iter->start_char = iter->end_char;
1240 + if (LTR (iter->glyph_item))
1246 + if (glyph_index == glyphs->num_glyphs)
1248 + iter->end_index = item->offset + item->length;
1249 + iter->end_char = item->num_chars;
1253 + if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1255 + iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
1256 + iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
1257 + iter->end_index - iter->start_index);
1268 + if (glyph_index < 0)
1270 + iter->end_index = item->offset + item->length;
1271 + iter->end_char = item->num_chars;
1275 + if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1277 + iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
1278 + iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
1279 + iter->end_index - iter->start_index);
1285 + iter->end_glyph = glyph_index;
1290 + * _pango_glyph_item_iter_init_start:
1291 + * @iter: pointer to a #PangoGlyphItemIter structure
1292 + * @glyph_item: the glyph item that the iter points into
1293 + * @text: text corresponding to the glyph item
1295 + * Initializes a #PangoGlyphItemIter structure to point to the
1296 + * first cluster in a glyph item.
1298 + * Return value: %FALSE if there are no clusters in the glyph item;
1299 + * in this case, the state of the iter is undefined.
1302 +_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter,
1303 + PangoGlyphItem *glyph_item,
1306 + iter->glyph_item = glyph_item;
1307 + iter->text = text;
1309 + if (LTR (glyph_item))
1310 + iter->end_glyph = 0;
1312 + iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
1314 + iter->end_index = glyph_item->item->offset;
1315 + iter->end_char = 0;
1317 + /* Advance onto the first cluster of the glyph item */
1318 + return _pango_glyph_item_iter_next_cluster (iter);
1323 -nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
1324 - const PRUnichar *aOrigString,
1326 - GdkDrawable *aDrawable,
1327 - GdkGC *aGC, gint aX, gint aY,
1328 - PangoLayoutLine *aLine,
1329 - const nscoord *aSpacing)
1332 - app2dev = mDeviceContext->AppUnitsToDevUnits();
1334 +nsFontMetricsPango::ApplySpacing(const gchar *aText,
1336 + PangoLayoutLine *aLine,
1337 + const nscoord *aSpacing)
1339 + if (!(aSpacing && *aSpacing))
1342 + float app2dev = mDeviceContext->AppUnitsToDevUnits();
1345 * We walk the list of glyphs returned in each layout run,
1346 * matching up the glyphs with the characters in the source text.
1347 * We use the aSpacing argument to figure out where to place those
1348 - * glyphs. It's important to note that since the string we're
1349 - * working with is in UTF-8 while the spacing argument assumes
1350 - * that offset will be part of the UTF-16 string. Logical
1351 - * attributes in pango are in byte offsets in the UTF-8 string, so
1352 - * we need to store the offsets based on the UTF-8 string.
1355 - nscoord *utf8spacing = new nscoord[strlen(aText)];
1356 + for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
1357 + tmpList = tmpList->next) {
1358 + PangoGlyphItem *glyph_item = (PangoGlyphItem *)tmpList->data;
1359 + PangoGlyphItemIter iter;
1360 + gboolean have_cluster;
1361 + PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs;
1362 + int residualWidth = 0;
1364 + for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, aText);
1366 + have_cluster = _pango_glyph_item_iter_next_cluster (&iter))
1368 + int clusterOldWidth = 0;
1369 + int clusterNewWidth = 0;
1370 + int dir = iter.start_glyph < iter.end_glyph ? +1 : -1;
1371 + gboolean has_zero_width = FALSE;
1373 + for (const char *p = iter.text + iter.start_index;
1374 + p < iter.text + iter.end_index;
1375 + p = g_utf8_next_char (p))
1376 + clusterNewWidth += aSpacing[p - iter.text];
1378 + clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE);
1380 + for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) {
1381 + if (!glyphs[i].geometry.width)
1382 + has_zero_width = TRUE;
1383 + clusterOldWidth += glyphs[i].geometry.width;
1386 + /* if a zero-width glyph exists, don't touch the glyph widths.
1387 + * required for combining marks. ff thinks they have a width.
1388 + * instead, we charge the difference to the next space glyph. */
1389 + if (has_zero_width) {
1390 + residualWidth += clusterNewWidth - clusterOldWidth;
1394 - if (aOrigString) {
1395 - const gchar *curChar = aText;
1396 - bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
1398 - // Covert the utf16 spacing offsets to utf8 spacing offsets
1399 - for (PRUint32 curOffset=0; curOffset < aLength;
1400 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1401 - utf8spacing[curChar - aText] = aSpacing[curOffset];
1402 + /* If a space glyph is found, charge it whatever residual we
1403 + * have accumulated so far. */
1404 + if (iter.end_index - iter.start_index == 1 &&
1405 + *(iter.text + iter.start_index) == ' ') {
1406 + clusterNewWidth += residualWidth;
1407 + residualWidth = 0;
1411 + /* do some hinting for display */
1413 + if (clusterOldWidth % PANGO_SCALE == 0 && clusterNewWidth % PANGO_SCALE != 0) {
1414 + int tmp = clusterNewWidth;
1415 + clusterNewWidth = PANGO_PIXELS (clusterNewWidth) * PANGO_SCALE;
1416 + residualWidth += tmp - clusterNewWidth;
1420 - if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
1422 + /* find the first non-zero-width glyph and adjust its width */
1423 + for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir)
1424 + if (glyphs[i].geometry.width) {
1425 + glyphs[i].geometry.width += clusterNewWidth - clusterOldWidth;
1431 - memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
1437 +nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
1439 + PangoLayoutLine *aLine,
1440 + const nscoord *aSpacing)
1442 + if (!(aSpacing && *aSpacing))
1445 - for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
1446 - tmpList = tmpList->next, curRun++) {
1447 - PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
1448 - gint tmpOffset = 0;
1449 + const char *utf8Text = pango_layout_get_text (aLine->layout);
1450 + int utf8Text_len = aLine->start_index + aLine->length;
1452 - /* printf(" Rendering run %d: \"%s\"\n", curRun,
1453 - &aText[layoutRun->item->offset]); */
1454 + /* Since the string we're
1455 + * working with is in UTF-8 while the spacing argument assumes
1456 + * that offset will be part of the UTF-16 string. Logical
1457 + * attributes in pango are in byte offsets in the UTF-8 string, so
1458 + * we need to store the offsets based on the UTF-8 string.
1460 + nscoord *utf8spacing = g_new0 (nscoord, utf8Text_len);
1462 - for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
1463 - /* printf("glyph %d offset %d orig width %d new width %d\n", i,
1464 - * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
1465 - * layoutRun->glyphs->glyphs[i].geometry.width,
1466 - * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
1468 - gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
1469 - * app2dev * PANGO_SCALE);
1470 - layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
1471 - tmpOffset += thisOffset;
1473 + const gchar *curChar = utf8Text + aLine->start_index;
1475 - /* printf(" rendering at X coord %d\n", aX + offset); */
1476 - offset += tmpOffset;
1477 + // Covert the utf16 spacing offsets to utf8 spacing offsets
1478 + for (PRUint32 curOffset=0; curOffset < aLength;
1479 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1480 + utf8spacing[curChar - utf8Text] = aSpacing[curOffset];
1482 + if (IS_HIGH_SURROGATE(aText[curOffset]))
1486 - gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
1487 + ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing);
1489 - delete[] utf8spacing;
1490 + g_free (utf8spacing);
1494 @@ -1363,8 +1669,8 @@ nsFontMetricsPango::GetTextDimensionsInt
1496 nsTextDimensions& aDimensions,
1497 PRInt32& aNumCharsFit,
1498 - nsTextDimensions& aLastWordDimensions,
1499 - nsRenderingContextGTK *aContext)
1500 + nsTextDimensions& aLastWordDimensions
1503 NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
1505 @@ -1410,7 +1716,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1506 // All the characters should fit
1507 numChars = aLength - start;
1508 breakIndex = aNumBreaks - 1;
1512 breakIndex = prevBreakState_BreakIndex;
1513 while (((breakIndex + 1) < aNumBreaks) &&
1514 @@ -1431,7 +1737,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1515 if ((1 == numChars) && (aString[start] == ' '))
1516 GetSpaceWidth(twWidth);
1517 else if (numChars > 0)
1518 - GetWidth(&aString[start], numChars, twWidth, aContext);
1519 + GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
1521 // See if the text fits
1522 PRBool textFits = (twWidth + width) <= aAvailWidth;
1523 @@ -1481,8 +1787,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1524 if ((1 == numChars) && (aString[start] == ' '))
1525 GetSpaceWidth(twWidth);
1526 else if (numChars > 0)
1527 - GetWidth(&aString[start], numChars, twWidth,
1529 + GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
1531 aNumCharsFit = start;
1533 @@ -1504,9 +1809,16 @@ nsFontMetricsPango::GetTextDimensionsInt
1537 -nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
1538 - const char *aString)
1539 +nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
1541 + if (!mPangoSpaceWidth)
1544 + const char *aString = pango_layout_get_text (aLayout);
1546 + if (pango_layout_get_line_count(aLayout) != 1) {
1547 + printf("Warning: more than one line!\n");
1549 PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
1552 @@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
1557 +nsFontMetricsPango::GetLayout (const PRUnichar* aText,
1562 + utf16_to_utf8 (aText, aLength, text, length);
1564 + PangoLayout *layout = pango_layout_new(mPangoContext);
1565 + pango_layout_set_text (layout, text, length);
1566 + FixupSpaceWidths (layout);
1568 + g_free ((gpointer) text);
1574 +nsFontMetricsPango::GetLayout (const gchar* aText,
1577 + gboolean has_nul = FALSE;
1580 + for (i = 0; i < aLength; i++)
1587 + /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
1589 + char *p = (char *) g_memdup (aText, aLength);
1591 + /* don't need to reset i */
1592 + for (; i < aLength; i++)
1594 + p[i] = (char) 0xff;
1599 + PangoLayout *layout = pango_layout_new(mPangoContext);
1600 + pango_layout_set_text (layout, aText, aLength);
1601 + FixupSpaceWidths (layout);
1604 + g_free ((gpointer) aText);
1610 +utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
1612 + gboolean need_copy = FALSE;
1615 + for (i = 0; i < aLength; i++) {
1616 + if (!aText[i] || IS_LOW_SURROGATE (aText[i]))
1618 + else if (IS_HIGH_SURROGATE (aText[i])) {
1619 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1628 + /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
1629 + /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
1631 + PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0]));
1633 + /* don't need to reset i */
1634 + for (i = 0; i < aLength; i++) {
1635 + if (!p[i] || IS_LOW_SURROGATE (p[i]))
1637 + else if (IS_HIGH_SURROGATE (p[i])) {
1638 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1648 + glong items_written;
1649 + text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
1650 + length = items_written;
1653 + g_free ((gpointer) aText);
1659 GetPangoLanguage(nsIAtom *aLangGroup)
1660 --- mozilla.back/gfx/src/gtk/nsFontMetricsPango.h.orig 2006-06-30 01:18:34.000000000 +0200
1661 +++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.h 2007-06-28 15:16:39.000000000 +0200
1664 * ***** END LICENSE BLOCK ***** */
1667 #include "nsIFontMetrics.h"
1668 #include "nsIFontEnumerator.h"
1670 #include "nsIAtom.h"
1671 #include "nsString.h"
1672 #include "nsVoidArray.h"
1675 +#include "nsFontMetricsPS.h"
1677 #include "nsIFontMetricsGTK.h"
1680 #include <pango/pango.h>
1682 -class nsFontMetricsPango : public nsIFontMetricsGTK
1685 +#define CONTEXT_ARG_DEF
1686 +#define CONTEXT_ARG_PASS
1687 +#define CONTEXT_ARG_NULL
1688 +#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextPS *aContext
1689 +#define CONTEXT_AND_SURFACE_ARG_PASS , aContext
1693 +#define CONTEXT_ARG_DEF , nsRenderingContextGTK *aContext
1694 +#define CONTEXT_ARG_PASS , aContext
1695 +#define CONTEXT_ARG_NULL , NULL
1696 +#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextGTK *aContext, nsDrawingSurfaceGTK *aSurface
1697 +#define CONTEXT_AND_SURFACE_ARG_PASS , aContext, aSurface
1704 +#define nsFontMetricsPango nsFontMetricsPSPango
1705 +#define PSPANGO_PARENT_CLASS nsFontMetricsPS
1709 +#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
1713 +class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
1716 nsFontMetricsPango();
1717 @@ -136,20 +172,30 @@ public:
1719 PRInt32 GetMaxStringLength() { return mMaxStringLength; }
1721 - // nsIFontMetricsGTK (calls from the font rendering layer)
1722 - virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
1724 - nsRenderingContextGTK *aContext);
1725 - virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
1726 - nscoord& aWidth, PRInt32 *aFontID,
1727 - nsRenderingContextGTK *aContext);
1728 + // nsIFontMetrics (calls from the font rendering layer)
1730 - virtual nsresult GetTextDimensions(const PRUnichar* aString,
1732 + NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
1733 + NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
1736 + NS_METHOD GetWidth(const char* aString, PRUint32 aLength,
1739 + NS_METHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
1740 + nscoord& aWidth, PRInt32 *aFontID
1743 + NS_METHOD GetTextDimensions(const char* aString,
1745 + nsTextDimensions& aDimensions
1747 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1749 nsTextDimensions& aDimensions,
1751 - nsRenderingContextGTK *aContext);
1752 - virtual nsresult GetTextDimensions(const char* aString,
1755 + NS_METHOD GetTextDimensions(const char* aString,
1757 PRInt32 aAvailWidth,
1759 @@ -157,9 +203,9 @@ public:
1760 nsTextDimensions& aDimensions,
1761 PRInt32& aNumCharsFit,
1762 nsTextDimensions& aLastWordDimensions,
1764 - nsRenderingContextGTK *aContext);
1765 - virtual nsresult GetTextDimensions(const PRUnichar* aString,
1768 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1770 PRInt32 aAvailWidth,
1772 @@ -167,38 +213,37 @@ public:
1773 nsTextDimensions& aDimensions,
1774 PRInt32& aNumCharsFit,
1775 nsTextDimensions& aLastWordDimensions,
1777 - nsRenderingContextGTK *aContext);
1781 - virtual nsresult DrawString(const char *aString, PRUint32 aLength,
1782 + NS_METHOD DrawString(const char *aString, PRUint32 aLength,
1783 nscoord aX, nscoord aY,
1784 - const nscoord* aSpacing,
1785 - nsRenderingContextGTK *aContext,
1786 - nsDrawingSurfaceGTK *aSurface);
1787 - virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
1788 + const nscoord* aSpacing
1789 + CONTEXT_AND_SURFACE_ARG_DEF);
1791 + NS_METHOD DrawString(const PRUnichar* aString, PRUint32 aLength,
1792 nscoord aX, nscoord aY,
1794 - const nscoord* aSpacing,
1795 - nsRenderingContextGTK *aContext,
1796 - nsDrawingSurfaceGTK *aSurface);
1797 + const nscoord* aSpacing
1798 + CONTEXT_AND_SURFACE_ARG_DEF);
1801 - virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
1802 - nsBoundingMetrics &aBoundingMetrics,
1803 - nsRenderingContextGTK *aContext);
1804 - virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
1805 + NS_METHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
1806 + nsBoundingMetrics &aBoundingMetrics
1808 + NS_METHOD GetBoundingMetrics(const PRUnichar *aString,
1810 nsBoundingMetrics &aBoundingMetrics,
1812 - nsRenderingContextGTK *aContext);
1815 #endif /* MOZ_MATHML */
1818 virtual GdkFont* GetCurrentGDKFont(void);
1820 - virtual nsresult SetRightToLeftText(PRBool aIsRTL);
1822 virtual PRBool GetRightToLeftText();
1824 - virtual nsresult GetClusterInfo(const PRUnichar *aText,
1825 + NS_METHOD SetRightToLeftText(PRBool aIsRTL);
1827 + NS_METHOD GetClusterInfo(const PRUnichar *aText,
1829 PRUint8 *aClusterStarts);
1831 @@ -206,32 +251,35 @@ public:
1835 - virtual nsresult GetRangeWidth(const PRUnichar *aText,
1836 + NS_METHOD GetRangeWidth(const PRUnichar *aText,
1842 - virtual nsresult GetRangeWidth(const char *aText,
1843 + NS_METHOD GetRangeWidth(const char *aText,
1849 // get hints for the font
1850 - static PRUint32 GetHints (void);
1854 + PRUint32 GetHints (void);
1856 // drawing surface methods
1857 static nsresult FamilyExists (nsIDeviceContext *aDevice,
1858 const nsString &aName);
1863 // generic font metrics class bits
1864 nsCStringArray mFontList;
1865 nsAutoVoidArray mFontIsGeneric;
1867 - nsIDeviceContext *mDeviceContext;
1868 nsCOMPtr<nsIAtom> mLangGroup;
1869 nsCString *mGenericFont;
1871 @@ -246,6 +294,9 @@ private:
1872 PangoAttrList *mPangoAttrList;
1876 + nsIDeviceContext *mDeviceContext;
1878 // Cached font metrics
1880 nscoord mSuperscriptOffset;
1881 @@ -263,6 +314,7 @@ private:
1882 nscoord mMaxDescent;
1883 nscoord mMaxAdvance;
1884 nscoord mSpaceWidth;
1886 nscoord mPangoSpaceWidth;
1887 nscoord mAveCharWidth;
1888 PRInt32 mMaxStringLength;
1889 @@ -274,13 +326,14 @@ private:
1890 static PRBool EnumFontCallback(const nsString &aFamily,
1891 PRBool aIsGeneric, void *aData);
1893 - void DrawStringSlowly(const gchar *aText,
1894 - const PRUnichar *aOrigString,
1896 - GdkDrawable *aDrawable,
1897 - GdkGC *aGC, gint aX, gint aY,
1898 - PangoLayoutLine *aLine,
1899 - const nscoord *aSpacing);
1900 + void ApplySpacing(const gchar *aText,
1902 + PangoLayoutLine *aLine,
1903 + const nscoord *aSpacing);
1904 + void ApplySpacing(const PRUnichar *aText,
1906 + PangoLayoutLine *aLine,
1907 + const nscoord *aSpacing);
1909 nsresult GetTextDimensionsInternal(const gchar* aString,
1911 @@ -289,10 +342,20 @@ private:
1913 nsTextDimensions& aDimensions,
1914 PRInt32& aNumCharsFit,
1915 - nsTextDimensions& aLastWordDimensions,
1916 - nsRenderingContextGTK *aContext);
1917 + nsTextDimensions& aLastWordDimensions
1920 + void GetBoundingMetricsInternal(PangoLayout *aLayout,
1921 + nsBoundingMetrics &aBoundingMetrics
1923 +#endif /* MOZ_MATHML */
1925 + void FixupSpaceWidths (PangoLayout *aLayout);
1927 - void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
1928 + PangoLayout* GetLayout (const PRUnichar* aText,
1929 + PRUint32 aLength);
1930 + PangoLayout* GetLayout (const gchar* aText,
1934 class nsFontEnumeratorPango : public nsIFontEnumerator