author | Ms2ger <ms2ger@gmail.com> |
Tue, 12 Apr 2011 14:31:23 +0200 | |
changeset 68011 | 8a7c7bcc38dde1991e0e1957af95722c2f75d09f |
parent 68009 | 5b8812d6950b83d540fa324e870bec4f882356a7 (current diff) |
parent 68010 | ccc7f1ec807639c1505965a112d4196ae03f4584 (diff) |
child 68012 | 83b87584d902a028533c193b1f70055886ff9684 |
push id | 1 |
push user | root |
push date | Tue, 26 Apr 2011 22:38:44 +0000 |
treeherder | mozilla-beta@bfdb6e623a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jfkthame |
bugs | 633299 |
milestone | 2.2a1pre |
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
|
--- a/gfx/thebes/gfxUserFontSet.cpp +++ b/gfx/thebes/gfxUserFontSet.cpp @@ -103,28 +103,26 @@ gfxUserFontSet::gfxUserFontSet() mFontFamilies.Init(5); IncrementGeneration(); } gfxUserFontSet::~gfxUserFontSet() { } -gfxFontEntry* +void gfxUserFontSet::AddFontFace(const nsAString& aFamilyName, const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, PRUint32 aWeight, PRUint32 aStretch, PRUint32 aItalicStyle, const nsString& aFeatureSettings, const nsString& aLanguageOverride, gfxSparseBitSet *aUnicodeRanges) { - gfxProxyFontEntry *proxyEntry = nsnull; - nsAutoString key(aFamilyName); ToLowerCase(key); PRBool found; if (aWeight == 0) aWeight = FONT_WEIGHT_NORMAL; @@ -132,57 +130,39 @@ gfxUserFontSet::AddFontFace(const nsAStr gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found); if (!family) { family = new gfxMixedFontFamily(aFamilyName); mFontFamilies.Put(key, family); } // construct a new face and add it into the family - 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); + 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); #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)); - } + 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* gfxUserFontSet::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle, PRBool& aFoundFamily, PRBool& aNeedsBold, PRBool& aWaitForUserFont) @@ -556,17 +536,17 @@ gfxUserFontSet::OnLoadComplete(gfxFontEn } if (fe) { // copy OpenType feature/language settings from the proxy to the // newly-created font entry fe->mFeatureSettings.AppendElements(pe->mFeatureSettings); fe->mLanguageOverride = pe->mLanguageOverride; - ReplaceFontEntry(pe, fe); + static_cast<gfxMixedFontFamily*>(pe->mFamily)->ReplaceFontEntry(pe, fe); IncrementGeneration(); #ifdef PR_LOGGING if (LOG_ENABLED()) { nsCAutoString fontURI; pe->mSrcList[pe->mSrcIndex].mURI->GetSpec(fontURI); LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n", this, pe->mSrcIndex, fontURI.get(), NS_ConvertUTF16toUTF8(pe->mFamily->Name()).get(), @@ -645,17 +625,17 @@ gfxUserFontSet::LoadNext(gfxProxyFontEnt if (fe) { LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n", this, aProxyEntry->mSrcIndex, NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(), PRUint32(mGeneration))); fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings); fe->mLanguageOverride = aProxyEntry->mLanguageOverride; - ReplaceFontEntry(aProxyEntry, fe); + static_cast<gfxMixedFontFamily*>(aProxyEntry->mFamily)->ReplaceFontEntry(aProxyEntry, fe); return STATUS_LOADED; } else { LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n", this, aProxyEntry->mSrcIndex, NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(), NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get())); } }
--- a/gfx/thebes/gfxUserFontSet.h +++ b/gfx/thebes/gfxUserFontSet.h @@ -89,40 +89,36 @@ public: gfxMixedFontFamily(const nsAString& aName) : gfxFontFamily(aName) { } virtual ~gfxMixedFontFamily() { } void AddFontEntry(gfxFontEntry *aFontEntry) { nsRefPtr<gfxFontEntry> fe = aFontEntry; mAvailableFonts.AppendElement(fe); - aFontEntry->SetFamily(this); } void ReplaceFontEntry(gfxFontEntry *aOldFontEntry, gfxFontEntry *aNewFontEntry) { PRUint32 numFonts = mAvailableFonts.Length(); for (PRUint32 i = 0; i < numFonts; i++) { gfxFontEntry *fe = mAvailableFonts[i]; if (fe == aOldFontEntry) { mAvailableFonts[i] = aNewFontEntry; - aOldFontEntry->SetFamily(nsnull); - aNewFontEntry->SetFamily(this); return; } } } void RemoveFontEntry(gfxFontEntry *aFontEntry) { PRUint32 numFonts = mAvailableFonts.Length(); for (PRUint32 i = 0; i < numFonts; i++) { gfxFontEntry *fe = mAvailableFonts[i]; if (fe == aFontEntry) { - aFontEntry->SetFamily(nsnull); mAvailableFonts.RemoveElementAt(i); return; } } } // temp method to determine if all proxies are loaded PRBool AllLoaded() @@ -171,27 +167,24 @@ public: STATUS_END_OF_LIST }; // add in a font face // 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 - 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); + void AddFontFace(const nsAString& aFamilyName, + const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList, + PRUint32 aWeight, + PRUint32 aStretch, + PRUint32 aItalicStyle, + const nsString& aFeatureSettings, + const nsString& aLanguageOverride, + gfxSparseBitSet *aUnicodeRanges = nsnull); // Whether there is a face with this family name PRBool HasFamily(const nsAString& aFamilyName) const { return GetFamily(aFamilyName) != nsnull; } // lookup a font entry for a given style, returns null if not loaded @@ -211,22 +204,16 @@ public: // returns true if platform font creation sucessful (or local() // reference was next in line) // Ownership of aFontData is passed in here; the font set must // ensure that it is eventually deleted with NS_Free(). PRBool OnLoadComplete(gfxFontEntry *aFontToLoad, 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; } // increment the generation on font load void IncrementGeneration(); protected:
--- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -1767,16 +1767,187 @@ nsPresContext::InvalidateIsChromeCacheEx nsPresContext::HasAuthorSpecifiedRules(nsIFrame *aFrame, PRUint32 ruleTypeMask) const { return nsRuleNode::HasAuthorSpecifiedRules(aFrame->GetStyleContext(), 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() { // We want to initialize the user font set lazily the first time the // user asks for it, rather than building it too early and forcing // rule cascade creation. Thus we try to enforce the invariant that // we *never* build the user font set until the first call to // GetUserFontSet. However, once it's been requested, we can't wait @@ -1818,47 +1989,69 @@ nsPresContext::FlushUserFontSet() if (!mGetUserFontSetCalled) { return; // No one cares about this font set yet, but we want to be careful // to not unset our mUserFontSetDirty bit, so when someone really // does we'll create it. } if (mUserFontSetDirty) { if (gfxPlatform::GetPlatform()->DownloadableFontsEnabled()) { + nsRefPtr<gfxUserFontSet> oldUserFontSet = mUserFontSet; + nsTArray<nsFontFaceRuleContainer> rules; - if (!mShell->StyleSet()->AppendFontFaceRules(this, rules)) { - if (mUserFontSet) { - mUserFontSet->Destroy(); - NS_RELEASE(mUserFontSet); + 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; + } } - return; + } else { + differ = PR_TRUE; } - PRBool changed = PR_FALSE; - - if (rules.Length() == 0) { + // Only rebuild things if the set of @font-face rules is different. + if (differ) { if (mUserFontSet) { mUserFontSet->Destroy(); NS_RELEASE(mUserFontSet); } - changed = PR_TRUE; - } else if (!mUserFontSet) { - mUserFontSet = new nsUserFontSet(this); - NS_ADDREF(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); + } + } } - if (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) { +#ifdef DEBUG + PRBool success = +#endif + rules.SwapElements(mFontFaceRules); + NS_ASSERTION(success, "should never fail given both are heap arrays"); + + 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.) UserFontSetUpdated(); } } mUserFontSetDirty = PR_FALSE; } }
--- a/layout/base/nsPresContext.h +++ b/layout/base/nsPresContext.h @@ -1104,16 +1104,18 @@ protected: nsCOMPtr<nsITimer> mPrefChangedTimer; FramePropertyTable mPropertyTable; nsInvalidateRequestList mInvalidateRequests; // 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; nsRect mVisibleArea; nsSize mPageSize; float mPageScale; float mPPScale;
--- a/layout/style/nsFontFaceLoader.cpp +++ b/layout/style/nsFontFaceLoader.cpp @@ -68,18 +68,16 @@ #include "nsIContentPolicy.h" #include "nsContentPolicyUtils.h" #include "nsContentErrors.h" #include "nsCrossSiteListenerProxy.h" #include "nsIContentSecurityPolicy.h" #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" -#include "nsStyleSet.h" - #ifdef PR_LOGGING static PRLogModuleInfo *gFontDownloaderLog = PR_NewLogModule("fontdownloader"); #endif /* PR_LOGGING */ #define LOG(args) PR_LOG(gFontDownloaderLog, PR_LOG_DEBUG, args) #define LOG_ENABLED() PR_LOG_TEST(gFontDownloaderLog, PR_LOG_DEBUG) @@ -433,251 +431,8 @@ nsUserFontSet::StartLoad(gfxFontEntry *a if (NS_SUCCEEDED(rv)) { mLoaders.PutEntry(fontLoader); fontLoader->StartedLoading(streamLoader); } 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; - } - - return modified; -} - -void -nsUserFontSet::InsertRule(nsCSSFontFaceRule *aRule, PRUint8 aSheetType, - nsTArray<FontFaceRuleRecord>& oldRules, - 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 < oldRules.Length(); ++i) { - const FontFaceRuleRecord& ruleRec = oldRules[i]; - if (ruleRec.mContainer.mRule == aRule && - ruleRec.mContainer.mSheetType == aSheetType) { - AddFontFace(fontfamily, ruleRec.mFontEntry); - mRules.AppendElement(ruleRec); - oldRules.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); -}
--- a/layout/style/nsFontFaceLoader.h +++ b/layout/style/nsFontFaceLoader.h @@ -45,25 +45,23 @@ #include "nsCOMPtr.h" #include "nsIStreamLoader.h" #include "nsIURI.h" #include "nsIChannel.h" #include "nsITimer.h" #include "gfxUserFontSet.h" #include "nsHashKeys.h" #include "nsTHashtable.h" -#include "nsCSSRules.h" class nsIRequest; class nsISupports; class nsPresContext; class nsIPrincipal; class nsFontFaceLoader; -class nsCSSFontFaceRule; // nsUserFontSet - defines the loading mechanism for downloadable fonts class nsUserFontSet : public gfxUserFontSet { public: nsUserFontSet(nsPresContext *aContext); ~nsUserFontSet(); @@ -74,45 +72,25 @@ public: // returns whether load process successfully started or not nsresult StartLoad(gfxFontEntry *aFontToLoad, const gfxFontFaceSrc *aFontFaceSrc); // Called by nsFontFaceLoader when the loader has completed normally. // 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 { public: nsFontFaceLoader(gfxFontEntry *aFontToLoad, nsIURI *aFontURI, nsUserFontSet *aFontSet, nsIChannel *aChannel);