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,14 +228,20 @@ nsFontMetricsPango::Init(const nsFont& a
122 mLangGroup = aLangGroup;
124 // Hang on to the device context
126 + mDeviceContext = (nsDeviceContextPS *)aContext;
128 mDeviceContext = aContext;
131 mPointSize = NSTwipsToFloatPoints(mFont.size);
134 // Make sure to clamp the pixel size to something reasonable so we
135 // don't make the X server blow up.
136 nscoord screenPixels = gdk_screen_height();
137 mPointSize = PR_MIN((screenPixels - 1) * FONT_MAX_FONT_SCALE, mPointSize);
140 // enumerate over the font names passed in
141 mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
142 @@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
145 PangoLayout *layout = pango_layout_new(mPangoContext);
146 - pango_layout_set_text(layout, " ", 1);
147 + pango_layout_set_text(layout, " ", -1);
148 int pswidth, psheight;
149 pango_layout_get_size(layout, &pswidth, &psheight);
150 mPangoSpaceWidth = pswidth;
151 @@ -337,14 +402,14 @@ nsFontMetricsPango::CacheFontMetrics(voi
153 // mSpaceWidth (width of a space)
155 - GetWidth(" ", 1, tmpWidth, NULL);
156 + GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL);
157 mSpaceWidth = tmpWidth;
159 // mAveCharWidth (width of an 'average' char)
160 // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
161 //rawWidth = extents.width;
162 //mAveCharWidth = NSToCoordRound(rawWidth * f);
163 - GetWidth("x", 1, tmpWidth, NULL);
164 + GetWidth("x", 1, tmpWidth CONTEXT_ARG_NULL);
165 mAveCharWidth = tmpWidth;
167 // mXHeight (height of an 'x' character)
168 @@ -460,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont
170 // nsIFontMetricsPango impl
173 -nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
175 - nsRenderingContextGTK *aContext)
178 +nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
180 - PangoLayout *layout = pango_layout_new(mPangoContext);
182 - pango_layout_set_text(layout, aString, aLength);
183 + return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL);
186 - if (mPangoSpaceWidth)
187 - FixupSpaceWidths(layout, aString);
189 +nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
191 + return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
196 +nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
202 + PangoLayout *layout = GetLayout(aString, aLength);
203 pango_layout_get_size(layout, &width, &height);
205 g_object_unref(layout);
208 - f = mDeviceContext->DevUnitsToAppUnits();
209 + float f = mDeviceContext->DevUnitsToAppUnits();
210 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
212 - // printf("GetWidth (char *) %d\n", aWidth);
218 nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
219 - nscoord& aWidth, PRInt32 *aFontID,
220 - nsRenderingContextGTK *aContext)
221 + nscoord& aWidth, PRInt32 *aFontID
224 - nsresult rv = NS_OK;
225 - PangoLayout *layout = pango_layout_new(mPangoContext);
227 - gchar *text = g_utf16_to_utf8(aString, aLength,
233 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
234 - DUMP_PRUNICHAR(aString, aLength)
236 - rv = NS_ERROR_FAILURE;
242 - pango_layout_set_text(layout, text, strlen(text));
243 - FixupSpaceWidths(layout, text);
244 + PangoLayout *layout = GetLayout(aString, aLength);
245 pango_layout_get_size(layout, &width, &height);
246 + g_object_unref(layout);
249 - f = mDeviceContext->DevUnitsToAppUnits();
250 + float f = mDeviceContext->DevUnitsToAppUnits();
251 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
253 - // printf("GetWidth %d\n", aWidth);
257 - g_object_unref(layout);
265 -nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
266 +nsFontMetricsPango::GetTextDimensions(const char* aString,
268 - nsTextDimensions& aDimensions,
270 - nsRenderingContextGTK *aContext)
271 + nsTextDimensions& aDimensions
274 - nsresult rv = NS_OK;
276 - PangoLayout *layout = pango_layout_new(mPangoContext);
277 + PangoLayout *layout = GetLayout(aString, aLength);
278 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
280 - gchar *text = g_utf16_to_utf8(aString, aLength,
285 - NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
286 - DUMP_PRUNICHAR(aString, aLength)
288 - aDimensions.width = 0;
289 - aDimensions.ascent = 0;
290 - aDimensions.descent = 0;
292 - rv = NS_ERROR_FAILURE;
296 + PangoRectangle logical;
297 + pango_layout_line_get_extents(line, NULL, &logical);
298 + g_object_unref(layout);
300 - pango_layout_set_text(layout, text, strlen(text));
301 - FixupSpaceWidths(layout, text);
302 + float P2T = mDeviceContext->DevUnitsToAppUnits();
304 - // Get the logical extents
305 - PangoLayoutLine *line;
306 - if (pango_layout_get_line_count(layout) != 1) {
307 - printf("Warning: more than one line!\n");
309 - line = pango_layout_get_line(layout, 0);
310 + aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE);
311 + aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
312 + aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
314 - PangoRectangle rect;
315 - pango_layout_line_get_extents(line, NULL, &rect);
320 - P2T = mDeviceContext->DevUnitsToAppUnits();
322 +nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
324 + nsTextDimensions& aDimensions,
328 + PangoLayout *layout = GetLayout(aString, aLength);
329 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
331 - aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
332 - aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
333 - aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
334 + PangoRectangle logical;
335 + pango_layout_line_get_extents(line, NULL, &logical);
336 + g_object_unref(layout);
338 - // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
339 - //aDimensions.ascent, aDimensions.descent);
340 + float P2T = mDeviceContext->DevUnitsToAppUnits();
344 - g_object_unref(layout);
345 + aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(logical) * P2T / PANGO_SCALE);
346 + aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
347 + aDimensions.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
354 @@ -595,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co
355 nsTextDimensions& aDimensions,
356 PRInt32& aNumCharsFit,
357 nsTextDimensions& aLastWordDimensions,
359 - nsRenderingContextGTK *aContext)
364 return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
365 aNumBreaks, aDimensions, aNumCharsFit,
366 - aLastWordDimensions, aContext);
367 + aLastWordDimensions CONTEXT_ARG_PASS);
371 @@ -614,8 +645,8 @@ nsFontMetricsPango::GetTextDimensions(co
372 nsTextDimensions& aDimensions,
373 PRInt32& aNumCharsFit,
374 nsTextDimensions& aLastWordDimensions,
376 - nsRenderingContextGTK *aContext)
381 PRInt32 curBreak = 0;
382 @@ -623,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co
384 PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
386 - gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
390 + utf16_to_utf8 (aString, aLength, text, text_len);
396 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
397 - DUMP_PRUNICHAR(aString, (PRUint32)aLength)
399 - rv = NS_ERROR_FAILURE;
403 // Covert the utf16 break offsets to utf8 break offsets
404 for (PRInt32 curOffset=0; curOffset < aLength;
405 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
406 + curOffset++, curChar = g_utf8_next_char(curChar)) {
407 if (aBreaks[curBreak] == curOffset) {
408 utf8Breaks[curBreak] = curChar - text;
410 @@ -653,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co
411 utf8Breaks[curBreak] = curChar - text;
414 - if (strlen(text) != aLength) {
415 - printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
416 + if (text_len != aLength) {
417 + printf("Different lengths for utf16 %d and utf8 %d\n", aLength, text_len);
418 DUMP_PRUNICHAR(aString, aLength)
419 - DUMP_PRUNICHAR(text, strlen(text))
420 + DUMP_PRUNICHAR(text, text_len)
421 for (PRInt32 i = 0; i < aNumBreaks; ++i) {
422 printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
424 @@ -666,9 +689,9 @@ nsFontMetricsPango::GetTextDimensions(co
425 // We'll use curBreak to indicate which of the breaks end up being
426 // used for the break point for this line.
428 - rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
429 + rv = GetTextDimensionsInternal(text, text_len, aAvailWidth, utf8Breaks,
430 aNumBreaks, aDimensions, aNumCharsFit,
431 - aLastWordDimensions, aContext);
432 + aLastWordDimensions CONTEXT_ARG_PASS);
434 // Figure out which of the breaks we ended up using to convert
435 // back to utf16 - start from the end.
436 @@ -681,200 +704,365 @@ nsFontMetricsPango::GetTextDimensions(co
451 -nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
452 - nscoord aX, nscoord aY,
453 - const nscoord* aSpacing,
454 - nsRenderingContextGTK *aContext,
455 - nsDrawingSurfaceGTK *aSurface)
458 +typedef struct _nsPSPangoRenderer nsPSPangoRenderer;
459 +typedef struct _nsPSPangoRendererClass nsPSPangoRendererClass;
461 +struct _nsPSPangoRenderer
463 - PangoLayout *layout = pango_layout_new(mPangoContext);
464 + PangoRenderer parent_instance;
465 + nsRenderingContextPS *psContext;
466 + nsFontMetricsPSPango *psPangoFontMetrics;
470 - pango_layout_set_text(layout, aString, aLength);
471 - FixupSpaceWidths(layout, aString);
472 +struct _nsPSPangoRendererClass
474 + PangoRendererClass parent_class;
479 +#define _PS_TYPE_PANGO_RENDERER (_ps_pango_renderer_get_type())
480 +#define _PS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
481 +#define _PS_IS_PANGO_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
482 +#define _PS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
483 +#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
484 +#define _PS_PANGO_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
486 - aContext->GetTranMatrix()->TransformCoord(&x, &y);
487 +G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
489 - PangoLayoutLine *line;
490 - if (pango_layout_get_line_count(layout) != 1) {
491 - printf("Warning: more than one line!\n");
493 - line = pango_layout_get_line(layout, 0);
494 +static PangoRenderer *
497 + static PangoRenderer *renderer = NULL;
499 - aContext->UpdateGC();
500 - GdkGC *gc = aContext->GetGC();
502 + renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
504 - if (aSpacing && *aSpacing) {
505 - DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
506 - gc, x, y, line, aSpacing);
509 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
516 - g_object_unref(gc);
517 - g_object_unref(layout);
519 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
521 + PangoGlyphString *glyphs,
525 - // printf("DrawString (char *)\n");
527 +_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
529 + PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
531 + renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
536 +_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
540 +class nsPangoType1Generator : public nsPSFontGenerator {
542 + nsPangoType1Generator();
543 + ~nsPangoType1Generator();
544 + nsresult Init(PangoFont *aFont);
545 + void GeneratePSFont(FILE* aFile);
551 +nsPangoType1Generator::nsPangoType1Generator()
556 -nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
557 - nscoord aX, nscoord aY,
559 - const nscoord* aSpacing,
560 - nsRenderingContextGTK *aContext,
561 - nsDrawingSurfaceGTK *aSurface)
562 +nsPangoType1Generator::Init(PangoFont *aFont)
564 + NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
566 + g_object_ref (mFont);
570 +nsPangoType1Generator::~nsPangoType1Generator()
572 - nsresult rv = NS_OK;
575 + g_object_unref (mFont);
579 - aContext->UpdateGC();
580 - GdkGC *gc = aContext->GetGC();
581 +void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
583 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
585 - PangoLayout *layout = pango_layout_new(mPangoContext);
586 + if (face == nsnull)
589 - gchar *text = g_utf16_to_utf8(aString, aLength,
592 + if (mGlyphSubset->Count())
593 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
597 - NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
598 - DUMP_PRUNICHAR(aString, aLength)
600 - rv = NS_ERROR_FAILURE;
603 + pango_fc_font_unlock_face ((PangoFcFont *) mFont);
606 - pango_layout_set_text(layout, text, strlen(text));
607 - FixupSpaceWidths(layout, text);
610 + nsCString *FontNameBase;
615 - aContext->GetTranMatrix()->TransformCoord(&x, &y);
617 +ps_pango_font_data_destroy (PSPangoFontData *data)
620 + delete data->FontNameBase;
624 - PangoLayoutLine *line;
625 - if (pango_layout_get_line_count(layout) != 1) {
626 - printf("Warning: more than one line!\n");
628 - line = pango_layout_get_line(layout, 0);
630 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
632 + PangoGlyphString *glyphs,
636 + if (!glyphs->num_glyphs)
639 - if (aSpacing && *aSpacing) {
640 - DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
641 - gc, x, y, line, aSpacing);
644 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
648 + static GQuark data_quark = 0;
650 + data_quark = g_quark_from_static_string ("ps-pango-font-data");
653 + PSPangoFontData *data;
654 + if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
656 + data = g_new (PSPangoFontData, 1);
659 - g_object_unref(gc);
660 - g_object_unref(layout);
661 + FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
662 + if (face == nsnull)
665 + data->FontNameBase = new nsCString ();
666 + if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
668 + pango_fc_font_unlock_face ((PangoFcFont *) font);
671 + pango_fc_font_unlock_face ((PangoFcFont *) font);
673 - // printf("DrawString\n");
674 + PangoFontDescription *desc = pango_font_describe (font);
675 + data->font_size = pango_font_description_get_size (desc);
676 + pango_font_description_free (desc);
678 + data->key = new nsCStringKey (*data->FontNameBase);
680 + g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
683 + nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
684 + nsRenderingContextPS *aContext = ps_renderer->psContext;
685 + nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
686 + nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
687 + nsPostScriptObj* psObj = aContext->GetPostScriptObj();
688 + nsHashtable *psFGList = dc->GetPSFontGeneratorList();
689 + g_return_if_fail (psFGList);
690 + nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
693 + psFontGen = new nsPangoType1Generator;
694 + g_return_if_fail (psFontGen);
695 + rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
696 + if (NS_FAILED(rv)) {
700 + psFGList->Put(data->key, (void *) psFontGen);
702 + nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
704 + g_return_if_fail (aContext);
705 + g_return_if_fail (psObj);
707 + nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
708 + nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
709 + psObj->moveto(aX, aY);
711 + PRInt32 currSubFont, prevSubFont = -1;
713 + PangoGlyphString gl;
715 + gl.glyphs = glyphs->glyphs;
717 + currSubFont = prevSubFont;
718 + for (i = 0; i < glyphs->num_glyphs; ++i) {
719 + PangoGlyph glyph = glyphs->glyphs[i].glyph;
721 + if (glyph != PANGO_GLYPH_EMPTY)
722 + currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph);
724 + if (prevSubFont != currSubFont) {
725 + if (prevSubFont != -1)
726 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
728 + psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
729 + prevSubFont = currSubFont;
730 + gl.glyphs = glyphs->glyphs + i;
738 + if (prevSubFont != -1)
739 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
744 +draw_layout_line (int x, int y,
745 + PangoLayoutLine *line,
746 + nsFontMetricsPango *fm
747 + CONTEXT_AND_SURFACE_ARG_DEF)
750 + PangoRenderer *renderer = get_renderer ();
751 + nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
752 + ps_renderer->psContext = aContext;
753 + ps_renderer->psPangoFontMetrics = fm;
754 + nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, fm->GetDeviceContext());
755 + ps_renderer->zoom = dc->DevUnitsToAppUnits();
757 + pango_renderer_draw_layout_line (renderer, line,
758 + NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
759 + NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
761 + aContext->UpdateGC();
762 + GdkGC *gc = aContext->GetGC();
763 + gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line);
764 + g_object_unref(gc);
771 -nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
772 - nsBoundingMetrics &aBoundingMetrics,
773 - nsRenderingContextGTK *aContext)
774 +nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
775 + nscoord aX, nscoord aY,
776 + const nscoord* aSpacing
777 + CONTEXT_AND_SURFACE_ARG_DEF)
779 - printf("GetBoundingMetrics (char *)\n");
780 - return NS_ERROR_FAILURE;
784 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
786 + PangoLayout *layout = GetLayout(aString, aLength);
787 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
789 + ApplySpacing(aString, aLength, line, aSpacing);
790 + draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
792 + g_object_unref(layout);
798 -nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
800 - nsBoundingMetrics &aBoundingMetrics,
802 - nsRenderingContextGTK *aContext)
803 +nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
804 + nscoord aX, nscoord aY,
806 + const nscoord* aSpacing
807 + CONTEXT_AND_SURFACE_ARG_DEF)
809 - nsresult rv = NS_OK;
810 - PangoLayout *layout = pango_layout_new(mPangoContext);
814 - gchar *text = g_utf16_to_utf8(aString, aLength,
816 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
820 - NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
821 - DUMP_PRUNICHAR(aString, aLength)
823 - aBoundingMetrics.Clear();
824 + PangoLayout *layout = GetLayout(aString, aLength);
825 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
827 - rv = NS_ERROR_FAILURE;
830 + ApplySpacing(aString, aLength, line, aSpacing);
831 + draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
833 - pango_layout_set_text(layout, text, -1);
834 - FixupSpaceWidths(layout, text);
835 + g_object_unref(layout);
840 - PangoLayoutLine *line;
841 - if (pango_layout_get_line_count(layout) != 1) {
842 - printf("Warning: more than one line!\n");
844 - line = pango_layout_get_line(layout, 0);
848 +nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
849 + nsBoundingMetrics &aBoundingMetrics
852 + PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
854 // Get the ink and logical extents
855 PangoRectangle ink, logical;
856 pango_layout_line_get_extents(line, &ink, &logical);
859 - P2T = mDeviceContext->DevUnitsToAppUnits();
860 + float P2T = mDeviceContext->DevUnitsToAppUnits();
862 aBoundingMetrics.leftBearing = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
863 aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
864 aBoundingMetrics.ascent = NSToCoordRound(PANGO_ASCENT(ink) * P2T / PANGO_SCALE);
865 aBoundingMetrics.descent = NSToCoordRound(PANGO_DESCENT(ink) * P2T / PANGO_SCALE);
866 aBoundingMetrics.width = NSToCoordRound(logical.width * P2T / PANGO_SCALE);
872 +nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
873 + nsBoundingMetrics &aBoundingMetrics
876 + PangoLayout *layout = GetLayout(aString, aLength);
877 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
878 g_object_unref(layout);
885 +nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
887 + nsBoundingMetrics &aBoundingMetrics,
891 + PangoLayout *layout = GetLayout(aString, aLength);
892 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
893 + g_object_unref(layout);
898 #endif /* MOZ_MATHML */
902 nsFontMetricsPango::GetCurrentGDKFont(void)
909 nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
912 if (!mRTLPangoContext) {
913 - mRTLPangoContext = gdk_pango_context_get();
914 + mRTLPangoContext = get_context();
915 pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
917 - gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
918 pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
919 pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
921 @@ -899,34 +1087,18 @@ nsFontMetricsPango::GetClusterInfo(const
923 PRUint8 *aClusterStarts)
925 - nsresult rv = NS_OK;
926 PangoLogAttr *attrs = NULL;
928 - PangoLayout *layout = pango_layout_new(mPangoContext);
930 - // Convert the incoming UTF-16 to UTF-8
931 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
935 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
936 - DUMP_PRUNICHAR(aText, aLength)
938 - rv = NS_ERROR_FAILURE;
942 - // Set up the pango layout
943 - pango_layout_set_text(layout, text, strlen(text));
944 - FixupSpaceWidths(layout, text);
945 + PangoLayout *layout = GetLayout(aText, aLength);
946 + pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
947 + g_object_unref(layout);
949 // Convert back to UTF-16 while filling in the cluster info
951 - pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
953 for (PRUint32 pos = 0; pos < aLength; pos++) {
954 if (IS_HIGH_SURROGATE(aText[pos])) {
955 - aClusterStarts[pos] = 1;
956 + aClusterStarts[pos] = 1;//FIXME: shouldn't this be zero?! --be
960 @@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
970 - g_object_unref(layout);
978 -nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
980 +nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
984 - const gchar *curChar;
987 float f = mDeviceContext->AppUnitsToDevUnits();
989 - PangoLayout *layout = pango_layout_new(mPangoContext);
990 PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
991 PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
993 - // Convert the incoming UTF-16 to UTF-8
994 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
998 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
999 - DUMP_PRUNICHAR(aText, aLength)
1005 - // Set up the pango layout
1006 - pango_layout_set_text(layout, text, strlen(text));
1007 - FixupSpaceWidths(layout, text);
1008 + PangoLayout *layout = GetLayout(aText, aLength);
1010 pango_layout_xy_to_index(layout, localX, localY,
1013 // Convert the index back to the utf-16 index
1015 + const gchar *text = pango_layout_get_text (layout);
1016 + const gchar *curChar = text;
1018 for (PRUint32 curOffset=0; curOffset < aLength;
1019 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1020 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1022 // Check for a match before checking for a surrogate pair
1023 if (curChar - text == inx) {
1024 @@ -1006,13 +1156,9 @@ nsFontMetricsPango::GetPosition(const PR
1032 - g_object_unref(layout);
1033 + g_object_unref(layout);
1040 @@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const
1044 - nsresult rv = NS_OK;
1045 PRUint32 utf8Start = 0;
1046 PRUint32 utf8End = 0;
1050 // Convert the incoming UTF-16 to UTF-8
1051 - gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
1052 - gchar *curChar = text;
1056 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1057 - DUMP_PRUNICHAR(aText, aLength)
1059 - rv = NS_ERROR_FAILURE;
1064 + utf16_to_utf8 (aText, aLength, text, text_len);
1065 + gchar *curChar = text;
1067 // Convert the utf16 offsets into utf8 offsets
1068 for (PRUint32 curOffset = 0; curOffset < aLength;
1069 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1070 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1072 if (curOffset == aStart)
1073 utf8Start = curChar - text;
1074 @@ -1057,15 +1196,13 @@ nsFontMetricsPango::GetRangeWidth(const
1076 // Special case where the end index is the same as the length
1077 if (aLength == aEnd)
1078 - utf8End = strlen(text);
1079 + utf8End = text_len;
1081 - rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
1082 + GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth);
1094 @@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const
1098 - nsresult rv = NS_OK;
1105 - PangoLayout *layout = pango_layout_new(mPangoContext);
1108 - rv = NS_ERROR_FAILURE;
1112 - pango_layout_set_text(layout, aText, aLength);
1113 - FixupSpaceWidths(layout, aText);
1115 - PangoLayoutLine *line;
1116 - if (pango_layout_get_line_count(layout) != 1) {
1117 - printf("Warning: more than one line!\n");
1119 - line = pango_layout_get_line(layout, 0);
1120 + PangoLayout *layout = GetLayout(aText, aLength);
1121 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
1123 pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
1125 aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
1127 f = mDeviceContext-> DevUnitsToAppUnits();
1128 - aWidth = nscoord(aWidth * f / PANGO_SCALE);
1129 + aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE);
1135 - g_object_unref(layout);
1137 + g_object_unref(layout);
1144 @@ -1134,7 +1254,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi
1145 NS_ConvertUTF16toUTF8 name(aName);
1147 nsresult rv = NS_ERROR_FAILURE;
1148 - PangoContext *context = gdk_pango_context_get();
1149 + PangoContext *context = get_context();
1150 PangoFontFamily **familyList;
1153 @@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
1155 // Now that we have the font description set up, create the
1157 - mLTRPangoContext = gdk_pango_context_get();
1158 + mLTRPangoContext = get_context();
1159 mPangoContext = mLTRPangoContext;
1161 // Make sure to set the base direction to LTR - if layout needs to
1162 // render RTL text it will use ::SetRightToLeftText()
1163 pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
1165 - // Set the color map so we can draw later.
1166 - gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
1168 // Set the pango language now that we have a context
1169 pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
1171 @@ -1280,79 +1397,268 @@ nsFontMetricsPango::EnumFontCallback(con
1172 * This is only used when there's per-character spacing happening.
1173 * Well, really it can be either line or character spacing but it's
1174 * just turtles all the way down!
1176 + * To do it correctly (ligatures, etc) we need machinery that is private
1177 + * in Pango. IMPORT IT:
1180 +#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter
1181 +#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter
1183 +#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
1185 +/* Structure holding state when we're iterating over a GlyphItem.
1186 + * start_index/cluster_end (and range_start/range_end in
1187 + * apply_attrs()) are offsets into the text, so note the difference
1188 + * of glyph_item->item->offset between them and clusters in the
1189 + * log_clusters[] array.
1191 +typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
1193 +struct _PangoGlyphItemIter
1195 + PangoGlyphItem *glyph_item;
1196 + const gchar *text;
1208 + * _pango_glyph_item_iter_next_cluster:
1209 + * @iter: a #PangoGlyphItemIter
1211 + * Advances the iterator to the next cluster in the glyph item.
1213 + * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
1217 +_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
1219 + int glyph_index = iter->end_glyph;
1220 + PangoGlyphString *glyphs = iter->glyph_item->glyphs;
1221 + PangoItem *item = iter->glyph_item->item;
1223 + if (LTR (iter->glyph_item))
1225 + if (glyph_index == glyphs->num_glyphs)
1230 + if (glyph_index < 0)
1234 + iter->start_glyph = iter->end_glyph;
1235 + iter->start_index = iter->end_index;
1236 + iter->start_char = iter->end_char;
1238 + if (LTR (iter->glyph_item))
1244 + if (glyph_index == glyphs->num_glyphs)
1246 + iter->end_index = item->offset + item->length;
1247 + iter->end_char = item->num_chars;
1251 + if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1253 + iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
1254 + iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
1255 + iter->end_index - iter->start_index);
1266 + if (glyph_index < 0)
1268 + iter->end_index = item->offset + item->length;
1269 + iter->end_char = item->num_chars;
1273 + if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1275 + iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
1276 + iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
1277 + iter->end_index - iter->start_index);
1283 + iter->end_glyph = glyph_index;
1288 + * _pango_glyph_item_iter_init_start:
1289 + * @iter: pointer to a #PangoGlyphItemIter structure
1290 + * @glyph_item: the glyph item that the iter points into
1291 + * @text: text corresponding to the glyph item
1293 + * Initializes a #PangoGlyphItemIter structure to point to the
1294 + * first cluster in a glyph item.
1296 + * Return value: %FALSE if there are no clusters in the glyph item;
1297 + * in this case, the state of the iter is undefined.
1300 +_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter,
1301 + PangoGlyphItem *glyph_item,
1304 + iter->glyph_item = glyph_item;
1305 + iter->text = text;
1307 + if (LTR (glyph_item))
1308 + iter->end_glyph = 0;
1310 + iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
1312 + iter->end_index = glyph_item->item->offset;
1313 + iter->end_char = 0;
1315 + /* Advance onto the first cluster of the glyph item */
1316 + return _pango_glyph_item_iter_next_cluster (iter);
1321 -nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
1322 - const PRUnichar *aOrigString,
1324 - GdkDrawable *aDrawable,
1325 - GdkGC *aGC, gint aX, gint aY,
1326 - PangoLayoutLine *aLine,
1327 - const nscoord *aSpacing)
1330 - app2dev = mDeviceContext->AppUnitsToDevUnits();
1332 +nsFontMetricsPango::ApplySpacing(const gchar *aText,
1334 + PangoLayoutLine *aLine,
1335 + const nscoord *aSpacing)
1337 + if (!(aSpacing && *aSpacing))
1340 + float app2dev = mDeviceContext->AppUnitsToDevUnits();
1343 * We walk the list of glyphs returned in each layout run,
1344 * matching up the glyphs with the characters in the source text.
1345 * We use the aSpacing argument to figure out where to place those
1346 - * glyphs. It's important to note that since the string we're
1347 - * working with is in UTF-8 while the spacing argument assumes
1348 - * that offset will be part of the UTF-16 string. Logical
1349 - * attributes in pango are in byte offsets in the UTF-8 string, so
1350 - * we need to store the offsets based on the UTF-8 string.
1353 - nscoord *utf8spacing = new nscoord[strlen(aText)];
1354 + for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
1355 + tmpList = tmpList->next) {
1356 + PangoGlyphItem *glyph_item = (PangoGlyphItem *)tmpList->data;
1357 + PangoGlyphItemIter iter;
1358 + gboolean have_cluster;
1359 + PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs;
1360 + int residualWidth = 0;
1362 + for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, aText);
1364 + have_cluster = _pango_glyph_item_iter_next_cluster (&iter))
1366 + int clusterOldWidth = 0;
1367 + int clusterNewWidth = 0;
1368 + int dir = iter.start_glyph < iter.end_glyph ? +1 : -1;
1369 + gboolean has_zero_width = FALSE;
1371 + for (const char *p = iter.text + iter.start_index;
1372 + p < iter.text + iter.end_index;
1373 + p = g_utf8_next_char (p))
1374 + clusterNewWidth += aSpacing[p - iter.text];
1376 + clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE);
1378 + for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) {
1379 + if (!glyphs[i].geometry.width)
1380 + has_zero_width = TRUE;
1381 + clusterOldWidth += glyphs[i].geometry.width;
1384 + /* if a zero-width glyph exists, don't touch the glyph widths.
1385 + * required for combining marks. ff thinks they have a width.
1386 + * instead, we charge the difference to the next space glyph. */
1387 + if (has_zero_width) {
1388 + residualWidth += clusterNewWidth - clusterOldWidth;
1392 - if (aOrigString) {
1393 - const gchar *curChar = aText;
1394 - bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
1396 - // Covert the utf16 spacing offsets to utf8 spacing offsets
1397 - for (PRUint32 curOffset=0; curOffset < aLength;
1398 - curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1399 - utf8spacing[curChar - aText] = aSpacing[curOffset];
1400 + /* If a space glyph is found, charge it whatever residual we
1401 + * have accumulated so far. */
1402 + if (iter.end_index - iter.start_index == 1 &&
1403 + *(iter.text + iter.start_index) == ' ') {
1404 + clusterNewWidth += residualWidth;
1405 + residualWidth = 0;
1409 + /* do some hinting for display */
1411 + if (clusterOldWidth % PANGO_SCALE == 0 && clusterNewWidth % PANGO_SCALE != 0) {
1412 + int tmp = clusterNewWidth;
1413 + clusterNewWidth = PANGO_PIXELS (clusterNewWidth) * PANGO_SCALE;
1414 + residualWidth += tmp - clusterNewWidth;
1418 - if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
1420 + /* find the first non-zero-width glyph and adjust its width */
1421 + for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir)
1422 + if (glyphs[i].geometry.width) {
1423 + glyphs[i].geometry.width += clusterNewWidth - clusterOldWidth;
1429 - memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
1435 +nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
1437 + PangoLayoutLine *aLine,
1438 + const nscoord *aSpacing)
1440 + if (!(aSpacing && *aSpacing))
1443 - for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
1444 - tmpList = tmpList->next, curRun++) {
1445 - PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
1446 - gint tmpOffset = 0;
1447 + const char *utf8Text = pango_layout_get_text (aLine->layout);
1448 + int utf8Text_len = aLine->start_index + aLine->length;
1450 - /* printf(" Rendering run %d: \"%s\"\n", curRun,
1451 - &aText[layoutRun->item->offset]); */
1452 + /* Since the string we're
1453 + * working with is in UTF-8 while the spacing argument assumes
1454 + * that offset will be part of the UTF-16 string. Logical
1455 + * attributes in pango are in byte offsets in the UTF-8 string, so
1456 + * we need to store the offsets based on the UTF-8 string.
1458 + nscoord *utf8spacing = g_new0 (nscoord, utf8Text_len);
1460 - for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
1461 - /* printf("glyph %d offset %d orig width %d new width %d\n", i,
1462 - * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
1463 - * layoutRun->glyphs->glyphs[i].geometry.width,
1464 - * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
1466 - gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
1467 - * app2dev * PANGO_SCALE);
1468 - layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
1469 - tmpOffset += thisOffset;
1471 + const gchar *curChar = utf8Text + aLine->start_index;
1473 - /* printf(" rendering at X coord %d\n", aX + offset); */
1474 - offset += tmpOffset;
1475 + // Covert the utf16 spacing offsets to utf8 spacing offsets
1476 + for (PRUint32 curOffset=0; curOffset < aLength;
1477 + curOffset++, curChar = g_utf8_next_char(curChar)) {
1478 + utf8spacing[curChar - utf8Text] = aSpacing[curOffset];
1480 + if (IS_HIGH_SURROGATE(aText[curOffset]))
1484 - gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
1485 + ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing);
1487 - delete[] utf8spacing;
1488 + g_free (utf8spacing);
1492 @@ -1363,8 +1669,8 @@ nsFontMetricsPango::GetTextDimensionsInt
1494 nsTextDimensions& aDimensions,
1495 PRInt32& aNumCharsFit,
1496 - nsTextDimensions& aLastWordDimensions,
1497 - nsRenderingContextGTK *aContext)
1498 + nsTextDimensions& aLastWordDimensions
1501 NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
1503 @@ -1410,7 +1716,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1504 // All the characters should fit
1505 numChars = aLength - start;
1506 breakIndex = aNumBreaks - 1;
1510 breakIndex = prevBreakState_BreakIndex;
1511 while (((breakIndex + 1) < aNumBreaks) &&
1512 @@ -1431,7 +1737,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1513 if ((1 == numChars) && (aString[start] == ' '))
1514 GetSpaceWidth(twWidth);
1515 else if (numChars > 0)
1516 - GetWidth(&aString[start], numChars, twWidth, aContext);
1517 + GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
1519 // See if the text fits
1520 PRBool textFits = (twWidth + width) <= aAvailWidth;
1521 @@ -1481,8 +1787,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1522 if ((1 == numChars) && (aString[start] == ' '))
1523 GetSpaceWidth(twWidth);
1524 else if (numChars > 0)
1525 - GetWidth(&aString[start], numChars, twWidth,
1527 + GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
1529 aNumCharsFit = start;
1531 @@ -1504,9 +1809,16 @@ nsFontMetricsPango::GetTextDimensionsInt
1535 -nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
1536 - const char *aString)
1537 +nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
1539 + if (!mPangoSpaceWidth)
1542 + const char *aString = pango_layout_get_text (aLayout);
1544 + if (pango_layout_get_line_count(aLayout) != 1) {
1545 + printf("Warning: more than one line!\n");
1547 PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
1550 @@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
1555 +nsFontMetricsPango::GetLayout (const PRUnichar* aText,
1560 + utf16_to_utf8 (aText, aLength, text, length);
1562 + PangoLayout *layout = pango_layout_new(mPangoContext);
1563 + pango_layout_set_text (layout, text, length);
1564 + FixupSpaceWidths (layout);
1566 + g_free ((gpointer) text);
1572 +nsFontMetricsPango::GetLayout (const gchar* aText,
1575 + gboolean has_nul = FALSE;
1578 + for (i = 0; i < aLength; i++)
1585 + /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
1587 + char *p = (char *) g_memdup (aText, aLength);
1589 + /* don't need to reset i */
1590 + for (; i < aLength; i++)
1592 + p[i] = (char) 0xff;
1597 + PangoLayout *layout = pango_layout_new(mPangoContext);
1598 + pango_layout_set_text (layout, aText, aLength);
1599 + FixupSpaceWidths (layout);
1602 + g_free ((gpointer) aText);
1608 +utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
1610 + gboolean need_copy = FALSE;
1613 + for (i = 0; i < aLength; i++) {
1614 + if (!aText[i] || IS_LOW_SURROGATE (aText[i]))
1616 + else if (IS_HIGH_SURROGATE (aText[i])) {
1617 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1626 + /* Pango doesn't correctly handle nuls. We convert them to 0xff. */
1627 + /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
1629 + PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0]));
1631 + /* don't need to reset i */
1632 + for (i = 0; i < aLength; i++) {
1633 + if (!p[i] || IS_LOW_SURROGATE (p[i]))
1635 + else if (IS_HIGH_SURROGATE (p[i])) {
1636 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1646 + glong items_written;
1647 + text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
1648 + length = items_written;
1651 + g_free ((gpointer) aText);
1657 GetPangoLanguage(nsIAtom *aLangGroup)
1658 --- mozilla.back/gfx/src/gtk/nsFontMetricsPango.h.orig 2006-06-30 01:18:34.000000000 +0200
1659 +++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.h 2007-06-28 15:16:39.000000000 +0200
1662 * ***** END LICENSE BLOCK ***** */
1665 #include "nsIFontMetrics.h"
1666 #include "nsIFontEnumerator.h"
1668 #include "nsIAtom.h"
1669 #include "nsString.h"
1670 #include "nsVoidArray.h"
1673 +#include "nsFontMetricsPS.h"
1675 #include "nsIFontMetricsGTK.h"
1678 #include <pango/pango.h>
1680 -class nsFontMetricsPango : public nsIFontMetricsGTK
1683 +#define CONTEXT_ARG_DEF
1684 +#define CONTEXT_ARG_PASS
1685 +#define CONTEXT_ARG_NULL
1686 +#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextPS *aContext
1687 +#define CONTEXT_AND_SURFACE_ARG_PASS , aContext
1691 +#define CONTEXT_ARG_DEF , nsRenderingContextGTK *aContext
1692 +#define CONTEXT_ARG_PASS , aContext
1693 +#define CONTEXT_ARG_NULL , NULL
1694 +#define CONTEXT_AND_SURFACE_ARG_DEF , nsRenderingContextGTK *aContext, nsDrawingSurfaceGTK *aSurface
1695 +#define CONTEXT_AND_SURFACE_ARG_PASS , aContext, aSurface
1702 +#define nsFontMetricsPango nsFontMetricsPSPango
1703 +#define PSPANGO_PARENT_CLASS nsFontMetricsPS
1707 +#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
1711 +class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
1714 nsFontMetricsPango();
1715 @@ -136,20 +172,30 @@ public:
1717 PRInt32 GetMaxStringLength() { return mMaxStringLength; }
1719 - // nsIFontMetricsGTK (calls from the font rendering layer)
1720 - virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
1722 - nsRenderingContextGTK *aContext);
1723 - virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
1724 - nscoord& aWidth, PRInt32 *aFontID,
1725 - nsRenderingContextGTK *aContext);
1726 + // nsIFontMetrics (calls from the font rendering layer)
1728 - virtual nsresult GetTextDimensions(const PRUnichar* aString,
1730 + NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
1731 + NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
1734 + NS_METHOD GetWidth(const char* aString, PRUint32 aLength,
1737 + NS_METHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
1738 + nscoord& aWidth, PRInt32 *aFontID
1741 + NS_METHOD GetTextDimensions(const char* aString,
1743 + nsTextDimensions& aDimensions
1745 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1747 nsTextDimensions& aDimensions,
1749 - nsRenderingContextGTK *aContext);
1750 - virtual nsresult GetTextDimensions(const char* aString,
1753 + NS_METHOD GetTextDimensions(const char* aString,
1755 PRInt32 aAvailWidth,
1757 @@ -157,9 +203,9 @@ public:
1758 nsTextDimensions& aDimensions,
1759 PRInt32& aNumCharsFit,
1760 nsTextDimensions& aLastWordDimensions,
1762 - nsRenderingContextGTK *aContext);
1763 - virtual nsresult GetTextDimensions(const PRUnichar* aString,
1766 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1768 PRInt32 aAvailWidth,
1770 @@ -167,38 +213,37 @@ public:
1771 nsTextDimensions& aDimensions,
1772 PRInt32& aNumCharsFit,
1773 nsTextDimensions& aLastWordDimensions,
1775 - nsRenderingContextGTK *aContext);
1779 - virtual nsresult DrawString(const char *aString, PRUint32 aLength,
1780 + NS_METHOD DrawString(const char *aString, PRUint32 aLength,
1781 nscoord aX, nscoord aY,
1782 - const nscoord* aSpacing,
1783 - nsRenderingContextGTK *aContext,
1784 - nsDrawingSurfaceGTK *aSurface);
1785 - virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
1786 + const nscoord* aSpacing
1787 + CONTEXT_AND_SURFACE_ARG_DEF);
1789 + NS_METHOD DrawString(const PRUnichar* aString, PRUint32 aLength,
1790 nscoord aX, nscoord aY,
1792 - const nscoord* aSpacing,
1793 - nsRenderingContextGTK *aContext,
1794 - nsDrawingSurfaceGTK *aSurface);
1795 + const nscoord* aSpacing
1796 + CONTEXT_AND_SURFACE_ARG_DEF);
1799 - virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
1800 - nsBoundingMetrics &aBoundingMetrics,
1801 - nsRenderingContextGTK *aContext);
1802 - virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
1803 + NS_METHOD GetBoundingMetrics(const char *aString, PRUint32 aLength,
1804 + nsBoundingMetrics &aBoundingMetrics
1806 + NS_METHOD GetBoundingMetrics(const PRUnichar *aString,
1808 nsBoundingMetrics &aBoundingMetrics,
1810 - nsRenderingContextGTK *aContext);
1813 #endif /* MOZ_MATHML */
1816 virtual GdkFont* GetCurrentGDKFont(void);
1818 - virtual nsresult SetRightToLeftText(PRBool aIsRTL);
1820 virtual PRBool GetRightToLeftText();
1822 - virtual nsresult GetClusterInfo(const PRUnichar *aText,
1823 + NS_METHOD SetRightToLeftText(PRBool aIsRTL);
1825 + NS_METHOD GetClusterInfo(const PRUnichar *aText,
1827 PRUint8 *aClusterStarts);
1829 @@ -206,32 +251,35 @@ public:
1833 - virtual nsresult GetRangeWidth(const PRUnichar *aText,
1834 + NS_METHOD GetRangeWidth(const PRUnichar *aText,
1840 - virtual nsresult GetRangeWidth(const char *aText,
1841 + NS_METHOD GetRangeWidth(const char *aText,
1847 // get hints for the font
1848 - static PRUint32 GetHints (void);
1852 + PRUint32 GetHints (void);
1854 // drawing surface methods
1855 static nsresult FamilyExists (nsIDeviceContext *aDevice,
1856 const nsString &aName);
1861 // generic font metrics class bits
1862 nsCStringArray mFontList;
1863 nsAutoVoidArray mFontIsGeneric;
1865 - nsIDeviceContext *mDeviceContext;
1866 nsCOMPtr<nsIAtom> mLangGroup;
1867 nsCString *mGenericFont;
1869 @@ -246,6 +294,9 @@ private:
1870 PangoAttrList *mPangoAttrList;
1874 + nsIDeviceContext *mDeviceContext;
1876 // Cached font metrics
1878 nscoord mSuperscriptOffset;
1879 @@ -263,6 +314,7 @@ private:
1880 nscoord mMaxDescent;
1881 nscoord mMaxAdvance;
1882 nscoord mSpaceWidth;
1884 nscoord mPangoSpaceWidth;
1885 nscoord mAveCharWidth;
1886 PRInt32 mMaxStringLength;
1887 @@ -274,13 +326,14 @@ private:
1888 static PRBool EnumFontCallback(const nsString &aFamily,
1889 PRBool aIsGeneric, void *aData);
1891 - void DrawStringSlowly(const gchar *aText,
1892 - const PRUnichar *aOrigString,
1894 - GdkDrawable *aDrawable,
1895 - GdkGC *aGC, gint aX, gint aY,
1896 - PangoLayoutLine *aLine,
1897 - const nscoord *aSpacing);
1898 + void ApplySpacing(const gchar *aText,
1900 + PangoLayoutLine *aLine,
1901 + const nscoord *aSpacing);
1902 + void ApplySpacing(const PRUnichar *aText,
1904 + PangoLayoutLine *aLine,
1905 + const nscoord *aSpacing);
1907 nsresult GetTextDimensionsInternal(const gchar* aString,
1909 @@ -289,10 +342,20 @@ private:
1911 nsTextDimensions& aDimensions,
1912 PRInt32& aNumCharsFit,
1913 - nsTextDimensions& aLastWordDimensions,
1914 - nsRenderingContextGTK *aContext);
1915 + nsTextDimensions& aLastWordDimensions
1918 + void GetBoundingMetricsInternal(PangoLayout *aLayout,
1919 + nsBoundingMetrics &aBoundingMetrics
1921 +#endif /* MOZ_MATHML */
1923 + void FixupSpaceWidths (PangoLayout *aLayout);
1925 - void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
1926 + PangoLayout* GetLayout (const PRUnichar* aText,
1927 + PRUint32 aLength);
1928 + PangoLayout* GetLayout (const gchar* aText,
1932 class nsFontEnumeratorPango : public nsIFontEnumerator