bug 879963 - part 2 - avoid adding duplicate face entries to a user font family. r=dbaron

This commit is contained in:
Jonathan Kew 2013-07-17 12:53:31 +01:00
parent b4ef30ac5c
commit 61edd65b1e
3 changed files with 89 additions and 10 deletions

View File

@ -44,7 +44,7 @@ static uint64_t sFontSetGeneration = 0;
gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
uint32_t aStretch,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
@ -59,6 +59,8 @@ gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSr
mSrcIndex = 0;
mWeight = aWeight;
mStretch = aStretch;
// XXX Currently, we don't distinguish 'italic' and 'oblique' styles;
// we need to fix this. (Bug 543715)
mItalic = (aItalicStyle & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) != 0;
mFeatureSettings.AppendElements(aFeatureSettings);
mLanguageOverride = aLanguageOverride;
@ -69,6 +71,29 @@ gfxProxyFontEntry::~gfxProxyFontEntry()
{
}
bool
gfxProxyFontEntry::Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges)
{
// XXX font entries don't distinguish italic from oblique (bug 543715)
bool isItalic =
(aItalicStyle & (NS_FONT_STYLE_ITALIC | NS_FONT_STYLE_OBLIQUE)) != 0;
return mWeight == aWeight &&
mStretch == aStretch &&
mItalic == isItalic &&
mFeatureSettings == aFeatureSettings &&
mLanguageOverride == aLanguageOverride &&
mSrcList == aFontFaceSrcList;
// XXX once we support unicode-range (bug 475891),
// we'll need to compare that here as well
}
gfxFont*
gfxProxyFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
{
@ -90,14 +115,12 @@ gfxFontEntry*
gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
uint32_t aStretch,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
const nsString& aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges)
{
gfxProxyFontEntry *proxyEntry = nullptr;
nsAutoString key(aFamilyName);
ToLowerCase(key);
@ -114,10 +137,42 @@ gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
mFontFamilies.Put(key, family);
}
// construct a new face and add it into the family
uint32_t languageOverride =
gfxFontStyle::ParseFontLanguageOverride(aLanguageOverride);
proxyEntry =
// If there's already a proxy in the family whose descriptors all match,
// we can just move it to the end of the list instead of adding a new
// face that will always "shadow" the old one.
// Note that we can't do this for "real" (non-proxy) entries, even if the
// style descriptors match, as they might have had a different source list,
// but we no longer have the old source list available to check.
nsTArray<nsRefPtr<gfxFontEntry> >& fontList = family->GetFontList();
for (uint32_t i = 0, count = fontList.Length(); i < count; i++) {
if (!fontList[i]->mIsProxy) {
continue;
}
gfxProxyFontEntry *existingProxyEntry =
static_cast<gfxProxyFontEntry*>(fontList[i].get());
if (!existingProxyEntry->Matches(aFontFaceSrcList,
aWeight, aStretch, aItalicStyle,
aFeatureSettings, languageOverride,
aUnicodeRanges)) {
continue;
}
// We've found an entry that matches the new face exactly, so advance
// it to the end of the list.
// (Hold a strong reference while doing this, in case the only thing
// keeping the proxyFontEntry alive is the reference from family!)
nsRefPtr<gfxFontEntry> ref(existingProxyEntry);
family->RemoveFontEntry(existingProxyEntry);
family->AddFontEntry(existingProxyEntry);
return existingProxyEntry;
}
// construct a new face and add it into the family
gfxProxyFontEntry *proxyEntry =
new gfxProxyFontEntry(aFontFaceSrcList, aWeight, aStretch,
aItalicStyle,
aFeatureSettings,

View File

@ -41,6 +41,20 @@ struct gfxFontFaceSrc {
nsCOMPtr<nsIPrincipal> mOriginPrincipal; // principal if url
};
inline bool
operator==(const gfxFontFaceSrc& a, const gfxFontFaceSrc& b)
{
bool equals;
return (a.mIsLocal && b.mIsLocal &&
a.mLocalName == b.mLocalName) ||
(!a.mIsLocal && !b.mIsLocal &&
a.mUseOriginPrincipal == b.mUseOriginPrincipal &&
a.mFormatFlags == b.mFormatFlags &&
NS_SUCCEEDED(a.mURI->Equals(b.mURI, &equals)) && equals &&
NS_SUCCEEDED(a.mReferrer->Equals(b.mReferrer, &equals)) && equals &&
a.mOriginPrincipal->Equals(b.mOriginPrincipal));
}
// Subclassed to store platform-specific code cleaned out when font entry is
// deleted.
// Lifetime: from when platform font is created until it is deactivated.
@ -168,13 +182,14 @@ public:
// add in a font face
// weight, stretch - 0 == unknown, [1, 9] otherwise
// weight - 0 == unknown, [100, 900] otherwise (multiples of 100)
// stretch = [NS_FONT_STRETCH_ULTRA_CONDENSED, NS_FONT_STRETCH_ULTRA_EXPANDED]
// italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL
// TODO: support for unicode ranges not yet implemented
gfxFontEntry *AddFontFace(const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
uint32_t aStretch,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
const nsString& aLanguageOverride,
@ -428,7 +443,7 @@ class gfxProxyFontEntry : public gfxFontEntry {
public:
gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
uint32_t aStretch,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
@ -436,6 +451,15 @@ public:
virtual ~gfxProxyFontEntry();
// Return whether the entry matches the given list of attributes
bool Matches(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
uint32_t aWeight,
int32_t aStretch,
uint32_t aItalicStyle,
const nsTArray<gfxFontFeature>& aFeatureSettings,
uint32_t aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges);
virtual gfxFont *CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold);
// note that code depends on the ordering of these values!

View File

@ -530,7 +530,7 @@ nsUserFontSet::InsertRule(nsCSSFontFaceRule *aRule, uint8_t aSheetType,
// this is a new rule:
uint32_t weight = NS_STYLE_FONT_WEIGHT_NORMAL;
uint32_t stretch = NS_STYLE_FONT_STRETCH_NORMAL;
int32_t stretch = NS_STYLE_FONT_STRETCH_NORMAL;
uint32_t italicStyle = NS_STYLE_FONT_STYLE_NORMAL;
nsString languageOverride;