b=597147 part 18: use GDK's default PangoFontMap when suitable r=jfkthame
authorKarl Tomlinson <karlt+@karlt.net>
Thu, 11 Nov 2010 11:30:21 +1300
changeset 57292 f106f44c297b087dd6b503fa37c1556173dce536
parent 57291 d520361cb370a341a64a654c73d6cf363bb92a3d
child 57293 0da762e2fcdbee60774b029fb50a1c78354140e5
push idunknown
push userunknown
push dateunknown
reviewersjfkthame
bugs597147
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=597147 part 18: use GDK's default PangoFontMap when suitable r=jfkthame
configure.in
gfx/thebes/gfxPangoFonts.cpp
--- a/configure.in
+++ b/configure.in
@@ -5489,17 +5489,17 @@ dnl ====================================
 dnl = Pango
 dnl ========================================================
 if test "$MOZ_ENABLE_GTK2"
 then
     AC_SUBST(MOZ_PANGO)
 
     PKG_CHECK_MODULES(_PANGOCHK, pango >= $PANGO_VERSION)
 
-    PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION)
+    PKG_CHECK_MODULES(MOZ_PANGO, pango >= $PANGO_VERSION pangoft2 >= $PANGO_VERSION pangocairo >= $PANGO_VERSION)
     AC_SUBST(MOZ_PANGO_CFLAGS)
     AC_SUBST(MOZ_PANGO_LIBS)
     if test "$MOZ_PANGO"
     then
         AC_DEFINE(MOZ_PANGO)
     else
         PKG_CHECK_MODULES(FT2, freetype2 > 6.1.0 fontconfig)
         AC_SUBST(FT2_CFLAGS)
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -68,16 +68,17 @@
 #include "gfxUserFontSet.h"
 #include "gfxAtoms.h"
 
 #include <cairo.h>
 #include <cairo-ft.h>
 
 #include <fontconfig/fcfreetype.h>
 #include <pango/pango.h>
+#include <pango/pangocairo.h>
 #include <pango/pango-modules.h>
 #include <pango/pangofc-fontmap.h>
 
 #ifdef MOZ_WIDGET_GTK2
 #include <gdk/gdk.h>
 #endif
 
 #include <math.h>
@@ -524,18 +525,16 @@ gfxDownloadedFcFontEntry::GetPangoCovera
  * cairo_scaled_font created from an FcPattern.
  */
 
 class gfxFcFont : public gfxFT2FontBase {
 public:
     virtual ~gfxFcFont();
     static already_AddRefed<gfxFcFont>
     GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern);
-    static already_AddRefed<gfxFcFont>
-    GetOrMakeFont(FcPattern *aRenderPattern, gfxPangoFcFont *aPangoFont);
 
     virtual PRBool InitTextRun(gfxContext *aContext,
                                gfxTextRun *aTextRun,
                                const PRUnichar *aString,
                                PRUint32 aRunStart,
                                PRUint32 aRunLength,
                                PRInt32 aRunScript);
 
@@ -553,17 +552,17 @@ public:
         if (!mPangoFont) {
             MakePangoFont();
         }
         return mPangoFont;
     }
 
 private:
     static already_AddRefed<gfxFcFont> GetOrMakeFont(FcPattern *aPattern);
-    gfxFcFont(cairo_scaled_font_t *aCairoFont,
+    gfxFcFont(cairo_scaled_font_t *aCairoFont, FcPattern *aFontPattern,
               gfxFontEntry *aFontEntry, const gfxFontStyle *aFontStyle);
 
     void MakePangoFont();
 
     // For memory efficiency, this is a font pattern, not a fully resolved
     // pattern.  Only needed for constructing mPangoFont.
     nsCountedRef<FcPattern> mFontPattern;
     PangoFont *mPangoFont;
@@ -613,32 +612,25 @@ struct gfxPangoFcFont {
     NewFont(gfxFcFont *aGfxFont, FcPattern *aFontPattern);
 
     // Tell |this| that it no longer needs the gfxFcFont and the caller
     // assumes ownership of the gfxFcFont reference added at construction of
     // |this|.  The method is called just before the gfxFcFont removes the
     // last reference to |this|.
     void ForgetGfxFont() { mGfxFont = nsnull; }
 
-    gfxFcFont *GfxFont()
-    {
-        if (!mGfxFont) {
-            SetGfxFont();
-        }
-        return mGfxFont;
-    }
+    gfxFcFont *GfxFont() { return mGfxFont; }
 
     cairo_scaled_font_t *CairoFont()
     {
         return GfxFont()->CairoScaledFont();
     }
 
 private:
     void SetFontMap();
-    void SetGfxFont();
 };
 
 struct gfxPangoFcFontClass {
     PangoFcFontClass parent_class;
 };
 
 G_DEFINE_TYPE (gfxPangoFcFont, gfx_pango_fc_font, PANGO_TYPE_FC_FONT)
 
@@ -695,24 +687,16 @@ gfxPangoFcFont::SetFontMap()
         // finalize() of the font.  In Pango versions from 1.22.0 this no
         // longer happens, so we'll end up leaking the (singleton)
         // fontmap.
         fc_font->fontmap = fontmap;
         g_object_ref(fc_font->fontmap);
     }
 }
 
-void
-gfxPangoFcFont::SetGfxFont() {
-    PangoFcFont *fc_font = &parent_instance;
-
-    // Created with gfxPangoFontMap::new_font()
-    mGfxFont = gfxFcFont::GetOrMakeFont(fc_font->font_pattern, this).get();
-}
-
 static void
 gfx_pango_fc_font_init(gfxPangoFcFont *font)
 {
 }
 
 static void
 gfx_pango_fc_font_finalize(GObject *object)
 {
@@ -1433,17 +1417,19 @@ static PRBool HasChar(FcPattern *aFont, 
     FcPatternGetCharSet(aFont, FC_CHARSET, 0, &charset);
 
     return charset && FcCharSetHasChar(charset, wc);
 }
 
 /**
  * gfxPangoFontMap: An implementation of a PangoFontMap.
  *
- * This is a PangoFcFontMap for gfxPangoFcFont.
+ * This is a PangoFcFontMap for gfxPangoFcFont.  It will only ever be used if
+ * some day pango_cairo_font_map_get_default() does not return a
+ * PangoFcFontMap.
  */
 
 #define GFX_TYPE_PANGO_FONT_MAP              (gfx_pango_font_map_get_type())
 #define GFX_PANGO_FONT_MAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GFX_TYPE_PANGO_FONT_MAP, gfxPangoFontMap))
 #define GFX_IS_PANGO_FONT_MAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GFX_TYPE_PANGO_FONT_MAP))
 
 GType gfx_pango_font_map_get_type (void);
 
@@ -1472,22 +1458,51 @@ struct gfxPangoFontMapClass {
 
 G_DEFINE_TYPE (gfxPangoFontMap, gfx_pango_font_map, PANGO_TYPE_FC_FONT_MAP)
 
 static void
 gfx_pango_font_map_init(gfxPangoFontMap *fontset)
 {
 }
 
-static double
-gfx_pango_font_map_get_resolution(PangoFcFontMap *fcfontmap,
-                                  PangoContext *context)
+static PangoFcFont *
+gfx_pango_font_map_new_font(PangoFcFontMap *fontmap,
+                            FcPattern *pattern)
+{
+    // new_font is not likely to be used, but the class makes the method
+    // available and shapers have access to the class through the font.  Not
+    // bothering to make an effort here because this will only ever be used if
+    // pango_cairo_font_map_get_default() does not return a PangoFcFontMap and
+    // a shaper tried to create a different font from the one it was provided.
+    // Only a basic implementation is provided that simply refuses to
+    // create a new font.  PangoFcFontMap allows NULL return values here.
+    return NULL;
+}
+
+static void
+gfx_pango_font_map_class_init(gfxPangoFontMapClass *klass)
 {
-    // This merely enables the FC_SIZE field of the pattern to be accurate.
-    return GetDPI();
+    // inherit GObjectClass::finalize from parent as this class adds no data.
+
+    // inherit PangoFontMap::load_font (which is not likely to be used)
+    //   from PangoFcFontMap
+    // inherit PangoFontMap::list_families (which is not likely to be used)
+    //   from PangoFcFontMap
+    // inherit PangoFontMap::load_fontset (which is not likely to be used)
+    //   from PangoFcFontMap
+    // inherit PangoFontMap::shape_engine_type from PangoFcFontMap
+
+    PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (klass);
+    // default_substitute is not required.
+    // The API for create_font changed between Pango 1.22 and 1.24 so new_font
+    // is provided instead.
+    fcfontmap_class->new_font = gfx_pango_font_map_new_font;
+    // get_resolution is not required.
+    // context_key_* virtual functions are only necessary if we want to
+    // dynamically respond to changes in the screen cairo_font_options_t.
 }
 
 #ifdef MOZ_WIDGET_GTK2
 static void ApplyGdkScreenFontOptions(FcPattern *aPattern);
 #endif
 
 // Apply user settings and defaults to pattern in preparation for matching.
 static void
@@ -1533,61 +1548,16 @@ PrepareSortPattern(FcPattern *aPattern, 
         || aSizeAdjustFactor != 1.0) {
         FcPatternDel(aPattern, FC_PIXEL_SIZE);
         FcPatternAddDouble(aPattern, FC_PIXEL_SIZE, size * aSizeAdjustFactor);
     }
 
     FcDefaultSubstitute(aPattern);
 }
 
-static void
-gfx_pango_font_map_default_substitute(PangoFcFontMap *fontmap,
-                                      FcPattern *pattern)
-{
-    // The context is not available here but most of our rendering is for the
-    // screen so aIsPrinterFont is set to FALSE.
-    PrepareSortPattern(pattern, 18.0, 1.0, FALSE);
-}
-
-static PangoFcFont *
-gfx_pango_font_map_new_font(PangoFcFontMap *fontmap,
-                            FcPattern *pattern)
-{
-    return PANGO_FC_FONT(g_object_new(GFX_TYPE_PANGO_FC_FONT,
-                                      "pattern", pattern, NULL));
-}
-
-static void
-gfx_pango_font_map_class_init(gfxPangoFontMapClass *klass)
-{
-    // inherit GObjectClass::finalize from parent as this class adds no data.
-
-    // inherit PangoFontMap::load_font (which is not likely to be used)
-    //   from PangoFcFontMap
-    // inherit PangoFontMap::list_families (which is not likely to be used)
-    //   from PangoFcFontMap
-    // inherit PangoFontMap::load_fontset (which is not likely to be used)
-    //   from PangoFcFontMap
-    // inherit PangoFontMap::shape_engine_type from PangoFcFontMap
-
-    PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (klass);
-    fcfontmap_class->get_resolution = gfx_pango_font_map_get_resolution;
-    // context_key_* virtual functions are only necessary if we want to
-    // dynamically respond to changes in the screen cairo_font_options_t.
-
-    // The APIs for context_substitute/fontset_key_substitute and create_font
-    //   changed between Pango 1.22 and 1.24 so default_substitute and
-    //   new_font are provided instead.
-    // default_substitute and new_font are not likely to be used but
-    //   implemented because the class makes them available and an
-    //   implementation should provide either create_font or new_font.
-    fcfontmap_class->default_substitute = gfx_pango_font_map_default_substitute;
-    fcfontmap_class->new_font = gfx_pango_font_map_new_font;
-}
-
 /**
  ** gfxPangoFontGroup
  **/
 
 struct FamilyCallbackData {
     FamilyCallbackData(nsTArray<nsString> *aFcFamilyList,
                        gfxUserFontSet *aUserFontSet)
         : mFcFamilyList(aFcFamilyList), mUserFontSet(aUserFontSet)
@@ -1900,19 +1870,21 @@ gfxPangoFontGroup::FindFontForChar(PRUin
 
 /**
  ** gfxFcFont
  **/
 
 cairo_user_data_key_t gfxFcFont::sGfxFontKey;
 
 gfxFcFont::gfxFcFont(cairo_scaled_font_t *aCairoFont,
+                     FcPattern *aFontPattern,
                      gfxFontEntry *aFontEntry,
                      const gfxFontStyle *aFontStyle)
     : gfxFT2FontBase(aCairoFont, aFontEntry, aFontStyle),
+      mFontPattern(aFontPattern),
       mPangoFont()
 {
     cairo_scaled_font_set_user_data(mScaledFont, &sGfxFontKey, this, NULL);
 }
 
 // The gfxFcFont keeps (only) a toggle_ref on mPangoFont.
 // While mPangoFont has other references, a reference (from mPangoFont) to the
 // gfxFcFont is held.  While mPangoFont has no other references, the reference
@@ -1979,22 +1951,16 @@ gfxFcFont::InitTextRun(gfxContext *aCont
     NS_WARN_IF_FALSE(ok, "shaper failed, expect scrambled or missing text");
     return ok;
 }
 
 /* static */ void
 gfxPangoFontGroup::Shutdown()
 {
     if (gPangoFontMap) {
-        if (PANGO_IS_FC_FONT_MAP (gPangoFontMap)) {
-            // This clears circular references from the fontmap to itself
-            // through its fonts.  (This is actually unnecessary with Pango
-            // versions >= 1.22.)
-            pango_fc_font_map_shutdown(PANGO_FC_FONT_MAP(gPangoFontMap));
-        }
         g_object_unref(gPangoFontMap);
         gPangoFontMap = NULL;
     }
 
     // Resetting gFTLibrary in case this is wanted again after a
     // cairo_debug_reset_static_data.
     gFTLibrary = NULL;
 }
@@ -2125,114 +2091,103 @@ GetPixelSize(FcPattern *aPattern)
  */
 
 /* static */
 already_AddRefed<gfxFcFont>
 gfxFcFont::GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern)
 {
     nsAutoRef<FcPattern> renderPattern
         (FcFontRenderPrepare(NULL, aRequestedPattern, aFontPattern));
-    nsRefPtr<gfxFcFont> font = GetOrMakeFont(renderPattern);
-    if (!font->mFontPattern) {
-        font->mFontPattern = aFontPattern;
-    }
-    return font.forget();
-}
-
-/* static */
-already_AddRefed<gfxFcFont>
-gfxFcFont::GetOrMakeFont(FcPattern *aRenderPattern, gfxPangoFcFont *aPangoFont)
-{
-    nsRefPtr<gfxFcFont> font = GetOrMakeFont(aRenderPattern);
-    if (!font->mPangoFont) {
-        font->mPangoFont = PANGO_FONT(aPangoFont);
-        g_object_add_toggle_ref(G_OBJECT(aPangoFont),
-                                PangoFontToggleNotify, font);
-    }
-    return font.forget();
-}
-
-/* static */
-already_AddRefed<gfxFcFont>
-gfxFcFont::GetOrMakeFont(FcPattern *aPattern)
-{
-    cairo_scaled_font_t *cairoFont = CreateScaledFont(aPattern);
+
+    cairo_scaled_font_t *cairoFont = CreateScaledFont(renderPattern);
 
     nsRefPtr<gfxFcFont> font = static_cast<gfxFcFont*>
         (cairo_scaled_font_get_user_data(cairoFont, &sGfxFontKey));
 
     if (!font) {
-        gfxFloat size = GetPixelSize(aPattern);
+        gfxFloat size = GetPixelSize(renderPattern);
 
         // Shouldn't actually need to take too much care about the correct
         // name or style, as size is the only thing expected to be important.
-        PRUint8 style = gfxFontconfigUtils::GetThebesStyle(aPattern);
-        PRUint16 weight = gfxFontconfigUtils::GetThebesWeight(aPattern);
+        PRUint8 style = gfxFontconfigUtils::GetThebesStyle(renderPattern);
+        PRUint16 weight = gfxFontconfigUtils::GetThebesWeight(renderPattern);
 
         // The LangSet in the FcPattern does not have an order so there is no
         // one particular language to choose and converting the set to a
         // string through FcNameUnparse() is more trouble than it's worth.
         nsIAtom *language = gfxAtoms::en; // TODO: get the correct language?
-        // FIXME: Pass a real stretch based on aPattern!
+        // FIXME: Pass a real stretch based on renderPattern!
         gfxFontStyle fontStyle(style, weight, NS_FONT_STRETCH_NORMAL,
                                size, language, 0.0,
                                PR_TRUE, PR_FALSE, PR_FALSE,
                                NS_LITERAL_STRING(""),
                                NS_LITERAL_STRING("")); // TODO: no opentype feature support here yet
 
         nsRefPtr<gfxFontEntry> fe;
         FcChar8 *fc_file;
-        if (FcPatternGetString(aPattern,
+        if (FcPatternGetString(renderPattern,
                                FC_FILE, 0, &fc_file) == FcResultMatch) {
             int index;
-            if (FcPatternGetInteger(aPattern,
+            if (FcPatternGetInteger(renderPattern,
                                     FC_INDEX, 0, &index) != FcResultMatch) {
                 // cairo won't know what to do with this pattern.
                 NS_NOTREACHED("No index in pattern for font face from file");
                 index = 0;
             }
 
             // Get a unique name for the font face data from the file and id.
             nsAutoString name;
             AppendUTF8toUTF16(gfxFontconfigUtils::ToCString(fc_file), name);
             if (index != 0) {
                 name.AppendLiteral("/");
                 name.AppendInt(index);
             }
 
             fe = new gfxFontEntry(name);
         } else {
-            fe = GetDownloadedFontEntry(aPattern);
+            fe = GetDownloadedFontEntry(renderPattern);
             if (!fe) {
                 // cairo won't know which font to open without a file.
                 // (We don't create fonts from an FT_Face.)
                 NS_NOTREACHED("Fonts without a file is not a web font!?");
                 fe = new gfxFontEntry(nsString());
             }
         }
 
         // Note that a file/index pair (or FT_Face) and the gfxFontStyle are
         // not necessarily enough to provide a key that will describe a unique
-        // font.  cairoFont contains information from aPattern, which is a
+        // font.  cairoFont contains information from renderPattern, which is a
         // fully resolved pattern from FcFontRenderPrepare.
         // FcFontRenderPrepare takes the requested pattern and the face
         // pattern as input and can modify elements of the resulting pattern
         // that affect rendering but are not included in the gfxFontStyle.
-        font = new gfxFcFont(cairoFont, fe, &fontStyle);
+        font = new gfxFcFont(cairoFont, aFontPattern, fe, &fontStyle);
     }
 
     cairo_scaled_font_destroy(cairoFont);
     return font.forget();
 }
 
 static PangoFontMap *
 GetPangoFontMap()
 {
     if (!gPangoFontMap) {
-        gPangoFontMap = gfxPangoFontMap::NewFontMap();
+        // This is the same FontMap used by GDK, so that the same
+        // PangoCoverage cache is shared.
+        gPangoFontMap = pango_cairo_font_map_get_default();
+
+        if (PANGO_IS_FC_FONT_MAP(gPangoFontMap)) {
+            g_object_ref(gPangoFontMap);
+        } else {
+            // Future proofing: We need a PangoFcFontMap for gfxPangoFcFont.
+            // pango_cairo_font_map_get_default() is expected to return a
+            // PangoFcFontMap on Linux systems, but, just in case this ever
+            // changes, we provide our own basic implementation.
+            gPangoFontMap = gfxPangoFontMap::NewFontMap();
+        }
     }
     return gPangoFontMap;
 }
 
 gfxFcFontSet *
 gfxPangoFontGroup::GetBaseFontSet()
 {
     if (mFontSets.Length() > 0)