[dfb,422221] Gtk/DirectFB port core; patches from dfb tree, r=vlad
authorVladimir Vukicevic <vladimir@pobox.com>
Wed, 06 Aug 2008 13:48:55 -0700
changeset 16526 a7b2f76a6ab8bae160d508f9f5b33ab7952ed53e
parent 16525 44089683e77dc62d631b36d231c3a0564d4650d4
child 16527 c07f8b1888748655b8707eb5bf4b3667b3f7faa2
push idunknown
push userunknown
push dateunknown
reviewersvlad
bugs422221
milestone1.9.1a2pre
[dfb,422221] Gtk/DirectFB port core; patches from dfb tree, r=vlad
configure.in
gfx/src/thebes/nsSystemFontsGTK2.cpp
gfx/src/thebes/nsThebesDeviceContext.cpp
gfx/src/thebes/nsThebesRenderingContext.cpp
gfx/thebes/public/Makefile.in
gfx/thebes/public/gfxDirectFBSurface.h
gfx/thebes/public/gfxFT2Fonts.h
gfx/thebes/public/gfxPlatformGtk.h
gfx/thebes/src/Makefile.in
gfx/thebes/src/gfxASurface.cpp
gfx/thebes/src/gfxDirectFBSurface.cpp
gfx/thebes/src/gfxFT2Fonts.cpp
gfx/thebes/src/gfxPlatformGtk.cpp
--- a/configure.in
+++ b/configure.in
@@ -960,17 +960,17 @@ MOZ_ZLIB_CFLAGS=
 MOZ_ZLIB_LIBS='$(call EXPAND_LIBNAME_PATH,mozz,$(DEPTH)/modules/zlib/src)'
 MOZ_BZ2_CFLAGS=
 MOZ_BZ2_LIBS='$(call EXPAND_LIBNAME_PATH,bz2,$(DEPTH)/modules/libbz2/src)'
 MOZ_PNG_CFLAGS=
 MOZ_PNG_LIBS='$(call EXPAND_LIBNAME_PATH,mozpng,$(DEPTH)/modules/libimg/png)'
 
 MOZ_JS_LIBS='-L$(LIBXUL_DIST)/bin -lmozjs'
 DYNAMIC_XPCOM_LIBS='-L$(LIBXUL_DIST)/bin -lxpcom -lxpcom_core'
-MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin'
+MOZ_FIX_LINK_PATHS='-Wl,-rpath-link,$(LIBXUL_DIST)/bin -Wl,-rpath-link,$(PREFIX)/lib'
 XPCOM_FROZEN_LDOPTS='-L$(LIBXUL_DIST)/bin -lxpcom'
 LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) -lxul'
 XPCOM_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue_s.$(LIB_SUFFIX) $(XPCOM_FROZEN_LDOPTS)'
 XPCOM_STANDALONE_GLUE_LDOPTS='$(LIBXUL_DIST)/lib/$(LIB_PREFIX)xpcomglue.$(LIB_SUFFIX)'
 
 MOZ_COMPONENT_NSPR_LIBS='-L$(LIBXUL_DIST)/bin $(NSPR_LIBS)'
 MOZ_XPCOM_OBSOLETE_LIBS='-L$(LIBXUL_DIST)/lib -lxpcom_compat'
 
@@ -4703,37 +4703,36 @@ MOZ_ARG_HEADER(Toolkit Options)
                           Select default toolkit
                           Platform specific defaults:
                             BeOS - cairo-beos
                             Mac OS X - cairo-cocoa
                             Neutrino/QNX - photon
                             OS/2 - cairo-os2
                             Win32 - cairo-windows
                             WinCE - windows
+                            Gtk2 with DirectFB - cairo-gtk2-dfb
                             * - cairo-gtk2],
     [ _DEFAULT_TOOLKIT=$enableval ],
     [ _DEFAULT_TOOLKIT=$_PLATFORM_DEFAULT_TOOLKIT])
 
     if test "$_DEFAULT_TOOLKIT" = "photon" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-windows" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2" \
+        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-dfb" \
+        -o "$_DEFAULT_TOOLKIT" = "cairo-gtk2-x11" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-beos" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-os2" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-mac" \
         -o "$_DEFAULT_TOOLKIT" = "cairo-cocoa"
     then
         dnl nglayout only supports building with one toolkit,
         dnl so ignore everything after the first comma (",").
         MOZ_WIDGET_TOOLKIT=`echo "$_DEFAULT_TOOLKIT" | sed -e "s/,.*$//"`
     else
-        if test "$no_x" != "yes"; then
-            AC_MSG_ERROR([Toolkit must be cairo-gtk2.])
-        else
-            AC_MSG_ERROR([Toolkit must be $_PLATFORM_DEFAULT_TOOLKIT (if supported).])
-        fi
+        AC_MSG_ERROR([You must specify a default toolkit (perhaps $_PLATFORM_DEFAULT_TOOLKIT).])
     fi
 
 AC_DEFINE_UNQUOTED(MOZ_DEFAULT_TOOLKIT,"$MOZ_WIDGET_TOOLKIT")
 
 dnl ========================================================
 dnl = Enable the toolkit as needed                         =
 dnl ========================================================
 
@@ -4743,25 +4742,47 @@ photon)
 	AC_DEFINE(MOZ_WIDGET_PHOTON)
     ;;
 
 cairo-windows)
     MOZ_WIDGET_TOOLKIT=windows
     MOZ_GFX_TOOLKIT=cairo
     ;;
 
-cairo-gtk2)
+cairo-gtk2|cairo-gtk2-x11)
     MOZ_WIDGET_TOOLKIT=gtk2
     MOZ_GFX_TOOLKIT=cairo
     MOZ_ENABLE_GTK2=1
     MOZ_ENABLE_XREMOTE=1
+
+    AC_DEFINE(MOZ_X11)
+    MOZ_X11=1
+
     TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
     TK_LIBS='$(MOZ_GTK2_LIBS)'
     AC_DEFINE(MOZ_WIDGET_GTK2)
     ;;
+
+cairo-gtk2-dfb)
+    MOZ_WIDGET_TOOLKIT=gtk2
+    MOZ_GFX_TOOLKIT=cairo
+    MOZ_ENABLE_GTK2=1
+
+    AC_DEFINE(MOZ_DFB)
+    MOZ_DFB=1
+
+    TK_CFLAGS='$(MOZ_GTK2_CFLAGS)'
+    TK_LIBS='$(MOZ_GTK2_LIBS)'
+    AC_DEFINE(MOZ_WIDGET_GTK2)
+    if test "$no_x" != "yes"; then
+        AC_MSG_WARN([Disabling X when DirectFB is specified.])
+        no_x=yes
+    fi
+    ;;
+
 cairo-beos)
     MOZ_WIDGET_TOOLKIT=beos
     MOZ_GFX_TOOLKIT=cairo
     TK_CFLAGS='$(MOZ_CAIRO_CFLAGS)'
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     ;;
 
 cairo-os2)
@@ -4791,20 +4812,27 @@ cairo-mac|cairo-cocoa)
     ;;
 esac
 
 if test "$MOZ_ENABLE_XREMOTE"; then
     AC_DEFINE(MOZ_ENABLE_XREMOTE)
 fi
 
 if test "$COMPILE_ENVIRONMENT"; then
-if test "$MOZ_ENABLE_GTK2"
-then
-    PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 gdk-x11-2.0 glib-2.0 gobject-2.0)
-fi
+  if test "$MOZ_ENABLE_GTK2"; then
+    if test "$MOZ_X11"; then
+      GDK_PACKAGES=gdk-x11-2.0
+    elif test "$MOZ_DFB"; then
+      PKG_CHECK_MODULES(MOZ_DFB, directfb >= 1.1.0)
+      GDK_PACKAGES=directfb
+    fi
+
+    PKG_CHECK_MODULES(MOZ_GTK2, gtk+-2.0 >= $GTK2_VERSION gtk+-unix-print-2.0 glib-2.0 gobject-2.0 $GDK_PACKAGES)
+  fi
+
 fi # COMPILE_ENVIRONMENT
 
 AC_SUBST(MOZ_DEFAULT_TOOLKIT)
 
 dnl ========================================================
 dnl = startup-notification support module
 dnl ========================================================
 
@@ -4848,21 +4876,17 @@ AC_SUBST(MOZ_ENABLE_PHOTON)
 AC_SUBST(MOZ_ENABLE_COCOA)
 AC_SUBST(MOZ_ENABLE_GLITZ)
 AC_SUBST(MOZ_ENABLE_XREMOTE)
 AC_SUBST(MOZ_GTK2_CFLAGS)
 AC_SUBST(MOZ_GTK2_LIBS)
 
 AC_SUBST(MOC)
 
-if test "$MOZ_ENABLE_GTK2"
-then
-    AC_DEFINE(MOZ_X11)
-    MOZ_X11=1
-fi
+AC_SUBST(MOZ_DFB)
 AC_SUBST(MOZ_X11)
 
 dnl ========================================================
 dnl =
 dnl = Components & Features
 dnl = 
 dnl ========================================================
 MOZ_ARG_HEADER(Components and Features)
@@ -4967,29 +4991,57 @@ MOZ_ARG_WITH_STRING(distribution-id,
 
 if test -z "$MOZ_DISTRIBUTION_ID"; then
    MOZ_DISTRIBUTION_ID="org.mozilla"
 fi
 
 AC_DEFINE_UNQUOTED(MOZ_DISTRIBUTION_ID,"$MOZ_DISTRIBUTION_ID")
 AC_SUBST(MOZ_DISTRIBUTION_ID)
 
+
+dnl ========================================================
+dnl complex text support off by default
+dnl ========================================================
+MOZ_PANGO=1
+MOZ_ARG_DISABLE_BOOL(pango,
+[  --disable-pango Disable usage of Pango ],
+    MOZ_PANGO=,
+    MOZ_PANGO=1)
+
+
 dnl ========================================================
 dnl = Xft and Pango
 dnl ========================================================
 if test "$MOZ_ENABLE_GTK2"
 then
-    PKG_CHECK_MODULES(MOZ_XFT, xft)
-    AC_SUBST(MOZ_XFT_CFLAGS)
-    AC_SUBST(MOZ_XFT_LIBS)
+    if test "$MOZ_X11"; then
+        PKG_CHECK_MODULES(MOZ_XFT, xft)
+        AC_SUBST(MOZ_XFT_CFLAGS)
+        AC_SUBST(MOZ_XFT_LIBS)
+    fi
+
+    AC_SUBST(MOZ_PANGO)
 
     PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION)
-    PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangocairo >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION)
-    AC_SUBST(MOZ_PANGO_CFLAGS)
-    AC_SUBST(MOZ_PANGO_LIBS)
+
+    if test "$MOZ_PANGO"
+    then
+        PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangocairo >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION)
+        AC_SUBST(MOZ_PANGO_CFLAGS)
+        AC_SUBST(MOZ_PANGO_LIBS)
+        AC_DEFINE(MOZ_PANGO)
+    else
+        PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION)
+        AC_SUBST(MOZ_PANGO_CFLAGS)
+        AC_SUBST(MOZ_PANGO_LIBS)
+
+        PKG_CHECK_MODULES(FT2, freetype2 > 6.1.0 fontconfig)
+        AC_SUBST(FT2_CFLAGS)
+        AC_SUBST(FT2_LIBS)
+    fi
 fi
 
 dnl ========================================================
 dnl = PostScript print module
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(postscript,
 [  --disable-postscript    Disable PostScript printing support ],
     MOZ_ENABLE_POSTSCRIPT=,
--- a/gfx/src/thebes/nsSystemFontsGTK2.cpp
+++ b/gfx/src/thebes/nsSystemFontsGTK2.cpp
@@ -40,28 +40,28 @@
 #include <stdlib.h>
 
 #include "nsIDeviceContext.h"
 #include "nsIRenderingContext.h"
 #include "prlink.h"
 
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
-#include <gdk/gdkx.h>
 
+#ifdef MOZ_PANGO
 #include <pango/pango.h>
-#include <pango/pangox.h>
 #include <pango/pango-fontmap.h>
+#endif
 
 #include <fontconfig/fontconfig.h>
 #include "nsSystemFontsGTK2.h"
 #include "gfxPlatformGtk.h"
 
 // Glue to avoid build/runtime dependencies on Pango > 1.6
-#ifndef THEBES_USE_PANGO_CAIRO
+#if defined(MOZ_PANGO) && !defined(THEBES_USE_PANGO_CAIRO)
 static gboolean
 (* PTR_pango_font_description_get_size_is_absolute)(PangoFontDescription*)
     = nsnull;
 
 static void InitPangoLib()
 {
     static PRBool initialized = PR_FALSE;
     if (initialized)
@@ -96,22 +96,24 @@ MOZ_pango_font_description_get_size_is_a
 static inline void InitPangoLib()
 {
 }
 
 static inline void ShutdownPangoLib()
 {
 }
 
+#ifdef MOZ_PANGO
 static inline gboolean
 MOZ_pango_font_description_get_size_is_absolute(PangoFontDescription *desc)
 {
     pango_font_description_get_size_is_absolute(desc);
 }
 #endif
+#endif
 
 nsSystemFontsGTK2::nsSystemFontsGTK2()
   : mDefaultFontName(NS_LITERAL_STRING("sans-serif"))
   , mButtonFontName(NS_LITERAL_STRING("sans-serif"))
   , mFieldFontName(NS_LITERAL_STRING("sans-serif"))
   , mMenuFontName(NS_LITERAL_STRING("sans-serif"))
 {
     InitPangoLib();
@@ -185,16 +187,17 @@ nsSystemFontsGTK2::~nsSystemFontsGTK2()
 {
     ShutdownPangoLib();
 }
 
 nsresult
 nsSystemFontsGTK2::GetSystemFontInfo(GtkWidget *aWidget, nsString *aFontName,
                                      gfxFontStyle *aFontStyle) const
 {
+#ifdef MOZ_PANGO
     GtkSettings *settings = gtk_widget_get_settings(aWidget);
 
     aFontStyle->style       = FONT_STYLE_NORMAL;
 
     gchar *fontname;
     g_object_get(settings, "gtk-font-name", &fontname, NULL);
 
     PangoFontDescription *desc;
@@ -220,16 +223,28 @@ nsSystemFontsGTK2::GetSystemFontInfo(Gtk
     }
 
     // |size| is now pixels
 
     aFontStyle->size = size;
   
     pango_font_description_free(desc);
 
+#else
+    /* FIXME: DFB FT2 Hardcoding the system font info for now.. */
+    aFontStyle->style       = FONT_STYLE_NORMAL;
+    aFontStyle->systemFont = PR_TRUE;
+
+    NS_NAMED_LITERAL_STRING(fontname, "\"Sans\"");
+    *aFontName = fontname;
+    aFontStyle->weight = 400;
+    aFontStyle->size = 40/3;
+
+#endif
+
     return NS_OK;
 }
 
 nsresult
 nsSystemFontsGTK2::GetSystemFont(nsSystemFontID anID, nsString *aFontName,
                                  gfxFontStyle *aFontStyle) const
 {
     switch (anID) {
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -50,21 +50,24 @@
 #ifdef MOZ_ENABLE_GTK2
 // for getenv
 #include <cstdlib>
 // for round
 #include <cmath>
 
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
-#include <gdk/gdkx.h>
+
 #include "nsFont.h"
 
 #include <pango/pango.h>
+#ifdef MOZ_X11
+#include <gdk/gdkx.h>
 #include <pango/pangox.h>
+#endif /* MOZ_X11 */
 #include <pango/pango-fontmap.h>
 #endif /* GTK2 */
 
 #include "gfxImageSurface.h"
 
 #ifdef MOZ_ENABLE_GTK2
 #include "nsSystemFontsGTK2.h"
 #include "gfxPDFSurface.h"
@@ -87,17 +90,17 @@ static nsSystemFontsBeOS *gSystemFonts =
 #include "nsSystemFontsMac.h"
 #include "gfxQuartzSurface.h"
 #include "gfxImageSurface.h"
 static nsSystemFontsMac *gSystemFonts = nsnull;
 #else
 #error Need to declare gSystemFonts!
 #endif
 
-#ifdef MOZ_ENABLE_GTK2
+#if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11)
 extern "C" {
 static int x11_error_handler (Display *dpy, XErrorEvent *err) {
     NS_ASSERTION(PR_FALSE, "X Error");
     return 0;
 }
 }
 #endif
 
@@ -266,17 +269,17 @@ nsThebesDeviceContext::SetDPI()
 NS_IMETHODIMP
 nsThebesDeviceContext::Init(nsNativeWidget aWidget)
 {
     mWidget = aWidget;
 
     SetDPI();
 
 
-#ifdef MOZ_ENABLE_GTK2
+#if defined(MOZ_ENABLE_GTK2) && defined(MOZ_X11)
     if (getenv ("MOZ_X_SYNC")) {
         PR_LOG (gThebesGFXLog, PR_LOG_DEBUG, ("+++ Enabling XSynchronize\n"));
         XSynchronize (gdk_x11_get_default_xdisplay(), True);
         XSetErrorHandler(x11_error_handler);
     }
 
 #endif
 
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -969,17 +969,17 @@ nsThebesRenderingContext::GetTextDimensi
                                                     nsTextDimensions& aDimensions,
                                                     PRInt32* aFontID)
 {
   mFontMetrics->GetMaxAscent(aDimensions.ascent);
   mFontMetrics->GetMaxDescent(aDimensions.descent);
   return GetWidth(aString, aLength, aDimensions.width, aFontID);
 }
 
-#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS) || defined(XP_MACOSX)
+#if defined(_WIN32) || defined(XP_OS2) || defined(MOZ_X11) || defined(XP_BEOS) || defined(XP_MACOSX) || defined (MOZ_DFB)
 NS_IMETHODIMP
 nsThebesRenderingContext::GetTextDimensionsInternal(const char*       aString,
                                                     PRInt32           aLength,
                                                     PRInt32           aAvailWidth,
                                                     PRInt32*          aBreaks,
                                                     PRInt32           aNumBreaks,
                                                     nsTextDimensions& aDimensions,
                                                     PRInt32&          aNumCharsFit,
--- a/gfx/thebes/public/Makefile.in
+++ b/gfx/thebes/public/Makefile.in
@@ -48,18 +48,32 @@ EXPORTS	+=	gfxWindowsFonts.h \
 EXPORTS +=	gfxPDFSurface.h
 
 ifdef MOZ_ENABLE_GLITZ
 REQUIRES += glitzwgl
 endif
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-EXPORTS +=      gfxXlibSurface.h gfxPlatformGtk.h gfxXlibNativeRenderer.h
-EXPORTS +=	gfxPangoFonts.h
+
+ifdef MOZ_X11
+EXPORTS += gfxXlibSurface.h
+endif
+
+ifdef MOZ_PANGO 
+EXPORTS += gfxPangoFonts.h
+else
+EXPORTS += gfxFT2Fonts.h
+endif
+
+ifdef MOZ_DFB
+EXPORTS += gfxDirectFBSurface.h
+endif
+
+EXPORTS +=  gfxPlatformGtk.h gfxGdkNativeRenderer.h
 EXPORTS +=	gfxPDFSurface.h gfxPSSurface.h
 
 ifdef MOZ_ENABLE_GLITZ
 REQUIRES += glitzglx
 endif
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),os2)
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxDirectFBSurface.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 DirectFB Thebes code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 GFX_DIRECTFBSURFACE_H
+#define GFX_DIRECTFBSURFACE_H
+
+#include "gfxASurface.h"
+
+extern "C" {
+#include "direct/messages.h"
+
+typedef struct _IDirectFB IDirectFB;
+typedef struct _IDirectFBSurface IDirectFBSurface;
+
+}
+
+class THEBES_API gfxDirectFBSurface : public gfxASurface {
+public:
+    gfxDirectFBSurface(IDirectFB *dfb, IDirectFBSurface *surface);
+    gfxDirectFBSurface(IDirectFBSurface *surface);
+    gfxDirectFBSurface(cairo_surface_t *csurf);
+
+    gfxDirectFBSurface(const gfxIntSize& size, gfxImageFormat format);
+
+    virtual ~gfxDirectFBSurface();
+
+    IDirectFB* DirectFB() { return mDFB; }
+    IDirectFBSurface* DirectFBSurface() { return mDFBSurface; }
+
+protected:
+    IDirectFB *mDFB;
+    IDirectFBSurface *mDFBSurface;
+};
+
+#endif /* GFX_DIRECTFBSURFACE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxFT2Fonts.h
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@mozilla.com>
+ *   Masayuki Nakano <masayuki@d-toybox.com>
+ *
+ * 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 GFX_GTKDFBFONTS_H
+#define GFX_GTKDFBFONTS_H
+
+#include "cairo.h"
+#include "gfxTypes.h"
+#include "gfxFont.h"
+#include "gfxContext.h"
+#include "gfxFontUtils.h"
+
+typedef struct FT_FaceRec_* FT_Face;
+
+/**
+ * FontFamily is a class that describes one of the fonts on the users system.  It holds
+ * each FontEntry (maps more directly to a font face) which holds font type, charset info
+ * and character map info.
+ */
+class FontEntry;
+class FontFamily
+{
+public:
+    THEBES_INLINE_DECL_REFCOUNTING(FontFamily)
+
+    FontFamily(const nsAString& aName) :
+        mName(aName) { }
+
+    FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
+
+public:
+    nsTArray<nsRefPtr<FontEntry> > mFaces;
+    nsString mName;
+};
+
+class FontEntry
+{
+public:
+    THEBES_INLINE_DECL_REFCOUNTING(FontEntry)
+
+    FontEntry(const nsString& aFaceName) : 
+        mFontFace(nsnull), mFaceName(aFaceName), mFTFontIndex(0), mUnicodeFont(PR_FALSE), mSymbolFont(PR_FALSE)
+    { }
+
+    FontEntry(const FontEntry& aFontEntry);
+    ~FontEntry();
+
+    const nsString& GetName() const {
+        return mFaceName;
+    }
+
+    cairo_font_face_t *CairoFontFace();
+
+    cairo_font_face_t *mFontFace;
+
+    nsString mFaceName;
+    nsCString mFilename;
+    PRUint8 mFTFontIndex;
+
+    PRPackedBool mUnicodeFont : 1;
+    PRPackedBool mSymbolFont  : 1;
+    PRPackedBool mTrueType    : 1;
+    PRPackedBool mIsType1     : 1;
+    PRPackedBool mItalic      : 1;
+    PRUint16 mWeight;
+
+    gfxSparseBitSet mCharacterMap;
+};
+
+
+
+class gfxFT2Font : public gfxFont {
+public: // new functions
+    gfxFT2Font(FontEntry *aFontEntry,
+               const gfxFontStyle *aFontStyle);
+    virtual ~gfxFT2Font ();
+
+    virtual const gfxFont::Metrics& GetMetrics();
+
+    cairo_font_face_t *CairoFontFace();
+    cairo_scaled_font_t *CairoScaledFont();
+
+    virtual PRBool SetupCairoFont(gfxContext *aContext);
+    virtual nsString GetUniqueName();
+    virtual PRUint32 GetSpaceGlyph();
+
+    FontEntry *GetFontEntry() { return mFontEntry; }
+private:
+    cairo_scaled_font_t *mScaledFont;
+
+    PRBool mHasSpaceGlyph;
+    PRUint32 mSpaceGlyph;
+    PRBool mHasMetrics;
+    Metrics mMetrics;
+    gfxFloat mAdjustedSize;
+
+    nsRefPtr<FontEntry> mFontEntry;
+};
+
+class THEBES_API gfxFT2FontGroup : public gfxFontGroup {
+public: // new functions
+    gfxFT2FontGroup (const nsAString& families,
+                    const gfxFontStyle *aStyle);
+    virtual ~gfxFT2FontGroup ();
+
+    inline gfxFT2Font *GetFontAt (PRInt32 i) {
+        return static_cast <gfxFT2Font *>(static_cast <gfxFont *>(mFonts[i]));
+    }
+
+protected: // from gfxFontGroup
+    virtual gfxTextRun *MakeTextRun(const PRUnichar *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
+    virtual gfxTextRun *MakeTextRun(const PRUint8 *aString, 
+                                    PRUint32 aLength,
+                                    const Parameters *aParams, 
+                                    PRUint32 aFlags);
+
+    virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
+
+
+protected: // new functions
+    void InitTextRun(gfxTextRun *aTextRun);
+
+    void CreateGlyphRunsFT(gfxTextRun *aTextRun);
+    void AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnichar *str, PRUint32 len);
+
+    static PRBool FontCallback (const nsAString & fontName, 
+                                const nsACString & genericName, 
+                                void *closure);
+    PRBool mEnableKerning;
+
+    gfxFT2Font *FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont);
+    PRUint32 ComputeRanges();
+
+    struct TextRange {
+        TextRange(PRUint32 aStart,  PRUint32 aEnd) : start(aStart), end(aEnd) { }
+        PRUint32 Length() const { return end - start; }
+        nsRefPtr<gfxFT2Font> font;
+        PRUint32 start, end;
+    };
+
+    nsTArray<TextRange> mRanges;
+    nsString mString;
+};
+
+#endif /* GFX_GTKDFBFONTS_H */
+
--- a/gfx/thebes/public/gfxPlatformGtk.h
+++ b/gfx/thebes/public/gfxPlatformGtk.h
@@ -34,21 +34,30 @@
  * 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 GFX_PLATFORM_GTK_H
 #define GFX_PLATFORM_GTK_H
 
-#include <gdk/gdkx.h>
-
 #include "gfxPlatform.h"
 
+extern "C" {
+    typedef struct _GdkDrawable GdkDrawable;
+}
+
 class gfxFontconfigUtils;
+#ifndef MOZ_PANGO
+class FontFamily;
+class FontEntry;
+typedef struct FT_LibraryRec_ *FT_Library;
+#endif
+
+
 
 class THEBES_API gfxPlatformGtk : public gfxPlatform {
 public:
     gfxPlatformGtk();
     virtual ~gfxPlatformGtk();
 
     static gfxPlatformGtk *GetPlatform() {
         return (gfxPlatformGtk*) gfxPlatform::GetPlatform();
@@ -67,24 +76,37 @@ public:
                              FontResolverCallback aCallback,
                              void *aClosure, PRBool& aAborted);
 
     nsresult GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName);
 
     gfxFontGroup *CreateFontGroup(const nsAString &aFamilies,
                                   const gfxFontStyle *aStyle);
 
+#ifndef MOZ_PANGO
+    FontFamily *FindFontFamily(const nsAString& aName);
+    FontEntry *FindFontEntry(const nsAString& aFamilyName, const gfxFontStyle& aFontStyle);
+#endif
+
     static PRInt32 DPI() {
         if (sDPI == -1) {
             InitDPI();
         }
         NS_ASSERTION(sDPI > 0, "Something is wrong");
         return sDPI;
     }
 
+#ifndef MOZ_PANGO
+    FT_Library GetFTLibrary();
+#endif
+
+    void SetGdkDrawable(gfxASurface *target,
+                        GdkDrawable *drawable);
+    GdkDrawable *GetGdkDrawable(gfxASurface *target);
+
 protected:
     static void InitDPI();
 
     static PRInt32 sDPI;
     static gfxFontconfigUtils *sFontconfigUtils;
 
 private:
     virtual cmsHPROFILE GetPlatformCMSOutputProfile();
--- a/gfx/thebes/src/Makefile.in
+++ b/gfx/thebes/src/Makefile.in
@@ -75,25 +75,47 @@ CPPSRCS	+=	gfxOS2Fonts.cpp \
 		gfxFontconfigUtils.cpp \
 		$(NULL)
 CPPSRCS +=	gfxPDFSurface.cpp
 EXTRA_DSO_LDOPTS += $(MOZ_CAIRO_LIBS)
 REQUIRES += uconv
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
-CPPSRCS +=      gfxXlibSurface.cpp gfxPlatformGtk.cpp gfxXlibNativeRenderer.cpp
-CPPSRCS +=	gfxPangoFonts.cpp 
+
+ifdef MOZ_PANGO
+CPPSRCS += gfxPangoFonts.cpp
+else
+CPPSRCS += gfxFT2Fonts.cpp
+endif
+
+ifdef MOZ_X11
+CPPSRCS += gfxXlibSurface.cpp
+endif
+
+CPPSRCS +=  gfxPlatformGtk.cpp gfxGdkNativeRenderer.cpp
 CPPSRCS +=	gfxPDFSurface.cpp gfxPSSurface.cpp
 CPPSRCS +=	gfxFontconfigUtils.cpp
 CPPSRCS +=	nsUnicodeRange.cpp
+
+ifdef MOZ_X11
 CSRCS = cairo-xlib-utils.c
+endif
+
+ifdef MOZ_DFB
+CSRCS = cairo-gdk-utils.c
+endif
+
 EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) $(ZLIB_LIBS) $(MOZ_XFT_LIBS) $(XLDFLAGS) $(XLIBS)
 endif
 
+ifdef MOZ_DFB
+CPPSRCS += gfxDirectFBSurface.cpp
+endif
+
 ifeq ($(MOZ_WIDGET_TOOLKIT),beos)
 CPPSRCS	+= 	gfxBeOSSurface.cpp gfxBeOSPlatform.cpp
 CPPSRCS +=	gfxPangoFonts.cpp 
 #CPPSRCS +=	gfxPDFSurface.cpp
 CPPSRCS +=	gfxFontconfigUtils.cpp
 CPPSRCS +=	nsUnicodeRange.cpp
 EXTRA_DSO_LDOPTS += $(MOZ_PANGO_LIBS) $(CAIRO_FT_LIBS) -lfontconfig -lpangocairo-1.0
 endif
--- a/gfx/thebes/src/gfxASurface.cpp
+++ b/gfx/thebes/src/gfxASurface.cpp
@@ -50,16 +50,20 @@
 #include "gfxXlibSurface.h"
 #endif
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include "gfxQuartzSurface.h"
 #include "gfxQuartzImageSurface.h"
 #endif
 
+#ifdef CAIRO_HAS_DIRECTFB_SURFACE
+#include "gfxDirectFBSurface.h"
+#endif
+
 #include <stdio.h>
 #include <limits.h>
 
 static cairo_user_data_key_t gfxasurface_pointer_key;
 
 // Surfaces use refcounting that's tied to the cairo surface refcnt, to avoid
 // refcount mismatch issues.
 nsrefcnt
@@ -158,16 +162,21 @@ gfxASurface::Wrap (cairo_surface_t *csur
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
     else if (stype == CAIRO_SURFACE_TYPE_QUARTZ) {
         result = new gfxQuartzSurface(csurf);
     }
     else if (stype == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
         result = new gfxQuartzImageSurface(csurf);
     }
 #endif
+#ifdef CAIRO_HAS_DIRECTFB_SURFACE
+    else if (stype == CAIRO_SURFACE_TYPE_DIRECTFB) {
+        result = new gfxDirectFBSurface(csurf);
+    }
+#endif
     else {
         result = new gfxUnknownSurface(csurf);
     }
 
     // fprintf(stderr, "New wrapper for %p -> %p\n", csurf, result);
 
     NS_ADDREF(result);
     return result;
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxDirectFBSurface.cpp
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir@pobox.com>
+ *
+ * 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 "gfxDirectFBSurface.h"
+
+#include "cairo-directfb.h"
+
+gfxDirectFBSurface::gfxDirectFBSurface(IDirectFB *dfb, IDirectFBSurface *dfbs)
+    : mDFB(nsnull), mDFBSurface(nsnull)
+{
+    dfb->AddRef( dfb );
+    dfbs->AddRef( dfbs );
+
+    cairo_surface_t *surf = cairo_directfb_surface_create(dfb, dfbs);
+
+    mDFB = dfb;
+    mDFBSurface = dfbs;
+
+    Init(surf);
+}
+
+gfxDirectFBSurface::gfxDirectFBSurface(IDirectFBSurface *dfbs)
+    : mDFB(nsnull), mDFBSurface(nsnull)
+{
+    DFBResult ret;
+
+    dfbs->AddRef( dfbs );
+
+    /* Lightweight, getting singleton */
+    ret = DirectFBCreate( &mDFB );
+    if (ret) {
+         D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: DirectFBCreate() failed!\n" );
+         return;
+    }
+
+    cairo_surface_t *surf = cairo_directfb_surface_create(mDFB, dfbs);
+
+    mDFBSurface = dfbs;
+
+    Init(surf);
+}
+
+gfxDirectFBSurface::gfxDirectFBSurface(cairo_surface_t *csurf)
+{
+    mDFB = nsnull;
+    mDFBSurface = nsnull;
+
+    Init(csurf, PR_TRUE);
+}
+
+gfxDirectFBSurface::gfxDirectFBSurface(const gfxIntSize& size, gfxImageFormat format) :
+    mDFB(nsnull), mDFBSurface(nsnull)
+{
+     DFBResult             ret;
+     DFBSurfaceDescription desc;
+
+     if (!CheckSurfaceSize(size) || size.width <= 0 || size.height <= 0)
+          return;
+
+     /* Lightweight, getting singleton */
+     ret = DirectFBCreate( &mDFB );
+     if (ret) {
+          D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: DirectFBCreate() failed!\n" );
+          return;
+     }
+
+     desc.flags  = (DFBSurfaceDescriptionFlags)( DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT );
+     desc.width  = size.width;
+     desc.height = size.height;
+
+     switch (format) {
+          case gfxASurface::ImageFormatARGB32:
+               desc.pixelformat = DSPF_ARGB;
+               break;
+
+          case gfxASurface::ImageFormatRGB24:
+               desc.pixelformat = DSPF_RGB32;
+               break;
+
+          case gfxASurface::ImageFormatA8:
+               desc.pixelformat = DSPF_A8;
+               break;
+
+          case gfxASurface::ImageFormatA1:
+               desc.pixelformat = DSPF_A1;
+               break;
+
+          default:
+               D_BUG( "unknown format" );
+               return;
+     }
+
+     ret = mDFB->CreateSurface( mDFB, &desc, &mDFBSurface );
+     if (ret) {
+          D_DERROR( (DirectResult) ret, "gfxDirectFBSurface: "
+                                        "IDirectFB::CreateSurface( %dx%d ) failed!\n", desc.width, desc.height );
+          return;
+     }
+
+     cairo_surface_t *surface = cairo_directfb_surface_create(mDFB, mDFBSurface);
+
+     Init(surface);
+}
+
+gfxDirectFBSurface::~gfxDirectFBSurface()
+{
+     if (mDFBSurface)
+          mDFBSurface->Release( mDFBSurface );
+
+     if (mDFB)
+          mDFB->Release( mDFB );
+}
+
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxFT2Fonts.cpp
@@ -0,0 +1,862 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 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 Foundation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * 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 ***** */
+
+#include "gfxPlatformGtk.h"
+#include "gfxTypes.h"
+#include "gfxFT2Fonts.h"
+#include <locale.h>
+#include "cairo-ft.h"
+#include <freetype/tttables.h>
+#include "gfxFontUtils.h"
+
+/**
+ * FontEntry
+ */
+
+FontEntry::FontEntry(const FontEntry& aFontEntry) :
+    mFaceName(aFontEntry.mFaceName),
+    mUnicodeFont(aFontEntry.mUnicodeFont),
+    mSymbolFont(aFontEntry.mSymbolFont),
+    mItalic(aFontEntry.mItalic),
+    mWeight(aFontEntry.mWeight),
+    mCharacterMap(aFontEntry.mCharacterMap)
+{
+    if (aFontEntry.mFontFace)
+        mFontFace = cairo_font_face_reference(aFontEntry.mFontFace);
+    else
+        mFontFace = nsnull;
+}
+
+FontEntry::~FontEntry()
+{
+    if (mFontFace) {
+        cairo_font_face_destroy(mFontFace);
+        mFontFace = nsnull;
+    }
+}
+
+static void
+FTFontDestroyFunc(void *data)
+{
+    FT_Face face = (FT_Face)data;
+    FT_Done_Face(face);
+}
+
+cairo_font_face_t *
+FontEntry::CairoFontFace()
+{
+    static cairo_user_data_key_t key;
+
+    if (!mFontFace) {
+        FT_Face face;
+        FT_New_Face(gfxPlatformGtk::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
+        mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
+        cairo_font_face_set_user_data(mFontFace, &key, face, FTFontDestroyFunc);
+    }
+    return mFontFace;
+}
+
+FontEntry *
+FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
+{
+    PRBool italic = (aFontStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
+
+    FontEntry *weightList[10] = { 0 };
+    for (PRUint32 j = 0; j < 2; j++) {
+        PRBool matchesSomething = PR_FALSE;
+        // build up an array of weights that match the italicness we're looking for
+        for (PRUint32 i = 0; i < mFaces.Length(); i++) {
+            FontEntry *fe = mFaces[i];
+            const PRUint8 weight = (fe->mWeight / 100);
+            if (fe->mItalic == italic) {
+                weightList[weight] = fe;
+                matchesSomething = PR_TRUE;
+            }
+        }
+        if (matchesSomething)
+            break;
+        italic = !italic;
+    }
+
+    PRInt8 baseWeight, weightDistance;
+    aFontStyle.ComputeWeightAndOffset(&baseWeight, &weightDistance);
+
+    // 500 isn't quite bold so we want to treat it as 400 if we don't
+    // have a 500 weight
+    if (baseWeight == 5 && weightDistance == 0) {
+        // If we have a 500 weight then use it
+        if (weightList[5])
+            return weightList[5];
+
+        // Otherwise treat as 400
+        baseWeight = 4;
+    }
+
+    PRInt8 matchBaseWeight = 0;
+    PRInt8 direction = (baseWeight > 5) ? 1 : -1;
+    for (PRInt8 i = baseWeight; ; i += direction) {
+        if (weightList[i]) {
+            matchBaseWeight = i;
+            break;
+        }
+
+        // if we've reached one side without finding a font,
+        // go the other direction until we find a match
+        if (i == 1 || i == 9)
+            direction = -direction;
+    }
+
+    FontEntry *matchFE;
+    const PRInt8 absDistance = abs(weightDistance);
+    direction = (weightDistance >= 0) ? 1 : -1;
+    for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
+        if (weightList[i]) {
+            matchFE = weightList[i];
+            k++;
+        }
+        if (k > absDistance)
+            break;
+    }
+
+    if (!matchFE)
+        matchFE = weightList[matchBaseWeight];
+
+    NS_ASSERTION(matchFE, "we should always be able to return something here");
+    return matchFE;
+}
+
+
+
+/**
+ * gfxFT2FontGroup
+ */
+
+PRBool
+gfxFT2FontGroup::FontCallback(const nsAString& fontName,
+                             const nsACString& genericName,
+                             void *closure)
+{
+    nsStringArray *sa = static_cast<nsStringArray*>(closure);
+
+    if (!fontName.IsEmpty() && sa->IndexOf(fontName) < 0) {
+        sa->AppendString(fontName);
+#ifdef DEBUG_pavlov
+        printf(" - %s\n", NS_ConvertUTF16toUTF8(fontName).get());
+#endif
+    }
+
+    return PR_TRUE;
+}
+
+/**
+ * Look up the font in the gfxFont cache. If we don't find it, create one.
+ * In either case, add a ref, append it to the aFonts array, and return it ---
+ * except for OOM in which case we do nothing and return null.
+ */
+static already_AddRefed<gfxFT2Font>
+GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle)
+{
+    nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aName, aStyle);
+    if (!font) {
+        FontEntry *fe = gfxPlatformGtk::GetPlatform()->FindFontEntry(aName, *aStyle);
+        if (!fe) {
+            printf("Failed to find font entry for %s\n", NS_ConvertUTF16toUTF8(aName).get());
+            return nsnull;
+        }
+
+        font = new gfxFT2Font(fe, aStyle);
+        if (!font)
+            return nsnull;
+        gfxFontCache::GetCache()->AddNew(font);
+    }
+    gfxFont *f = nsnull;
+    font.swap(f);
+    return static_cast<gfxFT2Font *>(f);
+}
+
+
+gfxFT2FontGroup::gfxFT2FontGroup(const nsAString& families,
+                               const gfxFontStyle *aStyle)
+    : gfxFontGroup(families, aStyle)
+{
+#ifdef DEBUG_pavlov
+    printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get());
+#endif
+    nsStringArray familyArray;
+    ForEachFont(FontCallback, &familyArray);
+
+    if (familyArray.Count() == 0) {
+        nsAutoString prefFamilies;
+        gfxPlatformGtk::GetPlatform()->GetPrefFonts(aStyle->langGroup.get(), prefFamilies, nsnull);
+        if (!prefFamilies.IsEmpty()) {
+            ForEachFont(prefFamilies, aStyle->langGroup, FontCallback, &familyArray);
+        }
+    }
+#if 0 /* FIXME DFB */
+    if (familyArray.Count() == 0) {
+        printf("failde to find a font. sadface\n");
+        // We want to get rid of this entirely at some point, but first we need real lists of fonts.
+        QFont defaultFont;
+        QFontInfo fi (defaultFont);
+        familyArray.AppendString(nsDependentString(static_cast<const PRUnichar *>(fi.family().utf16())));
+    }
+#endif
+
+    for (int i = 0; i < familyArray.Count(); i++) {
+        nsRefPtr<gfxFT2Font> font = GetOrMakeFont(*familyArray[i], &mStyle);
+        if (font) {
+            mFonts.AppendElement(font);
+        }
+    }
+}
+
+gfxFT2FontGroup::~gfxFT2FontGroup()
+{
+}
+
+gfxFontGroup *
+gfxFT2FontGroup::Copy(const gfxFontStyle *aStyle)
+{
+     return new gfxFT2FontGroup(mFamilies, aStyle);
+}
+
+/**
+ * We use this to append an LTR or RTL Override character to the start of the
+ * string. This forces Pango to honour our direction even if there are neutral
+ * characters in the string.
+ */
+static PRInt32 AppendDirectionalIndicatorUTF8(PRBool aIsRTL, nsACString& aString)
+{
+    static const PRUnichar overrides[2][2] = { { 0x202d, 0 }, { 0x202e, 0 }}; // LRO, RLO
+    AppendUTF16toUTF8(overrides[aIsRTL], aString);
+    return 3; // both overrides map to 3 bytes in UTF8
+}
+
+gfxTextRun *gfxFT2FontGroup::MakeTextRun(const PRUnichar* aString, PRUint32 aLength,
+                                        const Parameters* aParams, PRUint32 aFlags)
+{
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    textRun->RecordSurrogates(aString);
+
+    mString.Assign(nsDependentSubstring(aString, aString + aLength));
+
+    InitTextRun(textRun);
+
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
+
+gfxTextRun *gfxFT2FontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
+                                        const Parameters *aParams, PRUint32 aFlags)
+{
+    NS_ASSERTION(aFlags & TEXT_IS_8BIT, "8bit should have been set");
+    gfxTextRun *textRun = gfxTextRun::Create(aParams, aString, aLength, this, aFlags);
+    if (!textRun)
+        return nsnull;
+
+    const char *chars = reinterpret_cast<const char *>(aString);
+
+    mString.Assign(NS_ConvertASCIItoUTF16(nsDependentCSubstring(chars, chars + aLength)));
+
+    InitTextRun(textRun);
+
+    textRun->FetchGlyphExtents(aParams->mContext);
+
+    return textRun;
+}
+
+void gfxFT2FontGroup::InitTextRun(gfxTextRun *aTextRun)
+{
+    CreateGlyphRunsFT(aTextRun);
+}
+
+
+// Helper function to return the leading UTF-8 character in a char pointer
+// as 32bit number. Also sets the length of the current character (i.e. the
+// offset to the next one) in the second argument
+PRUint32 getUTF8CharAndNext(const PRUint8 *aString, PRUint8 *aLength)
+{
+    *aLength = 1;
+    if (aString[0] < 0x80) { // normal 7bit ASCII char
+        return aString[0];
+    }
+    if ((aString[0] >> 5) == 6) { // two leading ones -> two bytes
+        *aLength = 2;
+        return ((aString[0] & 0x1F) << 6) + (aString[1] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 14) { // three leading ones -> three bytes
+        *aLength = 3;
+        return ((aString[0] & 0x0F) << 12) + ((aString[1] & 0x3F) << 6) +
+               (aString[2] & 0x3F);
+    }
+    if ((aString[0] >> 4) == 15) { // four leading ones -> four bytes
+        *aLength = 4;
+        return ((aString[0] & 0x07) << 18) + ((aString[1] & 0x3F) << 12) +
+               ((aString[2] & 0x3F) <<  6) + (aString[3] & 0x3F);
+    }
+    return aString[0];
+}
+
+
+
+
+
+
+
+
+PRBool
+HasCharacter(gfxFT2Font *aFont, PRUint32 ch)
+{
+    if (aFont->GetFontEntry()->mCharacterMap.test(ch))
+        return PR_TRUE;
+
+    // XXX move this lock way way out
+    FT_Face face = cairo_ft_scaled_font_lock_face(aFont->CairoScaledFont());
+    FT_UInt gid = FT_Get_Char_Index(face, ch);
+    cairo_ft_scaled_font_unlock_face(aFont->CairoScaledFont());
+
+    if (gid != 0) {
+        aFont->GetFontEntry()->mCharacterMap.set(ch);
+        return PR_TRUE;
+    }
+    return PR_FALSE;
+}
+
+#if 0
+inline FontEntry *
+gfxFT2FontGroup::WhichFontSupportsChar(const nsTArray<>& foo, PRUint32 ch)
+{
+    for (int i = 0; i < aGroup->FontListLength(); i++) {
+        nsRefPtr<gfxFT2Font> font = aGroup->GetFontAt(i);
+        if (HasCharacter(font, ch))
+            return font;
+    }
+    return nsnull;
+}
+#endif
+
+inline gfxFT2Font *
+gfxFT2FontGroup::FindFontForChar(PRUint32 ch, PRUint32 prevCh, PRUint32 nextCh, gfxFT2Font *aFont)
+{
+    gfxFT2Font *selectedFont;
+
+    // if this character or the next one is a joiner use the
+    // same font as the previous range if we can
+    if (gfxFontUtils::IsJoiner(ch) || gfxFontUtils::IsJoiner(prevCh) || gfxFontUtils::IsJoiner(nextCh)) {
+        if (aFont && HasCharacter(aFont, ch))
+            return aFont;
+    }
+
+    for (PRUint32 i = 0; i < FontListLength(); i++) {
+        nsRefPtr<gfxFT2Font> font = GetFontAt(i);
+        if (HasCharacter(font, ch))
+            return font;
+    }
+    return nsnull;
+
+#if 0
+    // check the list of fonts
+    selectedFont = WhichFontSupportsChar(mGroup->GetFontList(), ch);
+
+
+    // don't look in other fonts if the character is in a Private Use Area
+    if ((ch >= 0xE000  && ch <= 0xF8FF) || 
+        (ch >= 0xF0000 && ch <= 0x10FFFD))
+        return selectedFont;
+
+    // check out the style's language group
+    if (!selectedFont) {
+        nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
+        this->GetPrefFonts(mGroup->GetStyle()->langGroup.get(), fonts);
+        selectedFont = WhichFontSupportsChar(fonts, ch);
+    }
+
+    // otherwise search prefs
+    if (!selectedFont) {
+        /* first check with the script properties to see what they think */
+        if (ch <= 0xFFFF) {
+            PRUint32 unicodeRange = FindCharUnicodeRange(ch);
+            
+            /* special case CJK */
+            if (unicodeRange == kRangeSetCJK) {
+                if (PR_LOG_TEST(gFontLog, PR_LOG_DEBUG))
+                    PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: CJK"));
+
+                nsAutoTArray<nsRefPtr<FontEntry>, 15> fonts;
+                this->GetCJKPrefFonts(fonts);
+                selectedFont = WhichFontSupportsChar(fonts, ch);
+            } else {
+                const char *langGroup = LangGroupFromUnicodeRange(unicodeRange);
+                if (langGroup) {
+                    PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s", langGroup));
+
+                    nsAutoTArray<nsRefPtr<FontEntry>, 5> fonts;
+                    this->GetPrefFonts(langGroup, fonts);
+                    selectedFont = WhichFontSupportsChar(fonts, ch);
+                }
+            }
+        }
+    }
+
+    // before searching for something else check the font used for the previous character
+    if (!selectedFont && aFont && HasCharacter(aFont, ch))
+        selectedFont = aFont;
+
+    // otherwise look for other stuff
+    if (!selectedFont) {
+        PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Looking for best match"));
+        
+        nsRefPtr<gfxWindowsFont> refFont = mGroup->GetFontAt(0);
+        gfxWindowsPlatform *platform = gfxWindowsPlatform::GetPlatform();
+        selectedFont = platform->FindFontForChar(ch, refFont);
+    }
+
+    return selectedFont;
+#endif
+}
+
+PRUint32
+gfxFT2FontGroup::ComputeRanges()
+{
+    const PRUnichar *str = mString.get();
+    PRUint32 len = mString.Length();
+
+    mRanges.Clear();
+
+    PRUint32 prevCh = 0;
+    for (PRUint32 i = 0; i < len; i++) {
+        const PRUint32 origI = i; // save off incase we increase for surrogate
+        PRUint32 ch = str[i];
+        if ((i+1 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+1])) {
+            i++;
+            ch = SURROGATE_TO_UCS4(ch, str[i]);
+        }
+
+        PRUint32 nextCh = 0;
+        if (i+1 < len) {
+            nextCh = str[i+1];
+            if ((i+2 < len) && NS_IS_HIGH_SURROGATE(ch) && NS_IS_LOW_SURROGATE(str[i+2]))
+                nextCh = SURROGATE_TO_UCS4(nextCh, str[i+2]);
+        }
+        gfxFT2Font *fe = FindFontForChar(ch,
+                                        prevCh,
+                                        nextCh,
+                                        (mRanges.Length() == 0) ? nsnull : mRanges[mRanges.Length() - 1].font);
+
+        prevCh = ch;
+
+        if (mRanges.Length() == 0) {
+            TextRange r(0,1);
+            r.font = fe;
+            mRanges.AppendElement(r);
+        } else {
+            TextRange& prevRange = mRanges[mRanges.Length() - 1];
+            if (prevRange.font != fe) {
+                // close out the previous range
+                prevRange.end = origI;
+
+                TextRange r(origI, i+1);
+                r.font = fe;
+                mRanges.AppendElement(r);
+            }
+        }
+    }
+    mRanges[mRanges.Length()-1].end = len;
+
+    PRUint32 nranges = mRanges.Length();
+    return nranges;
+}
+
+void gfxFT2FontGroup::CreateGlyphRunsFT(gfxTextRun *aTextRun)
+{
+    ComputeRanges();
+
+    const PRUnichar *strStart = mString.get();
+    for (PRUint32 i = 0; i < mRanges.Length(); ++i) {
+        const TextRange& range = mRanges[i];
+        const PRUnichar *rangeString = strStart + range.start;
+        PRUint32 rangeLength = range.Length();
+
+        gfxFT2Font *font = range.font ? range.font.get() : GetFontAt(0);
+        AddRange(aTextRun, font, rangeString, rangeLength);
+    }
+    
+}
+
+void
+gfxFT2FontGroup::AddRange(gfxTextRun *aTextRun, gfxFT2Font *font, const PRUnichar *str, PRUint32 len)
+{
+    const PRUint32 appUnitsPerDevUnit = aTextRun->GetAppUnitsPerDevUnit();
+    // we'll pass this in/figure it out dynamically, but at this point there can be only one face.
+    FT_Face face = cairo_ft_scaled_font_lock_face(font->CairoScaledFont());
+
+    gfxTextRun::CompressedGlyph g;
+
+    aTextRun->AddGlyphRun(font, 0);
+    for (PRUint32 i = 0; i < len; i++) {
+        PRUint32 ch = str[i];
+
+        if (ch == 0) {
+            // treat this null byte as a missing glyph, don't create a glyph for it
+            aTextRun->SetMissingGlyph(i, 0);
+            continue;
+        }
+
+        NS_ASSERTION(!IsInvalidChar(ch), "Invalid char detected");
+        FT_UInt gid = FT_Get_Char_Index(face, ch); // find the glyph id
+        PRInt32 advance = 0;
+
+        if (gid == font->GetSpaceGlyph()) {
+            advance = (int)(font->GetMetrics().spaceWidth * appUnitsPerDevUnit);
+        } else if (gid == 0) {
+            advance = -1; // trigger the missing glyphs case below
+        } else {
+            // find next character and its glyph -- in case they exist
+            // and exist in the current font face -- to compute kerning
+            PRUint32 chNext = 0;
+            FT_UInt gidNext = 0;
+            FT_Pos lsbDeltaNext = 0;
+
+            if (FT_HAS_KERNING(face) && i + 1 < len) {
+                chNext = str[i+1];
+                if (chNext != 0) {
+                    gidNext = FT_Get_Char_Index(face, chNext);
+                    if (gidNext && gidNext != font->GetSpaceGlyph()) {
+                        FT_Load_Glyph(face, gidNext, FT_LOAD_DEFAULT);
+                        lsbDeltaNext = face->glyph->lsb_delta;
+                    }
+                }
+            }
+
+            // now load the current glyph
+            FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT); // load glyph into the slot
+            advance = face->glyph->advance.x;
+
+            // now add kerning to the current glyph's advance
+            if (chNext && gidNext) {
+                FT_Vector kerning; kerning.x = 0;
+                FT_Get_Kerning(face, gid, gidNext, FT_KERNING_DEFAULT, &kerning);
+                advance += kerning.x;
+                if (face->glyph->rsb_delta - lsbDeltaNext >= 32) {
+                    advance -= 64;
+                } else if (face->glyph->rsb_delta - lsbDeltaNext < -32) {
+                    advance += 64;
+                }
+            }
+
+            // now apply unit conversion and scaling
+            advance = (advance >> 6) * appUnitsPerDevUnit;
+        }
+#ifdef DEBUG_thebes_2
+        printf(" gid=%d, advance=%d (%s)\n", gid, advance,
+               NS_LossyConvertUTF16toASCII(font->GetName()).get());
+#endif
+
+        if (advance >= 0 &&
+            gfxTextRun::CompressedGlyph::IsSimpleAdvance(advance) &&
+            gfxTextRun::CompressedGlyph::IsSimpleGlyphID(gid)) {
+            aTextRun->SetSimpleGlyph(i, g.SetSimpleGlyph(advance, gid));
+        } else if (gid == 0) {
+            // gid = 0 only happens when the glyph is missing from the font
+            aTextRun->SetMissingGlyph(i, ch);
+        } else {
+            gfxTextRun::DetailedGlyph details;
+            details.mGlyphID = gid;
+            NS_ASSERTION(details.mGlyphID == gid, "Seriously weird glyph ID detected!");
+            details.mAdvance = advance;
+            details.mXOffset = 0;
+            details.mYOffset = 0;
+            g.SetComplex(aTextRun->IsClusterStart(i), PR_TRUE, 1);
+            aTextRun->SetGlyphs(i, g, &details);
+        }
+    }
+
+    cairo_ft_scaled_font_unlock_face(font->CairoScaledFont());
+}
+
+/**
+ * gfxFT2Font
+ */
+gfxFT2Font::gfxFT2Font(FontEntry *aFontEntry,
+                     const gfxFontStyle *aFontStyle)
+    : gfxFont(aFontEntry->GetName(), aFontStyle),
+    mScaledFont(nsnull),
+    mHasSpaceGlyph(PR_FALSE),
+    mSpaceGlyph(0),
+    mHasMetrics(PR_FALSE),
+    mAdjustedSize(0),
+    mFontEntry(aFontEntry)
+{
+}
+
+gfxFT2Font::~gfxFT2Font()
+{
+    if (mScaledFont) {
+        cairo_scaled_font_destroy(mScaledFont);
+        mScaledFont = nsnull;
+    }
+}
+
+// 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))))
+
+const gfxFont::Metrics&
+gfxFT2Font::GetMetrics()
+{
+    if (mHasMetrics)
+        return mMetrics;
+
+    mMetrics.emHeight = GetStyle()->size;
+
+    FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
+
+    if (!face) {
+        // Abort here already, otherwise we crash in the following
+        // this can happen if the font-size requested is zero.
+        // The metrics will be incomplete, but then we don't care.
+        return mMetrics;
+    }
+
+    mMetrics.emHeight = GetStyle()->size;
+
+    FT_UInt gid; // glyph ID
+
+    const double emUnit = 1.0 * face->units_per_EM;
+    const double xScale = face->size->metrics.x_ppem / emUnit;
+    const double yScale = face->size->metrics.y_ppem / emUnit;
+
+    // properties of space
+    gid = FT_Get_Char_Index(face, ' ');
+    if (gid) {
+        FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
+        // face->glyph->metrics.width doesn't work for spaces, use advance.x instead
+        mMetrics.spaceWidth = face->glyph->advance.x >> 6;
+        // save the space glyph
+        mSpaceGlyph = gid;
+    } else {
+        NS_ASSERTION(0, "blah");
+    }
+            
+    // properties of 'x', also use its width as average width
+    gid = FT_Get_Char_Index(face, 'x'); // select the glyph
+    if (gid) {
+        // Load glyph into glyph slot. Here, use no_scale to get font units.
+        FT_Load_Glyph(face, gid, FT_LOAD_NO_SCALE);
+        mMetrics.xHeight = face->glyph->metrics.height * yScale;
+        mMetrics.aveCharWidth = face->glyph->metrics.width * xScale;
+    } else {
+        // this font doesn't have an 'x'...
+        // fake these metrics using a fraction of the font size
+        mMetrics.xHeight = mMetrics.emHeight * 0.5;
+        mMetrics.aveCharWidth = mMetrics.emHeight * 0.5;
+    }
+
+    // compute an adjusted size if we need to
+    if (mAdjustedSize == 0 && GetStyle()->sizeAdjust != 0) {
+        gfxFloat aspect = mMetrics.xHeight / GetStyle()->size;
+        mAdjustedSize = GetStyle()->GetAdjustedSize(aspect);
+        mMetrics.emHeight = mAdjustedSize;
+    }
+
+    // now load the OS/2 TrueType table to load access some more properties
+    TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
+    if (os2 && os2->version != 0xFFFF) { // should be there if not old Mac font
+        // if we are here we can improve the avgCharWidth
+        mMetrics.aveCharWidth = os2->xAvgCharWidth * xScale;
+
+        mMetrics.superscriptOffset = os2->ySuperscriptYOffset * yScale;
+        mMetrics.superscriptOffset = PR_MAX(1, mMetrics.superscriptOffset);
+        // some fonts have the incorrect sign (from gfxPangoFonts)
+        mMetrics.subscriptOffset   = fabs(os2->ySubscriptYOffset * yScale);
+        mMetrics.subscriptOffset   = PR_MAX(1, fabs(mMetrics.subscriptOffset));
+        mMetrics.strikeoutOffset   = os2->yStrikeoutPosition * yScale;
+        mMetrics.strikeoutSize     = os2->yStrikeoutSize * yScale;
+    } else {
+        // use fractions of emHeight instead of xHeight for these to be more robust
+        mMetrics.superscriptOffset = mMetrics.emHeight * 0.5;
+        mMetrics.subscriptOffset   = mMetrics.emHeight * 0.2;
+        mMetrics.strikeoutOffset   = mMetrics.emHeight * 0.3;
+        mMetrics.strikeoutSize     = face->underline_thickness * yScale;
+    }
+    // seems that underlineOffset really has to be negative
+    mMetrics.underlineOffset = face->underline_position * yScale;
+    mMetrics.underlineSize   = face->underline_thickness * yScale;
+
+    // descents are negative in FT but Thebes wants them positive
+    mMetrics.emAscent        = face->ascender * yScale;
+    mMetrics.emDescent       = -face->descender * yScale;
+    mMetrics.maxHeight       = face->height * yScale;
+    mMetrics.maxAscent       = face->bbox.yMax * yScale;
+    mMetrics.maxDescent      = -face->bbox.yMin * yScale;
+    mMetrics.maxAdvance      = face->max_advance_width * xScale;
+    // leading are not available directly (only for WinFNTs)
+    double lineHeight = mMetrics.maxAscent + mMetrics.maxDescent;
+    if (lineHeight > mMetrics.emHeight) {
+        mMetrics.internalLeading = lineHeight - mMetrics.emHeight;
+    } else {
+        mMetrics.internalLeading = 0;
+    }
+    mMetrics.externalLeading = 0; // normal value for OS/2 fonts, too
+
+    SanitizeMetrics(&mMetrics, PR_FALSE);
+
+    /*
+    printf("gfxOS2Font[%#x]::GetMetrics():\n"
+           "  emHeight=%f == %f=gfxFont::style.size == %f=adjSz\n"
+           "  maxHeight=%f  xHeight=%f\n"
+           "  aveCharWidth=%f==xWidth  spaceWidth=%f\n"
+           "  supOff=%f SubOff=%f   strOff=%f strSz=%f\n"
+           "  undOff=%f undSz=%f    intLead=%f extLead=%f\n"
+           "  emAsc=%f emDesc=%f maxH=%f\n"
+           "  maxAsc=%f maxDes=%f maxAdv=%f\n",
+           (unsigned)this,
+           mMetrics.emHeight, GetStyle()->size, mAdjustedSize,
+           mMetrics.maxHeight, mMetrics.xHeight,
+           mMetrics.aveCharWidth, mMetrics.spaceWidth,
+           mMetrics.superscriptOffset, mMetrics.subscriptOffset,
+           mMetrics.strikeoutOffset, mMetrics.strikeoutSize,
+           mMetrics.underlineOffset, mMetrics.underlineSize,
+           mMetrics.internalLeading, mMetrics.externalLeading,
+           mMetrics.emAscent, mMetrics.emDescent, mMetrics.maxHeight,
+           mMetrics.maxAscent, mMetrics.maxDescent, mMetrics.maxAdvance
+          );
+    */
+
+    // XXX mMetrics.height needs to be set.
+    cairo_ft_scaled_font_unlock_face(CairoScaledFont());
+
+    mHasMetrics = PR_TRUE;
+    return mMetrics;
+}
+
+
+nsString
+gfxFT2Font::GetUniqueName()
+{
+    return mName;
+}
+
+PRUint32
+gfxFT2Font::GetSpaceGlyph()
+{
+    NS_ASSERTION (GetStyle ()->size != 0,
+    "forgot to short-circuit a text run with zero-sized font?");
+
+    if(!mHasSpaceGlyph)
+    {
+        FT_UInt gid = 0; // glyph ID
+        FT_Face face = cairo_ft_scaled_font_lock_face(CairoScaledFont());
+        gid = FT_Get_Char_Index(face, ' ');
+        FT_Load_Glyph(face, gid, FT_LOAD_DEFAULT);
+        mSpaceGlyph = gid;
+        mHasSpaceGlyph = PR_TRUE;
+        cairo_ft_scaled_font_unlock_face(CairoScaledFont());
+    }
+    return mSpaceGlyph;
+}
+
+cairo_font_face_t *
+gfxFT2Font::CairoFontFace()
+{
+    // XXX we need to handle fake bold here (or by having a sepaerate font entry)
+    if (mStyle.weight >= 600 && mFontEntry->mWeight < 600)
+        printf("** We want fake weight\n");
+    return mFontEntry->CairoFontFace();
+}
+
+cairo_scaled_font_t *
+gfxFT2Font::CairoScaledFont()
+{
+    if (!mScaledFont) {
+        cairo_matrix_t sizeMatrix;
+        cairo_matrix_t identityMatrix;
+
+        // XXX deal with adjusted size
+        cairo_matrix_init_scale(&sizeMatrix, mStyle.size, mStyle.size);
+        cairo_matrix_init_identity(&identityMatrix);
+
+        // synthetic oblique by skewing via the font matrix
+        PRBool needsOblique = (!mFontEntry->mItalic && (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)));
+
+        if (needsOblique) {
+            const double kSkewFactor = 0.25;
+
+            cairo_matrix_t style;
+            cairo_matrix_init(&style,
+                              1,                //xx
+                              0,                //yx
+                              -1 * kSkewFactor,  //xy
+                              1,                //yy
+                              0,                //x0
+                              0);               //y0
+            cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
+        }
+
+        cairo_font_options_t *fontOptions = cairo_font_options_create();
+        mScaledFont = cairo_scaled_font_create(CairoFontFace(), &sizeMatrix,
+                                               &identityMatrix, fontOptions);
+        cairo_font_options_destroy(fontOptions);
+    }
+
+    NS_ASSERTION(mAdjustedSize == 0.0 ||
+                 cairo_scaled_font_status(mScaledFont) == CAIRO_STATUS_SUCCESS,
+                 "Failed to make scaled font");
+
+    return mScaledFont;
+}
+
+PRBool
+gfxFT2Font::SetupCairoFont(gfxContext *aContext)
+{
+    cairo_scaled_font_t *scaledFont = CairoScaledFont();
+
+    if (cairo_scaled_font_status(scaledFont) != CAIRO_STATUS_SUCCESS) {
+        // Don't cairo_set_scaled_font as that would propagate the error to
+        // the cairo_t, precluding any further drawing.
+        return PR_FALSE;
+    }
+    cairo_set_scaled_font(aContext->GetCairo(), scaledFont);
+    return PR_TRUE;
+}
--- a/gfx/thebes/src/gfxPlatformGtk.cpp
+++ b/gfx/thebes/src/gfxPlatformGtk.cpp
@@ -31,91 +31,146 @@
  * 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 ***** */
 
+#ifdef MOZ_PANGO
 #define PANGO_ENABLE_BACKEND
 #define PANGO_ENABLE_ENGINE
+#endif
 
 #include "gfxPlatformGtk.h"
 
 #include "gfxFontconfigUtils.h"
+#ifdef MOZ_PANGO
+#include <pango/pangocairo.h>
 #include "gfxPangoFonts.h"
 #include "gfxContext.h"
+#else
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include "gfxFT2Fonts.h"
+#endif
 
 #include "cairo.h"
 #include <gtk/gtk.h>
-#include <gdk/gdkx.h>
 
 #include "gfxImageSurface.h"
+#ifdef MOZ_X11
+#include <gdk/gdkx.h>
 #include "gfxXlibSurface.h"
+#endif /* MOZ_X11 */
 
-#include "gfxPangoFonts.h"
-
-#include <pango/pangocairo.h>
+#ifdef MOZ_DFB
+#include "gfxDirectFBSurface.h"
+#endif
 
 #ifdef MOZ_ENABLE_GLITZ
 #include "gfxGlitzSurface.h"
 #include "glitz-glx.h"
 #endif
 
+#ifdef MOZ_DFB
+#include "gfxDirectFBSurface.h"
+#endif
+
 #include <fontconfig/fontconfig.h>
 
 #include "nsMathUtils.h"
 
 #include "lcms.h"
 
+#ifndef MOZ_PANGO
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#endif
+
 PRInt32 gfxPlatformGtk::sDPI = -1;
 gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
 
+static cairo_user_data_key_t cairo_gdk_drawable_key;
+
+#ifndef MOZ_PANGO
+typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
+static FontTable *gPlatformFonts = NULL;
+static FontTable *gPlatformFontAliases = NULL;
+static FT_Library gPlatformFTLibrary = NULL;
+#endif
+
+
 static cairo_user_data_key_t cairo_gdk_pixmap_key;
 static void do_gdk_pixmap_unref (void *data)
 {
     GdkPixmap *pmap = (GdkPixmap*)data;
     gdk_pixmap_unref (pmap);
 }
 
 gfxPlatformGtk::gfxPlatformGtk()
 {
 #ifdef MOZ_ENABLE_GLITZ
     if (UseGlitz())
         glitz_glx_init(NULL);
 #endif
     if (!sFontconfigUtils)
         sFontconfigUtils = gfxFontconfigUtils::GetFontconfigUtils();
 
+#ifndef MOZ_PANGO
+    FT_Init_FreeType(&gPlatformFTLibrary);
+
+    gPlatformFonts = new FontTable();
+    /* FIXME: DFB */
+    //gPlatformFonts->Init(100);
+    gPlatformFonts->Init(20);
+    gPlatformFontAliases = new FontTable();
+    /* FIXME: DFB */
+    //gPlatformFontAliases->Init(100);
+    gPlatformFontAliases->Init(20);
+    UpdateFontList();
+#endif
+
     InitDPI();
 }
 
 gfxPlatformGtk::~gfxPlatformGtk()
 {
     gfxFontconfigUtils::Shutdown();
     sFontconfigUtils = nsnull;
 
+#ifdef MOZ_PANGO
     gfxPangoFont::Shutdown();
+#else
+    delete gPlatformFonts;
+    gPlatformFonts = NULL;
+    delete gPlatformFontAliases;
+    gPlatformFontAliases = NULL;
+
+    FT_Done_FreeType(gPlatformFTLibrary);
+    gPlatformFTLibrary = NULL;
+#endif
 
 #if 0
     // It would be nice to do this (although it might need to be after
     // the cairo shutdown that happens in ~gfxPlatform).  It even looks
     // idempotent.  But it has fatal assertions that fire if stuff is
     // leaked, and we hit them.
     FcFini();
 #endif
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size,
                                        gfxASurface::gfxImageFormat imageFormat)
 {
     nsRefPtr<gfxASurface> newSurface = nsnull;
 
+#ifdef MOZ_X11
     int glitzf;
     int xrenderFormatID;
     switch (imageFormat) {
         case gfxASurface::ImageFormatARGB32:
             glitzf = 0; // GLITZ_STANDARD_ARGB32;
             xrenderFormatID = PictStandardARGB32;
             break;
         case gfxASurface::ImageFormatRGB24:
@@ -159,16 +214,17 @@ gfxPlatformGtk::CreateOffscreenSurface(c
             }
 
             if (newSurface && newSurface->CairoStatus() == 0) {
                 // set up the surface to auto-unref the gdk pixmap when
                 // the surface is released
                 newSurface->SetData(&cairo_gdk_pixmap_key,
                                     pixmap,
                                     do_gdk_pixmap_unref);
+            SetGdkDrawable(newSurface, GDK_DRAWABLE(pixmap));
             } else {
                 // something went wrong with the surface creation.
                 // Ignore and let's fall back to image surfaces.
                 if (pixmap)
                     gdk_pixmap_unref(pixmap);
                 newSurface = nsnull;
             }
         }
@@ -202,26 +258,29 @@ gfxPlatformGtk::CreateOffscreenSurface(c
                                  size.height,
                                  0,
                                  NULL);
 
         glitz_surface_attach(gsurf, gdraw, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR);
         newSurface = new gfxGlitzSurface(gdraw, gsurf, PR_TRUE);
 #endif
     }
+#endif
 
     if (newSurface) {
         gfxContext tmpCtx(newSurface);
         tmpCtx.SetOperator(gfxContext::OPERATOR_CLEAR);
         tmpCtx.Paint();
     }
 
     return newSurface.forget();
 }
 
+#ifdef MOZ_PANGO
+
 nsresult
 gfxPlatformGtk::GetFontList(const nsACString& aLangGroup,
                             const nsACString& aGenericFamily,
                             nsStringArray& aListOfFonts)
 {
     return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily,
                                          aListOfFonts);
 }
@@ -250,33 +309,257 @@ gfxPlatformGtk::GetStandardFamilyName(co
 
 gfxFontGroup *
 gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
                                 const gfxFontStyle *aStyle)
 {
     return new gfxPangoFontGroup(aFamilies, aStyle);
 }
 
+#else
+
+nsresult
+gfxPlatformGtk::GetFontList(const nsACString& aLangGroup,
+                            const nsACString& aGenericFamily,
+                            nsStringArray& aListOfFonts)
+{
+    return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily,
+                                         aListOfFonts);
+}
+
+nsresult
+gfxPlatformGtk::UpdateFontList()
+{
+    FcPattern *pat = NULL;
+    FcObjectSet *os = NULL;
+    FcFontSet *fs = NULL;
+    PRInt32 result = -1;
+
+    pat = FcPatternCreate();
+    os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_WEIGHT, FC_SLANT, FC_WIDTH, NULL);
+
+    fs = FcFontList(NULL, pat, os);
+
+
+    for (int i = 0; i < fs->nfont; i++) {
+        char *str;
+
+        if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+
+        //printf("Family: %s\n", str);
+
+        nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get());
+        nsAutoString key(name);
+        /* FIXME DFB */
+        //ToLowerCase(key);
+        nsRefPtr<FontFamily> ff;
+        if (!gPlatformFonts->Get(key, &ff)) {
+            ff = new FontFamily(name);
+            gPlatformFonts->Put(key, ff);
+        }
+
+        nsRefPtr<FontEntry> fe = new FontEntry(ff->mName);
+        ff->mFaces.AppendElement(fe);
+
+        if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) {
+            fe->mFilename = nsDependentCString(str);
+            //printf(" - file: %s\n", str);
+        }
+
+        int x;
+        if (FcPatternGetInteger(fs->fonts[i], FC_INDEX, 0, &x) == FcResultMatch) {
+            //printf(" - index: %d\n", x);
+            fe->mFTFontIndex = x;
+        } else {
+            fe->mFTFontIndex = 0;
+        }
+
+        if (FcPatternGetInteger(fs->fonts[i], FC_WEIGHT, 0, &x) == FcResultMatch) {
+            switch(x) {
+            case 0:
+                fe->mWeight = 100;
+                break;
+            case 40:
+                fe->mWeight = 200;
+                break;
+            case 50:
+                fe->mWeight = 300;
+                break;
+            case 75:
+            case 80:
+                fe->mWeight = 400;
+                break;
+            case 100:
+                fe->mWeight = 500;
+                break;
+            case 180:
+                fe->mWeight = 600;
+                break;
+            case 200:
+                fe->mWeight = 700;
+                break;
+            case 205:
+                fe->mWeight = 800;
+                break;
+            case 210:
+                fe->mWeight = 900;
+                break;
+            default:
+                // rough estimate
+                fe->mWeight = (((x * 4) + 100) / 100) * 100;
+                break;
+            }
+            //printf(" - weight: %d\n", fe->mWeight);
+        }
+
+        fe->mItalic = PR_FALSE;
+        if (FcPatternGetInteger(fs->fonts[i], FC_SLANT, 0, &x) == FcResultMatch) {
+            switch (x) {
+            case FC_SLANT_ITALIC:
+            case FC_SLANT_OBLIQUE:
+                fe->mItalic = PR_TRUE;
+            }
+            //printf(" - slant: %d\n", x);
+        }
+
+        //if (FcPatternGetInteger(fs->fonts[i], FC_WIDTH, 0, &x) == FcResultMatch)
+            //printf(" - width: %d\n", x);
+        // XXX deal with font-stretch stuff later
+    }
+
+    if (pat)
+        FcPatternDestroy(pat);
+    if (os)
+        FcObjectSetDestroy(os);
+    if (fs)
+        FcFontSetDestroy(fs);
+
+    return sFontconfigUtils->UpdateFontList();
+}
+
+nsresult
+gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
+                                FontResolverCallback aCallback,
+                                void *aClosure,
+                                PRBool& aAborted)
+{
+
+    nsAutoString name(aFontName);
+    /* FIXME: DFB */
+    //ToLowerCase(name);
+
+    nsRefPtr<FontFamily> ff;
+    if (gPlatformFonts->Get(name, &ff) ||
+        gPlatformFontAliases->Get(name, &ff)) {
+        aAborted = !(*aCallback)(ff->mName, aClosure);
+        return NS_OK;
+    }
+
+    nsCAutoString utf8Name = NS_ConvertUTF16toUTF8(aFontName);
+
+    FcPattern *npat = FcPatternCreate();
+    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
+    FcObjectSet *nos = FcObjectSetBuild(FC_FAMILY, NULL);
+    FcFontSet *nfs = FcFontList(NULL, npat, nos);
+
+    for (int k = 0; k < nfs->nfont; k++) {
+        FcChar8 *str;
+        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
+        /* FIXME: DFB */
+        //ToLowerCase(altName);
+        if (gPlatformFonts->Get(altName, &ff)) {
+            //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
+            gPlatformFontAliases->Put(name, ff);
+            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
+            goto DONE;
+        }
+    }
+
+    FcPatternDestroy(npat);
+    FcObjectSetDestroy(nos);
+    FcFontSetDestroy(nfs);
+
+    {
+    npat = FcPatternCreate();
+    FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
+    FcPatternDel(npat, FC_LANG);
+    FcConfigSubstitute(NULL, npat, FcMatchPattern);
+    FcDefaultSubstitute(npat);
+
+    nos = FcObjectSetBuild(FC_FAMILY, NULL);
+    nfs = FcFontList(NULL, npat, nos);
+
+    FcResult fresult;
+
+    FcPattern *match = FcFontMatch(NULL, npat, &fresult);
+    if (match)
+        FcFontSetAdd(nfs, match);
+
+    for (int k = 0; k < nfs->nfont; k++) {
+        FcChar8 *str;
+        if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
+            continue;
+        nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
+        /* FIXME: DFB */
+        //ToLowerCase(altName);
+        if (gPlatformFonts->Get(altName, &ff)) {
+            //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
+            gPlatformFontAliases->Put(name, ff);
+            aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
+            goto DONE;
+        }
+    }
+    }
+ DONE:
+    FcPatternDestroy(npat);
+    FcObjectSetDestroy(nos);
+    FcFontSetDestroy(nfs);
+
+    return NS_OK;
+}
+
+nsresult
+gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
+{
+    return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
+}
+
+gfxFontGroup *
+gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
+                               const gfxFontStyle *aStyle)
+{
+    return new gfxFT2FontGroup(aFamilies, aStyle);
+}
+
+#endif
+
+
 /* static */
 void
 gfxPlatformGtk::InitDPI()
 {
+#ifdef MOZ_PANGO
     PangoContext *context = gdk_pango_context_get ();
     sDPI = pango_cairo_context_get_resolution (context);
     g_object_unref (context);
+#endif
 
     if (sDPI <= 0) {
 	// Fall back to something sane
 	sDPI = 96;
     }
 }
 
 cmsHPROFILE
 gfxPlatformGtk::GetPlatformCMSOutputProfile()
 {
+#ifdef MOZ_X11
     const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
     const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE";
 
     Atom edidAtom, iccAtom;
     Display *dpy = GDK_DISPLAY();
     Window root = gdk_x11_get_default_root_xwindow();
 
     Atom retAtom;
@@ -388,10 +671,69 @@ gfxPlatformGtk::GetPlatformCMSOutputProf
                         "ICM profile read from %s successfully\n",
                         EDID1_ATOM_NAME);
             }
 #endif
 
             return profile;
         }
     }
+#endif
+
     return nsnull;
 }
+
+
+#ifndef MOZ_PANGO
+FT_Library
+gfxPlatformGtk::GetFTLibrary()
+{
+    return gPlatformFTLibrary;
+}
+
+FontFamily *
+gfxPlatformGtk::FindFontFamily(const nsAString& aName)
+{
+    nsAutoString name(aName);
+    /* FIXME: DFB */
+    //ToLowerCase(name);
+
+    nsRefPtr<FontFamily> ff;
+    if (!gPlatformFonts->Get(name, &ff)) {
+        return nsnull;
+    }
+    return ff.get();
+}
+
+FontEntry *
+gfxPlatformGtk::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
+{
+    nsRefPtr<FontFamily> ff = FindFontFamily(aName);
+    if (!ff)
+        return nsnull;
+
+    return ff->FindFontEntry(aFontStyle);
+}
+#endif
+
+
+void
+gfxPlatformGtk::SetGdkDrawable(gfxASurface *target,
+                               GdkDrawable *drawable)
+{
+    if (target->CairoStatus())
+        return;
+
+    cairo_surface_set_user_data (target->CairoSurface(),
+                                 &cairo_gdk_drawable_key,
+                                 drawable,
+                                 NULL);
+}
+
+GdkDrawable *
+gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
+{
+    if (target->CairoStatus())
+        return nsnull;
+
+    return (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(),
+                                                       &cairo_gdk_drawable_key);
+}