]> git.pld-linux.org Git - packages/firefox.git/blob - mozilla-firefox-pango-ligatures.patch
- updated to 3.5rc3
[packages/firefox.git] / mozilla-firefox-pango-ligatures.patch
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.
5   *
6   * Contributor(s):
7 + *   Christopher Blizzard <blizzard@mozilla.org>
8 + *   Behdad Esfahbod <behdad@behdad.org>
9   *
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 @@
13   *
14   * ***** END LICENSE BLOCK ***** */
15  
16 +#define PANGO_ENABLE_BACKEND
17 +
18 +#include "nsFontMetricsPango.h"
19 +
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"
26  
27 -#define PANGO_ENABLE_BACKEND
28 -#define PANGO_ENABLE_ENGINE
29 -
30 -#include "nsFontMetricsPango.h"
31 -#include "nsRenderingContextGTK.h"
32 -#include "nsDeviceContextGTK.h"
33  #include "nsFontConfigUtils.h"
34  
35  #include "nsUnicharUtils.h"
36  #include "nsQuickSort.h"
37  #include "nsFontConfigUtils.h"
38 +#include "mozilla-decoder.h"
39 +
40 +#define FORCE_PR_LOG
41 +#include "prlog.h"
42 +
43  
44  #include <fontconfig/fontconfig.h>
45 +#include <freetype/tttables.h>
46 +
47 +#include <pango/pango.h>
48 +#include <pango/pangofc-font.h>
49 +
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
62 +
63  
64 -#include "mozilla-decoder.h"
65  
66 -#define FORCE_PR_LOG
67 -#include "prlog.h"
68  
69  // Globals
70  
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);
77 +
78 +#ifdef PSPANGO
79 +static void
80 +default_substitute (FcPattern *pattern,
81 +                    gpointer   data)
82 +{
83 +  FcPatternDel (pattern, FC_HINTING);
84 +  FcPatternAddBool (pattern, FC_HINTING, 0);
85 +}
86 +#endif
87 +
88 +static PangoFontMap *
89 +get_fontmap (void)
90 +{
91 +  static PangoFontMap               *fontmap = NULL;
92 +
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
103 +  }
104 +
105 +  return fontmap;
106 +}
107 +
108 +static PangoContext *
109 +get_context (void)
110 +{
111 +#ifdef PSPANGO
112 +  return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
113 +#else
114 +  return gdk_pango_context_get();
115 +#endif
116 +}
117 +
118  
119  nsFontMetricsPango::nsFontMetricsPango()
120  {
121 @@ -228,14 +228,20 @@
122      mLangGroup = aLangGroup;
123  
124      // Hang on to the device context
125 +#ifdef PSPANGO
126 +    mDeviceContext = (nsDeviceContextPS *)aContext;
127 +#else
128      mDeviceContext = aContext;
129 +#endif
130      
131      mPointSize = NSTwipsToFloatPoints(mFont.size);
132  
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
139  
140      // enumerate over the font names passed in
141      mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
142 @@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
143  
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
152  
153      // mSpaceWidth (width of a space)
154      nscoord tmpWidth;
155 -    GetWidth(" ", 1, tmpWidth, NULL);
156 +    GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL);
157      mSpaceWidth = tmpWidth;
158  
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;
166  
167      // mXHeight (height of an 'x' character)
168 @@ -460,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont
169  
170  // nsIFontMetricsPango impl
171  
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)
179  {
180 -    PangoLayout *layout = pango_layout_new(mPangoContext);
181 -
182 -    pango_layout_set_text(layout, aString, aLength);
183 +    return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL);
184 +}
185  
186 -    if (mPangoSpaceWidth)
187 -        FixupSpaceWidths(layout, aString);
188 +NS_IMETHODIMP
189 +nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
190 +{
191 +    return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
192 +}
193 +#endif
194  
195 +nsresult
196 +nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
197 +                             nscoord& aWidth
198 +                             CONTEXT_ARG_DEF)
199 +{
200      int width, height;
201 -
202 +    PangoLayout *layout = GetLayout(aString, aLength);
203      pango_layout_get_size(layout, &width, &height);
204 -
205      g_object_unref(layout);
206  
207 -    float f;
208 -    f = mDeviceContext->DevUnitsToAppUnits();
209 +    float f = mDeviceContext->DevUnitsToAppUnits();
210      aWidth = NSToCoordRound(width * f / PANGO_SCALE);
211  
212 -    //    printf("GetWidth (char *) %d\n", aWidth);
213 -
214      return NS_OK;
215  }
216  
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)
223  {
224 -    nsresult rv = NS_OK;
225 -    PangoLayout *layout = pango_layout_new(mPangoContext);
226 -
227 -    gchar *text = g_utf16_to_utf8(aString, aLength,
228 -                                  NULL, NULL, NULL);
229 -
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;
238 -    }
239 -
240      gint width, height;
241 -
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);
247  
248 -    float f;
249 -    f = mDeviceContext->DevUnitsToAppUnits();
250 +    float f = mDeviceContext->DevUnitsToAppUnits();
251      aWidth = NSToCoordRound(width * f / PANGO_SCALE);
252  
253 -    //    printf("GetWidth %d\n", aWidth);
254 -
255 - loser:
256 -    g_free(text);
257 -    g_object_unref(layout);
258 -
259 -    return rv;
260 +    return NS_OK;
261  }
262  
263  
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)
273  {
274 -    nsresult rv = NS_OK;
275 -
276 -    PangoLayout *layout = pango_layout_new(mPangoContext);
277 +    PangoLayout *layout = GetLayout(aString, aLength);
278 +    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
279  
280 -    gchar *text = g_utf16_to_utf8(aString, aLength,
281 -                                  NULL, NULL, NULL);
282 -
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;
291 -
292 -        rv = NS_ERROR_FAILURE;
293 -        goto loser;
294 -    }
295 -        
296 +    PangoRectangle logical;
297 +    pango_layout_line_get_extents(line, NULL, &logical);
298 +    g_object_unref(layout);
299  
300 -    pango_layout_set_text(layout, text, strlen(text));
301 -    FixupSpaceWidths(layout, text);
302 +    float P2T = mDeviceContext->DevUnitsToAppUnits();
303  
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");
308 -    }
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);
313  
314 -    PangoRectangle rect;
315 -    pango_layout_line_get_extents(line, NULL, &rect);
316 +    return NS_OK;
317 +}
318  
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)
327 +{
328 +    PangoLayout *layout = GetLayout(aString, aLength);
329 +    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
330  
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);
337  
338 -    //    printf("GetTextDimensions %d %d %d\n", aDimensions.width,
339 -    //aDimensions.ascent, aDimensions.descent);
340 +    float P2T = mDeviceContext->DevUnitsToAppUnits();
341  
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);
348  
349 -    return rv;
350 +    return NS_OK;
351  }
352  
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)
362  {
363  
364      return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
365                                       aNumBreaks, aDimensions, aNumCharsFit,
366 -                                     aLastWordDimensions, aContext);
367 +                                     aLastWordDimensions CONTEXT_ARG_PASS);
368  
369  }
370  
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)
379  {
380      nsresult rv = NS_OK;
381      PRInt32 curBreak = 0;
382 @@ -623,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co
383  
384      PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
385  
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);
391  
392      curChar = text;
393  
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;
401 -    }
402 -
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;
412  
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]);
423          }
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);
433  
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
437          }
438      }
439  
440 - loser:
441 -    if (text)
442 -        g_free(text);
443 +    g_free(text);
444  
445      delete[] utf8Breaks;
446  
447      return rv;
448  }
449  
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
457 +
458 +typedef struct _nsPSPangoRenderer        nsPSPangoRenderer;
459 +typedef struct _nsPSPangoRendererClass   nsPSPangoRendererClass;
460 +
461 +struct _nsPSPangoRenderer
462  {
463 -    PangoLayout *layout = pango_layout_new(mPangoContext);
464 +  PangoRenderer parent_instance;
465 +  nsRenderingContextPS *psContext;
466 +  nsFontMetricsPSPango *psPangoFontMetrics;
467 +  float zoom;
468 +};
469  
470 -    pango_layout_set_text(layout, aString, aLength);
471 -    FixupSpaceWidths(layout, aString);
472 +struct _nsPSPangoRendererClass
473 +{
474 +  PangoRendererClass parent_class;
475 +};
476  
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))
485  
486 -    aContext->GetTranMatrix()->TransformCoord(&x, &y);
487 +G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
488  
489 -    PangoLayoutLine *line;
490 -    if (pango_layout_get_line_count(layout) != 1) {
491 -        printf("Warning: more than one line!\n");
492 -    }
493 -    line = pango_layout_get_line(layout, 0);
494 +static PangoRenderer *
495 +get_renderer (void)
496 +{
497 +  static PangoRenderer               *renderer = NULL;
498  
499 -    aContext->UpdateGC();
500 -    GdkGC *gc = aContext->GetGC();
501 +  if (!renderer)
502 +    renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
503  
504 -    if (aSpacing && *aSpacing) {
505 -        DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
506 -                         gc, x, y, line, aSpacing);
507 -    }
508 -    else {
509 -        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
510 -                             x, y,
511 -                             line);
512 -    }
513 +  return renderer;
514 +}
515  
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);
524  
525 -    //    printf("DrawString (char *)\n");
526 +static void
527 +_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
528 +{
529 +  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
530 +  
531 +  renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
532 +}
533  
534 -    return NS_OK;
535 +static void
536 +_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
537 +{
538 +}
539 +
540 +class nsPangoType1Generator : public nsPSFontGenerator {
541 +public:
542 +  nsPangoType1Generator();
543 +  ~nsPangoType1Generator();
544 +  nsresult Init(PangoFont *aFont);
545 +  void  GeneratePSFont(FILE* aFile);
546 +
547 +protected:
548 +  PangoFont *mFont;
549 +};
550 +
551 +nsPangoType1Generator::nsPangoType1Generator()
552 +{
553  }
554  
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)
563 +  {
564 +  NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
565 +  mFont = aFont;
566 +  g_object_ref (mFont);
567 +  return NS_OK;
568 +}
569 +
570 +nsPangoType1Generator::~nsPangoType1Generator()
571  {
572 -    nsresult rv = NS_OK;
573 -    int x = aX;
574 -    int y = aY;
575 +  g_object_unref (mFont);
576 +  mFont = nsnull;
577 +}
578  
579 -    aContext->UpdateGC();
580 -    GdkGC *gc = aContext->GetGC();
581 +void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
582 +{
583 +  FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
584  
585 -    PangoLayout *layout = pango_layout_new(mPangoContext);
586 +  if (face == nsnull)
587 +    return;
588  
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);
594  
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;
602 -    }
603 + pango_fc_font_unlock_face ((PangoFcFont *) mFont);
604 +}
605  
606 -    pango_layout_set_text(layout, text, strlen(text));
607 -    FixupSpaceWidths(layout, text);
608 +typedef struct
609 +{
610 +  nsCString    *FontNameBase;
611 +  nsCStringKey *key;
612 +  int           font_size;
613 +} PSPangoFontData;
614  
615 -    aContext->GetTranMatrix()->TransformCoord(&x, &y);
616 +static void
617 +ps_pango_font_data_destroy (PSPangoFontData *data)
618 +{
619 +  delete data->key;
620 +  delete data->FontNameBase;
621 +  g_free (data);
622 +}
623  
624 -    PangoLayoutLine *line;
625 -    if (pango_layout_get_line_count(layout) != 1) {
626 -        printf("Warning: more than one line!\n");
627 -    }
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)
635 +{
636 +  if (!glyphs->num_glyphs)
637 +    return;
638  
639 -    if (aSpacing && *aSpacing) {
640 -        DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
641 -                         gc, x, y, line, aSpacing);
642 -    }
643 -    else {
644 -        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
645 -                             x, y,
646 -                             line);
647 -    }
648 +  static GQuark data_quark = 0;
649 +  if (!data_quark)
650 +    data_quark = g_quark_from_static_string ("ps-pango-font-data");
651  
652 - loser:
653 +  PSPangoFontData *data;
654 +  if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
655 +    {
656 +      data = g_new (PSPangoFontData, 1);
657  
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;
670 +      }
671 +      pango_fc_font_unlock_face ((PangoFcFont *) font);
672  
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);
677 +
678 +      data->key = new nsCStringKey (*data->FontNameBase);
679 +
680 +      g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
681 +    }
682 +
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;
699 +    }
700 +    psFGList->Put(data->key, (void *) psFontGen);
701 +  }
702 +  nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
703 +
704 +  g_return_if_fail (aContext);
705 +  g_return_if_fail (psObj);
706 +
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);
710 +
711 +  PRInt32 currSubFont, prevSubFont = -1;
712 +  PRUint32 i;
713 +  PangoGlyphString gl;
714 +
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;
720 +
721 +    if (glyph != PANGO_GLYPH_EMPTY)
722 +      currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph);
723 +
724 +    if (prevSubFont != currSubFont) {
725 +      if (prevSubFont != -1)
726 +        psObj->show(&gl, ps_renderer->zoom,  psFontGen, prevSubFont);
727 +
728 +      psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
729 +      prevSubFont = currSubFont;
730 +      gl.glyphs = glyphs->glyphs + i;
731 +      gl.num_glyphs = 0;
732 +    }
733  
734 -    return rv;
735 +    gl.num_glyphs++;
736 +  }
737 +
738 +  if (prevSubFont != -1)
739 +    psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
740  }
741 +#endif
742 +
743 +static void
744 +draw_layout_line (int x, int y,
745 +                  PangoLayoutLine *line,
746 +                  nsFontMetricsPango *fm
747 +                  CONTEXT_AND_SURFACE_ARG_DEF)
748 +{
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();
756 +
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
766 +}
767 +
768  
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)
778  {
779 -    printf("GetBoundingMetrics (char *)\n");
780 -    return NS_ERROR_FAILURE;
781 +    int x = aX;
782 +    int y = aY;
783 +
784 +    aContext->GetTranMatrix()->TransformCoord(&x, &y);
785 +
786 +    PangoLayout *layout = GetLayout(aString, aLength);
787 +    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
788 +
789 +    ApplySpacing(aString, aLength, line, aSpacing);
790 +    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
791 +
792 +    g_object_unref(layout);
793 +
794 +    return NS_OK;
795  }
796  
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)
808  {
809 -    nsresult rv = NS_OK;
810 -    PangoLayout *layout = pango_layout_new(mPangoContext);
811 +    int x = aX;
812 +    int y = aY;
813  
814 -    gchar *text = g_utf16_to_utf8(aString, aLength,
815 -                                  NULL, NULL, NULL);
816 +    aContext->GetTranMatrix()->TransformCoord(&x, &y);
817  
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);
826  
827 -        rv = NS_ERROR_FAILURE;
828 -        goto loser;
829 -    }
830 +    ApplySpacing(aString, aLength, line, aSpacing);
831 +    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
832  
833 -    pango_layout_set_text(layout, text, -1);
834 -    FixupSpaceWidths(layout, text);
835 +    g_object_unref(layout);
836 +
837 +    return NS_OK;
838 +}
839  
840 -    PangoLayoutLine *line;
841 -    if (pango_layout_get_line_count(layout) != 1) {
842 -        printf("Warning: more than one line!\n");
843 -    }
844 -    line = pango_layout_get_line(layout, 0);
845 +
846 +#ifdef MOZ_MATHML
847 +void
848 +nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
849 +                                               nsBoundingMetrics &aBoundingMetrics
850 +                                               CONTEXT_ARG_DEF)
851 +{
852 +    PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
853  
854      // Get the ink and logical extents
855      PangoRectangle ink, logical;
856      pango_layout_line_get_extents(line, &ink, &logical);
857  
858 -    float P2T;
859 -    P2T = mDeviceContext->DevUnitsToAppUnits();
860 +    float P2T = mDeviceContext->DevUnitsToAppUnits();
861  
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);
867 +}
868  
869 - loser:
870 -    g_free(text);
871 +nsresult
872 +nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
873 +                                       nsBoundingMetrics &aBoundingMetrics
874 +                                       CONTEXT_ARG_DEF)
875 +{
876 +    PangoLayout *layout = GetLayout(aString, aLength);
877 +    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
878      g_object_unref(layout);
879  
880 -    return rv;
881 +   return NS_OK;
882 +}
883 +
884 +nsresult
885 +nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
886 +                                       PRUint32 aLength,
887 +                                       nsBoundingMetrics &aBoundingMetrics,
888 +                                       PRInt32 *aFontID
889 +                                       CONTEXT_ARG_DEF)
890 +{
891 +    PangoLayout *layout = GetLayout(aString, aLength);
892 +    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
893 +    g_object_unref(layout);
894 +
895 +    return NS_OK;
896  }
897  
898  #endif /* MOZ_MATHML */
899  
900 +#ifndef PSPANGO
901  GdkFont*
902  nsFontMetricsPango::GetCurrentGDKFont(void)
903  {
904      return nsnull;
905  }
906 +#endif
907  
908  nsresult
909  nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
910  {
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);
916 -
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);
920          }
921 @@ -899,34 +1087,18 @@ nsFontMetricsPango::GetClusterInfo(const
922                                     PRUint32 aLength,
923                                     PRUint8 *aClusterStarts)
924  {
925 -    nsresult rv = NS_OK;
926      PangoLogAttr *attrs = NULL;
927      gint n_attrs = 0;
928 -    PangoLayout *layout = pango_layout_new(mPangoContext);
929 -    
930 -    // Convert the incoming UTF-16 to UTF-8
931 -    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
932  
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;
940 -    }
941 -
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);
948  
949      // Convert back to UTF-16 while filling in the cluster info
950      // structure.
951 -    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
952 -
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++;
958          }
959          else {
960 @@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
961          }
962      }
963  
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);
972  
973 -    return rv;
974 +    return NS_OK;
975  }
976  
977  PRInt32
978 -nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
979 -                                nsPoint aPt)
980 +nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
981  {
982      int trailing = 0;
983      int inx = 0;
984 -    const gchar *curChar;
985      PRInt32 retval = 0;
986  
987      float f = mDeviceContext->AppUnitsToDevUnits();
988      
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);
992  
993 -    // Convert the incoming UTF-16 to UTF-8
994 -    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
995 -
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;
1003 -    }
1004 -
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);
1009      
1010      pango_layout_xy_to_index(layout, localX, localY,
1011                               &inx, &trailing);
1012  
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;
1017  
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)) {
1021  
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--;
1026      }
1027  
1028 - loser:
1029 -    if (text)
1030 -        g_free(text);
1031 -    if (layout)
1032 -        g_object_unref(layout);
1033 +    g_object_unref(layout);
1034  
1035 -    return retval;
1036 +    return retval; 
1037  }
1038  
1039  nsresult
1040 @@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const 
1041                                    PRUint32 aEnd,
1042                                    PRUint32 &aWidth)
1043  {
1044 -    nsresult rv = NS_OK;
1045      PRUint32 utf8Start = 0;
1046      PRUint32 utf8End = 0;
1047  
1048      aWidth = 0;
1049  
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;
1053  
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;
1061 -    }
1062 +    gchar* text;
1063 +    gint text_len;
1064 +    utf16_to_utf8 (aText, aLength, text, text_len);
1065 +    gchar *curChar = text;
1066  
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)) {
1071  
1072          if (curOffset == aStart)
1073              utf8Start = curChar - text;
1074 @@ -1057,15 +1196,13 @@ nsFontMetricsPango::GetRangeWidth(const 
1075  
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;
1080  
1081 -    rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
1082 +    GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth);
1083  
1084 - loser:
1085 -    if (text)
1086 -        g_free(text);
1087 +    g_free(text);
1088  
1089 -    return rv;
1090 +    return NS_OK;
1091  }
1092  
1093  nsresult
1094 @@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const 
1095                                    PRUint32 aEnd,
1096                                    PRUint32 &aWidth)
1097  {
1098 -    nsresult rv = NS_OK;
1099      int *ranges = NULL;
1100      int n_ranges = 0;
1101      float f;
1102  
1103      aWidth = 0;
1104  
1105 -    PangoLayout *layout = pango_layout_new(mPangoContext);
1106 -
1107 -    if (!aText) {
1108 -        rv = NS_ERROR_FAILURE;
1109 -        goto loser;
1110 -    }
1111 -
1112 -    pango_layout_set_text(layout, aText, aLength);
1113 -    FixupSpaceWidths(layout, aText);
1114 -
1115 -    PangoLayoutLine *line;
1116 -    if (pango_layout_get_line_count(layout) != 1) {
1117 -        printf("Warning: more than one line!\n");
1118 -    }
1119 -    line = pango_layout_get_line(layout, 0);
1120 +    PangoLayout *layout = GetLayout(aText, aLength);
1121 +    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
1122  
1123      pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
1124  
1125      aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
1126  
1127      f = mDeviceContext-> DevUnitsToAppUnits();
1128 -    aWidth = nscoord(aWidth * f / PANGO_SCALE);
1129 +    aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE);
1130  
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);
1138  
1139 -    return rv;
1140 +    return NS_OK;
1141  }
1142  
1143  /* static */
1144 @@ -1134,7 +1254,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi
1145      NS_ConvertUTF16toUTF8 name(aName);
1146  
1147      nsresult rv = NS_ERROR_FAILURE;
1148 -    PangoContext *context = gdk_pango_context_get();
1149 +    PangoContext *context = get_context();
1150      PangoFontFamily **familyList;
1151      int n;
1152  
1153 @@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
1154  
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;
1160  
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);
1164  
1165 -    // Set the color map so we can draw later.
1166 -    gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
1167 -
1168      // Set the pango language now that we have a context
1169      pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
1170  
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!
1175 + *
1176 + * To do it correctly (ligatures, etc) we need machinery that is private
1177 + * in Pango.  IMPORT IT:
1178 + */
1179 +
1180 +#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter
1181 +#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter
1182 +
1183 +#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
1184 +
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.
1190   */
1191 +typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
1192 +
1193 +struct _PangoGlyphItemIter
1194 +{
1195 +  PangoGlyphItem *glyph_item;
1196 +  const gchar *text;
1197 +  
1198 +  int start_glyph;
1199 +  int start_index;
1200 +  int start_char;
1201 +
1202 +  int end_glyph;
1203 +  int end_index;
1204 +  int end_char;
1205 +};
1206 +
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)
1218 +{
1219 +  int glyph_index = iter->end_glyph;
1220 +  PangoGlyphString *glyphs = iter->glyph_item->glyphs;
1221 +  PangoItem *item = iter->glyph_item->item;
1222 +
1223 +  if (LTR (iter->glyph_item))
1224 +    {
1225 +      if (glyph_index == glyphs->num_glyphs)
1226 +       return FALSE;
1227 +    }
1228 +  else
1229 +    {
1230 +      if (glyph_index < 0)
1231 +       return FALSE;
1232 +    }
1233 +      
1234 +  iter->start_glyph = iter->end_glyph;
1235 +  iter->start_index = iter->end_index;
1236 +  iter->start_char = iter->end_char;
1237 +  
1238 +  if (LTR (iter->glyph_item))
1239 +    {
1240 +      while (TRUE)
1241 +       {
1242 +         glyph_index++;
1243 +         
1244 +         if (glyph_index == glyphs->num_glyphs)
1245 +           {
1246 +             iter->end_index = item->offset + item->length;
1247 +             iter->end_char = item->num_chars;
1248 +             break;
1249 +           }
1250 +         
1251 +         if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1252 +           {
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; 
1257 +           }
1258 +       }
1259 +    }
1260 +  else                 /* RTL */
1261 +    {
1262 +      while (TRUE)
1263 +       {
1264 +         glyph_index--;
1265 +         
1266 +         if (glyph_index < 0)
1267 +           {
1268 +             iter->end_index = item->offset + item->length;
1269 +             iter->end_char = item->num_chars;
1270 +             break;
1271 +           }
1272 +         
1273 +         if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
1274 +           {
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; 
1279 +           }
1280 +       }
1281 +    }
1282 +
1283 +  iter->end_glyph = glyph_index;
1284 +  return TRUE;
1285 +}
1286 +
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)
1303 +{
1304 +  iter->glyph_item = glyph_item;
1305 +  iter->text = text;
1306 +  
1307 +  if (LTR (glyph_item))
1308 +    iter->end_glyph = 0;
1309 +  else
1310 +    iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
1311 +
1312 +  iter->end_index = glyph_item->item->offset;
1313 +  iter->end_char = 0;
1314 +
1315 +  /* Advance onto the first cluster of the glyph item */
1316 +  return _pango_glyph_item_iter_next_cluster (iter);
1317 +}
1318 +
1319  
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)
1328 -{
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)
1336 +{
1337 +    if (!(aSpacing && *aSpacing))
1338 +      return;
1339 +
1340 +    float app2dev = mDeviceContext->AppUnitsToDevUnits();
1341  
1342      /*
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.
1352       */
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;
1361 +
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))
1365 +        {
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;
1370 +
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];
1375 +
1376 +          clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE);
1377 +
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;
1382 +          }
1383 +            
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;
1390 +          }
1391  
1392 -    if (aOrigString) {
1393 -        const gchar *curChar = aText;
1394 -        bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
1395 -
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;
1406 +          }
1407 +          
1408 +#ifndef PSPANGO
1409 +          /* do some hinting for display */
1410 +
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;
1415 +          }
1416 +#endif
1417  
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;
1425 +            }
1426          }
1427      }
1428 -    else {
1429 -        memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
1430 -    }
1431 +}
1432  
1433 -    gint curRun = 0;
1434 +void
1435 +nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
1436 +                                 PRUint32 aLength,
1437 +                                 PangoLayoutLine *aLine,
1438 +                                 const nscoord *aSpacing)
1439 +{
1440 +    if (!(aSpacing && *aSpacing))
1441 +      return;
1442  
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;
1449  
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);
1459  
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;
1470 -        }
1471 +    const gchar *curChar = utf8Text + aLine->start_index;
1472  
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];
1479 +
1480 +        if (IS_HIGH_SURROGATE(aText[curOffset]))
1481 +            curOffset++;
1482      }
1483  
1484 -    gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
1485 +    ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing);
1486  
1487 -    delete[] utf8spacing;
1488 +    g_free (utf8spacing);
1489  }
1490  
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)
1500  {
1501      NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
1502  
1503 @@ -1410,7 +1716,7 @@ nsFontMetricsPango::GetTextDimensionsInt
1504              // All the characters should fit
1505              numChars = aLength - start;
1506              breakIndex = aNumBreaks - 1;
1507 -        } 
1508 +        }
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);
1518  
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
1532  }
1533  
1534  void
1535 -nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
1536 -                                      const char *aString)
1537 +nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
1538  {
1539 +    if (!mPangoSpaceWidth)
1540 +      return;
1541 +
1542 +    const char *aString = pango_layout_get_text (aLayout);
1543 +
1544 +    if (pango_layout_get_line_count(aLayout) != 1) {
1545 +        printf("Warning: more than one line!\n");
1546 +    }
1547      PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
1548  
1549      gint curRun = 0;
1550 @@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
1551      }
1552  }
1553  
1554 +PangoLayout*
1555 +nsFontMetricsPango::GetLayout (const PRUnichar* aText,
1556 +                               PRUint32         aLength)
1557 +{
1558 +  gchar* text;
1559 +  gint length;
1560 +  utf16_to_utf8 (aText, aLength, text, length);
1561 +
1562 +  PangoLayout *layout = pango_layout_new(mPangoContext);
1563 +  pango_layout_set_text (layout, text, length);
1564 +  FixupSpaceWidths (layout);
1565 +
1566 +  g_free ((gpointer) text);
1567 +
1568 +  return layout;
1569 +}
1570 +
1571 +PangoLayout*
1572 +nsFontMetricsPango::GetLayout (const gchar*     aText,
1573 +                               PRInt32          aLength)
1574 +{
1575 +  gboolean has_nul = FALSE;
1576 +  int i;
1577 +
1578 +  for (i = 0; i < aLength; i++)
1579 +    if (!aText[i]) {
1580 +      has_nul = TRUE;
1581 +      break;
1582 +    }
1583 +
1584 +  if (has_nul) {
1585 +    /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
1586 +
1587 +    char *p = (char *) g_memdup (aText, aLength);
1588 +
1589 +    /* don't need to reset i */
1590 +    for (; i < aLength; i++)
1591 +      if (!p[i])
1592 +        p[i] = (char) 0xff;
1593 +
1594 +    aText = p;
1595 +  }
1596 +
1597 +  PangoLayout *layout = pango_layout_new(mPangoContext);
1598 +  pango_layout_set_text (layout, aText, aLength);
1599 +  FixupSpaceWidths (layout);
1600 +
1601 +  if (has_nul)
1602 +    g_free ((gpointer) aText);
1603 +
1604 +  return layout;
1605 +}
1606 +
1607 +static void
1608 +utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
1609 +{
1610 +  gboolean need_copy = FALSE;
1611 +  int i;
1612 +
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;
1621 +    }
1622 +  }
1623 +
1624 +  if (need_copy) {
1625 +
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. */
1628 +
1629 +    PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0]));
1630 +
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;
1640 +      }
1641 +    }
1642 +
1643 +    aText = p;
1644 +  }
1645 +
1646 +  glong items_written;
1647 +  text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
1648 +  length = items_written;
1649 +
1650 +  if (need_copy)
1651 +    g_free ((gpointer) aText);
1652 +
1653 +}
1654 +
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 @@
1661   *
1662   * ***** END LICENSE BLOCK ***** */
1663  
1664 +
1665  #include "nsIFontMetrics.h"
1666  #include "nsIFontEnumerator.h"
1667  #include "nsCRT.h"
1668  #include "nsIAtom.h"
1669  #include "nsString.h"
1670  #include "nsVoidArray.h"
1671 +
1672 +#ifdef PSPANGO
1673 +#include "nsFontMetricsPS.h"
1674 +#else
1675  #include "nsIFontMetricsGTK.h"
1676 +#endif
1677  
1678  #include <pango/pango.h>
1679  
1680 -class nsFontMetricsPango : public nsIFontMetricsGTK
1681 +#ifdef PSPANGO
1682 +
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
1688 +
1689 +#else
1690 +
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
1696 +
1697 +#endif
1698 +
1699 +
1700 +#ifdef PSPANGO
1701 +
1702 +#define nsFontMetricsPango   nsFontMetricsPSPango
1703 +#define PSPANGO_PARENT_CLASS nsFontMetricsPS
1704 +
1705 +#else
1706 +
1707 +#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
1708 +
1709 +#endif
1710 +
1711 +class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
1712  {
1713  public:
1714      nsFontMetricsPango();
1715 @@ -136,20 +172,30 @@ public:
1716  
1717      PRInt32 GetMaxStringLength() { return mMaxStringLength; }
1718  
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)
1727  
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
1733 +
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);
1740 +
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);
1778  
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);
1788 +
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);
1797  
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 */
1814 -
1815 +#ifndef PSPANGO
1816      virtual GdkFont* GetCurrentGDKFont(void);
1817 -
1818 -    virtual nsresult SetRightToLeftText(PRBool aIsRTL);
1819 +#endif
1820      virtual PRBool GetRightToLeftText();
1821 -
1822 -    virtual nsresult GetClusterInfo(const PRUnichar *aText,
1823 +    NS_METHOD        SetRightToLeftText(PRBool aIsRTL);
1824 +    
1825 +    NS_METHOD        GetClusterInfo(const PRUnichar *aText,
1826                                      PRUint32 aLength,
1827                                      PRUint8 *aClusterStarts);
1828  
1829 @@ -206,32 +251,35 @@ public:
1830                                  PRUint32 aLength,
1831                                  nsPoint aPt);
1832  
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);
1839  
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);
1846  
1847      // get hints for the font
1848 -    static PRUint32    GetHints     (void);
1849 +#ifndef PSPANGO
1850 +    static
1851 +#endif
1852 +    PRUint32    GetHints     (void);
1853  
1854      // drawing surface methods
1855      static nsresult FamilyExists    (nsIDeviceContext *aDevice,
1856                                       const nsString &aName);
1857  
1858 +
1859  private:
1860  
1861      // generic font metrics class bits
1862      nsCStringArray       mFontList;
1863      nsAutoVoidArray      mFontIsGeneric;
1864  
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;
1872  
1873 +#ifndef PSPANGO
1874 +    nsIDeviceContext    *mDeviceContext; 
1875 +
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);
1890  
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);
1906  
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 */
1922 +
1923 +    void FixupSpaceWidths (PangoLayout *aLayout);
1924  
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);
1930  };
1931  
1932  class nsFontEnumeratorPango : public nsIFontEnumerator
This page took 2.190559 seconds and 3 git commands to generate.