Magellan Linux

Annotation of /trunk/mozilla-firefox/patches/mozilla-firefox-1.0.7-pango-render.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 153 - (hide annotations) (download)
Tue May 8 20:52:56 2007 UTC (17 years, 1 month ago) by niro
File size: 101086 byte(s)
-import

1 niro 153 --- mozilla/config/autoconf.mk.in.foo 2004-03-20 21:31:17.000000000 -0500
2     +++ mozilla/config/autoconf.mk.in 2004-10-18 22:49:40.000000000 -0400
3     @@ -376,6 +376,10 @@
4     MOZ_XFT_LIBS = @MOZ_XFT_LIBS@
5     MOZ_ENABLE_COREXFONTS = @MOZ_ENABLE_COREXFONTS@
6    
7     +MOZ_ENABLE_PANGO = @MOZ_ENABLE_PANGO@
8     +MOZ_PANGO_CFLAGS = @MOZ_PANGO_CFLAGS@
9     +MOZ_PANGO_LIBS = @MOZ_PANGO_LIBS@
10     +
11     MOZ_EXTRA_X11CONVERTERS = @MOZ_EXTRA_X11CONVERTERS@
12    
13     MOZ_ENABLE_XINERAMA = @MOZ_ENABLE_XINERAMA@
14     --- mozilla/gfx/src/gtk/nsGfxFactoryGTK.cpp.foo 2003-09-07 18:20:38.000000000 -0400
15     +++ mozilla/gfx/src/gtk/nsGfxFactoryGTK.cpp 2004-10-18 22:49:40.000000000 -0400
16     @@ -62,6 +62,9 @@
17     #ifdef NATIVE_THEME_SUPPORT
18     #include "nsNativeThemeGTK.h"
19     #endif
20     +#ifdef MOZ_ENABLE_PANGO
21     +#include "nsFontMetricsPango.h"
22     +#endif
23     #ifdef MOZ_ENABLE_XFT
24     #include "nsFontMetricsXft.h"
25     #endif
26     @@ -112,6 +115,13 @@
27     if (aOuter)
28     return NS_ERROR_NO_AGGREGATION;
29    
30     +#ifdef MOZ_ENABLE_PANGO
31     + if (NS_IsPangoEnabled()) {
32     + result = new nsFontMetricsPango();
33     + if (!result)
34     + return NS_ERROR_OUT_OF_MEMORY;
35     + } else {
36     +#endif
37     #ifdef MOZ_ENABLE_XFT
38     if (NS_IsXftEnabled()) {
39     result = new nsFontMetricsXft();
40     @@ -127,6 +137,9 @@
41     #ifdef MOZ_ENABLE_XFT
42     }
43     #endif
44     +#ifdef MOZ_ENABLE_PANGO
45     + }
46     +#endif
47    
48     NS_ADDREF(result);
49     nsresult rv = result->QueryInterface(aIID, aResult);
50     @@ -148,6 +161,13 @@
51     if (aOuter)
52     return NS_ERROR_NO_AGGREGATION;
53    
54     +#ifdef MOZ_ENABLE_PANGO
55     + if (NS_IsPangoEnabled()) {
56     + result = new nsFontEnumeratorPango();
57     + if (!result)
58     + return NS_ERROR_OUT_OF_MEMORY;
59     + } else {
60     +#endif
61     #ifdef MOZ_ENABLE_XFT
62     if (NS_IsXftEnabled()) {
63     result = new nsFontEnumeratorXft();
64     @@ -163,6 +183,9 @@
65     #ifdef MOZ_ENABLE_XFT
66     }
67     #endif
68     +#ifdef MOZ_ENABLE_PANGO
69     + }
70     +#endif
71    
72     NS_ADDREF(result);
73     nsresult rv = result->QueryInterface(aIID, aResult);
74     --- /dev/null 2004-02-18 10:26:44.000000000 -0500
75     +++ mozilla/gfx/src/gtk/mozilla-decoder.h 2004-10-18 22:49:40.000000000 -0400
76     @@ -0,0 +1,72 @@
77     +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
78     +/* vim:expandtab:shiftwidth=4:tabstop=4:
79     + */
80     +/* ***** BEGIN LICENSE BLOCK *****
81     + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
82     + *
83     + * The contents of this file are subject to the Mozilla Public License Version
84     + * 1.1 (the "License"); you may not use this file except in compliance with
85     + * the License. You may obtain a copy of the License at
86     + * http://www.mozilla.org/MPL/
87     + *
88     + * Software distributed under the License is distributed on an "AS IS" basis,
89     + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
90     + * for the specific language governing rights and limitations under the
91     + * License.
92     + *
93     + * The Original Code is mozilla.org code.
94     + *
95     + * The Initial Developer of the Original Code is Christopher Blizzard
96     + * <blizzard@mozilla.org>. Portions created by the Initial Developer
97     + * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
98     + *
99     + * Contributor(s):
100     + *
101     + * Alternatively, the contents of this file may be used under the terms of
102     + * either the GNU General Public License Version 2 or later (the "GPL"), or
103     + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
104     + * in which case the provisions of the GPL or the LGPL are applicable instead
105     + * of those above. If you wish to allow use of your version of this file only
106     + * under the terms of either the GPL or the LGPL, and not to allow others to
107     + * use your version of this file under the terms of the MPL, indicate your
108     + * decision by deleting the provisions above and replace them with the notice
109     + * and other provisions required by the GPL or the LGPL. If you do not delete
110     + * the provisions above, a recipient may use your version of this file under
111     + * the terms of any one of the MPL, the GPL or the LGPL.
112     + *
113     + * ***** END LICENSE BLOCK ***** */
114     +
115     +#ifndef _MOZILLA_DECODER_H
116     +#define _MOZILLA_DECODER_H
117     +
118     +#include <pango/pangofc-decoder.h>
119     +
120     +G_BEGIN_DECLS
121     +
122     +#define MOZILLA_TYPE_DECODER (mozilla_decoder_get_type())
123     +#define MOZILLA_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaDecoder))
124     +#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER))
125     +
126     +typedef struct _MozillaDecoder MozillaDecoder;
127     +typedef struct _MozillaDecoderClass MozillaDecoderClass;
128     +
129     +#define MOZILLA_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
130     +#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER))
131     +#define MOZILLA_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderClass))
132     +
133     +struct _MozillaDecoder
134     +{
135     + PangoFcDecoder parent_instance;
136     +};
137     +
138     +struct _MozillaDecoderClass
139     +{
140     + PangoFcDecoderClass parent_class;
141     +};
142     +
143     +GType mozilla_decoder_get_type (void);
144     +int mozilla_decoders_init (void);
145     +
146     +G_END_DECLS
147     +
148     +#endif /*_MOZILLA_DECODER_H */
149     --- /dev/null 2004-02-18 10:26:44.000000000 -0500
150     +++ mozilla/gfx/src/gtk/mozilla-decoder.cpp 2004-10-18 22:49:40.000000000 -0400
151     @@ -0,0 +1,376 @@
152     +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
153     +/* vim:expandtab:shiftwidth=4:tabstop=4:
154     + */
155     +/* ***** BEGIN LICENSE BLOCK *****
156     + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
157     + *
158     + * The contents of this file are subject to the Mozilla Public License Version
159     + * 1.1 (the "License"); you may not use this file except in compliance with
160     + * the License. You may obtain a copy of the License at
161     + * http://www.mozilla.org/MPL/
162     + *
163     + * Software distributed under the License is distributed on an "AS IS" basis,
164     + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
165     + * for the specific language governing rights and limitations under the
166     + * License.
167     + *
168     + * The Original Code is mozilla.org code.
169     + *
170     + * The Initial Developer of the Original Code is Christopher Blizzard
171     + * <blizzard@mozilla.org>. Portions created by the Initial Developer
172     + * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
173     + *
174     + * Contributor(s):
175     + *
176     + * Alternatively, the contents of this file may be used under the terms of
177     + * either the GNU General Public License Version 2 or later (the "GPL"), or
178     + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
179     + * in which case the provisions of the GPL or the LGPL are applicable instead
180     + * of those above. If you wish to allow use of your version of this file only
181     + * under the terms of either the GPL or the LGPL, and not to allow others to
182     + * use your version of this file under the terms of the MPL, indicate your
183     + * decision by deleting the provisions above and replace them with the notice
184     + * and other provisions required by the GPL or the LGPL. If you do not delete
185     + * the provisions above, a recipient may use your version of this file under
186     + * the terms of any one of the MPL, the GPL or the LGPL.
187     + *
188     + * ***** END LICENSE BLOCK ***** */
189     +
190     +#define PANGO_ENABLE_BACKEND
191     +#define PANGO_ENABLE_ENGINE
192     +
193     +#include "mozilla-decoder.h"
194     +#include <pango/pangoxft.h>
195     +#include <pango/pangofc-fontmap.h>
196     +#include <pango/pangofc-font.h>
197     +#include <gdk/gdkx.h>
198     +
199     +#include "nsString.h"
200     +#include "nsIPersistentProperties2.h"
201     +#include "nsNetUtil.h"
202     +#include "nsReadableUtils.h"
203     +#include "nsICharsetConverterManager.h"
204     +#include "nsICharRepresentable.h"
205     +#include "nsCompressedCharMap.h"
206     +
207     +#undef DEBUG_CUSTOM_ENCODER
208     +
209     +G_DEFINE_TYPE (MozillaDecoder, mozilla_decoder, PANGO_TYPE_FC_DECODER)
210     +
211     +MozillaDecoder *mozilla_decoder_new (void);
212     +
213     +static FcCharSet *mozilla_decoder_get_charset (PangoFcDecoder *decoder,
214     + PangoFcFont *fcfont);
215     +static PangoGlyph mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
216     + PangoFcFont *fcfont,
217     + guint32 wc);
218     +
219     +static PangoFcDecoder *mozilla_find_decoder (FcPattern *pattern,
220     + gpointer user_data);
221     +
222     +typedef struct _MozillaDecoderPrivate MozillaDecoderPrivate;
223     +
224     +#define MOZILLA_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaDecoderPrivate))
225     +
226     +struct _MozillaDecoderPrivate {
227     + char *family;
228     + char *encoder;
229     + char *cmap;
230     + gboolean is_wide;
231     + FcCharSet *charset;
232     + nsCOMPtr<nsIUnicodeEncoder> uEncoder;
233     +};
234     +
235     +static nsICharsetConverterManager *gCharsetManager = NULL;
236     +
237     +static NS_DEFINE_CID(kCharsetConverterManagerCID,
238     + NS_ICHARSETCONVERTERMANAGER_CID);
239     +
240     +// Hash tables that hold the custom encodings and custom cmaps used in
241     +// various fonts.
242     +GHashTable *encoder_hash = NULL;
243     +GHashTable *cmap_hash = NULL;
244     +GHashTable *wide_hash = NULL;
245     +
246     +void
247     +mozilla_decoder_init (MozillaDecoder *decoder)
248     +{
249     +}
250     +
251     +void
252     +mozilla_decoder_class_init (MozillaDecoderClass *klass)
253     +{
254     + GObjectClass *object_class = G_OBJECT_CLASS(klass);
255     + PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
256     +
257     + /* object_class->finalize = test_finalize; */
258     +
259     + parent_class->get_charset = mozilla_decoder_get_charset;
260     + parent_class->get_glyph = mozilla_decoder_get_glyph;
261     +
262     + g_type_class_add_private (object_class, sizeof (MozillaDecoderPrivate));
263     +}
264     +
265     +MozillaDecoder *
266     +mozilla_decoder_new(void)
267     +{
268     + return (MozillaDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
269     +}
270     +
271     +#ifdef DEBUG_CUSTOM_ENCODER
272     +void
273     +dump_hash(char *key, char *val, void *arg)
274     +{
275     + printf("%s -> %s\n", key, val);
276     +}
277     +#endif
278     +
279     +/**
280     + * mozilla_decoders_init:
281     + *
282     + * #mozilla_decoders_init:
283     + *
284     + * This initializes all of the application-specific custom decoders
285     + * that Mozilla uses. This should only be called once during the
286     + * lifetime of the application.
287     + *
288     + * Return value: zero on success, not zero on failure.
289     + *
290     + **/
291     +
292     +int
293     +mozilla_decoders_init(void)
294     +{
295     + static PRBool initialized = PR_FALSE;
296     + if (initialized)
297     + return 0;
298     +
299     + encoder_hash = g_hash_table_new(g_str_hash, g_str_equal);
300     + cmap_hash = g_hash_table_new(g_str_hash, g_str_equal);
301     + wide_hash = g_hash_table_new(g_str_hash, g_str_equal);
302     +
303     + PRBool dumb = PR_FALSE;
304     + nsCOMPtr<nsIPersistentProperties> props;
305     + nsCOMPtr<nsISimpleEnumerator> encodeEnum;
306     +
307     + NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
308     + NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
309     +
310     + if (!props)
311     + goto loser;
312     +
313     + // Enumerate the properties in this file and figure out all of the
314     + // fonts for which we have custom encodings.
315     + props->Enumerate(getter_AddRefs(encodeEnum));
316     + if (!encodeEnum)
317     + goto loser;
318     +
319     + while (encodeEnum->HasMoreElements(&dumb), dumb) {
320     + nsCOMPtr<nsIPropertyElement> prop;
321     + encodeEnum->GetNext(getter_AddRefs(prop));
322     + if (!prop)
323     + goto loser;
324     +
325     + nsCAutoString name;
326     + prop->GetKey(name);
327     + nsAutoString value;
328     + prop->GetValue(value);
329     +
330     + if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
331     + printf("string doesn't begin with encoding?\n");
332     + continue;
333     + }
334     +
335     + name = Substring(name, 9);
336     +
337     + if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
338     + name = Substring(name, 0, name.Length() - 4);
339     +
340     + // Strip off a .wide if it's there.
341     + if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) {
342     + g_hash_table_insert(wide_hash, g_strdup(name.get()),
343     + g_strdup("wide"));
344     + value = Substring(value, 0, name.Length() - 5);
345     + }
346     +
347     + g_hash_table_insert(encoder_hash,
348     + g_strdup(name.get()),
349     + g_strdup(NS_ConvertUTF16toUTF8(value).get()));
350     + }
351     + else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) {
352     + name = Substring(name, 0, name.Length() - 7);
353     + g_hash_table_insert(cmap_hash,
354     + g_strdup(name.get()),
355     + g_strdup(NS_ConvertUTF16toUTF8(value).get()));
356     + }
357     + else {
358     + printf("unknown suffix used for mapping\n");
359     + }
360     + }
361     +
362     + pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(pango_xft_get_font_map(GDK_DISPLAY(),gdk_x11_get_default_screen())),
363     + mozilla_find_decoder,
364     + NULL,
365     + NULL);
366     +
367     + initialized = PR_TRUE;
368     +
369     +#ifdef DEBUG_CUSTOM_ENCODER
370     + printf("*** encoders\n");
371     + g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
372     +
373     + printf("*** cmaps\n");
374     + g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
375     +#endif
376     +
377     + return 0;
378     +
379     + loser:
380     + return -1;
381     +}
382     +
383     +FcCharSet *
384     +mozilla_decoder_get_charset (PangoFcDecoder *decoder,
385     + PangoFcFont *fcfont)
386     +{
387     + MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
388     +
389     + if (priv->charset)
390     + return priv->charset;
391     +
392     + // First time this has been accessed. Populate the charset.
393     + priv->charset = FcCharSetCreate();
394     +
395     + if (!gCharsetManager) {
396     + nsServiceManager::GetService(kCharsetConverterManagerCID,
397     + NS_GET_IID(nsICharsetConverterManager), (nsISupports**)&gCharsetManager);
398     + }
399     +
400     + nsCOMPtr<nsIUnicodeEncoder> encoder;
401     + nsCOMPtr<nsICharRepresentable> represent;
402     +
403     + if (!gCharsetManager)
404     + goto end;
405     +
406     + gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
407     + if (!encoder)
408     + goto end;
409     +
410     + encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
411     +
412     + priv->uEncoder = encoder;
413     +
414     + represent = do_QueryInterface(encoder);
415     + if (!represent)
416     + goto end;
417     +
418     + PRUint32 map[UCS2_MAP_LEN];
419     + memset(map, 0, sizeof(map));
420     +
421     + represent->FillInfo(map);
422     +
423     + for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
424     + if (IS_REPRESENTABLE(map, i))
425     + FcCharSetAddChar(priv->charset, i);
426     + }
427     +
428     + end:
429     + return priv->charset;
430     +}
431     +
432     +PangoGlyph
433     +mozilla_decoder_get_glyph (PangoFcDecoder *decoder,
434     + PangoFcFont *fcfont,
435     + guint32 wc)
436     +{
437     + MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
438     +
439     + PangoGlyph retval = 0;
440     + PRUnichar inchar = wc;
441     + PRInt32 inlen = 1;
442     + char outchar[2] = {0,0};
443     + PRInt32 outlen = 2;
444     +
445     + priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
446     + if (outlen != 1) {
447     + printf("Warning: mozilla_decoder_get_glyph doesn't support more than one character conversions.\n");
448     + return 0;
449     + }
450     +
451     + FT_Face face = pango_fc_font_lock_face(fcfont);
452     +
453     +#ifdef DEBUG_CUSTOM_ENCODER
454     + char *filename;
455     + FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
456     + printf("filename is %s\n", filename);
457     +#endif
458     +
459     + // Make sure to set the right charmap before trying to get the
460     + // glyph
461     + if (priv->cmap) {
462     + if (!strcmp(priv->cmap, "mac_roman")) {
463     + FT_Select_Charmap(face, ft_encoding_apple_roman);
464     + }
465     + else if (!strcmp(priv->cmap, "unicode")) {
466     + FT_Select_Charmap(face, ft_encoding_unicode);
467     + }
468     + else {
469     + printf("Warning: Invalid charmap entry for family %s\n",
470     + priv->family);
471     + }
472     + }
473     +
474     + // Standard 8 bit to glyph translation
475     + if (!priv->is_wide) {
476     + FcChar32 blah = PRUint8(outchar[0]);
477     + retval = FT_Get_Char_Index(face, blah);
478     +#ifdef DEBUG_CUSTOM_ENCODER
479     + printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n",
480     + wc, outchar[0], blah, retval, (void *)face);
481     +#endif
482     + }
483     + else {
484     + printf("Warning: We don't support .wide fonts!\n");
485     + retval = 0;
486     + }
487     +
488     + pango_fc_font_unlock_face(fcfont);
489     +
490     + return retval;
491     +}
492     +
493     +PangoFcDecoder *
494     +mozilla_find_decoder (FcPattern *pattern, gpointer user_data)
495     +{
496     + // Compare the family name of the font that's been opened to see
497     + // if we have a custom decoder.
498     + const char *orig = NULL;
499     + FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig);
500     +
501     + nsCAutoString family;
502     + family.Assign(orig);
503     +
504     + family.StripWhitespace();
505     + ToLowerCase(family);
506     +
507     + char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
508     + if (!encoder)
509     + return NULL;
510     +
511     + MozillaDecoder *decoder = mozilla_decoder_new();
512     +
513     + MozillaDecoderPrivate *priv = MOZILLA_DECODER_GET_PRIVATE(decoder);
514     +
515     + priv->family = g_strdup(family.get());
516     + priv->encoder = g_strdup(encoder);
517     +
518     + char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
519     + if (cmap)
520     + priv->cmap = g_strdup(cmap);
521     +
522     + char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
523     + if (wide)
524     + priv->is_wide = TRUE;
525     +
526     + return PANGO_FC_DECODER(decoder);
527     +}
528     --- mozilla/gfx/src/gtk/gfxgtk.pkg.foo 2004-01-06 20:21:35.000000000 -0500
529     +++ mozilla/gfx/src/gtk/gfxgtk.pkg 2004-10-18 22:49:40.000000000 -0400
530     @@ -7,3 +7,6 @@
531     #if MOZ_ENABLE_XFT
532     dist/bin/res/fonts/fontEncoding.properties
533     #endif
534     +#if MOZ_ENABLE_PANGO
535     +dist/bin/res/fonts/pangoFontEncoding.properties
536     +#endif
537     --- mozilla/gfx/src/gtk/nsFontMetricsXft.cpp.foo 2004-04-05 15:18:43.000000000 -0400
538     +++ mozilla/gfx/src/gtk/nsFontMetricsXft.cpp 2004-10-18 22:49:40.000000000 -0400
539     @@ -238,7 +238,7 @@
540    
541     static int CalculateSlant (PRUint8 aStyle);
542     static int CalculateWeight (PRUint16 aWeight);
543     -static void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
544     +/* static */ void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
545     static void AddFFRE (FcPattern *aPattern, nsCString *aFamily,
546     PRBool aWeak);
547     static void FFREToFamily (nsACString &aFFREName, nsACString &oFamily);
548     @@ -449,7 +449,7 @@
549     // Make sure that the pixel size is at least greater than zero
550     if (mPixelSize < 1) {
551     #ifdef DEBUG
552     - printf("*** Warning: nsFontMetricsXft was passed a pixel size of %d\n",
553     + printf("*** Warning: nsFontMetricsXft was passed a pixel size of %f\n",
554     mPixelSize);
555     #endif
556     mPixelSize = 1;
557     @@ -474,6 +474,26 @@
558     if (NS_FAILED(RealizeFont()))
559     return NS_ERROR_FAILURE;
560    
561     +#ifdef DEBUG_foo
562     + printf("%i\n", mXHeight);
563     + printf("%i\n", mSuperscriptOffset);
564     + printf("%i\n", mSubscriptOffset);
565     + printf("%i\n", mStrikeoutOffset);
566     + printf("%i\n", mStrikeoutSize);
567     + printf("%i\n", mUnderlineOffset);
568     + printf("%i\n", mUnderlineSize);
569     + printf("%i\n", mMaxHeight);
570     + printf("%i\n", mLeading);
571     + printf("%i\n", mEmHeight);
572     + printf("%i\n", mEmAscent);
573     + printf("%i\n", mEmDescent);
574     + printf("%i\n", mMaxAscent);
575     + printf("%i\n", mMaxDescent);
576     + printf("%i\n", mMaxAdvance);
577     + printf("%i\n", mSpaceWidth);
578     + printf("%i\n", mAveCharWidth);
579     +#endif /* DEBUG_foo */
580     +
581     return NS_OK;
582     }
583    
584     @@ -530,6 +550,10 @@
585     f = mDeviceContext->DevUnitsToAppUnits();
586     aWidth = NSToCoordRound(glyphInfo.xOff * f);
587    
588     +#ifdef DEBUG_foo
589     + printf("GetWidth (char *) %d\n", aWidth);
590     +#endif
591     +
592     return NS_OK;
593     }
594    
595     @@ -553,6 +577,10 @@
596     if (aFontID)
597     *aFontID = 0;
598    
599     +#ifdef DEBUG_foo
600     + printf("GetWidth %d\n", aWidth);
601     +#endif
602     +
603     return NS_OK;
604     }
605    
606     @@ -586,6 +614,11 @@
607     if (nsnull != aFontID)
608     *aFontID = 0;
609    
610     +#ifdef DEBUG_foo
611     + printf("GetTextDimensions %d %d %d\n", aDimensions.width,
612     + aDimensions.ascent, aDimensions.descent);
613     +#endif
614     +
615     return NS_OK;
616     }
617    
618     @@ -645,6 +678,10 @@
619     nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
620     data.drawBuffer = &drawBuffer;
621    
622     +#ifdef DEBUG_foo
623     + printf("DrawString (char *)\n");
624     +#endif
625     +
626     return EnumerateGlyphs(aString, aLength,
627     &nsFontMetricsXft::DrawStringCallback, &data);
628     }
629     @@ -675,6 +712,10 @@
630     nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
631     data.drawBuffer = &drawBuffer;
632    
633     +#ifdef DEBUG_foo
634     + printf("DrawString\n");
635     +#endif
636     +
637     return EnumerateGlyphs(aString, aLength,
638     &nsFontMetricsXft::DrawStringCallback, &data);
639     }
640     @@ -714,6 +755,15 @@
641     aBoundingMetrics.ascent = NSToCoordRound(aBoundingMetrics.ascent * P2T);
642     aBoundingMetrics.descent = NSToCoordRound(aBoundingMetrics.descent * P2T);
643    
644     +#ifdef DEBUG_foo
645     + printf("GetBoundingMetrics (char *)%d %d %d %d %d\n",
646     + aBoundingMetrics.leftBearing,
647     + aBoundingMetrics.rightBearing,
648     + aBoundingMetrics.width,
649     + aBoundingMetrics.ascent,
650     + aBoundingMetrics.descent);
651     +#endif
652     +
653     return NS_OK;
654     }
655    
656     @@ -755,6 +805,15 @@
657     if (nsnull != aFontID)
658     *aFontID = 0;
659    
660     +#ifdef DEBUG_foo
661     + printf("GetBoundingMetrics %d %d %d %d %d\n",
662     + aBoundingMetrics.leftBearing,
663     + aBoundingMetrics.rightBearing,
664     + aBoundingMetrics.width,
665     + aBoundingMetrics.ascent,
666     + aBoundingMetrics.descent);
667     +#endif
668     +
669     return NS_OK;
670     }
671    
672     @@ -766,6 +825,12 @@
673     return nsnull;
674     }
675    
676     +nsresult
677     +nsFontMetricsXft::SetRightToLeftText(PRBool aIsRTL)
678     +{
679     + return NS_OK;
680     +}
681     +
682     PRUint32
683     nsFontMetricsXft::GetHints(void)
684     {
685     --- mozilla/gfx/src/gtk/Makefile.in.foo 2003-11-10 07:24:51.000000000 -0500
686     +++ mozilla/gfx/src/gtk/Makefile.in 2004-10-18 22:51:01.000000000 -0400
687     @@ -102,6 +102,12 @@
688     nsFontMetricsXft.cpp
689     endif
690    
691     +ifdef MOZ_ENABLE_PANGO
692     +CPPSRCS += \
693     + nsFontMetricsPango.cpp \
694     + mozilla-decoder.cpp
695     +endif
696     +
697     ifdef MOZ_ENABLE_GTK
698     CPPSRCS += \
699     nsRegionGTK.cpp \
700     @@ -155,10 +161,10 @@
701     endif
702    
703     ifdef MOZ_ENABLE_XFT
704     -libs:: fontEncoding.properties
705     +libs:: fontEncoding.properties pangoFontEncoding.properties
706     $(INSTALL) $^ $(DIST)/bin/res/fonts
707    
708     -install:: fontEncoding.properties
709     +install:: fontEncoding.properties pangoFontEncoding.properties
710     $(SYSINSTALL) $(IFLAGS1) $^ $(DESTDIR)$(mozappdir)/res/fonts
711     endif
712    
713     --- /dev/null 2004-02-18 10:26:44.000000000 -0500
714     +++ mozilla/gfx/src/gtk/pangoFontEncoding.properties 2004-10-18 22:49:40.000000000 -0400
715     @@ -0,0 +1,120 @@
716     +# ***** BEGIN LICENSE BLOCK *****
717     +# Version: MPL 1.1/GPL 2.0/LGPL 2.1
718     +#
719     +# The contents of this file are subject to the Mozilla Public License Version
720     +# 1.1 (the "License"); you may not use this file except in compliance with
721     +# the License. You may obtain a copy of the License at
722     +# http://www.mozilla.org/MPL/
723     +#
724     +# Software distributed under the License is distributed on an "AS IS" basis,
725     +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
726     +# for the specific language governing rights and limitations under the
727     +# License.
728     +#
729     +# The Original Code is Mozilla MathML Project.
730     +#
731     +# The Initial Developer of the Original Code is
732     +# The University of Queensland.
733     +# Portions created by the Initial Developer are Copyright (C) 2001
734     +# the Initial Developer. All Rights Reserved.
735     +#
736     +# Contributor(s):
737     +# Roger B. Sidje <rbs@maths.uq.edu.au>
738     +# Jungshik Shin <jshin@mailaps.org>
739     +# Christopher Blizzard <blizzard@mozilla.org>
740     +#
741     +# Alternatively, the contents of this file may be used under the terms of
742     +# either the GNU General Public License Version 2 or later (the "GPL"), or
743     +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
744     +# in which case the provisions of the GPL or the LGPL are applicable instead
745     +# of those above. If you wish to allow use of your version of this file only
746     +# under the terms of either the GPL or the LGPL, and not to allow others to
747     +# use your version of this file under the terms of the MPL, indicate your
748     +# decision by deleting the provisions above and replace them with the notice
749     +# and other provisions required by the GPL or the LGPL. If you do not delete
750     +# the provisions above, a recipient may use your version of this file under
751     +# the terms of any one of the MPL, the GPL or the LGPL.
752     +#
753     +# ***** END LICENSE BLOCK *****
754     +
755     +# LOCALIZATION NOTE: FILE
756     +# Do not translate anything in this file
757     +
758     +# This file contains supported custom encodings for pango font
759     +# rendering. For information about the specific encodings, look at
760     +# fontEncoding.properties. It contains a lot more verbiage than you
761     +# will find here. There are a lot of encodings supported in the old
762     +# encoding file that pango supports directly, so there should be
763     +# little reason to use those custom encodings. The pango custom code
764     +# doesn't support .wide fonts, so consider yourself warned!
765     +#
766     +
767     +# To be honest, we basically support mathml and that's about it.
768     +
769     +encoding.cmr10.ttf = x-ttf-cmr
770     +encoding.cmmi10.ttf = x-ttf-cmmi
771     +encoding.cmsy10.ttf = x-ttf-cmsy
772     +encoding.cmex10.ttf = x-ttf-cmex
773     +
774     +encoding.cmr10.ftcmap = unicode
775     +encoding.cmmi10.ftcmap = unicode
776     +encoding.cmsy10.ftcmap = unicode
777     +encoding.cmex10.ftcmap = unicode
778     +
779     +encoding.math1.ttf = x-mathematica1
780     +encoding.math1-bold.ttf = x-mathematica1
781     +encoding.math1mono.ttf = x-mathematica1
782     +encoding.math1mono-bold.ttf = x-mathematica1
783     +
784     +encoding.math2.ttf = x-mathematica2
785     +encoding.math2-bold.ttf = x-mathematica2
786     +encoding.math2mono.ttf = x-mathematica2
787     +encoding.math2mono-bold.ttf = x-mathematica2
788     +
789     +encoding.math3.ttf = x-mathematica3
790     +encoding.math3-bold.ttf = x-mathematica3
791     +encoding.math3mono.ttf = x-mathematica3
792     +encoding.math3mono-bold.ttf = x-mathematica3
793     +
794     +encoding.math4.ttf = x-mathematica4
795     +encoding.math4-bold.ttf = x-mathematica4
796     +encoding.math4mono.ttf = x-mathematica4
797     +encoding.math4mono-bold.ttf = x-mathematica4
798     +
799     +encoding.math5.ttf = x-mathematica5
800     +encoding.math5-bold.ttf = x-mathematica5
801     +encoding.math5bold.ttf = x-mathematica5
802     +encoding.math5mono.ttf = x-mathematica5
803     +encoding.math5mono-bold.ttf = x-mathematica5
804     +encoding.math5monobold.ttf = x-mathematica5
805     +
806     +encoding.math1.ftcmap = mac_roman
807     +encoding.math1-bold.ftcmap = mac_roman
808     +encoding.math1mono.ftcmap = mac_roman
809     +encoding.math1mono-bold.ftcmap = mac_roman
810     +
811     +encoding.math2.ftcmap = mac_roman
812     +encoding.math2-bold.ftcmap = mac_roman
813     +encoding.math2mono.ftcmap = mac_roman
814     +encoding.math2mono-bold.ftcmap = mac_roman
815     +
816     +encoding.math3.ftcmap = mac_roman
817     +encoding.math3-bold.ftcmap = mac_roman
818     +encoding.math3mono.ftcmap = mac_roman
819     +encoding.math3mono-bold.ftcmap = mac_roman
820     +
821     +encoding.math4.ftcmap = mac_roman
822     +encoding.math4-bold.ftcmap = mac_roman
823     +encoding.math4mono.ftcmap = mac_roman
824     +encoding.math4mono-bold.ftcmap = mac_roman
825     +
826     +encoding.math5.ftcmap = mac_roman
827     +encoding.math5-bold.ftcmap = mac_roman
828     +encoding.math5bold.ftcmap = mac_roman
829     +encoding.math5mono.ftcmap = mac_roman
830     +encoding.math5mono-bold.ftcmap = mac_roman
831     +encoding.math5monobold.ftcmap = mac_roman
832     +
833     +encoding.mtextra.ttf = x-mtextra
834     +encoding.mtextra.ftcmap = mac_roman
835     +
836     --- mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp.foo 2002-10-11 22:03:32.000000000 -0400
837     +++ mozilla/gfx/src/gtk/nsFontMetricsUtils.cpp 2004-10-18 22:51:32.000000000 -0400
838     @@ -50,11 +50,20 @@
839     #include "nsFontMetricsGTK.h"
840     #endif
841    
842     +#ifdef MOZ_ENABLE_PANGO
843     +#include "nsFontMetricsPango.h"
844     +#endif
845     +
846     #include "nsFontMetricsUtils.h"
847    
848     PRUint32
849     NS_FontMetricsGetHints(void)
850     {
851     +#ifdef MOZ_ENABLE_PANGO
852     + if (NS_IsPangoEnabled()) {
853     + return nsFontMetricsPango::GetHints();
854     + }
855     +#endif
856     #ifdef MOZ_ENABLE_XFT
857     if (NS_IsXftEnabled()) {
858     return nsFontMetricsXft::GetHints();
859     @@ -69,6 +78,11 @@
860     nsresult
861     NS_FontMetricsFamilyExists(nsIDeviceContext *aDevice, const nsString &aName)
862     {
863     +#ifdef MOZ_ENABLE_PANGO
864     + if (NS_IsPangoEnabled()) {
865     + return nsFontMetricsPango::FamilyExists(aDevice, aName);
866     + }
867     +#endif
868     #ifdef MOZ_ENABLE_XFT
869     // try to fall through to the core fonts if xft fails
870     if (NS_IsXftEnabled()) {
871     @@ -121,3 +135,17 @@
872     }
873    
874     #endif /* MOZ_ENABLE_XFT */
875     +
876     +#ifdef MOZ_ENABLE_PANGO
877     +
878     +PRBool
879     +NS_IsPangoEnabled(void)
880     +{
881     + char *val = PR_GetEnv("MOZ_ENABLE_PANGO");
882     + if (val)
883     + return TRUE;
884     +
885     + return FALSE;
886     +}
887     +
888     +#endif
889     --- /dev/null 2004-02-18 10:26:44.000000000 -0500
890     +++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 2004-10-18 22:49:40.000000000 -0400
891     @@ -0,0 +1,1662 @@
892     +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
893     +/* vim:expandtab:shiftwidth=4:tabstop=4:
894     + */
895     +/* ***** BEGIN LICENSE BLOCK *****
896     + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
897     + *
898     + * The contents of this file are subject to the Mozilla Public License Version
899     + * 1.1 (the "License"); you may not use this file except in compliance with
900     + * the License. You may obtain a copy of the License at
901     + * http://www.mozilla.org/MPL/
902     + *
903     + * Software distributed under the License is distributed on an "AS IS" basis,
904     + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
905     + * for the specific language governing rights and limitations under the
906     + * License.
907     + *
908     + * The Original Code is mozilla.org code.
909     + *
910     + * The Initial Developer of the Original Code is Christopher Blizzard
911     + * <blizzard@mozilla.org>. Portions created by the Initial Developer
912     + * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
913     + *
914     + * Contributor(s):
915     + *
916     + * Alternatively, the contents of this file may be used under the terms of
917     + * either the GNU General Public License Version 2 or later (the "GPL"), or
918     + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
919     + * in which case the provisions of the GPL or the LGPL are applicable instead
920     + * of those above. If you wish to allow use of your version of this file only
921     + * under the terms of either the GPL or the LGPL, and not to allow others to
922     + * use your version of this file under the terms of the MPL, indicate your
923     + * decision by deleting the provisions above and replace them with the notice
924     + * and other provisions required by the GPL or the LGPL. If you do not delete
925     + * the provisions above, a recipient may use your version of this file under
926     + * the terms of any one of the MPL, the GPL or the LGPL.
927     + *
928     + * ***** END LICENSE BLOCK ***** */
929     +
930     +#include "nsFont.h"
931     +#include "nsIDeviceContext.h"
932     +#include "nsICharsetConverterManager.h"
933     +#include "nsIPref.h"
934     +#include "nsIServiceManagerUtils.h"
935     +
936     +#define PANGO_ENABLE_BACKEND
937     +#define PANGO_ENABLE_ENGINE
938     +
939     +#include "nsFontMetricsPango.h"
940     +#include "nsRenderingContextGTK.h"
941     +#include "nsDeviceContextGTK.h"
942     +
943     +#include "nsUnicharUtils.h"
944     +#include "nsQuickSort.h"
945     +
946     +#include <pango/pangoxft.h>
947     +#include <fontconfig/fontconfig.h>
948     +#include <gdk/gdk.h>
949     +#include <gdk/gdkx.h>
950     +#include <freetype/tttables.h>
951     +
952     +#include "mozilla-decoder.h"
953     +
954     +#define FORCE_PR_LOG
955     +#include "prlog.h"
956     +
957     +// Globals
958     +
959     +static PRLogModuleInfo *gPangoFontLog;
960     +static int gNumInstances;
961     +
962     +// Defines
963     +
964     +// This is the scaling factor that we keep fonts limited to against
965     +// the display size. If a pixel size is requested that is more than
966     +// this factor larger than the height of the display, it's clamped to
967     +// that value instead of the requested size.
968     +#define FONT_MAX_FONT_SCALE 2
969     +
970     +static NS_DEFINE_CID(kCharsetConverterManagerCID,
971     + NS_ICHARSETCONVERTERMANAGER_CID);
972     +
973     +struct MozPangoLangGroup {
974     + const char *mozLangGroup;
975     + const char *PangoLang;
976     +};
977     +
978     +static const MozPangoLangGroup MozPangoLangGroups[] = {
979     + { "x-western", "en" },
980     + { "x-central-euro", "pl" },
981     + { "x-cyrillic", "ru" },
982     + { "x-baltic", "lv" },
983     + { "x-devanagari", "hi" },
984     + { "x-tamil", "ta" },
985     + { "x-unicode", 0 },
986     + { "x-user-def", 0 },
987     +};
988     +
989     +#define NUM_PANGO_LANG_GROUPS (sizeof (MozPangoLangGroups) / \
990     + sizeof (MozPangoLangGroups[0]))
991     +
992     +#ifdef DEBUG
993     +#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \
994     + printf("0x%x ", ustr[llen]); \
995     + printf("\n");
996     +#endif
997     +
998     +// rounding and truncation functions for a Freetype floating point number
999     +// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
1000     +// part and low 6 bits for the fractional part.
1001     +#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
1002     +#define MOZ_FT_TRUNC(x) ((x) >> 6)
1003     +#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
1004     + MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
1005     +
1006     +// Static function decls
1007     +
1008     +static PRBool IsASCIIFontName (const nsString& aName);
1009     +static int FFRECountHyphens (nsACString &aFFREName);
1010     +
1011     +static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup);
1012     +static const MozPangoLangGroup* FindPangoLangGroup (nsACString &aLangGroup);
1013     +
1014     +static void FreeGlobals (void);
1015     +
1016     +static PangoStyle CalculateStyle (PRUint8 aStyle);
1017     +static PangoWeight CalculateWeight (PRUint16 aWeight);
1018     +
1019     +static nsresult EnumFontsPango (nsIAtom* aLangGroup, const char* aGeneric,
1020     + PRUint32* aCount, PRUnichar*** aResult);
1021     +static int CompareFontNames (const void* aArg1, const void* aArg2,
1022     + void* aClosure);
1023     +
1024     +extern void AddLangGroup (FcPattern *aPattern, nsIAtom *aLangGroup);
1025     +
1026     +nsFontMetricsPango::nsFontMetricsPango()
1027     +{
1028     + if (!gPangoFontLog)
1029     + gPangoFontLog = PR_NewLogModule("PangoFont");
1030     +
1031     + gNumInstances++;
1032     +
1033     + mPangoFontDesc = nsnull;
1034     + mPangoContext = nsnull;
1035     + mLTRPangoContext = nsnull;
1036     + mRTLPangoContext = nsnull;
1037     + mPangoAttrList = nsnull;
1038     + mIsRTL = PR_FALSE;
1039     +
1040     + static PRBool initialized = PR_FALSE;
1041     + if (initialized)
1042     + return;
1043     +
1044     + // Initialized the custom decoders
1045     + if (!mozilla_decoders_init())
1046     + initialized = PR_TRUE;
1047     +}
1048     +
1049     +nsFontMetricsPango::~nsFontMetricsPango()
1050     +{
1051     + delete mFont;
1052     +
1053     + if (mDeviceContext)
1054     + mDeviceContext->FontMetricsDeleted(this);
1055     +
1056     + if (mPangoFontDesc)
1057     + pango_font_description_free(mPangoFontDesc);
1058     +
1059     + if (mLTRPangoContext)
1060     + g_object_unref(mLTRPangoContext);
1061     +
1062     + if (mRTLPangoContext)
1063     + g_object_unref(mRTLPangoContext);
1064     +
1065     + if (mPangoAttrList)
1066     + pango_attr_list_unref(mPangoAttrList);
1067     +
1068     + // XXX clean up all the pango objects
1069     +
1070     + if (--gNumInstances == 0)
1071     + FreeGlobals();
1072     +}
1073     +
1074     +
1075     +NS_IMPL_ISUPPORTS1(nsFontMetricsPango, nsIFontMetrics)
1076     +
1077     +// nsIFontMetrics impl
1078     +
1079     +NS_IMETHODIMP
1080     +nsFontMetricsPango::Init(const nsFont& aFont, nsIAtom* aLangGroup,
1081     + nsIDeviceContext *aContext)
1082     +{
1083     + mFont = new nsFont(aFont);
1084     + mLangGroup = aLangGroup;
1085     +
1086     + // Hang on to the device context
1087     + mDeviceContext = aContext;
1088     +
1089     + mPointSize = NSTwipsToFloatPoints(mFont->size);
1090     +
1091     + // Make sure to clamp the pixel size to something reasonable so we
1092     + // don't make the X server blow up.
1093     + nscoord screenPixels = gdk_screen_height();
1094     + mPointSize = PR_MIN(screenPixels * FONT_MAX_FONT_SCALE, mPointSize);
1095     +
1096     + // enumerate over the font names passed in
1097     + mFont->EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
1098     +
1099     + nsCOMPtr<nsIPref> prefService;
1100     + prefService = do_GetService(NS_PREF_CONTRACTID);
1101     + if (!prefService)
1102     + return NS_ERROR_FAILURE;
1103     +
1104     + nsXPIDLCString value;
1105     +
1106     + // Set up the default font name if it's not set
1107     + if (!mGenericFont) {
1108     + prefService->CopyCharPref("font.default", getter_Copies(value));
1109     +
1110     + if (value.get())
1111     + mDefaultFont = value.get();
1112     + else
1113     + mDefaultFont = "serif";
1114     +
1115     + mGenericFont = &mDefaultFont;
1116     + }
1117     +
1118     + // set up the minimum sizes for fonts
1119     + if (mLangGroup) {
1120     + nsCAutoString name("font.min-size.");
1121     +
1122     + if (mGenericFont->Equals("monospace"))
1123     + name.Append("fixed");
1124     + else
1125     + name.Append("variable");
1126     +
1127     + name.Append(char('.'));
1128     +
1129     + const char* langGroup;
1130     + mLangGroup->GetUTF8String(&langGroup);
1131     +
1132     + name.Append(langGroup);
1133     +
1134     + PRInt32 minimumInt = 0;
1135     + float minimum;
1136     + nsresult res;
1137     + res = prefService->GetIntPref(name.get(), &minimumInt);
1138     + if (NS_FAILED(res))
1139     + prefService->GetDefaultIntPref(name.get(), &minimumInt);
1140     +
1141     + if (minimumInt < 0)
1142     + minimumInt = 0;
1143     +
1144     + minimum = minimumInt;
1145     +
1146     + // The minimum size is specified in pixels, not in points.
1147     + // Convert the size from pixels to points.
1148     + minimum = NSTwipsToFloatPoints(NSFloatPixelsToTwips(minimum, mDeviceContext->DevUnitsToAppUnits()));
1149     + if (mPointSize < minimum)
1150     + mPointSize = minimum;
1151     + }
1152     +
1153     + // Make sure that the pixel size is at least greater than zero
1154     + if (mPointSize < 1) {
1155     +#ifdef DEBUG
1156     + printf("*** Warning: nsFontMetricsPango created with point size %f\n",
1157     + mPointSize);
1158     +#endif
1159     + mPointSize = 1;
1160     + }
1161     +
1162     + nsresult rv = RealizeFont();
1163     + if (NS_FAILED(rv))
1164     + return rv;
1165     +
1166     + // Cache font metrics for the 'x' character
1167     + return CacheFontMetrics();
1168     +}
1169     +
1170     +nsresult
1171     +nsFontMetricsPango::CacheFontMetrics(void)
1172     +{
1173     + // Get our scale factor
1174     + float f;
1175     + float val;
1176     + f = mDeviceContext->DevUnitsToAppUnits();
1177     +
1178     + mPangoAttrList = pango_attr_list_new();
1179     +
1180     + GList *items = pango_itemize(mPangoContext,
1181     + "a", 0, 1, mPangoAttrList, NULL);
1182     +
1183     + if (!items)
1184     + return NS_ERROR_FAILURE;
1185     +
1186     + guint nitems = g_list_length(items);
1187     + if (nitems != 1)
1188     + return NS_ERROR_FAILURE;
1189     +
1190     + PangoItem *item = (PangoItem *)items->data;
1191     + PangoFcFont *fcfont = PANGO_FC_FONT(item->analysis.font);
1192     + if (!fcfont)
1193     + return NS_ERROR_FAILURE;
1194     +
1195     + // Get our font face
1196     + FT_Face face;
1197     + TT_OS2 *os2;
1198     + XftFont *xftFont = pango_xft_font_get_font(PANGO_FONT(fcfont));
1199     + if (!xftFont)
1200     + return NS_ERROR_NOT_AVAILABLE;
1201     +
1202     + face = XftLockFace(xftFont);
1203     + os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1204     +
1205     + // mEmHeight (size in pixels of EM height)
1206     + int size;
1207     + if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) !=
1208     + FcResultMatch) {
1209     + size = 12;
1210     + }
1211     + mEmHeight = PR_MAX(1, nscoord(size * f));
1212     +
1213     + // mMaxAscent
1214     + mMaxAscent = nscoord(xftFont->ascent * f);
1215     +
1216     + // mMaxDescent
1217     + mMaxDescent = nscoord(xftFont->descent * f);
1218     +
1219     + nscoord lineHeight = mMaxAscent + mMaxDescent;
1220     +
1221     + // mLeading (needs ascent and descent and EM height)
1222     + if (lineHeight > mEmHeight)
1223     + mLeading = lineHeight - mEmHeight;
1224     + else
1225     + mLeading = 0;
1226     +
1227     + // mMaxHeight (needs ascent and descent)
1228     + mMaxHeight = lineHeight;
1229     +
1230     + // mEmAscent (needs maxascent, EM height, ascent and descent)
1231     + mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight);
1232     +
1233     + // mEmDescent (needs EM height and EM ascent
1234     + mEmDescent = mEmHeight - mEmAscent;
1235     +
1236     + // mMaxAdvance
1237     + mMaxAdvance = nscoord(xftFont->max_advance_width * f);
1238     +
1239     + // mSpaceWidth (width of a space)
1240     + nscoord tmpWidth;
1241     + GetWidth(" ", 1, tmpWidth, NULL);
1242     + mSpaceWidth = tmpWidth;
1243     +
1244     + // mAveCharWidth (width of an 'average' char)
1245     + // XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
1246     + //rawWidth = extents.width;
1247     + //mAveCharWidth = NSToCoordRound(rawWidth * f);
1248     + GetWidth("x", 1, tmpWidth, NULL);
1249     + mAveCharWidth = tmpWidth;
1250     +
1251     + // mXHeight (height of an 'x' character)
1252     + PRUnichar xUnichar('x');
1253     + XGlyphInfo extents;
1254     + if (FcCharSetHasChar(xftFont->charset, xUnichar)) {
1255     + XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
1256     + mXHeight = extents.height;
1257     + }
1258     + else {
1259     + // 56% of ascent, best guess for non-true type or asian fonts
1260     + mXHeight = nscoord(((float)mMaxAscent) * 0.56);
1261     + }
1262     + mXHeight = nscoord(mXHeight * f);
1263     +
1264     + // mUnderlineOffset (offset for underlines)
1265     + val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position,
1266     + face->size->metrics.y_scale);
1267     + if (val) {
1268     + mUnderlineOffset = NSToIntRound(val * f);
1269     + }
1270     + else {
1271     + mUnderlineOffset =
1272     + -NSToIntRound(PR_MAX(1, floor(0.1 * xftFont->height + 0.5)) * f);
1273     + }
1274     +
1275     + // mUnderlineSize (thickness of an underline)
1276     + val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness,
1277     + face->size->metrics.y_scale);
1278     + if (val) {
1279     + mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1280     + }
1281     + else {
1282     + mUnderlineSize =
1283     + NSToIntRound(PR_MAX(1, floor(0.05 * xftFont->height + 0.5)) * f);
1284     + }
1285     +
1286     + // mSuperscriptOffset
1287     + if (os2 && os2->ySuperscriptYOffset) {
1288     + val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySuperscriptYOffset,
1289     + face->size->metrics.y_scale);
1290     + mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1291     + }
1292     + else {
1293     + mSuperscriptOffset = mXHeight;
1294     + }
1295     +
1296     + // mSubscriptOffset
1297     + if (os2 && os2->ySubscriptYOffset) {
1298     + val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySubscriptYOffset,
1299     + face->size->metrics.y_scale);
1300     + // some fonts have the incorrect sign.
1301     + val = (val < 0) ? -val : val;
1302     + mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
1303     + }
1304     + else {
1305     + mSubscriptOffset = mXHeight;
1306     + }
1307     +
1308     + // mStrikeoutOffset
1309     + mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
1310     +
1311     + // mStrikeoutSize
1312     + mStrikeoutSize = mUnderlineSize;
1313     +
1314     + XftUnlockFace(xftFont);
1315     +
1316     + /*
1317     + printf("%i\n", mXHeight);
1318     + printf("%i\n", mSuperscriptOffset);
1319     + printf("%i\n", mSubscriptOffset);
1320     + printf("%i\n", mStrikeoutOffset);
1321     + printf("%i\n", mStrikeoutSize);
1322     + printf("%i\n", mUnderlineOffset);
1323     + printf("%i\n", mUnderlineSize);
1324     + printf("%i\n", mMaxHeight);
1325     + printf("%i\n", mLeading);
1326     + printf("%i\n", mEmHeight);
1327     + printf("%i\n", mEmAscent);
1328     + printf("%i\n", mEmDescent);
1329     + printf("%i\n", mMaxAscent);
1330     + printf("%i\n", mMaxDescent);
1331     + printf("%i\n", mMaxAdvance);
1332     + printf("%i\n", mSpaceWidth);
1333     + printf("%i\n", mAveCharWidth);
1334     + */
1335     +
1336     + return NS_OK;
1337     +}
1338     +
1339     +NS_IMETHODIMP
1340     +nsFontMetricsPango::Destroy()
1341     +{
1342     + mDeviceContext = nsnull;
1343     + return NS_OK;
1344     +}
1345     +
1346     +NS_IMETHODIMP
1347     +nsFontMetricsPango::GetFont(const nsFont *&aFont)
1348     +{
1349     + aFont = mFont;
1350     + return NS_OK;
1351     +}
1352     +
1353     +NS_IMETHODIMP
1354     +nsFontMetricsPango::GetLangGroup(nsIAtom** aLangGroup)
1355     +{
1356     + *aLangGroup = mLangGroup;
1357     + NS_IF_ADDREF(*aLangGroup);
1358     +
1359     + return NS_OK;
1360     +}
1361     +
1362     +NS_IMETHODIMP
1363     +nsFontMetricsPango::GetFontHandle(nsFontHandle &aHandle)
1364     +{
1365     + return NS_ERROR_NOT_IMPLEMENTED;
1366     +}
1367     +
1368     +// nsIFontMetricsPango impl
1369     +
1370     +nsresult
1371     +nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
1372     + nscoord& aWidth,
1373     + nsRenderingContextGTK *aContext)
1374     +{
1375     + PangoLayout *layout = pango_layout_new(mPangoContext);
1376     +
1377     + pango_layout_set_text(layout, aString, aLength);
1378     +
1379     + int width, height;
1380     +
1381     + pango_layout_get_size(layout, &width, &height);
1382     +
1383     + width /= PANGO_SCALE;
1384     +
1385     + g_object_unref(layout);
1386     +
1387     + float f;
1388     + f = mDeviceContext->DevUnitsToAppUnits();
1389     + aWidth = NSToCoordRound(width * f);
1390     +
1391     + // printf("GetWidth (char *) %d\n", aWidth);
1392     +
1393     + return NS_OK;
1394     +}
1395     +
1396     +nsresult
1397     +nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
1398     + nscoord& aWidth, PRInt32 *aFontID,
1399     + nsRenderingContextGTK *aContext)
1400     +{
1401     + nsresult rv = NS_OK;
1402     + PangoLayout *layout = pango_layout_new(mPangoContext);
1403     +
1404     + gchar *text = g_utf16_to_utf8(aString, aLength,
1405     + NULL, NULL, NULL);
1406     +
1407     + if (!text) {
1408     + aWidth = 0;
1409     +#ifdef DEBUG
1410     + NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1411     + DUMP_PRUNICHAR(aString, aLength)
1412     +#endif
1413     + rv = NS_ERROR_FAILURE;
1414     + goto loser;
1415     + }
1416     +
1417     + gint width, height;
1418     +
1419     + pango_layout_set_text(layout, text, strlen(text));
1420     + pango_layout_get_size(layout, &width, &height);
1421     +
1422     + width /= PANGO_SCALE;
1423     +
1424     + float f;
1425     + f = mDeviceContext->DevUnitsToAppUnits();
1426     + aWidth = NSToCoordRound(width * f);
1427     +
1428     + // printf("GetWidth %d\n", aWidth);
1429     +
1430     + loser:
1431     + g_free(text);
1432     + g_object_unref(layout);
1433     +
1434     + return rv;
1435     +}
1436     +
1437     +
1438     +nsresult
1439     +nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
1440     + PRUint32 aLength,
1441     + nsTextDimensions& aDimensions,
1442     + PRInt32* aFontID,
1443     + nsRenderingContextGTK *aContext)
1444     +{
1445     + nsresult rv = NS_OK;
1446     +
1447     + PangoLayout *layout = pango_layout_new(mPangoContext);
1448     +
1449     + gchar *text = g_utf16_to_utf8(aString, aLength,
1450     + NULL, NULL, NULL);
1451     +
1452     + if (!text) {
1453     +#ifdef DEBUG
1454     + NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
1455     + DUMP_PRUNICHAR(aString, aLength)
1456     +#endif
1457     + aDimensions.width = 0;
1458     + aDimensions.ascent = 0;
1459     + aDimensions.descent = 0;
1460     +
1461     + rv = NS_ERROR_FAILURE;
1462     + goto loser;
1463     + }
1464     +
1465     +
1466     + pango_layout_set_text(layout, text, strlen(text));
1467     +
1468     + // Get the logical extents
1469     + PangoLayoutLine *line;
1470     + if (pango_layout_get_line_count(layout) != 1) {
1471     + printf("Warning: more than one line!\n");
1472     + }
1473     + line = pango_layout_get_line(layout, 0);
1474     +
1475     + PangoRectangle rect;
1476     + pango_layout_line_get_extents(line, NULL, &rect);
1477     +
1478     + float P2T;
1479     + P2T = mDeviceContext->DevUnitsToAppUnits();
1480     +
1481     + aDimensions.width = NSToCoordRound(rect.width / PANGO_SCALE * P2T);
1482     + aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) / PANGO_SCALE * P2T);
1483     + aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) / PANGO_SCALE * P2T);
1484     +
1485     + // printf("GetTextDimensions %d %d %d\n", aDimensions.width,
1486     + //aDimensions.ascent, aDimensions.descent);
1487     +
1488     + loser:
1489     + g_free(text);
1490     + g_object_unref(layout);
1491     +
1492     + return rv;
1493     +}
1494     +
1495     +nsresult
1496     +nsFontMetricsPango::GetTextDimensions(const char* aString,
1497     + PRInt32 aLength,
1498     + PRInt32 aAvailWidth,
1499     + PRInt32* aBreaks,
1500     + PRInt32 aNumBreaks,
1501     + nsTextDimensions& aDimensions,
1502     + PRInt32& aNumCharsFit,
1503     + nsTextDimensions& aLastWordDimensions,
1504     + PRInt32* aFontID,
1505     + nsRenderingContextGTK *aContext)
1506     +{
1507     +
1508     + return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
1509     + aNumBreaks, aDimensions, aNumCharsFit,
1510     + aLastWordDimensions, aContext);
1511     +
1512     +}
1513     +
1514     +nsresult
1515     +nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
1516     + PRInt32 aLength,
1517     + PRInt32 aAvailWidth,
1518     + PRInt32* aBreaks,
1519     + PRInt32 aNumBreaks,
1520     + nsTextDimensions& aDimensions,
1521     + PRInt32& aNumCharsFit,
1522     + nsTextDimensions& aLastWordDimensions,
1523     + PRInt32* aFontID,
1524     + nsRenderingContextGTK *aContext)
1525     +{
1526     + nsresult rv = NS_OK;
1527     + PRInt32 curBreak = 0;
1528     + gchar *curChar;
1529     +
1530     + PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
1531     +
1532     + gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
1533     + NULL, NULL, NULL);
1534     +
1535     + curChar = text;
1536     +
1537     + if (!text) {
1538     +#ifdef DEBUG
1539     + NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
1540     + DUMP_PRUNICHAR(aString, (PRUint32)aLength)
1541     +#endif
1542     + rv = NS_ERROR_FAILURE;
1543     + goto loser;
1544     + }
1545     +
1546     + // Covert the utf16 break offsets to utf8 break offsets
1547     + for (PRInt32 curOffset=0; curOffset < aLength;
1548     + curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1549     + if (aBreaks[curBreak] == curOffset) {
1550     + utf8Breaks[curBreak] = curChar - text;
1551     + curBreak++;
1552     + }
1553     +
1554     + if (IS_HIGH_SURROGATE(aString[curOffset]))
1555     + curOffset++;
1556     + }
1557     +
1558     + // Always catch the last break
1559     + utf8Breaks[curBreak] = curChar - text;
1560     +
1561     +#if 0
1562     + if (strlen(text) != aLength) {
1563     + printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
1564     + DUMP_PRUNICHAR(aString, aLength)
1565     + DUMP_PRUNICHAR(text, strlen(text))
1566     + for (PRInt32 i = 0; i < aNumBreaks; ++i) {
1567     + printf(" break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
1568     + }
1569     + }
1570     +#endif
1571     +
1572     + // We'll use curBreak to indicate which of the breaks end up being
1573     + // used for the break point for this line.
1574     + curBreak = 0;
1575     + rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
1576     + aNumBreaks, aDimensions, aNumCharsFit,
1577     + aLastWordDimensions, aContext);
1578     +
1579     + // Figure out which of the breaks we ended up using to convert
1580     + // back to utf16 - start from the end.
1581     + for (PRInt32 i = aNumBreaks - 1; i >= 0; --i) {
1582     + if (utf8Breaks[i] == aNumCharsFit) {
1583     + // if (aNumCharsFit != aBreaks[i])
1584     + // printf("Fixing utf8 -> utf16 %d -> %d\n", aNumCharsFit, aBreaks[i]);
1585     + aNumCharsFit = aBreaks[i];
1586     + break;
1587     + }
1588     + }
1589     +
1590     + loser:
1591     + if (text)
1592     + g_free(text);
1593     +
1594     + delete[] utf8Breaks;
1595     +
1596     + return rv;
1597     +}
1598     +
1599     +nsresult
1600     +nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
1601     + nscoord aX, nscoord aY,
1602     + const nscoord* aSpacing,
1603     + nsRenderingContextGTK *aContext,
1604     + nsDrawingSurfaceGTK *aSurface)
1605     +{
1606     + PangoLayout *layout = pango_layout_new(mPangoContext);
1607     +
1608     + pango_layout_set_text(layout, aString, aLength);
1609     +
1610     + int x = aX;
1611     + int y = aY;
1612     +
1613     + aContext->GetTranMatrix()->TransformCoord(&x, &y);
1614     +
1615     + PangoLayoutLine *line;
1616     + if (pango_layout_get_line_count(layout) != 1) {
1617     + printf("Warning: more than one line!\n");
1618     + }
1619     + line = pango_layout_get_line(layout, 0);
1620     +
1621     + aContext->UpdateGC();
1622     + GdkGC *gc = aContext->GetGC();
1623     +
1624     + if (aSpacing && *aSpacing) {
1625     + DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
1626     + gc, x, y, line, aSpacing);
1627     + }
1628     + else {
1629     + gdk_draw_layout_line(aSurface->GetDrawable(), gc,
1630     + x, y,
1631     + line);
1632     + }
1633     +
1634     + g_object_unref(gc);
1635     + g_object_unref(layout);
1636     +
1637     + // printf("DrawString (char *)\n");
1638     +
1639     + return NS_OK;
1640     +}
1641     +
1642     +nsresult
1643     +nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
1644     + nscoord aX, nscoord aY,
1645     + PRInt32 aFontID,
1646     + const nscoord* aSpacing,
1647     + nsRenderingContextGTK *aContext,
1648     + nsDrawingSurfaceGTK *aSurface)
1649     +{
1650     + nsresult rv = NS_OK;
1651     + int x = aX;
1652     + int y = aY;
1653     +
1654     + aContext->UpdateGC();
1655     + GdkGC *gc = aContext->GetGC();
1656     +
1657     + PangoLayout *layout = pango_layout_new(mPangoContext);
1658     +
1659     + gchar *text = g_utf16_to_utf8(aString, aLength,
1660     + NULL, NULL, NULL);
1661     +
1662     + if (!text) {
1663     +#ifdef DEBUG
1664     + NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
1665     + DUMP_PRUNICHAR(aString, aLength)
1666     +#endif
1667     + rv = NS_ERROR_FAILURE;
1668     + goto loser;
1669     + }
1670     +
1671     + pango_layout_set_text(layout, text, strlen(text));
1672     +
1673     + aContext->GetTranMatrix()->TransformCoord(&x, &y);
1674     +
1675     + PangoLayoutLine *line;
1676     + if (pango_layout_get_line_count(layout) != 1) {
1677     + printf("Warning: more than one line!\n");
1678     + }
1679     + line = pango_layout_get_line(layout, 0);
1680     +
1681     + if (aSpacing && *aSpacing) {
1682     + DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
1683     + gc, x, y, line, aSpacing);
1684     + }
1685     + else {
1686     + gdk_draw_layout_line(aSurface->GetDrawable(), gc,
1687     + x, y,
1688     + line);
1689     + }
1690     +
1691     + loser:
1692     +
1693     + g_free(text);
1694     + g_object_unref(gc);
1695     + g_object_unref(layout);
1696     +
1697     + // printf("DrawString\n");
1698     +
1699     + return rv;
1700     +}
1701     +
1702     +#ifdef MOZ_MATHML
1703     +nsresult
1704     +nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
1705     + nsBoundingMetrics &aBoundingMetrics,
1706     + nsRenderingContextGTK *aContext)
1707     +{
1708     + printf("GetBoundingMetrics (char *)\n");
1709     + return NS_ERROR_FAILURE;
1710     +}
1711     +
1712     +nsresult
1713     +nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
1714     + PRUint32 aLength,
1715     + nsBoundingMetrics &aBoundingMetrics,
1716     + PRInt32 *aFontID,
1717     + nsRenderingContextGTK *aContext)
1718     +{
1719     + nsresult rv = NS_OK;
1720     + PangoLayout *layout = pango_layout_new(mPangoContext);
1721     +
1722     + gchar *text = g_utf16_to_utf8(aString, aLength,
1723     + NULL, NULL, NULL);
1724     +
1725     + if (!text) {
1726     +#ifdef DEBUG
1727     + NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
1728     + DUMP_PRUNICHAR(aString, aLength)
1729     +#endif
1730     + aBoundingMetrics.leftBearing = 0;
1731     + aBoundingMetrics.rightBearing = 0;
1732     + aBoundingMetrics.width = 0;
1733     + aBoundingMetrics.ascent = 0;
1734     + aBoundingMetrics.descent = 0;
1735     +
1736     + rv = NS_ERROR_FAILURE;
1737     + goto loser;
1738     + }
1739     +
1740     + pango_layout_set_text(layout, text, strlen(text));
1741     +
1742     + // Get the logical extents
1743     + PangoLayoutLine *line;
1744     + if (pango_layout_get_line_count(layout) != 1) {
1745     + printf("Warning: more than one line!\n");
1746     + }
1747     + line = pango_layout_get_line(layout, 0);
1748     +
1749     + // Get the ink extents
1750     + PangoRectangle rect;
1751     + pango_layout_line_get_extents(line, NULL, &rect);
1752     +
1753     + float P2T;
1754     + P2T = mDeviceContext->DevUnitsToAppUnits();
1755     +
1756     + aBoundingMetrics.leftBearing =
1757     + NSToCoordRound(rect.x / PANGO_SCALE * P2T);
1758     + aBoundingMetrics.rightBearing =
1759     + NSToCoordRound(rect.width / PANGO_SCALE * P2T);
1760     + aBoundingMetrics.width = NSToCoordRound((rect.x + rect.width) / PANGO_SCALE * P2T);
1761     + aBoundingMetrics.ascent = NSToCoordRound(rect.y / PANGO_SCALE * P2T);
1762     + aBoundingMetrics.descent = NSToCoordRound(rect.height / PANGO_SCALE * P2T);
1763     +
1764     + loser:
1765     + g_free(text);
1766     + g_object_unref(layout);
1767     +
1768     + return rv;
1769     +}
1770     +
1771     +#endif /* MOZ_MATHML */
1772     +
1773     +GdkFont*
1774     +nsFontMetricsPango::GetCurrentGDKFont(void)
1775     +{
1776     + return nsnull;
1777     +}
1778     +
1779     +nsresult
1780     +nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
1781     +{
1782     + if (aIsRTL) {
1783     + if (!mRTLPangoContext) {
1784     + mRTLPangoContext = pango_xft_get_context(GDK_DISPLAY(), 0);
1785     + pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
1786     +
1787     + gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
1788     + pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
1789     + pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
1790     + }
1791     + mPangoContext = mRTLPangoContext;
1792     + }
1793     + else {
1794     + mPangoContext = mLTRPangoContext;
1795     + }
1796     +
1797     + mIsRTL = aIsRTL;
1798     + return NS_OK;
1799     +}
1800     +
1801     +/* static */
1802     +PRUint32
1803     +nsFontMetricsPango::GetHints(void)
1804     +{
1805     + return (NS_RENDERING_HINT_BIDI_REORDERING |
1806     + NS_RENDERING_HINT_ARABIC_SHAPING |
1807     + NS_RENDERING_HINT_FAST_MEASURE);
1808     +}
1809     +
1810     +/* static */
1811     +nsresult
1812     +nsFontMetricsPango::FamilyExists(nsIDeviceContext *aDevice,
1813     + const nsString &aName)
1814     +{
1815     + if (!IsASCIIFontName(aName))
1816     + return NS_ERROR_FAILURE;
1817     +
1818     + NS_ConvertUCS2toUTF8 name(aName);
1819     +
1820     + nsresult rv = NS_ERROR_FAILURE;
1821     + PangoContext *context = pango_xft_get_context(GDK_DISPLAY(), 0);
1822     + PangoFontFamily **familyList;
1823     + int n;
1824     +
1825     + pango_context_list_families(context, &familyList, &n);
1826     +
1827     + for (int i=0; i < n; i++) {
1828     + const char *tmpname = pango_font_family_get_name(familyList[i]);
1829     + if (!Compare(nsDependentCString(tmpname), name,
1830     + nsCaseInsensitiveCStringComparator())) {
1831     + rv = NS_OK;
1832     + break;
1833     + }
1834     + }
1835     +
1836     + g_free(familyList);
1837     + g_object_unref(context);
1838     +
1839     + return rv;
1840     +}
1841     +
1842     +// Private Methods
1843     +
1844     +nsresult
1845     +nsFontMetricsPango::RealizeFont(void)
1846     +{
1847     + nsCString familyList;
1848     + // Create and fill out the font description.
1849     + mPangoFontDesc = pango_font_description_new();
1850     +
1851     + // Add CSS names - walk the list of fonts, adding the generic as
1852     + // the last font
1853     + for (int i=0; i < mFontList.Count(); ++i) {
1854     + // if this was a generic name, break out of the loop since we
1855     + // don't want to add it to the pattern yet
1856     + if (mFontIsGeneric[i])
1857     + break;;
1858     +
1859     + nsCString *familyName = mFontList.CStringAt(i);
1860     + familyList.Append(familyName->get());
1861     + familyList.Append(',');
1862     + }
1863     +
1864     + // If there's a generic add a pref for the generic if there's one
1865     + // set.
1866     + if (mGenericFont && !mFont->systemFont) {
1867     + nsCString name;
1868     + name += "font.name.";
1869     + name += mGenericFont->get();
1870     + name += ".";
1871     +
1872     + nsString langGroup;
1873     + mLangGroup->ToString(langGroup);
1874     +
1875     + name.AppendWithConversion(langGroup);
1876     +
1877     + nsCOMPtr<nsIPref> pref;
1878     + pref = do_GetService(NS_PREF_CONTRACTID);
1879     + if (pref) {
1880     + nsresult rv;
1881     + nsXPIDLCString value;
1882     + rv = pref->GetCharPref(name.get(), getter_Copies(value));
1883     +
1884     + // we ignore prefs that have three hypens since they are X
1885     + // style prefs.
1886     + if (FFRECountHyphens(value) < 3) {
1887     + nsCString tmpstr;
1888     + tmpstr.Append(value);
1889     +
1890     + familyList.Append(tmpstr);
1891     + familyList.Append(',');
1892     + }
1893     + }
1894     + }
1895     +
1896     + // Add the generic if there is one.
1897     + if (mGenericFont && !mFont->systemFont) {
1898     + familyList.Append(mGenericFont->get());
1899     + familyList.Append(',');
1900     + }
1901     +
1902     + // Set the family
1903     + pango_font_description_set_family(mPangoFontDesc,
1904     + familyList.get());
1905     +
1906     + // Set the point size
1907     + pango_font_description_set_size(mPangoFontDesc,
1908     + (gint)(mPointSize * PANGO_SCALE));
1909     +
1910     + // Set the style
1911     + pango_font_description_set_style(mPangoFontDesc,
1912     + CalculateStyle(mFont->style));
1913     +
1914     + // Set the weight
1915     + pango_font_description_set_weight(mPangoFontDesc,
1916     + CalculateWeight(mFont->weight));
1917     +
1918     + // Now that we have the font description set up, create the
1919     + // context.
1920     + mLTRPangoContext = pango_xft_get_context(GDK_DISPLAY(), 0);
1921     + mPangoContext = mLTRPangoContext;
1922     +
1923     + // Set the color map so we can draw later.
1924     + gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
1925     +
1926     + // Set the pango language now that we have a context
1927     + pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
1928     +
1929     + // And attach the font description to this context
1930     + pango_context_set_font_description(mPangoContext, mPangoFontDesc);
1931     +
1932     + return NS_OK;
1933     +}
1934     +
1935     +/* static */
1936     +PRBool
1937     +nsFontMetricsPango::EnumFontCallback(const nsString &aFamily,
1938     + PRBool aIsGeneric, void *aData)
1939     +{
1940     + // make sure it's an ascii name, if not then return and continue
1941     + // enumerating
1942     + if (!IsASCIIFontName(aFamily))
1943     + return PR_TRUE;
1944     +
1945     + nsCAutoString name;
1946     + name.AssignWithConversion(aFamily.get());
1947     + ToLowerCase(name);
1948     + nsFontMetricsPango *metrics = (nsFontMetricsPango *)aData;
1949     + metrics->mFontList.AppendCString(name);
1950     + metrics->mFontIsGeneric.AppendElement((void *)aIsGeneric);
1951     + if (aIsGeneric) {
1952     + metrics->mGenericFont =
1953     + metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1);
1954     + return PR_FALSE; // stop processing
1955     + }
1956     +
1957     + return PR_TRUE; // keep processing
1958     +}
1959     +
1960     +/*
1961     + * This is only used when there's per-character spacing happening.
1962     + * Well, really it can be either line or character spacing but it's
1963     + * just turtles all the way down!
1964     + */
1965     +
1966     +void
1967     +nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
1968     + const PRUnichar *aOrigString,
1969     + PRUint32 aLength,
1970     + GdkDrawable *aDrawable,
1971     + GdkGC *aGC, gint aX, gint aY,
1972     + PangoLayoutLine *aLine,
1973     + const nscoord *aSpacing)
1974     +{
1975     + float app2dev;
1976     + app2dev = mDeviceContext->AppUnitsToDevUnits();
1977     + gint offset = 0;
1978     +
1979     + /*
1980     + * We walk the list of glyphs returned in each layout run,
1981     + * matching up the glyphs with the characters in the source text.
1982     + * We use the aSpacing argument to figure out where to place those
1983     + * glyphs. It's important to note that since the string we're
1984     + * working with is in UTF-8 while the spacing argument assumes
1985     + * that offset will be part of the UTF-16 string. Logical
1986     + * attributes in pango are in byte offsets in the UTF-8 string, so
1987     + * we need to store the offsets based on the UTF-8 string.
1988     + */
1989     + nscoord *utf8spacing = new nscoord[strlen(aText)];
1990     +
1991     + if (aOrigString) {
1992     + const gchar *curChar = aText;
1993     + bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
1994     +
1995     + // Covert the utf16 spacing offsets to utf8 spacing offsets
1996     + for (PRUint32 curOffset=0; curOffset < aLength;
1997     + curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
1998     + utf8spacing[curChar - aText] = aSpacing[curOffset];
1999     +
2000     + if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
2001     + curOffset++;
2002     + }
2003     + }
2004     + else {
2005     + memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
2006     + }
2007     +
2008     + gint curRun = 0;
2009     +
2010     + for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
2011     + tmpList = tmpList->next, curRun++) {
2012     + PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
2013     + gint tmpOffset = 0;
2014     +
2015     + /* printf(" Rendering run %d: \"%s\"\n", curRun,
2016     + &aText[layoutRun->item->offset]); */
2017     +
2018     + for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
2019     + /* printf("glyph %d offset %d orig width %d new width %d\n", i,
2020     + * layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
2021     + * layoutRun->glyphs->glyphs[i].geometry.width,
2022     + * (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
2023     + */
2024     + gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
2025     + * app2dev * PANGO_SCALE);
2026     + layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
2027     + tmpOffset += thisOffset;
2028     + }
2029     +
2030     + /* printf(" rendering at X coord %d\n", aX + offset); */
2031     +
2032     + gdk_draw_glyphs(aDrawable, aGC, layoutRun->item->analysis.font,
2033     + aX + (gint)(offset / PANGO_SCALE), aY, layoutRun->glyphs);
2034     +
2035     + offset += tmpOffset;
2036     + }
2037     +
2038     + delete[] utf8spacing;
2039     +}
2040     +
2041     +nsresult
2042     +nsFontMetricsPango::GetTextDimensionsInternal(const gchar* aString,
2043     + PRInt32 aLength,
2044     + PRInt32 aAvailWidth,
2045     + PRInt32* aBreaks,
2046     + PRInt32 aNumBreaks,
2047     + nsTextDimensions& aDimensions,
2048     + PRInt32& aNumCharsFit,
2049     + nsTextDimensions& aLastWordDimensions,
2050     + nsRenderingContextGTK *aContext)
2051     +{
2052     + NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
2053     +
2054     + // If we need to back up this state represents the last place
2055     + // we could break. We can use this to avoid remeasuring text
2056     + PRInt32 prevBreakState_BreakIndex = -1; // not known
2057     + // (hasn't been computed)
2058     + nscoord prevBreakState_Width = 0; // accumulated width to this point
2059     +
2060     + // Initialize OUT parameters
2061     + GetMaxAscent(aLastWordDimensions.ascent);
2062     + GetMaxDescent(aLastWordDimensions.descent);
2063     + aLastWordDimensions.width = -1;
2064     + aNumCharsFit = 0;
2065     +
2066     + // Iterate each character in the string and determine which font to use
2067     + nscoord width = 0;
2068     + PRInt32 start = 0;
2069     + nscoord aveCharWidth;
2070     + GetAveCharWidth(aveCharWidth);
2071     +
2072     + while (start < aLength) {
2073     + // Estimate how many characters will fit. Do that by
2074     + // diving the available space by the average character
2075     + // width. Make sure the estimated number of characters is
2076     + // at least 1
2077     + PRInt32 estimatedNumChars = 0;
2078     +
2079     + if (aveCharWidth > 0)
2080     + estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
2081     +
2082     + if (estimatedNumChars < 1)
2083     + estimatedNumChars = 1;
2084     +
2085     + // Find the nearest break offset
2086     + PRInt32 estimatedBreakOffset = start + estimatedNumChars;
2087     + PRInt32 breakIndex;
2088     + nscoord numChars;
2089     +
2090     + // Find the nearest place to break that is less than or equal to
2091     + // the estimated break offset
2092     + if (aLength <= estimatedBreakOffset) {
2093     + // All the characters should fit
2094     + numChars = aLength - start;
2095     + breakIndex = aNumBreaks - 1;
2096     + }
2097     + else {
2098     + breakIndex = prevBreakState_BreakIndex;
2099     + while (((breakIndex + 1) < aNumBreaks) &&
2100     + (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
2101     + ++breakIndex;
2102     + }
2103     +
2104     + if (breakIndex == prevBreakState_BreakIndex) {
2105     + ++breakIndex; // make sure we advanced past the
2106     + // previous break index
2107     + }
2108     +
2109     + numChars = aBreaks[breakIndex] - start;
2110     + }
2111     +
2112     + // Measure the text
2113     + nscoord twWidth = 0;
2114     + if ((1 == numChars) && (aString[start] == ' '))
2115     + GetSpaceWidth(twWidth);
2116     + else if (numChars > 0)
2117     + GetWidth(&aString[start], numChars, twWidth, aContext);
2118     +
2119     + // See if the text fits
2120     + PRBool textFits = (twWidth + width) <= aAvailWidth;
2121     +
2122     + // If the text fits then update the width and the number of
2123     + // characters that fit
2124     + if (textFits) {
2125     + aNumCharsFit += numChars;
2126     + width += twWidth;
2127     + start += numChars;
2128     +
2129     + // This is a good spot to back up to if we need to so remember
2130     + // this state
2131     + prevBreakState_BreakIndex = breakIndex;
2132     + prevBreakState_Width = width;
2133     + }
2134     + else {
2135     + // See if we can just back up to the previous saved
2136     + // state and not have to measure any text
2137     + if (prevBreakState_BreakIndex > 0) {
2138     + // If the previous break index is just before the
2139     + // current break index then we can use it
2140     + if (prevBreakState_BreakIndex == (breakIndex - 1)) {
2141     + aNumCharsFit = aBreaks[prevBreakState_BreakIndex];
2142     + width = prevBreakState_Width;
2143     + break;
2144     + }
2145     + }
2146     +
2147     + // We can't just revert to the previous break state
2148     + if (0 == breakIndex) {
2149     + // There's no place to back up to, so even though
2150     + // the text doesn't fit return it anyway
2151     + aNumCharsFit += numChars;
2152     + width += twWidth;
2153     + break;
2154     + }
2155     +
2156     + // Repeatedly back up until we get to where the text
2157     + // fits or we're all the way back to the first word
2158     + width += twWidth;
2159     + while ((breakIndex >= 1) && (width > aAvailWidth)) {
2160     + twWidth = 0;
2161     + start = aBreaks[breakIndex - 1];
2162     + numChars = aBreaks[breakIndex] - start;
2163     +
2164     + if ((1 == numChars) && (aString[start] == ' '))
2165     + GetSpaceWidth(twWidth);
2166     + else if (numChars > 0)
2167     + GetWidth(&aString[start], numChars, twWidth,
2168     + aContext);
2169     + width -= twWidth;
2170     + aNumCharsFit = start;
2171     + breakIndex--;
2172     + }
2173     + break;
2174     + }
2175     + }
2176     +
2177     + aDimensions.width = width;
2178     + GetMaxAscent(aDimensions.ascent);
2179     + GetMaxDescent(aDimensions.descent);
2180     +
2181     + /* printf("aDimensions %d %d %d aLastWordDimensions %d %d %d aNumCharsFit %d\n",
2182     + aDimensions.width, aDimensions.ascent, aDimensions.descent,
2183     + aLastWordDimensions.width, aLastWordDimensions.ascent, aLastWordDimensions.descent,
2184     + aNumCharsFit); */
2185     +
2186     + return NS_OK;
2187     +}
2188     +
2189     +/* static */
2190     +PRBool
2191     +IsASCIIFontName(const nsString& aName)
2192     +{
2193     + PRUint32 len = aName.Length();
2194     + const PRUnichar* str = aName.get();
2195     + for (PRUint32 i = 0; i < len; i++) {
2196     + /*
2197     + * X font names are printable ASCII, ignore others (for now)
2198     + */
2199     + if ((str[i] < 0x20) || (str[i] > 0x7E)) {
2200     + return PR_FALSE;
2201     + }
2202     + }
2203     +
2204     + return PR_TRUE;
2205     +}
2206     +
2207     +/* static */
2208     +int
2209     +FFRECountHyphens (nsACString &aFFREName)
2210     +{
2211     + int h = 0;
2212     + PRInt32 hyphen = 0;
2213     + while ((hyphen = aFFREName.FindChar('-', hyphen)) >= 0) {
2214     + ++h;
2215     + ++hyphen;
2216     + }
2217     + return h;
2218     +}
2219     +
2220     +/* static */
2221     +PangoLanguage *
2222     +GetPangoLanguage(nsIAtom *aLangGroup)
2223     +{
2224     + // Find the FC lang group for this lang group
2225     + nsCAutoString cname;
2226     + aLangGroup->ToUTF8String(cname);
2227     +
2228     + // see if the lang group needs to be translated from mozilla's
2229     + // internal mapping into fontconfig's
2230     + const struct MozPangoLangGroup *langGroup;
2231     + langGroup = FindPangoLangGroup(cname);
2232     +
2233     + // if there's no lang group, just use the lang group as it was
2234     + // passed to us
2235     + //
2236     + // we're casting away the const here for the strings - should be
2237     + // safe.
2238     + if (!langGroup)
2239     + return pango_language_from_string(cname.get());
2240     + else if (langGroup->PangoLang)
2241     + return pango_language_from_string(langGroup->PangoLang);
2242     +
2243     + return pango_language_from_string("en");
2244     +}
2245     +
2246     +/* static */
2247     +const MozPangoLangGroup*
2248     +FindPangoLangGroup (nsACString &aLangGroup)
2249     +{
2250     + for (unsigned int i=0; i < NUM_PANGO_LANG_GROUPS; ++i) {
2251     + if (aLangGroup.Equals(MozPangoLangGroups[i].mozLangGroup,
2252     + nsCaseInsensitiveCStringComparator())) {
2253     + return &MozPangoLangGroups[i];
2254     + }
2255     + }
2256     +
2257     + return nsnull;
2258     +}
2259     +
2260     +/* static */
2261     +void
2262     +FreeGlobals(void)
2263     +{
2264     +}
2265     +
2266     +/* static */
2267     +PangoStyle
2268     +CalculateStyle(PRUint8 aStyle)
2269     +{
2270     + switch(aStyle) {
2271     + case NS_FONT_STYLE_ITALIC:
2272     + return PANGO_STYLE_OBLIQUE;
2273     + break;
2274     + case NS_FONT_STYLE_OBLIQUE:
2275     + return PANGO_STYLE_OBLIQUE;
2276     + break;
2277     + }
2278     +
2279     + return PANGO_STYLE_NORMAL;
2280     +}
2281     +
2282     +/* static */
2283     +PangoWeight
2284     +CalculateWeight (PRUint16 aWeight)
2285     +{
2286     + /*
2287     + * weights come in two parts crammed into one
2288     + * integer -- the "base" weight is weight / 100,
2289     + * the rest of the value is the "offset" from that
2290     + * weight -- the number of steps to move to adjust
2291     + * the weight in the list of supported font weights,
2292     + * this value can be negative or positive.
2293     + */
2294     + PRInt32 baseWeight = (aWeight + 50) / 100;
2295     + PRInt32 offset = aWeight - baseWeight * 100;
2296     +
2297     + /* clip weights to range 0 to 9 */
2298     + if (baseWeight < 0)
2299     + baseWeight = 0;
2300     + if (baseWeight > 9)
2301     + baseWeight = 9;
2302     +
2303     + /* Map from weight value to fcWeights index */
2304     + static int fcWeightLookup[10] = {
2305     + 0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
2306     + };
2307     +
2308     + PRInt32 fcWeight = fcWeightLookup[baseWeight];
2309     +
2310     + /*
2311     + * adjust by the offset value, make sure we stay inside the
2312     + * fcWeights table
2313     + */
2314     + fcWeight += offset;
2315     +
2316     + if (fcWeight < 0)
2317     + fcWeight = 0;
2318     + if (fcWeight > 4)
2319     + fcWeight = 4;
2320     +
2321     + /* Map to final PANGO_WEIGHT value */
2322     + static int fcWeights[5] = {
2323     + 349,
2324     + 499,
2325     + 649,
2326     + 749,
2327     + 999
2328     + };
2329     +
2330     + return (PangoWeight)fcWeights[fcWeight];
2331     +}
2332     +
2333     +/* static */
2334     +nsresult
2335     +EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric,
2336     + PRUint32* aCount, PRUnichar*** aResult)
2337     +{
2338     + FcPattern *pat = NULL;
2339     + FcObjectSet *os = NULL;
2340     + FcFontSet *fs = NULL;
2341     + nsresult rv = NS_ERROR_FAILURE;
2342     +
2343     + PRUnichar **array = NULL;
2344     + PRUint32 narray = 0;
2345     + PRInt32 serif = 0, sansSerif = 0, monospace = 0, nGenerics;
2346     +
2347     + *aCount = 0;
2348     + *aResult = nsnull;
2349     +
2350     + pat = FcPatternCreate();
2351     + if (!pat)
2352     + goto end;
2353     +
2354     + os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, 0);
2355     + if (!os)
2356     + goto end;
2357     +
2358     + // take the pattern and add the lang group to it
2359     + if (aLangGroup)
2360     + AddLangGroup(pat, aLangGroup);
2361     +
2362     + // get the font list
2363     + fs = FcFontList(0, pat, os);
2364     +
2365     + if (!fs)
2366     + goto end;
2367     +
2368     + if (!fs->nfont) {
2369     + rv = NS_OK;
2370     + goto end;
2371     + }
2372     +
2373     + // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
2374     + // "monospace", slightly different from CSS's 5.
2375     + if (!aGeneric)
2376     + serif = sansSerif = monospace = 1;
2377     + else if (!strcmp(aGeneric, "serif"))
2378     + serif = 1;
2379     + else if (!strcmp(aGeneric, "sans-serif"))
2380     + sansSerif = 1;
2381     + else if (!strcmp(aGeneric, "monospace"))
2382     + monospace = 1;
2383     + else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
2384     + serif = sansSerif = 1;
2385     + else
2386     + NS_NOTREACHED("unexpected generic family");
2387     + nGenerics = serif + sansSerif + monospace;
2388     +
2389     + array = NS_STATIC_CAST(PRUnichar **,
2390     + nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
2391     + if (!array)
2392     + goto end;
2393     +
2394     + if (serif) {
2395     + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
2396     + if (!name)
2397     + goto end;
2398     + array[narray++] = name;
2399     + }
2400     +
2401     + if (sansSerif) {
2402     + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
2403     + if (!name)
2404     + goto end;
2405     + array[narray++] = name;
2406     + }
2407     +
2408     + if (monospace) {
2409     + PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
2410     + if (!name)
2411     + goto end;
2412     + array[narray++] = name;
2413     + }
2414     +
2415     + for (int i=0; i < fs->nfont; ++i) {
2416     + char *family;
2417     + PRUnichar *name;
2418     +
2419     + // if there's no family, just move to the next iteration
2420     + if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
2421     + (FcChar8 **) &family) != FcResultMatch) {
2422     + continue;
2423     + }
2424     +
2425     + name = NS_STATIC_CAST(PRUnichar *,
2426     + nsMemory::Alloc ((strlen (family) + 1)
2427     + * sizeof (PRUnichar)));
2428     +
2429     + if (!name)
2430     + goto end;
2431     +
2432     + PRUnichar *r = name;
2433     + for (char *f = family; *f; ++f)
2434     + *r++ = *f;
2435     + *r = '\0';
2436     +
2437     + array[narray++] = name;
2438     + }
2439     +
2440     + NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
2441     + CompareFontNames, nsnull);
2442     +
2443     + *aCount = narray;
2444     + if (narray)
2445     + *aResult = array;
2446     + else
2447     + nsMemory::Free(array);
2448     +
2449     + rv = NS_OK;
2450     +
2451     + end:
2452     + if (NS_FAILED(rv) && array) {
2453     + while (narray)
2454     + nsMemory::Free (array[--narray]);
2455     + nsMemory::Free (array);
2456     + }
2457     + if (pat)
2458     + FcPatternDestroy(pat);
2459     + if (os)
2460     + FcObjectSetDestroy(os);
2461     + if (fs)
2462     + FcFontSetDestroy(fs);
2463     +
2464     + return rv;
2465     +}
2466     +
2467     +/* static */
2468     +int
2469     +CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure)
2470     +{
2471     + const PRUnichar* str1 = *((const PRUnichar**) aArg1);
2472     + const PRUnichar* str2 = *((const PRUnichar**) aArg2);
2473     +
2474     + return nsCRT::strcmp(str1, str2);
2475     +}
2476     +
2477     +
2478     +// nsFontEnumeratorPango class
2479     +
2480     +nsFontEnumeratorPango::nsFontEnumeratorPango()
2481     +{
2482     +}
2483     +
2484     +NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator)
2485     +
2486     +NS_IMETHODIMP
2487     +nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount,
2488     + PRUnichar ***aResult)
2489     +{
2490     + NS_ENSURE_ARG_POINTER(aResult);
2491     + *aResult = nsnull;
2492     + NS_ENSURE_ARG_POINTER(aCount);
2493     + *aCount = 0;
2494     +
2495     + return EnumFontsPango(nsnull, nsnull, aCount, aResult);
2496     +}
2497     +
2498     +NS_IMETHODIMP
2499     +nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup,
2500     + const char *aGeneric,
2501     + PRUint32 *aCount,
2502     + PRUnichar ***aResult)
2503     +{
2504     + NS_ENSURE_ARG_POINTER(aResult);
2505     + *aResult = nsnull;
2506     + NS_ENSURE_ARG_POINTER(aCount);
2507     + *aCount = 0;
2508     +
2509     + // aLangGroup=null or "" means any (i.e., don't care)
2510     + // aGeneric=null or "" means any (i.e, don't care)
2511     + nsCOMPtr<nsIAtom> langGroup;
2512     + if (aLangGroup && *aLangGroup)
2513     + langGroup = do_GetAtom(aLangGroup);
2514     + const char* generic = nsnull;
2515     + if (aGeneric && *aGeneric)
2516     + generic = aGeneric;
2517     +
2518     + return EnumFontsPango(langGroup, generic, aCount, aResult);
2519     +}
2520     +
2521     +NS_IMETHODIMP
2522     +nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup,
2523     + PRBool *aResult)
2524     +{
2525     + NS_ENSURE_ARG_POINTER(aResult);
2526     + *aResult = PR_FALSE;
2527     + NS_ENSURE_ARG_POINTER(aLangGroup);
2528     +
2529     + *aResult = PR_TRUE; // always return true for now.
2530     + // Finish me - ftang
2531     + return NS_OK;
2532     +}
2533     +
2534     +NS_IMETHODIMP
2535     +nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup,
2536     + const char *aGeneric,
2537     + PRUnichar **aResult)
2538     +{
2539     + NS_ENSURE_ARG_POINTER(aResult);
2540     + *aResult = nsnull;
2541     +
2542     + // Have a look at nsFontEnumeratorXft::GetDefaultFont for some
2543     + // possible code for this function.
2544     +
2545     + return NS_OK;
2546     +}
2547     +
2548     +NS_IMETHODIMP
2549     +nsFontEnumeratorPango::UpdateFontList(PRBool *_retval)
2550     +{
2551     + *_retval = PR_FALSE; // always return false for now
2552     + return NS_OK;
2553     +}
2554     --- mozilla/gfx/src/gtk/nsRenderingContextGTK.h.foo 2003-02-24 21:38:34.000000000 -0500
2555     +++ mozilla/gfx/src/gtk/nsRenderingContextGTK.h 2004-10-18 22:49:40.000000000 -0400
2556     @@ -194,6 +194,8 @@
2557     const nsRect &aDestBounds, PRUint32 aCopyFlags);
2558     NS_IMETHOD RetrieveCurrentNativeGraphicData(PRUint32 * ngd);
2559    
2560     + NS_IMETHOD SetRightToLeftText(PRBool aIsRTL);
2561     +
2562     NS_IMETHOD DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint);
2563     NS_IMETHOD DrawScaledImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsRect * aDestRect);
2564    
2565     --- /dev/null 2004-02-18 10:26:44.000000000 -0500
2566     +++ mozilla/gfx/src/gtk/nsFontMetricsPango.h 2004-10-18 22:49:40.000000000 -0400
2567     @@ -0,0 +1,278 @@
2568     +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2569     +/* vim:expandtab:shiftwidth=4:tabstop=4:
2570     + */
2571     +/* ***** BEGIN LICENSE BLOCK *****
2572     + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
2573     + *
2574     + * The contents of this file are subject to the Mozilla Public License Version
2575     + * 1.1 (the "License"); you may not use this file except in compliance with
2576     + * the License. You may obtain a copy of the License at
2577     + * http://www.mozilla.org/MPL/
2578     + *
2579     + * Software distributed under the License is distributed on an "AS IS" basis,
2580     + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
2581     + * for the specific language governing rights and limitations under the
2582     + * License.
2583     + *
2584     + * The Original Code is mozilla.org code.
2585     + *
2586     + * The Initial Developer of the Original Code Christopher Blizzard
2587     + * <blizzard@mozilla.org>. Portions created by the Initial Developer
2588     + * are Copyright (C) 2002 the Initial Developer. All Rights Reserved.
2589     + *
2590     + * Contributor(s):
2591     + *
2592     + * Alternatively, the contents of this file may be used under the terms of
2593     + * either the GNU General Public License Version 2 or later (the "GPL"), or
2594     + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
2595     + * in which case the provisions of the GPL or the LGPL are applicable instead
2596     + * of those above. If you wish to allow use of your version of this file only
2597     + * under the terms of either the GPL or the LGPL, and not to allow others to
2598     + * use your version of this file under the terms of the MPL, indicate your
2599     + * decision by deleting the provisions above and replace them with the notice
2600     + * and other provisions required by the GPL or the LGPL. If you do not delete
2601     + * the provisions above, a recipient may use your version of this file under
2602     + * the terms of any one of the MPL, the GPL or the LGPL.
2603     + *
2604     + * ***** END LICENSE BLOCK ***** */
2605     +
2606     +#include "nsIFontMetrics.h"
2607     +#include "nsIFontEnumerator.h"
2608     +#include "nsCRT.h"
2609     +#include "nsIAtom.h"
2610     +#include "nsString.h"
2611     +#include "nsVoidArray.h"
2612     +#include "nsIFontMetricsGTK.h"
2613     +
2614     +#include <pango/pango.h>
2615     +
2616     +class nsFontMetricsPango : public nsIFontMetricsGTK
2617     +{
2618     +public:
2619     + nsFontMetricsPango();
2620     + virtual ~nsFontMetricsPango();
2621     +
2622     + NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
2623     +
2624     + // nsISupports
2625     + NS_DECL_ISUPPORTS
2626     +
2627     + // nsIFontMetrics
2628     + NS_IMETHOD Init (const nsFont& aFont, nsIAtom* aLangGroup,
2629     + nsIDeviceContext *aContext);
2630     + NS_IMETHOD Destroy();
2631     + NS_IMETHOD GetFont (const nsFont *&aFont);
2632     + NS_IMETHOD GetLangGroup (nsIAtom** aLangGroup);
2633     + NS_IMETHOD GetFontHandle (nsFontHandle &aHandle);
2634     +
2635     + NS_IMETHOD GetXHeight (nscoord& aResult)
2636     + { aResult = mXHeight; return NS_OK; };
2637     +
2638     + NS_IMETHOD GetSuperscriptOffset (nscoord& aResult)
2639     + { aResult = mSuperscriptOffset;
2640     + return NS_OK; };
2641     +
2642     + NS_IMETHOD GetSubscriptOffset (nscoord& aResult)
2643     + { aResult = mSubscriptOffset;
2644     + return NS_OK; };
2645     +
2646     + NS_IMETHOD GetStrikeout (nscoord& aOffset, nscoord& aSize)
2647     + { aOffset = mStrikeoutOffset;
2648     + aSize = mStrikeoutSize;
2649     + return NS_OK; };
2650     +
2651     + NS_IMETHOD GetUnderline (nscoord& aOffset, nscoord& aSize)
2652     + { aOffset = mUnderlineOffset;
2653     + aSize = mUnderlineSize;
2654     + return NS_OK; };
2655     +
2656     + NS_IMETHOD GetHeight (nscoord &aHeight)
2657     + { aHeight = mMaxHeight;
2658     + return NS_OK; };
2659     +
2660     + NS_IMETHOD GetNormalLineHeight (nscoord &aHeight)
2661     + { aHeight = mEmHeight + mLeading;
2662     + return NS_OK; };
2663     +
2664     + NS_IMETHOD GetLeading (nscoord &aLeading)
2665     + { aLeading = mLeading;
2666     + return NS_OK; };
2667     +
2668     + NS_IMETHOD GetEmHeight (nscoord &aHeight)
2669     + { aHeight = mEmHeight;
2670     + return NS_OK; };
2671     +
2672     + NS_IMETHOD GetEmAscent (nscoord &aAscent)
2673     + { aAscent = mEmAscent;
2674     + return NS_OK; };
2675     +
2676     + NS_IMETHOD GetEmDescent (nscoord &aDescent)
2677     + { aDescent = mEmDescent;
2678     + return NS_OK; };
2679     +
2680     + NS_IMETHOD GetMaxHeight (nscoord &aHeight)
2681     + { aHeight = mMaxHeight;
2682     + return NS_OK; };
2683     +
2684     + NS_IMETHOD GetMaxAscent (nscoord &aAscent)
2685     + { aAscent = mMaxAscent;
2686     + return NS_OK; };
2687     +
2688     + NS_IMETHOD GetMaxDescent (nscoord &aDescent)
2689     + { aDescent = mMaxDescent;
2690     + return NS_OK; };
2691     +
2692     + NS_IMETHOD GetMaxAdvance (nscoord &aAdvance)
2693     + { aAdvance = mMaxAdvance;
2694     + return NS_OK; };
2695     +
2696     + NS_IMETHOD GetSpaceWidth (nscoord &aSpaceCharWidth)
2697     + { aSpaceCharWidth = mSpaceWidth;
2698     + return NS_OK; };
2699     +
2700     + NS_IMETHOD GetAveCharWidth (nscoord &aAveCharWidth)
2701     + { aAveCharWidth = mAveCharWidth;
2702     + return NS_OK; };
2703     +
2704     + // nsIFontMetricsGTK (calls from the font rendering layer)
2705     + virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
2706     + nscoord& aWidth,
2707     + nsRenderingContextGTK *aContext);
2708     + virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
2709     + nscoord& aWidth, PRInt32 *aFontID,
2710     + nsRenderingContextGTK *aContext);
2711     +
2712     + virtual nsresult GetTextDimensions(const PRUnichar* aString,
2713     + PRUint32 aLength,
2714     + nsTextDimensions& aDimensions,
2715     + PRInt32* aFontID,
2716     + nsRenderingContextGTK *aContext);
2717     + virtual nsresult GetTextDimensions(const char* aString,
2718     + PRInt32 aLength,
2719     + PRInt32 aAvailWidth,
2720     + PRInt32* aBreaks,
2721     + PRInt32 aNumBreaks,
2722     + nsTextDimensions& aDimensions,
2723     + PRInt32& aNumCharsFit,
2724     + nsTextDimensions& aLastWordDimensions,
2725     + PRInt32* aFontID,
2726     + nsRenderingContextGTK *aContext);
2727     + virtual nsresult GetTextDimensions(const PRUnichar* aString,
2728     + PRInt32 aLength,
2729     + PRInt32 aAvailWidth,
2730     + PRInt32* aBreaks,
2731     + PRInt32 aNumBreaks,
2732     + nsTextDimensions& aDimensions,
2733     + PRInt32& aNumCharsFit,
2734     + nsTextDimensions& aLastWordDimensions,
2735     + PRInt32* aFontID,
2736     + nsRenderingContextGTK *aContext);
2737     +
2738     + virtual nsresult DrawString(const char *aString, PRUint32 aLength,
2739     + nscoord aX, nscoord aY,
2740     + const nscoord* aSpacing,
2741     + nsRenderingContextGTK *aContext,
2742     + nsDrawingSurfaceGTK *aSurface);
2743     + virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
2744     + nscoord aX, nscoord aY,
2745     + PRInt32 aFontID,
2746     + const nscoord* aSpacing,
2747     + nsRenderingContextGTK *aContext,
2748     + nsDrawingSurfaceGTK *aSurface);
2749     +
2750     +#ifdef MOZ_MATHML
2751     + virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
2752     + nsBoundingMetrics &aBoundingMetrics,
2753     + nsRenderingContextGTK *aContext);
2754     + virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
2755     + PRUint32 aLength,
2756     + nsBoundingMetrics &aBoundingMetrics,
2757     + PRInt32 *aFontID,
2758     + nsRenderingContextGTK *aContext);
2759     +#endif /* MOZ_MATHML */
2760     +
2761     + virtual GdkFont* GetCurrentGDKFont(void);
2762     +
2763     + virtual nsresult SetRightToLeftText(PRBool aIsRTL);
2764     +
2765     + // get hints for the font
2766     + static PRUint32 GetHints (void);
2767     +
2768     + // drawing surface methods
2769     + static nsresult FamilyExists (nsIDeviceContext *aDevice,
2770     + const nsString &aName);
2771     +
2772     +private:
2773     +
2774     + // generic font metrics class bits
2775     + nsCStringArray mFontList;
2776     + nsAutoVoidArray mFontIsGeneric;
2777     +
2778     + nsIDeviceContext *mDeviceContext;
2779     + nsCOMPtr<nsIAtom> mLangGroup;
2780     + nsCString *mGenericFont;
2781     + nsFont *mFont;
2782     + float mPointSize;
2783     +
2784     + nsCAutoString mDefaultFont;
2785     +
2786     + // Pango-related items
2787     + PangoFontDescription *mPangoFontDesc;
2788     + PangoContext *mPangoContext;
2789     + PangoContext *mLTRPangoContext;
2790     + PangoContext *mRTLPangoContext;
2791     + PangoAttrList *mPangoAttrList;
2792     + PRBool mIsRTL;
2793     +
2794     + // Cached font metrics
2795     + nscoord mXHeight;
2796     + nscoord mSuperscriptOffset;
2797     + nscoord mSubscriptOffset;
2798     + nscoord mStrikeoutOffset;
2799     + nscoord mStrikeoutSize;
2800     + nscoord mUnderlineOffset;
2801     + nscoord mUnderlineSize;
2802     + nscoord mMaxHeight;
2803     + nscoord mLeading;
2804     + nscoord mEmHeight;
2805     + nscoord mEmAscent;
2806     + nscoord mEmDescent;
2807     + nscoord mMaxAscent;
2808     + nscoord mMaxDescent;
2809     + nscoord mMaxAdvance;
2810     + nscoord mSpaceWidth;
2811     + nscoord mAveCharWidth;
2812     +
2813     + // Private methods
2814     + nsresult RealizeFont(void);
2815     + nsresult CacheFontMetrics(void);
2816     +
2817     + static PRBool EnumFontCallback(const nsString &aFamily,
2818     + PRBool aIsGeneric, void *aData);
2819     +
2820     + void DrawStringSlowly(const gchar *aText,
2821     + const PRUnichar *aOrigString,
2822     + PRUint32 aLength,
2823     + GdkDrawable *aDrawable,
2824     + GdkGC *aGC, gint aX, gint aY,
2825     + PangoLayoutLine *aLine,
2826     + const nscoord *aSpacing);
2827     +
2828     + nsresult GetTextDimensionsInternal(const gchar* aString,
2829     + PRInt32 aLength,
2830     + PRInt32 aAvailWidth,
2831     + PRInt32* aBreaks,
2832     + PRInt32 aNumBreaks,
2833     + nsTextDimensions& aDimensions,
2834     + PRInt32& aNumCharsFit,
2835     + nsTextDimensions& aLastWordDimensions,
2836     + nsRenderingContextGTK *aContext);
2837     +};
2838     +
2839     +class nsFontEnumeratorPango : public nsIFontEnumerator
2840     +{
2841     +public:
2842     + nsFontEnumeratorPango();
2843     + NS_DECL_ISUPPORTS
2844     + NS_DECL_NSIFONTENUMERATOR
2845     +};
2846     --- mozilla/gfx/src/gtk/nsFontMetricsUtils.h.foo 2002-10-11 22:03:32.000000000 -0400
2847     +++ mozilla/gfx/src/gtk/nsFontMetricsUtils.h 2004-10-18 22:49:40.000000000 -0400
2848     @@ -42,9 +42,12 @@
2849     extern PRUint32 NS_FontMetricsGetHints (void);
2850     extern nsresult NS_FontMetricsFamilyExists(nsIDeviceContext *aDevice,
2851     const nsString &aName);
2852     -
2853     #ifdef MOZ_ENABLE_XFT
2854     extern PRBool NS_IsXftEnabled(void);
2855     #endif
2856    
2857     +#ifdef MOZ_ENABLE_PANGO
2858     +extern PRBool NS_IsPangoEnabled(void);
2859     +#endif
2860     +
2861     #endif /* __nsFontMetricsUtils_h */
2862     --- mozilla/gfx/src/gtk/nsIFontMetricsGTK.h.foo 2002-10-11 23:00:17.000000000 -0400
2863     +++ mozilla/gfx/src/gtk/nsIFontMetricsGTK.h 2004-10-18 22:49:40.000000000 -0400
2864     @@ -121,6 +121,9 @@
2865     // particular handle.
2866     virtual GdkFont* GetCurrentGDKFont(void) = 0;
2867    
2868     + // Set the direction of the text rendering
2869     + virtual nsresult SetRightToLeftText(PRBool aIsRTL) = 0;
2870     +
2871     };
2872    
2873     #endif /* __nsIFontMetricsGTK_h */
2874     --- mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp.foo 2004-02-12 11:52:22.000000000 -0500
2875     +++ mozilla/gfx/src/gtk/nsRenderingContextGTK.cpp 2004-10-18 22:49:40.000000000 -0400
2876     @@ -524,6 +524,9 @@
2877    
2878     values.foreground.pixel =
2879     gdk_rgb_xpixel_from_rgb(NS_TO_GDK_RGB(mCurrentColor));
2880     + values.foreground.red = (NS_GET_R(mCurrentColor) << 8) | NS_GET_R(mCurrentColor);
2881     + values.foreground.green = (NS_GET_G(mCurrentColor) << 8) | NS_GET_G(mCurrentColor);
2882     + values.foreground.blue = (NS_GET_B(mCurrentColor) << 8) | NS_GET_B(mCurrentColor);
2883     valuesMask = GDK_GC_FOREGROUND;
2884    
2885     #ifdef MOZ_ENABLE_COREXFONTS
2886     @@ -1438,6 +1441,11 @@
2887    
2888     #endif /* MOZ_MATHML */
2889    
2890     +NS_IMETHODIMP nsRenderingContextGTK::SetRightToLeftText(PRBool aIsRTL)
2891     +{
2892     + return mFontMetrics->SetRightToLeftText(aIsRTL);
2893     +}
2894     +
2895     NS_IMETHODIMP nsRenderingContextGTK::DrawImage(imgIContainer *aImage, const nsRect * aSrcRect, const nsPoint * aDestPoint)
2896     {
2897     UpdateGC();
2898     --- mozilla/gfx/src/gtk/nsGCCache.cpp.foo 2002-02-02 22:47:15.000000000 -0500
2899     +++ mozilla/gfx/src/gtk/nsGCCache.cpp 2004-10-18 22:49:40.000000000 -0400
2900     @@ -232,98 +232,42 @@
2901     // We have old GC, reuse it and check what
2902     // we have to change
2903    
2904     - XGCValues xvalues;
2905     - unsigned long xvalues_mask=0;
2906     + GdkGCValues xvalues;
2907     + int xvalues_mask = 0;
2908    
2909     if (entry->clipRegion) {
2910     // set it to none here and then set the clip region with
2911     // gdk_gc_set_clip_region in GetGC()
2912     xvalues.clip_mask = None;
2913     - xvalues_mask |= GCClipMask;
2914     + xvalues_mask |= GDK_GC_CLIP_MASK;
2915     gdk_region_destroy(entry->clipRegion);
2916     entry->clipRegion = NULL;
2917     }
2918    
2919     if (entry->gcv.foreground.pixel != gcv->foreground.pixel) {
2920     - xvalues.foreground = gcv->foreground.pixel;
2921     - xvalues_mask |= GCForeground;
2922     + xvalues.foreground.pixel = gcv->foreground.pixel;
2923     + xvalues_mask |= GDK_GC_FOREGROUND;
2924     }
2925    
2926     if (entry->gcv.function != gcv->function) {
2927     - switch (gcv->function) {
2928     - case GDK_COPY:
2929     - xvalues.function = GXcopy;
2930     - break;
2931     - case GDK_INVERT:
2932     - xvalues.function = GXinvert;
2933     - break;
2934     - case GDK_XOR:
2935     - xvalues.function = GXxor;
2936     - break;
2937     - case GDK_CLEAR:
2938     - xvalues.function = GXclear;
2939     - break;
2940     - case GDK_AND:
2941     - xvalues.function = GXand;
2942     - break;
2943     - case GDK_AND_REVERSE:
2944     - xvalues.function = GXandReverse;
2945     - break;
2946     - case GDK_AND_INVERT:
2947     - xvalues.function = GXandInverted;
2948     - break;
2949     - case GDK_NOOP:
2950     - xvalues.function = GXnoop;
2951     - break;
2952     - case GDK_OR:
2953     - xvalues.function = GXor;
2954     - break;
2955     - case GDK_EQUIV:
2956     - xvalues.function = GXequiv;
2957     - break;
2958     - case GDK_OR_REVERSE:
2959     - xvalues.function = GXorReverse;
2960     - break;
2961     - case GDK_COPY_INVERT:
2962     - xvalues.function = GXcopyInverted;
2963     - break;
2964     - case GDK_OR_INVERT:
2965     - xvalues.function = GXorInverted;
2966     - break;
2967     - case GDK_NAND:
2968     - xvalues.function = GXnand;
2969     - break;
2970     - case GDK_SET:
2971     - xvalues.function = GXset;
2972     - break;
2973     - }
2974     - xvalues_mask |= GCFunction;
2975     + xvalues.function = gcv->function;
2976     + xvalues_mask |= GDK_GC_FUNCTION;
2977     }
2978    
2979     if(entry->gcv.font != gcv->font && flags & GDK_GC_FONT) {
2980     - xvalues.font = ((XFontStruct *)GDK_FONT_XFONT(gcv->font))->fid;
2981     - xvalues_mask |= GCFont;
2982     + xvalues.font = gcv->font;
2983     + xvalues_mask |= GDK_GC_FONT;
2984     }
2985    
2986     if (entry->gcv.line_style != gcv->line_style) {
2987     - switch (gcv->line_style) {
2988     - case GDK_LINE_SOLID:
2989     - xvalues.line_style = LineSolid;
2990     - break;
2991     - case GDK_LINE_ON_OFF_DASH:
2992     - xvalues.line_style = LineOnOffDash;
2993     - break;
2994     - case GDK_LINE_DOUBLE_DASH:
2995     - xvalues.line_style = LineDoubleDash;
2996     - break;
2997     - }
2998     - xvalues_mask |= GCLineStyle;
2999     + xvalues.line_style = gcv->line_style;
3000     + xvalues_mask |= GDK_GC_LINE_STYLE;
3001     }
3002    
3003     if (xvalues_mask != 0) {
3004     - XChangeGC(GDK_GC_XDISPLAY(entry->gc), GDK_GC_XGC(entry->gc),
3005     - xvalues_mask, &xvalues);
3006     + gdk_gc_set_values(entry->gc, &xvalues, (GdkGCValuesMask)xvalues_mask);
3007     }
3008     +
3009     entry->flags = flags;
3010     entry->gcv = *gcv;
3011     }
3012     --- mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp.foo 2004-03-09 09:14:54.000000000 -0500
3013     +++ mozilla/gfx/src/gtk/nsFontMetricsGTK.cpp 2004-10-18 22:49:40.000000000 -0400
3014     @@ -4600,6 +4600,12 @@
3015     return mCurrentFont->GetGDKFont();
3016     }
3017    
3018     +nsresult
3019     +nsFontMetricsGTK::SetRightToLeftText(PRBool aIsRTL)
3020     +{
3021     + return NS_OK;
3022     +}
3023     +
3024     PR_BEGIN_EXTERN_C
3025     static int
3026     CompareSizes(const void* aArg1, const void* aArg2, void *data)
3027     --- mozilla/gfx/src/gtk/nsFontMetricsXft.h.foo 2004-02-23 16:38:52.000000000 -0500
3028     +++ mozilla/gfx/src/gtk/nsFontMetricsXft.h 2004-10-18 22:49:40.000000000 -0400
3029     @@ -202,6 +202,8 @@
3030    
3031     virtual GdkFont* GetCurrentGDKFont(void);
3032    
3033     + virtual nsresult SetRightToLeftText(PRBool aIsRTL);
3034     +
3035     // get hints for the font
3036     static PRUint32 GetHints (void);
3037    
3038     --- mozilla/gfx/src/gtk/nsFontMetricsGTK.h.foo 2004-02-04 20:57:03.000000000 -0500
3039     +++ mozilla/gfx/src/gtk/nsFontMetricsGTK.h 2004-10-18 22:49:40.000000000 -0400
3040     @@ -344,6 +344,8 @@
3041    
3042     virtual GdkFont* GetCurrentGDKFont(void);
3043    
3044     + virtual nsresult SetRightToLeftText(PRBool aIsRTL);
3045     +
3046     static nsresult FamilyExists(nsIDeviceContext *aDevice, const nsString& aName);
3047     static PRUint32 GetHints(void);
3048    
3049     --- mozilla/configure.in.foo 2004-05-25 22:25:16.000000000 -0400
3050     +++ mozilla/configure.in 2004-10-18 22:49:40.000000000 -0400
3051     @@ -3429,6 +3429,34 @@
3052     AC_SUBST(MOZ_XFT_LIBS)
3053    
3054     dnl ========================================================
3055     +dnl = pango font rendering
3056     +dnl ========================================================
3057     +MOZ_ARG_ENABLE_BOOL(pango,
3058     +[ --enable-pango Enable Pango font rendering support],
3059     + MOZ_ENABLE_PANGO=1,
3060     + MOZ_ENABLE_PANGO=)
3061     +
3062     +if test "$MOZ_ENABLE_PANGO"
3063     +then
3064     + AC_DEFINE(MOZ_ENABLE_PANGO)
3065     + PKG_CHECK_MODULES(MOZ_PANGO, pango >= 1.5.0)
3066     +
3067     + dnl Make sure that the pango version is _actually_ new enough
3068     + _SAVE_CFLAGS=$CFLAGS
3069     + _SAVE_LDFLAGS=$LDFLAGS
3070     + CFLAGS="$MOZ_PANGO_CFLAGS $CFLAGS"
3071     + LDFLAGS="$MOZ_PANGO_LIBS $LDFLAGS"
3072     + AC_CHECK_LIB(pangoft2-1.0, pango_fc_font_map_add_decoder_find_func,,
3073     + AC_MSG_ERROR([Your Pango is too old. Sorry.]))
3074     + CFLAGS=$_SAVE_CFLAGS
3075     + LDFLAGS=$_SAVE_LDFLAGS
3076     +
3077     + AC_SUBST(MOZ_ENABLE_PANGO)
3078     + AC_SUBST(MOZ_PANGO_CFLAGS)
3079     + AC_SUBST(MOZ_PANGO_LIBS)
3080     +fi
3081     +
3082     +dnl ========================================================
3083     dnl = disabling x11 core support, enabled by default
3084     dnl ========================================================
3085     MOZ_ENABLE_COREXFONTS=${MOZ_ENABLE_COREXFONTS-1}