bug 633299 - don't discard font entries for @font-face rules that haven't changed. r=dbaron

This commit is contained in:
Jonathan Kew 2011-04-12 11:53:20 +01:00
parent 5a633fc5ed
commit 99d0c392b8
6 changed files with 360 additions and 251 deletions

View File

@ -108,7 +108,7 @@ gfxUserFontSet::~gfxUserFontSet()
{
}
void
gfxFontEntry*
gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
PRUint32 aWeight,
@ -118,6 +118,8 @@ gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
const nsString& aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges)
{
gfxProxyFontEntry *proxyEntry = nsnull;
nsAutoString key(aFamilyName);
ToLowerCase(key);
@ -135,29 +137,47 @@ gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
}
// construct a new face and add it into the family
if (family) {
nsTArray<gfxFontFeature> featureSettings;
gfxFontStyle::ParseFontFeatureSettings(aFeatureSettings,
featureSettings);
PRUint32 languageOverride =
gfxFontStyle::ParseFontLanguageOverride(aLanguageOverride);
gfxProxyFontEntry *proxyEntry =
new gfxProxyFontEntry(aFontFaceSrcList, family, aWeight, aStretch,
aItalicStyle,
featureSettings,
languageOverride,
aUnicodeRanges);
family->AddFontEntry(proxyEntry);
nsTArray<gfxFontFeature> featureSettings;
gfxFontStyle::ParseFontFeatureSettings(aFeatureSettings,
featureSettings);
PRUint32 languageOverride =
gfxFontStyle::ParseFontLanguageOverride(aLanguageOverride);
proxyEntry =
new gfxProxyFontEntry(aFontFaceSrcList, family, aWeight, aStretch,
aItalicStyle,
featureSettings,
languageOverride,
aUnicodeRanges);
family->AddFontEntry(proxyEntry);
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
LOG(("userfonts (%p) added (%s) with style: %s weight: %d stretch: %d",
this, NS_ConvertUTF16toUTF8(aFamilyName).get(),
(aItalicStyle & FONT_STYLE_ITALIC ? "italic" :
(aItalicStyle & FONT_STYLE_OBLIQUE ? "oblique" : "normal")),
aWeight, aStretch));
}
#endif
if (LOG_ENABLED()) {
LOG(("userfonts (%p) added (%s) with style: %s weight: %d stretch: %d",
this, NS_ConvertUTF16toUTF8(aFamilyName).get(),
(aItalicStyle & FONT_STYLE_ITALIC ? "italic" :
(aItalicStyle & FONT_STYLE_OBLIQUE ? "oblique" : "normal")),
aWeight, aStretch));
}
#endif
return proxyEntry;
}
void
gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
gfxFontEntry *aFontEntry)
{
nsAutoString key(aFamilyName);
ToLowerCase(key);
PRBool found;
gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
if (!family) {
family = new gfxMixedFontFamily(aFamilyName);
mFontFamilies.Put(key, family);
}
family->AddFontEntry(aFontEntry);
}
gfxFontEntry*
@ -541,7 +561,7 @@ gfxUserFontSet::OnLoadComplete(gfxFontEntry *aFontToLoad,
fe->mFeatureSettings.AppendElements(pe->mFeatureSettings);
fe->mLanguageOverride = pe->mLanguageOverride;
static_cast<gfxMixedFontFamily*>(pe->mFamily)->ReplaceFontEntry(pe, fe);
ReplaceFontEntry(pe, fe);
IncrementGeneration();
#ifdef PR_LOGGING
if (LOG_ENABLED()) {
@ -630,7 +650,7 @@ gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
PRUint32(mGeneration)));
fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings);
fe->mLanguageOverride = aProxyEntry->mLanguageOverride;
static_cast<gfxMixedFontFamily*>(aProxyEntry->mFamily)->ReplaceFontEntry(aProxyEntry, fe);
ReplaceFontEntry(aProxyEntry, fe);
return STATUS_LOADED;
} else {
LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",

View File

@ -94,6 +94,7 @@ public:
void AddFontEntry(gfxFontEntry *aFontEntry) {
nsRefPtr<gfxFontEntry> fe = aFontEntry;
mAvailableFonts.AppendElement(fe);
aFontEntry->SetFamily(this);
}
void ReplaceFontEntry(gfxFontEntry *aOldFontEntry, gfxFontEntry *aNewFontEntry)
@ -103,6 +104,8 @@ public:
gfxFontEntry *fe = mAvailableFonts[i];
if (fe == aOldFontEntry) {
mAvailableFonts[i] = aNewFontEntry;
aOldFontEntry->SetFamily(nsnull);
aNewFontEntry->SetFamily(this);
return;
}
}
@ -114,6 +117,7 @@ public:
for (PRUint32 i = 0; i < numFonts; i++) {
gfxFontEntry *fe = mAvailableFonts[i];
if (fe == aFontEntry) {
aFontEntry->SetFamily(nsnull);
mAvailableFonts.RemoveElementAt(i);
return;
}
@ -172,14 +176,17 @@ public:
// weight, stretch - 0 == unknown, [1, 9] otherwise
// italic style = constants in gfxFontConstants.h, e.g. NS_FONT_STYLE_NORMAL
// TODO: support for unicode ranges not yet implemented
void AddFontFace(const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
PRUint32 aWeight,
PRUint32 aStretch,
PRUint32 aItalicStyle,
const nsString& aFeatureSettings,
const nsString& aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges = nsnull);
gfxFontEntry *AddFontFace(const nsAString& aFamilyName,
const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
PRUint32 aWeight,
PRUint32 aStretch,
PRUint32 aItalicStyle,
const nsString& aFeatureSettings,
const nsString& aLanguageOverride,
gfxSparseBitSet *aUnicodeRanges = nsnull);
// add in a font face for which we have the gfxFontEntry already
void AddFontFace(const nsAString& aFamilyName, gfxFontEntry* aFontEntry);
// Whether there is a face with this family name
PRBool HasFamily(const nsAString& aFamilyName) const
@ -209,6 +216,12 @@ public:
const PRUint8 *aFontData, PRUint32 aLength,
nsresult aDownloadStatus);
// Replace a proxy with a real fontEntry; this is implemented in
// nsUserFontSet in order to keep track of the entry corresponding
// to each @font-face rule.
virtual void ReplaceFontEntry(gfxProxyFontEntry *aProxy,
gfxFontEntry *aFontEntry) = 0;
// generation - each time a face is loaded, generation is
// incremented so that the change can be recognized
PRUint64 GetGeneration() { return mGeneration; }

View File

@ -1772,177 +1772,6 @@ nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask)
UseDocumentColors());
}
static void
InsertFontFaceRule(nsCSSFontFaceRule *aRule, gfxUserFontSet* aFontSet,
PRUint8 aSheetType)
{
NS_ABORT_IF_FALSE(aRule->GetType() == nsICSSRule::FONT_FACE_RULE,
"InsertFontFaceRule passed a non-fontface CSS rule");
// aRule->List();
nsAutoString fontfamily;
nsCSSValue val;
PRUint32 unit;
PRUint32 weight = NS_STYLE_FONT_WEIGHT_NORMAL;
PRUint32 stretch = NS_STYLE_FONT_STRETCH_NORMAL;
PRUint32 italicStyle = FONT_STYLE_NORMAL;
nsString featureSettings, languageOverride;
// set up family name
aRule->GetDesc(eCSSFontDesc_Family, val);
unit = val.GetUnit();
if (unit == eCSSUnit_String) {
val.GetStringValue(fontfamily);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face family name has unexpected unit");
// If there is no family name, this rule cannot contribute a
// usable font, so there is no point in processing it further.
return;
}
// set up weight
aRule->GetDesc(eCSSFontDesc_Weight, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Integer || unit == eCSSUnit_Enumerated) {
weight = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
weight = NS_STYLE_FONT_WEIGHT_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face weight has unexpected unit");
}
// set up stretch
aRule->GetDesc(eCSSFontDesc_Stretch, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
stretch = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
stretch = NS_STYLE_FONT_STRETCH_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face stretch has unexpected unit");
}
// set up font style
aRule->GetDesc(eCSSFontDesc_Style, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
italicStyle = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
italicStyle = FONT_STYLE_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face style has unexpected unit");
}
// set up font features
aRule->GetDesc(eCSSFontDesc_FontFeatureSettings, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Normal) {
// empty feature string
} else if (unit == eCSSUnit_String) {
val.GetStringValue(featureSettings);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face font-feature-settings has unexpected unit");
}
// set up font language override
aRule->GetDesc(eCSSFontDesc_FontLanguageOverride, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Normal) {
// empty feature string
} else if (unit == eCSSUnit_String) {
val.GetStringValue(languageOverride);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face font-language-override has unexpected unit");
}
// set up src array
nsTArray<gfxFontFaceSrc> srcArray;
aRule->GetDesc(eCSSFontDesc_Src, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Array) {
nsCSSValue::Array *srcArr = val.GetArrayValue();
size_t numSrc = srcArr->Count();
for (size_t i = 0; i < numSrc; i++) {
val = srcArr->Item(i);
unit = val.GetUnit();
gfxFontFaceSrc *face = srcArray.AppendElements(1);
if (!face)
return;
switch (unit) {
case eCSSUnit_Local_Font:
val.GetStringValue(face->mLocalName);
face->mIsLocal = PR_TRUE;
face->mURI = nsnull;
face->mFormatFlags = 0;
break;
case eCSSUnit_URL:
face->mIsLocal = PR_FALSE;
face->mURI = val.GetURLValue();
NS_ASSERTION(face->mURI, "null url in @font-face rule");
face->mReferrer = val.GetURLStructValue()->mReferrer;
face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
// agent and user stylesheets are treated slightly differently,
// the same-site origin check and access control headers are
// enforced against the sheet principal rather than the document
// principal to allow user stylesheets to include @font-face rules
face->mUseOriginPrincipal = (aSheetType == nsStyleSet::eUserSheet ||
aSheetType == nsStyleSet::eAgentSheet);
face->mLocalName.Truncate();
face->mFormatFlags = 0;
while (i + 1 < numSrc && (val = srcArr->Item(i+1),
val.GetUnit() == eCSSUnit_Font_Format)) {
nsDependentString valueString(val.GetStringBufferValue());
if (valueString.LowerCaseEqualsASCII("woff")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_WOFF;
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_OPENTYPE;
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE;
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT;
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_EOT;
} else if (valueString.LowerCaseEqualsASCII("svg")) {
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_SVG;
} else {
// unknown format specified, mark to distinguish from the
// case where no format hints are specified
face->mFormatFlags |= gfxUserFontSet::FLAG_FORMAT_UNKNOWN;
}
i++;
}
break;
default:
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
"strange unit type in font-face src array");
break;
}
}
} else {
NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
}
if (!fontfamily.IsEmpty() && srcArray.Length() > 0) {
aFontSet->AddFontFace(fontfamily, srcArray, weight, stretch, italicStyle,
featureSettings, languageOverride);
}
}
gfxUserFontSet*
nsPresContext::GetUserFontSetInternal()
{
@ -1983,8 +1812,9 @@ nsPresContext::GetUserFontSetExternal()
void
nsPresContext::FlushUserFontSet()
{
if (!mShell)
if (!mShell) {
return; // we've been torn down
}
if (!mGetUserFontSetCalled) {
return; // No one cares about this font set yet, but we want to be careful
@ -1994,59 +1824,36 @@ nsPresContext::FlushUserFontSet()
if (mUserFontSetDirty) {
if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) {
nsRefPtr<gfxUserFontSet> oldUserFontSet = mUserFontSet;
nsTArray<nsFontFaceRuleContainer> rules;
if (!mShell->StyleSet()->AppendFontFaceRules(this, rules))
return;
PRBool differ;
if (rules.Length() == mFontFaceRules.Length()) {
differ = PR_FALSE;
for (PRUint32 i = 0, i_end = rules.Length(); i < i_end; ++i) {
if (rules[i].mRule != mFontFaceRules[i].mRule ||
rules[i].mSheetType != mFontFaceRules[i].mSheetType) {
differ = PR_TRUE;
break;
}
}
} else {
differ = PR_TRUE;
}
// Only rebuild things if the set of @font-face rules is different.
if (differ) {
if (!mShell->StyleSet()->AppendFontFaceRules(this, rules)) {
if (mUserFontSet) {
mUserFontSet->Destroy();
NS_RELEASE(mUserFontSet);
}
if (rules.Length() > 0) {
nsUserFontSet *fs = new nsUserFontSet(this);
if (!fs)
return;
mUserFontSet = fs;
NS_ADDREF(mUserFontSet);
for (PRUint32 i = 0, i_end = rules.Length(); i < i_end; ++i) {
InsertFontFaceRule(rules[i].mRule, fs, rules[i].mSheetType);
}
}
return;
}
#ifdef DEBUG
PRBool success =
#endif
rules.SwapElements(mFontFaceRules);
NS_ASSERTION(success, "should never fail given both are heap arrays");
PRBool changed = PR_FALSE;
if (mGetUserFontSetCalled && oldUserFontSet != mUserFontSet) {
// If we've changed, created, or destroyed a user font set, we
// need to trigger a style change reflow.
// We need to enqueue a style change reflow (for later) to
// reflect that we're dropping @font-face rules. (However,
// without a reflow, nothing will happen to start any downloads
// that are needed.)
if (rules.Length() == 0) {
if (mUserFontSet) {
mUserFontSet->Destroy();
NS_RELEASE(mUserFontSet);
changed = PR_TRUE;
}
} else {
if (!mUserFontSet) {
mUserFontSet = new nsUserFontSet(this);
NS_ADDREF(mUserFontSet);
}
changed = mUserFontSet->UpdateRules(rules);
}
// We need to enqueue a style change reflow (for later) to
// reflect that we're modifying @font-face rules. (However,
// without a reflow, nothing will happen to start any downloads
// that are needed.)
if (changed) {
UserFontSetUpdated();
}
}

View File

@ -1109,8 +1109,6 @@ protected:
// container for per-context fonts (downloadable, SVG, etc.)
nsUserFontSet* mUserFontSet;
// The list of @font-face rules that we put into mUserFontSet
nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
PRInt32 mFontScaler;
nscoord mMinimumFontSizePref;

View File

@ -73,6 +73,8 @@
#include "nsIChannelPolicy.h"
#include "nsChannelPolicy.h"
#include "nsStyleSet.h"
#ifdef PR_LOGGING
static PRLogModuleInfo *gFontDownloaderLog = PR_NewLogModule("fontdownloader");
#endif /* PR_LOGGING */
@ -436,3 +438,250 @@ nsUserFontSet::StartLoad(gfxFontEntry *aFontToLoad,
return rv;
}
PRBool
nsUserFontSet::UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules)
{
nsTArray<FontFaceRuleRecord> oldRules;
mRules.SwapElements(oldRules);
// destroy the font family records; we need to re-create them
// because we might end up with faces in a different order,
// even if they're the same font entries as before
mFontFamilies.Clear();
PRBool modified = PR_FALSE;
for (PRUint32 i = 0, i_end = aRules.Length(); i < i_end; ++i) {
// insert each rule into our list, migrating old font entries if possible
// rather than creating new ones; set modified to true if we detect
// that rule ordering has changed, or if a new entry is created
InsertRule(aRules[i].mRule, aRules[i].mSheetType, oldRules, modified);
}
// if any rules are left in the old list, note that the set has changed
if (oldRules.Length() > 0) {
modified = PR_TRUE;
}
if (modified) {
IncrementGeneration();
}
return modified;
}
void
nsUserFontSet::InsertRule(nsCSSFontFaceRule *aRule, PRUint8 aSheetType,
nsTArray<FontFaceRuleRecord>& aOldRules,
PRBool& aFontSetModified)
{
NS_ABORT_IF_FALSE(aRule->GetType() == nsICSSRule::FONT_FACE_RULE,
"InsertRule passed a non-fontface CSS rule");
// set up family name
nsAutoString fontfamily;
nsCSSValue val;
PRUint32 unit;
aRule->GetDesc(eCSSFontDesc_Family, val);
unit = val.GetUnit();
if (unit == eCSSUnit_String) {
val.GetStringValue(fontfamily);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face family name has unexpected unit");
}
if (fontfamily.IsEmpty()) {
// If there is no family name, this rule cannot contribute a
// usable font, so there is no point in processing it further.
return;
}
// first, we check in oldRules; if the rule exists there, just move it
// to the new rule list, and put the entry into the appropriate family
for (PRUint32 i = 0; i < aOldRules.Length(); ++i) {
const FontFaceRuleRecord& ruleRec = aOldRules[i];
if (ruleRec.mContainer.mRule == aRule &&
ruleRec.mContainer.mSheetType == aSheetType) {
AddFontFace(fontfamily, ruleRec.mFontEntry);
mRules.AppendElement(ruleRec);
aOldRules.RemoveElementAt(i);
// note the set has been modified if an old rule was skipped to find
// this one - something has been dropped, or ordering changed
if (i > 0) {
aFontSetModified = PR_TRUE;
}
return;
}
}
// this is a new rule:
PRUint32 weight = NS_STYLE_FONT_WEIGHT_NORMAL;
PRUint32 stretch = NS_STYLE_FONT_STRETCH_NORMAL;
PRUint32 italicStyle = FONT_STYLE_NORMAL;
nsString featureSettings, languageOverride;
// set up weight
aRule->GetDesc(eCSSFontDesc_Weight, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Integer || unit == eCSSUnit_Enumerated) {
weight = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
weight = NS_STYLE_FONT_WEIGHT_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face weight has unexpected unit");
}
// set up stretch
aRule->GetDesc(eCSSFontDesc_Stretch, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
stretch = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
stretch = NS_STYLE_FONT_STRETCH_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face stretch has unexpected unit");
}
// set up font style
aRule->GetDesc(eCSSFontDesc_Style, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Enumerated) {
italicStyle = val.GetIntValue();
} else if (unit == eCSSUnit_Normal) {
italicStyle = FONT_STYLE_NORMAL;
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face style has unexpected unit");
}
// set up font features
aRule->GetDesc(eCSSFontDesc_FontFeatureSettings, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Normal) {
// empty feature string
} else if (unit == eCSSUnit_String) {
val.GetStringValue(featureSettings);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face font-feature-settings has unexpected unit");
}
// set up font language override
aRule->GetDesc(eCSSFontDesc_FontLanguageOverride, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Normal) {
// empty feature string
} else if (unit == eCSSUnit_String) {
val.GetStringValue(languageOverride);
} else {
NS_ASSERTION(unit == eCSSUnit_Null,
"@font-face font-language-override has unexpected unit");
}
// set up src array
nsTArray<gfxFontFaceSrc> srcArray;
aRule->GetDesc(eCSSFontDesc_Src, val);
unit = val.GetUnit();
if (unit == eCSSUnit_Array) {
nsCSSValue::Array *srcArr = val.GetArrayValue();
size_t numSrc = srcArr->Count();
for (size_t i = 0; i < numSrc; i++) {
val = srcArr->Item(i);
unit = val.GetUnit();
gfxFontFaceSrc *face = srcArray.AppendElements(1);
if (!face)
return;
switch (unit) {
case eCSSUnit_Local_Font:
val.GetStringValue(face->mLocalName);
face->mIsLocal = PR_TRUE;
face->mURI = nsnull;
face->mFormatFlags = 0;
break;
case eCSSUnit_URL:
face->mIsLocal = PR_FALSE;
face->mURI = val.GetURLValue();
NS_ASSERTION(face->mURI, "null url in @font-face rule");
face->mReferrer = val.GetURLStructValue()->mReferrer;
face->mOriginPrincipal = val.GetURLStructValue()->mOriginPrincipal;
NS_ASSERTION(face->mOriginPrincipal, "null origin principal in @font-face rule");
// agent and user stylesheets are treated slightly differently,
// the same-site origin check and access control headers are
// enforced against the sheet principal rather than the document
// principal to allow user stylesheets to include @font-face rules
face->mUseOriginPrincipal = (aSheetType == nsStyleSet::eUserSheet ||
aSheetType == nsStyleSet::eAgentSheet);
face->mLocalName.Truncate();
face->mFormatFlags = 0;
while (i + 1 < numSrc && (val = srcArr->Item(i+1),
val.GetUnit() == eCSSUnit_Font_Format)) {
nsDependentString valueString(val.GetStringBufferValue());
if (valueString.LowerCaseEqualsASCII("woff")) {
face->mFormatFlags |= FLAG_FORMAT_WOFF;
} else if (valueString.LowerCaseEqualsASCII("opentype")) {
face->mFormatFlags |= FLAG_FORMAT_OPENTYPE;
} else if (valueString.LowerCaseEqualsASCII("truetype")) {
face->mFormatFlags |= FLAG_FORMAT_TRUETYPE;
} else if (valueString.LowerCaseEqualsASCII("truetype-aat")) {
face->mFormatFlags |= FLAG_FORMAT_TRUETYPE_AAT;
} else if (valueString.LowerCaseEqualsASCII("embedded-opentype")) {
face->mFormatFlags |= FLAG_FORMAT_EOT;
} else if (valueString.LowerCaseEqualsASCII("svg")) {
face->mFormatFlags |= FLAG_FORMAT_SVG;
} else {
// unknown format specified, mark to distinguish from the
// case where no format hints are specified
face->mFormatFlags |= FLAG_FORMAT_UNKNOWN;
}
i++;
}
break;
default:
NS_ASSERTION(unit == eCSSUnit_Local_Font || unit == eCSSUnit_URL,
"strange unit type in font-face src array");
break;
}
}
} else {
NS_ASSERTION(unit == eCSSUnit_Null, "@font-face src has unexpected unit");
}
if (srcArray.Length() > 0) {
FontFaceRuleRecord ruleRec;
ruleRec.mContainer.mRule = aRule;
ruleRec.mContainer.mSheetType = aSheetType;
ruleRec.mFontEntry = AddFontFace(fontfamily, srcArray,
weight, stretch, italicStyle,
featureSettings, languageOverride);
if (ruleRec.mFontEntry) {
mRules.AppendElement(ruleRec);
}
// this was a new rule and fontEntry, so note that the set was modified
aFontSetModified = PR_TRUE;
}
}
void
nsUserFontSet::ReplaceFontEntry(gfxProxyFontEntry *aProxy,
gfxFontEntry *aFontEntry)
{
for (PRUint32 i = 0; i < mRules.Length(); ++i) {
if (mRules[i].mFontEntry == aProxy) {
mRules[i].mFontEntry = aFontEntry;
break;
}
}
static_cast<gfxMixedFontFamily*>(aProxy->Family())->
ReplaceFontEntry(aProxy, aFontEntry);
}

View File

@ -50,6 +50,7 @@
#include "gfxUserFontSet.h"
#include "nsHashKeys.h"
#include "nsTHashtable.h"
#include "nsCSSRules.h"
class nsIRequest;
class nsISupports;
@ -57,6 +58,7 @@ class nsPresContext;
class nsIPrincipal;
class nsFontFaceLoader;
class nsCSSFontFaceRule;
// nsUserFontSet - defines the loading mechanism for downloadable fonts
class nsUserFontSet : public gfxUserFontSet
@ -77,15 +79,35 @@ public:
// It's removed from the mLoaders set.
void RemoveLoader(nsFontFaceLoader *aLoader);
PRBool UpdateRules(const nsTArray<nsFontFaceRuleContainer>& aRules);
nsPresContext *GetPresContext() { return mPresContext; }
virtual void ReplaceFontEntry(gfxProxyFontEntry *aProxy,
gfxFontEntry *aFontEntry);
protected:
// The font-set keeps track of the collection of rules, and their
// corresponding font entries (whether proxies or real entries),
// so that we can update the set without having to throw away
// all the existing fonts.
struct FontFaceRuleRecord {
nsRefPtr<gfxFontEntry> mFontEntry;
nsFontFaceRuleContainer mContainer;
};
void InsertRule(nsCSSFontFaceRule *aRule, PRUint8 aSheetType,
nsTArray<FontFaceRuleRecord>& oldRules,
PRBool& aFontSetModified);
nsPresContext *mPresContext; // weak reference
// Set of all loaders pointing to us. These are not strong pointers,
// but that's OK because nsFontFaceLoader always calls RemoveLoader on
// us before it dies (unless we die first).
nsTHashtable< nsPtrHashKey<nsFontFaceLoader> > mLoaders;
nsTArray<FontFaceRuleRecord> mRules;
};
class nsFontFaceLoader : public nsIStreamLoaderObserver