Chromium Code Reviews| Index: Source/core/css/resolver/StyleResolver.cpp |
| diff --git a/Source/core/css/resolver/StyleResolver.cpp b/Source/core/css/resolver/StyleResolver.cpp |
| index 1a745194d5a8089ba4d33fbbf59eaabae0eef019..d78e94e891a5e469245dddcea4ac22d9e4250a0d 100644 |
| --- a/Source/core/css/resolver/StyleResolver.cpp |
| +++ b/Source/core/css/resolver/StyleResolver.cpp |
| @@ -57,6 +57,8 @@ |
| #include "core/css/PageRuleCollector.h" |
| #include "core/css/RuleSet.h" |
| #include "core/css/StylePropertySet.h" |
| +#include "core/css/StyleRuleImport.h" |
| +#include "core/css/StyleSheetContents.h" |
| #include "core/css/resolver/AnimatedStyleBuilder.h" |
| #include "core/css/resolver/MatchResult.h" |
| #include "core/css/resolver/MediaQueryResult.h" |
| @@ -138,6 +140,7 @@ StyleResolver::StyleResolver(Document& document, bool matchAuthorAndUserStyles) |
| , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles) |
| , m_fontSelector(CSSFontSelector::create(&document)) |
| , m_viewportStyleResolver(ViewportStyleResolver::create(&document)) |
| + , m_needCollectFeatures(false) |
| , m_styleResourceLoader(document.fetcher()) |
| { |
| Element* root = document.documentElement(); |
| @@ -181,6 +184,105 @@ StyleResolver::StyleResolver(Document& document, bool matchAuthorAndUserStyles) |
| styleSheetCollection->appendActiveAuthorStyleSheets(this); |
| } |
| +void StyleResolver::filterFontFaceAndViewportRules(const Vector<RefPtr<StyleRuleBase> >& rules, bool& needsResolveViewport) |
| +{ |
| + for (unsigned i = 0; i < rules.size(); ++i) { |
| + StyleRuleBase* rule = rules[i].get(); |
| + |
| + if (rule->isFontFaceRule()) { |
| + const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(rule); |
|
eseidel
2013/11/06 01:39:10
Do we have a toStyleRuleFontFace() method instead
tasak
2013/11/06 05:42:26
Done.
|
| + fontSelector()->addFontFaceRule(fontFaceRule); |
| + invalidateMatchedPropertiesCache(); |
| + } else if (rule->isViewportRule()) { |
| + m_styleTree.ensureScopedStyleResolver(m_document)->addViewportRule(static_cast<StyleRuleViewport*>(rule)); |
| + needsResolveViewport = true; |
| + } else if (rule->isMediaRule()) { |
| + StyleRuleMedia* mediaRule = static_cast<StyleRuleMedia*>(rule); |
|
eseidel
2013/11/06 01:39:10
We've slowly been moving away from using static_ca
tasak
2013/11/06 05:42:26
Done.
|
| + if ((!mediaRule->mediaQueries() || m_medium->eval(mediaRule->mediaQueries(), viewportDependentMediaQueryResults()))) |
| + filterFontFaceAndViewportRules(mediaRule->childRules(), needsResolveViewport); |
| + } |
| + } |
| +} |
| + |
| +void StyleResolver::filterFontFaceAndViewportRulesFromSheet(StyleSheetContents* sheet, bool& needsResolveViewport) |
| +{ |
| + if (!sheet) |
| + return; |
| + |
| + if (sheet->importRules().size() > 0) { |
| + const Vector<RefPtr<StyleRuleImport> >& importRules = sheet->importRules(); |
| + for (unsigned i = 0; i < importRules.size(); ++i) { |
| + StyleRuleImport* importRule = importRules[i].get(); |
| + filterFontFaceAndViewportRulesFromSheet(importRule->styleSheet(), needsResolveViewport); |
| + } |
| + } |
| + filterFontFaceAndViewportRules(sheet->childRules(), needsResolveViewport); |
| +} |
| + |
| +bool StyleResolver::filterFontFaceAndViewportRulesFromAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets) |
| +{ |
| + bool needsResolveViewport = false; |
| + |
| + unsigned size = styleSheets.size(); |
| + for (unsigned i = firstNew; i < size; ++i) { |
| + CSSStyleSheet* cssSheet = styleSheets[i].get(); |
| + ASSERT(!cssSheet->disabled()); |
| + if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults)) |
| + continue; |
| + // @viewport and @font-face rules work only in document scope. |
| + if (cssSheet->ownerNode()->isInShadowTree() || !isDocumentScope(ScopedStyleResolver::scopingNodeFor(cssSheet))) |
| + continue; |
| + filterFontFaceAndViewportRulesFromSheet(cssSheet->contents(), needsResolveViewport); |
| + } |
| + return needsResolveViewport; |
| +} |
| + |
| +void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets) |
| +{ |
| + // FIXME: Currently We cannot lazy apppend stylesheets if the sheets have @viewport and @font-face rules. |
| + // Need to find the best place to update pending stylesheets for "viewport" rules. |
| + // Talking about @font-face rules, addFontFaceRule triggers loading font resources. |
| + // If we delays "addFontFaceRule", we probably wait more time until fonts are loaded. |
| + // At least, we should filter @viewport and @font-face here and should lazily add other rules if possible. |
| + bool needsResolveViewport = filterFontFaceAndViewportRulesFromAuthorStyleSheets(firstNew, styleSheets); |
| + |
| + unsigned size = styleSheets.size(); |
| + for (unsigned i = firstNew; i < size; ++i) |
| + m_pendingStyleSheets.add(styleSheets[i].get()); |
| + |
| + if (needsResolveViewport) |
| + collectViewportRules(); |
| +} |
| + |
| +void StyleResolver::removePendingAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& styleSheets) |
| +{ |
| + for (unsigned i = 0; i < styleSheets.size(); ++i) |
| + m_pendingStyleSheets.remove(styleSheets[i].get()); |
| +} |
| + |
| +void StyleResolver::appendPendingAuthorStyleSheets() |
| +{ |
| + setBuildScopedStyleTreeInDocumentOrder(false); |
| + for (ListHashSet<CSSStyleSheet*, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it) { |
| + CSSStyleSheet* cssSheet = *it; |
| + ASSERT(!cssSheet->disabled()); |
| + if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults)) |
| + continue; |
| + |
| + StyleSheetContents* sheet = cssSheet->contents(); |
| + const ContainerNode* scopingNode = ScopedStyleResolver::scopingNodeFor(cssSheet); |
| + if (!scopingNode && cssSheet->ownerNode() && cssSheet->ownerNode()->isInShadowTree()) |
| + continue; |
| + |
| + ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode); |
| + ASSERT(resolver); |
| + resolver->addRulesFromSheet(sheet, *m_medium, this, false); |
| + m_inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet); |
| + } |
| + m_pendingStyleSheets.clear(); |
| + finishAppendAuthorStyleSheets(); |
| +} |
| + |
| void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets) |
| { |
| // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver |
| @@ -199,7 +301,7 @@ void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefP |
| ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode); |
| ASSERT(resolver); |
| - resolver->addRulesFromSheet(sheet, *m_medium, this); |
| + resolver->addRulesFromSheet(sheet, *m_medium, this, true); |
| m_inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet); |
| } |
| } |
| @@ -212,6 +314,17 @@ void StyleResolver::finishAppendAuthorStyleSheets() |
| document().renderer()->style()->font().update(fontSelector()); |
| collectViewportRules(); |
| + |
| + document().styleEngine()->resetCSSFeatureFlags(ruleFeatureSet()); |
| +} |
| + |
| +void StyleResolver::resetRuleFeatures() |
| +{ |
| + // Need to recreate RuleFeatureSet. |
| + m_features.clear(); |
| + m_siblingRuleSet.clear(); |
| + m_uncommonAttributeRuleSet.clear(); |
| + m_needCollectFeatures = true; |
| } |
| void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode) |
| @@ -225,6 +338,7 @@ void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode) |
| m_ruleSets.treeBoundaryCrossingRules().reset(scopingNode); |
| resolver->resetAuthorStyle(); |
| + resetRuleFeatures(); |
| if (!scopingNode) |
| return; |
| @@ -274,6 +388,7 @@ void StyleResolver::collectFeatures() |
| m_siblingRuleSet = makeRuleSet(m_features.siblingRules); |
| m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); |
| + m_needCollectFeatures = false; |
| } |
| bool StyleResolver::hasRulesForId(const AtomicString& id) const |
| @@ -611,6 +726,8 @@ PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderS |
| { |
| ASSERT(document().frame()); |
| ASSERT(documentSettings()); |
| + ASSERT(!hasPendingAuthorStyleSheets()); |
| + ASSERT(!m_needCollectFeatures); |
| // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer |
| // will vanish if a style recalc happens during loading. |
| @@ -707,6 +824,7 @@ PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* e, const Render |
| { |
| ASSERT(document().frame()); |
| ASSERT(documentSettings()); |
| + ASSERT(!hasPendingAuthorStyleSheets()); |
| if (e == document().documentElement()) |
| resetDirectionAndWritingModeOnDocument(document()); |
| @@ -782,6 +900,9 @@ void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* el |
| if (!e || list.animationName().isEmpty()) |
| return; |
| + if (hasPendingAuthorStyleSheets()) |
| + appendPendingAuthorStyleSheets(); |
| + |
| const StyleRuleKeyframes* keyframesRule = matchScopedKeyframesRule(e, list.animationName().impl()); |
| if (!keyframesRule) |
| return; |
| @@ -1051,6 +1172,7 @@ PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const P |
| PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex) |
| { |
| + ASSERT(!hasPendingAuthorStyleSheets()); |
| resetDirectionAndWritingModeOnDocument(document()); |
| StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style. |