updated on Thu Jan 19 20:01:47 UTC 2012
[aur-mirror.git] / firefox2 / firefox-2.0-pango-ligatures.patch
blobcfd1da76f827d0cef6f614be96554746d229cfed
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
3 @@ -21,6 +21,8 @@
4 * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
6 * Contributor(s):
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
12 @@ -36,6 +38,10 @@
14 * ***** END LICENSE BLOCK ***** */
16 +#define PANGO_ENABLE_BACKEND
18 +#include "nsFontMetricsPango.h"
20 #include <strings.h>
21 #include "nsFont.h"
22 #include "nsIDeviceContext.h"
23 @@ -43,27 +49,37 @@
24 #include "nsIPref.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"
40 +#define FORCE_PR_LOG
41 +#include "prlog.h"
44 #include <fontconfig/fontconfig.h>
45 +#include <freetype/tttables.h>
47 +#include <pango/pango.h>
48 +#include <pango/pangofc-font.h>
50 +#ifdef PSPANGO
51 +#include <pango/pangoft2.h>
52 +#include "nsRenderingContextPS.h"
53 +#include "nsDeviceContextPS.h"
54 +#include "nsType1.h"
55 +#else
56 #include <gdk/gdk.h>
57 #include <gdk/gdkx.h>
58 -#include <freetype/tttables.h>
59 +#include "nsRenderingContextGTK.h"
60 +#include "nsDeviceContextGTK.h"
61 +#endif
64 -#include "mozilla-decoder.h"
66 -#define FORCE_PR_LOG
67 -#include "prlog.h"
69 // Globals
71 @@ -108,6 +124,49 @@ static nsresult EnumFontsPango (nsI
72 PRUint32* aCount, PRUnichar*** aResult);
73 static int CompareFontNames (const void* aArg1, const void* aArg2,
74 void* aClosure);
75 +static void utf16_to_utf8 (const PRUnichar* aString, PRUint32 aLength,
76 + char *&text, gint &text_len);
78 +#ifdef PSPANGO
79 +static void
80 +default_substitute (FcPattern *pattern,
81 + gpointer data)
83 + FcPatternDel (pattern, FC_HINTING);
84 + FcPatternAddBool (pattern, FC_HINTING, 0);
86 +#endif
88 +static PangoFontMap *
89 +get_fontmap (void)
91 + static PangoFontMap *fontmap = NULL;
93 + if (!fontmap) {
94 +#ifdef PSPANGO
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);
98 +#else
99 + PangoContext* context = gdk_pango_context_get ();
100 + fontmap = pango_context_get_font_map (context);
101 + g_object_unref (context);
102 +#endif
105 + return fontmap;
108 +static PangoContext *
109 +get_context (void)
111 +#ifdef PSPANGO
112 + return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
113 +#else
114 + return gdk_pango_context_get();
115 +#endif
119 nsFontMetricsPango::nsFontMetricsPango()
121 @@ -169,14 +228,20 @@ nsFontMetricsPango::Init(const nsFont& a
122 mLangGroup = aLangGroup;
124 // Hang on to the device context
125 +#ifdef PSPANGO
126 + mDeviceContext = (nsDeviceContextPS *)aContext;
127 +#else
128 mDeviceContext = aContext;
129 +#endif
131 mPointSize = NSTwipsToFloatPoints(mFont.size);
133 +#ifndef PSPANGO
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);
138 +#endif
140 // enumerate over the font names passed in
141 mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
142 @@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
144 // mPangoSpaceWidth
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)
154 nscoord tmpWidth;
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
172 -nsresult
173 -nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
174 - nscoord& aWidth,
175 - nsRenderingContextGTK *aContext)
176 +#ifdef PSPANGO
177 +NS_IMETHODIMP
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);
188 +NS_IMETHODIMP
189 +nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
191 + return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
193 +#endif
195 +nsresult
196 +nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
197 + nscoord& aWidth
198 + CONTEXT_ARG_DEF)
200 int width, height;
202 + PangoLayout *layout = GetLayout(aString, aLength);
203 pango_layout_get_size(layout, &width, &height);
205 g_object_unref(layout);
207 - float f;
208 - f = mDeviceContext->DevUnitsToAppUnits();
209 + float f = mDeviceContext->DevUnitsToAppUnits();
210 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
212 - // printf("GetWidth (char *) %d\n", aWidth);
214 return NS_OK;
217 nsresult
218 nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
219 - nscoord& aWidth, PRInt32 *aFontID,
220 - nsRenderingContextGTK *aContext)
221 + nscoord& aWidth, PRInt32 *aFontID
222 + CONTEXT_ARG_DEF)
224 - nsresult rv = NS_OK;
225 - PangoLayout *layout = pango_layout_new(mPangoContext);
227 - gchar *text = g_utf16_to_utf8(aString, aLength,
228 - NULL, NULL, NULL);
230 - if (!text) {
231 - aWidth = 0;
232 -#ifdef DEBUG
233 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
234 - DUMP_PRUNICHAR(aString, aLength)
235 -#endif
236 - rv = NS_ERROR_FAILURE;
237 - goto loser;
240 gint width, height;
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);
248 - float f;
249 - f = mDeviceContext->DevUnitsToAppUnits();
250 + float f = mDeviceContext->DevUnitsToAppUnits();
251 aWidth = NSToCoordRound(width * f / PANGO_SCALE);
253 - // printf("GetWidth %d\n", aWidth);
255 - loser:
256 - g_free(text);
257 - g_object_unref(layout);
259 - return rv;
260 + return NS_OK;
264 nsresult
265 -nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
266 +nsFontMetricsPango::GetTextDimensions(const char* aString,
267 PRUint32 aLength,
268 - nsTextDimensions& aDimensions,
269 - PRInt32* aFontID,
270 - nsRenderingContextGTK *aContext)
271 + nsTextDimensions& aDimensions
272 + CONTEXT_ARG_DEF)
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,
281 - NULL, NULL, NULL);
283 - if (!text) {
284 -#ifdef DEBUG
285 - NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
286 - DUMP_PRUNICHAR(aString, aLength)
287 -#endif
288 - aDimensions.width = 0;
289 - aDimensions.ascent = 0;
290 - aDimensions.descent = 0;
292 - rv = NS_ERROR_FAILURE;
293 - goto loser;
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);
316 + return NS_OK;
319 - float P2T;
320 - P2T = mDeviceContext->DevUnitsToAppUnits();
321 +nsresult
322 +nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
323 + PRUint32 aLength,
324 + nsTextDimensions& aDimensions,
325 + PRInt32* aFontID
326 + CONTEXT_ARG_DEF)
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();
342 - loser:
343 - g_free(text);
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);
349 - return rv;
350 + return NS_OK;
353 nsresult
354 @@ -595,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co
355 nsTextDimensions& aDimensions,
356 PRInt32& aNumCharsFit,
357 nsTextDimensions& aLastWordDimensions,
358 - PRInt32* aFontID,
359 - nsRenderingContextGTK *aContext)
360 + PRInt32* aFontID
361 + CONTEXT_ARG_DEF)
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,
375 - PRInt32* aFontID,
376 - nsRenderingContextGTK *aContext)
377 + PRInt32* aFontID
378 + CONTEXT_ARG_DEF)
380 nsresult rv = NS_OK;
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,
387 - NULL, NULL, NULL);
388 + gchar* text;
389 + gint text_len;
390 + utf16_to_utf8 (aString, aLength, text, text_len);
392 curChar = text;
394 - if (!text) {
395 -#ifdef DEBUG
396 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
397 - DUMP_PRUNICHAR(aString, (PRUint32)aLength)
398 -#endif
399 - rv = NS_ERROR_FAILURE;
400 - goto loser;
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;
409 curBreak++;
410 @@ -653,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co
411 utf8Breaks[curBreak] = curChar - text;
413 #if 0
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.
427 curBreak = 0;
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
440 - loser:
441 - if (text)
442 - g_free(text);
443 + g_free(text);
445 delete[] utf8Breaks;
447 return rv;
450 -nsresult
451 -nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
452 - nscoord aX, nscoord aY,
453 - const nscoord* aSpacing,
454 - nsRenderingContextGTK *aContext,
455 - nsDrawingSurfaceGTK *aSurface)
456 +#ifdef PSPANGO
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;
467 + float zoom;
470 - pango_layout_set_text(layout, aString, aLength);
471 - FixupSpaceWidths(layout, aString);
472 +struct _nsPSPangoRendererClass
474 + PangoRendererClass parent_class;
477 - int x = aX;
478 - int y = aY;
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 *
495 +get_renderer (void)
497 + static PangoRenderer *renderer = NULL;
499 - aContext->UpdateGC();
500 - GdkGC *gc = aContext->GetGC();
501 + if (!renderer)
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);
508 - else {
509 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
510 - x, y,
511 - line);
513 + return renderer;
516 - g_object_unref(gc);
517 - g_object_unref(layout);
518 +static void
519 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
520 + PangoFont *font,
521 + PangoGlyphString *glyphs,
522 + int x,
523 + int y);
525 - // printf("DrawString (char *)\n");
526 +static void
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;
534 - return NS_OK;
535 +static void
536 +_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
540 +class nsPangoType1Generator : public nsPSFontGenerator {
541 +public:
542 + nsPangoType1Generator();
543 + ~nsPangoType1Generator();
544 + nsresult Init(PangoFont *aFont);
545 + void GeneratePSFont(FILE* aFile);
547 +protected:
548 + PangoFont *mFont;
551 +nsPangoType1Generator::nsPangoType1Generator()
555 nsresult
556 -nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
557 - nscoord aX, nscoord aY,
558 - PRInt32 aFontID,
559 - const nscoord* aSpacing,
560 - nsRenderingContextGTK *aContext,
561 - nsDrawingSurfaceGTK *aSurface)
562 +nsPangoType1Generator::Init(PangoFont *aFont)
564 + NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
565 + mFont = aFont;
566 + g_object_ref (mFont);
567 + return NS_OK;
570 +nsPangoType1Generator::~nsPangoType1Generator()
572 - nsresult rv = NS_OK;
573 - int x = aX;
574 - int y = aY;
575 + g_object_unref (mFont);
576 + mFont = nsnull;
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)
587 + return;
589 - gchar *text = g_utf16_to_utf8(aString, aLength,
590 - NULL, NULL, NULL);
591 + int wmode = 0;
592 + if (mGlyphSubset->Count())
593 + FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
595 - if (!text) {
596 -#ifdef DEBUG
597 - NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
598 - DUMP_PRUNICHAR(aString, aLength)
599 -#endif
600 - rv = NS_ERROR_FAILURE;
601 - goto loser;
603 + pango_fc_font_unlock_face ((PangoFcFont *) mFont);
606 - pango_layout_set_text(layout, text, strlen(text));
607 - FixupSpaceWidths(layout, text);
608 +typedef struct
610 + nsCString *FontNameBase;
611 + nsCStringKey *key;
612 + int font_size;
613 +} PSPangoFontData;
615 - aContext->GetTranMatrix()->TransformCoord(&x, &y);
616 +static void
617 +ps_pango_font_data_destroy (PSPangoFontData *data)
619 + delete data->key;
620 + delete data->FontNameBase;
621 + g_free (data);
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);
629 +static void
630 +_ps_pango_renderer_draw_glyphs (PangoRenderer *renderer,
631 + PangoFont *font,
632 + PangoGlyphString *glyphs,
633 + int x,
634 + int y)
636 + if (!glyphs->num_glyphs)
637 + return;
639 - if (aSpacing && *aSpacing) {
640 - DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
641 - gc, x, y, line, aSpacing);
643 - else {
644 - gdk_draw_layout_line(aSurface->GetDrawable(), gc,
645 - x, y,
646 - line);
648 + static GQuark data_quark = 0;
649 + if (!data_quark)
650 + data_quark = g_quark_from_static_string ("ps-pango-font-data");
652 - loser:
653 + PSPangoFontData *data;
654 + if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
656 + data = g_new (PSPangoFontData, 1);
658 - g_free(text);
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)
663 + return;
664 + int wmode = 0;
665 + data->FontNameBase = new nsCString ();
666 + if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
667 + g_free (data);
668 + pango_fc_font_unlock_face ((PangoFcFont *) font);
669 + return;
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);
691 + if (!psFontGen) {
692 + nsresult rv;
693 + psFontGen = new nsPangoType1Generator;
694 + g_return_if_fail (psFontGen);
695 + rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
696 + if (NS_FAILED(rv)) {
697 + delete psFontGen;
698 + return;
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;
712 + PRUint32 i;
713 + PangoGlyphString gl;
715 + gl.glyphs = glyphs->glyphs;
716 + gl.num_glyphs = 0;
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;
731 + gl.num_glyphs = 0;
734 - return rv;
735 + gl.num_glyphs++;
738 + if (prevSubFont != -1)
739 + psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
741 +#endif
743 +static void
744 +draw_layout_line (int x, int y,
745 + PangoLayoutLine *line,
746 + nsFontMetricsPango *fm
747 + CONTEXT_AND_SURFACE_ARG_DEF)
749 +#ifdef PSPANGO
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));
760 +#else
761 + aContext->UpdateGC();
762 + GdkGC *gc = aContext->GetGC();
763 + gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line);
764 + g_object_unref(gc);
765 +#endif
769 -#ifdef MOZ_MATHML
770 nsresult
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;
781 + int x = aX;
782 + int y = aY;
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);
794 + return NS_OK;
797 nsresult
798 -nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
799 - PRUint32 aLength,
800 - nsBoundingMetrics &aBoundingMetrics,
801 - PRInt32 *aFontID,
802 - nsRenderingContextGTK *aContext)
803 +nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
804 + nscoord aX, nscoord aY,
805 + PRInt32 aFontID,
806 + const nscoord* aSpacing
807 + CONTEXT_AND_SURFACE_ARG_DEF)
809 - nsresult rv = NS_OK;
810 - PangoLayout *layout = pango_layout_new(mPangoContext);
811 + int x = aX;
812 + int y = aY;
814 - gchar *text = g_utf16_to_utf8(aString, aLength,
815 - NULL, NULL, NULL);
816 + aContext->GetTranMatrix()->TransformCoord(&x, &y);
818 - if (!text) {
819 -#ifdef DEBUG
820 - NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
821 - DUMP_PRUNICHAR(aString, aLength)
822 -#endif
823 - aBoundingMetrics.Clear();
824 + PangoLayout *layout = GetLayout(aString, aLength);
825 + PangoLayoutLine *line = pango_layout_get_line(layout, 0);
827 - rv = NS_ERROR_FAILURE;
828 - goto loser;
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);
837 + return NS_OK;
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);
846 +#ifdef MOZ_MATHML
847 +void
848 +nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
849 + nsBoundingMetrics &aBoundingMetrics
850 + CONTEXT_ARG_DEF)
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);
858 - float P2T;
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);
869 - loser:
870 - g_free(text);
871 +nsresult
872 +nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
873 + nsBoundingMetrics &aBoundingMetrics
874 + CONTEXT_ARG_DEF)
876 + PangoLayout *layout = GetLayout(aString, aLength);
877 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
878 g_object_unref(layout);
880 - return rv;
881 + return NS_OK;
884 +nsresult
885 +nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
886 + PRUint32 aLength,
887 + nsBoundingMetrics &aBoundingMetrics,
888 + PRInt32 *aFontID
889 + CONTEXT_ARG_DEF)
891 + PangoLayout *layout = GetLayout(aString, aLength);
892 + GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
893 + g_object_unref(layout);
895 + return NS_OK;
898 #endif /* MOZ_MATHML */
900 +#ifndef PSPANGO
901 GdkFont*
902 nsFontMetricsPango::GetCurrentGDKFont(void)
904 return nsnull;
906 +#endif
908 nsresult
909 nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
911 if (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
922 PRUint32 aLength,
923 PRUint8 *aClusterStarts)
925 - nsresult rv = NS_OK;
926 PangoLogAttr *attrs = NULL;
927 gint n_attrs = 0;
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);
933 - if (!text) {
934 -#ifdef DEBUG
935 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
936 - DUMP_PRUNICHAR(aText, aLength)
937 -#endif
938 - rv = NS_ERROR_FAILURE;
939 - goto loser;
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
950 // structure.
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
957 pos++;
959 else {
960 @@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
964 - loser:
965 - if (attrs)
966 - g_free(attrs);
967 - if (text)
968 - g_free(text);
969 - if (layout)
970 - g_object_unref(layout);
971 + g_free(attrs);
973 - return rv;
974 + return NS_OK;
977 PRInt32
978 -nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
979 - nsPoint aPt)
980 +nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
982 int trailing = 0;
983 int inx = 0;
984 - const gchar *curChar;
985 PRInt32 retval = 0;
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);
996 - if (!text) {
997 -#ifdef DEBUG
998 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
999 - DUMP_PRUNICHAR(aText, aLength)
1000 -#endif
1001 - retval = -1;
1002 - goto loser;
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,
1011 &inx, &trailing);
1013 // Convert the index back to the utf-16 index
1014 - curChar = text;
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
1025 trailing--;
1028 - loser:
1029 - if (text)
1030 - g_free(text);
1031 - if (layout)
1032 - g_object_unref(layout);
1033 + g_object_unref(layout);
1035 - return retval;
1036 + return retval;
1039 nsresult
1040 @@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const
1041 PRUint32 aEnd,
1042 PRUint32 &aWidth)
1044 - nsresult rv = NS_OK;
1045 PRUint32 utf8Start = 0;
1046 PRUint32 utf8End = 0;
1048 aWidth = 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;
1054 - if (!text) {
1055 -#ifdef DEBUG
1056 - NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1057 - DUMP_PRUNICHAR(aText, aLength)
1058 -#endif
1059 - rv = NS_ERROR_FAILURE;
1060 - goto loser;
1062 + gchar* text;
1063 + gint text_len;
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);
1084 - loser:
1085 - if (text)
1086 - g_free(text);
1087 + g_free(text);
1089 - return rv;
1090 + return NS_OK;
1093 nsresult
1094 @@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const
1095 PRUint32 aEnd,
1096 PRUint32 &aWidth)
1098 - nsresult rv = NS_OK;
1099 int *ranges = NULL;
1100 int n_ranges = 0;
1101 float f;
1103 aWidth = 0;
1105 - PangoLayout *layout = pango_layout_new(mPangoContext);
1107 - if (!aText) {
1108 - rv = NS_ERROR_FAILURE;
1109 - goto loser;
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);
1131 - loser:
1132 - if (ranges)
1133 - g_free(ranges);
1134 - if (layout)
1135 - g_object_unref(layout);
1136 + g_free(ranges);
1137 + g_object_unref(layout);
1139 - return rv;
1140 + return NS_OK;
1143 /* static */
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;
1151 int n;
1153 @@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
1155 // Now that we have the font description set up, create the
1156 // context.
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:
1178 + */
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;
1198 + int start_glyph;
1199 + int start_index;
1200 + int start_char;
1202 + int end_glyph;
1203 + int end_index;
1204 + int end_char;
1207 +/**
1208 + * _pango_glyph_item_iter_next_cluster:
1209 + * @iter: a #PangoGlyphItemIter
1210 + *
1211 + * Advances the iterator to the next cluster in the glyph item.
1212 + *
1213 + * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
1214 + * last cluster.
1215 + **/
1216 +static gboolean
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)
1226 + return FALSE;
1228 + else
1230 + if (glyph_index < 0)
1231 + return FALSE;
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))
1240 + while (TRUE)
1242 + glyph_index++;
1244 + if (glyph_index == glyphs->num_glyphs)
1246 + iter->end_index = item->offset + item->length;
1247 + iter->end_char = item->num_chars;
1248 + break;
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);
1256 + break;
1260 + else /* RTL */
1262 + while (TRUE)
1264 + glyph_index--;
1266 + if (glyph_index < 0)
1268 + iter->end_index = item->offset + item->length;
1269 + iter->end_char = item->num_chars;
1270 + break;
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);
1278 + break;
1283 + iter->end_glyph = glyph_index;
1284 + return TRUE;
1287 +/**
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
1292 + *
1293 + * Initializes a #PangoGlyphItemIter structure to point to the
1294 + * first cluster in a glyph item.
1295 + *
1296 + * Return value: %FALSE if there are no clusters in the glyph item;
1297 + * in this case, the state of the iter is undefined.
1298 + **/
1299 +static gboolean
1300 +_pango_glyph_item_iter_init_start (PangoGlyphItemIter *iter,
1301 + PangoGlyphItem *glyph_item,
1302 + const char *text)
1304 + iter->glyph_item = glyph_item;
1305 + iter->text = text;
1307 + if (LTR (glyph_item))
1308 + iter->end_glyph = 0;
1309 + else
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);
1320 void
1321 -nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
1322 - const PRUnichar *aOrigString,
1323 - PRUint32 aLength,
1324 - GdkDrawable *aDrawable,
1325 - GdkGC *aGC, gint aX, gint aY,
1326 - PangoLayoutLine *aLine,
1327 - const nscoord *aSpacing)
1329 - float app2dev;
1330 - app2dev = mDeviceContext->AppUnitsToDevUnits();
1331 - gint offset = 0;
1332 +nsFontMetricsPango::ApplySpacing(const gchar *aText,
1333 + PRUint32 aLength,
1334 + PangoLayoutLine *aLine,
1335 + const nscoord *aSpacing)
1337 + if (!(aSpacing && *aSpacing))
1338 + return;
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.
1351 + * glyphs.
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);
1363 + have_cluster;
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;
1389 + continue;
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;
1408 +#ifndef PSPANGO
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;
1416 +#endif
1418 - if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
1419 - 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;
1424 + break;
1428 - else {
1429 - memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
1433 - gint curRun = 0;
1434 +void
1435 +nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
1436 + PRUint32 aLength,
1437 + PangoLayoutLine *aLine,
1438 + const nscoord *aSpacing)
1440 + if (!(aSpacing && *aSpacing))
1441 + return;
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.
1457 + */
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));
1465 - */
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]))
1481 + 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);
1491 nsresult
1492 @@ -1363,8 +1669,8 @@ nsFontMetricsPango::GetTextDimensionsInt
1493 PRInt32 aNumBreaks,
1494 nsTextDimensions& aDimensions,
1495 PRInt32& aNumCharsFit,
1496 - nsTextDimensions& aLastWordDimensions,
1497 - nsRenderingContextGTK *aContext)
1498 + nsTextDimensions& aLastWordDimensions
1499 + CONTEXT_ARG_DEF)
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;
1507 - }
1509 else {
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,
1526 - aContext);
1527 + GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
1528 width -= twWidth;
1529 aNumCharsFit = start;
1530 breakIndex--;
1531 @@ -1504,9 +1809,16 @@ nsFontMetricsPango::GetTextDimensionsInt
1534 void
1535 -nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
1536 - const char *aString)
1537 +nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
1539 + if (!mPangoSpaceWidth)
1540 + return;
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);
1549 gint curRun = 0;
1550 @@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
1554 +PangoLayout*
1555 +nsFontMetricsPango::GetLayout (const PRUnichar* aText,
1556 + PRUint32 aLength)
1558 + gchar* text;
1559 + gint length;
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);
1568 + return layout;
1571 +PangoLayout*
1572 +nsFontMetricsPango::GetLayout (const gchar* aText,
1573 + PRInt32 aLength)
1575 + gboolean has_nul = FALSE;
1576 + int i;
1578 + for (i = 0; i < aLength; i++)
1579 + if (!aText[i]) {
1580 + has_nul = TRUE;
1581 + break;
1584 + if (has_nul) {
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++)
1591 + if (!p[i])
1592 + p[i] = (char) 0xff;
1594 + aText = p;
1597 + PangoLayout *layout = pango_layout_new(mPangoContext);
1598 + pango_layout_set_text (layout, aText, aLength);
1599 + FixupSpaceWidths (layout);
1601 + if (has_nul)
1602 + g_free ((gpointer) aText);
1604 + return layout;
1607 +static void
1608 +utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
1610 + gboolean need_copy = FALSE;
1611 + int i;
1613 + for (i = 0; i < aLength; i++) {
1614 + if (!aText[i] || IS_LOW_SURROGATE (aText[i]))
1615 + need_copy = TRUE;
1616 + else if (IS_HIGH_SURROGATE (aText[i])) {
1617 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1618 + i++;
1619 + else
1620 + need_copy = TRUE;
1624 + if (need_copy) {
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]))
1634 + p[i] = 0xFFFD;
1635 + else if (IS_HIGH_SURROGATE (p[i])) {
1636 + if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
1637 + i++;
1638 + else
1639 + p[i] = 0xFFFD;
1643 + aText = p;
1646 + glong items_written;
1647 + text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
1648 + length = items_written;
1650 + if (need_copy)
1651 + g_free ((gpointer) aText);
1655 /* static */
1656 PangoLanguage *
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
1660 @@ -37,17 +37,53 @@
1662 * ***** END LICENSE BLOCK ***** */
1665 #include "nsIFontMetrics.h"
1666 #include "nsIFontEnumerator.h"
1667 #include "nsCRT.h"
1668 #include "nsIAtom.h"
1669 #include "nsString.h"
1670 #include "nsVoidArray.h"
1672 +#ifdef PSPANGO
1673 +#include "nsFontMetricsPS.h"
1674 +#else
1675 #include "nsIFontMetricsGTK.h"
1676 +#endif
1678 #include <pango/pango.h>
1680 -class nsFontMetricsPango : public nsIFontMetricsGTK
1681 +#ifdef PSPANGO
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
1689 +#else
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
1697 +#endif
1700 +#ifdef PSPANGO
1702 +#define nsFontMetricsPango nsFontMetricsPSPango
1703 +#define PSPANGO_PARENT_CLASS nsFontMetricsPS
1705 +#else
1707 +#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
1709 +#endif
1711 +class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
1713 public:
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,
1721 - nscoord& aWidth,
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,
1729 +#ifdef PSPANGO
1730 + NS_IMETHOD GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
1731 + NS_IMETHOD GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
1732 +#endif
1734 + NS_METHOD GetWidth(const char* aString, PRUint32 aLength,
1735 + nscoord& aWidth
1736 + CONTEXT_ARG_DEF);
1737 + NS_METHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
1738 + nscoord& aWidth, PRInt32 *aFontID
1739 + CONTEXT_ARG_DEF);
1741 + NS_METHOD GetTextDimensions(const char* aString,
1742 + PRUint32 aLength,
1743 + nsTextDimensions& aDimensions
1744 + CONTEXT_ARG_DEF);
1745 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1746 PRUint32 aLength,
1747 nsTextDimensions& aDimensions,
1748 - PRInt32* aFontID,
1749 - nsRenderingContextGTK *aContext);
1750 - virtual nsresult GetTextDimensions(const char* aString,
1751 + PRInt32* aFontID
1752 + CONTEXT_ARG_DEF);
1753 + NS_METHOD GetTextDimensions(const char* aString,
1754 PRInt32 aLength,
1755 PRInt32 aAvailWidth,
1756 PRInt32* aBreaks,
1757 @@ -157,9 +203,9 @@ public:
1758 nsTextDimensions& aDimensions,
1759 PRInt32& aNumCharsFit,
1760 nsTextDimensions& aLastWordDimensions,
1761 - PRInt32* aFontID,
1762 - nsRenderingContextGTK *aContext);
1763 - virtual nsresult GetTextDimensions(const PRUnichar* aString,
1764 + PRInt32* aFontID
1765 + CONTEXT_ARG_DEF);
1766 + NS_METHOD GetTextDimensions(const PRUnichar* aString,
1767 PRInt32 aLength,
1768 PRInt32 aAvailWidth,
1769 PRInt32* aBreaks,
1770 @@ -167,38 +213,37 @@ public:
1771 nsTextDimensions& aDimensions,
1772 PRInt32& aNumCharsFit,
1773 nsTextDimensions& aLastWordDimensions,
1774 - PRInt32* aFontID,
1775 - nsRenderingContextGTK *aContext);
1776 + PRInt32* aFontID
1777 + CONTEXT_ARG_DEF);
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,
1791 PRInt32 aFontID,
1792 - const nscoord* aSpacing,
1793 - nsRenderingContextGTK *aContext,
1794 - nsDrawingSurfaceGTK *aSurface);
1795 + const nscoord* aSpacing
1796 + CONTEXT_AND_SURFACE_ARG_DEF);
1798 #ifdef MOZ_MATHML
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
1805 + CONTEXT_ARG_DEF);
1806 + NS_METHOD GetBoundingMetrics(const PRUnichar *aString,
1807 PRUint32 aLength,
1808 nsBoundingMetrics &aBoundingMetrics,
1809 - PRInt32 *aFontID,
1810 - nsRenderingContextGTK *aContext);
1811 + PRInt32 *aFontID
1812 + CONTEXT_ARG_DEF);
1813 #endif /* MOZ_MATHML */
1815 +#ifndef PSPANGO
1816 virtual GdkFont* GetCurrentGDKFont(void);
1818 - virtual nsresult SetRightToLeftText(PRBool aIsRTL);
1819 +#endif
1820 virtual PRBool GetRightToLeftText();
1822 - virtual nsresult GetClusterInfo(const PRUnichar *aText,
1823 + NS_METHOD SetRightToLeftText(PRBool aIsRTL);
1825 + NS_METHOD GetClusterInfo(const PRUnichar *aText,
1826 PRUint32 aLength,
1827 PRUint8 *aClusterStarts);
1829 @@ -206,32 +251,35 @@ public:
1830 PRUint32 aLength,
1831 nsPoint aPt);
1833 - virtual nsresult GetRangeWidth(const PRUnichar *aText,
1834 + NS_METHOD GetRangeWidth(const PRUnichar *aText,
1835 PRUint32 aLength,
1836 PRUint32 aStart,
1837 PRUint32 aEnd,
1838 PRUint32 &aWidth);
1840 - virtual nsresult GetRangeWidth(const char *aText,
1841 + NS_METHOD GetRangeWidth(const char *aText,
1842 PRUint32 aLength,
1843 PRUint32 aStart,
1844 PRUint32 aEnd,
1845 PRUint32 &aWidth);
1847 // get hints for the font
1848 - static PRUint32 GetHints (void);
1849 +#ifndef PSPANGO
1850 + static
1851 +#endif
1852 + PRUint32 GetHints (void);
1854 // drawing surface methods
1855 static nsresult FamilyExists (nsIDeviceContext *aDevice,
1856 const nsString &aName);
1859 private:
1861 // generic font metrics class bits
1862 nsCStringArray mFontList;
1863 nsAutoVoidArray mFontIsGeneric;
1865 - nsIDeviceContext *mDeviceContext;
1866 nsCOMPtr<nsIAtom> mLangGroup;
1867 nsCString *mGenericFont;
1868 float mPointSize;
1869 @@ -246,6 +294,9 @@ private:
1870 PangoAttrList *mPangoAttrList;
1871 PRBool mIsRTL;
1873 +#ifndef PSPANGO
1874 + nsIDeviceContext *mDeviceContext;
1876 // Cached font metrics
1877 nscoord mXHeight;
1878 nscoord mSuperscriptOffset;
1879 @@ -263,6 +314,7 @@ private:
1880 nscoord mMaxDescent;
1881 nscoord mMaxAdvance;
1882 nscoord mSpaceWidth;
1883 +#endif
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,
1893 - PRUint32 aLength,
1894 - GdkDrawable *aDrawable,
1895 - GdkGC *aGC, gint aX, gint aY,
1896 - PangoLayoutLine *aLine,
1897 - const nscoord *aSpacing);
1898 + void ApplySpacing(const gchar *aText,
1899 + PRUint32 aLength,
1900 + PangoLayoutLine *aLine,
1901 + const nscoord *aSpacing);
1902 + void ApplySpacing(const PRUnichar *aText,
1903 + PRUint32 aLength,
1904 + PangoLayoutLine *aLine,
1905 + const nscoord *aSpacing);
1907 nsresult GetTextDimensionsInternal(const gchar* aString,
1908 PRInt32 aLength,
1909 @@ -289,10 +342,20 @@ private:
1910 PRInt32 aNumBreaks,
1911 nsTextDimensions& aDimensions,
1912 PRInt32& aNumCharsFit,
1913 - nsTextDimensions& aLastWordDimensions,
1914 - nsRenderingContextGTK *aContext);
1915 + nsTextDimensions& aLastWordDimensions
1916 + CONTEXT_ARG_DEF);
1917 +#ifdef MOZ_MATHML
1918 + void GetBoundingMetricsInternal(PangoLayout *aLayout,
1919 + nsBoundingMetrics &aBoundingMetrics
1920 + CONTEXT_ARG_DEF);
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,
1929 + PRInt32 aLength);
1932 class nsFontEnumeratorPango : public nsIFontEnumerator