Bug 833169 - add font family name to font entries and use in user font cache key. r=jkew
authorJohn Daggett <jdaggett@mozilla.com>
Mon, 18 Feb 2013 11:22:55 +0900
changeset 122199 820dff9bdc55add3299ad566fb44070cd762b29b
parent 122198 8a5523cc2812c8290d79ac419b0d80901ff84563
child 122200 da82798eb2751aca52f3802a6540db180a591c20
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjkew
bugs833169
milestone21.0a1
Bug 833169 - add font family name to font entries and use in user font cache key. r=jkew
accessible/src/base/TextAttrs.cpp
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxPangoFonts.cpp
gfx/thebes/gfxPangoFonts.h
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
layout/inspector/src/nsFontFace.cpp
layout/mathml/nsMathMLChar.cpp
--- a/accessible/src/base/TextAttrs.cpp
+++ b/accessible/src/base/TextAttrs.cpp
@@ -446,17 +446,19 @@ TextAttrsMgr::FontFamilyTextAttr::
 bool
 TextAttrsMgr::FontFamilyTextAttr::
   GetFontFamily(nsIFrame* aFrame, nsString& aFamily)
 {
   nsRefPtr<nsFontMetrics> fm;
   nsLayoutUtils::GetFontMetricsForFrame(aFrame, getter_AddRefs(fm));
 
   gfxFontGroup* fontGroup = fm->GetThebesFontGroup();
-  aFamily = fontGroup->GetFamilyNameAt(0);
+  gfxFont* font = fontGroup->GetFontAt(0);
+  gfxFontEntry* fontEntry = font->GetFontEntry();
+  aFamily = fontEntry->FamilyName();
   return true;
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // FontSizeTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -163,31 +163,16 @@ uint16_t gfxFontEntry::GetUVSGlyph(uint3
 nsresult gfxFontEntry::ReadCMAP()
 {
     NS_ASSERTION(false, "using default no-op implementation of ReadCMAP");
     mCharacterMap = new gfxCharacterMap();
     return NS_OK;
 }
 
 nsString
-gfxFontEntry::FamilyName()
-{
-    FallibleTArray<uint8_t> nameTable;
-    nsresult rv = GetFontTable(TRUETYPE_TAG('n','a','m','e'), nameTable);
-    if (NS_SUCCEEDED(rv)) {
-        nsAutoString name;
-        rv = gfxFontUtils::GetFamilyNameFromTable(nameTable, name);
-        if (NS_SUCCEEDED(rv)) {
-            return name;
-        }
-    }
-    return Name();
-}
-
-nsString
 gfxFontEntry::RealFaceName()
 {
     FallibleTArray<uint8_t> nameTable;
     nsresult rv = GetFontTable(TRUETYPE_TAG('n','a','m','e'), nameTable);
     if (NS_SUCCEEDED(rv)) {
         nsAutoString name;
         rv = gfxFontUtils::GetFullNameFromTable(nameTable, name);
         if (NS_SUCCEEDED(rv)) {
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -227,29 +227,28 @@ public:
     { }
 
     virtual ~gfxFontEntry();
 
     // unique name for the face, *not* the family; not necessarily the
     // "real" or user-friendly name, may be an internal identifier
     const nsString& Name() const { return mName; }
 
+    // family name
+    const nsString& FamilyName() const { return mFamilyName; }
+
     // The following two methods may be relatively expensive, as they
     // will (usually, except on Linux) load and parse the 'name' table;
     // they are intended only for the font-inspection API, not for
     // perf-critical layout/drawing work.
 
     // The "real" name of the face, if available from the font resource;
     // returns Name() if nothing better is available.
     virtual nsString RealFaceName();
 
-    // The family name (if available) that would be used in css font-family
-    // properties; returns Name() if nothing better available.
-    virtual nsString FamilyName();
-
     uint16_t Weight() const { return mWeight; }
     int16_t Stretch() const { return mStretch; }
 
     bool IsUserFont() const { return mIsUserFont; }
     bool IsLocalUserFont() const { return mIsLocalUserFont; }
     bool IsFixedPitch() const { return mFixedPitch; }
     bool IsItalic() const { return mItalic; }
     bool IsBold() const { return mWeight >= 600; } // bold == weights 600 and above
@@ -330,16 +329,17 @@ public:
 
     // For memory reporting
     virtual void SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                      FontListSizes*    aSizes) const;
     virtual void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                      FontListSizes*    aSizes) const;
 
     nsString         mName;
+    nsString         mFamilyName;
 
     bool             mItalic      : 1;
     bool             mFixedPitch  : 1;
     bool             mIsProxy     : 1;
     bool             mIsValid     : 1;
     bool             mIsBadUnderlineFont : 1;
     bool             mIsUserFont  : 1;
     bool             mIsLocalUserFont  : 1;
@@ -556,16 +556,17 @@ public:
     void AddFontEntry(nsRefPtr<gfxFontEntry> aFontEntry) {
         // bug 589682 - set the IgnoreGDEF flag on entries for Italic faces
         // of Times New Roman, because of buggy table in those fonts
         if (aFontEntry->IsItalic() && !aFontEntry->IsUserFont() &&
             Name().EqualsLiteral("Times New Roman"))
         {
             aFontEntry->mIgnoreGDEF = true;
         }
+        aFontEntry->mFamilyName = Name();
         mAvailableFonts.AppendElement(aFontEntry);
     }
 
     // note that the styles for this family have been added
     void SetHasStyles(bool aHasStyles) { mHasStyles = aHasStyles; }
 
     // choose a specific face to match a style using CSS font matching
     // rules (weight matching occurs here).  may return a face that doesn't
@@ -3101,29 +3102,16 @@ public:
                      "Whoever was caching this font group should have "
                      "called UpdateFontList on it");
         NS_ASSERTION(mFonts.Length() > uint32_t(i) && mFonts[i].Font(), 
                      "Requesting a font index that doesn't exist");
 
         return mFonts[i].Font();
     }
 
-    // Return the family name of the primary font in the group.
-    // Note that gfxPangoFontGroup (for the Linux/Fontconfig backend),
-    // which does not have gfxFontFamily objects, must override this.
-    virtual nsString GetFamilyNameAt(int32_t i) {
-        NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
-                     "Whoever was caching this font group should have "
-                     "called UpdateFontList on it");
-        NS_ASSERTION(mFonts.Length() > uint32_t(i) && mFonts[i].Family(),
-                     "No fonts in the group!");
-
-        return mFonts[i].Family()->Name();
-    }
-
     uint32_t FontListLength() const {
         return mFonts.Length();
     }
 
     bool Equals(const gfxFontGroup& other) const {
         return mFamilies.Equals(other.mFamilies) &&
             mStyle.Equals(other.mStyle);
     }
--- a/gfx/thebes/gfxPangoFonts.cpp
+++ b/gfx/thebes/gfxPangoFonts.cpp
@@ -170,18 +170,16 @@ public:
             (cairo_font_face_get_user_data(aFace, &sFontEntryKey));
     }
 
     // override the gfxFontEntry impl to read the name from fontconfig
     // instead of trying to get the 'name' table, as we don't implement
     // GetFontTable() here
     virtual nsString RealFaceName();
 
-    virtual nsString FamilyName();
-
     // This is needed to make gfxFontEntry::HasCharacter(aCh) work.
     virtual bool TestCharacterMap(uint32_t aCh)
     {
         for (uint32_t i = 0; i < mPatterns.Length(); ++i) {
             if (HasChar(mPatterns[i], aCh)) {
                 return true;
             }
         }
@@ -229,30 +227,16 @@ gfxFcFontEntry::RealFaceName()
             }
             return result;
         }
     }
     // fall back to gfxFontEntry implementation (only works for sfnt fonts)
     return gfxFontEntry::RealFaceName();
 }
 
-nsString
-gfxFcFontEntry::FamilyName()
-{
-    FcChar8 *name;
-    if (!mPatterns.IsEmpty()) {
-        if (FcPatternGetString(mPatterns[0],
-                               FC_FAMILY, 0, &name) == FcResultMatch) {
-            return NS_ConvertUTF8toUTF16((const char*)name);
-        }
-    }
-    // fall back to gfxFontEntry implementation (only works for sfnt fonts)
-    return gfxFontEntry::FamilyName();
-}
-
 #ifdef MOZ_GRAPHITE
 void
 gfxFcFontEntry::CheckForGraphiteTables()
 {
     FcChar8 *capability;
     mHasGraphiteTables =
         !mPatterns.IsEmpty() &&
         FcPatternGetString(mPatterns[0],
@@ -788,26 +772,16 @@ public:
     // The PangoFont returned is owned by the gfxFcFont
     PangoFont *GetPangoFont() {
         if (!mPangoFont) {
             MakePangoFont();
         }
         return mPangoFont;
     }
 
-    nsString GetFamilyName() {
-        PangoFontDescription *desc = pango_font_describe(GetPangoFont());
-        const char *name = pango_font_description_get_family(desc);
-        if (name) {
-            return NS_ConvertUTF8toUTF16(name);
-        } else {
-            return GetFontEntry()->FamilyName();
-        }
-    }
-
 protected:
     virtual bool ShapeText(gfxContext      *aContext,
                            const PRUnichar *aText,
                            uint32_t         aOffset,
                            uint32_t         aLength,
                            int32_t          aScript,
                            gfxShapedText   *aShapedText,
                            bool             aPreferPlatformShaping);
@@ -1980,32 +1954,16 @@ gfxPangoFontGroup::GetFontAt(int32_t i)
                  "Whoever was caching this font group should have "
                  "called UpdateFontList on it");
 
     NS_PRECONDITION(i == 0, "Only have one font");
 
     return GetBaseFont();
 }
 
-nsString
-gfxPangoFontGroup::GetFamilyNameAt(int32_t i)
-{
-    gfxFcFont* font = static_cast<gfxFcFont*>(GetFontAt(i));
-
-    if (font->GetFontEntry()->IsUserFont()) {
-        gfxFontFamily* family =
-            GetUserFontSet()->FindFamilyFor(font->GetFontEntry());
-        if (family) { // should never fail, but just in case...
-            return family->Name();
-        }
-    }
-
-    return font->GetFamilyName();
-}
-
 void
 gfxPangoFontGroup::UpdateFontList()
 {
     if (!mUserFontSet)
         return;
 
     uint64_t newGeneration = mUserFontSet->GetGeneration();
     if (newGeneration == mCurrGeneration)
--- a/gfx/thebes/gfxPangoFonts.h
+++ b/gfx/thebes/gfxPangoFonts.h
@@ -28,18 +28,16 @@ public:
                        const gfxFontStyle *aStyle,
                        gfxUserFontSet *aUserFontSet);
     virtual ~gfxPangoFontGroup ();
 
     virtual gfxFontGroup *Copy(const gfxFontStyle *aStyle);
 
     virtual gfxFont *GetFontAt(int32_t i);
 
-    virtual nsString GetFamilyNameAt(int32_t i);
-
     virtual void UpdateFontList();
 
     virtual already_AddRefed<gfxFont>
         FindFontForChar(uint32_t aCh, uint32_t aPrevCh, int32_t aRunScript,
                         gfxFont *aPrevMatchedFont,
                         uint8_t *aMatchType);
 
     static void Shutdown();
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -532,17 +532,16 @@ gfxUserFontSet::LoadNext(gfxMixedFontFam
                         uint32_t bufferLength = 0;
 
                         // sync load font immediately
                         rv = SyncLoadFontData(aProxyEntry, &currSrc,
                                               buffer, bufferLength);
                         if (NS_SUCCEEDED(rv) &&
                             (fe = LoadFont(aFamily, aProxyEntry,
                                            buffer, bufferLength))) {
-                            UserFontCache::CacheFont(fe);
                             return STATUS_LOADED;
                         } else {
                             LogMessage(aFamily, aProxyEntry,
                                        "font load failed",
                                        nsIScriptError::errorFlag, rv);
                         }
                     } else {
                         // otherwise load font async
@@ -667,18 +666,18 @@ gfxUserFontSet::LoadFont(gfxMixedFontFam
             nsAutoCString fontURI;
             aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
                  this, aProxy->mSrcIndex, fontURI.get(),
                  NS_ConvertUTF16toUTF8(aFamily->Name()).get(),
                  uint32_t(mGeneration)));
         }
 #endif
+        ReplaceFontEntry(aFamily, aProxy, fe);
         UserFontCache::CacheFont(fe);
-        ReplaceFontEntry(aFamily, aProxy, fe);
     } else {
 #ifdef PR_LOGGING
         if (LOG_ENABLED()) {
             nsAutoCString fontURI;
             aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
             LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s)"
                  " error making platform font\n",
                  this, aProxy->mSrcIndex, fontURI.get(),
@@ -759,26 +758,29 @@ gfxUserFontSet::UserFontCache::Entry::Ke
         return false;
     }
 
     const gfxFontEntry *fe = aKey->mFontEntry;
     if (mFontEntry->mItalic           != fe->mItalic          ||
         mFontEntry->mWeight           != fe->mWeight          ||
         mFontEntry->mStretch          != fe->mStretch         ||
         mFontEntry->mFeatureSettings  != fe->mFeatureSettings ||
-        mFontEntry->mLanguageOverride != fe->mLanguageOverride) {
+        mFontEntry->mLanguageOverride != fe->mLanguageOverride ||
+        mFontEntry->mFamilyName       != fe->mFamilyName) {
         return false;
     }
 
     return true;
 }
 
 void
 gfxUserFontSet::UserFontCache::CacheFont(gfxFontEntry *aFontEntry)
 {
+    NS_ASSERTION(aFontEntry->mFamilyName.Length() != 0,
+                 "caching a font associated with no family yet");
     if (!sUserFonts) {
         sUserFonts = new nsTHashtable<Entry>;
         sUserFonts->Init();
     }
 
     gfxUserFontData *data = aFontEntry->mUserFontData;
     sUserFonts->PutEntry(Key(data->mURI, data->mPrincipal, aFontEntry));
 }
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -74,27 +74,29 @@ public:
     gfxMixedFontFamily(const nsAString& aName)
         : gfxFontFamily(aName) { }
 
     virtual ~gfxMixedFontFamily() { }
 
     void AddFontEntry(gfxFontEntry *aFontEntry) {
         nsRefPtr<gfxFontEntry> fe = aFontEntry;
         mAvailableFonts.AppendElement(fe);
+        aFontEntry->mFamilyName = Name();
         ResetCharacterMap();
     }
 
     void ReplaceFontEntry(gfxFontEntry *aOldFontEntry,
                           gfxFontEntry *aNewFontEntry) {
         uint32_t numFonts = mAvailableFonts.Length();
         for (uint32_t i = 0; i < numFonts; i++) {
             gfxFontEntry *fe = mAvailableFonts[i];
             if (fe == aOldFontEntry) {
                 // note that this may delete aOldFontEntry, if there's no
                 // other reference to it except from its family
+                aNewFontEntry->mFamilyName = Name();
                 mAvailableFonts[i] = aNewFontEntry;
                 break;
             }
         }
         ResetCharacterMap();
     }
 
     void RemoveFontEntry(gfxFontEntry *aFontEntry) {
@@ -298,16 +300,17 @@ public:
             static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
 
             static PLDHashNumber HashKey(const KeyTypePointer aKey) {
                 uint32_t principalHash;
                 aKey->mPrincipal->GetHashValue(&principalHash);
                 return mozilla::HashGeneric(principalHash,
                                             nsURIHashKey::HashKey(aKey->mURI),
                                             HashFeatures(aKey->mFontEntry->mFeatureSettings),
+                                            mozilla::HashString(aKey->mFontEntry->mFamilyName),
                                             ((uint32_t)aKey->mFontEntry->mItalic |
                                              (aKey->mFontEntry->mWeight << 1) |
                                              (aKey->mFontEntry->mStretch << 10) ) ^
                                              aKey->mFontEntry->mLanguageOverride);
             }
 
             enum { ALLOW_MEMMOVE = false };
 
--- a/layout/inspector/src/nsFontFace.cpp
+++ b/layout/inspector/src/nsFontFace.cpp
@@ -69,55 +69,16 @@ nsFontFace::GetName(nsAString & aName)
   }
   return NS_OK;
 }
 
 /* readonly attribute DOMString CSSFamilyName; */
 NS_IMETHODIMP
 nsFontFace::GetCSSFamilyName(nsAString & aCSSFamilyName)
 {
-  if (mFontEntry->IsUserFont()) {
-    // for a user font, find CSS family name from the @font-face rule
-    nsUserFontSet* fontSet =
-      static_cast<nsUserFontSet*>(mFontGroup->GetUserFontSet());
-    if (fontSet) {
-      nsCSSFontFaceRule* rule = fontSet->FindRuleForEntry(mFontEntry);
-      if (rule) {
-        nsCOMPtr<nsIDOMCSSStyleDeclaration> style;
-        nsresult rv = rule->GetStyle(getter_AddRefs(style));
-        if (NS_SUCCEEDED(rv)) {
-          nsString familyName;
-          rv = style->GetPropertyValue(NS_LITERAL_STRING("font-family"),
-                                       aCSSFamilyName);
-          if (NS_SUCCEEDED(rv)) {
-            // GetPropertyValue gives us the name in "quotes"; strip them off.
-            // XXX What about possible CSS escapes - should we unescape here?
-            // Or don't we care, as this is just for display/debugging use?
-            if (aCSSFamilyName[0] == '"' &&
-                aCSSFamilyName[aCSSFamilyName.Length() - 1] == '"') {
-              aCSSFamilyName.Truncate(aCSSFamilyName.Length() - 1);
-              aCSSFamilyName.Cut(0, 1);
-            }
-            return NS_OK;
-          }
-        }
-      }
-    }
-  }
-
-  // look through the font-group's list for this entry
-  uint32_t count = mFontGroup->FontListLength();
-  for (uint32_t i = 0; i < count; ++i) {
-    if (mFontGroup->GetFontAt(i)->GetFontEntry() == mFontEntry) {
-      aCSSFamilyName = mFontGroup->GetFamilyNameAt(i);
-      return NS_OK;
-    }
-  }
-
-  // if it wasn't found there, query the font entry itself
   aCSSFamilyName = mFontEntry->FamilyName();
   return NS_OK;
 }
 
 /* readonly attribute nsIDOMCSSFontFaceRule rule; */
 NS_IMETHODIMP
 nsFontFace::GetRule(nsIDOMCSSFontFaceRule **aRule)
 {
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -921,17 +921,18 @@ SetFontFamily(nsStyleContext*      aStyl
     nsRefPtr<nsFontMetrics> fm;
     aRenderingContext.DeviceContext()->GetMetricsFor(font,
       aStyleContext->StyleFont()->mLanguage,
       aStyleContext->PresContext()->GetUserFontSet(),
       *getter_AddRefs(fm));
     // Set the font if it is an unicode table
     // or if the same family name has been found
     if (aGlyphTable == &gGlyphTableList->mUnicodeTable ||
-        fm->GetThebesFontGroup()->GetFamilyNameAt(0) == family) {
+      fm->GetThebesFontGroup()->GetFontAt(0)->GetFontEntry()->
+      FamilyName() == family) {
       aFont.name = family;
       aRenderingContext.SetFont(fm);
     } else {
       return false; // We did not set the font
     }
   }
   return true;
 }