Bug 833169 - add font family name to font entries and use in user font cache key. r=jkew
--- 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;
}