bug 684889 pt2 - move and rename FontFamily/Entry classes from gfxFT2Fonts to gfxFT2FontList source file. r=jdaggett
☠☠ backed out by e7895429a628 ☠ ☠
authorJonathan Kew <jfkthame@gmail.com>
Fri, 23 Sep 2011 09:53:41 +0100
changeset 77407 f4b1fa7a0f3147b20e67701f124c8b9ddfe0c447
parent 77406 864c08bd7c63049a15d501dc40827ee606f1e8ba
child 77408 e7895429a628e1299064757484072f0ec07ae480
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersjdaggett
bugs684889
milestone9.0a1
bug 684889 pt2 - move and rename FontFamily/Entry classes from gfxFT2Fonts to gfxFT2FontList source file. r=jdaggett
gfx/thebes/gfxAndroidPlatform.h
gfx/thebes/gfxFT2FontList.cpp
gfx/thebes/gfxFT2FontList.h
gfx/thebes/gfxFT2Fonts.cpp
gfx/thebes/gfxFT2Fonts.h
--- a/gfx/thebes/gfxAndroidPlatform.h
+++ b/gfx/thebes/gfxAndroidPlatform.h
@@ -39,16 +39,23 @@
 #ifndef GFX_PLATFORM_ANDROID_H
 #define GFX_PLATFORM_ANDROID_H
 
 #include "gfxFT2Fonts.h"
 #include "gfxPlatform.h"
 #include "gfxUserFontSet.h"
 #include "nsTArray.h"
 
+namespace mozilla {
+    namespace dom {
+        class FontListEntry;
+    };
+};
+using mozilla::dom::FontListEntry;
+
 typedef struct FT_LibraryRec_ *FT_Library;
 
 class THEBES_API gfxAndroidPlatform : public gfxPlatform {
 public:
     gfxAndroidPlatform();
     virtual ~gfxAndroidPlatform();
 
     static gfxAndroidPlatform *GetPlatform() {
--- a/gfx/thebes/gfxFT2FontList.cpp
+++ b/gfx/thebes/gfxFT2FontList.cpp
@@ -34,34 +34,50 @@
  * 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 ***** */
 
+#if defined(MOZ_WIDGET_GTK2)
+#include "gfxPlatformGtk.h"
+#define gfxToolkitPlatform gfxPlatformGtk
+#elif defined(MOZ_WIDGET_QT)
+#include <qfontinfo.h>
+#include "gfxQtPlatform.h"
+#define gfxToolkitPlatform gfxQtPlatform
+#elif defined(XP_WIN)
+#include "gfxWindowsPlatform.h"
+#define gfxToolkitPlatform gfxWindowsPlatform
+#elif defined(ANDROID)
+#include "mozilla/dom/ContentChild.h"
+#include "gfxAndroidPlatform.h"
+#define gfxToolkitPlatform gfxAndroidPlatform
+#endif
+
 #ifdef ANDROID
-#include "mozilla/dom/ContentChild.h"
 #include "nsXULAppAPI.h"
-
-#include "gfxAndroidPlatform.h"
 #include <dirent.h>
 #include <android/log.h>
 #define ALOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gecko" , ## args)
 #endif
 
+#include "ft2build.h"
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_TRUETYPE_TABLES_H
+#include "cairo-ft.h"
+
 #include "gfxFT2FontList.h"
+#include "gfxFT2Fonts.h"
 #include "gfxUserFontSet.h"
 #include "gfxFontUtils.h"
 
-#include "ft2build.h"
-#include FT_FREETYPE_H
-#include "gfxFT2Fonts.h"
-
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 #include "nsUnicharUtils.h"
 
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsISimpleEnumerator.h"
@@ -73,29 +89,342 @@
 #include "nsIWindowsRegKey.h"
 #include <windows.h>
 #endif
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo *gFontInfoLog = PR_NewLogModule("fontInfoLog");
 #endif /* PR_LOGGING */
 
+#undef LOG
 #define LOG(args) PR_LOG(gFontInfoLog, PR_LOG_DEBUG, args)
 #define LOG_ENABLED() PR_LOG_TEST(gFontInfoLog, PR_LOG_DEBUG)
 
 static __inline void
 BuildKeyNameFromFontName(nsAString &aName)
 {
 #ifdef XP_WIN
     if (aName.Length() >= LF_FACESIZE)
         aName.Truncate(LF_FACESIZE - 1);
 #endif
     ToLowerCase(aName);
 }
 
+/*
+ * FT2FontEntry
+ * gfxFontEntry subclass corresponding to a specific face that can be
+ * rendered by freetype. This is associated with a face index in a
+ * file (normally a .ttf/.otf file holding a single face, but in principle
+ * there could be .ttc files with multiple faces).
+ * The FT2FontEntry can create the necessary FT_Face on demand, and can
+ * then create a Cairo font_face and scaled_font for drawing.
+ */
+
+cairo_scaled_font_t *
+FT2FontEntry::CreateScaledFont(const gfxFontStyle *aStyle)
+{
+    cairo_scaled_font_t *scaledFont = NULL;
+
+    cairo_matrix_t sizeMatrix;
+    cairo_matrix_t identityMatrix;
+
+    // XXX deal with adjusted size
+    cairo_matrix_init_scale(&sizeMatrix, aStyle->size, aStyle->size);
+    cairo_matrix_init_identity(&identityMatrix);
+
+    // synthetic oblique by skewing via the font matrix
+    PRBool needsOblique = !IsItalic() &&
+            (aStyle->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();
+
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+    cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
+#endif
+
+    scaledFont = cairo_scaled_font_create(CairoFontFace(),
+                                          &sizeMatrix,
+                                          &identityMatrix, fontOptions);
+    cairo_font_options_destroy(fontOptions);
+
+    NS_ASSERTION(cairo_scaled_font_status(scaledFont) == CAIRO_STATUS_SUCCESS,
+                 "Failed to make scaled font");
+
+    return scaledFont;
+}
+
+FT2FontEntry::~FT2FontEntry()
+{
+    // Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
+    mFTFace = nsnull;
+
+#ifndef ANDROID
+    if (mFontFace) {
+        cairo_font_face_destroy(mFontFace);
+        mFontFace = nsnull;
+    }
+#endif
+}
+
+gfxFont*
+FT2FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
+{
+    cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontStyle);
+    gfxFont *font = new gfxFT2Font(scaledFont, this, aFontStyle, aNeedsBold);
+    cairo_scaled_font_destroy(scaledFont);
+    return font;
+}
+
+/* static */
+FT2FontEntry*
+FT2FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
+                              const PRUint8 *aFontData,
+                              PRUint32 aLength)
+{
+    // Ownership of aFontData is passed in here; the fontEntry must
+    // retain it as long as the FT_Face needs it, and ensure it is
+    // eventually deleted.
+    FT_Face face;
+    FT_Error error =
+        FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
+                           aFontData, aLength, 0, &face);
+    if (error != FT_Err_Ok) {
+        NS_Free((void*)aFontData);
+        return nsnull;
+    }
+    FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(face, nsnull, 0, aFontData);
+    if (fe) {
+        fe->mItalic = aProxyEntry.mItalic;
+        fe->mWeight = aProxyEntry.mWeight;
+        fe->mStretch = aProxyEntry.mStretch;
+    }
+    return fe;
+}
+
+class FTUserFontData {
+public:
+    FTUserFontData(FT_Face aFace, const PRUint8* aData)
+        : mFace(aFace), mFontData(aData)
+    {
+    }
+
+    ~FTUserFontData()
+    {
+        FT_Done_Face(mFace);
+        if (mFontData) {
+            NS_Free((void*)mFontData);
+        }
+    }
+
+private:
+    FT_Face        mFace;
+    const PRUint8 *mFontData;
+};
+
+static void
+FTFontDestroyFunc(void *data)
+{
+    FTUserFontData *userFontData = static_cast<FTUserFontData*>(data);
+    delete userFontData;
+}
+
+/* static */
+FT2FontEntry*
+FT2FontEntry::CreateFontEntry(const FontListEntry& aFLE)
+{
+    FT2FontEntry *fe = new FT2FontEntry(aFLE.faceName());
+    fe->mFilename = aFLE.filepath();
+    fe->mFTFontIndex = aFLE.index();
+    fe->mWeight = aFLE.weight();
+    fe->mStretch = aFLE.stretch();
+    fe->mItalic = aFLE.italic();
+    return fe;
+}
+
+/* static */
+FT2FontEntry*
+FT2FontEntry::CreateFontEntry(FT_Face aFace,
+                              const char* aFilename, PRUint8 aIndex,
+                              const PRUint8 *aFontData)
+{
+    static cairo_user_data_key_t key;
+
+    if (!aFace->family_name) {
+        FT_Done_Face(aFace);
+        return nsnull;
+    }
+    // Construct font name from family name and style name, regular fonts
+    // do not have the modifier by convention.
+    NS_ConvertUTF8toUTF16 fontName(aFace->family_name);
+    if (aFace->style_name && strcmp("Regular", aFace->style_name)) {
+        fontName.AppendLiteral(" ");
+        AppendUTF8toUTF16(aFace->style_name, fontName);
+    }
+    FT2FontEntry *fe = new FT2FontEntry(fontName);
+    fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
+    fe->mFTFace = aFace;
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+    fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
+#else
+    fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
+#endif
+    fe->mFilename = aFilename;
+    fe->mFTFontIndex = aIndex;
+    FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
+    cairo_font_face_set_user_data(fe->mFontFace, &key,
+                                  userFontData, FTFontDestroyFunc);
+
+    TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(aFace, ft_sfnt_os2));
+    PRUint16 os2weight = 0;
+    if (os2 && os2->version != 0xffff) {
+        // Technically, only 100 to 900 are valid, but some fonts
+        // have this set wrong -- e.g. "Microsoft Logo Bold Italic" has
+        // it set to 6 instead of 600.  We try to be nice and handle that
+        // as well.
+        if (os2->usWeightClass >= 100 && os2->usWeightClass <= 900)
+            os2weight = os2->usWeightClass;
+        else if (os2->usWeightClass >= 1 && os2->usWeightClass <= 9)
+            os2weight = os2->usWeightClass * 100;
+    }
+
+    if (os2weight != 0)
+        fe->mWeight = os2weight;
+    else if (aFace->style_flags & FT_STYLE_FLAG_BOLD)
+        fe->mWeight = 700;
+    else
+        fe->mWeight = 400;
+
+    NS_ASSERTION(fe->mWeight >= 100 && fe->mWeight <= 900, "Invalid final weight in font!");
+
+    return fe;
+}
+
+FT2FontEntry*
+gfxFT2Font::GetFontEntry()
+{
+    return static_cast<FT2FontEntry*> (mFontEntry.get());
+}
+
+cairo_font_face_t *
+FT2FontEntry::CairoFontFace()
+{
+    static cairo_user_data_key_t key;
+
+    if (!mFontFace) {
+        FT_Face face;
+        FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
+        mFTFace = face;
+#ifdef MOZ_GFX_OPTIMIZE_MOBILE
+        mFontFace = cairo_ft_font_face_create_for_ft_face(face, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
+#else
+        mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
+#endif
+        FTUserFontData *userFontData = new FTUserFontData(face, nsnull);
+        cairo_font_face_set_user_data(mFontFace, &key,
+                                      userFontData, FTFontDestroyFunc);
+    }
+    return mFontFace;
+}
+
+nsresult
+FT2FontEntry::ReadCMAP()
+{
+    if (mCmapInitialized) {
+        return NS_OK;
+    }
+
+    // attempt this once, if errors occur leave a blank cmap
+    mCmapInitialized = PR_TRUE;
+
+    AutoFallibleTArray<PRUint8,16384> buffer;
+    nsresult rv = GetFontTable(TTAG_cmap, buffer);
+    
+    if (NS_SUCCEEDED(rv)) {
+        PRPackedBool unicodeFont;
+        PRPackedBool symbolFont;
+        rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
+                                    mCharacterMap, mUVSOffset,
+                                    unicodeFont, symbolFont);
+    }
+
+    mHasCmapTable = NS_SUCCEEDED(rv);
+    return rv;
+}
+
+nsresult
+FT2FontEntry::GetFontTable(PRUint32 aTableTag,
+                           FallibleTArray<PRUint8>& aBuffer)
+{
+    // Ensure existence of mFTFace
+    CairoFontFace();
+    NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);
+
+    FT_Error status;
+    FT_ULong len = 0;
+    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
+    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
+
+    if (!aBuffer.SetLength(len)) {
+        return NS_ERROR_OUT_OF_MEMORY;
+    }
+    PRUint8 *buf = aBuffer.Elements();
+    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
+    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
+
+    return NS_OK;
+}
+
+/*
+ * FT2FontFamily
+ * A standard gfxFontFamily; just adds a method used to support sending
+ * the font list from chrome to content via IPC.
+ */
+
+void
+FT2FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
+{
+    for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) {
+        const FT2FontEntry *fe =
+            static_cast<const FT2FontEntry*>(mAvailableFonts[i].get());
+        if (!fe) {
+            continue;
+        }
+        
+        aFontList->AppendElement(FontListEntry(Name(), fe->Name(),
+                                               fe->mFilename,
+                                               fe->Weight(), fe->Stretch(),
+                                               fe->IsItalic(),
+                                               fe->mFTFontIndex));
+    }
+}
+
+/*
+ * Startup cache support for the font list:
+ * We store the list of families and faces, with their style attributes and the
+ * corresponding font files, in the startup cache.
+ * This allows us to recreate the gfxFT2FontList collection of families and
+ * faces without instantiating Freetype faces for each font file (in order to
+ * find their attributes), leading to significantly quicker startup.
+ */
+
 #define CACHE_KEY "font.cached-list"
 
 class FontNameCache {
 public:
     FontNameCache()
         : mWriteNeeded(PR_FALSE)
     {
         mOps = (PLDHashTableOps) {
@@ -304,21 +633,16 @@ private:
 /***************************************************************
  *
  * gfxFT2FontList
  *
  */
 
 // For Mobile, we use gfxFT2Fonts, and we build the font list by directly
 // scanning the system's Fonts directory for OpenType and TrueType files.
-//
-// FontEntry is currently defined in gfxFT2Fonts.h, but should probably be
-// moved here for consistency with other platform implementations, and
-// because it logically "belongs" to the fontlist that manages the families
-// and entries.
 
 gfxFT2FontList::gfxFT2FontList()
 {
 }
 
 void
 gfxFT2FontList::AppendFacesFromCachedFaceList(nsCString& aFileName,
                                               PRBool aStdFile,
@@ -363,17 +687,17 @@ gfxFT2FontList::AppendFacesFromCachedFac
 
         beginning = end + 1;
         end = strchr(beginning, ',');
     }
 }
 
 static void
 AppendToFaceList(nsCString& aFaceList,
-                 nsAString& aFamilyName, FontEntry* aFontEntry)
+                 nsAString& aFamilyName, FT2FontEntry* aFontEntry)
 {
     aFaceList.Append(NS_ConvertUTF16toUTF8(aFamilyName));
     aFaceList.Append(',');
     aFaceList.Append(NS_ConvertUTF16toUTF8(aFontEntry->Name()));
     aFaceList.Append(',');
     aFaceList.AppendInt(aFontEntry->mFTFontIndex);
     aFaceList.Append(',');
     aFaceList.Append(aFontEntry->IsItalic() ? '1' : '0');
@@ -417,23 +741,24 @@ gfxFT2FontList::AppendFacesFromFontFile(
         timestamp = s.st_mtime;
         filesize = s.st_size;
         for (FT_Long i = 0; i < dummy->num_faces; i++) {
             FT_Face face;
             if (FT_Err_Ok != FT_New_Face(ftLibrary, aFileName.get(), i, &face)) {
                 continue;
             }
 
-            FontEntry* fe = FontEntry::CreateFontEntry(face, aFileName.get(), i);
+            FT2FontEntry* fe =
+                FT2FontEntry::CreateFontEntry(face, aFileName.get(), i);
             if (fe) {
                 NS_ConvertUTF8toUTF16 name(face->family_name);
                 BuildKeyNameFromFontName(name);       
                 gfxFontFamily *family = mFontFamilies.GetWeak(name);
                 if (!family) {
-                    family = new gfxFontFamily(name);
+                    family = new FT2FontFamily(name);
                     mFontFamilies.Put(name, family);
                     if (mBadUnderlineFamilyNames.Contains(name)) {
                         family->SetBadUnderlineFamily();
                     }
                 }
                 fe->mStandardFace = aStdFile;
                 family->AddFontEntry(fe);
                 if (family->IsBadUnderlineFamily()) {
@@ -627,23 +952,23 @@ gfxFT2FontList::FindFonts()
     mFontFamilies.Enumerate(FinalizeFamilyMemberList, this);
 #endif // XP_WIN && ANDROID
 }
 
 void
 gfxFT2FontList::AppendFaceFromFontListEntry(const FontListEntry& aFLE,
                                             PRBool aStdFile)
 {
-    FontEntry* fe = FontEntry::CreateFontEntry(aFLE);
+    FT2FontEntry* fe = FT2FontEntry::CreateFontEntry(aFLE);
     if (fe) {
         fe->mStandardFace = aStdFile;
         nsAutoString name(aFLE.familyName());
         gfxFontFamily *family = mFontFamilies.GetWeak(name);
         if (!family) {
-            family = new gfxFontFamily(name);
+            family = new FT2FontFamily(name);
             mFontFamilies.Put(name, family);
             if (mBadUnderlineFamilyNames.Contains(name)) {
                 family->SetBadUnderlineFamily();
             }
         }
         family->AddFontEntry(fe);
         if (family->IsBadUnderlineFamily()) {
             fe->mIsBadUnderlineFont = PR_TRUE;
@@ -654,17 +979,17 @@ gfxFT2FontList::AppendFaceFromFontListEn
 static PLDHashOperator
 AddFamilyToFontList(nsStringHashKey::KeyType aKey,
                     nsRefPtr<gfxFontFamily>& aFamily,
                     void* aUserArg)
 {
     InfallibleTArray<FontListEntry>* fontlist =
         reinterpret_cast<InfallibleTArray<FontListEntry>*>(aUserArg);
 
-    FontFamily *family = static_cast<FontFamily*>(aFamily.get());
+    FT2FontFamily *family = static_cast<FT2FontFamily*>(aFamily.get());
     family->AddFacesToFontList(fontlist);
 
     return PL_DHASH_NEXT;
 }
 
 void
 gfxFT2FontList::GetFontList(InfallibleTArray<FontListEntry>* retValue)
 {
@@ -718,17 +1043,17 @@ FindFullName(nsStringHashKey::KeyType aK
         }
     }
 
     return PL_DHASH_NEXT;
 }
 
 gfxFontEntry* 
 gfxFT2FontList::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
-                                       const nsAString& aFontName)
+                                const nsAString& aFontName)
 {
     // walk over list of names
     FullFontNameSearch data(aFontName);
 
     mFontFamilies.Enumerate(FindFullName, &data);
 
     return data.mFontEntry;
 }
@@ -757,10 +1082,11 @@ gfxFT2FontList::GetDefaultFont(const gfx
 gfxFontEntry*
 gfxFT2FontList::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
                                  const PRUint8 *aFontData,
                                  PRUint32 aLength)
 {
     // The FT2 font needs the font data to persist, so we do NOT free it here
     // but instead pass ownership to the font entry.
     // Deallocation will happen later, when the font face is destroyed.
-    return FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
+    return FT2FontEntry::CreateFontEntry(*aProxyEntry, aFontData, aLength);
 }
+
--- a/gfx/thebes/gfxFT2FontList.h
+++ b/gfx/thebes/gfxFT2FontList.h
@@ -50,16 +50,79 @@
 namespace mozilla {
     namespace dom {
         class FontListEntry;
     };
 };
 using mozilla::dom::FontListEntry;
 
 class FontNameCache;
+typedef struct FT_FaceRec_* FT_Face;
+
+class FT2FontEntry : public gfxFontEntry
+{
+public:
+    FT2FontEntry(const nsAString& aFaceName) :
+        gfxFontEntry(aFaceName)
+    {
+        mFTFace = nsnull;
+        mFontFace = nsnull;
+        mFTFontIndex = 0;
+    }
+
+    ~FT2FontEntry();
+
+    const nsString& GetName() const {
+        return Name();
+    }
+
+    // create a font entry for a downloaded font
+    static FT2FontEntry* 
+    CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
+                    const PRUint8 *aFontData, PRUint32 aLength);
+
+    // create a font entry representing an installed font, identified by
+    // a FontListEntry; the freetype and cairo faces will not be instantiated
+    // until actually needed
+    static FT2FontEntry*
+    CreateFontEntry(const FontListEntry& aFLE);
+
+    // create a font entry for a given freetype face; if it is an installed font,
+    // also record the filename and index
+    static FT2FontEntry* 
+    CreateFontEntry(FT_Face aFace, const char *aFilename, PRUint8 aIndex,
+                    const PRUint8 *aFontData = nsnull);
+        // aFontData is NS_Malloc'ed data that aFace depends on, to be freed
+        // after the face is destroyed; null if there is no such buffer
+
+    virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle,
+                                        PRBool aNeedsBold);
+
+    cairo_font_face_t *CairoFontFace();
+    cairo_scaled_font_t *CreateScaledFont(const gfxFontStyle *aStyle);
+
+    nsresult ReadCMAP();
+    nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
+
+    FT_Face mFTFace;
+    cairo_font_face_t *mFontFace;
+
+    nsCString mFilename;
+    PRUint8 mFTFontIndex;
+};
+
+class FT2FontFamily : public gfxFontFamily
+{
+public:
+    FT2FontFamily(const nsAString& aName) :
+        gfxFontFamily(aName) { }
+
+    // Append this family's faces to the IPC fontlist
+    void AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList);
+};
 
 class gfxFT2FontList : public gfxPlatformFontList
 {
 public:
     gfxFT2FontList();
 
     virtual gfxFontEntry* GetDefaultFont(const gfxFontStyle* aStyle,
                                          PRBool& aNeedsBold);
--- a/gfx/thebes/gfxFT2Fonts.cpp
+++ b/gfx/thebes/gfxFT2Fonts.cpp
@@ -39,32 +39,27 @@
 #define gfxToolkitPlatform gfxPlatformGtk
 #elif defined(MOZ_WIDGET_QT)
 #include <qfontinfo.h>
 #include "gfxQtPlatform.h"
 #define gfxToolkitPlatform gfxQtPlatform
 #elif defined(XP_WIN)
 #include "gfxWindowsPlatform.h"
 #define gfxToolkitPlatform gfxWindowsPlatform
-#include "gfxFT2FontList.h"
 #elif defined(ANDROID)
-#include "mozilla/dom/ContentChild.h"
 #include "gfxAndroidPlatform.h"
 #define gfxToolkitPlatform gfxAndroidPlatform
 #endif
 
 #include "gfxTypes.h"
 #include "gfxFT2Fonts.h"
 #include "gfxFT2FontBase.h"
 #include "gfxFT2Utils.h"
+#include "gfxFT2FontList.h"
 #include <locale.h>
-#include "cairo-ft.h"
-#include FT_TRUETYPE_TAGS_H
-#include FT_TRUETYPE_TABLES_H
-#include "gfxFontUtils.h"
 #include "gfxHarfBuzzShaper.h"
 #include "gfxUnicodeProperties.h"
 #include "gfxAtoms.h"
 #include "nsTArray.h"
 #include "nsUnicodeRange.h"
 #include "nsCRT.h"
 
 #include "prlog.h"
@@ -77,312 +72,16 @@ static PRLogModuleInfo *gFontLog = PR_Ne
 // 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 cairo_scaled_font_t *
-CreateScaledFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle)
-{
-    cairo_scaled_font_t *scaledFont = NULL;
-
-    cairo_matrix_t sizeMatrix;
-    cairo_matrix_t identityMatrix;
-
-    // XXX deal with adjusted size
-    cairo_matrix_init_scale(&sizeMatrix, aStyle->size, aStyle->size);
-    cairo_matrix_init_identity(&identityMatrix);
-
-    // synthetic oblique by skewing via the font matrix
-    PRBool needsOblique =
-        !aFontEntry->mItalic &&
-            (aStyle->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();
-
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
-    cairo_font_options_set_hint_metrics(fontOptions, CAIRO_HINT_METRICS_OFF);
-#endif
-
-    scaledFont = cairo_scaled_font_create(aFontEntry->CairoFontFace(),
-                                          &sizeMatrix,
-                                          &identityMatrix, fontOptions);
-    cairo_font_options_destroy(fontOptions);
-
-    NS_ASSERTION(cairo_scaled_font_status(scaledFont) == CAIRO_STATUS_SUCCESS,
-                 "Failed to make scaled font");
-
-    return scaledFont;
-}
-
-/**
- * FontEntry
- */
-
-FontEntry::~FontEntry()
-{
-    // Do nothing for mFTFace here since FTFontDestroyFunc is called by cairo.
-    mFTFace = nsnull;
-
-#ifndef ANDROID
-    if (mFontFace) {
-        cairo_font_face_destroy(mFontFace);
-        mFontFace = nsnull;
-    }
-#endif
-}
-
-gfxFont*
-FontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold)
-{
-    cairo_scaled_font_t *scaledFont = CreateScaledFont(this, aFontStyle);
-    gfxFont *font = new gfxFT2Font(scaledFont, this, aFontStyle, aNeedsBold);
-    cairo_scaled_font_destroy(scaledFont);
-    return font;
-}
-
-/* static */
-FontEntry*
-FontEntry::CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
-                           const PRUint8 *aFontData,
-                           PRUint32 aLength)
-{
-    // Ownership of aFontData is passed in here; the fontEntry must
-    // retain it as long as the FT_Face needs it, and ensure it is
-    // eventually deleted.
-    FT_Face face;
-    FT_Error error =
-        FT_New_Memory_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(),
-                           aFontData, aLength, 0, &face);
-    if (error != FT_Err_Ok) {
-        NS_Free((void*)aFontData);
-        return nsnull;
-    }
-    FontEntry* fe = FontEntry::CreateFontEntry(face, nsnull, 0, aFontData);
-    if (fe) {
-        fe->mItalic = aProxyEntry.mItalic;
-        fe->mWeight = aProxyEntry.mWeight;
-        fe->mStretch = aProxyEntry.mStretch;
-    }
-    return fe;
-}
-
-class FTUserFontData {
-public:
-    FTUserFontData(FT_Face aFace, const PRUint8* aData)
-        : mFace(aFace), mFontData(aData)
-    {
-    }
-
-    ~FTUserFontData()
-    {
-        FT_Done_Face(mFace);
-        if (mFontData) {
-            NS_Free((void*)mFontData);
-        }
-    }
-
-private:
-    FT_Face        mFace;
-    const PRUint8 *mFontData;
-};
-
-static void
-FTFontDestroyFunc(void *data)
-{
-    FTUserFontData *userFontData = static_cast<FTUserFontData*>(data);
-    delete userFontData;
-}
-
-/* static */ FontEntry*
-FontEntry::CreateFontEntry(const FontListEntry& aFLE)
-{
-    FontEntry *fe = new FontEntry(aFLE.faceName());
-    fe->mFilename = aFLE.filepath();
-    fe->mFTFontIndex = aFLE.index();
-    fe->mWeight = aFLE.weight();
-    fe->mStretch = aFLE.stretch();
-    fe->mItalic = aFLE.italic();
-    return fe;
-}
-
-/* static */ FontEntry*
-FontEntry::CreateFontEntry(FT_Face aFace,
-                           const char* aFilename, PRUint8 aIndex,
-                           const PRUint8 *aFontData)
-{
-    static cairo_user_data_key_t key;
-
-    if (!aFace->family_name) {
-        FT_Done_Face(aFace);
-        return nsnull;
-    }
-    // Construct font name from family name and style name, regular fonts
-    // do not have the modifier by convention.
-    NS_ConvertUTF8toUTF16 fontName(aFace->family_name);
-    if (aFace->style_name && strcmp("Regular", aFace->style_name)) {
-        fontName.AppendLiteral(" ");
-        AppendUTF8toUTF16(aFace->style_name, fontName);
-    }
-    FontEntry *fe = new FontEntry(fontName);
-    fe->mItalic = aFace->style_flags & FT_STYLE_FLAG_ITALIC;
-    fe->mFTFace = aFace;
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
-    fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
-#else
-    fe->mFontFace = cairo_ft_font_face_create_for_ft_face(aFace, 0);
-#endif
-    fe->mFilename = aFilename;
-    fe->mFTFontIndex = aIndex;
-    FTUserFontData *userFontData = new FTUserFontData(aFace, aFontData);
-    cairo_font_face_set_user_data(fe->mFontFace, &key,
-                                  userFontData, FTFontDestroyFunc);
-
-    TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(aFace, ft_sfnt_os2));
-    PRUint16 os2weight = 0;
-    if (os2 && os2->version != 0xffff) {
-        // Technically, only 100 to 900 are valid, but some fonts
-        // have this set wrong -- e.g. "Microsoft Logo Bold Italic" has
-        // it set to 6 instead of 600.  We try to be nice and handle that
-        // as well.
-        if (os2->usWeightClass >= 100 && os2->usWeightClass <= 900)
-            os2weight = os2->usWeightClass;
-        else if (os2->usWeightClass >= 1 && os2->usWeightClass <= 9)
-            os2weight = os2->usWeightClass * 100;
-    }
-
-    if (os2weight != 0)
-        fe->mWeight = os2weight;
-    else if (aFace->style_flags & FT_STYLE_FLAG_BOLD)
-        fe->mWeight = 700;
-    else
-        fe->mWeight = 400;
-
-    NS_ASSERTION(fe->mWeight >= 100 && fe->mWeight <= 900, "Invalid final weight in font!");
-
-    return fe;
-}
-
-FontEntry*
-gfxFT2Font::GetFontEntry()
-{
-    return static_cast<FontEntry*> (mFontEntry.get());
-}
-
-cairo_font_face_t *
-FontEntry::CairoFontFace()
-{
-    static cairo_user_data_key_t key;
-
-    if (!mFontFace) {
-        FT_Face face;
-        FT_New_Face(gfxToolkitPlatform::GetPlatform()->GetFTLibrary(), mFilename.get(), mFTFontIndex, &face);
-        mFTFace = face;
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
-        mFontFace = cairo_ft_font_face_create_for_ft_face(face, FT_LOAD_NO_AUTOHINT | FT_LOAD_NO_HINTING);
-#else
-        mFontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
-#endif
-        FTUserFontData *userFontData = new FTUserFontData(face, nsnull);
-        cairo_font_face_set_user_data(mFontFace, &key,
-                                      userFontData, FTFontDestroyFunc);
-    }
-    return mFontFace;
-}
-
-nsresult
-FontEntry::ReadCMAP()
-{
-    if (mCmapInitialized) {
-        return NS_OK;
-    }
-
-    // attempt this once, if errors occur leave a blank cmap
-    mCmapInitialized = PR_TRUE;
-
-    AutoFallibleTArray<PRUint8,16384> buffer;
-    nsresult rv = GetFontTable(TTAG_cmap, buffer);
-    
-    if (NS_SUCCEEDED(rv)) {
-        PRPackedBool unicodeFont;
-        PRPackedBool symbolFont;
-        rv = gfxFontUtils::ReadCMAP(buffer.Elements(), buffer.Length(),
-                                    mCharacterMap, mUVSOffset,
-                                    unicodeFont, symbolFont);
-    }
-
-    mHasCmapTable = NS_SUCCEEDED(rv);
-    return rv;
-}
-
-nsresult
-FontEntry::GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer)
-{
-    // Ensure existence of mFTFace
-    CairoFontFace();
-    NS_ENSURE_TRUE(mFTFace, NS_ERROR_FAILURE);
-
-    FT_Error status;
-    FT_ULong len = 0;
-    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nsnull, &len);
-    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
-    NS_ENSURE_TRUE(len != 0, NS_ERROR_FAILURE);
-
-    if (!aBuffer.SetLength(len)) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    PRUint8 *buf = aBuffer.Elements();
-    status = FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, buf, &len);
-    NS_ENSURE_TRUE(status == 0, NS_ERROR_FAILURE);
-
-    return NS_OK;
-}
-
-FontEntry *
-FontFamily::FindFontEntry(const gfxFontStyle& aFontStyle)
-{
-    PRBool needsBold = PR_FALSE;
-    return static_cast<FontEntry*>(FindFontForStyle(aFontStyle, needsBold));
-}
-
-void
-FontFamily::AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList)
-{
-    for (int i = 0, n = mAvailableFonts.Length(); i < n; ++i) {
-        const FontEntry *fe =
-            static_cast<const FontEntry*>(mAvailableFonts[i].get());
-        if (!fe) {
-            continue;
-        }
-        
-        aFontList->AppendElement(FontListEntry(Name(), fe->Name(),
-                                               fe->mFilename,
-                                               fe->Weight(), fe->Stretch(),
-                                               fe->IsItalic(),
-                                               fe->mFTFontIndex));
-    }
-}
-
 #ifndef ANDROID // not needed on Android, we use the generic gfxFontGroup
 /**
  * gfxFT2FontGroup
  */
 
 PRBool
 gfxFT2FontGroup::FontCallback(const nsAString& fontName,
                               const nsACString& genericName,
@@ -847,17 +546,17 @@ gfxFT2Font::AddRange(gfxTextRun *aTextRu
             details.mYOffset = 0;
             g.SetComplex(aTextRun->IsClusterStart(offset + i), PR_TRUE, 1);
             aTextRun->SetGlyphs(offset + i, g, &details);
         }
     }
 }
 
 gfxFT2Font::gfxFT2Font(cairo_scaled_font_t *aCairoFont,
-                       FontEntry *aFontEntry,
+                       FT2FontEntry *aFontEntry,
                        const gfxFontStyle *aFontStyle,
                        PRBool aNeedsBold)
     : gfxFT2FontBase(aCairoFont, aFontEntry, aFontStyle)
 {
     NS_ASSERTION(mFontEntry, "Unable to find font entry for font.  Something is whack.");
     mApplySyntheticBold = aNeedsBold;
     mCharGlyphCache.Init(64);
 }
@@ -876,34 +575,36 @@ gfxFT2Font::CairoFontFace()
  * 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.
  */
 #ifndef ANDROID // this is only for gfxFT2FontGroup, which is not used on Android
 already_AddRefed<gfxFT2Font>
 gfxFT2Font::GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle, PRBool aNeedsBold)
 {
-    FontEntry *fe = static_cast<FontEntry*>
+    FT2FontEntry *fe = static_cast<FT2FontEntry*>
         (gfxToolkitPlatform::GetPlatform()->FindFontEntry(aName, *aStyle));
     if (!fe) {
         NS_WARNING("Failed to find font entry for font!");
         return nsnull;
     }
 
     nsRefPtr<gfxFT2Font> font = GetOrMakeFont(fe, aStyle, aNeedsBold);
     return font.forget();
 }
 #endif
 
 already_AddRefed<gfxFT2Font>
-gfxFT2Font::GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNeedsBold)
+gfxFT2Font::GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
+                          PRBool aNeedsBold)
 {
-    nsRefPtr<gfxFont> font = gfxFontCache::GetCache()->Lookup(aFontEntry, aStyle);
+    nsRefPtr<gfxFont> font =
+        gfxFontCache::GetCache()->Lookup(aFontEntry, aStyle);
     if (!font) {
-        cairo_scaled_font_t *scaledFont = CreateScaledFont(aFontEntry, aStyle);
+        cairo_scaled_font_t *scaledFont = aFontEntry->CreateScaledFont(aStyle);
         font = new gfxFT2Font(scaledFont, aFontEntry, aStyle, aNeedsBold);
         cairo_scaled_font_destroy(scaledFont);
         if (!font)
             return nsnull;
         gfxFontCache::GetCache()->AddNew(font);
     }
     gfxFont *f = nsnull;
     font.swap(f);
--- a/gfx/thebes/gfxFT2Fonts.h
+++ b/gfx/thebes/gfxFT2Fonts.h
@@ -42,113 +42,39 @@
 #include "cairo.h"
 #include "gfxTypes.h"
 #include "gfxFont.h"
 #include "gfxFT2FontBase.h"
 #include "gfxContext.h"
 #include "gfxFontUtils.h"
 #include "gfxUserFontSet.h"
 
-namespace mozilla {
-    namespace dom {
-        class FontListEntry;
-    };
-};
-using mozilla::dom::FontListEntry;
-
-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 gfxFontFamily
-{
-public:
-    FontFamily(const nsAString& aName) :
-        gfxFontFamily(aName) { }
-
-    FontEntry *FindFontEntry(const gfxFontStyle& aFontStyle);
-
-    // Append this family's faces to the IPC fontlist
-    void AddFacesToFontList(InfallibleTArray<FontListEntry>* aFontList);
-};
-
-class FontEntry : public gfxFontEntry
-{
-public:
-    FontEntry(const nsAString& aFaceName) :
-        gfxFontEntry(aFaceName)
-    {
-        mFTFace = nsnull;
-        mFontFace = nsnull;
-        mFTFontIndex = 0;
-    }
-
-    ~FontEntry();
-
-    const nsString& GetName() const {
-        return Name();
-    }
-
-    // create a font entry for a downloaded font
-    static FontEntry* 
-    CreateFontEntry(const gfxProxyFontEntry &aProxyEntry,
-                    const PRUint8 *aFontData, PRUint32 aLength);
-
-    // create a font entry representing an installed font, identified by
-    // a FontListEntry; the freetype and cairo faces will not be instantiated
-    // until actually needed
-    static FontEntry*
-    CreateFontEntry(const FontListEntry& aFLE);
-
-    // create a font entry for a given freetype face; if it is an installed font,
-    // also record the filename and index
-    static FontEntry* 
-    CreateFontEntry(FT_Face aFace, const char *aFilename, PRUint8 aIndex,
-                    const PRUint8 *aFontData = nsnull);
-        // aFontData is NS_Malloc'ed data that aFace depends on, to be freed
-        // after the face is destroyed; null if there is no such buffer
-
-    virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, PRBool aNeedsBold);
-
-    cairo_font_face_t *CairoFontFace();
-    nsresult ReadCMAP();
-
-    nsresult GetFontTable(PRUint32 aTableTag, FallibleTArray<PRUint8>& aBuffer);
-
-    FT_Face mFTFace;
-    cairo_font_face_t *mFontFace;
-
-    nsCString mFilename;
-    PRUint8 mFTFontIndex;
-};
-
+class FT2FontEntry;
 
 class gfxFT2Font : public gfxFT2FontBase {
 public: // new functions
     gfxFT2Font(cairo_scaled_font_t *aCairoFont,
-               FontEntry *aFontEntry,
+               FT2FontEntry *aFontEntry,
                const gfxFontStyle *aFontStyle,
                PRBool aNeedsBold);
     virtual ~gfxFT2Font ();
 
     cairo_font_face_t *CairoFontFace();
 
-    FontEntry *GetFontEntry();
+    FT2FontEntry *GetFontEntry();
 
 #ifndef ANDROID
     static already_AddRefed<gfxFT2Font>
-    GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle, PRBool aNeedsBold = PR_FALSE);
+    GetOrMakeFont(const nsAString& aName, const gfxFontStyle *aStyle,
+                  PRBool aNeedsBold = PR_FALSE);
 #endif
 
     static already_AddRefed<gfxFT2Font>
-    GetOrMakeFont(FontEntry *aFontEntry, const gfxFontStyle *aStyle, PRBool aNeedsBold = PR_FALSE);
+    GetOrMakeFont(FT2FontEntry *aFontEntry, const gfxFontStyle *aStyle,
+                  PRBool aNeedsBold = PR_FALSE);
 
     struct CachedGlyphData {
         CachedGlyphData()
             : glyphIndex(0xffffffffU) { }
 
         CachedGlyphData(PRUint32 gid)
             : glyphIndex(gid) { }