]> git.pld-linux.org Git - packages/firefox.git/commitdiff
This commit was manufactured by cvs2git to create branch 'DEVEL'.
authorcvs2git <feedback@pld-linux.org>
Sun, 17 May 2009 09:08:50 +0000 (09:08 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Cherrypick from master 2008-06-23 12:58:27 UTC hawk <hawk@pld-linux.org> '- better way to show "Add exception" button directly w/o clicking through stupid links':
    mozilla-firefox-414239.patch -> 1.1
    mozilla-firefox-agent-ac.patch -> 1.1
    mozilla-firefox-agent.patch -> 1.2
    mozilla-firefox-branding.patch -> 1.3
    mozilla-firefox-fonts.patch -> 1.2
    mozilla-firefox-gcc3.patch -> 1.1
    mozilla-firefox-install.patch -> 1.2
    mozilla-firefox-myspell.patch -> 1.3
    mozilla-firefox-nss_cflags.patch -> 1.1
    mozilla-firefox-pango-cursor-position-more.patch -> 1.1
    mozilla-firefox-pango-cursor-position.patch -> 1.1
    mozilla-firefox-pango-justified-range.patch -> 1.1
    mozilla-firefox-pango-printing.patch -> 1.1
    mozilla-firefox-pango-underline.patch -> 1.1
    mozilla-firefox-prefs.patch -> 1.4
    mozilla-firefox-ti-agent.patch -> 1.1
    mozilla-firefox-xft-randewidth.patch -> 1.1
    mozilla-firefox.desktop -> 1.6
    mozilla-install.patch -> 1.1
Cherrypick from master 2006-01-16 15:32:05 UTC blekot <blekot@pld-linux.org> '- taken from mandriva cvs':
    mozilla-firefox-lang.patch -> 1.1
    mozilla-firefox-nopangoxft.patch -> 1.1
    mozilla-firefox-nss.patch -> 1.2
Cherrypick from master 2009-05-17 09:08:50 UTC bszx <bszx@pld-linux.org> '- updated to 3.0.10':
    mozilla-firefox-urls.patch -> 1.1
    mozilla-firefox.spec -> 1.266
Cherrypick from master 2006-11-12 14:49:22 UTC Elan Ruusamäe <glen@pld-linux.org> '- wtf, 0 = 0??':
    mozilla-firefox.sh -> 1.15
Cherrypick from master 2007-11-30 17:40:46 UTC Arkadiusz Miśkiewicz <arekm@maven.pl> '- add font fixes from fedora':
    mozilla-firefox-pango-ligatures.patch -> 1.1

26 files changed:
mozilla-firefox-414239.patch [new file with mode: 0644]
mozilla-firefox-agent-ac.patch [new file with mode: 0644]
mozilla-firefox-agent.patch [new file with mode: 0644]
mozilla-firefox-branding.patch [new file with mode: 0644]
mozilla-firefox-fonts.patch [new file with mode: 0644]
mozilla-firefox-gcc3.patch [new file with mode: 0644]
mozilla-firefox-install.patch [new file with mode: 0644]
mozilla-firefox-lang.patch [new file with mode: 0644]
mozilla-firefox-myspell.patch [new file with mode: 0644]
mozilla-firefox-nopangoxft.patch [new file with mode: 0644]
mozilla-firefox-nss.patch [new file with mode: 0644]
mozilla-firefox-nss_cflags.patch [new file with mode: 0644]
mozilla-firefox-pango-cursor-position-more.patch [new file with mode: 0644]
mozilla-firefox-pango-cursor-position.patch [new file with mode: 0644]
mozilla-firefox-pango-justified-range.patch [new file with mode: 0644]
mozilla-firefox-pango-ligatures.patch [new file with mode: 0644]
mozilla-firefox-pango-printing.patch [new file with mode: 0644]
mozilla-firefox-pango-underline.patch [new file with mode: 0644]
mozilla-firefox-prefs.patch [new file with mode: 0644]
mozilla-firefox-ti-agent.patch [new file with mode: 0644]
mozilla-firefox-urls.patch [new file with mode: 0644]
mozilla-firefox-xft-randewidth.patch [new file with mode: 0644]
mozilla-firefox.desktop [new file with mode: 0644]
mozilla-firefox.sh [new file with mode: 0644]
mozilla-firefox.spec [new file with mode: 0644]
mozilla-install.patch [new file with mode: 0644]

diff --git a/mozilla-firefox-414239.patch b/mozilla-firefox-414239.patch
new file mode 100644 (file)
index 0000000..62139b4
--- /dev/null
@@ -0,0 +1,40 @@
+Index: gfx/thebes/src/gfxPangoFonts.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/thebes/src/gfxPangoFonts.cpp,v
+retrieving revision 1.128
+diff -u -p -U 8 -r1.128 gfxPangoFonts.cpp
+--- gfx/thebes/src/gfxPangoFonts.cpp   27 Jan 2008 10:27:08 -0000      1.128
++++ gfx/thebes/src/gfxPangoFonts.cpp   1 Feb 2008 20:07:47 -0000
+@@ -371,24 +371,28 @@ NewPangoFontDescription(const nsAString 
+ /* static */
+ already_AddRefed<gfxPangoFont>
+ gfxPangoFont::GetOrMakeFont(PangoFont *aPangoFont)
+ {
+     gfxPangoFont *font = static_cast<gfxPangoFont*>
+         (g_object_get_qdata(G_OBJECT(aPangoFont), GetFontQuark()));
+     if (!font) {
+-        PangoFontDescription *desc =
+-            pango_font_describe_with_absolute_size(aPangoFont);
++        // pango_font_describe_with_absolute_size requires Pango-1.14
++        PangoFontDescription *desc = pango_font_describe(aPangoFont);
++
++        PangoFcFont *fcfont = PANGO_FC_FONT(aPangoFont);
++        double size;
++        if (FcPatternGetDouble(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size)
++            != FcResultMatch)
++            size = pango_font_description_get_size(desc) / FLOAT_PANGO_SCALE;
+         // Shouldn't actually need to take too much care about the correct
+         // family or style, as size is the only thing expected to be
+         // important.
+-        gfxFloat size =
+-            pango_font_description_get_size(desc) / FLOAT_PANGO_SCALE;
+         PRUint8 style =
+             PangoStyleToThebesStyle(pango_font_description_get_style(desc));
+         PRUint16 weight = pango_font_description_get_weight(desc);
+         NS_NAMED_LITERAL_CSTRING(langGroup, "x-unicode");
+         gfxFontStyle fontStyle(style, weight, size, langGroup, 0.0,
+                                PR_TRUE, PR_FALSE);
+         // (The PangoFontDescription owns the family string)
diff --git a/mozilla-firefox-agent-ac.patch b/mozilla-firefox-agent-ac.patch
new file mode 100644 (file)
index 0000000..f6533d5
--- /dev/null
@@ -0,0 +1,12 @@
+--- mozilla-firefox/browser/app/profile/firefox.js.orig        2007-03-21 17:21:55.000000000 +0100
++++ mozilla-firefox/browser/app/profile/firefox.js     2007-03-21 17:23:53.000000000 +0100
+@@ -163,6 +163,9 @@
+ pref("general.useragent.locale", "@AB_CD@");
+ pref("general.skins.selectedSkin", "classic/1.0");
+ pref("general.useragent.extra.firefox", "@APP_UA_NAME@/@APP_VERSION@");
++pref("general.useragent.vendor", "PLD");
++pref("general.useragent.vendorSub", "2.0");
++pref("general.useragent.vendorComment", "Ac");
+ pref("general.smoothScroll", false);
+ #ifdef UNIX_BUT_NOT_MAC
diff --git a/mozilla-firefox-agent.patch b/mozilla-firefox-agent.patch
new file mode 100644 (file)
index 0000000..d5a5d7e
--- /dev/null
@@ -0,0 +1,12 @@
+--- mozilla-firefox/browser/app/profile/firefox.js.orig        2007-03-21 17:21:55.000000000 +0100
++++ mozilla-firefox/browser/app/profile/firefox.js     2007-03-21 17:23:53.000000000 +0100
+@@ -163,6 +163,9 @@
+ pref("general.useragent.locale", "@AB_CD@");
+ pref("general.skins.selectedSkin", "classic/1.0");
+ pref("general.useragent.extra.firefox", "@APP_UA_NAME@/@APP_VERSION@");
++pref("general.useragent.vendor", "PLD");
++pref("general.useragent.vendorSub", "3.0");
++pref("general.useragent.vendorComment", "Th");
+ pref("general.smoothScroll", false);
+ #ifdef UNIX_BUT_NOT_MAC
diff --git a/mozilla-firefox-branding.patch b/mozilla-firefox-branding.patch
new file mode 100644 (file)
index 0000000..07d5574
--- /dev/null
@@ -0,0 +1,62 @@
+diff -ur mozilla.orig/browser/app/firefox-branding.js mozilla/browser/app/firefox-branding.js
+--- mozilla.orig/browser/app/firefox-branding.js       2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/app/firefox-branding.js    2008-06-21 15:31:20.000000000 +0200
+@@ -1,5 +1,6 @@
+-pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
+-pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
++pref("browser.startup.homepage_override.mstone", "ignore");
++pref("startup.homepage_override_url","");
++pref("startup.homepage_welcome_url","");
+ // URL user can browse to manually if for some reason all update installation
+ // attempts fail.
+ pref("app.update.url.manual", "http://www.mozilla.org/products/%APP%/");
+@@ -8,7 +9,7 @@
+ pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
+ // Release notes URL
+-pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
++pref("app.releaseNotesURL", "http://www.mozilla.com/%LOCALE%/%APP%/%VERSION%/releasenotes/");
+ // Search codes belong only in builds with official branding
+ pref("browser.search.param.yahoo-fr", "");
+diff -ur mozilla.orig/browser/base/content/browserconfig.properties mozilla/browser/base/content/browserconfig.properties
+--- mozilla.orig/browser/base/content/browserconfig.properties 2008-06-21 12:55:29.000000000 +0200
++++ mozilla/browser/base/content/browserconfig.properties      2008-06-21 15:05:50.000000000 +0200
+@@ -1,2 +1,2 @@
+ # Do NOT localize or otherwise change these values
+-browser.startup.homepage=http://www.mozilla.org/projects/minefield/
++browser.startup.homepage=http://www.pld-linux.org/
+diff -ur mozilla.orig/browser/locales/en-US/chrome/branding/brand.dtd mozilla/browser/locales/en-US/chrome/branding/brand.dtd
+--- mozilla.orig/browser/locales/en-US/chrome/branding/brand.dtd       2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/locales/en-US/chrome/branding/brand.dtd    2008-06-21 16:13:49.000000000 +0200
+@@ -1,3 +1,3 @@
+-<!ENTITY  brandShortName        "Minefield">
+-<!ENTITY  brandFullName         "Minefield">            
++<!ENTITY  brandShortName        "Firefox Community Edition">
++<!ENTITY  brandFullName         "Firefox Community Edition">            
+ <!ENTITY  vendorShortName       "Mozilla">
+diff -ur mozilla.orig/browser/locales/en-US/chrome/branding/brand.properties mozilla/browser/locales/en-US/chrome/branding/brand.properties
+--- mozilla.orig/browser/locales/en-US/chrome/branding/brand.properties        2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/locales/en-US/chrome/branding/brand.properties     2008-06-21 16:14:14.000000000 +0200
+@@ -1,3 +1,3 @@
+-brandShortName=Minefield
+-brandFullName=Minefield
++brandShortName=Firefox Community Edition
++brandFullName=Firefox Community Edition
+ vendorShortName=Mozilla
+diff -ur mozilla.orig/browser/locales/en-US/profile/bookmarks.html mozilla/browser/locales/en-US/profile/bookmarks.html
+--- mozilla.orig/browser/locales/en-US/profile/bookmarks.html  2008-06-22 15:20:46.000000000 +0200
++++ mozilla/browser/locales/en-US/profile/bookmarks.html       2008-06-22 17:42:09.000000000 +0200
+@@ -23,4 +23,12 @@
+         <DT><A HREF="http://en-US.www.mozilla.com/en-US/firefox/community/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" ID="rdf:#$42iCK1">Get Involved</A>
+         <DT><A HREF="http://en-US.www.mozilla.com/en-US/firefox/about/" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg==" ID="rdf:#$52iCK1">About Us</A>
+     </DL><p>
++    <DT><H3>PLD Linux Distribution</H3>
++    <DL><p>
++        <DT><A HREF="http://www.pld-linux.org/" ICON_URI="http://www.pld-linux.org/favicon.ico" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHUlEQVQ4jc1SwWqDQBB91pyFpsWLSGklRVHw7CnJLyTpzaMf4Dck5Feay4bc96T4BQkevCTiXc0nTA9lxbIJ2FP7YFh2Zt+bN8MCfw1lyKPmWhNjDACwWq3w9Pjc8UZDBBhj4JxjPB5j97n7UXu4RTjlR2quNYk75xwA0LYtJu8T9GsSNts1KSrIcW3aHxg115oM0yDHtUlRQcuPxX2ywGw+JUUFGaZBaZaQoqKLQQKiq3DSF0iz5L7AKT92RTFKPxzXlsjdEtMsId/3ISzqui41iONYyo2E5eViiSiKEIYhLMui8/l802VZXUjTNOR5Ds/zvhOb7ZrK6iLZ2x8YzeZTMkxDOsWSlbK60OvL26Af2R+3KAoEQfAb2n/FF3KJkR/xf7tGAAAAAElFTkSuQmCC">PLD Home Page</A>
++        <DT><A HREF="http://www.pld-users.org/" ICON_URI="http://www.pld-linux.org/favicon.ico" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHUlEQVQ4jc1SwWqDQBB91pyFpsWLSGklRVHw7CnJLyTpzaMf4Dck5Feay4bc96T4BQkevCTiXc0nTA9lxbIJ2FP7YFh2Zt+bN8MCfw1lyKPmWhNjDACwWq3w9Pjc8UZDBBhj4JxjPB5j97n7UXu4RTjlR2quNYk75xwA0LYtJu8T9GsSNts1KSrIcW3aHxg115oM0yDHtUlRQcuPxX2ywGw+JUUFGaZBaZaQoqKLQQKiq3DSF0iz5L7AKT92RTFKPxzXlsjdEtMsId/3ISzqui41iONYyo2E5eViiSiKEIYhLMui8/l802VZXUjTNOR5Ds/zvhOb7ZrK6iLZ2x8YzeZTMkxDOsWSlbK60OvL26Af2R+3KAoEQfAb2n/FF3KJkR/xf7tGAAAAAElFTkSuQmCC">PLD Users Wiki</A>
++        <DT><A HREF="http://docs.pld-linux.org/" ICON_URI="http://www.pld-linux.org/favicon.ico" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHUlEQVQ4jc1SwWqDQBB91pyFpsWLSGklRVHw7CnJLyTpzaMf4Dck5Feay4bc96T4BQkevCTiXc0nTA9lxbIJ2FP7YFh2Zt+bN8MCfw1lyKPmWhNjDACwWq3w9Pjc8UZDBBhj4JxjPB5j97n7UXu4RTjlR2quNYk75xwA0LYtJu8T9GsSNts1KSrIcW3aHxg115oM0yDHtUlRQcuPxX2ywGw+JUUFGaZBaZaQoqKLQQKiq3DSF0iz5L7AKT92RTFKPxzXlsjdEtMsId/3ISzqui41iONYyo2E5eViiSiKEIYhLMui8/l802VZXUjTNOR5Ds/zvhOb7ZrK6iLZ2x8YzeZTMkxDOsWSlbK60OvL26Af2R+3KAoEQfAb2n/FF3KJkR/xf7tGAAAAAElFTkSuQmCC">PLD Documentation in english</A>
++        <DT><A HREF="http://pl.docs.pld-linux.org/" ICON_URI="http://www.pld-linux.org/favicon.ico" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHUlEQVQ4jc1SwWqDQBB91pyFpsWLSGklRVHw7CnJLyTpzaMf4Dck5Feay4bc96T4BQkevCTiXc0nTA9lxbIJ2FP7YFh2Zt+bN8MCfw1lyKPmWhNjDACwWq3w9Pjc8UZDBBhj4JxjPB5j97n7UXu4RTjlR2quNYk75xwA0LYtJu8T9GsSNts1KSrIcW3aHxg115oM0yDHtUlRQcuPxX2ywGw+JUUFGaZBaZaQoqKLQQKiq3DSF0iz5L7AKT92RTFKPxzXlsjdEtMsId/3ISzqui41iONYyo2E5eViiSiKEIYhLMui8/l802VZXUjTNOR5Ds/zvhOb7ZrK6iLZ2x8YzeZTMkxDOsWSlbK60OvL26Af2R+3KAoEQfAb2n/FF3KJkR/xf7tGAAAAAElFTkSuQmCC">PLD Documentation in polish</A>
++        <DT><A HREF="http://planet.pld-linux.org/" ICON_URI="http://www.pld-linux.org/favicon.ico" ICON="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHUlEQVQ4jc1SwWqDQBB91pyFpsWLSGklRVHw7CnJLyTpzaMf4Dck5Feay4bc96T4BQkevCTiXc0nTA9lxbIJ2FP7YFh2Zt+bN8MCfw1lyKPmWhNjDACwWq3w9Pjc8UZDBBhj4JxjPB5j97n7UXu4RTjlR2quNYk75xwA0LYtJu8T9GsSNts1KSrIcW3aHxg115oM0yDHtUlRQcuPxX2ywGw+JUUFGaZBaZaQoqKLQQKiq3DSF0iz5L7AKT92RTFKPxzXlsjdEtMsId/3ISzqui41iONYyo2E5eViiSiKEIYhLMui8/l802VZXUjTNOR5Ds/zvhOb7ZrK6iLZ2x8YzeZTMkxDOsWSlbK60OvL26Af2R+3KAoEQfAb2n/FF3KJkR/xf7tGAAAAAElFTkSuQmCC">Planet PLD</A>
++    </DL><p>
+ </DL><p>
diff --git a/mozilla-firefox-fonts.patch b/mozilla-firefox-fonts.patch
new file mode 100644 (file)
index 0000000..61ece27
--- /dev/null
@@ -0,0 +1,140 @@
+--- mozilla.orig/modules/libpref/src/init/all.js       2006-05-08 22:22:51.000000000 +0200
++++ mozilla/modules/libpref/src/init/all.js    2006-07-25 07:44:06.744790000 +0200
+@@ -1886,33 +1886,33 @@
+ // th
+-pref("font.name.serif.tr", "Times");
+-pref("font.name.sans-serif.tr", "Helvetica");
+-pref("font.name.monospace.tr", "Courier");
++pref("font.name.serif.tr", "serif");
++pref("font.name.sans-serif.tr", "sans-serif");
++pref("font.name.monospace.tr", "monospace");
+ pref("font.name.serif.x-baltic", "serif");
+ pref("font.name.sans-serif.x-baltic", "sans-serif");
+ pref("font.name.monospace.x-baltic", "monospace");
+-pref("font.name.serif.x-central-euro", "Times");
+-pref("font.name.sans-serif.x-central-euro", "Helvetica");
+-pref("font.name.monospace.x-central-euro", "Courier");
++pref("font.name.serif.x-central-euro", "serif");
++pref("font.name.sans-serif.x-central-euro", "sans-serif");
++pref("font.name.monospace.x-central-euro", "monospace");
+ pref("font.name.serif.x-cyrillic", "serif");
+ pref("font.name.sans-serif.x-cyrillic", "sans-serif");
+ pref("font.name.monospace.x-cyrillic", "monospace");
+-pref("font.name.serif.x-unicode", "Times");
+-pref("font.name.sans-serif.x-unicode", "Helvetica");
+-pref("font.name.monospace.x-unicode", "Courier");
+-
+-pref("font.name.serif.x-user-def", "Times");
+-pref("font.name.sans-serif.x-user-def", "Helvetica");
+-pref("font.name.monospace.x-user-def", "Courier");
+-
+-pref("font.name.serif.x-western", "Times");
+-pref("font.name.sans-serif.x-western", "Helvetica");
+-pref("font.name.monospace.x-western", "Courier");
++pref("font.name.serif.x-unicode", "serif");
++pref("font.name.sans-serif.x-unicode", "sans-serif");
++pref("font.name.monospace.x-unicode", "monospace");
++
++pref("font.name.serif.x-user-def", "serif");
++pref("font.name.sans-serif.x-user-def", "sans-serif");
++pref("font.name.monospace.x-user-def", "monospace");
++
++pref("font.name.serif.x-western", "serif");
++pref("font.name.sans-serif.x-western", "sans-serif");
++pref("font.name.monospace.x-western", "monospace");
+ pref("font.name.serif.zh-CN", "serif");
+ pref("font.name.sans-serif.zh-CN", "sans-serif");
+@@ -1989,63 +1989,63 @@
+ pref("font.default.ar", "sans-serif");
+ pref("font.size.variable.ar", 16);
+-pref("font.size.fixed.ar", 12);
++pref("font.size.fixed.ar", 14);
+-pref("font.default.el", "serif");
++pref("font.default.el", "sans-serif");
+ pref("font.size.variable.el", 16);
+-pref("font.size.fixed.el", 12);
++pref("font.size.fixed.el", 14);
+ pref("font.default.he", "sans-serif");
+ pref("font.size.variable.he", 16);
+-pref("font.size.fixed.he", 12);
++pref("font.size.fixed.he", 14);
+ pref("font.default.ja", "sans-serif");
+ pref("font.size.variable.ja", 16);
+-pref("font.size.fixed.ja", 16);
++pref("font.size.fixed.ja", 14);
+ pref("font.default.ko", "sans-serif");
+ pref("font.size.variable.ko", 16);
+-pref("font.size.fixed.ko", 16);
++pref("font.size.fixed.ko", 14);
+-pref("font.default.th", "serif");
++pref("font.default.th", "sans-serif");
+ pref("font.size.variable.th", 16);
+-pref("font.size.fixed.th", 12);
++pref("font.size.fixed.th", 14);
+-pref("font.default.tr", "serif");
++pref("font.default.tr", "sans-serif");
+ pref("font.size.variable.tr", 16);
+-pref("font.size.fixed.tr", 12);
++pref("font.size.fixed.tr", 14);
+-pref("font.default.x-baltic", "serif");
++pref("font.default.x-baltic", "sans-serif");
+ pref("font.size.variable.x-baltic", 16);
+-pref("font.size.fixed.x-baltic", 12);
++pref("font.size.fixed.x-baltic", 14);
+-pref("font.default.x-central-euro", "serif");
++pref("font.default.x-central-euro", "sans-serif");
+ pref("font.size.variable.x-central-euro", 16);
+-pref("font.size.fixed.x-central-euro", 12);
++pref("font.size.fixed.x-central-euro", 14);
+-pref("font.default.x-cyrillic", "serif");
++pref("font.default.x-cyrillic", "sans-serif");
+ pref("font.size.variable.x-cyrillic", 16);
+-pref("font.size.fixed.x-cyrillic", 12);
++pref("font.size.fixed.x-cyrillic", 14);
+-pref("font.default.x-unicode", "serif");
++pref("font.default.x-unicode", "sans-serif");
+ pref("font.size.variable.x-unicode", 16);
+-pref("font.size.fixed.x-unicode", 12);
++pref("font.size.fixed.x-unicode", 14);
+-pref("font.default.x-western", "serif");
++pref("font.default.x-western", "sans-serif");
+ pref("font.size.variable.x-western", 16);
+-pref("font.size.fixed.x-western", 12);
++pref("font.size.fixed.x-western", 14);
+ pref("font.default.zh-CN", "sans-serif");
+ pref("font.size.variable.zh-CN", 16);
+-pref("font.size.fixed.zh-CN", 16);
++pref("font.size.fixed.zh-CN", 14);
+ pref("font.default.zh-TW", "sans-serif");
+ pref("font.size.variable.zh-TW", 16);
+-pref("font.size.fixed.zh-TW", 16);
++pref("font.size.fixed.zh-TW", 14);
+ pref("font.default.zh-HK", "sans-serif");
+ pref("font.size.variable.zh-HK", 16);
+-pref("font.size.fixed.zh-HK", 16);
++pref("font.size.fixed.zh-HK", 14);
+ // below a certian pixel size outline scaled fonts produce poor results
+ pref("font.scale.outline.min",      6);
diff --git a/mozilla-firefox-gcc3.patch b/mozilla-firefox-gcc3.patch
new file mode 100644 (file)
index 0000000..5f4efc6
--- /dev/null
@@ -0,0 +1,41 @@
+in short: that '-z defs' makes tls symbols invisible on gcc 3.3.6
+
+gmake[1]: Entering directory `/home/glen/rpm/pld/BUILD/mozilla-firefox-3.0/mozilla/obj-amd64/memory/jemalloc'
+rm -f libjemalloc.so
+ccache amd64-pld-linux-g++ -I/usr/X11R6/include -fno-rtti -fno-exceptions -Wall -Wconversion -Wpointer-arith -Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -Wcast-align -Wno-long-long -pedantic -fno-strict-aliasing -fshort-wchar -pthread -pipe  -DNDEBUG -DTRIMMED -O2 -fno-strict-aliasing -fPIC -shared -Wl,-z,defs -Wl,-h,libjemalloc.so -o libjemalloc.so  jemalloc.o     -lpthread   -Wl,-rpath-link,../../dist/bin   -ldl -lm
+jemalloc.o(.text+0x1b5c): In function `choose_arena_hard':
+jemalloc.c: undefined reference to `__tls_get_addr'
+jemalloc.o(.text+0x3cf1): In function `arena_ralloc':
+jemalloc.c: undefined reference to `__tls_get_addr'
+jemalloc.o(.text+0x4921): In function `malloc_init_hard':
+jemalloc.c: undefined reference to `__tls_get_addr'
+jemalloc.o(.text+0x4ce1): In function `malloc':
+jemalloc.c: undefined reference to `__tls_get_addr'
+jemalloc.o(.text+0x4eb7): In function `calloc':
+jemalloc.c: undefined reference to `__tls_get_addr'
+jemalloc.o(.text+0x5051):jemalloc.c: more undefined references to `__tls_get_addr' follow
+collect2: ld returned 1 exit status
+gmake[1]: *** [libjemalloc.so] Error 1
+
+--- mozilla-firefox-3.0rc1/mozilla/configure~  2008-05-06 00:11:03.000000000 +0300
++++ mozilla-firefox-3.0rc1/mozilla/configure   2008-05-27 08:09:43.180357890 +0300
+@@ -5444,7 +5444,7 @@
+     DSO_LDOPTS='-shared'
+     if test "$GCC_USE_GNU_LD"; then
+         # Don't allow undefined symbols in libraries
+-        DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
++: #        DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
+     fi
+     WARNINGS_AS_ERRORS='-Werror'
+     DSO_CFLAGS=''
+--- mozilla-firefox-3.0rc1/mozilla/configure.in~       2008-05-06 00:08:14.000000000 +0300
++++ mozilla-firefox-3.0rc1/mozilla/configure.in        2008-05-27 08:09:43.210357726 +0300
+@@ -1273,7 +1273,7 @@
+     DSO_LDOPTS='-shared'
+     if test "$GCC_USE_GNU_LD"; then
+         # Don't allow undefined symbols in libraries
+-        DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
++: #        DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs"
+     fi
+     WARNINGS_AS_ERRORS='-Werror'
+     DSO_CFLAGS=''
diff --git a/mozilla-firefox-install.patch b/mozilla-firefox-install.patch
new file mode 100644 (file)
index 0000000..73a3530
--- /dev/null
@@ -0,0 +1,37 @@
+--- mozilla/toolkit/mozapps/installer/packager.mk      2006-12-23 03:38:32.302235167 +0200
++++ mozilla/toolkit/mozapps/installer/packager.mk      2008-03-05 22:59:55.020447000 +0000
+@@ -328,13 +328,13 @@
+ # NOTE: this must be a tar now that dist links into the tree so that we
+ # do not strip the binaries actually in the tree.
+       @echo "Creating package directory..."
+-      @mkdir $(DIST)/$(MOZ_PKG_APPNAME)
++      @mkdir -p $(DESTDIR)$(MOZ_PKG_APPDIR)
+ ifdef MOZ_PKG_MANIFEST
+       $(RM) -rf $(DIST)/xpt
+       $(call PACKAGER_COPY, "$(DIST)",\
+-               "$(DIST)/$(MOZ_PKG_APPNAME)", \
++               "$(DESTDIR)/$(MOZ_PKG_APPDIR)", \
+               "$(MOZ_PKG_MANIFEST)", "$(PKGCP_OS)", 1, 0, 1)
+-      $(PERL) $(topsrcdir)/xpinstall/packager/xptlink.pl -s $(DIST) -d $(DIST)/xpt -f $(DIST)/$(MOZ_PKG_APPNAME)/components -v -x "$(XPIDL_LINK)"
++      $(PERL) $(topsrcdir)/xpinstall/packager/xptlink.pl -s $(DIST) -d $(DIST)/xpt -f $(DESTDIR)/$(MOZ_PKG_APPDIR)/components -v -x "$(XPIDL_LINK)"
+ else # !MOZ_PKG_MANIFEST
+ ifeq ($(MOZ_PKG_FORMAT),DMG)
+ # If UNIVERSAL_BINARY, the package will be made from an already-prepared
+@@ -343,7 +343,7 @@
+       @cd $(DIST) && rsync -auv --copy-unsafe-links $(_APPNAME) $(MOZ_PKG_APPNAME)
+ endif
+ else
+-      @cd $(DIST)/bin && tar $(TAR_CREATE_FLAGS) - * | (cd ../$(MOZ_PKG_APPNAME); tar -xf -)
++      cp -rfLp $(DIST)/bin/* $(DESTDIR)$(MOZ_PKG_APPDIR)
+ endif # DMG
+ endif # MOZ_PKG_MANIFEST
+ ifndef PKG_SKIP_STRIP
+@@ -375,7 +375,7 @@
+ endif
+       @echo "Removing unpackaged files..."
+ ifdef NO_PKG_FILES
+-      cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME)$(_BINPATH); rm -rf $(NO_PKG_FILES)
++      cd $(DESTDIR)$(MOZ_PKG_APPDIR)$(_BINPATH); rm -rf $(NO_PKG_FILES)
+ endif
+ ifdef MOZ_PKG_REMOVALS
+       $(SYSINSTALL) $(MOZ_PKG_REMOVALS_GEN) $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME)$(_BINPATH)
diff --git a/mozilla-firefox-lang.patch b/mozilla-firefox-lang.patch
new file mode 100644 (file)
index 0000000..f0f7325
--- /dev/null
@@ -0,0 +1,12 @@
+--- mozilla/browser/app/profile/firefox.js.lang        2005-01-13 15:32:03.509282726 +0100
++++ mozilla/browser/app/profile/firefox.js     2005-01-13 15:33:40.220914789 +0100
+@@ -253,6 +253,9 @@
+ pref("font.language.group", "chrome://global/locale/intl.properties");
+ pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");
++// Use LANG environment variable to choose locale
++pref("intl.locale.matchOS", true);
++
+ // 0=lines, 1=pages, 2=history , 3=text size
+ pref("mousewheel.withcontrolkey.action",3);
+ pref("mousewheel.withshiftkey.action",2);
diff --git a/mozilla-firefox-myspell.patch b/mozilla-firefox-myspell.patch
new file mode 100644 (file)
index 0000000..45902a3
--- /dev/null
@@ -0,0 +1,222 @@
+--- firefox-2.0+0dfsg.orig/extensions/spellcheck/myspell/src/Makefile.in
++++ firefox-2.0+0dfsg/extensions/spellcheck/myspell/src/Makefile.in
+@@ -60,15 +60,18 @@
+                 xulapp \
+                 $(NULL)
+-CPPSRCS =         affentry.cpp \
++CPPSRCS =         mozMySpell.cpp \
++                mozMySpellFactory.cpp \
++                  $(NULL)
++ifndef MOZ_NATIVE_MYSPELL
++CPPSRCS +=      affentry.cpp \
+                 affixmgr.cpp \
+                 hashmgr.cpp \
+                 suggestmgr.cpp \
+                 csutil.cpp \
+                 myspell.cpp \
+-                mozMySpell.cpp \
+-                mozMySpellFactory.cpp \
+                   $(NULL)
++endif
+ ifdef MOZ_XUL_APP
+ CPPSRCS += mozMySpellDirProvider.cpp
+@@ -79,6 +82,7 @@
+               $(XPCOM_LIBS) \
+               $(NSPR_LIBS) \
+               $(MOZ_UNICHARUTIL_LIBS) \
++              $(MOZ_MYSPELL_LIBS) \
+               $(NULL)
+ include $(topsrcdir)/config/rules.mk
+--- firefox-2.0+0dfsg.orig/configure
++++ firefox-2.0+0dfsg/configure
+@@ -60,6 +60,8 @@
+   --with-system-png[=PFX]
+                           Use system libpng [installed at prefix PFX]"
+ ac_help="$ac_help
++  --enable-system-myspell   Use system myspell (located with pkgconfig)"
++ac_help="$ac_help
+   --with-java-include-path=dir   Location of Java SDK headers"
+ ac_help="$ac_help
+   --with-java-bin-path=dir   Location of Java binaries (java, javac, jar)"
+@@ -12011,6 +11953,116 @@
+ fi # SKIP_LIBRARY_CHECKS
++# Check whether --enable-system-myspell or --disable-system-myspell was given.
++if test "${enable_system_myspell+set}" = set; then
++  enableval="$enable_system_myspell"
++  if test "$enableval" = "yes"; then
++    SYSTEM_MYSPELL=1 
++  elif test "$enableval" = "no"; then
++    :
++  else
++    { echo "configure: error: Option, system-myspell, does not take an argument ($enableval)." 1>&2; exit 1; }
++  fi
++fi
++
++
++if test -n "$SYSTEM_MYSPELL"; then
++    
++  succeeded=no
++
++  if test -z "$PKG_CONFIG"; then
++    # Extract the first word of "pkg-config", so it can be a program name with args.
++set dummy pkg-config; ac_word=$2
++echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
++echo "configure:11978: checking for $ac_word" >&5
++if eval "test \"`echo '$''{'ac_cv_path_PKG_CONFIG'+set}'`\" = set"; then
++  echo $ac_n "(cached) $ac_c" 1>&6
++else
++  case "$PKG_CONFIG" in
++  /*)
++  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
++  ;;
++  ?:/*)                        
++  ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a dos path.
++  ;;
++  *)
++  IFS="${IFS=         }"; ac_save_ifs="$IFS"; IFS=":"
++  ac_dummy="$PATH"
++  for ac_dir in $ac_dummy; do 
++    test -z "$ac_dir" && ac_dir=.
++    if test -f $ac_dir/$ac_word; then
++      ac_cv_path_PKG_CONFIG="$ac_dir/$ac_word"
++      break
++    fi
++  done
++  IFS="$ac_save_ifs"
++  test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
++  ;;
++esac
++fi
++PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
++if test -n "$PKG_CONFIG"; then
++  echo "$ac_t""$PKG_CONFIG" 1>&6
++else
++  echo "$ac_t""no" 1>&6
++fi
++
++  fi
++
++  if test "$PKG_CONFIG" = "no" ; then
++     echo "*** The pkg-config script could not be found. Make sure it is"
++     echo "*** in your path, or set the PKG_CONFIG environment variable"
++     echo "*** to the full path to pkg-config."
++     echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
++  else
++     PKG_CONFIG_MIN_VERSION=0.9.0
++     if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
++        echo $ac_n "checking for myspell""... $ac_c" 1>&6
++echo "configure:12022: checking for myspell" >&5
++
++        if $PKG_CONFIG --exists "myspell" ; then
++            echo "$ac_t""yes" 1>&6
++            succeeded=yes
++
++            echo $ac_n "checking MOZ_MYSPELL_CFLAGS""... $ac_c" 1>&6
++echo "configure:12029: checking MOZ_MYSPELL_CFLAGS" >&5
++            MOZ_MYSPELL_CFLAGS=`$PKG_CONFIG --cflags "myspell"`
++            echo "$ac_t""$MOZ_MYSPELL_CFLAGS" 1>&6
++
++            echo $ac_n "checking MOZ_MYSPELL_LIBS""... $ac_c" 1>&6
++echo "configure:12034: checking MOZ_MYSPELL_LIBS" >&5
++            ## don't use --libs since that can do evil things like add
++            ## -Wl,--export-dynamic
++            MOZ_MYSPELL_LIBS="`$PKG_CONFIG --libs-only-L \"myspell\"` `$PKG_CONFIG --libs-only-l \"myspell\"`"
++            echo "$ac_t""$MOZ_MYSPELL_LIBS" 1>&6
++        else
++            MOZ_MYSPELL_CFLAGS=""
++            MOZ_MYSPELL_LIBS=""
++            ## If we have a custom action on failure, don't print errors, but 
++            ## do set a variable so people can do so.
++            MOZ_MYSPELL_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "myspell"`
++            echo $MOZ_MYSPELL_PKG_ERRORS
++        fi
++
++        
++        
++     else
++        echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
++        echo "*** See http://www.freedesktop.org/software/pkgconfig"
++     fi
++  fi
++
++  if test $succeeded = yes; then
++     :
++  else
++     { echo "configure: error: Library requirements (myspell) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them." 1>&2; exit 1; }
++  fi
++
++fi
++
++
++
++
+ JAVA_INCLUDE_PATH=
+ # Check whether --with-java-include-path or --without-java-include-path was given.
+ if test "${with_java_include_path+set}" = set; then
+@@ -20291,10 +20347,13 @@
+ s%@NSS_CONFIG@%$NSS_CONFIG%g
+ s%@NSS_CFLAGS@%$NSS_CFLAGS%g
+ s%@NSS_LIBS@%$NSS_LIBS%g
++s%@PKG_CONFIG@%$PKG_CONFIG%g
++s%@MOZ_MYSPELL_CFLAGS@%$MOZ_MYSPELL_CFLAGS%g
++s%@MOZ_MYSPELL_LIBS@%$MOZ_MYSPELL_LIBS%g
++s%@SYSTEM_MYSPELL@%$SYSTEM_MYSPELL%g
+ s%@GTK_CONFIG@%$GTK_CONFIG%g
+ s%@GTK_CFLAGS@%$GTK_CFLAGS%g
+ s%@GTK_LIBS@%$GTK_LIBS%g
+-s%@PKG_CONFIG@%$PKG_CONFIG%g
+ s%@MOZ_GTK2_CFLAGS@%$MOZ_GTK2_CFLAGS%g
+ s%@MOZ_GTK2_LIBS@%$MOZ_GTK2_LIBS%g
+ s%@HOST_MOC@%$HOST_MOC%g
+--- firefox-2.0+0dfsg.orig/configure.in
++++ firefox-2.0+0dfsg/configure.in
+@@ -3840,6 +3870,19 @@
+ fi # SKIP_LIBRARY_CHECKS
++dnl system MySpell Support
++dnl ========================================================
++MOZ_ARG_ENABLE_BOOL(system-myspell,
++[  --enable-system-myspell   Use system myspell (located with pkgconfig)],
++    SYSTEM_MYSPELL=1 )
++
++if test -n "$SYSTEM_MYSPELL"; then
++    PKG_CHECK_MODULES(MOZ_MYSPELL, myspell)
++fi
++
++AC_SUBST(SYSTEM_MYSPELL)
++AC_SUBST(MOZ_MYSPELL_LIBS)
++
+ dnl ========================================================
+ dnl Java SDK support
+ dnl ========================================================
+--- firefox-2.0+0dfsg.orig/config/autoconf.mk.in
++++ firefox-2.0+0dfsg/config/autoconf.mk.in
+@@ -190,6 +190,9 @@
+ NECKO_SMALL_BUFFERS = @NECKO_SMALL_BUFFERS@
+ NECKO_COOKIES = @NECKO_COOKIES@
++MOZ_NATIVE_MYSPELL = @SYSTEM_MYSPELL@
++MOZ_MYSPELL_LIBS = @MOZ_MYSPELL_LIBS@
++
+ MOZ_NATIVE_ZLIB       = @SYSTEM_ZLIB@
+ MOZ_NATIVE_JPEG       = @SYSTEM_JPEG@
+ MOZ_NATIVE_PNG        = @SYSTEM_PNG@
+--- mozilla/toolkit/content/inlineSpellCheckUI.js~     2006-11-27 23:43:52.000000000 +0200
++++ mozilla/toolkit/content/inlineSpellCheckUI.js      2007-03-05 00:41:13.030876638 +0200
+@@ -202,6 +166,10 @@
+     for (var i = 0; i < list.length; i ++) {
+       // get the display name for this dictionary
+       isoStrArray = list[i].split("-");
++        // if we can't split by Mozilla locale names (en-US), try system separator (en_US)
++        if (isoStrArray.length < 2) {
++                isoStrArray = list[i].split("_");
++        }
+       var displayName = "";
+       if (this.mLanguageBundle && isoStrArray[0]) {
+         try {
diff --git a/mozilla-firefox-nopangoxft.patch b/mozilla-firefox-nopangoxft.patch
new file mode 100644 (file)
index 0000000..608e803
--- /dev/null
@@ -0,0 +1,20 @@
+--- mozilla/gfx/src/gtk/mozilla-decoder.cpp.noxft      2005-08-18 22:41:26.000000000 -0400
++++ mozilla/gfx/src/gtk/mozilla-decoder.cpp    2005-08-18 22:38:01.000000000 -0400
+@@ -40,7 +40,7 @@
+ #define PANGO_ENABLE_ENGINE
+ #include "mozilla-decoder.h"
+-#include <pango/pangoxft.h>
++#include <pango/pangocairo.h>
+ #include <pango/pangofc-fontmap.h>
+ #include <pango/pangofc-font.h>
+ #include <gdk/gdkx.h>
+@@ -208,7 +208,7 @@
+         }
+     }
+-    pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(pango_xft_get_font_map(GDK_DISPLAY(),gdk_x11_get_default_screen())),
++    pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(pango_cairo_font_map_get_default()),
+                                             mozilla_find_decoder,
+                                             NULL,
+                                             NULL);
diff --git a/mozilla-firefox-nss.patch b/mozilla-firefox-nss.patch
new file mode 100644 (file)
index 0000000..b740331
--- /dev/null
@@ -0,0 +1,83 @@
+diff -ur firefox.orig/config/config.mk firefox/config/config.mk
+--- firefox.orig/config/config.mk      2004-06-05 02:26:13.000000000 +0200
++++ firefox/config/config.mk   2004-06-16 09:42:32.000000000 +0200
+@@ -169,7 +169,7 @@
+ NSS_LIBS      = \
+       $(LIBS_DIR) \
+-      $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \
++      -lcrmf \
+       -lsmime3 \
+       -lssl3 \
+       -lnss3 \
+@@ -189,11 +189,6 @@
+ endif
+ NSS_DEP_LIBS  = \
+-      $(DIST)/lib/$(LIB_PREFIX)crmf.$(LIB_SUFFIX) \
+-      $(DIST)/lib/$(DLL_PREFIX)smime3$(DLL_SUFFIX) \
+-      $(DIST)/lib/$(DLL_PREFIX)ssl3$(DLL_SUFFIX) \
+-      $(DIST)/lib/$(DLL_PREFIX)nss3$(DLL_SUFFIX) \
+-      $(DIST)/lib/$(DLL_PREFIX)softokn3$(DLL_SUFFIX) \
+       $(NULL)
+ MOZ_UNICHARUTIL_LIBS = $(DIST)/lib/$(LIB_PREFIX)unicharutil_s.$(LIB_SUFFIX)
+diff -ur firefox.orig/security/manager/Makefile.in firefox/security/manager/Makefile.in
+--- firefox.orig/security/manager/Makefile.in  2004-03-23 05:15:56.000000000 +0100
++++ firefox/security/manager/Makefile.in       2004-06-16 09:48:35.000000000 +0200
+@@ -148,43 +148,6 @@
+ else
+       cd $(DIST)/lib; cp -f $(LIB_PREFIX)mozdbm_s.$(LIB_SUFFIX) $(LIB_PREFIX)dbm.$(LIB_SUFFIX); $(RANLIB) $(LIB_PREFIX)dbm.$(LIB_SUFFIX)
+ endif
+-      $(MAKE) -C $(topsrcdir)/security/nss/lib $(DEFAULT_GMAKE_FLAGS)
+-ifndef SKIP_CHK
+-      $(MAKE) -C $(topsrcdir)/security/nss/cmd/lib $(DEFAULT_GMAKE_FLAGS)
+-      $(MAKE) -C $(topsrcdir)/security/nss/cmd/shlibsign $(DEFAULT_GMAKE_FLAGS)
+-endif
+-ifndef DISABLE_DIST_GRE
+-      $(INSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(GRE_DIST)
+-ifndef SKIP_CHK
+-      $(INSTALL) -m 644 $(DIST)/lib/$(SOFTOKEN3_CHK) $(GRE_DIST)
+-endif
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(GRE_DIST)
+-      $(INSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(GRE_DIST)
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(GRE_DIST)
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(GRE_DIST)
+-ifdef HAVE_FREEBL_MODULES
+-      $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_PURE32_CHK) $(GRE_DIST)
+-      $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_PURE32_MODULE) $(GRE_DIST)
+-      $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_HYBRID_CHK) $(GRE_DIST)
+-      $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_HYBRID_MODULE) $(GRE_DIST)
+-endif
+-endif
+-ifndef _SKIP_OLD_GRE_INSTALL
+-      $(INSTALL) -m 755 $(DIST)/lib/$(LOADABLE_ROOT_MODULE) $(DIST)/bin
+-ifndef SKIP_CHK
+-      $(INSTALL) -m 644 $(DIST)/lib/$(SOFTOKEN3_CHK) $(DIST)/bin
+-endif
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SOFTOKEN3_LIB) $(DIST)/bin
+-      $(INSTALL) -m 755 $(DIST)/lib/$(NSS3_LIB) $(DIST)/bin
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SSL3_LIB) $(DIST)/bin
+-      $(INSTALL) -m 755 $(DIST)/lib/$(SMIME3_LIB) $(DIST)/bin
+-ifdef HAVE_FREEBL_MODULES
+-      $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_PURE32_CHK) $(DIST)/bin
+-      $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_PURE32_MODULE) $(DIST)/bin
+-      $(INSTALL) -m 644 $(DIST)/lib/$(FREEBL_HYBRID_CHK) $(DIST)/bin
+-      $(INSTALL) -m 755 $(DIST)/lib/$(FREEBL_HYBRID_MODULE) $(DIST)/bin
+-endif
+-endif
+       $(MAKE) -C boot $@
+       $(MAKE) -C ssl $@
+ ifdef MOZ_XUL
+diff -ur firefox.orig/security/manager/ssl/src/Makefile.in firefox/security/manager/ssl/src/Makefile.in
+--- firefox.orig/security/manager/ssl/src/Makefile.in  2004-01-07 14:36:51.000000000 +0100
++++ firefox/security/manager/ssl/src/Makefile.in       2004-06-16 09:42:34.000000000 +0200
+@@ -116,7 +116,7 @@
+ # Use local includes because they are inserted before INCLUDES
+ # so that Mozilla's nss.h is used, not glibc's
+-LOCAL_INCLUDES += -I$(DIST)/public/nss \
++LOCAL_INCLUDES += -I/usr/include/nss \
+                   $(NULL)
+ EXTRA_DSO_LDOPTS += \
diff --git a/mozilla-firefox-nss_cflags.patch b/mozilla-firefox-nss_cflags.patch
new file mode 100644 (file)
index 0000000..90d0154
--- /dev/null
@@ -0,0 +1,42 @@
+--- mozilla/config/autoconf.mk.in.orig 2008-06-19 17:55:40.000000000 +0200
++++ mozilla/config/autoconf.mk.in      2008-06-19 18:45:18.000000000 +0200
+@@ -276,7 +276,7 @@
+ OS_COMPILE_CFLAGS = $(OS_CPPFLAGS) @COMPILE_CFLAGS@
+ OS_COMPILE_CXXFLAGS = $(OS_CPPFLAGS) @COMPILE_CXXFLAGS@
+-OS_INCLUDES   = $(NSPR_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(ZLIB_CFLAGS) $(LCMS_CFLAGS)
++OS_INCLUDES   = $(NSPR_CFLAGS) $(NSS_CFLAGS) $(JPEG_CFLAGS) $(PNG_CFLAGS) $(ZLIB_CFLAGS) $(LCMS_CFLAGS)
+ OS_LIBS               = @LIBS@
+ ACDEFINES     = @MOZ_DEFINES@
+--- mozilla/config/rules.mk.orig       2008-06-19 18:45:00.000000000 +0200
++++ mozilla/config/rules.mk    2008-06-19 18:42:40.000000000 +0200
+@@ -1235,23 +1235,23 @@
+ # Rules for building native targets must come first because of the host_ prefix
+ host_%.$(OBJ_SUFFIX): %.c Makefile Makefile.in
+       $(REPORT_BUILD)
+-      $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
++      $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(NSS_CFLAGS) $(_VPATH_SRCS)
+ host_%.$(OBJ_SUFFIX): %.cpp Makefile Makefile.in
+       $(REPORT_BUILD)
+-      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
++      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(NSS_CFLAGS) $(_VPATH_SRCS)
+ host_%.$(OBJ_SUFFIX): %.cc Makefile Makefile.in
+       $(REPORT_BUILD)
+-      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
++      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(NSS_CFLAGS) $(_VPATH_SRCS)
+ host_%.$(OBJ_SUFFIX): %.m Makefile Makefile.in
+       $(REPORT_BUILD)
+-      $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
++      $(ELOG) $(HOST_CC) $(HOST_OUTOPTION)$@ -c $(HOST_CFLAGS) $(HOST_CMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(NSS_CFLAGS) $(_VPATH_SRCS)
+ host_%.$(OBJ_SUFFIX): %.mm Makefile Makefile.in
+       $(REPORT_BUILD)
+-      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(_VPATH_SRCS)
++      $(ELOG) $(HOST_CXX) $(HOST_OUTOPTION)$@ -c $(HOST_CXXFLAGS) $(HOST_CMMFLAGS) $(INCLUDES) $(NSPR_CFLAGS) $(NSS_CFLAGS) $(_VPATH_SRCS)
+ %: %.c Makefile Makefile.in
+       $(REPORT_BUILD)
diff --git a/mozilla-firefox-pango-cursor-position-more.patch b/mozilla-firefox-pango-cursor-position-more.patch
new file mode 100644 (file)
index 0000000..ef5b967
--- /dev/null
@@ -0,0 +1,19 @@
+diff -pruN -x '.moz*' -x .deps -x 'firefox*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp        2006-08-26 13:33:35.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp     2006-12-13 20:54:32.000000000 +0900
+@@ -4261,12 +4261,10 @@ nsTextFrame::GetPointFromOffset(nsPresCo
+       if (tc) {
+         totalLength = tc->Text()->GetLength(); // raw value which includes whitespace
+       }
+-      if ((hitLength == textLength) && (inOffset = mContentLength) &&
+-          (mContentOffset + mContentLength == totalLength)) {
+-        // no need to re-measure when at the end of the last-in-flow
+-      }
++      if (hitLength > 0)
++      inRendContext->GetRangeWidth(paintBuffer.mBuffer, textLength, 0, hitLength, (PRUint32&)width);
+       else
+-        inRendContext->GetWidth(paintBuffer.mBuffer, hitLength, width);
++      width = 0;
+     }
+     if ((hitLength == textLength) && (TEXT_TRIMMED_WS & mState)) {
+       //
diff --git a/mozilla-firefox-pango-cursor-position.patch b/mozilla-firefox-pango-cursor-position.patch
new file mode 100644 (file)
index 0000000..d287fd3
--- /dev/null
@@ -0,0 +1,52 @@
+Index: mozilla/gfx/src/gtk/nsFontMetricsPango.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/gtk/nsFontMetricsPango.cpp,v
+retrieving revision 1.24
+diff -d -u -p -6 -r1.24 nsFontMetricsPango.cpp
+--- mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 25 Aug 2006 01:02:34 -0000      1.24
++++ mozilla/gfx/src/gtk/nsFontMetricsPango.cpp 6 Sep 2006 07:01:49 -0000
+@@ -948,13 +948,12 @@ nsFontMetricsPango::GetClusterInfo(const
+ PRInt32
+ nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
+                                 nsPoint aPt)
+ {
+     int trailing = 0;
+     int inx = 0;
+-    gboolean found = FALSE;
+     const gchar *curChar;
+     PRInt32 retval = 0;
+     float f = mDeviceContext->AppUnitsToDevUnits();
+     
+     PangoLayout *layout = pango_layout_new(mPangoContext);
+@@ -974,28 +973,18 @@ nsFontMetricsPango::GetPosition(const PR
+     }
+     // Set up the pango layout
+     pango_layout_set_text(layout, text, strlen(text));
+     FixupSpaceWidths(layout, text);
+     
+-    found = pango_layout_xy_to_index(layout, localX, localY,
+-                                     &inx, &trailing);
++    pango_layout_xy_to_index(layout, localX, localY,
++                             &inx, &trailing);
+     // Convert the index back to the utf-16 index
+     curChar = text;
+-    // Jump to the end if it's not found.
+-    if (!found) {
+-        if (inx == 0)
+-            retval = 0;
+-        else if (trailing)
+-            retval = aLength;
+-
+-        goto loser;
+-    }
+-
+     for (PRUint32 curOffset=0; curOffset < aLength;
+          curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
+         // Check for a match before checking for a surrogate pair
+         if (curChar - text == inx) {
+             retval = curOffset;
diff --git a/mozilla-firefox-pango-justified-range.patch b/mozilla-firefox-pango-justified-range.patch
new file mode 100644 (file)
index 0000000..7614d0e
--- /dev/null
@@ -0,0 +1,53 @@
+diff -pruN -x '.moz*' -x .deps -x 'thunderbird*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' -x 'firefox*' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp        2006-12-20 12:15:38.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp     2006-12-20 21:29:39.000000000 +0900
+@@ -2973,15 +2973,16 @@ nsTextFrame::RenderString(nsIRenderingCo
+   nsIFontMetrics* lastFont = aTextStyle.mLastFont;
+   PRInt32 pendingCount;
+-  PRUnichar* runStart = bp;
++  PRUnichar* runStart = bp, *top = aBuffer;
+   nscoord charWidth, width = 0;
+   PRInt32 countSoFar = 0;
++  PRUint32 offset;
+   // Save the color we want to use for the text, since calls to
+   // PaintTextDecorations in this method will call SetColor() on the rendering
+   // context.
+   nscolor textColor;
+   aRenderingContext.GetColor(textColor);
+-  for (; --aLength >= 0; aBuffer++) {
++  for (offset = 0; offset < aLength; aBuffer++, offset++) {
+     nsIFontMetrics* nextFont;
+     nscoord glyphWidth = 0;
+     PRUnichar ch = *aBuffer;
+@@ -3038,7 +3039,7 @@ nsTextFrame::RenderString(nsIRenderingCo
+     else if (ch == ' ') {
+       glyphWidth += aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing + aTextStyle.mLetterSpacing;
+     }
+-    else if (IS_HIGH_SURROGATE(ch) && aLength > 0 &&
++    else if (IS_HIGH_SURROGATE(ch) && (offset + 1) < aLength &&
+            IS_LOW_SURROGATE(*(aBuffer+1))) {
+       
+       // special handling for surrogate pair
+@@ -3046,7 +3047,7 @@ nsTextFrame::RenderString(nsIRenderingCo
+       glyphWidth += charWidth + aTextStyle.mLetterSpacing;
+       // copy the surrogate low
+       *bp++ = ch;
+-      --aLength;
++      offset++;
+       aBuffer++;
+       ch = *aBuffer;
+       // put the width into the space buffer
+@@ -3058,10 +3059,10 @@ nsTextFrame::RenderString(nsIRenderingCo
+       glyphWidth = 0;
+     }
+     else {
+-      aRenderingContext.GetWidth(ch, charWidth);
++      aRenderingContext.GetRangeWidth(top, aLength, offset, offset + 1, (PRUint32&)charWidth);
+       glyphWidth += charWidth + aTextStyle.mLetterSpacing;
+     }
+-    if (justifying && (!isEndOfLine || aLength > 0)
++    if (justifying && (!isEndOfLine || (offset + 1) < aLength)
+         && IsJustifiableCharacter(ch, isCJ)) {
+       glyphWidth += aTextStyle.mExtraSpacePerJustifiableCharacter;
+       if ((PRUint32)--aTextStyle.mNumJustifiableCharacterToRender
diff --git a/mozilla-firefox-pango-ligatures.patch b/mozilla-firefox-pango-ligatures.patch
new file mode 100644 (file)
index 0000000..2eb5b0b
--- /dev/null
@@ -0,0 +1,1932 @@
+--- mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp.orig       2007-06-28 14:44:31.000000000 +0200
++++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.cpp    2007-06-28 15:48:04.000000000 +0200
+@@ -21,6 +21,8 @@
+  * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
+  *
+  * Contributor(s):
++ *   Christopher Blizzard <blizzard@mozilla.org>
++ *   Behdad Esfahbod <behdad@behdad.org>
+  *
+  * Alternatively, the contents of this file may be used under the terms of
+  * either the GNU General Public License Version 2 or later (the "GPL"), or
+@@ -36,6 +38,10 @@
+  *
+  * ***** END LICENSE BLOCK ***** */
++#define PANGO_ENABLE_BACKEND
++
++#include "nsFontMetricsPango.h"
++
+ #include <strings.h>
+ #include "nsFont.h"
+ #include "nsIDeviceContext.h"
+@@ -43,27 +49,37 @@
+ #include "nsIPref.h"
+ #include "nsServiceManagerUtils.h"
+-#define PANGO_ENABLE_BACKEND
+-#define PANGO_ENABLE_ENGINE
+-
+-#include "nsFontMetricsPango.h"
+-#include "nsRenderingContextGTK.h"
+-#include "nsDeviceContextGTK.h"
+ #include "nsFontConfigUtils.h"
+ #include "nsUnicharUtils.h"
+ #include "nsQuickSort.h"
+ #include "nsFontConfigUtils.h"
++#include "mozilla-decoder.h"
++
++#define FORCE_PR_LOG
++#include "prlog.h"
++
+ #include <fontconfig/fontconfig.h>
++#include <freetype/tttables.h>
++
++#include <pango/pango.h>
++#include <pango/pangofc-font.h>
++
++#ifdef PSPANGO
++#include <pango/pangoft2.h>
++#include "nsRenderingContextPS.h"
++#include "nsDeviceContextPS.h"
++#include "nsType1.h"
++#else
+ #include <gdk/gdk.h>
+ #include <gdk/gdkx.h>
+-#include <freetype/tttables.h>
++#include "nsRenderingContextGTK.h"
++#include "nsDeviceContextGTK.h"
++#endif
++
+-#include "mozilla-decoder.h"
+-#define FORCE_PR_LOG
+-#include "prlog.h"
+ // Globals
+@@ -108,6 +124,49 @@ static nsresult    EnumFontsPango   (nsI
+                                      PRUint32* aCount, PRUnichar*** aResult);
+ static int         CompareFontNames (const void* aArg1, const void* aArg2,
+                                      void* aClosure);
++static void  utf16_to_utf8 (const PRUnichar* aString, PRUint32 aLength,
++                            char *&text, gint &text_len);
++
++#ifdef PSPANGO
++static void
++default_substitute (FcPattern *pattern,
++                    gpointer   data)
++{
++  FcPatternDel (pattern, FC_HINTING);
++  FcPatternAddBool (pattern, FC_HINTING, 0);
++}
++#endif
++
++static PangoFontMap *
++get_fontmap (void)
++{
++  static PangoFontMap               *fontmap = NULL;
++
++  if (!fontmap) {
++#ifdef PSPANGO
++    fontmap = pango_ft2_font_map_new ();
++    pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.);
++    pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL);
++#else
++    PangoContext* context = gdk_pango_context_get ();
++    fontmap = pango_context_get_font_map (context);
++    g_object_unref (context);
++#endif
++  }
++
++  return fontmap;
++}
++
++static PangoContext *
++get_context (void)
++{
++#ifdef PSPANGO
++  return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
++#else
++  return gdk_pango_context_get();
++#endif
++}
++
+ nsFontMetricsPango::nsFontMetricsPango()
+ {
+@@ -228,14 +228,20 @@
+     mLangGroup = aLangGroup;
+     // Hang on to the device context
++#ifdef PSPANGO
++    mDeviceContext = (nsDeviceContextPS *)aContext;
++#else
+     mDeviceContext = aContext;
++#endif
+     
+     mPointSize = NSTwipsToFloatPoints(mFont.size);
++#ifndef PSPANGO
+     // Make sure to clamp the pixel size to something reasonable so we
+     // don't make the X server blow up.
+     nscoord screenPixels = gdk_screen_height();
+     mPointSize = PR_MIN((screenPixels - 1) * FONT_MAX_FONT_SCALE, mPointSize);
++#endif
+     // enumerate over the font names passed in
+     mFont.EnumerateFamilies(nsFontMetricsPango::EnumFontCallback, this);
+@@ -329,7 +394,7 @@ nsFontMetricsPango::CacheFontMetrics(voi
+     // mPangoSpaceWidth
+     PangoLayout *layout = pango_layout_new(mPangoContext);
+-    pango_layout_set_text(layout, " ", 1);
++    pango_layout_set_text(layout, " ", -1);
+     int pswidth, psheight;
+     pango_layout_get_size(layout, &pswidth, &psheight);
+     mPangoSpaceWidth = pswidth;
+@@ -337,14 +402,14 @@ nsFontMetricsPango::CacheFontMetrics(voi
+     // mSpaceWidth (width of a space)
+     nscoord tmpWidth;
+-    GetWidth(" ", 1, tmpWidth, NULL);
++    GetWidth(" ", 1, tmpWidth CONTEXT_ARG_NULL);
+     mSpaceWidth = tmpWidth;
+     // mAveCharWidth (width of an 'average' char)
+     //    XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
+     //rawWidth = extents.width;
+     //mAveCharWidth = NSToCoordRound(rawWidth * f);
+-    GetWidth("x", 1, tmpWidth, NULL);
++    GetWidth("x", 1, tmpWidth CONTEXT_ARG_NULL);
+     mAveCharWidth = tmpWidth;
+     // mXHeight (height of an 'x' character)
+@@ -460,130 +525,96 @@ nsFontMetricsPango::GetFontHandle(nsFont
+ // nsIFontMetricsPango impl
+-nsresult
+-nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
+-                             nscoord& aWidth,
+-                             nsRenderingContextGTK *aContext)
++#ifdef PSPANGO
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
+ {
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
+-
+-    pango_layout_set_text(layout, aString, aLength);
++    return GetWidth (String, (PRUint32) aLength, aWidth CONTEXT_ARG_NULL);
++}
+-    if (mPangoSpaceWidth)
+-        FixupSpaceWidths(layout, aString);
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
++{
++    return GetWidth (aString, (PRUint32)aLength, aWidth, NULL CONTEXT_ARG_NULL);
++}
++#endif
++nsresult
++nsFontMetricsPango::GetWidth(const char* aString, PRUint32 aLength,
++                             nscoord& aWidth
++                             CONTEXT_ARG_DEF)
++{
+     int width, height;
+-
++    PangoLayout *layout = GetLayout(aString, aLength);
+     pango_layout_get_size(layout, &width, &height);
+-
+     g_object_unref(layout);
+-    float f;
+-    f = mDeviceContext->DevUnitsToAppUnits();
++    float f = mDeviceContext->DevUnitsToAppUnits();
+     aWidth = NSToCoordRound(width * f / PANGO_SCALE);
+-    //    printf("GetWidth (char *) %d\n", aWidth);
+-
+     return NS_OK;
+ }
+ nsresult
+ nsFontMetricsPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
+-                             nscoord& aWidth, PRInt32 *aFontID,
+-                             nsRenderingContextGTK *aContext)
++                             nscoord& aWidth, PRInt32 *aFontID
++                             CONTEXT_ARG_DEF)
+ {
+-    nsresult rv = NS_OK;
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
+-
+-    gchar *text = g_utf16_to_utf8(aString, aLength,
+-                                  NULL, NULL, NULL);
+-
+-    if (!text) {
+-        aWidth = 0;
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
+-        DUMP_PRUNICHAR(aString, aLength)
+-#endif
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
+-
+     gint width, height;
+-
+-    pango_layout_set_text(layout, text, strlen(text));
+-    FixupSpaceWidths(layout, text);
++    PangoLayout *layout = GetLayout(aString, aLength);
+     pango_layout_get_size(layout, &width, &height);
++    g_object_unref(layout);
+-    float f;
+-    f = mDeviceContext->DevUnitsToAppUnits();
++    float f = mDeviceContext->DevUnitsToAppUnits();
+     aWidth = NSToCoordRound(width * f / PANGO_SCALE);
+-    //    printf("GetWidth %d\n", aWidth);
+-
+- loser:
+-    g_free(text);
+-    g_object_unref(layout);
+-
+-    return rv;
++    return NS_OK;
+ }
+ nsresult
+-nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
++nsFontMetricsPango::GetTextDimensions(const char* aString,
+                                       PRUint32 aLength,
+-                                      nsTextDimensions& aDimensions, 
+-                                      PRInt32* aFontID,
+-                                      nsRenderingContextGTK *aContext)
++                                      nsTextDimensions& aDimensions
++                                      CONTEXT_ARG_DEF)
+ {
+-    nsresult rv = NS_OK;
+-
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
++    PangoLayout *layout = GetLayout(aString, aLength);
++    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
+-    gchar *text = g_utf16_to_utf8(aString, aLength,
+-                                  NULL, NULL, NULL);
+-
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetTextDimensions invalid unicode to follow");
+-        DUMP_PRUNICHAR(aString, aLength)
+-#endif
+-        aDimensions.width = 0;
+-        aDimensions.ascent = 0;
+-        aDimensions.descent = 0;
+-
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
+-        
++    PangoRectangle logical;
++    pango_layout_line_get_extents(line, NULL, &logical);
++    g_object_unref(layout);
+-    pango_layout_set_text(layout, text, strlen(text));
+-    FixupSpaceWidths(layout, text);
++    float P2T = mDeviceContext->DevUnitsToAppUnits();
+-    // Get the logical extents
+-    PangoLayoutLine *line;
+-    if (pango_layout_get_line_count(layout) != 1) {
+-        printf("Warning: more than one line!\n");
+-    }
+-    line = pango_layout_get_line(layout, 0);
++    aDimensions.ascent  = NSToCoordRound(PANGO_ASCENT(logical)  * P2T / PANGO_SCALE);
++    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
++    aDimensions.width   = NSToCoordRound(logical.width          * P2T / PANGO_SCALE);
+-    PangoRectangle rect;
+-    pango_layout_line_get_extents(line, NULL, &rect);
++    return NS_OK;
++}
+-    float P2T;
+-    P2T = mDeviceContext->DevUnitsToAppUnits();
++nsresult
++nsFontMetricsPango::GetTextDimensions(const PRUnichar* aString,
++                                      PRUint32 aLength,
++                                      nsTextDimensions& aDimensions, 
++                                      PRInt32* aFontID
++                                      CONTEXT_ARG_DEF)
++{
++    PangoLayout *layout = GetLayout(aString, aLength);
++    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
+-    aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
+-    aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
+-    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
++    PangoRectangle logical;
++    pango_layout_line_get_extents(line, NULL, &logical);
++    g_object_unref(layout);
+-    //    printf("GetTextDimensions %d %d %d\n", aDimensions.width,
+-    //aDimensions.ascent, aDimensions.descent);
++    float P2T = mDeviceContext->DevUnitsToAppUnits();
+- loser:
+-    g_free(text);
+-    g_object_unref(layout);
++    aDimensions.ascent  = NSToCoordRound(PANGO_ASCENT(logical)  * P2T / PANGO_SCALE);
++    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(logical) * P2T / PANGO_SCALE);
++    aDimensions.width   = NSToCoordRound(logical.width          * P2T / PANGO_SCALE);
+-    return rv;
++    return NS_OK;
+ }
+ nsresult
+@@ -595,13 +626,13 @@ nsFontMetricsPango::GetTextDimensions(co
+                                       nsTextDimensions&   aDimensions,
+                                       PRInt32&            aNumCharsFit,
+                                       nsTextDimensions&   aLastWordDimensions,
+-                                      PRInt32*            aFontID,
+-                                      nsRenderingContextGTK *aContext)
++                                      PRInt32*            aFontID
++                                      CONTEXT_ARG_DEF)
+ {
+     return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
+                                      aNumBreaks, aDimensions, aNumCharsFit,
+-                                     aLastWordDimensions, aContext);
++                                     aLastWordDimensions CONTEXT_ARG_PASS);
+ }
+@@ -614,8 +645,8 @@ nsFontMetricsPango::GetTextDimensions(co
+                                       nsTextDimensions&   aDimensions,
+                                       PRInt32&            aNumCharsFit,
+                                       nsTextDimensions&   aLastWordDimensions,
+-                                      PRInt32*            aFontID,
+-                                      nsRenderingContextGTK *aContext)
++                                      PRInt32*            aFontID
++                                      CONTEXT_ARG_DEF)
+ {
+     nsresult rv = NS_OK;
+     PRInt32 curBreak = 0;
+@@ -623,23 +654,15 @@ nsFontMetricsPango::GetTextDimensions(co
+     PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
+-    gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
+-                                  NULL, NULL, NULL);
++    gchar* text;
++    gint text_len;
++    utf16_to_utf8 (aString, aLength, text, text_len);
+     curChar = text;
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
+-        DUMP_PRUNICHAR(aString, (PRUint32)aLength)
+-#endif
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
+-
+     // Covert the utf16 break offsets to utf8 break offsets
+     for (PRInt32 curOffset=0; curOffset < aLength;
+-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++         curOffset++, curChar = g_utf8_next_char(curChar)) {
+         if (aBreaks[curBreak] == curOffset) {
+             utf8Breaks[curBreak] = curChar - text;
+             curBreak++;
+@@ -653,10 +676,10 @@ nsFontMetricsPango::GetTextDimensions(co
+     utf8Breaks[curBreak] = curChar - text;
+ #if 0
+-    if (strlen(text) != aLength) {
+-        printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
++    if (text_len != aLength) {
++        printf("Different lengths for utf16 %d and utf8 %d\n", aLength, text_len);
+         DUMP_PRUNICHAR(aString, aLength)
+-        DUMP_PRUNICHAR(text, strlen(text))
++        DUMP_PRUNICHAR(text, text_len)
+         for (PRInt32 i = 0; i < aNumBreaks; ++i) {
+             printf("  break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
+         }
+@@ -666,9 +689,9 @@ nsFontMetricsPango::GetTextDimensions(co
+     // We'll use curBreak to indicate which of the breaks end up being
+     // used for the break point for this line.
+     curBreak = 0;
+-    rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
++    rv = GetTextDimensionsInternal(text, text_len, aAvailWidth, utf8Breaks,
+                                    aNumBreaks, aDimensions, aNumCharsFit,
+-                                   aLastWordDimensions, aContext);
++                                   aLastWordDimensions CONTEXT_ARG_PASS);
+     // Figure out which of the breaks we ended up using to convert
+     // back to utf16 - start from the end.
+@@ -681,200 +704,365 @@ nsFontMetricsPango::GetTextDimensions(co
+         }
+     }
+- loser:
+-    if (text)
+-        g_free(text);
++    g_free(text);
+     delete[] utf8Breaks;
+     return rv;
+ }
+-nsresult
+-nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
+-                               nscoord aX, nscoord aY,
+-                               const nscoord* aSpacing,
+-                               nsRenderingContextGTK *aContext,
+-                               nsDrawingSurfaceGTK *aSurface)
++#ifdef PSPANGO
++
++typedef struct _nsPSPangoRenderer        nsPSPangoRenderer;
++typedef struct _nsPSPangoRendererClass   nsPSPangoRendererClass;
++
++struct _nsPSPangoRenderer
+ {
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
++  PangoRenderer parent_instance;
++  nsRenderingContextPS *psContext;
++  nsFontMetricsPSPango *psPangoFontMetrics;
++  float zoom;
++};
+-    pango_layout_set_text(layout, aString, aLength);
+-    FixupSpaceWidths(layout, aString);
++struct _nsPSPangoRendererClass
++{
++  PangoRendererClass parent_class;
++};
+-    int x = aX;
+-    int y = aY;
++#define _PS_TYPE_PANGO_RENDERER            (_ps_pango_renderer_get_type())
++#define _PS_PANGO_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
++#define _PS_IS_PANGO_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
++#define _PS_PANGO_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
++#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
++#define _PS_PANGO_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
+-    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
+-    PangoLayoutLine *line;
+-    if (pango_layout_get_line_count(layout) != 1) {
+-        printf("Warning: more than one line!\n");
+-    }
+-    line = pango_layout_get_line(layout, 0);
++static PangoRenderer *
++get_renderer (void)
++{
++  static PangoRenderer               *renderer = NULL;
+-    aContext->UpdateGC();
+-    GdkGC *gc = aContext->GetGC();
++  if (!renderer)
++    renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
+-    if (aSpacing && *aSpacing) {
+-        DrawStringSlowly(aString, NULL, aLength, aSurface->GetDrawable(),
+-                         gc, x, y, line, aSpacing);
+-    }
+-    else {
+-        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
+-                             x, y,
+-                             line);
+-    }
++  return renderer;
++}
+-    g_object_unref(gc);
+-    g_object_unref(layout);
++static void
++_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
++                              PangoFont        *font,
++                              PangoGlyphString *glyphs,
++                              int               x,
++                              int               y);
+-    //    printf("DrawString (char *)\n");
++static void
++_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
++{
++  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
++  
++  renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
++}
+-    return NS_OK;
++static void
++_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
++{
++}
++
++class nsPangoType1Generator : public nsPSFontGenerator {
++public:
++  nsPangoType1Generator();
++  ~nsPangoType1Generator();
++  nsresult Init(PangoFont *aFont);
++  void  GeneratePSFont(FILE* aFile);
++
++protected:
++  PangoFont *mFont;
++};
++
++nsPangoType1Generator::nsPangoType1Generator()
++{
+ }
+ nsresult
+-nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
+-                               nscoord aX, nscoord aY,
+-                               PRInt32 aFontID,
+-                               const nscoord* aSpacing,
+-                               nsRenderingContextGTK *aContext,
+-                               nsDrawingSurfaceGTK *aSurface)
++nsPangoType1Generator::Init(PangoFont *aFont)
++  {
++  NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
++  mFont = aFont;
++  g_object_ref (mFont);
++  return NS_OK;
++}
++
++nsPangoType1Generator::~nsPangoType1Generator()
+ {
+-    nsresult rv = NS_OK;
+-    int x = aX;
+-    int y = aY;
++  g_object_unref (mFont);
++  mFont = nsnull;
++}
+-    aContext->UpdateGC();
+-    GdkGC *gc = aContext->GetGC();
++void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
++{
++  FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
++  if (face == nsnull)
++    return;
+-    gchar *text = g_utf16_to_utf8(aString, aLength,
+-                                  NULL, NULL, NULL);
++  int wmode = 0;
++  if (mGlyphSubset->Count())
++    FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::DrawString invalid unicode to follow");
+-        DUMP_PRUNICHAR(aString, aLength)
+-#endif
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
++ pango_fc_font_unlock_face ((PangoFcFont *) mFont);
++}
+-    pango_layout_set_text(layout, text, strlen(text));
+-    FixupSpaceWidths(layout, text);
++typedef struct
++{
++  nsCString    *FontNameBase;
++  nsCStringKey *key;
++  int           font_size;
++} PSPangoFontData;
+-    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++static void
++ps_pango_font_data_destroy (PSPangoFontData *data)
++{
++  delete data->key;
++  delete data->FontNameBase;
++  g_free (data);
++}
+-    PangoLayoutLine *line;
+-    if (pango_layout_get_line_count(layout) != 1) {
+-        printf("Warning: more than one line!\n");
+-    }
+-    line = pango_layout_get_line(layout, 0);
++static void
++_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
++                              PangoFont        *font,
++                              PangoGlyphString *glyphs,
++                              int               x,
++                              int               y)
++{
++  if (!glyphs->num_glyphs)
++    return;
+-    if (aSpacing && *aSpacing) {
+-        DrawStringSlowly(text, aString, aLength, aSurface->GetDrawable(),
+-                         gc, x, y, line, aSpacing);
+-    }
+-    else {
+-        gdk_draw_layout_line(aSurface->GetDrawable(), gc,
+-                             x, y,
+-                             line);
+-    }
++  static GQuark data_quark = 0;
++  if (!data_quark)
++    data_quark = g_quark_from_static_string ("ps-pango-font-data");
+- loser:
++  PSPangoFontData *data;
++  if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
++    {
++      data = g_new (PSPangoFontData, 1);
+-    g_free(text);
+-    g_object_unref(gc);
+-    g_object_unref(layout);
++      FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
++      if (face == nsnull)
++        return;
++      int wmode = 0;
++      data->FontNameBase = new nsCString ();
++      if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
++        g_free (data);
++        pango_fc_font_unlock_face ((PangoFcFont *) font);
++        return;
++      }
++      pango_fc_font_unlock_face ((PangoFcFont *) font);
+-    //    printf("DrawString\n");
++      PangoFontDescription *desc = pango_font_describe (font);
++      data->font_size = pango_font_description_get_size (desc);
++      pango_font_description_free (desc);
++
++      data->key = new nsCStringKey (*data->FontNameBase);
++
++      g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
++    }
++
++  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
++  nsRenderingContextPS *aContext = ps_renderer->psContext;
++  nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
++  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
++  nsPostScriptObj* psObj = aContext->GetPostScriptObj();
++  nsHashtable *psFGList = dc->GetPSFontGeneratorList();
++  g_return_if_fail (psFGList);
++  nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
++  if (!psFontGen) {
++    nsresult rv;
++    psFontGen = new nsPangoType1Generator;
++    g_return_if_fail (psFontGen);
++    rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
++    if (NS_FAILED(rv)) {
++      delete psFontGen;
++      return;
++    }
++    psFGList->Put(data->key, (void *) psFontGen);
++  }
++  nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
++
++  g_return_if_fail (aContext);
++  g_return_if_fail (psObj);
++
++  nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
++  nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
++  psObj->moveto(aX, aY);
++
++  PRInt32 currSubFont, prevSubFont = -1;
++  PRUint32 i;
++  PangoGlyphString gl;
++
++  gl.glyphs = glyphs->glyphs;
++  gl.num_glyphs = 0;
++  currSubFont = prevSubFont;
++  for (i = 0; i < glyphs->num_glyphs; ++i) {
++    PangoGlyph glyph = glyphs->glyphs[i].glyph;
++
++    if (glyph != PANGO_GLYPH_EMPTY)
++      currSubFont = psFontGen->AddToGlyphSubset(glyph > 0x0fffffff ? 0 : glyph);
++
++    if (prevSubFont != currSubFont) {
++      if (prevSubFont != -1)
++        psObj->show(&gl, ps_renderer->zoom,  psFontGen, prevSubFont);
++
++      psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
++      prevSubFont = currSubFont;
++      gl.glyphs = glyphs->glyphs + i;
++      gl.num_glyphs = 0;
++    }
+-    return rv;
++    gl.num_glyphs++;
++  }
++
++  if (prevSubFont != -1)
++    psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
+ }
++#endif
++
++static void
++draw_layout_line (int x, int y,
++                  PangoLayoutLine *line,
++                  nsFontMetricsPango *fm
++                  CONTEXT_AND_SURFACE_ARG_DEF)
++{
++#ifdef PSPANGO
++  PangoRenderer *renderer = get_renderer ();
++  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
++  ps_renderer->psContext = aContext;
++  ps_renderer->psPangoFontMetrics = fm;
++  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, fm->GetDeviceContext());
++  ps_renderer->zoom = dc->DevUnitsToAppUnits();
++
++  pango_renderer_draw_layout_line (renderer, line,
++                                   NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
++                                   NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
++#else
++    aContext->UpdateGC();
++    GdkGC *gc = aContext->GetGC();
++    gdk_draw_layout_line(aSurface->GetDrawable(), gc, x, y, line);
++    g_object_unref(gc);
++#endif
++}
++
+-#ifdef MOZ_MATHML
+ nsresult
+-nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
+-                                       nsBoundingMetrics &aBoundingMetrics,
+-                                       nsRenderingContextGTK *aContext)
++nsFontMetricsPango::DrawString(const char *aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               const nscoord* aSpacing
++                               CONTEXT_AND_SURFACE_ARG_DEF)
+ {
+-    printf("GetBoundingMetrics (char *)\n");
+-    return NS_ERROR_FAILURE;
++    int x = aX;
++    int y = aY;
++
++    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++
++    PangoLayout *layout = GetLayout(aString, aLength);
++    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
++
++    ApplySpacing(aString, aLength, line, aSpacing);
++    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
++
++    g_object_unref(layout);
++
++    return NS_OK;
+ }
+ nsresult
+-nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
+-                                       PRUint32 aLength,
+-                                       nsBoundingMetrics &aBoundingMetrics,
+-                                       PRInt32 *aFontID,
+-                                       nsRenderingContextGTK *aContext)
++nsFontMetricsPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               PRInt32 aFontID,
++                               const nscoord* aSpacing
++                               CONTEXT_AND_SURFACE_ARG_DEF)
+ {
+-    nsresult rv = NS_OK;
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
++    int x = aX;
++    int y = aY;
+-    gchar *text = g_utf16_to_utf8(aString, aLength,
+-                                  NULL, NULL, NULL);
++    aContext->GetTranMatrix()->TransformCoord(&x, &y);
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetBoundingMetrics invalid unicode to follow");
+-        DUMP_PRUNICHAR(aString, aLength)
+-#endif
+-        aBoundingMetrics.Clear();
++    PangoLayout *layout = GetLayout(aString, aLength);
++    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
++    ApplySpacing(aString, aLength, line, aSpacing);
++    draw_layout_line(x, y, line, this CONTEXT_AND_SURFACE_ARG_PASS);
+-    pango_layout_set_text(layout, text, -1);
+-    FixupSpaceWidths(layout, text);
++    g_object_unref(layout);
++
++    return NS_OK;
++}
+-    PangoLayoutLine *line;
+-    if (pango_layout_get_line_count(layout) != 1) {
+-        printf("Warning: more than one line!\n");
+-    }
+-    line = pango_layout_get_line(layout, 0);
++
++#ifdef MOZ_MATHML
++void
++nsFontMetricsPango::GetBoundingMetricsInternal(PangoLayout *aLayout,
++                                               nsBoundingMetrics &aBoundingMetrics
++                                               CONTEXT_ARG_DEF)
++{
++    PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
+     // Get the ink and logical extents
+     PangoRectangle ink, logical;
+     pango_layout_line_get_extents(line, &ink, &logical);
+-    float P2T;
+-    P2T = mDeviceContext->DevUnitsToAppUnits();
++    float P2T = mDeviceContext->DevUnitsToAppUnits();
+     aBoundingMetrics.leftBearing  = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
+     aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
+     aBoundingMetrics.ascent       = NSToCoordRound(PANGO_ASCENT(ink)   * P2T / PANGO_SCALE);
+     aBoundingMetrics.descent      = NSToCoordRound(PANGO_DESCENT(ink)  * P2T / PANGO_SCALE);
+     aBoundingMetrics.width        = NSToCoordRound(logical.width       * P2T / PANGO_SCALE);
++}
+- loser:
+-    g_free(text);
++nsresult
++nsFontMetricsPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
++                                       nsBoundingMetrics &aBoundingMetrics
++                                       CONTEXT_ARG_DEF)
++{
++    PangoLayout *layout = GetLayout(aString, aLength);
++    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
+     g_object_unref(layout);
+-    return rv;
++   return NS_OK;
++}
++
++nsresult
++nsFontMetricsPango::GetBoundingMetrics(const PRUnichar *aString,
++                                       PRUint32 aLength,
++                                       nsBoundingMetrics &aBoundingMetrics,
++                                       PRInt32 *aFontID
++                                       CONTEXT_ARG_DEF)
++{
++    PangoLayout *layout = GetLayout(aString, aLength);
++    GetBoundingMetricsInternal (layout, aBoundingMetrics CONTEXT_ARG_PASS);
++    g_object_unref(layout);
++
++    return NS_OK;
+ }
+ #endif /* MOZ_MATHML */
++#ifndef PSPANGO
+ GdkFont*
+ nsFontMetricsPango::GetCurrentGDKFont(void)
+ {
+     return nsnull;
+ }
++#endif
+ nsresult
+ nsFontMetricsPango::SetRightToLeftText(PRBool aIsRTL)
+ {
+     if (aIsRTL) {
+         if (!mRTLPangoContext) {
+-            mRTLPangoContext = gdk_pango_context_get();
++            mRTLPangoContext = get_context();
+             pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
+-
+-            gdk_pango_context_set_colormap(mRTLPangoContext, gdk_rgb_get_cmap());
+             pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
+             pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
+         }
+@@ -899,34 +1087,18 @@ nsFontMetricsPango::GetClusterInfo(const
+                                    PRUint32 aLength,
+                                    PRUint8 *aClusterStarts)
+ {
+-    nsresult rv = NS_OK;
+     PangoLogAttr *attrs = NULL;
+     gint n_attrs = 0;
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
+-    
+-    // Convert the incoming UTF-16 to UTF-8
+-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
+-        DUMP_PRUNICHAR(aText, aLength)
+-#endif
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
+-
+-    // Set up the pango layout
+-    pango_layout_set_text(layout, text, strlen(text));
+-    FixupSpaceWidths(layout, text);
++    PangoLayout *layout = GetLayout(aText, aLength);
++    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
++    g_object_unref(layout);
+     // Convert back to UTF-16 while filling in the cluster info
+     // structure.
+-    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
+-
+     for (PRUint32 pos = 0; pos < aLength; pos++) {
+         if (IS_HIGH_SURROGATE(aText[pos])) {
+-            aClusterStarts[pos] = 1;
++            aClusterStarts[pos] = 1;//FIXME: shouldn't this be zero?! --be
+             pos++;
+         }
+         else {
+@@ -934,56 +1106,34 @@ nsFontMetricsPango::GetClusterInfo(const
+         }
+     }
+- loser:
+-    if (attrs)
+-        g_free(attrs);
+-    if (text)
+-        g_free(text);
+-    if (layout)
+-        g_object_unref(layout);
++    g_free(attrs);
+-    return rv;
++    return NS_OK;
+ }
+ PRInt32
+-nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
+-                                nsPoint aPt)
++nsFontMetricsPango::GetPosition(const PRUnichar *aText, PRUint32 aLength, nsPoint aPt)
+ {
+     int trailing = 0;
+     int inx = 0;
+-    const gchar *curChar;
+     PRInt32 retval = 0;
+     float f = mDeviceContext->AppUnitsToDevUnits();
+     
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
+     PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
+     PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
+-    // Convert the incoming UTF-16 to UTF-8
+-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
+-
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
+-        DUMP_PRUNICHAR(aText, aLength)
+-#endif
+-        retval = -1;
+-        goto loser;
+-    }
+-
+-    // Set up the pango layout
+-    pango_layout_set_text(layout, text, strlen(text));
+-    FixupSpaceWidths(layout, text);
++    PangoLayout *layout = GetLayout(aText, aLength);
+     
+     pango_layout_xy_to_index(layout, localX, localY,
+                              &inx, &trailing);
+     // Convert the index back to the utf-16 index
+-    curChar = text;
++    const gchar *text = pango_layout_get_text (layout);
++    const gchar *curChar = text;
+     for (PRUint32 curOffset=0; curOffset < aLength;
+-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++         curOffset++, curChar = g_utf8_next_char(curChar)) {
+         // Check for a match before checking for a surrogate pair
+         if (curChar - text == inx) {
+@@ -1006,13 +1156,9 @@ nsFontMetricsPango::GetPosition(const PR
+         trailing--;
+     }
+- loser:
+-    if (text)
+-        g_free(text);
+-    if (layout)
+-        g_object_unref(layout);
++    g_object_unref(layout);
+-    return retval;
++    return retval; 
+ }
+ nsresult
+@@ -1022,28 +1168,21 @@ nsFontMetricsPango::GetRangeWidth(const 
+                                   PRUint32 aEnd,
+                                   PRUint32 &aWidth)
+ {
+-    nsresult rv = NS_OK;
+     PRUint32 utf8Start = 0;
+     PRUint32 utf8End = 0;
+     aWidth = 0;
+     // Convert the incoming UTF-16 to UTF-8
+-    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
+-    gchar *curChar = text;
+-    if (!text) {
+-#ifdef DEBUG
+-        NS_WARNING("nsFontMetricsPango::GetWidth invalid unicode to follow");
+-        DUMP_PRUNICHAR(aText, aLength)
+-#endif
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
++    gchar* text;
++    gint text_len;
++    utf16_to_utf8 (aText, aLength, text, text_len);
++    gchar *curChar = text;
+     // Convert the utf16 offsets into utf8 offsets
+     for (PRUint32 curOffset = 0; curOffset < aLength;
+-         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++         curOffset++, curChar = g_utf8_next_char(curChar)) {
+         if (curOffset == aStart)
+             utf8Start = curChar - text;
+@@ -1057,15 +1196,13 @@ nsFontMetricsPango::GetRangeWidth(const 
+     // Special case where the end index is the same as the length
+     if (aLength == aEnd)
+-        utf8End = strlen(text);
++        utf8End = text_len;
+-    rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
++    GetRangeWidth(text, text_len, utf8Start, utf8End, aWidth);
+- loser:
+-    if (text)
+-        g_free(text);
++    g_free(text);
+-    return rv;
++    return NS_OK;
+ }
+ nsresult
+@@ -1075,43 +1212,26 @@ nsFontMetricsPango::GetRangeWidth(const 
+                                   PRUint32 aEnd,
+                                   PRUint32 &aWidth)
+ {
+-    nsresult rv = NS_OK;
+     int *ranges = NULL;
+     int n_ranges = 0;
+     float f;
+     aWidth = 0;
+-    PangoLayout *layout = pango_layout_new(mPangoContext);
+-
+-    if (!aText) {
+-        rv = NS_ERROR_FAILURE;
+-        goto loser;
+-    }
+-
+-    pango_layout_set_text(layout, aText, aLength);
+-    FixupSpaceWidths(layout, aText);
+-
+-    PangoLayoutLine *line;
+-    if (pango_layout_get_line_count(layout) != 1) {
+-        printf("Warning: more than one line!\n");
+-    }
+-    line = pango_layout_get_line(layout, 0);
++    PangoLayout *layout = GetLayout(aText, aLength);
++    PangoLayoutLine *line = pango_layout_get_line(layout, 0);
+     pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
+     aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
+     f = mDeviceContext-> DevUnitsToAppUnits();
+-    aWidth = nscoord(aWidth * f / PANGO_SCALE);
++    aWidth = NSToCoordRound(aWidth * f / PANGO_SCALE);
+- loser:
+-    if (ranges)
+-        g_free(ranges);
+-    if (layout)
+-        g_object_unref(layout);
++    g_free(ranges);
++    g_object_unref(layout);
+-    return rv;
++    return NS_OK;
+ }
+ /* static */
+@@ -1134,7 +1254,7 @@ nsFontMetricsPango::FamilyExists(nsIDevi
+     NS_ConvertUTF16toUTF8 name(aName);
+     nsresult rv = NS_ERROR_FAILURE;
+-    PangoContext *context = gdk_pango_context_get();
++    PangoContext *context = get_context();
+     PangoFontFamily **familyList;
+     int n;
+@@ -1233,16 +1353,13 @@ nsFontMetricsPango::RealizeFont(void)
+     // Now that we have the font description set up, create the
+     // context.
+-    mLTRPangoContext = gdk_pango_context_get();
++    mLTRPangoContext = get_context();
+     mPangoContext = mLTRPangoContext;
+     // Make sure to set the base direction to LTR - if layout needs to
+     // render RTL text it will use ::SetRightToLeftText()
+     pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
+-    // Set the color map so we can draw later.
+-    gdk_pango_context_set_colormap(mPangoContext, gdk_rgb_get_cmap());
+-
+     // Set the pango language now that we have a context
+     pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
+@@ -1280,79 +1397,268 @@ nsFontMetricsPango::EnumFontCallback(con
+  * This is only used when there's per-character spacing happening.
+  * Well, really it can be either line or character spacing but it's
+  * just turtles all the way down!
++ *
++ * To do it correctly (ligatures, etc) we need machinery that is private
++ * in Pango.  IMPORT IT:
++ */
++
++#define _PangoGlyphItemIter _nsFontMetricsPangoGlyphItemIter
++#define PangoGlyphItemIter nsFontMetricsPangoGlyphItemIter
++
++#define LTR(glyph_item) (((glyph_item)->item->analysis.level % 2) == 0)
++
++/* Structure holding state when we're iterating over a GlyphItem.
++ * start_index/cluster_end (and range_start/range_end in
++ * apply_attrs()) are offsets into the text, so note the difference
++ * of glyph_item->item->offset between them and clusters in the
++ * log_clusters[] array.
+  */
++typedef struct _PangoGlyphItemIter PangoGlyphItemIter;
++
++struct _PangoGlyphItemIter
++{
++  PangoGlyphItem *glyph_item;
++  const gchar *text;
++  
++  int start_glyph;
++  int start_index;
++  int start_char;
++
++  int end_glyph;
++  int end_index;
++  int end_char;
++};
++
++/**
++ * _pango_glyph_item_iter_next_cluster:
++ * @iter: a #PangoGlyphItemIter
++ * 
++ * Advances the iterator to the next cluster in the glyph item.
++ * 
++ * Return value: %TRUE if the iterator was advanced, %FALSE if we were already on the
++ *  last cluster.
++ **/
++static gboolean
++_pango_glyph_item_iter_next_cluster (PangoGlyphItemIter *iter)
++{
++  int glyph_index = iter->end_glyph;
++  PangoGlyphString *glyphs = iter->glyph_item->glyphs;
++  PangoItem *item = iter->glyph_item->item;
++
++  if (LTR (iter->glyph_item))
++    {
++      if (glyph_index == glyphs->num_glyphs)
++      return FALSE;
++    }
++  else
++    {
++      if (glyph_index < 0)
++      return FALSE;
++    }
++      
++  iter->start_glyph = iter->end_glyph;
++  iter->start_index = iter->end_index;
++  iter->start_char = iter->end_char;
++  
++  if (LTR (iter->glyph_item))
++    {
++      while (TRUE)
++      {
++        glyph_index++;
++        
++        if (glyph_index == glyphs->num_glyphs)
++          {
++            iter->end_index = item->offset + item->length;
++            iter->end_char = item->num_chars;
++            break;
++          }
++        
++        if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
++          {
++            iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
++            iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
++                                             iter->end_index - iter->start_index);
++            break; 
++          }
++      }
++    }
++  else                        /* RTL */
++    {
++      while (TRUE)
++      {
++        glyph_index--;
++        
++        if (glyph_index < 0)
++          {
++            iter->end_index = item->offset + item->length;
++            iter->end_char = item->num_chars;
++            break;
++          }
++        
++        if (item->offset + glyphs->log_clusters[glyph_index] != iter->start_index)
++          {
++            iter->end_index = item->offset + glyphs->log_clusters[glyph_index];
++            iter->end_char += g_utf8_strlen (iter->text + iter->start_index,
++                                             iter->end_index - iter->start_index);
++            break; 
++          }
++      }
++    }
++
++  iter->end_glyph = glyph_index;
++  return TRUE;
++}
++
++/**
++ * _pango_glyph_item_iter_init_start:
++ * @iter: pointer to a #PangoGlyphItemIter structure
++ * @glyph_item: the glyph item that the iter points into
++ * @text: text corresponding to the glyph item
++ * 
++ * Initializes a #PangoGlyphItemIter structure to point to the
++ * first cluster in a glyph item.
++ * 
++ * Return value: %FALSE if there are no clusters in the glyph item;
++ *  in this case, the state of the iter is undefined.
++ **/
++static gboolean
++_pango_glyph_item_iter_init_start (PangoGlyphItemIter  *iter,
++                                 PangoGlyphItem      *glyph_item,
++                                 const char          *text)
++{
++  iter->glyph_item = glyph_item;
++  iter->text = text;
++  
++  if (LTR (glyph_item))
++    iter->end_glyph = 0;
++  else
++    iter->end_glyph = glyph_item->glyphs->num_glyphs - 1;
++
++  iter->end_index = glyph_item->item->offset;
++  iter->end_char = 0;
++
++  /* Advance onto the first cluster of the glyph item */
++  return _pango_glyph_item_iter_next_cluster (iter);
++}
++
+ void
+-nsFontMetricsPango::DrawStringSlowly(const gchar *aText,
+-                                     const PRUnichar *aOrigString,
+-                                     PRUint32 aLength,
+-                                     GdkDrawable *aDrawable,
+-                                     GdkGC *aGC, gint aX, gint aY,
+-                                     PangoLayoutLine *aLine,
+-                                     const nscoord *aSpacing)
+-{
+-    float app2dev;
+-    app2dev = mDeviceContext->AppUnitsToDevUnits();
+-    gint offset = 0;
++nsFontMetricsPango::ApplySpacing(const gchar *aText,
++                                 PRUint32 aLength,
++                                 PangoLayoutLine *aLine,
++                                 const nscoord *aSpacing)
++{
++    if (!(aSpacing && *aSpacing))
++      return;
++
++    float app2dev = mDeviceContext->AppUnitsToDevUnits();
+     /*
+      * We walk the list of glyphs returned in each layout run,
+      * matching up the glyphs with the characters in the source text.
+      * We use the aSpacing argument to figure out where to place those
+-     * glyphs.  It's important to note that since the string we're
+-     * working with is in UTF-8 while the spacing argument assumes
+-     * that offset will be part of the UTF-16 string.  Logical
+-     * attributes in pango are in byte offsets in the UTF-8 string, so
+-     * we need to store the offsets based on the UTF-8 string.
++     * glyphs.
+      */
+-    nscoord *utf8spacing = new nscoord[strlen(aText)];
++    for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
++         tmpList = tmpList->next) {
++        PangoGlyphItem *glyph_item = (PangoGlyphItem *)tmpList->data;
++        PangoGlyphItemIter iter;
++        gboolean have_cluster;
++        PangoGlyphInfo *glyphs = glyph_item->glyphs->glyphs;
++        int residualWidth = 0;
++
++        for (have_cluster = _pango_glyph_item_iter_init_start (&iter, glyph_item, aText);
++             have_cluster;
++             have_cluster = _pango_glyph_item_iter_next_cluster (&iter))
++        {
++          int clusterOldWidth = 0;
++          int clusterNewWidth = 0;
++          int dir = iter.start_glyph < iter.end_glyph ? +1 : -1;
++          gboolean has_zero_width = FALSE;
++
++          for (const char *p = iter.text + iter.start_index;
++               p < iter.text + iter.end_index;
++               p = g_utf8_next_char (p))
++            clusterNewWidth += aSpacing[p - iter.text];
++
++          clusterNewWidth = (gint)(clusterNewWidth * app2dev * PANGO_SCALE);
++
++          for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir) {
++            if (!glyphs[i].geometry.width)
++              has_zero_width = TRUE;
++            clusterOldWidth += glyphs[i].geometry.width;
++          }
++            
++          /* if a zero-width glyph exists, don't touch the glyph widths.
++           * required for combining marks.  ff thinks they have a width.
++           * instead, we charge the difference to the next space glyph. */
++          if (has_zero_width) {
++            residualWidth += clusterNewWidth - clusterOldWidth;
++            continue;
++          }
+-    if (aOrigString) {
+-        const gchar *curChar = aText;
+-        bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
+-
+-        // Covert the utf16 spacing offsets to utf8 spacing offsets
+-        for (PRUint32 curOffset=0; curOffset < aLength;
+-             curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
+-            utf8spacing[curChar - aText] = aSpacing[curOffset];
++          /* If a space glyph is found, charge it whatever residual we
++           * have accumulated so far. */
++          if (iter.end_index - iter.start_index == 1 &&
++              *(iter.text + iter.start_index) == ' ') {
++            clusterNewWidth += residualWidth;
++            residualWidth = 0;
++          }
++          
++#ifndef PSPANGO
++          /* do some hinting for display */
++
++          if (clusterOldWidth % PANGO_SCALE == 0 && clusterNewWidth % PANGO_SCALE != 0) {
++            int tmp = clusterNewWidth;
++            clusterNewWidth = PANGO_PIXELS (clusterNewWidth) * PANGO_SCALE;
++            residualWidth += tmp - clusterNewWidth;
++          }
++#endif
+-            if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
+-                curOffset++;
++          /* find the first non-zero-width glyph and adjust its width */
++          for (gint i = iter.start_glyph; i != iter.end_glyph; i += dir)
++            if (glyphs[i].geometry.width) {
++              glyphs[i].geometry.width += clusterNewWidth - clusterOldWidth;
++              break;
++            }
+         }
+     }
+-    else {
+-        memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
+-    }
++}
+-    gint curRun = 0;
++void
++nsFontMetricsPango::ApplySpacing(const PRUnichar *aText,
++                                 PRUint32 aLength,
++                                 PangoLayoutLine *aLine,
++                                 const nscoord *aSpacing)
++{
++    if (!(aSpacing && *aSpacing))
++      return;
+-    for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
+-         tmpList = tmpList->next, curRun++) {
+-        PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
+-        gint tmpOffset = 0;
++    const char *utf8Text = pango_layout_get_text (aLine->layout);
++    int utf8Text_len = aLine->start_index + aLine->length;
+-        /*        printf("    Rendering run %d: \"%s\"\n", curRun,
+-                  &aText[layoutRun->item->offset]); */
++    /* Since the string we're
++     * working with is in UTF-8 while the spacing argument assumes
++     * that offset will be part of the UTF-16 string.  Logical
++     * attributes in pango are in byte offsets in the UTF-8 string, so
++     * we need to store the offsets based on the UTF-8 string.
++     */
++    nscoord *utf8spacing = g_new0 (nscoord, utf8Text_len);
+-        for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
+-            /* printf("glyph %d offset %d orig width %d new width %d\n", i,
+-             *        layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
+-             *        layoutRun->glyphs->glyphs[i].geometry.width,
+-             *       (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
+-             */
+-            gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
+-                                     * app2dev * PANGO_SCALE);
+-            layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
+-            tmpOffset += thisOffset;
+-        }
++    const gchar *curChar = utf8Text + aLine->start_index;
+-        /*        printf("    rendering at X coord %d\n", aX + offset); */
+-        offset += tmpOffset;
++    // Covert the utf16 spacing offsets to utf8 spacing offsets
++    for (PRUint32 curOffset=0; curOffset < aLength;
++         curOffset++, curChar = g_utf8_next_char(curChar)) {
++        utf8spacing[curChar - utf8Text] = aSpacing[curOffset];
++
++        if (IS_HIGH_SURROGATE(aText[curOffset]))
++            curOffset++;
+     }
+-    gdk_draw_layout_line(aDrawable, aGC, aX, aY, aLine);
++    ApplySpacing (utf8Text, utf8Text_len, aLine, utf8spacing);
+-    delete[] utf8spacing;
++    g_free (utf8spacing);
+ }
+ nsresult
+@@ -1363,8 +1669,8 @@ nsFontMetricsPango::GetTextDimensionsInt
+                                               PRInt32             aNumBreaks,
+                                               nsTextDimensions&   aDimensions,
+                                               PRInt32&            aNumCharsFit,
+-                                              nsTextDimensions&   aLastWordDimensions,
+-                                              nsRenderingContextGTK *aContext)
++                                              nsTextDimensions&   aLastWordDimensions
++                                              CONTEXT_ARG_DEF)
+ {
+     NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
+@@ -1410,7 +1716,7 @@ nsFontMetricsPango::GetTextDimensionsInt
+             // All the characters should fit
+             numChars = aLength - start;
+             breakIndex = aNumBreaks - 1;
+-        } 
++        }
+         else {
+             breakIndex = prevBreakState_BreakIndex;
+             while (((breakIndex + 1) < aNumBreaks) &&
+@@ -1431,7 +1737,7 @@ nsFontMetricsPango::GetTextDimensionsInt
+         if ((1 == numChars) && (aString[start] == ' '))
+             GetSpaceWidth(twWidth);
+         else if (numChars > 0)
+-            GetWidth(&aString[start], numChars, twWidth, aContext);
++            GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
+         // See if the text fits
+         PRBool  textFits = (twWidth + width) <= aAvailWidth;
+@@ -1481,8 +1787,7 @@ nsFontMetricsPango::GetTextDimensionsInt
+                 if ((1 == numChars) && (aString[start] == ' '))
+                     GetSpaceWidth(twWidth);
+                 else if (numChars > 0)
+-                    GetWidth(&aString[start], numChars, twWidth,
+-                             aContext);
++                    GetWidth(&aString[start], numChars, twWidth CONTEXT_ARG_PASS);
+                 width -= twWidth;
+                 aNumCharsFit = start;
+                 breakIndex--;
+@@ -1504,9 +1809,16 @@ nsFontMetricsPango::GetTextDimensionsInt
+ }
+ void
+-nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout,
+-                                      const char *aString)
++nsFontMetricsPango::FixupSpaceWidths (PangoLayout *aLayout)
+ {
++    if (!mPangoSpaceWidth)
++      return;
++
++    const char *aString = pango_layout_get_text (aLayout);
++
++    if (pango_layout_get_line_count(aLayout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
+     PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
+     gint curRun = 0;
+@@ -1523,6 +1835,107 @@ nsFontMetricsPango::FixupSpaceWidths (Pa
+     }
+ }
++PangoLayout*
++nsFontMetricsPango::GetLayout (const PRUnichar* aText,
++                               PRUint32         aLength)
++{
++  gchar* text;
++  gint length;
++  utf16_to_utf8 (aText, aLength, text, length);
++
++  PangoLayout *layout = pango_layout_new(mPangoContext);
++  pango_layout_set_text (layout, text, length);
++  FixupSpaceWidths (layout);
++
++  g_free ((gpointer) text);
++
++  return layout;
++}
++
++PangoLayout*
++nsFontMetricsPango::GetLayout (const gchar*     aText,
++                               PRInt32          aLength)
++{
++  gboolean has_nul = FALSE;
++  int i;
++
++  for (i = 0; i < aLength; i++)
++    if (!aText[i]) {
++      has_nul = TRUE;
++      break;
++    }
++
++  if (has_nul) {
++    /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
++
++    char *p = (char *) g_memdup (aText, aLength);
++
++    /* don't need to reset i */
++    for (; i < aLength; i++)
++      if (!p[i])
++        p[i] = (char) 0xff;
++
++    aText = p;
++  }
++
++  PangoLayout *layout = pango_layout_new(mPangoContext);
++  pango_layout_set_text (layout, aText, aLength);
++  FixupSpaceWidths (layout);
++
++  if (has_nul)
++    g_free ((gpointer) aText);
++
++  return layout;
++}
++
++static void
++utf16_to_utf8 (const PRUnichar* aText, PRUint32 aLength, char *&text, gint &length)
++{
++  gboolean need_copy = FALSE;
++  int i;
++
++  for (i = 0; i < aLength; i++) {
++    if (!aText[i] || IS_LOW_SURROGATE (aText[i]))
++      need_copy = TRUE;
++    else if (IS_HIGH_SURROGATE (aText[i])) {
++      if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
++        i++;
++      else
++        need_copy = TRUE;
++    }
++  }
++
++  if (need_copy) {
++
++    /* Pango doesn't correctly handle nuls.  We convert them to 0xff. */
++    /* Also "validate" UTF-16 text to make sure conversion doesn't fail. */
++
++    PRUnichar *p = (PRUnichar *) g_memdup (aText, aLength * sizeof (aText[0]));
++
++    /* don't need to reset i */
++    for (i = 0; i < aLength; i++) {
++      if (!p[i] || IS_LOW_SURROGATE (p[i]))
++        p[i] = 0xFFFD;
++      else if (IS_HIGH_SURROGATE (p[i])) {
++        if (i < aLength - 1 && IS_LOW_SURROGATE (aText[i+1]))
++          i++;
++        else
++          p[i] = 0xFFFD;
++      }
++    }
++
++    aText = p;
++  }
++
++  glong items_written;
++  text = g_utf16_to_utf8 (aText, aLength, NULL, &items_written, NULL);
++  length = items_written;
++
++  if (need_copy)
++    g_free ((gpointer) aText);
++
++}
++
+ /* static */
+ PangoLanguage *
+ GetPangoLanguage(nsIAtom *aLangGroup)
+--- mozilla.back/gfx/src/gtk/nsFontMetricsPango.h.orig 2006-06-30 01:18:34.000000000 +0200
++++ mozilla.back/gfx/src/gtk/nsFontMetricsPango.h      2007-06-28 15:16:39.000000000 +0200
+@@ -37,17 +37,53 @@
+  *
+  * ***** END LICENSE BLOCK ***** */
++
+ #include "nsIFontMetrics.h"
+ #include "nsIFontEnumerator.h"
+ #include "nsCRT.h"
+ #include "nsIAtom.h"
+ #include "nsString.h"
+ #include "nsVoidArray.h"
++
++#ifdef PSPANGO
++#include "nsFontMetricsPS.h"
++#else
+ #include "nsIFontMetricsGTK.h"
++#endif
+ #include <pango/pango.h>
+-class nsFontMetricsPango : public nsIFontMetricsGTK
++#ifdef PSPANGO
++
++#define CONTEXT_ARG_DEF
++#define CONTEXT_ARG_PASS
++#define CONTEXT_ARG_NULL
++#define CONTEXT_AND_SURFACE_ARG_DEF  , nsRenderingContextPS *aContext
++#define CONTEXT_AND_SURFACE_ARG_PASS , aContext
++
++#else
++
++#define CONTEXT_ARG_DEF              , nsRenderingContextGTK *aContext
++#define CONTEXT_ARG_PASS             , aContext
++#define CONTEXT_ARG_NULL             , NULL
++#define CONTEXT_AND_SURFACE_ARG_DEF  , nsRenderingContextGTK *aContext, nsDrawingSurfaceGTK *aSurface
++#define CONTEXT_AND_SURFACE_ARG_PASS , aContext, aSurface
++
++#endif
++
++
++#ifdef PSPANGO
++
++#define nsFontMetricsPango   nsFontMetricsPSPango
++#define PSPANGO_PARENT_CLASS nsFontMetricsPS
++
++#else
++
++#define PSPANGO_PARENT_CLASS nsIFontMetricsGTK
++
++#endif
++
++class nsFontMetricsPango : public PSPANGO_PARENT_CLASS
+ {
+ public:
+     nsFontMetricsPango();
+@@ -136,20 +172,30 @@ public:
+     PRInt32 GetMaxStringLength() { return mMaxStringLength; }
+-    // nsIFontMetricsGTK (calls from the font rendering layer)
+-    virtual nsresult GetWidth(const char* aString, PRUint32 aLength,
+-                              nscoord& aWidth,
+-                              nsRenderingContextGTK *aContext);
+-    virtual nsresult GetWidth(const PRUnichar* aString, PRUint32 aLength,
+-                              nscoord& aWidth, PRInt32 *aFontID,
+-                              nsRenderingContextGTK *aContext);
++    // nsIFontMetrics (calls from the font rendering layer)
+-    virtual nsresult GetTextDimensions(const PRUnichar* aString,
++#ifdef PSPANGO
++    NS_IMETHOD  GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
++    NS_IMETHOD  GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
++#endif
++
++    NS_METHOD        GetWidth(const char* aString, PRUint32 aLength,
++                              nscoord& aWidth
++                              CONTEXT_ARG_DEF);
++    NS_METHOD        GetWidth(const PRUnichar* aString, PRUint32 aLength,
++                              nscoord& aWidth, PRInt32 *aFontID
++                              CONTEXT_ARG_DEF);
++
++    NS_METHOD        GetTextDimensions(const char* aString,
++                                       PRUint32 aLength,
++                                       nsTextDimensions& aDimensions
++                                       CONTEXT_ARG_DEF);
++    NS_METHOD        GetTextDimensions(const PRUnichar* aString,
+                                        PRUint32 aLength,
+                                        nsTextDimensions& aDimensions, 
+-                                       PRInt32* aFontID,
+-                                       nsRenderingContextGTK *aContext);
+-    virtual nsresult GetTextDimensions(const char*         aString,
++                                       PRInt32* aFontID
++                                       CONTEXT_ARG_DEF);
++    NS_METHOD        GetTextDimensions(const char*         aString,
+                                        PRInt32             aLength,
+                                        PRInt32             aAvailWidth,
+                                        PRInt32*            aBreaks,
+@@ -157,9 +203,9 @@ public:
+                                        nsTextDimensions&   aDimensions,
+                                        PRInt32&            aNumCharsFit,
+                                        nsTextDimensions&   aLastWordDimensions,
+-                                       PRInt32*            aFontID,
+-                                       nsRenderingContextGTK *aContext);
+-    virtual nsresult GetTextDimensions(const PRUnichar*    aString,
++                                       PRInt32*            aFontID
++                                       CONTEXT_ARG_DEF);
++    NS_METHOD        GetTextDimensions(const PRUnichar*    aString,
+                                        PRInt32             aLength,
+                                        PRInt32             aAvailWidth,
+                                        PRInt32*            aBreaks,
+@@ -167,38 +213,37 @@ public:
+                                        nsTextDimensions&   aDimensions,
+                                        PRInt32&            aNumCharsFit,
+                                        nsTextDimensions&   aLastWordDimensions,
+-                                       PRInt32*            aFontID,
+-                                       nsRenderingContextGTK *aContext);
++                                       PRInt32*            aFontID
++                                       CONTEXT_ARG_DEF);
+-    virtual nsresult DrawString(const char *aString, PRUint32 aLength,
++    NS_METHOD        DrawString(const char *aString, PRUint32 aLength,
+                                 nscoord aX, nscoord aY,
+-                                const nscoord* aSpacing,
+-                                nsRenderingContextGTK *aContext,
+-                                nsDrawingSurfaceGTK *aSurface);
+-    virtual nsresult DrawString(const PRUnichar* aString, PRUint32 aLength,
++                                const nscoord* aSpacing  
++                                CONTEXT_AND_SURFACE_ARG_DEF);
++
++    NS_METHOD        DrawString(const PRUnichar* aString, PRUint32 aLength,
+                                 nscoord aX, nscoord aY,
+                                 PRInt32 aFontID,
+-                                const nscoord* aSpacing,
+-                                nsRenderingContextGTK *aContext,
+-                                nsDrawingSurfaceGTK *aSurface);
++                                const nscoord* aSpacing  
++                                CONTEXT_AND_SURFACE_ARG_DEF);
+ #ifdef MOZ_MATHML
+-    virtual nsresult GetBoundingMetrics(const char *aString, PRUint32 aLength,
+-                                        nsBoundingMetrics &aBoundingMetrics,
+-                                        nsRenderingContextGTK *aContext);
+-    virtual nsresult GetBoundingMetrics(const PRUnichar *aString,
++    NS_METHOD        GetBoundingMetrics(const char *aString, PRUint32 aLength,
++                                        nsBoundingMetrics &aBoundingMetrics
++                                        CONTEXT_ARG_DEF);
++    NS_METHOD        GetBoundingMetrics(const PRUnichar *aString,
+                                         PRUint32 aLength,
+                                         nsBoundingMetrics &aBoundingMetrics,
+-                                        PRInt32 *aFontID,
+-                                        nsRenderingContextGTK *aContext);
++                                        PRInt32 *aFontID
++                                        CONTEXT_ARG_DEF);
+ #endif /* MOZ_MATHML */
+-
++#ifndef PSPANGO
+     virtual GdkFont* GetCurrentGDKFont(void);
+-
+-    virtual nsresult SetRightToLeftText(PRBool aIsRTL);
++#endif
+     virtual PRBool GetRightToLeftText();
+-
+-    virtual nsresult GetClusterInfo(const PRUnichar *aText,
++    NS_METHOD        SetRightToLeftText(PRBool aIsRTL);
++    
++    NS_METHOD        GetClusterInfo(const PRUnichar *aText,
+                                     PRUint32 aLength,
+                                     PRUint8 *aClusterStarts);
+@@ -206,32 +251,35 @@ public:
+                                 PRUint32 aLength,
+                                 nsPoint aPt);
+-    virtual nsresult GetRangeWidth(const PRUnichar *aText,
++    NS_METHOD        GetRangeWidth(const PRUnichar *aText,
+                                    PRUint32 aLength,
+                                    PRUint32 aStart,
+                                    PRUint32 aEnd,
+                                    PRUint32 &aWidth);
+-    virtual nsresult GetRangeWidth(const char *aText,
++    NS_METHOD        GetRangeWidth(const char *aText,
+                                    PRUint32 aLength,
+                                    PRUint32 aStart,
+                                    PRUint32 aEnd,
+                                    PRUint32 &aWidth);
+     // get hints for the font
+-    static PRUint32    GetHints     (void);
++#ifndef PSPANGO
++    static
++#endif
++    PRUint32    GetHints     (void);
+     // drawing surface methods
+     static nsresult FamilyExists    (nsIDeviceContext *aDevice,
+                                      const nsString &aName);
++
+ private:
+     // generic font metrics class bits
+     nsCStringArray       mFontList;
+     nsAutoVoidArray      mFontIsGeneric;
+-    nsIDeviceContext    *mDeviceContext;
+     nsCOMPtr<nsIAtom>    mLangGroup;
+     nsCString           *mGenericFont;
+     float                mPointSize;
+@@ -246,6 +294,9 @@ private:
+     PangoAttrList        *mPangoAttrList;
+     PRBool                mIsRTL;
++#ifndef PSPANGO
++    nsIDeviceContext    *mDeviceContext; 
++
+     // Cached font metrics
+     nscoord                  mXHeight;
+     nscoord                  mSuperscriptOffset;
+@@ -263,6 +314,7 @@ private:
+     nscoord                  mMaxDescent;
+     nscoord                  mMaxAdvance;
+     nscoord                  mSpaceWidth;
++#endif
+     nscoord                  mPangoSpaceWidth;
+     nscoord                  mAveCharWidth;
+     PRInt32                  mMaxStringLength;
+@@ -274,13 +326,14 @@ private:
+     static PRBool EnumFontCallback(const nsString &aFamily,
+                                    PRBool aIsGeneric, void *aData);
+-    void     DrawStringSlowly(const gchar *aText,
+-                              const PRUnichar *aOrigString,
+-                              PRUint32 aLength,
+-                              GdkDrawable *aDrawable,
+-                              GdkGC *aGC, gint aX, gint aY,
+-                              PangoLayoutLine *aLine,
+-                              const nscoord *aSpacing);
++    void ApplySpacing(const gchar *aText,
++                      PRUint32 aLength,
++                      PangoLayoutLine *aLine,
++                      const nscoord *aSpacing);
++    void ApplySpacing(const PRUnichar *aText,
++                      PRUint32 aLength,
++                      PangoLayoutLine *aLine,
++                      const nscoord *aSpacing);
+     nsresult GetTextDimensionsInternal(const gchar*        aString,
+                                        PRInt32             aLength,
+@@ -289,10 +342,20 @@ private:
+                                        PRInt32             aNumBreaks,
+                                        nsTextDimensions&   aDimensions,
+                                        PRInt32&            aNumCharsFit,
+-                                       nsTextDimensions&   aLastWordDimensions,
+-                                       nsRenderingContextGTK *aContext);
++                                       nsTextDimensions&   aLastWordDimensions
++                                       CONTEXT_ARG_DEF);
++#ifdef MOZ_MATHML
++    void GetBoundingMetricsInternal(PangoLayout *aLayout,
++                                    nsBoundingMetrics &aBoundingMetrics
++                                    CONTEXT_ARG_DEF);
++#endif /* MOZ_MATHML */
++
++    void FixupSpaceWidths (PangoLayout *aLayout);
+-    void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
++    PangoLayout* GetLayout (const PRUnichar* aText,
++                            PRUint32         aLength);
++    PangoLayout* GetLayout (const gchar*     aText,
++                            PRInt32          aLength);
+ };
+ class nsFontEnumeratorPango : public nsIFontEnumerator
diff --git a/mozilla-firefox-pango-printing.patch b/mozilla-firefox-pango-printing.patch
new file mode 100644 (file)
index 0000000..0490892
--- /dev/null
@@ -0,0 +1,4586 @@
+Patch for Firefox 1.5.0.7 to add support for printing via Pango.
+This also implements printing MathML via Pango, and prints bitmap
+fonts too.
+
+Authors:
+       Behdad Esfahbod
+       Chris Blizzard
+       Akira TAGOH
+
+Index: gfx/src/freetype/nsFreeType.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.cpp,v
+retrieving revision 1.28
+diff -u -p -d -r1.28 nsFreeType.cpp
+--- gfx/src/freetype/nsFreeType.cpp    13 Jul 2005 18:21:10 -0000      1.28
++++ gfx/src/freetype/nsFreeType.cpp    23 Oct 2006 17:37:09 -0000
+@@ -123,6 +123,8 @@ FtFuncList nsFreeType2::FtFuncs [] = {
+ // #endif
+   {"FT_Get_First_Char",       NS_FT2_OFFSET(nsFT_Get_First_Char),       PR_FALSE},
+   {"FT_Get_Next_Char",        NS_FT2_OFFSET(nsFT_Get_Next_Char),        PR_FALSE},
++  {"FT_Has_PS_Glyph_Names",   NS_FT2_OFFSET(nsFT_Has_PS_Glyph_Names),   PR_FALSE},
++  {"FT_Get_Glyph_Name",       NS_FT2_OFFSET(nsFT_Get_Glyph_Name),       PR_TRUE},
+   {nsnull,                    0, 0}
+ };
+@@ -388,6 +390,22 @@ nsFreeType2::GetNextChar(FT_Face face, F
+ } 
+ NS_IMETHODIMP
++nsFreeType2::HasPSGlyphNames(FT_Face face, FT_Int *result)
++{
++  // call the FreeType2 function via the function pointer
++  *result = nsFT_Has_PS_Glyph_Names(face);
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFreeType2::GetGlyphName(FT_Face face, FT_UInt glyph_index, FT_Pointer buffer, FT_UInt buffer_max)
++{
++  // call the FreeType2 function via the function pointer
++  FT_Error error = nsFT_Get_Glyph_Name(face, glyph_index, buffer, buffer_max);
++  return error ? NS_ERROR_FAILURE : NS_OK;
++}
++
++NS_IMETHODIMP
+ nsFreeType2::SupportsExtFunc(PRBool *res)
+ { 
+   *res = gHasExtFunc;
+Index: gfx/src/freetype/nsFreeType.h
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/freetype/nsFreeType.h,v
+retrieving revision 1.18
+diff -u -p -d -r1.18 nsFreeType.h
+--- gfx/src/freetype/nsFreeType.h      1 May 2005 17:36:19 -0000       1.18
++++ gfx/src/freetype/nsFreeType.h      23 Oct 2006 17:37:09 -0000
+@@ -52,6 +52,7 @@
+ #include FT_CACHE_H
+ #include FT_CACHE_IMAGE_H
+ #include FT_TRUETYPE_TABLES_H
++#include FT_TYPE1_TABLES_H
+ #include "nsIFreeType2.h"
+ typedef struct FT_FaceRec_*  FT_Face;
+@@ -138,6 +139,8 @@ typedef FT_Error (*FT_Glyph_To_Bitmap_t)
+ typedef FT_ULong (*FT_Get_First_Char_t)(FT_Face, FT_UInt*);
+ typedef FT_ULong (*FT_Get_Next_Char_t)(FT_Face, FT_ULong, FT_UInt*);
++typedef FT_Int   (*FT_Has_PS_Glyph_Names_t)(FT_Face);
++typedef FT_Error (*FT_Get_Glyph_Name_t)(FT_Face, FT_UInt, FT_Pointer, FT_UInt);
+ class nsFreeTypeFace;
+@@ -193,11 +196,13 @@ protected:
+ // #endif
+   FT_Get_First_Char_t       nsFT_Get_First_Char;
+   FT_Get_Next_Char_t        nsFT_Get_Next_Char;
++  FT_Has_PS_Glyph_Names_t   nsFT_Has_PS_Glyph_Names;
++  FT_Get_Glyph_Name_t       nsFT_Get_Glyph_Name;
+   // this array needs to be big enough to hold all the function pointers
+   // plus one extra for the null at the end
+ // #ifdef MOZ_SVG
+-  static FtFuncList FtFuncs[24];
++  static FtFuncList FtFuncs[28];
+ // #else
+ //  static FtFuncList FtFuncs[20];
+ // #endif
+Index: gfx/src/ps/Makefile.in
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/Makefile.in,v
+retrieving revision 1.57.8.1
+diff -d -u -p -r1.57.8.1 Makefile.in
+--- gfx/src/ps/Makefile.in     17 Jun 2006 15:16:14 -0000      1.57.8.1
++++ gfx/src/ps/Makefile.in     24 Oct 2006 18:36:45 -0000
+@@ -98,6 +98,15 @@ EXTRA_DSO_LDOPTS = \
+               $(MOZ_UNICHARUTIL_LIBS) \
+               $(NULL)
++ifdef MOZ_ENABLE_PANGO
++CPPSRCS                += \
++               nsFontMetricsPSPango.cpp \
++               mozilla-ps-decoder.cpp
++EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS)
++CXXFLAGS       += $(MOZ_PANGO_CFLAGS)
++CFLAGS         += $(MOZ_PANGO_CFLAGS)
++endif
++
+ ifdef MOZ_ENABLE_XFT
+ EXTRA_DSO_LDOPTS += \
+               $(MOZ_XFT_LIBS) \
+@@ -105,7 +114,7 @@ EXTRA_DSO_LDOPTS += \
+               $(NULL)
+ endif
+-ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT))
++ifneq (,$(MOZ_ENABLE_FREETYPE2)$(MOZ_ENABLE_XFT)$(MOZ_ENABLE_PANGO))
+ CPPSRCS               += \
+               nsType1.cpp \
+               $(NULL)
+Index: gfx/src/ps/mozilla-ps-decoder.cpp
+===================================================================
+RCS file: gfx/src/ps/mozilla-ps-decoder.cpp
+diff -N gfx/src/ps/mozilla-ps-decoder.cpp
+--- /dev/null  1 Jan 1970 00:00:00 -0000
++++ gfx/src/ps/mozilla-ps-decoder.cpp  23 Oct 2006 17:37:10 -0000
+@@ -0,0 +1,376 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is Christopher Blizzard
++ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
++ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#define PANGO_ENABLE_BACKEND
++#define PANGO_ENABLE_ENGINE
++
++#include "mozilla-ps-decoder.h"
++#include <pango/pangofc-fontmap.h>
++#include <pango/pangofc-font.h>
++
++#include "nsString.h"
++#include "nsIPersistentProperties2.h"
++#include "nsNetUtil.h"
++#include "nsReadableUtils.h"
++#include "nsICharsetConverterManager.h"
++#include "nsICharRepresentable.h"
++#include "nsCompressedCharMap.h"
++
++#undef DEBUG_CUSTOM_ENCODER
++
++G_DEFINE_TYPE (MozillaPSDecoder, mozilla_ps_decoder, PANGO_TYPE_FC_DECODER)
++
++MozillaPSDecoder *mozilla_ps_decoder_new      (void);
++
++static FcCharSet  *mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder,
++                                                PangoFcFont    *fcfont);
++static PangoGlyph  mozilla_ps_decoder_get_glyph   (PangoFcDecoder *decoder,
++                                                PangoFcFont    *fcfont,
++                                                guint32         wc);
++
++static PangoFcDecoder *mozilla_find_ps_decoder    (FcPattern *pattern,
++                                                gpointer   user_data);
++
++typedef struct _MozillaPSDecoderPrivate MozillaPSDecoderPrivate;
++
++#define MOZILLA_PS_DECODER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderPrivate))
++
++struct _MozillaPSDecoderPrivate {
++    char *family;
++    char *encoder;
++    char *cmap;
++    gboolean is_wide;
++    FcCharSet *charset;
++    nsCOMPtr<nsIUnicodeEncoder> uEncoder;
++};
++
++static nsICharsetConverterManager *gCharsetManager = NULL;
++
++static NS_DEFINE_CID(kCharsetConverterManagerCID,
++                     NS_ICHARSETCONVERTERMANAGER_CID);
++
++// Hash tables that hold the custom encodings and custom cmaps used in
++// various fonts.
++static GHashTable *encoder_hash = NULL;
++static GHashTable *cmap_hash = NULL;
++static GHashTable *wide_hash = NULL;
++
++void
++mozilla_ps_decoder_init (MozillaPSDecoder *decoder)
++{
++}
++
++void
++mozilla_ps_decoder_class_init (MozillaPSDecoderClass *klass)
++{
++    GObjectClass *object_class = G_OBJECT_CLASS(klass);
++    PangoFcDecoderClass *parent_class = PANGO_FC_DECODER_CLASS (klass);
++
++    /*   object_class->finalize = test_finalize; */
++
++    parent_class->get_charset = mozilla_ps_decoder_get_charset;
++    parent_class->get_glyph = mozilla_ps_decoder_get_glyph;
++
++    g_type_class_add_private (object_class, sizeof (MozillaPSDecoderPrivate));
++}
++
++MozillaPSDecoder *
++mozilla_ps_decoder_new(void)
++{
++    return (MozillaPSDecoder *)g_object_new(MOZILLA_TYPE_DECODER, NULL);
++}
++
++#ifdef DEBUG_CUSTOM_ENCODER
++void
++dump_hash(char *key, char *val, void *arg)
++{
++    printf("%s -> %s\n", key, val);
++}
++#endif
++
++/**
++ * mozilla_ps_decoders_init:
++ *
++ * #mozilla_ps_decoders_init:
++ *
++ * This initializes all of the application-specific custom decoders
++ * that Mozilla uses.  This should only be called once during the
++ * lifetime of the application.
++ *
++ * Return value: zero on success, not zero on failure.
++ *
++ **/
++
++int
++mozilla_ps_decoders_init(PangoFontMap *fontmap)
++{
++    static PRBool initialized = PR_FALSE;
++    if (initialized)
++        return 0;
++
++    if (!PANGO_IS_FC_FONT_MAP (fontmap))
++        return -1;
++
++    encoder_hash = g_hash_table_new(g_str_hash, g_str_equal);
++    cmap_hash = g_hash_table_new(g_str_hash, g_str_equal);
++    wide_hash = g_hash_table_new(g_str_hash, g_str_equal);
++
++    PRBool dumb = PR_FALSE;
++    nsCOMPtr<nsIPersistentProperties> props;
++    nsCOMPtr<nsISimpleEnumerator> encodeEnum;
++
++    NS_LoadPersistentPropertiesFromURISpec(getter_AddRefs(props),
++        NS_LITERAL_CSTRING("resource://gre/res/fonts/pangoFontEncoding.properties"));
++
++    if (!props)
++        goto loser;
++
++    // Enumerate the properties in this file and figure out all of the
++    // fonts for which we have custom encodings.
++    props->Enumerate(getter_AddRefs(encodeEnum));
++    if (!encodeEnum)
++        goto loser;
++
++    while (encodeEnum->HasMoreElements(&dumb), dumb) {
++        nsCOMPtr<nsIPropertyElement> prop;
++        encodeEnum->GetNext(getter_AddRefs(prop));
++        if (!prop)
++            goto loser;
++
++        nsCAutoString name;
++        prop->GetKey(name);
++        nsAutoString value;
++        prop->GetValue(value);
++
++        if (!StringBeginsWith(name, NS_LITERAL_CSTRING("encoding."))) {
++            printf("string doesn't begin with encoding?\n");
++            continue;
++        }
++
++        name = Substring(name, 9);
++
++        if (StringEndsWith(name, NS_LITERAL_CSTRING(".ttf"))) {
++            name = Substring(name, 0, name.Length() - 4);
++
++            // Strip off a .wide if it's there.
++            if (StringEndsWith(value, NS_LITERAL_STRING(".wide"))) {
++                g_hash_table_insert(wide_hash, g_strdup(name.get()),
++                                    g_strdup("wide"));
++                value = Substring(value, 0, name.Length() - 5);
++            }
++
++            g_hash_table_insert(encoder_hash,
++                                g_strdup(name.get()),
++                                g_strdup(NS_ConvertUTF16toUTF8(value).get()));
++        }
++        else if (StringEndsWith(name, NS_LITERAL_CSTRING(".ftcmap"))) {
++            name = Substring(name, 0, name.Length() - 7);
++            g_hash_table_insert(cmap_hash,
++                                g_strdup(name.get()),
++                                g_strdup(NS_ConvertUTF16toUTF8(value).get()));
++        }
++        else {
++            printf("unknown suffix used for mapping\n");
++        }
++    }
++
++    pango_fc_font_map_add_decoder_find_func(PANGO_FC_FONT_MAP(fontmap),
++                                            mozilla_find_ps_decoder,
++                                            NULL,
++                                            NULL);
++
++    initialized = PR_TRUE;
++
++#ifdef DEBUG_CUSTOM_ENCODER
++    printf("*** encoders\n");
++    g_hash_table_foreach(encoder_hash, (GHFunc)dump_hash, NULL);
++
++    printf("*** cmaps\n");
++    g_hash_table_foreach(cmap_hash, (GHFunc)dump_hash, NULL);
++#endif
++
++    return 0;
++
++ loser:
++    return -1;
++}
++
++static FcCharSet *
++mozilla_ps_decoder_get_charset (PangoFcDecoder *decoder,
++                             PangoFcFont    *fcfont)
++{
++    MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
++
++    if (priv->charset)
++        return priv->charset;
++
++    // First time this has been accessed.  Populate the charset.
++    priv->charset = FcCharSetCreate();
++
++    if (!gCharsetManager) {
++        CallGetService(kCharsetConverterManagerCID, &gCharsetManager);
++    }
++
++    nsCOMPtr<nsIUnicodeEncoder> encoder;
++    nsCOMPtr<nsICharRepresentable> represent;
++
++    if (!gCharsetManager)
++        goto end;
++
++    gCharsetManager->GetUnicodeEncoderRaw(priv->encoder, getter_AddRefs(encoder));
++    if (!encoder)
++        goto end;
++    
++    encoder->SetOutputErrorBehavior(encoder->kOnError_Replace, nsnull, '?');
++
++    priv->uEncoder = encoder;
++
++    represent = do_QueryInterface(encoder);
++    if (!represent)
++        goto end;
++
++    PRUint32 map[UCS2_MAP_LEN];
++    memset(map, 0, sizeof(map));
++
++    represent->FillInfo(map);
++
++    for (int i = 0; i < NUM_UNICODE_CHARS; i++) {
++        if (IS_REPRESENTABLE(map, i))
++            FcCharSetAddChar(priv->charset, i);
++    }
++
++ end:
++    return priv->charset;
++}
++
++static PangoGlyph
++mozilla_ps_decoder_get_glyph   (PangoFcDecoder *decoder,
++                             PangoFcFont    *fcfont,
++                             guint32         wc)
++{
++    MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
++
++    PangoGlyph retval = 0;
++    PRUnichar inchar = wc;
++    PRInt32 inlen = 1;
++    char outchar[2] = {0,0};
++    PRInt32 outlen = 2;
++
++    priv->uEncoder->Convert(&inchar, &inlen, outchar, &outlen);
++    if (outlen != 1) {
++        printf("Warning: mozilla_ps_decoder_get_glyph doesn't support more than one character conversions.\n");
++        return 0;
++    }
++
++    FT_Face face = pango_fc_font_lock_face(fcfont);
++
++#ifdef DEBUG_CUSTOM_ENCODER
++    char *filename;
++    FcPatternGetString(fcfont->font_pattern, FC_FILE, 0, (FcChar8 **)&filename);
++    printf("filename is %s\n", filename);
++#endif
++
++    // Make sure to set the right charmap before trying to get the
++    // glyph
++    if (priv->cmap) {
++        if (!strcmp(priv->cmap, "mac_roman")) {
++            FT_Select_Charmap(face, ft_encoding_apple_roman);
++        }
++        else if (!strcmp(priv->cmap, "unicode")) {
++            FT_Select_Charmap(face, ft_encoding_unicode);
++        }
++        else {
++            printf("Warning: Invalid charmap entry for family %s\n",
++                   priv->family);
++        }
++    }
++
++    // Standard 8 bit to glyph translation
++    if (!priv->is_wide) {
++        FcChar32 blah = PRUint8(outchar[0]);
++        retval = FT_Get_Char_Index(face, blah);
++#ifdef DEBUG_CUSTOM_ENCODER
++        printf("wc 0x%x outchar[0] 0x%x index 0x%x retval 0x%x face %p\n",
++               wc, outchar[0], blah, retval, (void *)face);
++#endif
++    }
++    else {
++        printf("Warning: We don't support .wide fonts!\n");
++        retval = 0;
++    }
++
++    pango_fc_font_unlock_face(fcfont);
++
++    return retval;
++}
++
++static PangoFcDecoder *
++mozilla_find_ps_decoder (FcPattern *pattern, gpointer user_data)
++{
++    // Compare the family name of the font that's been opened to see
++    // if we have a custom decoder.
++    const char *orig = NULL;
++    FcPatternGetString(pattern, FC_FAMILY, 0, (FcChar8 **)&orig);
++
++    nsCAutoString family;
++    family.Assign(orig);
++
++    family.StripWhitespace();
++    ToLowerCase(family);
++
++    char *encoder = (char *)g_hash_table_lookup(encoder_hash, family.get());
++    if (!encoder)
++        return NULL;
++
++    MozillaPSDecoder *decoder = mozilla_ps_decoder_new();
++
++    MozillaPSDecoderPrivate *priv = MOZILLA_PS_DECODER_GET_PRIVATE(decoder);
++
++    priv->family = g_strdup(family.get());
++    priv->encoder = g_strdup(encoder);
++
++    char *cmap = (char *)g_hash_table_lookup(cmap_hash, family.get());
++    if (cmap)
++        priv->cmap = g_strdup(cmap);
++
++    char *wide = (char *)g_hash_table_lookup(wide_hash, family.get());
++    if (wide)
++        priv->is_wide = TRUE;
++
++    return PANGO_FC_DECODER(decoder);
++}
+Index: gfx/src/ps/mozilla-ps-decoder.h
+===================================================================
+RCS file: gfx/src/ps/mozilla-ps-decoder.h
+diff -N gfx/src/ps/mozilla-ps-decoder.h
+--- /dev/null  1 Jan 1970 00:00:00 -0000
++++ gfx/src/ps/mozilla-ps-decoder.h    23 Oct 2006 17:37:10 -0000
+@@ -0,0 +1,72 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is Christopher Blizzard
++ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
++ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef _MOZILLA_PS_DECODER_H
++#define _MOZILLA_PS_DECODER_H
++
++#include <pango/pangofc-decoder.h>
++
++G_BEGIN_DECLS
++
++#define MOZILLA_TYPE_DECODER (mozilla_ps_decoder_get_type())
++#define MOZILLA_PS_DECODER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), MOZILLA_TYPE_DECODER, MozillaPSDecoder))
++#define MOZILLA_IS_DECODER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), MOZILLA_TYPE_DECODER))
++
++typedef struct _MozillaPSDecoder      MozillaPSDecoder;
++typedef struct _MozillaPSDecoderClass MozillaPSDecoderClass;
++
++#define MOZILLA_PS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass))
++#define MOZILLA_IS_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MOZILLA_TYPE_DECODER))
++#define MOZILLA_PS_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MOZILLA_TYPE_DECODER, MozillaPSDecoderClass))
++
++struct _MozillaPSDecoder
++{
++  PangoFcDecoder parent_instance;
++};
++
++struct _MozillaPSDecoderClass
++{
++  PangoFcDecoderClass parent_class;
++};
++
++GType           mozilla_ps_decoder_get_type (void);
++int             mozilla_ps_decoders_init    (PangoFontMap *fontmap);
++
++G_END_DECLS
++
++#endif /*_MOZILLA_PS_DECODER_H */
+Index: gfx/src/ps/nsDeviceContextPS.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsDeviceContextPS.cpp,v
+retrieving revision 1.73
+diff -u -p -d -r1.73 nsDeviceContextPS.cpp
+--- gfx/src/ps/nsDeviceContextPS.cpp   21 May 2005 15:33:08 -0000      1.73
++++ gfx/src/ps/nsDeviceContextPS.cpp   23 Oct 2006 17:37:10 -0000
+@@ -58,12 +58,15 @@
+ #include "nsIPref.h"
+ #include "nsString.h"
+ #include "nsFontMetricsPS.h"
++#ifdef MOZ_ENABLE_PANGO
++#include "nsFontMetricsPSPango.h"
++#endif
+ #include "nsPostScriptObj.h"
+ #include "nspr.h"
+ #include "nsILanguageAtomService.h"
+ #include "nsPrintJobPS.h"
+ #include "nsPrintJobFactoryPS.h"
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+ #include "nsType1.h"
+ #endif
+@@ -223,7 +226,7 @@ nsDeviceContextPS::InitDeviceContextPS(n
+  
+   nsresult rv;
+   nsCOMPtr<nsIPref> pref(do_GetService(NS_PREF_CONTRACTID, &rv));
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+   if (NS_SUCCEEDED(rv)) {
+       rv = pref->GetBoolPref("font.FreeType2.printing", &mFTPEnable);
+       if (NS_FAILED(rv))
+@@ -469,7 +472,7 @@ NS_IMETHODIMP nsDeviceContextPS::EndDocu
+       NS_ASSERTION(submitFP, "No print job submission handle");
+       // Start writing the print job to the job handler
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+       mPSObj->write_prolog(submitFP, mFTPEnable);
+ #else 
+       mPSObj->write_prolog(submitFP);
+@@ -550,15 +553,52 @@ public:
+   virtual nsresult CreateFontMetricsInstance(nsIFontMetrics** aResult);
+ };
++#if defined(MOZ_ENABLE_PANGO)
++PRBool
++NS_IsPangoEnabled(void)
++{
++    static PRBool beenHere;
++    static PRBool pangoEnabled;
++
++    if (!beenHere) {
++        beenHere = PR_TRUE;
++
++        char *val = PR_GetEnv("MOZ_DISABLE_PANGO");
++        pangoEnabled = !(val);
++
++        if (pangoEnabled) {
++            nsCOMPtr<nsIPref> prefService = do_GetService(NS_PREF_CONTRACTID);
++            if (prefService)
++                prefService->SetDefaultCharPref("general.useragent.extra.pango",
++                                                "pango-text");
++        }
++    }
++
++    return pangoEnabled;
++}
++#endif
+ nsresult nsFontCachePS::CreateFontMetricsInstance(nsIFontMetrics** aResult)
+ {
+   NS_PRECONDITION(aResult, "null out param");
+-  nsIFontMetrics *fm = new nsFontMetricsPS();
+-  if (!fm)
+-    return NS_ERROR_OUT_OF_MEMORY;
+-  NS_ADDREF(fm);
+-  *aResult = fm;
++#ifdef MOZ_ENABLE_PANGO
++  if (NS_IsPangoEnabled())
++  {
++    nsIFontMetrics *fm = new nsFontMetricsPSPango();
++    if (!fm)
++      return NS_ERROR_OUT_OF_MEMORY;
++    NS_ADDREF(fm);
++    *aResult = fm;
++  }
++  else
++#endif
++  {
++    nsIFontMetrics *fm = new nsFontMetricsPS();
++    if (!fm)
++      return NS_ERROR_OUT_OF_MEMORY;
++    NS_ADDREF(fm);
++    *aResult = fm;
++  }
+   return NS_OK;
+ }
+Index: gfx/src/ps/nsFontMetricsPS.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.cpp,v
+retrieving revision 1.57.16.2
+diff -u -p -d -r1.57.16.2 nsFontMetricsPS.cpp
+--- gfx/src/ps/nsFontMetricsPS.cpp     7 May 2006 02:01:25 -0000       1.57.16.2
++++ gfx/src/ps/nsFontMetricsPS.cpp     23 Oct 2006 17:37:11 -0000
+@@ -461,6 +461,239 @@ nsFontMetricsPS :: GetStringWidth(const 
+   return NS_OK;
+ }
++nsresult
++nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               const nscoord* aSpacing,
++                               nsRenderingContextPS *aContext)
++{
++  nsPostScriptObj* psObj = aContext->GetPostScriptObj();
++  // When FT2 printing is enabled, we don't need to set langgroup
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++  if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) {
++#endif
++    nsCOMPtr<nsIAtom> langGroup;
++    GetLangGroup(getter_AddRefs(langGroup));
++    psObj->setlanggroup(langGroup);
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++  }
++#endif
++
++  if (aLength == 0)
++    return NS_OK;
++  nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
++  NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
++  fontPS->SetupFont(aContext);
++
++  PRUint32 i, start = 0;
++  for (i=0; i<aLength; i++) {
++    nsFontPS* fontThisChar;
++    fontThisChar = nsFontPS::FindFont(aString[i], Font(), this);
++    NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
++    if (fontThisChar != fontPS) {
++      // draw text up to this point
++      aX += DrawString(aString+start, i-start, aX, aY, fontPS, 
++                       aSpacing?aSpacing+start:nsnull, aContext);
++      start = i;
++
++      // setup for following text
++      fontPS = fontThisChar;
++      fontPS->SetupFont(aContext);
++    }
++  }
++
++  // draw the last part
++  if (aLength-start)
++    DrawString(aString+start, aLength-start, aX, aY, fontPS, 
++               aSpacing?aSpacing+start:nsnull, aContext);
++
++  return NS_OK;
++}
++
++nsresult
++nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               PRInt32 aFontID,
++                               const nscoord* aSpacing,
++                               nsRenderingContextPS *aContext)
++{
++  nsPostScriptObj* psObj = aContext->GetPostScriptObj();
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++  // When FT2 printing is enabled, we don't need to set langgroup
++  if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, GetDeviceContext())->mFTPEnable) {
++#endif
++    nsCOMPtr<nsIAtom> langGroup = nsnull;
++    GetLangGroup(getter_AddRefs(langGroup));
++    psObj->setlanggroup(langGroup);
++#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
++  }
++#endif
++
++  /* build up conversion table */
++  psObj->preshow(aString, aLength);
++
++  if (aLength == 0)
++    return NS_OK;
++  nsFontPS* fontPS = nsFontPS::FindFont(aString[0], Font(), this);
++  NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
++  fontPS->SetupFont(aContext);
++
++  PRUint32 i, start = 0;
++  for (i=0; i<aLength; i++) {
++    nsFontPS* fontThisChar;
++    fontThisChar = nsFontPS::FindFont(aString[i], Font(), this);
++    NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
++    if (fontThisChar != fontPS) {
++      // draw text up to this point
++      aX += DrawString(aString+start, i-start, aX, aY, fontPS, 
++                       aSpacing?aSpacing+start:nsnull, aContext);
++      start = i;
++
++      // setup for following text
++      fontPS = fontThisChar;
++      fontPS->SetupFont(aContext);
++    }
++  }
++
++  // draw the last part
++  if (aLength-start)
++    DrawString(aString+start, aLength-start, aX, aY, fontPS, 
++               aSpacing?aSpacing+start:nsnull, aContext);
++
++  return NS_OK;
++}
++
++PRInt32
++nsFontMetricsPS::DrawString(const char *aString, PRUint32 aLength,
++                        nscoord aX, nscoord aY, nsFontPS* aFontPS,
++                        const nscoord* aSpacing,
++                      nsRenderingContextPS *aContext)
++{
++  nscoord width = 0;
++  PRInt32 x = aX;
++  PRInt32 y = aY;
++
++  PRInt32 dxMem[500];
++  PRInt32* dx0 = 0;
++  if (aSpacing) {
++    dx0 = dxMem;
++    if (aLength > 500) {
++      dx0 = new PRInt32[aLength];
++      NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
++    }
++    aContext->GetTranMatrix()->ScaleXCoords(aSpacing, aLength, dx0);
++  }
++
++  aContext->GetTranMatrix()->TransformCoord(&x, &y);
++  width = aFontPS->DrawString(aContext, x, y, aString, aLength);
++
++  if ((aSpacing) && (dx0 != dxMem)) {
++    delete [] dx0;
++  }
++
++  return width;
++}
++
++
++PRInt32
++nsFontMetricsPS::DrawString(const PRUnichar* aString, PRUint32 aLength,
++                                 nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
++                                 const nscoord* aSpacing,
++                               nsRenderingContextPS *aContext)
++{
++  nscoord width = 0;
++  PRInt32 x = aX;
++  PRInt32 y = aY;
++
++  if (aSpacing) {
++    // Slow, but accurate rendering
++    const PRUnichar* end = aString + aLength;
++    while (aString < end){
++      x = aX;
++      y = aY;
++      aContext->GetTranMatrix()->TransformCoord(&x, &y);
++      aFontPS->DrawString(aContext, x, y, aString, 1);
++      aX += *aSpacing++;
++      aString++;
++    }
++    width = aX;
++  } else {
++    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++    width = aFontPS->DrawString(aContext, x, y, aString, aLength);
++  }
++
++  return width;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPS::GetTextDimensions(const char*       aString,
++                                        PRInt32           aLength,
++                                        PRInt32           aAvailWidth,
++                                        PRInt32*          aBreaks,
++                                        PRInt32           aNumBreaks,
++                                        nsTextDimensions& aDimensions,
++                                        PRInt32&          aNumCharsFit,
++                                        nsTextDimensions& aLastWordDimensions,
++                                        PRInt32*          aFontID)
++{
++  NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
++  return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPS::GetTextDimensions(const PRUnichar*  aString,
++                                        PRInt32           aLength,
++                                        PRInt32           aAvailWidth,
++                                        PRInt32*          aBreaks,
++                                        PRInt32           aNumBreaks,
++                                        nsTextDimensions& aDimensions,
++                                        PRInt32&          aNumCharsFit,
++                                        nsTextDimensions& aLastWordDimensions,
++                                        PRInt32*          aFontID)
++{
++  NS_NOTYETIMPLEMENTED("nsFontMetricsPS::GetTextDimensions");
++  return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
++                                          nsTextDimensions& aDimensions)
++{
++  GetStringWidth(aString, aDimensions.width, aLength);
++  GetMaxAscent(aDimensions.ascent);
++  GetMaxDescent(aDimensions.descent);
++  return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
++                                          nsTextDimensions& aDimensions, PRInt32* aFontID)
++{
++  GetStringWidth(aString, aDimensions.width, aLength);
++  //XXX temporary - bug 96609
++  GetMaxAscent(aDimensions.ascent);
++  GetMaxDescent(aDimensions.descent);
++  return NS_OK;
++}
++
++nsresult
++nsFontMetricsPS::GetBoundingMetrics(const char*        aString,
++                                     PRUint32           aLength,
++                                     nsBoundingMetrics& aBoundingMetrics)
++{
++  return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++nsresult
++nsFontMetricsPS::GetBoundingMetrics(const PRUnichar*   aString,
++                                     PRUint32           aLength,
++                                     nsBoundingMetrics &aBoundingMetrics,
++                                     PRInt32 *aFontID)
++{
++  return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++
+ nsFontPS*
+ nsFontPS::FindFont(char aChar, const nsFont& aFont, 
+                    nsFontMetricsPS* aFontMetrics)
+@@ -1128,23 +1361,38 @@ nsFontPSXft::DrawString(nsRenderingConte
+   PRUint32 start = 0;
+   PRUint32 i;
++  FT_Face face = getFTFace();
++  if (!face) {
++    NS_WARNING("Failed to get FT Face in nsFontPSXft::DrawString\n");
++    return 0;
++  }
++
++  nsValueArray glyphs(PR_UINT16_MAX);
++
+   // XXX : ignore surrogate pairs for now
+-  nsString *subSet = mPSFontGenerator->GetSubset();
+   for (i = 0; i < aLength; ++i) {
+-    currSubFont = mPSFontGenerator->AddToSubset(aString[i]);
++    PRUint32 glyph = FT_Get_Char_Index(face, aString[i]);
++    currSubFont = mPSFontGenerator->AddToGlyphSubset(glyph);
++
++    // Check if we need to render the current string
+     if (prevSubFont != currSubFont) {
+-      if (prevSubFont != -1)
+-        psObj->show(&aString[start], i - start, *subSet, prevSubFont);
++      if (prevSubFont != -1) {
++        psObj->show(&glyphs, mPSFontGenerator, prevSubFont);
++      }
+       NS_ASSERTION(!mFontNameBase.IsEmpty(),
+                   "font base name shouldn't be empty");
+       psObj->setfont(mFontNameBase, mHeight, currSubFont);
+       prevSubFont = currSubFont;
+       start = i;
++      glyphs.Clear();
+     }
++
++    glyphs.AppendValue(glyph);
+   }
+-  if (prevSubFont != -1)
+-    psObj->show(&aString[start], i - start, *subSet, prevSubFont); 
++  if (prevSubFont != -1) {
++    psObj->show(&glyphs, mPSFontGenerator, prevSubFont);
++  }
+   
+   return GetWidth(aString, aLength);
+ }
+@@ -2278,10 +2526,13 @@ nsFontPSFreeType::GetBoundingMetrics(con
+ // Implementation of nsPSFontGenerator
+ nsPSFontGenerator::nsPSFontGenerator()
+ {
++  mGlyphSubset = new nsValueArray(PR_UINT16_MAX, 40);
+ }
+ nsPSFontGenerator::~nsPSFontGenerator()
+ {
++  if (mGlyphSubset)
++    delete mGlyphSubset;
+ }
+ void nsPSFontGenerator::GeneratePSFont(FILE* aFile)
+@@ -2289,24 +2540,29 @@ void nsPSFontGenerator::GeneratePSFont(F
+   NS_ERROR("should never call nsPSFontGenerator::GeneratePSFont");
+ }
+-// Add a Unicode character to mSubset which will be divided into 
+-// multiple chunks (subfonts) of 255 (kSubFontSize) characters each. 
+-// Each chunk will be converted to a Type 1 font. Return the index of 
+-// a subfont (chunk) this character belongs to.
++// Add a glyph offset to mSubset which will be divided into multiple
++// chunks (subfonts) of 255 (kSubFontSize) glyphs each.  Each chunk
++// will then be converted into a Type 1 font.  Return the index of a
++// subfont (chunk) this glyph belongs to.
+ PRInt32
+-nsPSFontGenerator::AddToSubset(PRUnichar aChar)
++nsPSFontGenerator::AddToGlyphSubset(PRUint32 aGlyph)
+ {
+-  PRInt32 index = mSubset.FindChar(aChar);
+-  if (index == kNotFound) {
+-    mSubset.Append(aChar);
+-    index = mSubset.Length() - 1;
++  nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph);
++  if (index == NSVALUEARRAY_INVALID) {
++    mGlyphSubset->AppendValue(aGlyph);
++    index = mGlyphSubset->Count() - 1;
+   }
++
+   return index / kSubFontSize;
+ }
+-nsString *nsPSFontGenerator::GetSubset()
++PRInt32
++nsPSFontGenerator::InSubsetIndexOf(PRUint32 aGlyph)
+ {
+-  return &mSubset;
++  nsValueArrayIndex index = mGlyphSubset->IndexOf(aGlyph);
++  if (index == NSVALUEARRAY_INVALID)
++    return 0;
++  return (index % kSubFontSize) + 1;
+ }
+ #ifdef MOZ_ENABLE_XFT
+@@ -2353,8 +2609,8 @@ void nsXftType1Generator::GeneratePSFont
+   }
+   int wmode = 0;
+-  if (!mSubset.IsEmpty())
+-    FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
++  if (mGlyphSubset->Count())
++    FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
+ }
+ #else
+@@ -2402,8 +2658,8 @@ void nsFT2Type1Generator::GeneratePSFont
+     return;
+  
+   int wmode = 0;
+-  if (!mSubset.IsEmpty())
+-    FT2SubsetToType1FontSet(face, mSubset, wmode, aFile);
++  if (mGlyphSubset->Count())
++    FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
+ }
+ #endif //MOZ_ENABLE_FREETYPE2
+Index: gfx/src/ps/nsFontMetricsPS.h
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsFontMetricsPS.h,v
+retrieving revision 1.31
+diff -u -p -d -r1.31 nsFontMetricsPS.h
+--- gfx/src/ps/nsFontMetricsPS.h       28 Jun 2005 18:29:10 -0000      1.31
++++ gfx/src/ps/nsFontMetricsPS.h       23 Oct 2006 17:37:11 -0000
+@@ -66,6 +66,7 @@
+ #endif
+ #include "nsVoidArray.h"
+ #include "nsHashtable.h"
++#include "nsValueArray.h"
+ class nsPSFontGenerator;
+ class nsDeviceContextPS;
+@@ -108,6 +109,65 @@ public:
+   NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle);
+   NS_IMETHOD  GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
+   NS_IMETHOD  GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
++
++    NS_IMETHOD       GetTextDimensions(const char* aString,
++                                       PRUint32 aLength,
++                                       nsTextDimensions& aDimensions);
++    NS_IMETHOD       GetTextDimensions(const PRUnichar* aString,
++                                       PRUint32 aLength,
++                                       nsTextDimensions& aDimensions, 
++                                       PRInt32* aFontID);
++    NS_IMETHOD       GetTextDimensions(const char*         aString,
++                                       PRInt32             aLength,
++                                       PRInt32             aAvailWidth,
++                                       PRInt32*            aBreaks,
++                                       PRInt32             aNumBreaks,
++                                       nsTextDimensions&   aDimensions,
++                                       PRInt32&            aNumCharsFit,
++                                       nsTextDimensions&   aLastWordDimensions,
++                                       PRInt32*            aFontID);
++    NS_IMETHOD       GetTextDimensions(const PRUnichar*    aString,
++                                       PRInt32             aLength,
++                                       PRInt32             aAvailWidth,
++                                       PRInt32*            aBreaks,
++                                       PRInt32             aNumBreaks,
++                                       nsTextDimensions&   aDimensions,
++                                       PRInt32&            aNumCharsFit,
++                                       nsTextDimensions&   aLastWordDimensions,
++                                       PRInt32*            aFontID);
++#ifdef MOZ_MATHML
++    NS_IMETHOD       GetBoundingMetrics(const char *aString, PRUint32 aLength,
++                                        nsBoundingMetrics &aBoundingMetrics);
++    NS_IMETHOD       GetBoundingMetrics(const PRUnichar *aString,
++                                        PRUint32 aLength,
++                                        nsBoundingMetrics &aBoundingMetrics,
++                                        PRInt32 *aFontID);
++#endif /* MOZ_MATHML */
++
++  NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
++                        nscoord aX, nscoord aY,
++                        const nscoord* aSpacing,
++                      nsRenderingContextPS *aContext);
++  NS_IMETHOD DrawString(const PRUnichar *aString, PRUint32 aLength,
++                        nscoord aX, nscoord aY,
++                        PRInt32 aFontID,
++                        const nscoord* aSpacing,
++                      nsRenderingContextPS *aContext);
++
++protected:
++  PRInt32 DrawString(const char *aString, PRUint32 aLength,
++                        nscoord aX, nscoord aY, nsFontPS* aFontPS,
++                        const nscoord* aSpacing,
++                      nsRenderingContextPS *aContext);
++  PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength,
++                        nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
++                        const nscoord* aSpacing,
++                      nsRenderingContextPS *aContext);
++
++public:
++
++  virtual PRUint32    GetHints     (void) { return 0; }
++
+   
+   inline void SetXHeight(nscoord aXHeight) { mXHeight = aXHeight; };
+   inline void SetSuperscriptOffset(nscoord aSuperscriptOffset) { mSuperscriptOffset = aSuperscriptOffset; };
+@@ -455,16 +515,14 @@ public:
+   nsPSFontGenerator();
+   virtual ~nsPSFontGenerator();
+   virtual void  GeneratePSFont(FILE* aFile);
+-  PRInt32  AddToSubset(PRUnichar aChar);
+-  nsString *GetSubset();
++  PRInt32  AddToGlyphSubset(PRUint32 aGlyph);
++  PRInt32  InSubsetIndexOf(PRUint32 aGlyph);
+   // 256 (PS type 1 encoding vector size) - 1 (1 is for mandatory /.notdef)
+   const static PRUint16 kSubFontSize; 
+ protected:
+-  // XXX To support non-BMP characters, we may have to use 
+-  // nsValueArray with PRUint32
+-  nsString mSubset;
++  nsValueArray *mGlyphSubset;
+ };
+Index: gfx/src/ps/nsFontMetricsPSPango.cpp
+===================================================================
+RCS file: gfx/src/ps/nsFontMetricsPSPango.cpp
+diff -N gfx/src/ps/nsFontMetricsPSPango.cpp
+--- /dev/null  1 Jan 1970 00:00:00 -0000
++++ gfx/src/ps/nsFontMetricsPSPango.cpp        23 Oct 2006 17:37:13 -0000
+@@ -0,0 +1,2107 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is Christopher Blizzard
++ * <blizzard@mozilla.org>.  Portions created by the Initial Developer
++ * are Copyright (C) 2004 the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *   Christopher Blizzard <blizzard@mozilla.org>
++ *   Behdad Esfahbod <behdad@behdad.org>
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#include <strings.h>
++#include "nsFont.h"
++#include "nsIDeviceContext.h"
++#include "nsICharsetConverterManager.h"
++#include "nsIPref.h"
++#include "nsServiceManagerUtils.h"
++
++#define PANGO_ENABLE_BACKEND
++#define PANGO_ENABLE_ENGINE
++
++#include "nsFontMetricsPSPango.h"
++#include "nsRenderingContextPS.h"
++#include "nsDeviceContextPS.h"
++#include "nsFontConfigUtils.h"
++
++#include "nsPrintfCString.h"
++#include "nsUnicharUtils.h"
++#include "nsQuickSort.h"
++#include "nsFontConfigUtils.h"
++
++#include <fontconfig/fontconfig.h>
++#include <pango/pangoft2.h>
++#include <freetype/tttables.h>
++#include "nsType1.h"
++
++#include "mozilla-ps-decoder.h"
++
++#define FORCE_PR_LOG
++#include "prlog.h"
++
++// Globals
++
++static PRLogModuleInfo            *gPangoFontLog;
++static int                         gNumInstances;
++
++
++static void
++default_substitute (FcPattern *pattern,
++                    gpointer   data)
++{
++  FcPatternDel (pattern, FC_HINTING);
++  FcPatternAddBool (pattern, FC_HINTING, 0);
++}
++
++static PangoFontMap *
++get_fontmap (void)
++{
++  static PangoFontMap               *fontmap = NULL;
++
++  if (!fontmap) {
++    fontmap = pango_ft2_font_map_new ();
++    pango_ft2_font_map_set_resolution ((PangoFT2FontMap *)fontmap, 72., 72.);
++    pango_ft2_font_map_set_default_substitute ((PangoFT2FontMap *)fontmap, default_substitute, NULL, NULL);
++  }
++
++  return fontmap;
++}
++
++static PangoContext *
++get_context (void)
++{
++  return pango_ft2_font_map_create_context ((PangoFT2FontMap *) get_fontmap ());
++}
++
++// Defines
++
++// This is the scaling factor that we keep fonts limited to against
++// the display size.  If a pixel size is requested that is more than
++// this factor larger than the height of the display, it's clamped to
++// that value instead of the requested size.
++#define FONT_MAX_FONT_SCALE 2
++
++static NS_DEFINE_CID(kCharsetConverterManagerCID,
++                     NS_ICHARSETCONVERTERMANAGER_CID);
++
++#ifdef DEBUG
++#define DUMP_PRUNICHAR(ustr, ulen) for (PRUint32 llen=0;llen<ulen;llen++) \
++                                      printf("0x%x ", ustr[llen]); \
++                                   printf("\n");
++#endif
++
++// rounding and truncation functions for a Freetype floating point number 
++// (FT26Dot6) stored in a 32bit integer with high 26 bits for the integer
++// part and low 6 bits for the fractional part. 
++#define MOZ_FT_ROUND(x) (((x) + 32) & ~63) // 63 = 2^6 - 1
++#define MOZ_FT_TRUNC(x) ((x) >> 6)
++#define CONVERT_DESIGN_UNITS_TO_PIXELS(v, s) \
++        MOZ_FT_TRUNC(MOZ_FT_ROUND(FT_MulFix((v) , (s))))
++
++// Static function decls
++
++static PangoLanguage *GetPangoLanguage(nsIAtom *aLangGroup);
++
++static void   FreeGlobals    (void);
++
++static PangoStyle  CalculateStyle  (PRUint8 aStyle);
++static PangoWeight CalculateWeight (PRUint16 aWeight);
++
++static nsresult    EnumFontsPango   (nsIAtom* aLangGroup, const char* aGeneric,
++                                     PRUint32* aCount, PRUnichar*** aResult);
++static int         CompareFontNames (const void* aArg1, const void* aArg2,
++                                     void* aClosure);
++
++nsFontMetricsPSPango::nsFontMetricsPSPango()
++{
++    if (!gPangoFontLog)
++        gPangoFontLog = PR_NewLogModule("PangoFont");
++
++    gNumInstances++;
++
++    mPangoFontDesc = nsnull;
++    mPangoContext = nsnull;
++    mLTRPangoContext = nsnull;
++    mRTLPangoContext = nsnull;
++    mPangoAttrList = nsnull;
++    mIsRTL = PR_FALSE;
++    mPangoSpaceWidth = 0;
++
++    static PRBool initialized = PR_FALSE;
++    if (initialized)
++        return;
++
++    // Initialized the custom decoders
++    if (!mozilla_ps_decoders_init(get_fontmap ()))
++        initialized = PR_TRUE;
++}
++
++nsFontMetricsPSPango::~nsFontMetricsPSPango()
++{
++    if (mDeviceContext)
++        mDeviceContext->FontMetricsDeleted(this);
++
++    if (mPangoFontDesc)
++        pango_font_description_free(mPangoFontDesc);
++
++    if (mLTRPangoContext)
++        g_object_unref(mLTRPangoContext);
++
++    if (mRTLPangoContext)
++        g_object_unref(mRTLPangoContext);
++
++    if (mPangoAttrList)
++        pango_attr_list_unref(mPangoAttrList);
++
++    // XXX clean up all the pango objects
++
++    if (--gNumInstances == 0)
++        FreeGlobals();
++}
++
++
++NS_IMPL_ISUPPORTS1(nsFontMetricsPSPango, nsIFontMetrics)
++
++// nsIFontMetrics impl
++
++NS_IMETHODIMP
++nsFontMetricsPSPango::Init(const nsFont& aFont, nsIAtom* aLangGroup,
++                         nsIDeviceContext *aContext)
++{
++    mFont = aFont;
++    mLangGroup = aLangGroup;
++
++    // Hang on to the device context
++    mDeviceContext = aContext;
++    
++    mPointSize = NSTwipsToFloatPoints(mFont.size);
++
++    // enumerate over the font names passed in
++    mFont.EnumerateFamilies(nsFontMetricsPSPango::EnumFontCallback, this);
++
++    nsCOMPtr<nsIPref> prefService;
++    prefService = do_GetService(NS_PREF_CONTRACTID);
++    if (!prefService)
++        return NS_ERROR_FAILURE;
++        
++    nsXPIDLCString value;
++    const char* langGroup;
++    mLangGroup->GetUTF8String(&langGroup);
++
++    // Set up the default font name if it's not set
++    if (!mGenericFont) {
++        nsCAutoString name("font.default.");
++        name.Append(langGroup);
++        prefService->CopyCharPref(name.get(), getter_Copies(value));
++
++        if (value.get())
++            mDefaultFont = value.get();
++        else
++            mDefaultFont = "serif";
++        
++        mGenericFont = &mDefaultFont;
++    }
++
++    // set up the minimum sizes for fonts
++    if (mLangGroup) {
++        nsCAutoString name("font.min-size.");
++
++        if (mGenericFont->Equals("monospace"))
++            name.Append("fixed");
++        else
++            name.Append("variable");
++
++        name.Append(char('.'));
++        name.Append(langGroup);
++
++        PRInt32 minimumInt = 0;
++        float minimum;
++        nsresult res;
++        res = prefService->GetIntPref(name.get(), &minimumInt);
++        if (NS_FAILED(res))
++            prefService->GetDefaultIntPref(name.get(), &minimumInt);
++
++        if (minimumInt < 0)
++            minimumInt = 0;
++
++        minimum = minimumInt;
++
++        // The minimum size is specified in pixels, not in points.
++        // Convert the size from pixels to points.
++        minimum = NSTwipsToFloatPoints(NSFloatPixelsToTwips(minimum, mDeviceContext->DevUnitsToAppUnits()));
++        if (mPointSize < minimum)
++            mPointSize = minimum;
++    }
++
++    // Make sure that the pixel size is at least greater than zero
++    if (mPointSize < 1) {
++#ifdef DEBUG
++        printf("*** Warning: nsFontMetricsPSPango created with point size %f\n",
++               mPointSize);
++#endif
++        mPointSize = 1;
++    }
++
++    nsresult rv = RealizeFont();
++    if (NS_FAILED(rv))
++        return rv;
++
++    // Cache font metrics for the 'x' character
++    return CacheFontMetrics();
++}
++
++nsresult
++nsFontMetricsPSPango::CacheFontMetrics(void)
++{
++    // Get our scale factor
++    float f;
++    float val;
++    f = mDeviceContext->DevUnitsToAppUnits();
++
++    mPangoAttrList = pango_attr_list_new();
++
++    GList *items = pango_itemize(mPangoContext,
++                                 "a", 0, 1, mPangoAttrList, NULL);
++
++    if (!items)
++        return NS_ERROR_FAILURE;
++
++    guint nitems = g_list_length(items);
++    if (nitems != 1)
++        return NS_ERROR_FAILURE;
++
++    PangoItem *item = (PangoItem *)items->data;
++    PangoFcFont  *fcfont = PANGO_FC_FONT(item->analysis.font);
++    if (!fcfont)
++        return NS_ERROR_FAILURE;
++
++    // Get our font face
++    FT_Face face;
++    face = pango_fc_font_lock_face(fcfont);
++    if (!face)
++      return NS_ERROR_NOT_AVAILABLE;
++      
++    TT_OS2 *os2;
++    os2 = (TT_OS2 *) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
++
++    // mEmHeight (size in pixels of EM height)
++    int size;
++    if (FcPatternGetInteger(fcfont->font_pattern, FC_PIXEL_SIZE, 0, &size) !=
++        FcResultMatch) {
++        size = 12;
++    }
++    mEmHeight = PR_MAX(1, nscoord(size * f));
++
++    // mMaxAscent
++    val = MOZ_FT_TRUNC(face->size->metrics.ascender);
++    mMaxAscent = NSToIntRound(val * f);
++
++    // mMaxDescent
++    val = -MOZ_FT_TRUNC(face->size->metrics.descender);
++    mMaxDescent = NSToIntRound(val * f);
++
++    nscoord lineHeight = mMaxAscent + mMaxDescent;
++
++    // mLeading (needs ascent and descent and EM height) 
++    if (lineHeight > mEmHeight)
++        mLeading = lineHeight - mEmHeight;
++    else
++        mLeading = 0;
++
++    // mMaxHeight (needs ascent and descent)
++    mMaxHeight = lineHeight;
++
++    // mEmAscent (needs maxascent, EM height, ascent and descent)
++    mEmAscent = nscoord(mMaxAscent * mEmHeight / lineHeight);
++
++    // mEmDescent (needs EM height and EM ascent
++    mEmDescent = mEmHeight - mEmAscent;
++
++    // mMaxAdvance
++    val = MOZ_FT_TRUNC(face->size->metrics.max_advance);
++    mMaxAdvance = NSToIntRound(val * f);
++
++    // mPangoSpaceWidth
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++    pango_layout_set_text(layout, " ", 1);
++    int pswidth, psheight;
++    pango_layout_get_size(layout, &pswidth, &psheight);
++    mPangoSpaceWidth = pswidth;
++    g_object_unref(layout);
++
++    // mSpaceWidth (width of a space)
++    nscoord tmpWidth;
++    GetWidth(" ", 1, tmpWidth);
++    mSpaceWidth = tmpWidth;
++
++    // mAveCharWidth (width of an 'average' char)
++    //    XftTextExtents16(GDK_DISPLAY(), xftFont, &xUnichar, 1, &extents);
++    //rawWidth = extents.width;
++    //mAveCharWidth = NSToCoordRound(rawWidth * f);
++    GetWidth("x", 1, tmpWidth);
++    mAveCharWidth = tmpWidth;
++
++    // mXHeight (height of an 'x' character)
++    if (pango_fc_font_has_char(fcfont, 'x')) {
++        PangoRectangle rect;
++        PangoGlyph glyph = pango_fc_font_get_glyph (fcfont, 'x');
++        pango_font_get_glyph_extents (PANGO_FONT (fcfont), glyph, &rect, NULL);
++        mXHeight = NSToIntRound(rect.height * f / PANGO_SCALE);
++    }
++    else {
++        // 56% of ascent, best guess for non-true type or asian fonts
++        mXHeight = nscoord(((float)mMaxAscent) * 0.56 * f);
++    }
++
++    // mUnderlineOffset (offset for underlines)
++    val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_position,
++                                         face->size->metrics.y_scale);
++    if (val) {
++        mUnderlineOffset = NSToIntRound(val * f);
++    }
++    else {
++        mUnderlineOffset =
++            -NSToIntRound(PR_MAX(1, floor(0.1 *
++                MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
++    }
++
++    // mUnderlineSize (thickness of an underline)
++    val = CONVERT_DESIGN_UNITS_TO_PIXELS(face->underline_thickness,
++                                         face->size->metrics.y_scale);
++    if (val) {
++        mUnderlineSize = nscoord(PR_MAX(f, NSToIntRound(val * f)));
++    }
++    else {
++        mUnderlineSize =
++            NSToIntRound(PR_MAX(1,
++               floor(0.05 * MOZ_FT_TRUNC(face->size->metrics.height) + 0.5)) * f);
++    }
++
++    // mSuperscriptOffset
++    if (os2 && os2->ySuperscriptYOffset) {
++        val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySuperscriptYOffset,
++                                             face->size->metrics.y_scale);
++        mSuperscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
++    }
++    else {
++        mSuperscriptOffset = mXHeight;
++    }
++
++    // mSubscriptOffset
++    if (os2 && os2->ySubscriptYOffset) {
++        val = CONVERT_DESIGN_UNITS_TO_PIXELS(os2->ySubscriptYOffset,
++                                             face->size->metrics.y_scale);
++        // some fonts have the incorrect sign. 
++        val = (val < 0) ? -val : val;
++        mSubscriptOffset = nscoord(PR_MAX(f, NSToIntRound(val * f)));
++    }
++    else {
++        mSubscriptOffset = mXHeight;
++    }
++
++    // mStrikeoutOffset
++    mStrikeoutOffset = NSToCoordRound(mXHeight / 2.0);
++
++    // mStrikeoutSize
++    mStrikeoutSize = mUnderlineSize;
++
++    pango_fc_font_unlock_face(fcfont);
++
++    /*
++    printf("%i\n", mXHeight);
++    printf("%i\n", mSuperscriptOffset);
++    printf("%i\n", mSubscriptOffset);
++    printf("%i\n", mStrikeoutOffset);
++    printf("%i\n", mStrikeoutSize);
++    printf("%i\n", mUnderlineOffset);
++    printf("%i\n", mUnderlineSize);
++    printf("%i\n", mMaxHeight);
++    printf("%i\n", mLeading);
++    printf("%i\n", mEmHeight);
++    printf("%i\n", mEmAscent);
++    printf("%i\n", mEmDescent);
++    printf("%i\n", mMaxAscent);
++    printf("%i\n", mMaxDescent);
++    printf("%i\n", mMaxAdvance);
++    printf("%i\n", mSpaceWidth);
++    printf("%i\n", mAveCharWidth);
++    */
++
++    return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPSPango::Destroy()
++{
++    mDeviceContext = nsnull;
++    return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetLangGroup(nsIAtom** aLangGroup)
++{
++    *aLangGroup = mLangGroup;
++    NS_IF_ADDREF(*aLangGroup);
++
++    return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetFontHandle(nsFontHandle &aHandle)
++{
++    return NS_ERROR_NOT_IMPLEMENTED;
++}
++
++// nsIFontMetricsPango impl
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength)
++{
++    return GetWidth (String, (PRUint32) aLength, aWidth);
++}
++
++NS_IMETHODIMP
++nsFontMetricsPSPango::GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength)
++{
++    return GetWidth (aString, (PRUint32)aLength, aWidth);
++}
++
++nsresult
++nsFontMetricsPSPango::GetWidth(const char* aString, PRUint32 aLength,
++                             nscoord& aWidth)
++{
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    pango_layout_set_text(layout, aString, aLength);
++
++    if (mPangoSpaceWidth)
++        FixupSpaceWidths(layout, aString);
++
++    int width, height;
++
++    pango_layout_get_size(layout, &width, &height);
++
++    g_object_unref(layout);
++
++    float f;
++    f = mDeviceContext->DevUnitsToAppUnits();
++    aWidth = NSToCoordRound(width * f / PANGO_SCALE);
++
++    //    printf("GetWidth (char *) %d\n", aWidth);
++
++    return NS_OK;
++}
++
++nsresult
++nsFontMetricsPSPango::GetWidth(const PRUnichar* aString, PRUint32 aLength,
++                             nscoord& aWidth)
++{
++    nsresult rv = NS_OK;
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    gchar *text = g_utf16_to_utf8(aString, aLength,
++                                  NULL, NULL, NULL);
++
++    if (!text) {
++        aWidth = 0;
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
++        DUMP_PRUNICHAR(aString, aLength)
++#endif
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    gint width, height;
++
++    pango_layout_set_text(layout, text, strlen(text));
++    FixupSpaceWidths(layout, text);
++    pango_layout_get_size(layout, &width, &height);
++
++    float f;
++    f = mDeviceContext->DevUnitsToAppUnits();
++    aWidth = NSToCoordRound(width * f / PANGO_SCALE);
++
++    //    printf("GetWidth %d\n", aWidth);
++
++ loser:
++    g_free(text);
++    g_object_unref(layout);
++
++    return rv;
++}
++
++
++nsresult
++nsFontMetricsPSPango :: GetTextDimensions(const char* aString, PRUint32 aLength,
++                                          nsTextDimensions& aDimensions)
++{
++    nsresult rv = NS_OK;
++
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    pango_layout_set_text(layout, aString, aLength);
++    FixupSpaceWidths(layout,aString);
++
++    // Get the logical extents
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    PangoRectangle rect;
++    pango_layout_line_get_extents(line, NULL, &rect);
++
++    float P2T;
++    P2T = mDeviceContext->DevUnitsToAppUnits();
++
++    aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
++    aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
++    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
++
++    //    printf("GetTextDimensions %d %d %d\n", aDimensions.width,
++    //aDimensions.ascent, aDimensions.descent);
++
++ loser:
++    g_object_unref(layout);
++
++    return rv;
++}
++
++nsresult
++nsFontMetricsPSPango::GetTextDimensions(const PRUnichar* aString,
++                                      PRUint32 aLength,
++                                      nsTextDimensions& aDimensions, 
++                                      PRInt32* aFontID)
++{
++    nsresult rv = NS_OK;
++
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    gchar *text = g_utf16_to_utf8(aString, aLength,
++                                  NULL, NULL, NULL);
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetTextDimensions invalid unicode to follow");
++        DUMP_PRUNICHAR(aString, aLength)
++#endif
++        aDimensions.width = 0;
++        aDimensions.ascent = 0;
++        aDimensions.descent = 0;
++
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++        
++
++    pango_layout_set_text(layout, text, strlen(text));
++    FixupSpaceWidths(layout, text);
++
++    // Get the logical extents
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    PangoRectangle rect;
++    pango_layout_line_get_extents(line, NULL, &rect);
++
++    float P2T;
++    P2T = mDeviceContext->DevUnitsToAppUnits();
++
++    aDimensions.width = NSToCoordRound(rect.width * P2T / PANGO_SCALE);
++    aDimensions.ascent = NSToCoordRound(PANGO_ASCENT(rect) * P2T / PANGO_SCALE);
++    aDimensions.descent = NSToCoordRound(PANGO_DESCENT(rect) * P2T / PANGO_SCALE);
++
++    //    printf("GetTextDimensions %d %d %d\n", aDimensions.width,
++    //aDimensions.ascent, aDimensions.descent);
++
++ loser:
++    g_free(text);
++    g_object_unref(layout);
++
++    return rv;
++}
++
++nsresult
++nsFontMetricsPSPango::GetTextDimensions(const char*         aString,
++                                      PRInt32             aLength,
++                                      PRInt32             aAvailWidth,
++                                      PRInt32*            aBreaks,
++                                      PRInt32             aNumBreaks,
++                                      nsTextDimensions&   aDimensions,
++                                      PRInt32&            aNumCharsFit,
++                                      nsTextDimensions&   aLastWordDimensions,
++                                      PRInt32*            aFontID)
++{
++
++    return GetTextDimensionsInternal(aString, aLength, aAvailWidth, aBreaks,
++                                     aNumBreaks, aDimensions, aNumCharsFit,
++                                     aLastWordDimensions);
++
++}
++
++nsresult
++nsFontMetricsPSPango::GetTextDimensions(const PRUnichar*    aString,
++                                      PRInt32             aLength,
++                                      PRInt32             aAvailWidth,
++                                      PRInt32*            aBreaks,
++                                      PRInt32             aNumBreaks,
++                                      nsTextDimensions&   aDimensions,
++                                      PRInt32&            aNumCharsFit,
++                                      nsTextDimensions&   aLastWordDimensions,
++                                      PRInt32*            aFontID)
++{
++    nsresult rv = NS_OK;
++    PRInt32 curBreak = 0;
++    gchar *curChar;
++
++    PRInt32 *utf8Breaks = new PRInt32[aNumBreaks];
++
++    gchar *text = g_utf16_to_utf8(aString, (PRInt32)aLength,
++                                  NULL, NULL, NULL);
++
++    curChar = text;
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
++        DUMP_PRUNICHAR(aString, (PRUint32)aLength)
++#endif
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    // Covert the utf16 break offsets to utf8 break offsets
++    for (PRInt32 curOffset=0; curOffset < aLength;
++         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++        if (aBreaks[curBreak] == curOffset) {
++            utf8Breaks[curBreak] = curChar - text;
++            curBreak++;
++        }
++
++        if (IS_HIGH_SURROGATE(aString[curOffset]))
++            curOffset++;
++    }
++
++    // Always catch the last break
++    utf8Breaks[curBreak] = curChar - text;
++
++#if 0
++    if (strlen(text) != aLength) {
++        printf("Different lengths for utf16 %d and utf8 %d\n", aLength, strlen(text));
++        DUMP_PRUNICHAR(aString, aLength)
++        DUMP_PRUNICHAR(text, strlen(text))
++        for (PRInt32 i = 0; i < aNumBreaks; ++i) {
++            printf("  break %d utf16 %d utf8 %d\n", i, aBreaks[i], utf8Breaks[i]);
++        }
++    }
++#endif
++
++    // We'll use curBreak to indicate which of the breaks end up being
++    // used for the break point for this line.
++    curBreak = 0;
++    rv = GetTextDimensionsInternal(text, strlen(text), aAvailWidth, utf8Breaks,
++                                   aNumBreaks, aDimensions, aNumCharsFit,
++                                   aLastWordDimensions);
++
++    // Figure out which of the breaks we ended up using to convert
++    // back to utf16 - start from the end.
++    for (PRInt32 i = aNumBreaks - 1; i >= 0; --i) {
++        if (utf8Breaks[i] == aNumCharsFit) {
++            //      if (aNumCharsFit != aBreaks[i])
++            //                printf("Fixing utf8 -> utf16 %d -> %d\n", aNumCharsFit, aBreaks[i]);
++            aNumCharsFit = aBreaks[i];
++            break;
++        }
++    }
++
++ loser:
++    if (text)
++        g_free(text);
++
++    delete[] utf8Breaks;
++
++    return rv;
++}
++
++typedef struct _nsPSPangoRenderer        nsPSPangoRenderer;
++typedef struct _nsPSPangoRendererClass   nsPSPangoRendererClass;
++
++struct _nsPSPangoRenderer
++{
++  PangoRenderer parent_instance;
++  nsRenderingContextPS *psContext;
++  nsFontMetricsPSPango *psPangoFontMetrics;
++  float zoom;
++};
++
++struct _nsPSPangoRendererClass
++{
++  PangoRendererClass parent_class;
++};
++
++#define _PS_TYPE_PANGO_RENDERER            (_ps_pango_renderer_get_type())
++#define _PS_PANGO_RENDERER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRenderer))
++#define _PS_IS_PANGO_RENDERER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), _PS_TYPE_PANGO_RENDERER))
++#define _PS_PANGO_RENDERER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
++#define _PS_IS_PANGO_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), _PS_TYPE_PANGO_RENDERER))
++#define _PS_PANGO_RENDERER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), _PS_TYPE_PANGO_RENDERER, _nsPSPangoRendererClass))
++
++G_DEFINE_TYPE (_nsPSPangoRenderer, _ps_pango_renderer, PANGO_TYPE_RENDERER)
++
++static PangoRenderer *
++get_renderer (void)
++{
++  static PangoRenderer               *renderer = NULL;
++
++  if (!renderer)
++    renderer = (PangoRenderer *) g_object_new (_PS_TYPE_PANGO_RENDERER, NULL);
++
++  return renderer;
++}
++
++static void
++_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
++                              PangoFont        *font,
++                              PangoGlyphString *glyphs,
++                              int               x,
++                              int               y);
++
++static void
++_ps_pango_renderer_class_init (nsPSPangoRendererClass *klass)
++{
++  PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass);
++  
++  renderer_class->draw_glyphs = _ps_pango_renderer_draw_glyphs;
++}
++
++static void
++_ps_pango_renderer_init (nsPSPangoRenderer *renderer)
++{
++}
++
++class nsPangoType1Generator : public nsPSFontGenerator {
++public:
++  nsPangoType1Generator();
++  ~nsPangoType1Generator();
++  nsresult Init(PangoFont *aFont);
++  void  GeneratePSFont(FILE* aFile);
++
++protected:
++  PangoFont *mFont;
++};
++
++nsPangoType1Generator::nsPangoType1Generator()
++{
++}
++
++nsresult
++nsPangoType1Generator::Init(PangoFont *aFont)
++{
++  NS_ENSURE_TRUE(aFont, NS_ERROR_FAILURE);
++  mFont = aFont;
++  g_object_ref (mFont);
++  return NS_OK;
++}
++
++nsPangoType1Generator::~nsPangoType1Generator()
++{
++  g_object_unref (mFont);
++  mFont = nsnull;
++}
++
++void nsPangoType1Generator::GeneratePSFont(FILE* aFile)
++{
++  FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) mFont);
++
++  if (face == nsnull)
++    return;
++
++  int wmode = 0;
++  if (mGlyphSubset->Count())
++    FT2SubsetToType1FontSet(face, mGlyphSubset, wmode, aFile);
++
++  pango_fc_font_unlock_face ((PangoFcFont *) mFont);
++}
++
++typedef struct
++{
++  nsCString    *FontNameBase;
++  nsCStringKey *key;
++  int           font_size;
++} PSPangoFontData;
++
++static void
++ps_pango_font_data_destroy (PSPangoFontData *data)
++{
++  delete data->key;
++  delete data->FontNameBase;
++  g_free (data);
++}
++
++static void
++flattenName(nsCString& aString)
++{
++  nsCString::iterator start, end;
++  aString.BeginWriting(start);
++  aString.EndWriting(end);
++  while(start != end) {
++    if (*start == ' ')
++      *start= '_';
++    else if (*start == '(')
++      *start = '_';
++    else if (*start == ')')
++      *start = '_';
++    ++start;
++  }
++}
++
++static void
++_ps_pango_renderer_draw_glyphs (PangoRenderer    *renderer,
++                              PangoFont        *font,
++                              PangoGlyphString *glyphs,
++                              int               x,
++                              int               y)
++{
++  if (!glyphs->num_glyphs)
++    return;
++
++  static GQuark data_quark = 0;
++  if (!data_quark)
++    data_quark = g_quark_from_static_string ("ps-pango-font-data");
++
++  PSPangoFontData *data;
++  if (!(data = (PSPangoFontData *) g_object_get_qdata (G_OBJECT (font), data_quark)))
++    {
++      data = g_new (PSPangoFontData, 1);
++
++      FT_Face face = pango_fc_font_lock_face ((PangoFcFont *) font);
++      if (face == nsnull)
++        return;
++      int wmode = 0;
++      data->FontNameBase = new nsCString ();
++      if (NS_FAILED(FT2ToType1FontName(face, wmode, *data->FontNameBase))) {
++        g_free (data);
++        pango_fc_font_unlock_face ((PangoFcFont *) font);
++        return;
++      }
++      pango_fc_font_unlock_face ((PangoFcFont *) font);
++
++      PangoFontDescription *desc = pango_font_describe (font);
++      data->font_size = pango_font_description_get_size (desc);
++      pango_font_description_free (desc);
++
++      data->key = new nsCStringKey (*data->FontNameBase);
++
++      g_object_set_qdata_full (G_OBJECT (font), data_quark, data, (GDestroyNotify) ps_pango_font_data_destroy);
++    }
++
++  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
++  nsRenderingContextPS *aContext = ps_renderer->psContext;
++  nsFontMetricsPSPango *metrics = ps_renderer->psPangoFontMetrics;
++  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, metrics->GetDeviceContext());
++  nsPostScriptObj* psObj = aContext->GetPostScriptObj();
++  nsHashtable *psFGList = dc->GetPSFontGeneratorList();
++  g_return_if_fail (psFGList);
++  nsPSFontGenerator* psFontGen = (nsPSFontGenerator*) psFGList->Get(data->key);
++  if (!psFontGen) {
++    nsresult rv;
++    psFontGen = new nsPangoType1Generator;
++    g_return_if_fail (psFontGen);
++    rv = ((nsPangoType1Generator*)psFontGen)->Init(font);
++    if (NS_FAILED(rv)) {
++      delete psFontGen;
++      return;
++    }
++    psFGList->Put(data->key, (void *) psFontGen);
++  }
++  nscoord font_size = NSToCoordRound (ps_renderer->zoom * data->font_size / PANGO_SCALE);
++
++  g_return_if_fail (aContext);
++  g_return_if_fail (psObj);
++
++  nscoord aX = NSToCoordRound(ps_renderer->zoom * x / PANGO_SCALE);
++  nscoord aY = NSToCoordRound(ps_renderer->zoom * y / PANGO_SCALE);
++  psObj->moveto(aX, aY);
++
++  PRInt32 currSubFont, prevSubFont = -1;
++  PRUint32 i;
++  PangoGlyphString gl;
++
++  gl.glyphs = glyphs->glyphs;
++  gl.num_glyphs = 0;
++  for (i = 0; i < glyphs->num_glyphs; ++i) {
++    currSubFont = psFontGen->AddToGlyphSubset(glyphs->glyphs[i].glyph >= 0x00ffffff ? 0 : glyphs->glyphs[i].glyph);
++    if (prevSubFont != currSubFont) {
++      if (prevSubFont != -1)
++        psObj->show(&gl, ps_renderer->zoom,  psFontGen, prevSubFont);
++
++
++      psObj->setfont(*data->FontNameBase, (PRUint32) font_size, currSubFont);
++      prevSubFont = currSubFont;
++      gl.glyphs = glyphs->glyphs + i;
++      gl.num_glyphs = 0;
++    }
++
++    gl.num_glyphs++;
++  }
++
++  if (prevSubFont != -1)
++    psObj->show(&gl, ps_renderer->zoom, psFontGen, prevSubFont);
++}
++
++static void
++draw_layout_line (int x, int y, PangoLayoutLine *line, nsFontMetricsPSPango *aPSPangoFontMetrics, nsRenderingContextPS *aContext)
++{
++  PangoRenderer *renderer = get_renderer ();
++  nsPSPangoRenderer *ps_renderer = (nsPSPangoRenderer *)renderer;
++  ps_renderer->psContext = aContext;
++  ps_renderer->psPangoFontMetrics = aPSPangoFontMetrics;
++  nsDeviceContextPS* dc = NS_REINTERPRET_CAST (nsDeviceContextPS*, aPSPangoFontMetrics->GetDeviceContext());
++  ps_renderer->zoom = dc->DevUnitsToAppUnits();
++
++  pango_renderer_draw_layout_line (renderer, line,
++                                   NSToCoordRound (x * PANGO_SCALE / ps_renderer->zoom),
++                                   NSToCoordRound (y * PANGO_SCALE / ps_renderer->zoom));
++}
++
++nsresult
++nsFontMetricsPSPango::DrawString(const char *aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               const nscoord* aSpacing,
++                               nsRenderingContextPS *aContext)
++{
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    pango_layout_set_text(layout, aString, aLength);
++    FixupSpaceWidths(layout, aString);
++
++    int x = aX;
++    int y = aY;
++
++    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    if (aSpacing && *aSpacing) {
++        DrawStringSlowly(aString, NULL, aLength, x, y, line, aSpacing, aContext);
++    }
++    else {
++       draw_layout_line (x, y, line, this, aContext);
++    }
++
++    g_object_unref(layout);
++
++    return NS_OK;
++}
++
++nsresult
++nsFontMetricsPSPango::DrawString(const PRUnichar* aString, PRUint32 aLength,
++                               nscoord aX, nscoord aY,
++                               PRInt32 aFontID,
++                               const nscoord* aSpacing,
++                               nsRenderingContextPS *aContext)
++{
++    nsresult rv = NS_OK;
++    int x = aX;
++    int y = aY;
++
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    gchar *text = g_utf16_to_utf8(aString, aLength,
++                                  NULL, NULL, NULL);
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::DrawString invalid unicode to follow");
++        DUMP_PRUNICHAR(aString, aLength)
++#endif
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    pango_layout_set_text(layout, text, strlen(text));
++    FixupSpaceWidths(layout, text);
++
++    aContext->GetTranMatrix()->TransformCoord(&x, &y);
++
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    if (aSpacing && *aSpacing) {
++        DrawStringSlowly(text, aString, aLength, x, y, line, aSpacing, aContext);
++    }
++    else {
++       draw_layout_line (x, y, line, this, aContext);
++    }
++
++ loser:
++
++    g_free(text);
++    g_object_unref(layout);
++
++    return rv;
++}
++
++#ifdef MOZ_MATHML
++nsresult
++nsFontMetricsPSPango::GetBoundingMetrics(const char *aString, PRUint32 aLength,
++                                       nsBoundingMetrics &aBoundingMetrics)
++{
++    printf("GetBoundingMetrics (char *)\n");
++    return NS_ERROR_FAILURE;
++}
++
++nsresult
++nsFontMetricsPSPango::GetBoundingMetrics(const PRUnichar *aString,
++                                       PRUint32 aLength,
++                                       nsBoundingMetrics &aBoundingMetrics,
++                                       PRInt32 *aFontID)
++{
++    nsresult rv = NS_OK;
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    gchar *text = g_utf16_to_utf8(aString, aLength,
++                                  NULL, NULL, NULL);
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetBoundingMetrics invalid unicode to follow");
++        DUMP_PRUNICHAR(aString, aLength)
++#endif
++        aBoundingMetrics.leftBearing = 0;
++        aBoundingMetrics.rightBearing = 0;
++        aBoundingMetrics.width = 0;
++        aBoundingMetrics.ascent = 0;
++        aBoundingMetrics.descent = 0;
++
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    pango_layout_set_text(layout, text, -1);
++    FixupSpaceWidths(layout, text);
++
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    // Get the ink and logical extents
++    PangoRectangle ink, logical;
++    pango_layout_line_get_extents(line, &ink, &logical);
++
++    float P2T;
++    P2T = mDeviceContext->DevUnitsToAppUnits();
++
++    aBoundingMetrics.leftBearing  = NSToCoordRound(PANGO_LBEARING(ink) * P2T / PANGO_SCALE);
++    aBoundingMetrics.rightBearing = NSToCoordRound(PANGO_RBEARING(ink) * P2T / PANGO_SCALE);
++    aBoundingMetrics.ascent       = NSToCoordRound(PANGO_ASCENT(ink)   * P2T / PANGO_SCALE);
++    aBoundingMetrics.descent      = NSToCoordRound(PANGO_DESCENT(ink)  * P2T / PANGO_SCALE);
++    aBoundingMetrics.width        = NSToCoordRound(logical.width       * P2T / PANGO_SCALE);
++
++ loser:
++    g_free(text);
++    g_object_unref(layout);
++
++    return rv;
++}
++
++#endif /* MOZ_MATHML */
++
++nsresult
++nsFontMetricsPSPango::SetRightToLeftText(PRBool aIsRTL)
++{
++    if (aIsRTL) {
++        if (!mRTLPangoContext) {
++            mRTLPangoContext = get_context();
++            pango_context_set_base_dir(mRTLPangoContext, PANGO_DIRECTION_RTL);
++
++            pango_context_set_language(mRTLPangoContext, GetPangoLanguage(mLangGroup));
++            pango_context_set_font_description(mRTLPangoContext, mPangoFontDesc);
++        }
++        mPangoContext = mRTLPangoContext;
++    }
++    else {
++        mPangoContext = mLTRPangoContext;
++    }
++
++    mIsRTL = aIsRTL;
++    return NS_OK;
++}
++
++nsresult
++nsFontMetricsPSPango::GetClusterInfo(const PRUnichar *aText,
++                                   PRUint32 aLength,
++                                   PRUint8 *aClusterStarts)
++{
++    nsresult rv = NS_OK;
++    PangoLogAttr *attrs = NULL;
++    gint n_attrs = 0;
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++    
++    // Convert the incoming UTF-16 to UTF-8
++    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
++        DUMP_PRUNICHAR(aText, aLength)
++#endif
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    // Set up the pango layout
++    pango_layout_set_text(layout, text, strlen(text));
++    FixupSpaceWidths(layout, text);
++
++    // Convert back to UTF-16 while filling in the cluster info
++    // structure.
++    pango_layout_get_log_attrs(layout, &attrs, &n_attrs);
++
++    for (PRUint32 pos = 0; pos < aLength; pos++) {
++        if (IS_HIGH_SURROGATE(aText[pos])) {
++            aClusterStarts[pos] = 1;
++            pos++;
++        }
++        else {
++            aClusterStarts[pos] = attrs[pos].is_cursor_position;
++        }
++    }
++
++ loser:
++    if (attrs)
++        g_free(attrs);
++    if (text)
++        g_free(text);
++    if (layout)
++        g_object_unref(layout);
++
++    return rv;
++}
++
++PRInt32
++nsFontMetricsPSPango::GetPosition(const PRUnichar *aText, PRUint32 aLength,
++                                nsPoint aPt)
++{
++    int trailing = 0;
++    int inx = 0;
++    const gchar *curChar;
++    PRInt32 retval = 0;
++
++    float f = mDeviceContext->AppUnitsToDevUnits();
++    
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++    PRUint32 localX = (PRUint32)(aPt.x * PANGO_SCALE * f);
++    PRUint32 localY = (PRUint32)(aPt.y * PANGO_SCALE * f);
++
++    // Convert the incoming UTF-16 to UTF-8
++    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
++        DUMP_PRUNICHAR(aText, aLength)
++#endif
++        retval = -1;
++        goto loser;
++    }
++
++    // Set up the pango layout
++    pango_layout_set_text(layout, text, strlen(text));
++    FixupSpaceWidths(layout, text);
++    
++    pango_layout_xy_to_index(layout, localX, localY,
++                             &inx, &trailing);
++
++    // Convert the index back to the utf-16 index
++    curChar = text;
++
++    for (PRUint32 curOffset=0; curOffset < aLength;
++         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++
++        // Check for a match before checking for a surrogate pair
++        if (curChar - text == inx) {
++            retval = curOffset;
++            break;
++        }
++
++        if (IS_HIGH_SURROGATE(aText[curOffset]))
++            curOffset++;
++    }
++
++    // If there was a trailing result, advance the index pointer the
++    // number of characters equal to the trailing result.
++    while (trailing) {
++        retval++;
++        // Yes, this can make aInx > length to indicate the end of the
++        // string.
++        if (retval < (PRInt32)aLength && IS_HIGH_SURROGATE(aText[retval]))
++            retval++;
++        trailing--;
++    }
++
++ loser:
++    if (text)
++        g_free(text);
++    if (layout)
++        g_object_unref(layout);
++
++    return retval;
++}
++
++nsresult
++nsFontMetricsPSPango::GetRangeWidth(const PRUnichar *aText,
++                                  PRUint32 aLength,
++                                  PRUint32 aStart,
++                                  PRUint32 aEnd,
++                                  PRUint32 &aWidth)
++{
++    nsresult rv = NS_OK;
++    PRUint32 utf8Start = 0;
++    PRUint32 utf8End = 0;
++
++    aWidth = 0;
++
++    // Convert the incoming UTF-16 to UTF-8
++    gchar *text = g_utf16_to_utf8(aText, aLength, NULL, NULL, NULL);
++    gchar *curChar = text;
++
++    if (!text) {
++#ifdef DEBUG
++        NS_WARNING("nsFontMetricsPSPango::GetWidth invalid unicode to follow");
++        DUMP_PRUNICHAR(aText, aLength)
++#endif
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    // Convert the utf16 offsets into utf8 offsets
++    for (PRUint32 curOffset = 0; curOffset < aLength;
++         curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++
++        if (curOffset == aStart)
++            utf8Start = curChar - text;
++
++        if (curOffset == aEnd)
++            utf8End = curChar - text;
++        
++        if (IS_HIGH_SURROGATE(aText[curOffset]))
++            curOffset++;
++    }
++
++    // Special case where the end index is the same as the length
++    if (aLength == aEnd)
++        utf8End = strlen(text);
++
++    rv = GetRangeWidth(text, strlen(text), utf8Start, utf8End, aWidth);
++
++ loser:
++    if (text)
++        g_free(text);
++
++    return rv;
++}
++
++nsresult
++nsFontMetricsPSPango::GetRangeWidth(const char *aText,
++                                  PRUint32 aLength,
++                                  PRUint32 aStart,
++                                  PRUint32 aEnd,
++                                  PRUint32 &aWidth)
++{
++    nsresult rv = NS_OK;
++    int *ranges = NULL;
++    int n_ranges = 0;
++    float f;
++
++    aWidth = 0;
++
++    PangoLayout *layout = pango_layout_new(mPangoContext);
++
++    if (!aText) {
++        rv = NS_ERROR_FAILURE;
++        goto loser;
++    }
++
++    pango_layout_set_text(layout, aText, aLength);
++    FixupSpaceWidths(layout, aText);
++
++    PangoLayoutLine *line;
++    if (pango_layout_get_line_count(layout) != 1) {
++        printf("Warning: more than one line!\n");
++    }
++    line = pango_layout_get_line(layout, 0);
++
++    pango_layout_line_get_x_ranges(line, aStart, aEnd, &ranges, &n_ranges);
++
++    aWidth = (ranges[((n_ranges - 1) * 2) + 1] - ranges[0]);
++
++    f = mDeviceContext-> DevUnitsToAppUnits();
++    aWidth = nscoord(aWidth * f / PANGO_SCALE);
++
++ loser:
++    if (ranges)
++        g_free(ranges);
++    if (layout)
++        g_object_unref(layout);
++
++    return rv;
++}
++
++PRUint32
++nsFontMetricsPSPango::GetHints(void)
++{
++    return (NS_RENDERING_HINT_BIDI_REORDERING |
++            NS_RENDERING_HINT_ARABIC_SHAPING | 
++            NS_RENDERING_HINT_FAST_MEASURE |
++            NS_RENDERING_HINT_REORDER_SPACED_TEXT |
++            NS_RENDERING_HINT_TEXT_CLUSTERS);
++}
++
++/* static */
++nsresult
++nsFontMetricsPSPango::FamilyExists(nsIDeviceContext *aDevice,
++                                 const nsString &aName)
++{
++    // fontconfig family name is always in UTF-8
++    NS_ConvertUTF16toUTF8 name(aName);
++
++    nsresult rv = NS_ERROR_FAILURE;
++    PangoContext *context = get_context();
++    PangoFontFamily **familyList;
++    int n;
++
++    pango_context_list_families(context, &familyList, &n);
++
++    for (int i=0; i < n; i++) {
++        const char *tmpname = pango_font_family_get_name(familyList[i]);
++        if (!Compare(nsDependentCString(tmpname), name,
++                     nsCaseInsensitiveCStringComparator())) {
++            rv = NS_OK;
++            break;
++        }
++    }
++
++    g_free(familyList);
++    g_object_unref(context);
++
++    return rv;
++}
++
++// Private Methods
++
++nsresult
++nsFontMetricsPSPango::RealizeFont(void)
++{
++    nsCString familyList;
++    // Create and fill out the font description.
++    mPangoFontDesc = pango_font_description_new();
++
++    // Add CSS names - walk the list of fonts, adding the generic as
++    // the last font
++    for (int i=0; i < mFontList.Count(); ++i) {
++        // if this was a generic name, break out of the loop since we
++        // don't want to add it to the pattern yet
++        if (mFontIsGeneric[i])
++            break;;
++
++        nsCString *familyName = mFontList.CStringAt(i);
++        familyList.Append(familyName->get());
++        familyList.Append(',');
++    }
++
++    // If there's a generic add a pref for the generic if there's one
++    // set.
++    if (mGenericFont && !mFont.systemFont) {
++        nsCString name;
++        name += "font.name.";
++        name += mGenericFont->get();
++        name += ".";
++
++        nsString langGroup;
++        mLangGroup->ToString(langGroup);
++
++        name.AppendWithConversion(langGroup);
++
++        nsCOMPtr<nsIPref> pref;
++        pref = do_GetService(NS_PREF_CONTRACTID);
++        if (pref) {
++            nsresult rv;
++            nsXPIDLCString value;
++            rv = pref->GetCharPref(name.get(), getter_Copies(value));
++
++            // we ignore prefs that have three hypens since they are X
++            // style prefs.
++            if (NS_FFRECountHyphens(value) < 3) {
++                nsCString tmpstr;
++                tmpstr.Append(value);
++
++                familyList.Append(tmpstr);
++                familyList.Append(',');
++            }
++        }
++    }
++
++    // Add the generic if there is one.
++    if (mGenericFont && !mFont.systemFont) {
++        familyList.Append(mGenericFont->get());
++        familyList.Append(',');
++    }
++
++    // Set the family
++    pango_font_description_set_family(mPangoFontDesc,
++                                      familyList.get());
++
++    // Set the point size
++    pango_font_description_set_size(mPangoFontDesc,
++                                    (gint)(mPointSize * PANGO_SCALE));
++
++    // Set the style
++    pango_font_description_set_style(mPangoFontDesc,
++                                     CalculateStyle(mFont.style));
++
++    // Set the weight
++    pango_font_description_set_weight(mPangoFontDesc,
++                                      CalculateWeight(mFont.weight));
++
++    // Now that we have the font description set up, create the
++    // context.
++    mLTRPangoContext = get_context();
++    mPangoContext = mLTRPangoContext;
++
++    // Make sure to set the base direction to LTR - if layout needs to
++    // render RTL text it will use ::SetRightToLeftText()
++    pango_context_set_base_dir(mPangoContext, PANGO_DIRECTION_LTR);
++
++    // Set the pango language now that we have a context
++    pango_context_set_language(mPangoContext, GetPangoLanguage(mLangGroup));
++
++    // And attach the font description to this context
++    pango_context_set_font_description(mPangoContext, mPangoFontDesc);
++
++    return NS_OK;
++}
++
++/* static */
++PRBool
++nsFontMetricsPSPango::EnumFontCallback(const nsString &aFamily,
++                                     PRBool aIsGeneric, void *aData)
++{
++    NS_ConvertUTF16toUTF8 name(aFamily);
++
++    // The newest fontconfig does the full Unicode case folding so that 
++    // we're being lazy here by calling |ToLowerCase| after converting
++    // to UTF-8  assuming that in virtually all cases, we just have to
++    // fold [A-Z].  (bug 223653). 
++    ToLowerCase(name);
++    nsFontMetricsPSPango *metrics = (nsFontMetricsPSPango *)aData;
++    metrics->mFontList.AppendCString(name);
++    metrics->mFontIsGeneric.AppendElement((void *)aIsGeneric);
++    if (aIsGeneric) {
++        metrics->mGenericFont = 
++            metrics->mFontList.CStringAt(metrics->mFontList.Count() - 1);
++        return PR_FALSE; // stop processing
++    }
++
++    return PR_TRUE; // keep processing
++}
++
++/*
++ * This is only used when there's per-character spacing happening.
++ * Well, really it can be either line or character spacing but it's
++ * just turtles all the way down!
++ */
++
++void
++nsFontMetricsPSPango::DrawStringSlowly(const gchar *aText,
++                                     const PRUnichar *aOrigString,
++                                     PRUint32 aLength,
++                                     gint aX, gint aY,
++                                     PangoLayoutLine *aLine,
++                                     const nscoord *aSpacing,
++                                     nsRenderingContextPS *aContext)
++{
++    float app2dev;
++    app2dev = mDeviceContext->AppUnitsToDevUnits();
++    gint offset = 0;
++
++    /*
++     * We walk the list of glyphs returned in each layout run,
++     * matching up the glyphs with the characters in the source text.
++     * We use the aSpacing argument to figure out where to place those
++     * glyphs.  It's important to note that since the string we're
++     * working with is in UTF-8 while the spacing argument assumes
++     * that offset will be part of the UTF-16 string.  Logical
++     * attributes in pango are in byte offsets in the UTF-8 string, so
++     * we need to store the offsets based on the UTF-8 string.
++     */
++    nscoord *utf8spacing = new nscoord[strlen(aText)];
++
++    if (aOrigString) {
++        const gchar *curChar = aText;
++        bzero(utf8spacing, sizeof(nscoord) * strlen(aText));
++
++        // Covert the utf16 spacing offsets to utf8 spacing offsets
++        for (PRUint32 curOffset=0; curOffset < aLength;
++             curOffset++, curChar = g_utf8_find_next_char(curChar, NULL)) {
++            utf8spacing[curChar - aText] = aSpacing[curOffset];
++
++            if (IS_HIGH_SURROGATE(aOrigString[curOffset]))
++                curOffset++;
++        }
++    }
++    else {
++        memcpy(utf8spacing, aSpacing, (sizeof(nscoord *) * aLength));
++    }
++
++    gint curRun = 0;
++
++    for (GSList *tmpList = aLine->runs; tmpList && tmpList->data;
++         tmpList = tmpList->next, curRun++) {
++        PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
++        gint tmpOffset = 0;
++
++        /*        printf("    Rendering run %d: \"%s\"\n", curRun,
++                  &aText[layoutRun->item->offset]); */
++
++        for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
++            /* printf("glyph %d offset %d orig width %d new width %d\n", i,
++             *        layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset,
++             *        layoutRun->glyphs->glyphs[i].geometry.width,
++             *       (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset] * app2dev * PANGO_SCALE));
++             */
++            gint thisOffset = (gint)(utf8spacing[layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset]
++                                     * app2dev * PANGO_SCALE);
++            layoutRun->glyphs->glyphs[i].geometry.width = thisOffset;
++            tmpOffset += thisOffset;
++        }
++
++        /*        printf("    rendering at X coord %d\n", aX + offset); */
++        offset += tmpOffset;
++    }
++
++    draw_layout_line (aX, aY, aLine, this, aContext);
++
++    delete[] utf8spacing;
++}
++
++nsresult
++nsFontMetricsPSPango::GetTextDimensionsInternal(const gchar*        aString,
++                                              PRInt32             aLength,
++                                              PRInt32             aAvailWidth,
++                                              PRInt32*            aBreaks,
++                                              PRInt32             aNumBreaks,
++                                              nsTextDimensions&   aDimensions,
++                                              PRInt32&            aNumCharsFit,
++                                              nsTextDimensions&   aLastWordDimensions)
++{
++    NS_PRECONDITION(aBreaks[aNumBreaks - 1] == aLength, "invalid break array");
++
++    // If we need to back up this state represents the last place
++    // we could break. We can use this to avoid remeasuring text
++    PRInt32 prevBreakState_BreakIndex = -1; // not known
++                                            // (hasn't been computed)
++    nscoord prevBreakState_Width = 0; // accumulated width to this point
++
++    // Initialize OUT parameters
++    GetMaxAscent(aLastWordDimensions.ascent);
++    GetMaxDescent(aLastWordDimensions.descent);
++    aLastWordDimensions.width = -1;
++    aNumCharsFit = 0;
++
++    // Iterate each character in the string and determine which font to use
++    nscoord width = 0;
++    PRInt32 start = 0;
++    nscoord aveCharWidth;
++    GetAveCharWidth(aveCharWidth);
++
++    while (start < aLength) {
++        // Estimate how many characters will fit. Do that by
++        // diving the available space by the average character
++        // width. Make sure the estimated number of characters is
++        // at least 1
++        PRInt32 estimatedNumChars = 0;
++
++        if (aveCharWidth > 0)
++            estimatedNumChars = (aAvailWidth - width) / aveCharWidth;
++
++        if (estimatedNumChars < 1)
++            estimatedNumChars = 1;
++
++        // Find the nearest break offset
++        PRInt32 estimatedBreakOffset = start + estimatedNumChars;
++        PRInt32 breakIndex;
++        nscoord numChars;
++
++        // Find the nearest place to break that is less than or equal to
++        // the estimated break offset
++        if (aLength <= estimatedBreakOffset) {
++            // All the characters should fit
++            numChars = aLength - start;
++            breakIndex = aNumBreaks - 1;
++        } 
++        else {
++            breakIndex = prevBreakState_BreakIndex;
++            while (((breakIndex + 1) < aNumBreaks) &&
++                   (aBreaks[breakIndex + 1] <= estimatedBreakOffset)) {
++                ++breakIndex;
++            }
++
++            if (breakIndex == prevBreakState_BreakIndex) {
++                ++breakIndex; // make sure we advanced past the
++                // previous break index
++            }
++
++            numChars = aBreaks[breakIndex] - start;
++        }
++
++        // Measure the text
++        nscoord twWidth = 0;
++        if ((1 == numChars) && (aString[start] == ' '))
++            GetSpaceWidth(twWidth);
++        else if (numChars > 0)
++            GetWidth(&aString[start], numChars, twWidth);
++
++        // See if the text fits
++        PRBool  textFits = (twWidth + width) <= aAvailWidth;
++
++        // If the text fits then update the width and the number of
++        // characters that fit
++        if (textFits) {
++            aNumCharsFit += numChars;
++            width += twWidth;
++            start += numChars;
++
++            // This is a good spot to back up to if we need to so remember
++            // this state
++            prevBreakState_BreakIndex = breakIndex;
++            prevBreakState_Width = width;
++        }
++        else {
++            // See if we can just back up to the previous saved
++            // state and not have to measure any text
++            if (prevBreakState_BreakIndex > 0) {
++                // If the previous break index is just before the
++                // current break index then we can use it
++                if (prevBreakState_BreakIndex == (breakIndex - 1)) {
++                    aNumCharsFit = aBreaks[prevBreakState_BreakIndex];
++                    width = prevBreakState_Width;
++                    break;
++                }
++            }
++
++            // We can't just revert to the previous break state
++            if (0 == breakIndex) {
++                // There's no place to back up to, so even though
++                // the text doesn't fit return it anyway
++                aNumCharsFit += numChars;
++                width += twWidth;
++                break;
++            }
++
++            // Repeatedly back up until we get to where the text
++            // fits or we're all the way back to the first word
++            width += twWidth;
++            while ((breakIndex >= 1) && (width > aAvailWidth)) {
++                twWidth = 0;
++                start = aBreaks[breakIndex - 1];
++                numChars = aBreaks[breakIndex] - start;
++
++                if ((1 == numChars) && (aString[start] == ' '))
++                    GetSpaceWidth(twWidth);
++                else if (numChars > 0)
++                    GetWidth(&aString[start], numChars, twWidth);
++                width -= twWidth;
++                aNumCharsFit = start;
++                breakIndex--;
++            }
++            break;
++        }
++    }
++
++    aDimensions.width = width;
++    GetMaxAscent(aDimensions.ascent);
++    GetMaxDescent(aDimensions.descent);
++
++    /*    printf("aDimensions %d %d %d aLastWordDimensions %d %d %d aNumCharsFit %d\n",
++           aDimensions.width, aDimensions.ascent, aDimensions.descent,
++           aLastWordDimensions.width, aLastWordDimensions.ascent, aLastWordDimensions.descent,
++           aNumCharsFit); */
++
++    return NS_OK;
++}
++
++void
++nsFontMetricsPSPango::FixupSpaceWidths (PangoLayout *aLayout,
++                                      const char *aString)
++{
++    PangoLayoutLine *line = pango_layout_get_line(aLayout, 0);
++
++    gint curRun = 0;
++
++    for (GSList *tmpList = line->runs; tmpList && tmpList->data;
++         tmpList = tmpList->next, curRun++) {
++        PangoLayoutRun *layoutRun = (PangoLayoutRun *)tmpList->data;
++
++        for (gint i=0; i < layoutRun->glyphs->num_glyphs; i++) {
++            gint thisOffset = (gint)layoutRun->glyphs->log_clusters[i] + layoutRun->item->offset;
++            if (aString[thisOffset] == ' ')
++                layoutRun->glyphs->glyphs[i].geometry.width = mPangoSpaceWidth;
++        }
++    }
++}
++
++/* static */
++PangoLanguage *
++GetPangoLanguage(nsIAtom *aLangGroup)
++{
++    // Find the FC lang group for this lang group
++    nsCAutoString cname;
++    aLangGroup->ToUTF8String(cname);
++
++    // see if the lang group needs to be translated from mozilla's
++    // internal mapping into fontconfig's
++    const MozGtkLangGroup *langGroup;
++    langGroup = NS_FindFCLangGroup(cname);
++
++    // if there's no lang group, just use the lang group as it was
++    // passed to us
++    //
++    // we're casting away the const here for the strings - should be
++    // safe.
++    if (!langGroup)
++        return pango_language_from_string(cname.get());
++    else if (langGroup->Lang) 
++        return pango_language_from_string((char *) langGroup->Lang);
++
++    return pango_language_from_string("en");
++}
++
++/* static */
++void
++FreeGlobals(void)
++{
++}
++
++/* static */
++PangoStyle
++CalculateStyle(PRUint8 aStyle)
++{
++    switch(aStyle) {
++    case NS_FONT_STYLE_ITALIC:
++        return PANGO_STYLE_OBLIQUE;
++        break;
++    case NS_FONT_STYLE_OBLIQUE:
++        return PANGO_STYLE_OBLIQUE;
++        break;
++    }
++
++    return PANGO_STYLE_NORMAL;
++}
++
++/* static */
++PangoWeight
++CalculateWeight (PRUint16 aWeight)
++{
++    /*
++     * weights come in two parts crammed into one
++     * integer -- the "base" weight is weight / 100,
++     * the rest of the value is the "offset" from that
++     * weight -- the number of steps to move to adjust
++     * the weight in the list of supported font weights,
++     * this value can be negative or positive.
++     */
++    PRInt32 baseWeight = (aWeight + 50) / 100;
++    PRInt32 offset = aWeight - baseWeight * 100;
++
++    /* clip weights to range 0 to 9 */
++    if (baseWeight < 0)
++        baseWeight = 0;
++    if (baseWeight > 9)
++        baseWeight = 9;
++
++    /* Map from weight value to fcWeights index */
++    static int fcWeightLookup[10] = {
++        0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
++    };
++
++    PRInt32 fcWeight = fcWeightLookup[baseWeight];
++
++    /*
++     * adjust by the offset value, make sure we stay inside the 
++     * fcWeights table
++     */
++    fcWeight += offset;
++
++    if (fcWeight < 0)
++        fcWeight = 0;
++    if (fcWeight > 4)
++        fcWeight = 4;
++
++    /* Map to final PANGO_WEIGHT value */
++    static int fcWeights[5] = {
++        349,
++        499,
++        649,
++        749,
++        999
++    };
++
++    return (PangoWeight)fcWeights[fcWeight];
++}
++
++/* static */
++nsresult
++EnumFontsPango(nsIAtom* aLangGroup, const char* aGeneric,
++               PRUint32* aCount, PRUnichar*** aResult)
++{
++    FcPattern   *pat = NULL;
++    FcObjectSet *os  = NULL;
++    FcFontSet   *fs  = NULL;
++    nsresult     rv  = NS_ERROR_FAILURE;
++
++    PRUnichar **array = NULL;
++    PRUint32    narray = 0;
++    PRInt32     serif = 0, sansSerif = 0, monospace = 0, nGenerics;
++
++    *aCount = 0;
++    *aResult = nsnull;
++
++    pat = FcPatternCreate();
++    if (!pat)
++        goto end;
++
++    os = FcObjectSetBuild(FC_FAMILY, FC_FOUNDRY, NULL);
++    if (!os)
++        goto end;
++
++    // take the pattern and add the lang group to it
++    if (aLangGroup)
++        NS_AddLangGroup(pat, aLangGroup);
++
++    // get the font list
++    fs = FcFontList(0, pat, os);
++
++    if (!fs)
++        goto end;
++
++    if (!fs->nfont) {
++        rv = NS_OK;
++        goto end;
++    }
++
++    // Fontconfig supports 3 generic fonts, "serif", "sans-serif", and
++    // "monospace", slightly different from CSS's 5.
++    if (!aGeneric)
++        serif = sansSerif = monospace = 1;
++    else if (!strcmp(aGeneric, "serif"))
++        serif = 1;
++    else if (!strcmp(aGeneric, "sans-serif"))
++        sansSerif = 1;
++    else if (!strcmp(aGeneric, "monospace"))
++        monospace = 1;
++    else if (!strcmp(aGeneric, "cursive") || !strcmp(aGeneric, "fantasy"))
++        serif = sansSerif =  1;
++    else
++        NS_NOTREACHED("unexpected generic family");
++    nGenerics = serif + sansSerif + monospace;
++
++    array = NS_STATIC_CAST(PRUnichar **,
++               nsMemory::Alloc((fs->nfont + nGenerics) * sizeof(PRUnichar *)));
++    if (!array)
++        goto end;
++
++    if (serif) {
++        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("serif"));
++        if (!name)
++            goto end;
++        array[narray++] = name;
++    }
++
++    if (sansSerif) {
++        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("sans-serif"));
++        if (!name)
++            goto end;
++        array[narray++] = name;
++    }
++
++    if (monospace) {
++        PRUnichar *name = ToNewUnicode(NS_LITERAL_STRING("monospace"));
++        if (!name)
++            goto end;
++        array[narray++] = name;
++    }
++
++    for (int i=0; i < fs->nfont; ++i) {
++        char *family;
++
++        // if there's no family, just move to the next iteration
++        if (FcPatternGetString (fs->fonts[i], FC_FAMILY, 0,
++                                (FcChar8 **) &family) != FcResultMatch) {
++            continue;
++        }
++
++        // fontconfig always returns family names in UTF-8
++        PRUnichar* name =  UTF8ToNewUnicode(nsDependentCString(family));
++
++        if (!name)
++            goto end;
++
++        array[narray++] = name;
++    }
++
++    NS_QuickSort(array + nGenerics, narray - nGenerics, sizeof (PRUnichar*),
++                 CompareFontNames, nsnull);
++
++    *aCount = narray;
++    if (narray)
++        *aResult = array;
++    else
++        nsMemory::Free(array);
++
++    rv = NS_OK;
++
++ end:
++    if (NS_FAILED(rv) && array) {
++        while (narray)
++            nsMemory::Free (array[--narray]);
++        nsMemory::Free (array);
++    }
++    if (pat)
++        FcPatternDestroy(pat);
++    if (os)
++        FcObjectSetDestroy(os);
++    if (fs)
++        FcFontSetDestroy(fs);
++
++    return rv;
++}
++
++/* static */
++int
++CompareFontNames (const void* aArg1, const void* aArg2, void* aClosure)
++{
++    const PRUnichar* str1 = *((const PRUnichar**) aArg1);
++    const PRUnichar* str2 = *((const PRUnichar**) aArg2);
++
++    return nsCRT::strcmp(str1, str2);
++}
++
++
++// nsFontEnumeratorPango class
++
++nsFontEnumeratorPango::nsFontEnumeratorPango()
++{
++}
++
++NS_IMPL_ISUPPORTS1(nsFontEnumeratorPango, nsIFontEnumerator)
++
++NS_IMETHODIMP
++nsFontEnumeratorPango::EnumerateAllFonts(PRUint32 *aCount,
++                                         PRUnichar ***aResult)
++{
++    NS_ENSURE_ARG_POINTER(aResult);
++    *aResult = nsnull;
++    NS_ENSURE_ARG_POINTER(aCount);
++    *aCount = 0;
++
++    return EnumFontsPango(nsnull, nsnull, aCount, aResult);
++}
++
++NS_IMETHODIMP
++nsFontEnumeratorPango::EnumerateFonts(const char *aLangGroup,
++                                      const char *aGeneric,
++                                      PRUint32 *aCount,
++                                      PRUnichar ***aResult)
++{
++    NS_ENSURE_ARG_POINTER(aResult);
++    *aResult = nsnull;
++    NS_ENSURE_ARG_POINTER(aCount);
++    *aCount = 0;
++
++    // aLangGroup=null or ""  means any (i.e., don't care)
++    // aGeneric=null or ""  means any (i.e, don't care)
++    nsCOMPtr<nsIAtom> langGroup;
++    if (aLangGroup && *aLangGroup)
++        langGroup = do_GetAtom(aLangGroup);
++    const char* generic = nsnull;
++    if (aGeneric && *aGeneric)
++        generic = aGeneric;
++
++    return EnumFontsPango(langGroup, generic, aCount, aResult);
++}
++
++NS_IMETHODIMP
++nsFontEnumeratorPango::HaveFontFor(const char *aLangGroup,
++                                   PRBool *aResult)
++{
++    NS_ENSURE_ARG_POINTER(aResult);
++    *aResult = PR_FALSE;
++    NS_ENSURE_ARG_POINTER(aLangGroup);
++
++    *aResult = PR_TRUE; // always return true for now.
++    // Finish me - ftang
++    return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontEnumeratorPango::GetDefaultFont(const char *aLangGroup,
++                                      const char *aGeneric,
++                                      PRUnichar **aResult)
++{
++    NS_ENSURE_ARG_POINTER(aResult);
++    *aResult = nsnull;
++
++    // Have a look at nsFontEnumeratorXft::GetDefaultFont for some
++    // possible code for this function.
++
++    return NS_OK;
++}
++
++NS_IMETHODIMP
++nsFontEnumeratorPango::UpdateFontList(PRBool *_retval)
++{
++    *_retval = PR_FALSE; // always return false for now
++    return NS_OK;
++}
+Index: gfx/src/ps/nsFontMetricsPSPango.h
+===================================================================
+RCS file: gfx/src/ps/nsFontMetricsPSPango.h
+diff -N gfx/src/ps/nsFontMetricsPSPango.h
+--- /dev/null  1 Jan 1970 00:00:00 -0000
++++ gfx/src/ps/nsFontMetricsPSPango.h  23 Oct 2006 17:37:13 -0000
+@@ -0,0 +1,305 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/* vim:expandtab:shiftwidth=4:tabstop=4:
++ */
++/* ***** BEGIN LICENSE BLOCK *****
++ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
++ *
++ * The contents of this file are subject to the Mozilla Public License Version
++ * 1.1 (the "License"); you may not use this file except in compliance with
++ * the License. You may obtain a copy of the License at
++ * http://www.mozilla.org/MPL/
++ *
++ * Software distributed under the License is distributed on an "AS IS" basis,
++ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
++ * for the specific language governing rights and limitations under the
++ * License.
++ *
++ * The Original Code is mozilla.org code.
++ *
++ * The Initial Developer of the Original Code is
++ * Christopher Blizzard <blizzard@mozilla.org>.  
++ * Portions created by the Initial Developer are Copyright (C) 2002
++ * the Initial Developer. All Rights Reserved.
++ *
++ * Contributor(s):
++ *
++ * Alternatively, the contents of this file may be used under the terms of
++ * either the GNU General Public License Version 2 or later (the "GPL"), or
++ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
++ * in which case the provisions of the GPL or the LGPL are applicable instead
++ * of those above. If you wish to allow use of your version of this file only
++ * under the terms of either the GPL or the LGPL, and not to allow others to
++ * use your version of this file under the terms of the MPL, indicate your
++ * decision by deleting the provisions above and replace them with the notice
++ * and other provisions required by the GPL or the LGPL. If you do not delete
++ * the provisions above, a recipient may use your version of this file under
++ * the terms of any one of the MPL, the GPL or the LGPL.
++ *
++ * ***** END LICENSE BLOCK ***** */
++
++#ifndef nsFontMetricsPSPango_h__
++#define nsFontMetricsPSPango_h__
++
++#include "nsIFontMetrics.h"
++#include "nsIFontEnumerator.h"
++#include "nsCRT.h"
++#include "nsIAtom.h"
++#include "nsString.h"
++#include "nsVoidArray.h"
++#include "nsFontMetricsPS.h"
++
++#include <pango/pango.h>
++
++class nsRenderingContextPS;
++class nsIDrawingSurface;
++
++class nsFontMetricsPSPango : public nsFontMetricsPS
++{
++public:
++    nsFontMetricsPSPango();
++    virtual ~nsFontMetricsPSPango();
++
++    NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
++
++    // nsISupports
++    NS_DECL_ISUPPORTS
++
++    // nsIFontMetrics
++    NS_IMETHOD  Init                 (const nsFont& aFont, nsIAtom* aLangGroup,
++                                      nsIDeviceContext *aContext);
++    NS_IMETHOD  Destroy();
++    NS_IMETHOD  GetLangGroup         (nsIAtom** aLangGroup);
++    NS_IMETHOD  GetFontHandle        (nsFontHandle &aHandle);
++
++    NS_IMETHOD  GetXHeight           (nscoord& aResult)
++                                     { aResult = mXHeight; return NS_OK; };
++
++    NS_IMETHOD GetSuperscriptOffset  (nscoord& aResult)
++                                     { aResult = mSuperscriptOffset;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetSubscriptOffset    (nscoord& aResult)
++                                     { aResult = mSubscriptOffset;
++                                       return NS_OK; };
++                              
++    NS_IMETHOD GetStrikeout          (nscoord& aOffset, nscoord& aSize)
++                                     { aOffset = mStrikeoutOffset;
++                                       aSize = mStrikeoutSize; 
++                                       return NS_OK; };
++
++    NS_IMETHOD GetUnderline          (nscoord& aOffset, nscoord& aSize)
++                                     { aOffset = mUnderlineOffset;
++                                       aSize = mUnderlineSize; 
++                                       return NS_OK; };
++
++    NS_IMETHOD GetHeight             (nscoord &aHeight)
++                                     { aHeight = mMaxHeight; 
++                                       return NS_OK; };
++
++    NS_IMETHOD GetNormalLineHeight   (nscoord &aHeight)
++                                     { aHeight = mEmHeight + mLeading;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetLeading            (nscoord &aLeading)
++                                     { aLeading = mLeading; 
++                                       return NS_OK; };
++
++    NS_IMETHOD GetEmHeight           (nscoord &aHeight)
++                                     { aHeight = mEmHeight; 
++                                       return NS_OK; };
++
++    NS_IMETHOD GetEmAscent           (nscoord &aAscent)
++                                     { aAscent = mEmAscent;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetEmDescent          (nscoord &aDescent)
++                                     { aDescent = mEmDescent;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetMaxHeight          (nscoord &aHeight)
++                                     { aHeight = mMaxHeight;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetMaxAscent          (nscoord &aAscent)
++                                     { aAscent = mMaxAscent;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetMaxDescent         (nscoord &aDescent)
++                                     { aDescent = mMaxDescent;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetMaxAdvance         (nscoord &aAdvance)
++                                     { aAdvance = mMaxAdvance;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetSpaceWidth         (nscoord &aSpaceCharWidth)
++                                     { aSpaceCharWidth = mSpaceWidth;
++                                       return NS_OK; };
++
++    NS_IMETHOD GetAveCharWidth       (nscoord &aAveCharWidth)
++                                     { aAveCharWidth = mAveCharWidth;
++                                       return NS_OK; };
++
++    // nsIFontMetricsPS (calls from the font rendering layer)
++    NS_IMETHOD  GetStringWidth(const char *String,nscoord &aWidth,nscoord aLength);
++    NS_IMETHOD  GetStringWidth(const PRUnichar *aString,nscoord &aWidth,nscoord aLength);
++
++    NS_IMETHOD       GetWidth(const char* aString, PRUint32 aLength,
++                              nscoord& aWidth);
++    NS_IMETHOD       GetWidth(const PRUnichar* aString, PRUint32 aLength,
++                              nscoord& aWidth);
++
++    NS_IMETHOD       GetTextDimensions(const char* aString,
++                                       PRUint32 aLength,
++                                       nsTextDimensions& aDimensions);
++    NS_IMETHOD       GetTextDimensions(const PRUnichar* aString,
++                                       PRUint32 aLength,
++                                       nsTextDimensions& aDimensions, 
++                                       PRInt32* aFontID);
++    NS_IMETHOD       GetTextDimensions(const char*         aString,
++                                       PRInt32             aLength,
++                                       PRInt32             aAvailWidth,
++                                       PRInt32*            aBreaks,
++                                       PRInt32             aNumBreaks,
++                                       nsTextDimensions&   aDimensions,
++                                       PRInt32&            aNumCharsFit,
++                                       nsTextDimensions&   aLastWordDimensions,
++                                       PRInt32*            aFontID);
++    NS_IMETHOD       GetTextDimensions(const PRUnichar*    aString,
++                                       PRInt32             aLength,
++                                       PRInt32             aAvailWidth,
++                                       PRInt32*            aBreaks,
++                                       PRInt32             aNumBreaks,
++                                       nsTextDimensions&   aDimensions,
++                                       PRInt32&            aNumCharsFit,
++                                       nsTextDimensions&   aLastWordDimensions,
++                                       PRInt32*            aFontID);
++
++    NS_IMETHOD       DrawString(const char *aString, PRUint32 aLength,
++                                nscoord aX, nscoord aY,
++                                const nscoord* aSpacing,
++                                nsRenderingContextPS *aContext);
++    NS_IMETHOD       DrawString(const PRUnichar* aString, PRUint32 aLength,
++                                nscoord aX, nscoord aY,
++                                PRInt32 aFontID,
++                                const nscoord* aSpacing,
++                                nsRenderingContextPS *aContext);
++
++#ifdef MOZ_MATHML
++    NS_IMETHOD       GetBoundingMetrics(const char *aString, PRUint32 aLength,
++                                        nsBoundingMetrics &aBoundingMetrics);
++    NS_IMETHOD       GetBoundingMetrics(const PRUnichar *aString,
++                                        PRUint32 aLength,
++                                        nsBoundingMetrics &aBoundingMetrics,
++                                        PRInt32 *aFontID);
++#endif /* MOZ_MATHML */
++
++    NS_IMETHOD       SetRightToLeftText(PRBool aIsRTL);
++
++    NS_IMETHOD       GetClusterInfo(const PRUnichar *aText,
++                                    PRUint32 aLength,
++                                    PRUint8 *aClusterStarts);
++
++    virtual PRInt32 GetPosition(const PRUnichar *aText,
++                                PRUint32 aLength,
++                                nsPoint aPt);
++
++    NS_IMETHOD       GetRangeWidth(const PRUnichar *aText,
++                                   PRUint32 aLength,
++                                   PRUint32 aStart,
++                                   PRUint32 aEnd,
++                                   PRUint32 &aWidth);
++
++    NS_IMETHOD       GetRangeWidth(const char *aText,
++                                   PRUint32 aLength,
++                                   PRUint32 aStart,
++                                   PRUint32 aEnd,
++                                   PRUint32 &aWidth);
++
++    // get hints for the font
++    virtual PRUint32    GetHints     (void);
++
++    // drawing surface methods
++    static nsresult FamilyExists    (nsIDeviceContext *aDevice,
++                                     const nsString &aName);
++
++    inline nsIDeviceContext *GetDeviceContext() { return mDeviceContext; }
++
++private:
++
++    // generic font metrics class bits
++    nsCStringArray       mFontList;
++    nsAutoVoidArray      mFontIsGeneric;
++
++    nsIDeviceContext    *mDeviceContext;
++    nsCOMPtr<nsIAtom>    mLangGroup;
++    nsCString           *mGenericFont;
++    float                mPointSize;
++
++    nsCAutoString        mDefaultFont;
++
++    // Pango-related items
++    PangoFontDescription *mPangoFontDesc;
++    PangoContext         *mPangoContext;
++    PangoContext         *mLTRPangoContext;
++    PangoContext         *mRTLPangoContext;
++    PangoAttrList        *mPangoAttrList;
++    PRBool                mIsRTL;
++
++    // Cached font metrics
++    nscoord                  mXHeight;
++    nscoord                  mSuperscriptOffset;
++    nscoord                  mSubscriptOffset;
++    nscoord                  mStrikeoutOffset;
++    nscoord                  mStrikeoutSize;
++    nscoord                  mUnderlineOffset;
++    nscoord                  mUnderlineSize;
++    nscoord                  mMaxHeight;
++    nscoord                  mLeading;
++    nscoord                  mEmHeight;
++    nscoord                  mEmAscent;
++    nscoord                  mEmDescent;
++    nscoord                  mMaxAscent;
++    nscoord                  mMaxDescent;
++    nscoord                  mMaxAdvance;
++    nscoord                  mSpaceWidth;
++    nscoord                  mPangoSpaceWidth;
++    nscoord                  mAveCharWidth;
++
++    // Private methods
++    nsresult RealizeFont(void);
++    nsresult CacheFontMetrics(void);
++
++    static PRBool EnumFontCallback(const nsString &aFamily,
++                                   PRBool aIsGeneric, void *aData);
++
++    void     DrawStringSlowly(const gchar *aText,
++                              const PRUnichar *aOrigString,
++                              PRUint32 aLength,
++                              gint aX, gint aY,
++                              PangoLayoutLine *aLine,
++                              const nscoord *aSpacing,
++                              nsRenderingContextPS *aContext);
++
++    nsresult GetTextDimensionsInternal(const gchar*        aString,
++                                       PRInt32             aLength,
++                                       PRInt32             aAvailWidth,
++                                       PRInt32*            aBreaks,
++                                       PRInt32             aNumBreaks,
++                                       nsTextDimensions&   aDimensions,
++                                       PRInt32&            aNumCharsFit,
++                                       nsTextDimensions&   aLastWordDimensions);
++
++    void FixupSpaceWidths (PangoLayout *aLayout, const char *aString);
++};
++
++class nsFontEnumeratorPango : public nsIFontEnumerator
++{
++public:
++    nsFontEnumeratorPango();
++    NS_DECL_ISUPPORTS
++    NS_DECL_NSIFONTENUMERATOR
++};
++
++#endif
++
+Index: gfx/src/ps/nsPostScriptObj.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.cpp,v
+retrieving revision 1.124
+diff -u -p -d -r1.124 nsPostScriptObj.cpp
+--- gfx/src/ps/nsPostScriptObj.cpp     26 Jul 2005 15:54:18 -0000      1.124
++++ gfx/src/ps/nsPostScriptObj.cpp     23 Oct 2006 17:37:29 -0000
+@@ -2061,31 +2061,74 @@ nsPostScriptObj::show(const PRUnichar* t
+ #if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
+ void 
+-nsPostScriptObj::show(const PRUnichar* aTxt, int aLen,
+-                      const nsAFlatString& aCharList, PRUint16 aSubFontIdx)
++/*nsPostScriptObj::show(const PRUnichar* aTxt, int aLen,
++  const nsAFlatString& aCharList, PRUint16 aSubFontIdx) */
++nsPostScriptObj::show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset,
++                      PRUint16 aSubFontIdx)
+ {
+-  int i;
++  PRUint32 i;
+   fputc('<', mScriptFP);
+-  const PRUint16 subFontSize = nsPSFontGenerator::kSubFontSize;
++  for (i = 0; i < aGlyphs->Count(); i++) {
++    PRUint32 glyph = aGlyphs->ValueAt(i);
++    fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph));
++  }
+-  // the character repertoire of a subfont (255 characters max)
+-  const nsAString& repertoire = 
+-        Substring(aCharList, aSubFontIdx * subFontSize,
+-                  PR_MIN(subFontSize, 
+-                  aCharList.Length() - aSubFontIdx * subFontSize));
++  fputs("> show\n", mScriptFP);
++}
++#endif
+-  for (i = 0; i < aLen; i++) {
+-    // XXX This is a little inefficient, but printing is not perf. critical. 
+-    NS_ASSERTION(repertoire.FindChar(aTxt[i]) != kNotFound,
+-        "character is not covered by this subfont");
+-      
+-    // Type 1 encoding vector has 256 slots, but the 0-th slot is 
+-    // reserved for /.notdef so that we use the 1st through 255th slots
+-    // for actual characters (hence '+ 1')
+-    fprintf(mScriptFP, "%02x", repertoire.FindChar(aTxt[i]) + 1); 
++#ifdef MOZ_ENABLE_PANGO
++void
++nsPostScriptObj::show(const PangoGlyphString *glyphs, float zoom, 
++                      nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx)
++{
++  PRUint32 i;
++  int horiz = 1;
++
++  if (glyphs->glyphs[0].geometry.x_offset || glyphs->glyphs[0].geometry.y_offset)
++    rmoveto (NSToCoordRound (zoom * glyphs->glyphs[0].geometry.x_offset / PANGO_SCALE),
++             NSToCoordRound (zoom * glyphs->glyphs[0].geometry.y_offset / PANGO_SCALE));
++
++  fputc('<', mScriptFP);
++
++  for (i = 0; i < glyphs->num_glyphs; i++) {
++    PRUint32 glyph = glyphs->glyphs[i].glyph;
++    fprintf(mScriptFP, "%02x", aSubset->InSubsetIndexOf(glyph));
++    if (glyphs->glyphs[i].geometry.y_offset)
++      horiz = 0;
++  }
++
++  if (horiz) {
++    fputs(">\n[", mScriptFP);
++    for (i = 1; i < glyphs->num_glyphs; i++) {
++      fprintf(mScriptFP, "%d ",
++              NSToCoordRound (zoom * (+ glyphs->glyphs[i  ].geometry.x_offset
++                                      + glyphs->glyphs[i-1].geometry.width
++                                      - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE));
++    }
++    fprintf(mScriptFP, "%d",
++              NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width
++                                      - glyphs->glyphs[i-1].geometry.x_offset
++                                      - glyphs->glyphs[  0].geometry.x_offset) / PANGO_SCALE));
++    fputs("] xshow\n", mScriptFP);
++  } else {
++    fputs(">\n[", mScriptFP);
++    for (i = 1; i < glyphs->num_glyphs; i++) {
++      fprintf(mScriptFP, "%d %d ",
++              NSToCoordRound (zoom * (+ glyphs->glyphs[i  ].geometry.x_offset
++                                      + glyphs->glyphs[i-1].geometry.width
++                                      - glyphs->glyphs[i-1].geometry.x_offset) / PANGO_SCALE),
++              NSToCoordRound (zoom * (+ glyphs->glyphs[i  ].geometry.y_offset
++                                      - glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE));
++    }
++    fprintf(mScriptFP, "%d %d",
++              NSToCoordRound (zoom * (+ glyphs->glyphs[i-1].geometry.width
++                                      - glyphs->glyphs[i-1].geometry.x_offset
++                                      - glyphs->glyphs[  0].geometry.x_offset) / PANGO_SCALE),
++              NSToCoordRound (zoom * (- glyphs->glyphs[i-1].geometry.y_offset) / PANGO_SCALE));
++    fputs("] xyshow\n", mScriptFP);
+   }
+-  fputs("> show\n", mScriptFP);
+ }
+ #endif
+@@ -2101,6 +2144,16 @@ nsPostScriptObj::moveto(nscoord x, nscoo
+ /** ---------------------------------------------------
+  *  See documentation in nsPostScriptObj.h
++ *    @update 10/20/06 behdad
++ */
++void 
++nsPostScriptObj::rmoveto(nscoord x, nscoord y)
++{
++  fprintf(mScriptFP, "%d %d rmoveto\n", x, y);
++}
++
++/** ---------------------------------------------------
++ *  See documentation in nsPostScriptObj.h
+  *    @update 2/1/99 dwc
+  */
+ void 
+Index: gfx/src/ps/nsPostScriptObj.h
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsPostScriptObj.h,v
+retrieving revision 1.47
+diff -u -p -d -r1.47 nsPostScriptObj.h
+--- gfx/src/ps/nsPostScriptObj.h       8 May 2005 15:01:20 -0000       1.47
++++ gfx/src/ps/nsPostScriptObj.h       23 Oct 2006 17:37:30 -0000
+@@ -57,9 +57,15 @@
+ #include "nsIPersistentProperties2.h"
+ #include "nsTempfilePS.h"
+ #include "nsEPSObjectPS.h"
++#ifdef MOZ_ENABLE_PANGO
++#include <pango/pango.h>
++#endif
++
++class nsPSFontGenerator;
+ class nsIImage;
+ class nsIAtom;
++class nsValueArray;
+ #endif
+ #include <stdio.h>
+@@ -217,6 +223,14 @@ public:
+    */
+   void moveto(nscoord aX, nscoord aY);
+   /** ---------------------------------------------------
++   *  Move relative to the current point
++   *  @update 10/20/2006 behdad
++   *  @param  aX   X coordinate
++   *          aY   Y coordinate
++   *    @return VOID
++   */
++  void rmoveto(nscoord aX, nscoord aY);
++  /** ---------------------------------------------------
+    *  Add a line to the current path, from the current point
+    *  to the specified point.
+    *  @update 9/30/2003
+@@ -346,12 +360,24 @@ public:
+    */
+   void show(const PRUnichar* aText, int aLen, const char *aAlign, int aType);
+   /** ---------------------------------------------------
+-   *  This version takes a PRUnichar string, a font subset string
+-   *  for freetype printing and a subfont index
++   *  This version of show takes an array of glyphs, subfont and subfont index
++   *  to render and is used for freetype and xft printing.
+    *  @update 2/15/2005 jshin@mailaps.org
++   *    @update 6/7/2005 blizzard@mozilla.org
+    */
+-  void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList,
++  void show(const nsValueArray *aGlyphs, nsPSFontGenerator *aSubset,
+             PRUint16 aSubFontIdx);
++  /*void show(const PRUnichar* aText, int aLen, const nsAFlatString& aCharList,
++    PRUint16 aSubFontIdx); */
++#ifdef MOZ_ENABLE_PANGO
++  /** ---------------------------------------------------
++   *  This version of show takes a pango glyph string, subfont and subfont index
++   *  to render and is used for pango printing.
++   *  @update 10/20/2006 behdad@behdad.org
++   */
++  void show(const PangoGlyphString *glyphs, float zoom,
++            nsPSFontGenerator *aSubset, PRUint16 aSubFontIdx);
++#endif
+   /** ---------------------------------------------------
+    *  set the clipping path to the current path using the winding rule
+    *  @update 2/1/99 dwc
+Index: gfx/src/ps/nsRenderingContextPS.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.cpp,v
+retrieving revision 1.83
+diff -u -p -d -r1.83 nsRenderingContextPS.cpp
+--- gfx/src/ps/nsRenderingContextPS.cpp        4 Mar 2005 07:39:27 -0000       1.83
++++ gfx/src/ps/nsRenderingContextPS.cpp        23 Oct 2006 17:37:31 -0000
+@@ -251,6 +251,8 @@ nsRenderingContextPS :: GetDrawingSurfac
+ NS_IMETHODIMP
+ nsRenderingContextPS :: GetHints(PRUint32& aResult)
+ {
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  aResult = metrics->GetHints ();
+   return NS_OK;
+ }
+@@ -1006,8 +1008,11 @@ nsRenderingContextPS::GetTextDimensions(
+                                         nsTextDimensions& aLastWordDimensions,
+                                         PRInt32*          aFontID)
+ {
+-  NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions");
+-  return NS_ERROR_NOT_IMPLEMENTED;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
++                                   aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
+ }
+ NS_IMETHODIMP
+@@ -1021,43 +1026,31 @@ nsRenderingContextPS::GetTextDimensions(
+                                         nsTextDimensions& aLastWordDimensions,
+                                         PRInt32*          aFontID)
+ {
+-  NS_NOTYETIMPLEMENTED("nsRenderingContextPS::GetTextDimensions");
+-  return NS_ERROR_NOT_IMPLEMENTED;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetTextDimensions (aString, aLength, aAvailWidth, aBreaks, aNumBreaks,
++                                   aDimensions, aNumCharsFit, aLastWordDimensions, aFontID);
+ }
+ NS_IMETHODIMP
+ nsRenderingContextPS :: GetTextDimensions(const char* aString, PRUint32 aLength,
+                                           nsTextDimensions& aDimensions)
+ {
+-  nsresult rv = NS_ERROR_FAILURE;
+-
+-  if (mFontMetrics) {
+-    nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
+-    metrics->GetStringWidth(aString, aDimensions.width, aLength);
+-    metrics->GetMaxAscent(aDimensions.ascent);
+-    metrics->GetMaxDescent(aDimensions.descent);
+-    rv = NS_OK;
+-  }
+-  
+-  return rv;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetTextDimensions (aString, aLength, aDimensions);
+ }
+ NS_IMETHODIMP
+ nsRenderingContextPS :: GetTextDimensions(const PRUnichar* aString, PRUint32 aLength,
+                                           nsTextDimensions& aDimensions, PRInt32* aFontID)
+ {
+-  nsresult rv = NS_ERROR_FAILURE;
+-
+-  if (mFontMetrics) {
+-    nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
+-    metrics->GetStringWidth(aString, aDimensions.width, aLength);
+-     //XXX temporary - bug 96609
+-    metrics->GetMaxAscent(aDimensions.ascent);
+-    metrics->GetMaxDescent(aDimensions.descent);
+-    rv = NS_OK;
+-  }
+-
+-  return rv;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetTextDimensions (aString, aLength, aDimensions, aFontID);
+ }
+ /** ---------------------------------------------------
+@@ -1073,47 +1066,7 @@ nsRenderingContextPS :: DrawString(const
+   nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
+   NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
+-
+-  // When FT2 printing is enabled, we don't need to set langgroup
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
+-  if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) {
+-#endif
+-    nsCOMPtr<nsIAtom> langGroup;
+-    mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
+-    mPSObj->setlanggroup(langGroup);
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
+-  }
+-#endif
+-
+-  if (aLength == 0)
+-    return NS_OK;
+-  nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
+-  NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
+-  fontPS->SetupFont(this);
+-
+-  PRUint32 i, start = 0;
+-  for (i=0; i<aLength; i++) {
+-    nsFontPS* fontThisChar;
+-    fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics);
+-    NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
+-    if (fontThisChar != fontPS) {
+-      // draw text up to this point
+-      aX += DrawString(aString+start, i-start, aX, aY, fontPS, 
+-                       aSpacing?aSpacing+start:nsnull);
+-      start = i;
+-
+-      // setup for following text
+-      fontPS = fontThisChar;
+-      fontPS->SetupFont(this);
+-    }
+-  }
+-
+-  // draw the last part
+-  if (aLength-start)
+-    DrawString(aString+start, aLength-start, aX, aY, fontPS, 
+-               aSpacing?aSpacing+start:nsnull);
+-
+-  return NS_OK;
++  return metrics->DrawString (aString, aLength, aX, aY, aSpacing, this);
+ }
+ /** ---------------------------------------------------
+@@ -1129,110 +1082,7 @@ nsRenderingContextPS :: DrawString(const
+   
+   nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
+   NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
+-
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
+-  // When FT2 printing is enabled, we don't need to set langgroup
+-  if (!NS_REINTERPRET_CAST(nsDeviceContextPS *, mContext.get())->mFTPEnable) {
+-#endif
+-    nsCOMPtr<nsIAtom> langGroup = nsnull;
+-    mFontMetrics->GetLangGroup(getter_AddRefs(langGroup));
+-    mPSObj->setlanggroup(langGroup);
+-#if defined(MOZ_ENABLE_FREETYPE2) || defined(MOZ_ENABLE_XFT)
+-  }
+-#endif
+-
+-  /* build up conversion table */
+-  mPSObj->preshow(aString, aLength);
+-
+-  if (aLength == 0)
+-    return NS_OK;
+-  nsFontPS* fontPS = nsFontPS::FindFont(aString[0], metrics->Font(), metrics);
+-  NS_ENSURE_TRUE(fontPS, NS_ERROR_FAILURE);
+-  fontPS->SetupFont(this);
+-
+-  PRUint32 i, start = 0;
+-  for (i=0; i<aLength; i++) {
+-    nsFontPS* fontThisChar;
+-    fontThisChar = nsFontPS::FindFont(aString[i], metrics->Font(), metrics);
+-    NS_ENSURE_TRUE(fontThisChar, NS_ERROR_FAILURE);
+-    if (fontThisChar != fontPS) {
+-      // draw text up to this point
+-      aX += DrawString(aString+start, i-start, aX, aY, fontPS, 
+-                       aSpacing?aSpacing+start:nsnull);
+-      start = i;
+-
+-      // setup for following text
+-      fontPS = fontThisChar;
+-      fontPS->SetupFont(this);
+-    }
+-  }
+-
+-  // draw the last part
+-  if (aLength-start)
+-    DrawString(aString+start, aLength-start, aX, aY, fontPS, 
+-               aSpacing?aSpacing+start:nsnull);
+-
+-  return NS_OK;
+-}
+-
+-PRInt32 
+-nsRenderingContextPS::DrawString(const char *aString, PRUint32 aLength,
+-                                 nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
+-                                 const nscoord* aSpacing)
+-{
+-  nscoord width = 0;
+-  PRInt32 x = aX;
+-  PRInt32 y = aY;
+-
+-  PRInt32 dxMem[500];
+-  PRInt32* dx0 = 0;
+-  if (aSpacing) {
+-    dx0 = dxMem;
+-    if (aLength > 500) {
+-      dx0 = new PRInt32[aLength];
+-      NS_ENSURE_TRUE(dx0, NS_ERROR_OUT_OF_MEMORY);
+-    }
+-    mTranMatrix->ScaleXCoords(aSpacing, aLength, dx0);
+-  }
+-
+-  mTranMatrix->TransformCoord(&x, &y);
+-  width = aFontPS->DrawString(this, x, y, aString, aLength);
+-
+-  if ((aSpacing) && (dx0 != dxMem)) {
+-    delete [] dx0;
+-  }
+-
+-  return width;
+-}
+-
+-
+-PRInt32 
+-nsRenderingContextPS::DrawString(const PRUnichar *aString, PRUint32 aLength,
+-                                 nscoord aX, nscoord aY, nsFontPS* aFontPS,
+-                                 const nscoord* aSpacing)
+-{
+-  nscoord width = 0;
+-  PRInt32 x = aX;
+-  PRInt32 y = aY;
+-
+-  if (aSpacing) {
+-    // Slow, but accurate rendering
+-    const PRUnichar* end = aString + aLength;
+-    while (aString < end){
+-      x = aX;
+-      y = aY;
+-      mTranMatrix->TransformCoord(&x, &y);
+-      aFontPS->DrawString(this, x, y, aString, 1);
+-      aX += *aSpacing++;
+-      aString++;
+-    }
+-    width = aX;
+-  } else {
+-    mTranMatrix->TransformCoord(&x, &y);
+-    width = aFontPS->DrawString(this, x, y, aString, aLength);
+-  }
+-
+-  return width;
++  return metrics->DrawString (aString, aLength, aX, aY, aFontID, aSpacing, this);
+ }
+ /** ---------------------------------------------------
+@@ -1346,8 +1196,10 @@ nsRenderingContextPS::GetBoundingMetrics
+                                          PRUint32           aLength,
+                                          nsBoundingMetrics& aBoundingMetrics)
+ {
+-  // Fill me up 
+-  return NS_ERROR_NOT_IMPLEMENTED;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics);
+ }
+   /**
+@@ -1359,8 +1211,10 @@ nsRenderingContextPS::GetBoundingMetrics
+                                          nsBoundingMetrics& aBoundingMetrics,
+                                          PRInt32*           aFontID)
+ {
+-  // Fill me up 
+-  return NS_ERROR_NOT_IMPLEMENTED;
++  NS_ENSURE_TRUE(mFontMetrics, NS_ERROR_NULL_POINTER);
++  nsFontMetricsPS *metrics = NS_REINTERPRET_CAST(nsFontMetricsPS *, mFontMetrics.get());
++  NS_ENSURE_TRUE(metrics, NS_ERROR_FAILURE);
++  return metrics->GetBoundingMetrics (aString, aLength, aBoundingMetrics, aFontID);
+ }
+ #endif /* MOZ_MATHML */
+Index: gfx/src/ps/nsRenderingContextPS.h
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsRenderingContextPS.h,v
+retrieving revision 1.49
+diff -u -p -d -r1.49 nsRenderingContextPS.h
+--- gfx/src/ps/nsRenderingContextPS.h  20 Sep 2004 06:46:16 -0000      1.49
++++ gfx/src/ps/nsRenderingContextPS.h  23 Oct 2006 17:37:35 -0000
+@@ -154,6 +154,10 @@ public:
+   NS_IMETHOD GetWidth(const PRUnichar* aString, PRUint32 aLength,
+                       nscoord& aWidth, PRInt32 *aFontID);
++  nsTransform2D *GetTranMatrix() {
++    return mTranMatrix;
++  }
++
+   NS_IMETHOD DrawString(const char *aString, PRUint32 aLength,
+                         nscoord aX, nscoord aY,
+                         const nscoord* aSpacing);
+@@ -164,13 +168,6 @@ public:
+   NS_IMETHOD DrawString(const nsString& aString, nscoord aX, nscoord aY,
+                         PRInt32 aFontID,
+                         const nscoord* aSpacing);
+-protected:
+-  PRInt32 DrawString(const PRUnichar *aString, PRUint32 aLength,
+-                        nscoord aX, nscoord aY, nsFontPS* aFontPS,
+-                        const nscoord* aSpacing);
+-  PRInt32 DrawString(const char *aString, PRUint32 aLength,
+-                        nscoord &aX, nscoord &aY, nsFontPS* aFontPS,
+-                        const nscoord* aSpacing);
+ public:
+   NS_IMETHOD GetTextDimensions(const char* aString, PRUint32 aLength,
+Index: gfx/src/ps/nsType1.cpp
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.cpp,v
+retrieving revision 1.5.8.1
+diff -u -p -d -r1.5.8.1 nsType1.cpp
+--- gfx/src/ps/nsType1.cpp     19 Oct 2005 08:16:22 -0000      1.5.8.1
++++ gfx/src/ps/nsType1.cpp     23 Oct 2006 17:37:39 -0000
+@@ -73,8 +73,13 @@
+ #include "nsIFreeType2.h"
+ #include "nsServiceManagerUtils.h"
+ #endif
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
++#include FT_TYPE1_TABLES_H
++#endif
+ #include "nsPrintfCString.h"
+ #include "nsAutoBuffer.h"
++#include "nsValueArray.h"
++#include "nsVoidArray.h"
+ #define HEXASCII_LINE_LEN 64
+@@ -113,7 +118,7 @@ static void encryptAndHexOut(FILE *aFile
+                              const char *aBuf, PRInt32 aLen = -1);
+ static void charStringOut(FILE* aFile, PRUint32* aPos, PRUint16* aKey,
+                           const char *aStr, PRUint32 aLen, 
+-                          PRUnichar aId);
++                          const char *aGlyphName);
+ static void flattenName(nsCString& aString);
+ /* thunk a short name for this function */
+@@ -202,19 +207,30 @@ Type1EncryptString(unsigned char *aInBuf
+     aOutBuf[i] = Type1Encrypt(aInBuf[i], &key);
+ }
++static FT_UShort
++get_upm (FT_Face face)
++{
++  FT_UShort upm = face->units_per_EM;
++
++  if (!upm)
++    upm = 1000; // bitmap font or something
++
++  return upm;
++}
++
+ static PRBool
+ sideWidthAndBearing(const FT_Vector *aEndPt, FT2PT1_info *aFti)
+ {
+   int aw = 0;
+   int ah = 0;
+-  FT_UShort upm = aFti->face->units_per_EM;
++  FT_UShort upm = get_upm (aFti->face);
+   FT_GlyphSlot slot;
+   FT_Glyph glyph;
+   FT_BBox bbox;
+   slot = aFti->face->glyph;
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+   FT_Error error = FT_Get_Glyph(slot, &glyph);
+   if (error) {
+     NS_ERROR("sideWidthAndBearing failed to get glyph");
+@@ -256,7 +272,7 @@ static int
+ moveto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
+ {
+   FT2PT1_info *fti = (FT2PT1_info *)aClosure;
+-  FT_UShort upm = fti->face->units_per_EM;
++  FT_UShort upm = get_upm (fti->face);
+   PRBool rslt;
+   if (fti->elm_cnt == 0) {
+@@ -293,7 +309,7 @@ static int
+ lineto(nsFT_CONST FT_Vector *aEndPt, void *aClosure)
+ {
+   FT2PT1_info *fti = (FT2PT1_info *)aClosure;
+-  FT_UShort upm = fti->face->units_per_EM;
++  FT_UShort upm = get_upm (fti->face);
+   if (toCS(upm, aEndPt->x) == fti->cur_x) {
+     fti->len += ecsi(&fti->buf, toCS(upm, aEndPt->y) - (int)fti->cur_y);
+@@ -320,7 +336,7 @@ conicto(nsFT_CONST FT_Vector *aControlPt
+         void *aClosure)
+ {
+   FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
+-  FT_UShort upm = ftinfo->face->units_per_EM;
++  FT_UShort upm = get_upm (ftinfo->face);
+   double ctl_x, ctl_y;
+   double cur_x, cur_y, x3, y3;
+   FT_Vector aControlPt1, aControlPt2;
+@@ -353,7 +369,7 @@ cubicto(nsFT_CONST FT_Vector *aControlPt
+         nsFT_CONST FT_Vector *aEndPt, void *aClosure)
+ {
+   FT2PT1_info *ftinfo = (FT2PT1_info *)aClosure;
+-  FT_UShort upm = ftinfo->face->units_per_EM;
++  FT_UShort upm = get_upm (ftinfo->face);
+   double cur_x, cur_y, x1, y1, x2, y2, x3, y3;
+   cur_x = ftinfo->cur_x;
+@@ -408,8 +424,55 @@ static FT_Outline_Funcs ft_outline_funcs
+   0
+ };
++
++static int
++trace_bitmap_glyph (FT_GlyphSlot slot, FT2PT1_info *fti)
++{
++  unsigned char *row, *byte_ptr, byte;
++  int rows, cols;
++  int x, y, bit_mask;
++  int upm, x_off, y_off, x_mult, y_mult;
++
++  upm = get_upm (slot->face);
++  x_off = slot->bitmap_left;
++  y_off = slot->bitmap_top;
++  x_mult = upm / slot->face->size->metrics.x_ppem;
++  y_mult = upm / slot->face->size->metrics.y_ppem;
++
++  switch (slot->bitmap.pixel_mode) {
++  case FT_PIXEL_MODE_MONO:
++
++    for (y = 0, row = slot->bitmap.buffer, rows = slot->bitmap.rows; rows; row += slot->bitmap.pitch, rows--, y++) {
++      for (x = 0, byte_ptr = row, cols = (slot->bitmap.width + 7) / 8; cols; byte_ptr++, cols--) {
++          byte = *byte_ptr;
++          for (bit_mask = 128; bit_mask && x < slot->bitmap.width; bit_mask >>= 1, x++) {
++              if (byte & bit_mask) {
++                  FT_Vector p;
++                  p.x = x_mult * (x_off + x);
++                  p.y = y_mult * (y_off - y);
++                  moveto(&p, (void *) fti);
++                  p.x += x_mult;
++                  lineto(&p, (void *) fti);
++                  p.y += y_mult;
++                  lineto(&p, (void *) fti);
++                  p.x -= x_mult;
++                  lineto(&p, (void *) fti);
++              }
++          }
++      }
++    }
++    break;
++
++  default:
++    return 1;
++  }
++
++  return 0;
++}
++
++
+ FT_Error
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+ FT2GlyphToType1CharString(FT_Face aFace, PRUint32 aGlyphID,
+                           int aWmode, int aLenIV, unsigned char *aBuf)
+ #else
+@@ -423,7 +486,7 @@ FT2GlyphToType1CharString(nsIFreeType2 *
+   unsigned char *start = aBuf;
+   FT2PT1_info fti;
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+   FT_Error error = FT_Load_Glyph(aFace, aGlyphID, flags);
+   if (error) {
+     NS_ERROR("failed to load aGlyphID");
+@@ -438,11 +501,6 @@ FT2GlyphToType1CharString(nsIFreeType2 *
+ #endif
+   slot = aFace->glyph;
+-  if (slot->format != ft_glyph_format_outline) {
+-    NS_ERROR("aGlyphID is not an outline glyph");
+-    return 1;
+-  }
+-
+ #ifdef MOZ_ENABLE_FREETYPE2
+   fti.ft2     = aFt2;
+ #endif
+@@ -456,18 +514,27 @@ FT2GlyphToType1CharString(nsIFreeType2 *
+   for (j=0; j< aLenIV; j++) {
+     fti.len += ecsi(&fti.buf, 0);
+   }
+-#ifdef MOZ_ENABLE_XFT
+-  if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti))  {
+-    NS_ERROR("error decomposing aGlyphID");
+-    return 1;
+-  }
++
++  if (slot->format == ft_glyph_format_outline) {
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
++    if (FT_Outline_Decompose(&slot->outline, &ft_outline_funcs, &fti))  {
++      NS_ERROR("error decomposing aGlyphID");
++      return 1;
++    }
+ #else
+-  rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
+-  if (NS_FAILED(rv)) {
+-    NS_ERROR("error decomposing aGlyphID");
+-    return 1;
+-  }
++    rv = aFt2->OutlineDecompose(&slot->outline, &ft_outline_funcs, &fti);
++    if (NS_FAILED(rv)) {
++      NS_ERROR("error decomposing aGlyphID");
++    }
+ #endif
++  } else if (slot->format == ft_glyph_format_bitmap) {
++    /* ok, it's a bitmap glyph.  trace it! */
++    if (trace_bitmap_glyph (slot, &fti)) {
++      NS_ERROR("error tracing bitmap glyph");
++    }
++  } else {
++      NS_ERROR("aGlyphID has unhandled format");
++  }
+   if (fti.elm_cnt) {
+     fti.len += csc(&fti.buf, T1_CLOSEPATH);
+@@ -491,28 +558,52 @@ FT2GlyphToType1CharString(nsIFreeType2 *
+ }
+ static PRBool
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+ outputType1SubFont(FT_Face aFace,
+ #else
+ outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
+ #endif
+-                 const nsAString &aCharIDs, const char *aFontName,
+-                 int aWmode, int aLenIV, FILE *aFile);
++                   nsValueArray *aGlyphs,
++                   PRUint32 aOffset, PRUint32 aLen,
++                   const char *aFontName,
++                   int aWmode, int aLenIV, FILE *aFile);
+ nsresult
+ FT2ToType1FontName(FT_Face aFace, int aWmode, nsCString& aFontName)
+ {
++  // only hash the first 10 000 bytes of the font
++  int size = aFace->stream->size;
++  size = size > 10000 ? 10000 : size;
++
++  unsigned char *data;
++  if (aFace->stream->read) {
++    data = (unsigned char *) malloc (size);
++    aFace->stream->read (aFace->stream, 0, data, size);
++  } else {
++    data = aFace->stream->base;
++  }
++
++  unsigned int data_hash = 0;
++  int i;
++  for (i = 0; i < size; i++)
++    data_hash = (data_hash << 5) - data_hash + data[size];
++
++  if (aFace->stream->read)
++    free (data);
++
+   aFontName = aFace->family_name;
+   aFontName.AppendLiteral(".");
+   aFontName += aFace->style_name;
+-  aFontName += nsPrintfCString(".%ld.%d", aFace->face_index, aWmode ? 1 : 0);
++  aFontName += nsPrintfCString(".%ld.%d.%lx.%x", aFace->face_index, aWmode ? 1 : 0,
++                               (long) aFace->stream->size, data_hash);
+   flattenName(aFontName);
++
+   return NS_OK;
+ }
+ // output a subsetted truetype font converted to multiple type 1 fonts
+ PRBool
+-FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset,
++FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset,
+                         int aWmode,  FILE *aFile)
+ {
+ #ifdef MOZ_ENABLE_FREETYPE2
+@@ -527,32 +618,35 @@ FT2SubsetToType1FontSet(FT_Face aFace, c
+   nsCAutoString fontNameBase;
+   FT2ToType1FontName(aFace, aWmode, fontNameBase);
+   PRUint32 i = 0;
+-  for (; i <= aSubset.Length() / 255 ; i++) {
++  for (; i <= aGlyphSubset->Count() / 255 ; i++) {
+     nsCAutoString fontName(fontNameBase);
+     fontName.AppendLiteral(".Set");
+     fontName.AppendInt(i);
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+     outputType1SubFont(aFace,
+ #else
+     outputType1SubFont(ft2, aFace, 
+ #endif
+-      Substring(aSubset, i * 255, PR_MIN(255, aSubset.Length() - i * 255)),
+-      fontName.get(), aWmode, 4, aFile);
++                       aGlyphSubset,
++                       (i * 255), PR_MIN(255, aGlyphSubset->Count() - i * 255),
++                       fontName.get(), aWmode, 4, aFile);
+   }
+   return PR_TRUE;
+ }
+ // output a type 1 font (with 255 characters or fewer) 
+ static PRBool
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+ outputType1SubFont(FT_Face aFace,
+ #else
+ outputType1SubFont(nsIFreeType2 *aFt2, FT_Face aFace,
+ #endif
+-                 const nsAString& aCharIDs, const char *aFontName,
+-                 int aWmode, int aLenIV, FILE *aFile)
++                   nsValueArray *aGlyphs,
++                   PRUint32 aOffset, PRUint32 aLen,
++                   const char *aFontName,
++                   int aWmode, int aLenIV, FILE *aFile)
+ {
+-  FT_UShort upm = aFace->units_per_EM;
++  FT_UShort upm = get_upm (aFace);
+   fprintf(aFile, "%%%%BeginResource: font %s\n"
+                  "%%!PS-AdobeFont-1.0-3.0 %s 1.0\n"
+@@ -573,9 +667,13 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
+                  toCS(upm, aFace->bbox.xMax),
+                  toCS(upm, aFace->bbox.yMax));
+-  nsString charIDstr(aCharIDs);
+-  PRUint32 len = aCharIDs.Length();
+-  
++  nsValueArray glyphs(PR_UINT16_MAX);
++  nsCStringArray glyphnames(PR_UINT16_MAX);
++  glyphs = *aGlyphs;
++
++  PRUint32 len = aLen;
++  PRUint32 i;
++
+   if (len < 10) { 
+     // Add a small set of characters to the subset of the user
+     // defined font to produce to make sure the font ends up
+@@ -584,25 +682,47 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
+     // XXX : need to check if this is true of type 1 fonts as well.
+     // I suspect it's only the case of CID-keyed fonts (type 9) we used to
+     // generate. 
+-    charIDstr.AppendLiteral("1234567890"); 
++    for (i = 1; i <= 10; i++) {
++      glyphs.AppendValue(i);
++    }
+     len += 10;
+   }
+   
+-  const PRUnichar *charIDs = charIDstr.get();
+-
+-  PRUint32 i;
++  FT_Int has_glyph_name;
++#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO)
++  has_glyph_name = FT_Has_PS_Glyph_Names(aFace);
++#else
++  has_glyph_name = aFt2->hasPSGlyphNames(aFace);
++#endif
+   // construct an Encoding vector : the 0th element
+   // is /.notdef
+-  fputs("/Encoding [\n/.notdef\n", aFile); 
+-  for (i = 0; i < len; ++i) {
+-      fprintf(aFile, "/uni%04X", charIDs[i]); 
+-      if (i % 8 == 7) fputc('\n', aFile);
++  fputs("/Encoding [\n/.notdef", aFile); 
++  for (i = aOffset; i < aOffset + aLen; ++i) {
++      nsCString name;
++      char buffer[256];
++
++      if (glyphs.ValueAt(i) == 0) {
++        name = "/.notdef";
++      } else if (!has_glyph_name ||
++#if defined (MOZ_ENABLE_XFT) || defined (MOZ_ENABLE_PANGO)
++                 FT_Get_Glyph_Name(aFace, glyphs.ValueAt(i), buffer, 255) != FT_Err_Ok
++#else
++                 NS_FAILED(aFt2->getGlyphName(aFace, glyphs.ValueAt(i), buffer, 255))
++#endif
++      ) {
++        name = nsPrintfCString(256, "/idx%04X", glyphs.ValueAt(i));
++      } else {
++        name = nsPrintfCString(256, "/%s", buffer);
++      }
++      glyphnames.AppendCString(name);
++      fprintf(aFile, name.get());
++      if ((i-aOffset) % 8 == 6) fputc('\n', aFile);
+   }
+-  for (i = len; i < 255; ++i) {
++  for (i = PR_MAX (0, 255 - int(aLen)); i; --i) {
+       fputs("/.notdef", aFile);
+-      if (i % 8 == 7) fputc('\n', aFile);
++      if (i % 8 == 1) fputc('\n', aFile);
+   }
+   fputs("] def\n", aFile); 
+@@ -630,23 +750,21 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
+   // get the maximum charstring length without actually filling up the buffer
+   PRInt32 charStringLen;
+   PRInt32 maxCharStringLen =
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+     FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV, nsnull);
+ #else
+     FT2GlyphToType1CharString(aFt2, aFace, 0, aWmode, aLenIV, nsnull);
+ #endif
+-  PRUint32 glyphID;
+-
+-  for (i = 0; i < len; i++) {
+-#ifdef MOZ_ENABLE_XFT
+-    glyphID = FT_Get_Char_Index(aFace, charIDs[i]);
++  for (i = aOffset; i < aOffset + aLen; i++) {
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+     charStringLen =
+-      FT2GlyphToType1CharString(aFace, glyphID, aWmode, aLenIV, nsnull);
++      FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode, aLenIV,
++                                nsnull);
+ #else
+-    aFt2->GetCharIndex(aFace, charIDs[i], &glyphID);
+     charStringLen =
+-      FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode, aLenIV, nsnull);
++      FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i), aWmode, aLenIV,
++                                nsnull);
+ #endif
+     if (charStringLen > maxCharStringLen)
+@@ -666,7 +784,7 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
+                                    len + 1).get()); 
+   // output the notdef glyph
+-#ifdef MOZ_ENABLE_XFT
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
+   charStringLen = FT2GlyphToType1CharString(aFace, 0, aWmode, aLenIV,
+                                             charString.get());
+ #else
+@@ -676,22 +794,20 @@ outputType1SubFont(nsIFreeType2 *aFt2, F
+   // enclose charString with  "/.notdef RD .....  ND" 
+   charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()),
+-                charStringLen, 0); 
++                charStringLen, "/.notdef");
+   // output the charstrings for each glyph in this sub font
+-  for (i = 0; i < len; i++) {
+-#ifdef MOZ_ENABLE_XFT
+-    glyphID = FT_Get_Char_Index(aFace, charIDs[i]);
+-    charStringLen = FT2GlyphToType1CharString(aFace, glyphID, aWmode,
++  for (i = aOffset; i < aOffset + aLen; i++) {
++#if defined(MOZ_ENABLE_XFT) || defined(MOZ_ENABLE_PANGO)
++    charStringLen = FT2GlyphToType1CharString(aFace, glyphs.ValueAt(i), aWmode,
+                                               aLenIV, charString.get());
+ #else
+-    aFt2->GetCharIndex(aFace, charIDs[i], &glyphID);
+-    charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphID, aWmode,
+-                                              aLenIV, charString.get());
++    charStringLen = FT2GlyphToType1CharString(aFt2, aFace, glyphs.ValueAt(i),
++                                              aWmode, aLenIV, charString.get());
+ #endif
+     charStringOut(aFile, &pos, &key, NS_REINTERPRET_CAST(const char*, charString.get()),
+-                  charStringLen, charIDs[i]);
++                  charStringLen, glyphnames.CStringAt(i - aOffset)->get());
+   }
+   // wrap up the encrypted part of the font definition
+@@ -753,15 +869,12 @@ void encryptAndHexOut(FILE *aFile, PRUin
+ /* static */ 
+ void charStringOut(FILE* aFile,  PRUint32* aPos, PRUint16* aKey, 
+-                   const char *aStr, PRUint32 aLen, PRUnichar aId)
++                   const char *aStr, PRUint32 aLen, const char *aGlyphName)
+ {
+     // use a local buffer instead of nsPrintfCString to avoid alloc.
+     char buf[30];
+     int oLen;
+-    if (aId == 0)
+-      oLen = PR_snprintf(buf, 30, "/.notdef %d RD ", aLen); 
+-    else 
+-      oLen = PR_snprintf(buf, 30, "/uni%04X %d RD ", aId, aLen); 
++    oLen = PR_snprintf(buf, 30, "%s %d RD ", aGlyphName, aLen);
+     if (oLen >= 30) {
+       NS_WARNING("buffer size exceeded. charstring will be truncated");
+Index: gfx/src/ps/nsType1.h
+===================================================================
+RCS file: /cvsroot/mozilla/gfx/src/ps/nsType1.h,v
+retrieving revision 1.5
+diff -u -p -d -r1.5 nsType1.h
+--- gfx/src/ps/nsType1.h       4 Mar 2005 07:39:27 -0000       1.5
++++ gfx/src/ps/nsType1.h       23 Oct 2006 17:37:39 -0000
+@@ -122,8 +122,9 @@ FT_Error FT2GlyphToType1CharString(nsIFr
+ class nsString;
+ class nsCString;
++class nsValueArray;
+-PRBool FT2SubsetToType1FontSet(FT_Face aFace, const nsString& aSubset,
++PRBool FT2SubsetToType1FontSet(FT_Face aFace, nsValueArray *aGlyphSubset,
+                                int aWmode,  FILE *aFile);
+ nsresult FT2ToType1FontName(FT_Face aFace, int aWmode,
+                             nsCString& aFontName);
+Index: config/system-headers
+===================================================================
+--- config/system-headers      2006-10-26 12:21:39.000000000 -0400
++++ config/system-headers      2006-10-26 12:23:29.000000000 -0400
+@@ -199,6 +199,7 @@
+ freetype/ftoutln.h
+ freetype/ttnameid.h
+ freetype/tttables.h
++freetype/t1tables.h
+ fribidi/fribidi.h
+ FSp_fopen.h
+ fstream.h
+@@ -501,6 +503,7 @@
+ pango/pangofc-fontmap.h
+ pango/pango-fontmap.h
+ pango/pango.h
++pango/pangoft2.h
+ pango/pangoxft.h
+ pango/pangox.h
+ pango-types.h
+
diff --git a/mozilla-firefox-pango-underline.patch b/mozilla-firefox-pango-underline.patch
new file mode 100644 (file)
index 0000000..c6b8649
--- /dev/null
@@ -0,0 +1,39 @@
+diff -pruN -x '.moz*' -x .deps -x 'thunderbird*' -x '*.mk' -x 'config*' -x dist -x build -x toolkit -x '*o' -x '*a' -x '*html' mozilla.orig/layout/generic/nsTextFrame.cpp mozilla/layout/generic/nsTextFrame.cpp
+--- mozilla.orig/layout/generic/nsTextFrame.cpp        2006-12-20 12:53:26.000000000 +0900
++++ mozilla/layout/generic/nsTextFrame.cpp     2006-12-20 15:43:14.000000000 +0900
+@@ -2097,11 +2097,11 @@ nsTextFrame::PaintTextDecorations(nsIRen
+     nsRect rect = GetRect();
+     while(aDetails){
+       const nscoord* sp= aSpacing;
+-      PRInt32 startOffset = 0;
+-      PRInt32 textWidth = 0;
+-      PRInt32 start = PR_MAX(0,(aDetails->mStart - (PRInt32)aIndex));
+-      PRInt32 end = PR_MIN((PRInt32)aLength,(aDetails->mEnd - (PRInt32)aIndex));
+-      PRInt32 i;
++      PRUint32 startOffset = 0;
++      PRUint32 textWidth = 0;
++      PRInt32 start = PR_MAX(0,(aDetails->mStart - (PRInt32)aIndex));
++      PRInt32 end = PR_MIN((PRInt32)aLength,(aDetails->mEnd - (PRInt32)aIndex));
++      PRInt32 i;
+       if ((start < end) && ((aLength - start) > 0))
+       {
+         //aDetails allready processed to have offsets from frame start not content offsets
+@@ -2117,7 +2117,7 @@ nsTextFrame::PaintTextDecorations(nsIRen
+                 }
+               }
+               else
+-                aRenderingContext.GetWidth(aText, start, startOffset);
++                aRenderingContext.GetRangeWidth(aText, aLength, 0, start, startOffset);
+             }
+             if (sp){
+               for (i = start; i < end;i ++){
+@@ -2125,8 +2125,7 @@ nsTextFrame::PaintTextDecorations(nsIRen
+               }
+             }
+             else
+-              aRenderingContext.GetWidth(aText + start,
+-                                           PRUint32(end - start), textWidth);
++              aRenderingContext.GetRangeWidth(aText, aLength, start, end, textWidth);
+   
+           }
+           nscoord offset, size;
diff --git a/mozilla-firefox-prefs.patch b/mozilla-firefox-prefs.patch
new file mode 100644 (file)
index 0000000..e02c3f0
--- /dev/null
@@ -0,0 +1,99 @@
+diff -ur mozilla.orig/browser/app/profile/firefox.js mozilla/browser/app/profile/firefox.js
+--- mozilla.orig/browser/app/profile/firefox.js        2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/app/profile/firefox.js     2008-06-21 15:25:48.000000000 +0200
+@@ -89,12 +89,12 @@
+ // App-specific update preferences
+ // Whether or not app updates are enabled
+-pref("app.update.enabled", true);
++pref("app.update.enabled", false);
+ // This preference turns on app.update.mode and allows automatic download and
+ // install to take place. We use a separate boolean toggle for this to make
+ // the UI easier to construct.
+-pref("app.update.auto", true);
++pref("app.update.auto", false);
+ // Defines how the Application Update Service notifies the user about updates:
+ //
+@@ -186,7 +186,7 @@
+ // Whether or not the application should check at startup each time if it 
+ // is the default browser.
+-pref("browser.shell.checkDefaultBrowser", true);
++pref("browser.shell.checkDefaultBrowser", false);
+ // 0 = blank, 1 = home (browser.startup.homepage), 2 = last visited page, 3 = resume previous browser session
+ // The behavior of option 3 is detailed at: http://wiki.mozilla.org/Session_Restore
+@@ -445,7 +445,7 @@
+ pref("alerts.totalOpenTime", 4000);
+ pref("browser.xul.error_pages.enabled", true);
+-pref("browser.xul.error_pages.expert_bad_cert", false);
++pref("browser.xul.error_pages.expert_bad_cert", true);
+ // We want to make sure mail URLs are handled externally...
+ pref("network.protocol-handler.external.mailto", true); // for mail
+@@ -592,10 +592,10 @@
+ #ifdef MOZ_SAFE_BROWSING
+ // Safe browsing does nothing unless this pref is set
+-pref("browser.safebrowsing.enabled", true);
++pref("browser.safebrowsing.enabled", false);
+ // Prevent loading of pages identified as malware
+-pref("browser.safebrowsing.malware.enabled", true);
++pref("browser.safebrowsing.malware.enabled", false);
+ // Non-enhanced mode (local url lists) URL list to check for updates
+ pref("browser.safebrowsing.provider.0.updateURL", "http://safebrowsing.clients.google.com/safebrowsing/downloads?client={moz:client}&appver={moz:version}&pver=2.1");
+@@ -739,7 +739,7 @@
+ // 0 - don't pre-populate anything
+ // 1 - pre-populate site URL, but don't fetch certificate
+ // 2 - pre-populate site URL and pre-fetch certificate
+-pref("browser.ssl_override_behavior", 1);
++pref("browser.ssl_override_behavior", 2);
+ // Controls the display of domain in the identity box for SSL connections.
+ // 0 - do not show domain
+diff -ur mozilla.orig/browser/base/content/baseMenuOverlay.xul mozilla/browser/base/content/baseMenuOverlay.xul
+--- mozilla.orig/browser/base/content/baseMenuOverlay.xul      2008-06-21 12:55:29.000000000 +0200
++++ mozilla/browser/base/content/baseMenuOverlay.xul   2008-06-21 15:08:33.000000000 +0200
+@@ -97,12 +97,6 @@
+                   label="&helpReleaseNotes.label;"
+                   oncommand="openReleaseNotes(event)"
+                   onclick="checkForMiddleClick(this, event);"/>
+-        <menuseparator id="updateSeparator"/>
+-        <menuitem id="checkForUpdates"
+-                  accesskey="&updateCmd.accesskey;"
+-                  label="&updateCmd.label;"
+-                  class="menuitem-iconic"
+-                  oncommand="checkForUpdates();"/>
+         <menuseparator id="aboutSeparator"/>
+         <menuitem id="aboutName"
+                   accesskey="&aboutCmd.accesskey;"
+diff -ur mozilla.orig/browser/components/preferences/advanced.xul mozilla/browser/components/preferences/advanced.xul
+--- mozilla.orig/browser/components/preferences/advanced.xul   2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/components/preferences/advanced.xul        2008-06-21 16:01:22.000000000 +0200
+@@ -267,10 +267,6 @@
+         <tabpanel id="updatePanel" orient="vertical" align="start">
+           <label control="autoUpdateGroup">&autoCheck.label;</label>
+           <vbox class="indent" id="autoUpdateGroup" role="group">
+-            <checkbox id="enableAppUpdate"
+-                      label="&enableAppUpdate.label;"
+-                      accesskey="&enableAppUpdate.accesskey;"
+-                      preference="app.update.enabled"/>
+             <checkbox id="enableAddonUpdate"
+                       label="&enableAddonsUpdate.label;"
+                       accesskey="&enableAddonsUpdate.accesskey;"
+diff -ur mozilla.orig/browser/locales/en-US/chrome/overrides/netError.dtd mozilla/browser/locales/en-US/chrome/overrides/netError.dtd
+--- mozilla.orig/browser/locales/en-US/chrome/overrides/netError.dtd   2008-06-21 12:55:30.000000000 +0200
++++ mozilla/browser/locales/en-US/chrome/overrides/netError.dtd        2008-06-22 13:52:26.000000000 +0200
+@@ -175,6 +175,6 @@
+ <!ENTITY securityOverride.warningText "
+ <p>You should not add an exception if you are using an internet connection that you do not trust completely or if you are not used to seeing a warning for this server.</p>
+-<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='getMeOutOfHereButton' label='&securityOverride.getMeOutOfHereButton;'/>
+ <xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='exceptionDialogButton' label='&securityOverride.exceptionButtonLabel;'/>
++<xul:button xmlns:xul='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' id='getMeOutOfHereButton' label='&securityOverride.getMeOutOfHereButton;'/>
+ ">
diff --git a/mozilla-firefox-ti-agent.patch b/mozilla-firefox-ti-agent.patch
new file mode 100644 (file)
index 0000000..969b08a
--- /dev/null
@@ -0,0 +1,11 @@
+--- mozilla-firefox/browser/app/profile/firefox.js.orig        2007-03-21 17:21:55.000000000 +0100
++++ mozilla-firefox/browser/app/profile/firefox.js     2007-03-21 17:23:53.000000000 +0100
+@@ -163,6 +163,8 @@
+ pref("general.useragent.locale", "@AB_CD@");
+ pref("general.skins.selectedSkin", "classic/1.0");
+ pref("general.useragent.extra.firefox", "@APP_UA_NAME@/@APP_VERSION@");
++pref("general.useragent.vendor", "PLD");
++pref("general.useragent.vendorSub", "Titanium");
+ pref("general.smoothScroll", false);
+ #ifdef UNIX_BUT_NOT_MAC
diff --git a/mozilla-firefox-urls.patch b/mozilla-firefox-urls.patch
new file mode 100644 (file)
index 0000000..6a13b74
--- /dev/null
@@ -0,0 +1,19 @@
+--- mozilla/browser/app/firefox-branding.js~   2006-09-12 18:50:19.000000000 +0300
++++ mozilla/browser/app/firefox-branding.js    2008-10-03 11:14:14.032645886 +0300
+@@ -1,5 +1,5 @@
+-pref("startup.homepage_override_url","http://www.mozilla.org/projects/%APP%/%VERSION%/whatsnew/");
+-pref("startup.homepage_welcome_url","http://www.mozilla.org/projects/%APP%/%VERSION%/firstrun/");
++pref("startup.homepage_override_url","http://www.mozilla.com/%APP%/%VERSION%/releasenotes/");
++pref("startup.homepage_welcome_url","http://www.mozilla.com/%APP%/%VERSION%/firstrun/");
+ // URL user can browse to manually if for some reason all update installation
+ // attempts fail.
+ pref("app.update.url.manual", "http://www.mozilla.org/products/%APP%/");
+@@ -8,7 +8,7 @@
+ pref("app.update.url.details", "http://www.mozilla.org/projects/%APP%/");
+ // Release notes URL
+-pref("app.releaseNotesURL", "http://www.mozilla.org/projects/%APP%/%VERSION%/releasenotes/");
++pref("app.releaseNotesURL", "http://www.mozilla.com/%APP%/%VERSION%/releasenotes/");
+ // Search codes belong only in builds with official branding
+ pref("browser.search.param.yahoo-fr", "");
diff --git a/mozilla-firefox-xft-randewidth.patch b/mozilla-firefox-xft-randewidth.patch
new file mode 100644 (file)
index 0000000..1ecc5f2
--- /dev/null
@@ -0,0 +1,283 @@
+diff -pruN -x '.moz*' -x .libs -x .deps -x dist -x 'config*' -x 'firefox*' -x '*a' -x '*so' -x '*o' -x build -x '*html' mozilla.orig/gfx/src/gtk/nsFontMetricsXft.cpp mozilla/gfx/src/gtk/nsFontMetricsXft.cpp
+--- mozilla.orig/gfx/src/gtk/nsFontMetricsXft.cpp      2006-04-25 08:58:36.000000000 +0900
++++ mozilla/gfx/src/gtk/nsFontMetricsXft.cpp   2007-02-08 01:50:05.000000000 +0900
+@@ -227,10 +227,14 @@ static nsresult EnumFontsXft     (nsIAto
+ static        void ConvertCharToUCS4    (const char *aString,
+                                          PRUint32 aLength,
++                                         PRUint32 aStart,
++                                         PRUint32 aEnd,
+                                          nsAutoFcChar32Buffer &aOutBuffer,
+                                          PRUint32 *aOutLen);
+ static        void ConvertUnicharToUCS4 (const PRUnichar *aString,
+                                          PRUint32 aLength,
++                                         PRUint32 aStart,
++                                         PRUint32 aEnd,
+                                          nsAutoFcChar32Buffer &aOutBuffer,
+                                          PRUint32 *aOutLen);
+ static    nsresult ConvertUCS4ToCustom  (FcChar32 *aSrc, PRUint32 aSrcLen,
+@@ -507,7 +511,7 @@ nsFontMetricsXft::GetWidth(const PRUnich
+         return NS_OK;
+     }
+-    gint rawWidth = RawGetWidth(aString, aLength);
++    gint rawWidth = RawGetWidth(aString, aLength, 0, aLength);
+     float f;
+     f = mDeviceContext->DevUnitsToAppUnits();
+@@ -533,7 +537,7 @@ nsFontMetricsXft::GetTextDimensions(cons
+         return NS_OK;
+     nsresult rv;
+-    rv = EnumerateGlyphs(aString, aLength,
++    rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+                          &nsFontMetricsXft::TextDimensionsCallback,
+                          &aDimensions);
+@@ -608,7 +612,7 @@ nsFontMetricsXft::DrawString(const char 
+     nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
+     data.drawBuffer = &drawBuffer;
+-    return EnumerateGlyphs(aString, aLength,
++    return EnumerateGlyphs(aString, aLength, 0, aLength,
+                            &nsFontMetricsXft::DrawStringCallback, &data);
+ }
+@@ -638,7 +642,7 @@ nsFontMetricsXft::DrawString(const PRUni
+     nsAutoDrawSpecBuffer drawBuffer(data.draw, &data.color);
+     data.drawBuffer = &drawBuffer;
+-    return EnumerateGlyphs(aString, aLength,
++    return EnumerateGlyphs(aString, aLength, 0, aLength,
+                            &nsFontMetricsXft::DrawStringCallback, &data);
+ }
+@@ -662,7 +666,7 @@ nsFontMetricsXft::GetBoundingMetrics(con
+     data.firstTime = PR_TRUE; 
+     nsresult rv;
+-    rv = EnumerateGlyphs(aString, aLength,
++    rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+                          &nsFontMetricsXft::BoundingMetricsCallback, &data);
+     NS_ENSURE_SUCCESS(rv, rv);
+@@ -700,7 +704,7 @@ nsFontMetricsXft::GetBoundingMetrics(con
+     data.firstTime = PR_TRUE; 
+     nsresult rv;
+-    rv = EnumerateGlyphs(aString, aLength,
++    rv = EnumerateGlyphs(aString, aLength, 0, aLength,
+                          &nsFontMetricsXft::BoundingMetricsCallback, &data);
+     NS_ENSURE_SUCCESS(rv, rv);
+@@ -758,7 +762,17 @@ nsFontMetricsXft::GetRangeWidth(const PR
+                                 PRUint32 aEnd,
+                                 PRUint32 &aWidth)
+ {
+-    return NS_ERROR_NOT_IMPLEMENTED;
++    if (!aLength) {
++        aWidth = 0;
++        return NS_OK;
++    }
++
++    gint rawWidth = RawGetWidth(aText, aLength, aStart, aEnd);
++    float f = mDeviceContext->DevUnitsToAppUnits();
++
++    aWidth = NSToCoordRound(rawWidth * f);
++
++    return NS_OK;
+ }
+ nsresult
+@@ -768,7 +782,17 @@ nsFontMetricsXft::GetRangeWidth(const ch
+                                 PRUint32 aEnd,
+                                 PRUint32 &aWidth)
+ {
+-    return NS_ERROR_NOT_IMPLEMENTED;
++    if (!aLength) {
++        aWidth = 0;
++        return NS_OK;
++    }
++
++    gint rawWidth = RawGetWidth(aText, aLength, aStart, aEnd);
++    float f = mDeviceContext->DevUnitsToAppUnits();
++
++    aWidth = NSToCoordRound(rawWidth * f);
++
++    return NS_OK;
+ }
+ PRUint32
+@@ -850,12 +874,12 @@ nsFontMetricsXft::CacheFontMetrics(void)
+     // mSpaceWidth (width of a space)
+     gint rawWidth;
+     PRUnichar unispace(' ');
+-    rawWidth = RawGetWidth(&unispace, 1);
++    rawWidth = RawGetWidth(&unispace, 1, 0, 1);
+     mSpaceWidth = NSToCoordRound(rawWidth * f);
+     // mAveCharWidth (width of an 'average' char)
+     PRUnichar xUnichar('x');
+-    rawWidth = RawGetWidth(&xUnichar, 1);
++    rawWidth = RawGetWidth(&xUnichar, 1, 0, 1);
+     mAveCharWidth = NSToCoordRound(rawWidth * f);
+     // mXHeight (height of an 'x' character)
+@@ -1226,12 +1250,27 @@ nsFontMetricsXft::DoMatch(PRBool aMatchA
+ }
+ gint
+-nsFontMetricsXft::RawGetWidth(const PRUnichar* aString, PRUint32 aLength)
++nsFontMetricsXft::RawGetWidth(const PRUnichar* aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd)
++{
++    nscoord width = 0;
++    nsresult rv;
++
++    rv = EnumerateGlyphs(aString, aLength, aStart, aEnd,
++                         &nsFontMetricsXft::GetWidthCallback, &width);
++
++    if (NS_FAILED(rv))
++        width = 0;
++
++    return width;
++}
++
++gint
++nsFontMetricsXft::RawGetWidth(const char* aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd)
+ {
+     nscoord width = 0;
+     nsresult rv;
+-    rv = EnumerateGlyphs(aString, aLength,
++    rv = EnumerateGlyphs(aString, aLength, aStart, aEnd,
+                          &nsFontMetricsXft::GetWidthCallback, &width);
+     if (NS_FAILED(rv))
+@@ -1457,6 +1496,8 @@ nsFontMetricsXft::EnumerateXftGlyphs(con
+ nsresult
+ nsFontMetricsXft::EnumerateGlyphs(const PRUnichar *aString,
+                                   PRUint32 aLen,
++                                  PRUint32 aStart,
++                                  PRUint32 aEnd,
+                                   GlyphEnumeratorCallback aCallback,
+                                   void *aCallbackData)
+ {
+@@ -1465,7 +1506,7 @@ nsFontMetricsXft::EnumerateGlyphs(const 
+     NS_ENSURE_TRUE(aLen, NS_OK); 
+-    ConvertUnicharToUCS4(aString, aLen, charBuffer, &len);
++    ConvertUnicharToUCS4(aString, aLen, aStart, aEnd, charBuffer, &len);
+     if (!len)
+         return NS_ERROR_OUT_OF_MEMORY;
+@@ -1475,6 +1516,8 @@ nsFontMetricsXft::EnumerateGlyphs(const 
+ nsresult
+ nsFontMetricsXft::EnumerateGlyphs(const char *aString,
+                                   PRUint32 aLen,
++                                  PRUint32 aStart,
++                                  PRUint32 aEnd,
+                                   GlyphEnumeratorCallback aCallback,
+                                   void *aCallbackData)
+ {
+@@ -1484,7 +1527,7 @@ nsFontMetricsXft::EnumerateGlyphs(const 
+     NS_ENSURE_TRUE(aLen, NS_OK); 
+     // Convert the incoming string into an array of UCS4 chars
+-    ConvertCharToUCS4(aString, aLen, charBuffer, &len);
++    ConvertCharToUCS4(aString, aLen, aStart, aEnd, charBuffer, &len);
+     if (!len)
+         return NS_ERROR_OUT_OF_MEMORY;
+@@ -2343,7 +2386,7 @@ EnumFontsXft(nsIAtom* aLangGroup, const 
+ /* static */
+ void
+-ConvertCharToUCS4(const char *aString, PRUint32 aLength, 
++ConvertCharToUCS4(const char *aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd,
+                   nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
+ {
+     *aOutLen = 0;
+@@ -2352,19 +2395,21 @@ ConvertCharToUCS4(const char *aString, P
+     if (!aOutBuffer.EnsureElemCapacity(aLength))
+         return;
+     outBuffer  = aOutBuffer.get();
++    if (aEnd > aLength)
++        aEnd = aLength;
+     
+-    for (PRUint32 i = 0; i < aLength; ++i) {
+-        outBuffer[i] = PRUint8(aString[i]); // to convert char >= 0x80 correctly
++    for (PRUint32 i = aStart; i < aLength && i < aEnd; ++i) {
++        outBuffer[i - aStart] = PRUint8(aString[i]); // to convert char >= 0x80 correctly
+     }
+-    *aOutLen = aLength;
++    *aOutLen = aEnd - aStart;
+ }
+ // Convert the incoming string into an array of UCS4 chars
+   
+ /* static */
+ void
+-ConvertUnicharToUCS4(const PRUnichar *aString, PRUint32 aLength,
++ConvertUnicharToUCS4(const PRUnichar *aString, PRUint32 aLength, PRUint32 aStart, PRUint32 aEnd,
+                      nsAutoFcChar32Buffer &aOutBuffer, PRUint32 *aOutLen)
+ {
+     *aOutLen = 0;
+@@ -2378,7 +2423,7 @@ ConvertUnicharToUCS4(const PRUnichar *aS
+     // Walk the passed in string looking for surrogates to convert to
+     // their full ucs4 representation.
+-    for (PRUint32 i = 0; i < aLength; ++i) {
++    for (PRUint32 i = aStart; i < aLength && i < aEnd; ++i) {
+         PRUnichar c = aString[i];
+         // Optimized for the non-surrogate case
+@@ -2693,12 +2738,12 @@ ConvertUCS4ToCustom(FcChar32 *aSrc,  PRU
+ #endif
+         // Convert 16bit  custom font codes to UCS4
+         ConvertUnicharToUCS4(NS_REINTERPRET_CAST(PRUnichar *, med),
+-                             medLen >> 1, aResult, &aDestLen);
++                             medLen >> 1, 0, medLen >> 1, aResult, &aDestLen);
+         rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
+     }
+     else {
+         // Convert 8bit custom font codes to UCS4
+-        ConvertCharToUCS4(med, medLen, aResult, &aDestLen);
++        ConvertCharToUCS4(med, medLen, 0, medLen, aResult, &aDestLen);
+         rv = aDestLen ? rv : NS_ERROR_OUT_OF_MEMORY;
+     }
+diff -pruN -x '.moz*' -x .libs -x .deps -x dist -x 'config*' -x 'firefox*' -x '*a' -x '*so' -x '*o' -x build -x '*html' mozilla.orig/gfx/src/gtk/nsFontMetricsXft.h mozilla/gfx/src/gtk/nsFontMetricsXft.h
+--- mozilla.orig/gfx/src/gtk/nsFontMetricsXft.h        2005-05-03 05:48:30.000000000 +0900
++++ mozilla/gfx/src/gtk/nsFontMetricsXft.h     2007-02-08 01:38:27.000000000 +0900
+@@ -259,7 +259,13 @@ private:
+     void        DoMatch            (PRBool aMatchAll);
+     gint        RawGetWidth        (const PRUnichar* aString,
+-                                    PRUint32         aLength);
++                                    PRUint32         aLength,
++                                    PRUint32         aStart,
++                                    PRUint32         aEnd);
++    gint        RawGetWidth        (const char* aString,
++                                    PRUint32    aLength,
++                                    PRUint32    aStart,
++                                    PRUint32    aEnd);
+     nsresult    SetupMiniFont      (void);
+     nsresult    DrawUnknownGlyph   (FcChar32   aChar,
+                                     nscoord    aX,
+@@ -272,10 +278,14 @@ private:
+                                     void     *aCallbackData);
+     nsresult    EnumerateGlyphs    (const char *aString,
+                                     PRUint32  aLen,
++                                    PRUint32  aStart,
++                                    PRUint32  aEnd,
+                                     GlyphEnumeratorCallback aCallback,
+                                     void     *aCallbackData);
+     nsresult    EnumerateGlyphs    (const PRUnichar *aString,
+                                     PRUint32  aLen,
++                                    PRUint32  aStart,
++                                    PRUint32  aEnd,
+                                     GlyphEnumeratorCallback aCallback,
+                                     void     *aCallbackData);
+     void        PrepareToDraw      (nsRenderingContextGTK *aContext,
diff --git a/mozilla-firefox.desktop b/mozilla-firefox.desktop
new file mode 100644 (file)
index 0000000..0b92e93
--- /dev/null
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Name=Firefox Community Edition
+Name[pl]=Firefox Community Edition
+GenericName=Web Browser
+GenericName[pl]=Przeglądarka WWW
+Comment=Browse the Web powered by Mozilla technology
+Comment[pl]=Przeglądarka WWW oparta o technologię Mozilli
+Exec=mozilla-firefox
+Icon=mozilla-firefox
+Terminal=false
+Type=Application
+Categories=GTK;Network;WebBrowser;
+# vi: encoding=utf-8
diff --git a/mozilla-firefox.sh b/mozilla-firefox.sh
new file mode 100644 (file)
index 0000000..a8cc354
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+# based on script by (c) vip at linux.pl, wolf at pld-linux.org
+
+LIBDIR="@LIBDIR@/mozilla-firefox"
+
+MOZILLA_FIVE_HOME=$LIBDIR
+
+MOZARGS=
+MOZLOCALE="$(/usr/bin/locale | grep "^LC_MESSAGES=" | \
+               sed -e "s|LC_MESSAGES=||g" -e "s|\"||g" )"
+for MOZLANG in $(echo $LANGUAGE | tr ":" " ") $MOZLOCALE; do
+       eval MOZLANG="$(echo $MOZLANG | sed -e "s|_\([^.]*\).*|-\1|g")"
+
+       if [ -f $MOZILLA_FIVE_HOME/chrome/$MOZLANG.jar ]; then
+               MOZARGS="-UILocale $MOZLANG"
+               break
+       fi
+done
+
+if [ -z "$MOZARGS" ]; then
+       # try harder
+       for MOZLANG in $(echo $LANGUAGE | tr ":" " ") $MOZLOCALE; do
+               eval MOZLANG="$(echo $MOZLANG | sed -e "s|_.*||g")"
+
+               LANGFILE=$(echo ${MOZILLA_FIVE_HOME}/chrome/${MOZLANG}*.jar \
+                               | sed 's/\s.*//g' )
+               if [ -f "$LANGFILE" ]; then
+                       MOZLANG=$(basename "$LANGFILE" | sed 's/\.jar//')
+                       MOZARGS="-UILocale $MOZLANG"
+                       break
+               fi
+       done
+fi
+
+# compreg.dat and/or chrome.rdf will screw things up if it's from an
+# older version.  http://bugs.gentoo.org/show_bug.cgi?id=63999
+for f in ~/{.,.mozilla/}firefox/*/{compreg.dat,chrome.rdf,XUL.mfasl}; do
+       if [[ -f ${f} && ${f} -ot /usr/bin/mozilla-firefox ]]; then
+               echo "Removing ${f} leftover from older firefox"
+               rm -f "${f}"
+       fi
+done
+
+if [ -n "$MOZARGS" ]; then
+       FIREFOX="$LIBDIR/firefox $MOZARGS"
+else
+       FIREFOX="$LIBDIR/firefox"
+fi
+
+if [ "$1" == "-remote" ]; then
+       exec $FIREFOX "$@"
+else
+       PING=`$FIREFOX -remote 'ping()' 2>&1 >/dev/null`
+       if [ -n "$PING" ]; then
+               if [ -f "`pwd`/$1" ]; then
+                       exec $FIREFOX "file://`pwd`/$1"
+               else
+                       exec $FIREFOX "$@"
+               fi
+       else
+               if [ -z "$1" ]; then
+                       exec $FIREFOX -remote 'xfeDoCommand(openBrowser)'
+               elif [ "$1" == "-mail" ]; then
+                       exec $FIREFOX -remote 'xfeDoCommand(openInbox)'
+               elif [ "$1" == "-compose" ]; then
+                       exec $FIREFOX -remote 'xfeDoCommand(composeMessage)'
+               else
+                       if [ -f "`pwd`/$1" ]; then
+                               URL="file://`pwd`/$1"
+                       else
+                               URL="$1"
+                       fi
+                       grep browser.tabs.opentabfor.middleclick ~/.mozilla/firefox/*/prefs.js | grep true > /dev/null
+                       if [ $? -eq 0 ]; then
+                               exec $FIREFOX -new-tab "$URL"
+                       else
+                               exec $FIREFOX -new-window "$URL"
+                       fi
+               fi
+       fi
+fi
diff --git a/mozilla-firefox.spec b/mozilla-firefox.spec
new file mode 100644 (file)
index 0000000..0a028c7
--- /dev/null
@@ -0,0 +1,482 @@
+#
+# TODO:
+# - handle locales differently (runtime, since it's possible to do)
+# - see ftp://ftp.debian.org/debian/pool/main/m/mozilla-firefox/*diff*
+#   for hints how to make locales
+# - (12:22:58)  patrys:  can you also move _libdir/mozilla-firefox to just _libdir/firefox?
+#   (12:23:25)  patrys:  it's not like we ship official firefox
+# - fix wrapper script to allow playing with profiles (must not use -remote)
+#
+# Conditional build:
+%bcond_with    tests           # enable tests (whatever they check)
+%bcond_without gnomeui         # disable gnomeui support
+%bcond_without gnomevfs        # disable GNOME comp. (gconf+libgnome+gnomevfs) and gnomevfs ext.
+%bcond_without gnome           # disable all GNOME components (gnome+gnomeui+gnomevfs)
+%bcond_without kerberos        # disable krb5 support
+%bcond_with    xulrunner       # build with system xulrunner
+
+%if %{without gnome}
+%undefine      with_gnomeui
+%undefine      with_gnomevfs
+%endif
+
+Summary:       Firefox Community Edition web browser
+Summary(pl.UTF-8):     Firefox Community Edition - przeglądarka WWW
+Name:          mozilla-firefox
+Version:       3.0.10
+Release:       1
+License:       MPL 1.1 or GPL v2+ or LGPL v2.1+
+Group:         X11/Applications/Networking
+Source0:       ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/%{version}/source/firefox-%{version}-source.tar.bz2
+# Source0-md5: 1012e835a5c130d18479bccdee240640
+Source1:       %{name}.desktop
+Source2:       %{name}.sh
+Patch0:                %{name}-install.patch
+Patch1:                %{name}-gcc3.patch
+Patch2:                %{name}-agent.patch
+Patch3:                %{name}-agent-ac.patch
+Patch4:                %{name}-ti-agent.patch
+Patch5:                %{name}-branding.patch
+Patch6:                %{name}-prefs.patch
+Patch7:                %{name}-nss_cflags.patch
+URL:           http://www.mozilla.org/projects/firefox/
+%{?with_gnomevfs:BuildRequires:        GConf2-devel >= 1.2.1}
+BuildRequires: automake
+BuildRequires: cairo-devel >= 1.6.0
+BuildRequires: dbus-glib-devel >= 0.60
+BuildRequires: glib2-devel
+%{?with_gnomevfs:BuildRequires:        gnome-vfs2-devel >= 2.0}
+BuildRequires: gtk+2-devel >= 2:2.10
+%if "%{pld_release}" == "ac"
+%{?with_kerberos:BuildRequires:        heimdal-devel >= 0.7.1}
+%else
+%{?with_kerberos:BuildRequires:        krb5-devel}
+%endif
+BuildRequires: libIDL-devel >= 0.8.0
+%{?with_gnomevfs:BuildRequires:        libgnome-devel >= 2.0}
+%{?with_gnomeui:BuildRequires: libgnomeui-devel >= 2.2.0}
+BuildRequires: libjpeg-devel >= 6b
+BuildRequires: libpng(APNG)-devel >= 0.10
+BuildRequires: libpng-devel >= 1.2.7
+BuildRequires: libstdc++-devel
+BuildRequires: nspr-devel >= 1:4.7
+BuildRequires: nss-devel >= 1:3.12-2
+BuildRequires: pango-devel >= 1:1.10.0
+BuildRequires: perl-modules >= 5.004
+BuildRequires: pkgconfig
+BuildRequires: python-modules
+BuildRequires: sqlite3-devel >= 3.5.9
+BuildRequires: rpm >= 4.4.9-56
+BuildRequires: rpmbuild(macros) >= 1.453
+BuildRequires: startup-notification-devel
+%if "%{pld_release}" == "ac"
+BuildRequires: XFree86-devel
+%else
+BuildRequires: xorg-lib-libXext-devel
+BuildRequires: xorg-lib-libXft-devel >= 2.1
+BuildRequires: xorg-lib-libXinerama-devel
+BuildRequires: xorg-lib-libXp-devel
+BuildRequires: xorg-lib-libXt-devel
+%endif
+%if %{with xulrunner}
+BuildRequires: xulrunner-devel >= 1.9-2
+%endif
+BuildRequires: zip
+BuildRequires: zlib-devel >= 1.2.3
+Requires(post):        mktemp >= 1.5-18
+%if %{without xulrunner}
+Requires:      browser-plugins >= 2.0
+%endif
+Requires:      cairo >= 1.6.0
+Requires:      gtk+2 >= 2:2.10
+Requires:      libpng(APNG) >= 0.10
+Requires:      nspr >= 1:4.7
+Requires:      nss >= 1:3.12-2
+Requires:      pango >= 1:1.10.0
+Requires:      sqlite3 >= 3.5.9
+%if %{with xulrunner}
+%requires_eq_to        xulrunner xulrunner-devel
+%endif
+Provides:      wwwbrowser
+Obsoletes:     mozilla-firebird
+Obsoletes:     mozilla-firefox-lang-en < 2.0.0.8-3
+Obsoletes:     mozilla-firefox-libs
+BuildRoot:     %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+# don't satisfy other packages (don't use %{name} here)
+%define                _noautoprovfiles        %{_libdir}/mozilla-firefox
+# and as we don't provide them, don't require either
+%define                _noautoreq      libmozjs.so libxpcom.so libxul.so libjemalloc.so
+
+%if "%{cc_version}" >= "3.4"
+%define                specflags       -fno-strict-aliasing -fno-tree-vrp -fno-stack-protector
+%else
+%define                specflags       -fno-strict-aliasing
+%endif
+
+%description
+Firefox Community Edition is an open-source web browser, designed for
+standards compliance, performance and portability.
+
+%description -l pl.UTF-8
+Firefox Community Edition jest przeglądarką WWW rozpowszechnianą
+zgodnie z ideami ruchu otwartego oprogramowania oraz tworzoną z myślą
+o zgodności ze standardami, wydajnością i przenośnością.
+
+%prep
+%setup -qc -n %{name}-%{version}
+cd mozilla
+%patch0 -p1
+
+%if "%{cc_version}" < "3.4"
+%patch1 -p2
+%endif
+
+%if "%{pld_release}" == "th"
+%patch2 -p1
+%endif
+
+%if "%{pld_release}" == "ac"
+%patch3 -p1
+%endif
+
+%if "%{pld_release}" == "ti"
+%patch4 -p1
+%endif
+
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+
+%build
+cd mozilla
+cp -f %{_datadir}/automake/config.* build/autoconf
+cp -f %{_datadir}/automake/config.* nsprpub/build/autoconf
+
+cat << 'EOF' > .mozconfig
+. $topsrcdir/browser/config/mozconfig
+
+mk_add_options MOZ_OBJDIR=@TOPSRCDIR@/obj-%{_target_cpu}
+
+# Options for 'configure' (same as command-line options).
+ac_add_options --prefix=%{_prefix}
+ac_add_options --exec-prefix=%{_exec_prefix}
+ac_add_options --bindir=%{_bindir}
+ac_add_options --sbindir=%{_sbindir}
+ac_add_options --sysconfdir=%{_sysconfdir}
+ac_add_options --datadir=%{_datadir}
+ac_add_options --includedir=%{_includedir}
+ac_add_options --libdir=%{_libdir}
+ac_add_options --libexecdir=%{_libexecdir}
+ac_add_options --localstatedir=%{_localstatedir}
+ac_add_options --sharedstatedir=%{_sharedstatedir}
+ac_add_options --mandir=%{_mandir}
+ac_add_options --infodir=%{_infodir}
+%if %{?debug:1}0
+ac_add_options --disable-optimize
+ac_add_options --enable-debug
+ac_add_options --enable-debug-modules
+ac_add_options --enable-debugger-info-modules
+ac_add_options --enable-crash-on-assert
+%else
+ac_add_options --disable-debug
+ac_add_options --disable-debug-modules
+ac_add_options --disable-logging
+ac_add_options --enable-optimize="%{rpmcflags} -Os"
+%endif
+%if %{with tests}
+ac_add_options --enable-tests
+%else
+ac_add_options --disable-tests
+%endif
+%if %{with gnomeui}
+ac_add_options --enable-gnomeui
+%else
+ac_add_options --disable-gnomeui
+%endif
+%if %{with gnomevfs}
+ac_add_options --enable-gnomevfs
+%else
+ac_add_options --disable-gnomevfs
+%endif
+ac_add_options --disable-crashreporter
+ac_add_options --disable-installer
+ac_add_options --disable-javaxpcom
+ac_add_options --disable-updater
+ac_add_options --disable-strip
+ac_add_options --disable-xprint
+ac_add_options --enable-startup-notification
+ac_add_options --enable-svg
+ac_add_options --enable-system-cairo
+ac_add_options --enable-system-sqlite
+ac_add_options --enable-libxul
+ac_add_options --enable-xinerama
+ac_add_options --with-distribution-id=org.pld-linux
+%if %{with xulrunner}
+ac_add_options --with-libxul-sdk=%{_libdir}/xulrunner-sdk
+%endif
+ac_add_options --with-pthreads
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-nspr
+ac_add_options --with-system-nss
+ac_add_options --with-system-png
+ac_add_options --with-system-zlib
+ac_add_options --with-default-mozilla-five-home=%{_libdir}/%{name}
+EOF
+
+%{__make} -j1 -f client.mk build \
+       STRIP="/bin/true" \
+       CC="%{__cc}" \
+       CXX="%{__cxx}"
+
+%install
+rm -rf $RPM_BUILD_ROOT
+cd mozilla
+install -d \
+       $RPM_BUILD_ROOT{%{_bindir},%{_sbindir},%{_libdir}} \
+       $RPM_BUILD_ROOT{%{_pixmapsdir},%{_desktopdir}} \
+       $RPM_BUILD_ROOT%{_datadir}/%{name}
+
+%if %{without xulrunner}
+%browser_plugins_add_browser %{name} -p %{_libdir}/%{name}/plugins
+%endif
+
+%{__make} -C obj-%{_target_cpu}/browser/installer stage-package \
+       DESTDIR=$RPM_BUILD_ROOT \
+       MOZ_PKG_APPDIR=%{_libdir}/%{name} \
+       PKG_SKIP_STRIP=1
+
+# move arch independant ones to datadir
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/chrome $RPM_BUILD_ROOT%{_datadir}/%{name}/chrome
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/defaults $RPM_BUILD_ROOT%{_datadir}/%{name}/defaults
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/extensions $RPM_BUILD_ROOT%{_datadir}/%{name}/extensions
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/icons $RPM_BUILD_ROOT%{_datadir}/%{name}/icons
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/modules $RPM_BUILD_ROOT%{_datadir}/%{name}/modules
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/searchplugins $RPM_BUILD_ROOT%{_datadir}/%{name}/searchplugins
+%if %{without xulrunner}
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/greprefs $RPM_BUILD_ROOT%{_datadir}/%{name}/greprefs
+mv $RPM_BUILD_ROOT%{_libdir}/%{name}/res $RPM_BUILD_ROOT%{_datadir}/%{name}/res
+%endif
+ln -s ../../share/%{name}/chrome $RPM_BUILD_ROOT%{_libdir}/%{name}/chrome
+ln -s ../../share/%{name}/defaults $RPM_BUILD_ROOT%{_libdir}/%{name}/defaults
+ln -s ../../share/%{name}/extensions $RPM_BUILD_ROOT%{_libdir}/%{name}/extensions
+ln -s ../../share/%{name}/modules $RPM_BUILD_ROOT%{_libdir}/%{name}/modules
+ln -s ../../share/%{name}/icons $RPM_BUILD_ROOT%{_libdir}/%{name}/icons
+ln -s ../../share/%{name}/searchplugins $RPM_BUILD_ROOT%{_libdir}/%{name}/searchplugins
+%if %{without xulrunner}
+ln -s ../../share/%{name}/greprefs $RPM_BUILD_ROOT%{_libdir}/%{name}/greprefs
+ln -s ../../share/%{name}/res $RPM_BUILD_ROOT%{_libdir}/%{name}/res
+%endif
+
+%if %{without xulrunner}
+rm -rf $RPM_BUILD_ROOT%{_libdir}/%{name}/dictionaries
+ln -s %{_datadir}/myspell $RPM_BUILD_ROOT%{_libdir}/%{name}/dictionaries
+%endif
+
+sed 's,@LIBDIR@,%{_libdir},' %{SOURCE2} > $RPM_BUILD_ROOT%{_bindir}/mozilla-firefox
+ln -s mozilla-firefox $RPM_BUILD_ROOT%{_bindir}/firefox
+
+install browser/base/branding/icon64.png $RPM_BUILD_ROOT%{_pixmapsdir}/mozilla-firefox.png
+
+install %{SOURCE1} $RPM_BUILD_ROOT%{_desktopdir}/%{name}.desktop
+
+# files created by regxpcom and firefox -register
+touch $RPM_BUILD_ROOT%{_libdir}/%{name}/components/compreg.dat
+touch $RPM_BUILD_ROOT%{_libdir}/%{name}/components/xpti.dat
+
+# what's this? it's content is invalid anyway.
+rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/dependentlibs.list
+rm -f $RPM_BUILD_ROOT%{_libdir}/%{name}/old-homepage-default.properties
+
+cat << 'EOF' > $RPM_BUILD_ROOT%{_sbindir}/%{name}-chrome+xpcom-generate
+#!/bin/sh
+umask 022
+rm -f %{_libdir}/%{name}/components/{compreg,xpti}.dat
+
+# it attempts to touch files in $HOME/.mozilla
+# beware if you run this with sudo!!!
+export HOME=$(mktemp -d)
+# also TMPDIR could be pointing to sudo user's homedir
+unset TMPDIR TMP || :
+
+#LD_LIBRARY_PATH=%{_libdir}/%{name}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} %{_libdir}/%{name}/regxpcom
+%{_libdir}/%{name}/firefox -register
+
+rm -rf $HOME
+EOF
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%pretrans
+if [ -d %{_libdir}/%{name}/dictionaries ] && [ ! -L %{_libdir}/%{name}/dictionaries ]; then
+       mv -v %{_libdir}/%{name}/dictionaries{,.rpmsave}
+fi
+for d in chrome defaults extensions greprefs icons res searchplugins; do
+       if [ -d %{_libdir}/%{name}/$d ] && [ ! -L %{_libdir}/%{name}/$d ]; then
+               install -d %{_datadir}/%{name}
+               mv %{_libdir}/%{name}/$d %{_datadir}/%{name}/$d
+       fi
+done
+exit 0
+
+%post
+%{_sbindir}/%{name}-chrome+xpcom-generate
+%if %{without xulrunner}
+%update_browser_plugins
+%endif
+
+%postun
+%if %{without xulrunner}
+if [ "$1" = 0 ]; then
+       %update_browser_plugins
+fi
+%endif
+
+%files
+%defattr(644,root,root,755)
+%attr(755,root,root) %{_bindir}/%{name}
+%attr(755,root,root) %{_bindir}/firefox
+%attr(755,root,root) %{_sbindir}/%{name}-chrome+xpcom-generate
+
+%if %{without xulrunner}
+# browser plugins v2
+%{_browserpluginsconfdir}/browsers.d/%{name}.*
+%config(noreplace) %verify(not md5 mtime size) %{_browserpluginsconfdir}/blacklist.d/%{name}.*.blacklist
+%endif
+
+%dir %{_libdir}/%{name}
+%attr(755,root,root) %{_libdir}/%{name}/libjemalloc.so
+%if %{without xulrunner}
+%attr(755,root,root) %{_libdir}/%{name}/libmozjs.so
+%attr(755,root,root) %{_libdir}/%{name}/libxpcom.so
+%attr(755,root,root) %{_libdir}/%{name}/libxul.so
+%endif
+%{_libdir}/%{name}/blocklist.xml
+
+%if %{with crashreporter}
+%{_libdir}/%{name}/crashreporter
+%{_libdir}/%{name}/crashreporter-override.ini
+%{_libdir}/%{name}/crashreporter.ini
+%{_libdir}/%{name}/Throbber-small.gif
+%endif
+
+# config?
+%{_libdir}/%{name}/.autoreg
+%{_libdir}/%{name}/application.ini
+
+%dir %{_libdir}/%{name}/components
+
+%{_libdir}/%{name}/components/aboutRights.js
+%{_libdir}/%{name}/components/aboutRobots.js
+%{_libdir}/%{name}/components/FeedConverter.js
+%{_libdir}/%{name}/components/FeedWriter.js
+%{_libdir}/%{name}/components/WebContentConverter.js
+%{_libdir}/%{name}/components/browser.xpt
+%{_libdir}/%{name}/components/fuelApplication.js
+%{_libdir}/%{name}/components/nsBrowserContentHandler.js
+%{_libdir}/%{name}/components/nsBrowserGlue.js
+%{_libdir}/%{name}/components/nsMicrosummaryService.js
+%{_libdir}/%{name}/components/nsPlacesTransactionsService.js
+%{_libdir}/%{name}/components/nsSafebrowsingApplication.js
+%{_libdir}/%{name}/components/nsSearchService.js
+%{_libdir}/%{name}/components/nsSearchSuggestions.js
+%{_libdir}/%{name}/components/nsSessionStartup.js
+%{_libdir}/%{name}/components/nsSessionStore.js
+%{_libdir}/%{name}/components/nsSetDefaultBrowser.js
+%{_libdir}/%{name}/components/nsSidebar.js
+%if %{without xulrunner}
+%{_libdir}/%{name}/platform.ini
+%{_libdir}/%{name}/components/FeedProcessor.js
+%{_libdir}/%{name}/components/jsconsole-clhandler.js
+%{_libdir}/%{name}/components/nsAddonRepository.js
+%{_libdir}/%{name}/components/nsBadCertHandler.js
+%{_libdir}/%{name}/components/nsBlocklistService.js
+%{_libdir}/%{name}/components/nsContentDispatchChooser.js
+%{_libdir}/%{name}/components/nsContentPrefService.js
+%{_libdir}/%{name}/components/nsDefaultCLH.js
+%{_libdir}/%{name}/components/nsDownloadManagerUI.js
+%{_libdir}/%{name}/components/nsExtensionManager.js
+%{_libdir}/%{name}/components/nsFilePicker.js
+%{_libdir}/%{name}/components/nsHandlerService.js
+%{_libdir}/%{name}/components/nsHelperAppDlg.js
+%{_libdir}/%{name}/components/nsLivemarkService.js
+%{_libdir}/%{name}/components/nsLoginInfo.js
+%{_libdir}/%{name}/components/nsLoginManager.js
+%{_libdir}/%{name}/components/nsLoginManagerPrompter.js
+%{_libdir}/%{name}/components/nsProxyAutoConfig.js
+%{_libdir}/%{name}/components/nsTaggingService.js
+%{_libdir}/%{name}/components/nsTryToClose.js
+%{_libdir}/%{name}/components/nsURLFormatter.js
+%{_libdir}/%{name}/components/nsUpdateService.js
+%{_libdir}/%{name}/components/nsUrlClassifierLib.js
+%{_libdir}/%{name}/components/nsUrlClassifierListManager.js
+%{_libdir}/%{name}/components/nsWebHandlerApp.js
+%{_libdir}/%{name}/components/pluginGlue.js
+%{_libdir}/%{name}/components/storage-Legacy.js
+%{_libdir}/%{name}/components/txEXSLTRegExFunctions.js
+%endif
+
+%attr(755,root,root) %{_libdir}/%{name}/components/libbrowsercomps.so
+%attr(755,root,root) %{_libdir}/%{name}/components/libbrowserdirprovider.so
+%if %{without xulrunner}
+%attr(755,root,root) %{_libdir}/%{name}/components/libdbusservice.so
+%attr(755,root,root) %{_libdir}/%{name}/components/libimgicon.so
+%endif
+
+%if %{with gnomevfs}
+%if %{without xulrunner}
+%attr(755,root,root) %{_libdir}/%{name}/components/libmozgnome.so
+%endif
+%attr(755,root,root) %{_libdir}/%{name}/components/libnkgnomevfs.so
+%endif
+
+%attr(755,root,root) %{_libdir}/%{name}/*.sh
+%attr(755,root,root) %{_libdir}/%{name}/firefox
+%if %{without xulrunner}
+%attr(755,root,root) %{_libdir}/%{name}/firefox-bin
+%dir %{_libdir}/%{name}/plugins
+%attr(755,root,root) %{_libdir}/%{name}/plugins/*.so
+%attr(755,root,root) %{_libdir}/%{name}/mozilla-xremote-client
+%endif
+%{_pixmapsdir}/mozilla-firefox.png
+%{_desktopdir}/mozilla-firefox.desktop
+
+# symlinks
+%{_libdir}/%{name}/chrome
+%{_libdir}/%{name}/defaults
+%{_libdir}/%{name}/extensions
+%{_libdir}/%{name}/icons
+%{_libdir}/%{name}/modules
+%{_libdir}/%{name}/searchplugins
+%if %{without xulrunner}
+%{_libdir}/%{name}/dictionaries
+%{_libdir}/%{name}/greprefs
+%{_libdir}/%{name}/res
+%endif
+
+# browserconfig
+%{_libdir}/%{name}/browserconfig.properties
+
+%{_libdir}/%{name}/README.txt
+
+%dir %{_datadir}/%{name}
+%{_datadir}/%{name}/chrome
+%{_datadir}/%{name}/defaults
+%{_datadir}/%{name}/icons
+%{_datadir}/%{name}/modules
+%{_datadir}/%{name}/searchplugins
+%if %{without xulrunner}
+%{_datadir}/%{name}/greprefs
+%{_datadir}/%{name}/res
+%endif
+
+%dir %{_datadir}/%{name}/extensions
+# -dom-inspector subpackage?
+#%{_datadir}/%{name}/extensions/inspector@mozilla.org
+# the signature of the default theme
+%{_datadir}/%{name}/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}
+
+# files created by regxpcom and firefox -register
+%ghost %{_libdir}/%{name}/components/compreg.dat
+%ghost %{_libdir}/%{name}/components/xpti.dat
diff --git a/mozilla-install.patch b/mozilla-install.patch
new file mode 100644 (file)
index 0000000..5610bb5
--- /dev/null
@@ -0,0 +1,29 @@
+--- mozilla/toolkit/mozapps/installer/packager.mk~     2006-12-23 03:31:40.882927000 +0200
++++ mozilla/toolkit/mozapps/installer/packager.mk      2006-12-23 03:38:32.302235167 +0200
+@@ -301,7 +301,7 @@
+ # NOTE: this must be a tar now that dist links into the tree so that we
+ # do not strip the binaries actually in the tree.
+       @echo "Creating package directory..."
+-      @mkdir $(DIST)/$(MOZ_PKG_APPNAME)
++      @mkdir $(DESTDIR)$(MOZ_PKG_APPDIR)
+ ifdef MOZ_PKG_MANIFEST
+       $(RM) -rf $(DIST)/xpt
+       $(PERL) -I$(topsrcdir)/xpinstall/packager -e 'use Packager; \
+@@ -316,7 +316,7 @@
+       @cd $(DIST) && rsync -auv --copy-unsafe-links $(_APPNAME) $(MOZ_PKG_APPNAME)
+ endif
+ else
+-      @cd $(DIST)/bin && tar $(TAR_CREATE_FLAGS) - * | (cd ../$(MOZ_PKG_APPNAME); tar -xf -)
++      cp -rfLp $(DIST)/bin/* $(DESTDIR)$(MOZ_PKG_APPDIR)
+ endif # DMG
+ endif # MOZ_PKG_MANIFEST
+ ifndef PKG_SKIP_STRIP
+@@ -348,7 +348,7 @@
+ endif
+       @echo "Removing unpackaged files..."
+ ifdef NO_PKG_FILES
+-      cd $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME)$(_BINPATH); rm -rf $(NO_PKG_FILES)
++      cd $(DESTDIR)$(MOZ_PKG_APPDIR)$(_BINPATH); rm -rf $(NO_PKG_FILES)
+ endif
+ ifdef MOZ_PKG_REMOVALS
+       $(SYSINSTALL) $(MOZ_PKG_REMOVALS_GEN) $(DIST)/$(STAGEPATH)$(MOZ_PKG_APPNAME)$(_BINPATH)
This page took 0.861335 seconds and 4 git commands to generate.