Home | History | Annotate | Download | only in resolver
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde (at) carewolf.com)
      4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit (at) nickshanks.com)
      5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
      6  * Copyright (C) 2007 Alexey Proskuryakov <ap (at) webkit.org>
      7  * Copyright (C) 2007, 2008 Eric Seidel <eric (at) webkit.org>
      8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
     10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
     11  * Copyright (C) 2012 Google Inc. All rights reserved.
     12  *
     13  * This library is free software; you can redistribute it and/or
     14  * modify it under the terms of the GNU Library General Public
     15  * License as published by the Free Software Foundation; either
     16  * version 2 of the License, or (at your option) any later version.
     17  *
     18  * This library is distributed in the hope that it will be useful,
     19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21  * Library General Public License for more details.
     22  *
     23  * You should have received a copy of the GNU Library General Public License
     24  * along with this library; see the file COPYING.LIB.  If not, write to
     25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     26  * Boston, MA 02110-1301, USA.
     27  */
     28 
     29 #include "config.h"
     30 #include "core/css/resolver/StyleResolver.h"
     31 
     32 #include "CSSPropertyNames.h"
     33 #include "HTMLNames.h"
     34 #include "RuntimeEnabledFeatures.h"
     35 #include "StylePropertyShorthand.h"
     36 #include "core/animation/ActiveAnimations.h"
     37 #include "core/animation/AnimatableLength.h"
     38 #include "core/animation/AnimatableValue.h"
     39 #include "core/animation/Animation.h"
     40 #include "core/animation/DocumentTimeline.h"
     41 #include "core/animation/css/CSSAnimatableValueFactory.h"
     42 #include "core/animation/css/CSSAnimations.h"
     43 #include "core/css/CSSCalculationValue.h"
     44 #include "core/css/CSSDefaultStyleSheets.h"
     45 #include "core/css/CSSFontFace.h"
     46 #include "core/css/CSSFontSelector.h"
     47 #include "core/css/CSSKeyframeRule.h"
     48 #include "core/css/CSSKeyframesRule.h"
     49 #include "core/css/CSSParser.h"
     50 #include "core/css/CSSReflectValue.h"
     51 #include "core/css/CSSRuleList.h"
     52 #include "core/css/CSSSelector.h"
     53 #include "core/css/CSSStyleRule.h"
     54 #include "core/css/CSSValueList.h"
     55 #include "core/css/CSSVariableValue.h"
     56 #include "core/css/ElementRuleCollector.h"
     57 #include "core/css/MediaQueryEvaluator.h"
     58 #include "core/css/PageRuleCollector.h"
     59 #include "core/css/StylePropertySet.h"
     60 #include "core/css/StyleRuleImport.h"
     61 #include "core/css/StyleSheetContents.h"
     62 #include "core/css/resolver/AnimatedStyleBuilder.h"
     63 #include "core/css/resolver/MatchResult.h"
     64 #include "core/css/resolver/MediaQueryResult.h"
     65 #include "core/css/resolver/SharedStyleFinder.h"
     66 #include "core/css/resolver/StyleAdjuster.h"
     67 #include "core/css/resolver/StyleResolverStats.h"
     68 #include "core/css/resolver/ViewportStyleResolver.h"
     69 #include "core/dom/CSSSelectorWatch.h"
     70 #include "core/dom/NodeRenderStyle.h"
     71 #include "core/dom/StyleEngine.h"
     72 #include "core/dom/Text.h"
     73 #include "core/dom/shadow/ElementShadow.h"
     74 #include "core/dom/shadow/ShadowRoot.h"
     75 #include "core/html/HTMLIFrameElement.h"
     76 #include "core/inspector/InspectorInstrumentation.h"
     77 #include "core/frame/Frame.h"
     78 #include "core/frame/FrameView.h"
     79 #include "core/rendering/RenderView.h"
     80 #include "core/rendering/style/KeyframeList.h"
     81 #include "core/rendering/style/StyleCustomFilterProgramCache.h"
     82 #include "core/svg/SVGDocumentExtensions.h"
     83 #include "core/svg/SVGElement.h"
     84 #include "core/svg/SVGFontFaceElement.h"
     85 #include "wtf/StdLibExtras.h"
     86 
     87 using namespace std;
     88 
     89 namespace {
     90 
     91 using namespace WebCore;
     92 
     93 void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element)
     94 {
     95     // If any changes to CSS Animations were detected, stash the update away for application after the
     96     // render object is updated if we're in the appropriate scope.
     97     if (RuntimeEnabledFeatures::webAnimationsCSSEnabled() && state.animationUpdate())
     98         element.ensureActiveAnimations()->cssAnimations().setPendingUpdate(state.takeAnimationUpdate());
     99 }
    100 
    101 } // namespace
    102 
    103 namespace WebCore {
    104 
    105 using namespace HTMLNames;
    106 
    107 RenderStyle* StyleResolver::s_styleNotYetAvailable;
    108 
    109 static StylePropertySet* leftToRightDeclaration()
    110 {
    111     DEFINE_STATIC_REF(MutableStylePropertySet, leftToRightDecl, (MutableStylePropertySet::create()));
    112     if (leftToRightDecl->isEmpty())
    113         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
    114     return leftToRightDecl;
    115 }
    116 
    117 static StylePropertySet* rightToLeftDeclaration()
    118 {
    119     DEFINE_STATIC_REF(MutableStylePropertySet, rightToLeftDecl, (MutableStylePropertySet::create()));
    120     if (rightToLeftDecl->isEmpty())
    121         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
    122     return rightToLeftDecl;
    123 }
    124 
    125 static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule)
    126 {
    127     RefPtr<CSSFontFace> cssFontFace = CSSFontFace::createFromStyleRule(document, fontFaceRule);
    128     if (cssFontFace)
    129         cssFontSelector->addFontFaceRule(fontFaceRule, cssFontFace);
    130 }
    131 
    132 StyleResolver::StyleResolver(Document& document)
    133     : m_document(document)
    134     , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
    135     , m_needCollectFeatures(false)
    136     , m_styleResourceLoader(document.fetcher())
    137     , m_styleResolverStatsSequence(0)
    138     , m_accessCount(0)
    139 {
    140     // FIXME: Why do this here instead of as part of resolving style on the root?
    141     CSSDefaultStyleSheets::loadDefaultStylesheetIfNecessary();
    142 
    143     // Construct document root element default style. This is needed
    144     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
    145     // This is here instead of constructor because when constructor is run,
    146     // Document doesn't have documentElement.
    147     // NOTE: This assumes that element that gets passed to the styleForElement call
    148     // is always from the document that owns the StyleResolver.
    149     FrameView* view = document.view();
    150     if (view)
    151         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
    152     else
    153         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
    154 
    155     Element* root = document.documentElement();
    156     if (root)
    157         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
    158 
    159     if (m_rootDefaultStyle && view)
    160         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame(), m_rootDefaultStyle.get()));
    161 
    162     m_styleTree.clear();
    163 
    164     initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors());
    165 
    166 #if ENABLE(SVG_FONTS)
    167     if (document.svgExtensions()) {
    168         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements();
    169         HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
    170         for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
    171             addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule());
    172     }
    173 #endif
    174 }
    175 
    176 void StyleResolver::initWatchedSelectorRules(const Vector<RefPtr<StyleRule> >& watchedSelectors)
    177 {
    178     if (!watchedSelectors.size())
    179         return;
    180     m_watchedSelectorsRules = RuleSet::create();
    181     for (unsigned i = 0; i < watchedSelectors.size(); ++i)
    182         m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState);
    183 }
    184 
    185 void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
    186 {
    187     unsigned size = styleSheets.size();
    188     for (unsigned i = firstNew; i < size; ++i)
    189         m_pendingStyleSheets.add(styleSheets[i].get());
    190 }
    191 
    192 void StyleResolver::removePendingAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
    193 {
    194     for (unsigned i = 0; i < styleSheets.size(); ++i)
    195         m_pendingStyleSheets.remove(styleSheets[i].get());
    196 }
    197 
    198 void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet)
    199 {
    200     ASSERT(cssSheet);
    201     ASSERT(!cssSheet->disabled());
    202     if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults))
    203         return;
    204 
    205     StyleSheetContents* sheet = cssSheet->contents();
    206     ContainerNode* scopingNode = ScopedStyleResolver::scopingNodeFor(document(), cssSheet);
    207     if (!scopingNode)
    208         return;
    209 
    210     ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode);
    211     ASSERT(resolver);
    212     resolver->addRulesFromSheet(sheet, *m_medium, this);
    213     m_inspectorCSSOMWrappers.collectFromStyleSheetIfNeeded(cssSheet);
    214 }
    215 
    216 void StyleResolver::appendPendingAuthorStyleSheets()
    217 {
    218     setBuildScopedStyleTreeInDocumentOrder(false);
    219     for (ListHashSet<CSSStyleSheet*, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it)
    220         appendCSSStyleSheet(*it);
    221 
    222     m_pendingStyleSheets.clear();
    223     finishAppendAuthorStyleSheets();
    224 }
    225 
    226 void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
    227 {
    228     // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    229     // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    230     unsigned size = styleSheets.size();
    231     for (unsigned i = firstNew; i < size; ++i)
    232         appendCSSStyleSheet(styleSheets[i].get());
    233 }
    234 
    235 void StyleResolver::finishAppendAuthorStyleSheets()
    236 {
    237     collectFeatures();
    238 
    239     if (document().renderer() && document().renderer()->style())
    240         document().renderer()->style()->font().update(document().styleEngine()->fontSelector());
    241 
    242     collectViewportRules();
    243 
    244     document().styleEngine()->resetCSSFeatureFlags(m_features);
    245 }
    246 
    247 void StyleResolver::resetRuleFeatures()
    248 {
    249     // Need to recreate RuleFeatureSet.
    250     m_features.clear();
    251     m_siblingRuleSet.clear();
    252     m_uncommonAttributeRuleSet.clear();
    253     m_needCollectFeatures = true;
    254 }
    255 
    256 void StyleResolver::addTreeBoundaryCrossingRules(const Vector<MinimalRuleData>& rules, ContainerNode* scope)
    257 {
    258     for (unsigned i = 0; i < rules.size(); ++i) {
    259         const MinimalRuleData& info = rules[i];
    260         m_treeBoundaryCrossingRules.addRule(info.m_rule, info.m_selectorIndex, scope, info.m_flags);
    261     }
    262 }
    263 
    264 void StyleResolver::processScopedRules(const RuleSet& authorRules, const KURL& sheetBaseURL, ContainerNode* scope)
    265 {
    266     const Vector<StyleRuleKeyframes*> keyframesRules = authorRules.keyframesRules();
    267     for (unsigned i = 0; i < keyframesRules.size(); ++i)
    268         ensureScopedStyleResolver(scope)->addKeyframeStyle(keyframesRules[i]);
    269 
    270     addTreeBoundaryCrossingRules(authorRules.treeBoundaryCrossingRules(), scope);
    271 
    272     // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
    273     if (!scope || scope->isDocumentNode()) {
    274         const Vector<StyleRuleFontFace*> fontFaceRules = authorRules.fontFaceRules();
    275         for (unsigned i = 0; i < fontFaceRules.size(); ++i)
    276             addFontFaceRule(&m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]);
    277         if (fontFaceRules.size())
    278             invalidateMatchedPropertiesCache();
    279     } else {
    280         addTreeBoundaryCrossingRules(authorRules.shadowDistributedRules(), scope);
    281     }
    282 }
    283 
    284 void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode)
    285 {
    286     // FIXME: When chanking scoped attribute, scopingNode's hasScopedHTMLStyleChild has been already modified.
    287     // So we cannot use hasScopedHTMLStyleChild flag here.
    288     ScopedStyleResolver* resolver = scopingNode ? m_styleTree.lookupScopedStyleResolverFor(scopingNode) : m_styleTree.scopedStyleResolverForDocument();
    289     if (!resolver)
    290         return;
    291 
    292     treeBoundaryCrossingRules().reset(scopingNode);
    293 
    294     resolver->resetAuthorStyle();
    295     resetRuleFeatures();
    296     if (!scopingNode)
    297         return;
    298 
    299     m_styleTree.remove(scopingNode);
    300 }
    301 
    302 static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
    303 {
    304     size_t size = rules.size();
    305     if (!size)
    306         return nullptr;
    307     OwnPtr<RuleSet> ruleSet = RuleSet::create();
    308     for (size_t i = 0; i < size; ++i)
    309         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
    310     return ruleSet.release();
    311 }
    312 
    313 void StyleResolver::collectFeatures()
    314 {
    315     m_features.clear();
    316     // Collect all ids and rules using sibling selectors (:first-child and similar)
    317     // in the current set of stylesheets. Style sharing code uses this information to reject
    318     // sharing candidates.
    319     if (CSSDefaultStyleSheets::defaultStyle)
    320         m_features.add(CSSDefaultStyleSheets::defaultStyle->features());
    321 
    322     if (document().isViewSource())
    323         m_features.add(CSSDefaultStyleSheets::viewSourceStyle()->features());
    324 
    325     if (m_watchedSelectorsRules)
    326         m_features.add(m_watchedSelectorsRules->features());
    327 
    328     m_treeBoundaryCrossingRules.collectFeaturesTo(m_features);
    329 
    330     m_styleTree.collectFeaturesTo(m_features);
    331 
    332     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
    333     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
    334     m_needCollectFeatures = false;
    335 }
    336 
    337 bool StyleResolver::hasRulesForId(const AtomicString& id) const
    338 {
    339     return m_features.idsInRules.contains(id);
    340 }
    341 
    342 void StyleResolver::addToStyleSharingList(Element& element)
    343 {
    344     // Never add elements to the style sharing list if we're not in a recalcStyle,
    345     // otherwise we could leave stale pointers in there.
    346     if (!document().inStyleRecalc())
    347         return;
    348     INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates);
    349     if (m_styleSharingList.size() >= styleSharingListSize)
    350         m_styleSharingList.remove(--m_styleSharingList.end());
    351     m_styleSharingList.prepend(&element);
    352 }
    353 
    354 void StyleResolver::clearStyleSharingList()
    355 {
    356     m_styleSharingList.clear();
    357 }
    358 
    359 void StyleResolver::fontsNeedUpdate(FontSelector* fontSelector)
    360 {
    361     invalidateMatchedPropertiesCache();
    362     m_document.setNeedsStyleRecalc();
    363 }
    364 
    365 void StyleResolver::pushParentElement(Element& parent)
    366 {
    367     const ContainerNode* parentsParent = parent.parentOrShadowHostElement();
    368 
    369     // We are not always invoked consistently. For example, script execution can cause us to enter
    370     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
    371     // Reset the stack in this case, or if we see a new root element.
    372     // Otherwise just push the new parent.
    373     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
    374         m_selectorFilter.setupParentStack(parent);
    375     else
    376         m_selectorFilter.pushParent(parent);
    377 
    378     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
    379     m_styleTree.pushStyleCache(parent, parent.parentOrShadowHostNode());
    380 }
    381 
    382 void StyleResolver::popParentElement(Element& parent)
    383 {
    384     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
    385     // Pause maintaining the stack in this case.
    386     if (m_selectorFilter.parentStackIsConsistent(&parent))
    387         m_selectorFilter.popParent();
    388 
    389     m_styleTree.popStyleCache(parent);
    390 }
    391 
    392 void StyleResolver::pushParentShadowRoot(const ShadowRoot& shadowRoot)
    393 {
    394     ASSERT(shadowRoot.host());
    395     m_styleTree.pushStyleCache(shadowRoot, shadowRoot.host());
    396 }
    397 
    398 void StyleResolver::popParentShadowRoot(const ShadowRoot& shadowRoot)
    399 {
    400     ASSERT(shadowRoot.host());
    401     m_styleTree.popStyleCache(shadowRoot);
    402 }
    403 
    404 StyleResolver::~StyleResolver()
    405 {
    406     m_viewportStyleResolver->clearDocument();
    407 }
    408 
    409 inline void StyleResolver::collectTreeBoundaryCrossingRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
    410 {
    411     if (m_treeBoundaryCrossingRules.isEmpty())
    412         return;
    413 
    414     RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
    415 
    416     CascadeOrder cascadeOrder = 0;
    417 
    418     DocumentOrderedList::iterator it = m_treeBoundaryCrossingRules.end();
    419     while (it != m_treeBoundaryCrossingRules.begin()) {
    420         --it;
    421         const ContainerNode* scopingNode = toContainerNode(*it);
    422         RuleSet* ruleSet = m_treeBoundaryCrossingRules.ruleSetScopedBy(scopingNode);
    423         unsigned boundaryBehavior = SelectorChecker::CrossesBoundary | SelectorChecker::ScopeContainsLastMatchedElement;
    424 
    425         // If a given scoping node is a shadow root and a given element is in a descendant tree of tree hosted by
    426         // the scoping node's shadow host, we should use ScopeIsShadowHost.
    427         if (scopingNode && scopingNode->isShadowRoot()) {
    428             if (element->isInDescendantTreeOf(toShadowRoot(scopingNode)->host()))
    429                 boundaryBehavior |= SelectorChecker::ScopeIsShadowHost;
    430             scopingNode = toShadowRoot(scopingNode)->host();
    431         }
    432         collector.collectMatchingRules(MatchRequest(ruleSet, includeEmptyRules, scopingNode), ruleRange, static_cast<SelectorChecker::BehaviorAtBoundary>(boundaryBehavior), ignoreCascadeScope, cascadeOrder++);
    433     }
    434 }
    435 
    436 static inline bool applyAuthorStylesOf(const Element* element)
    437 {
    438     return element->treeScope().applyAuthorStyles() || (element->shadow() && element->shadow()->applyAuthorStyles());
    439 }
    440 
    441 void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, Vector<ScopedStyleResolver*, 8>& resolvers, Vector<ScopedStyleResolver*, 8>& resolversInShadowTree)
    442 {
    443     collector.clearMatchedRules();
    444     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
    445 
    446     CascadeScope cascadeScope = 0;
    447     CascadeOrder cascadeOrder = 0;
    448     bool applyAuthorStyles = applyAuthorStylesOf(element);
    449 
    450     for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
    451         resolversInShadowTree.at(j)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope, cascadeOrder++);
    452 
    453     if (resolvers.isEmpty() || resolvers.first()->treeScope() != element->treeScope())
    454         ++cascadeScope;
    455     cascadeOrder += resolvers.size();
    456     for (unsigned i = 0; i < resolvers.size(); ++i)
    457         resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, --cascadeOrder);
    458 
    459     collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    460     collector.sortAndTransferMatchedRules();
    461 }
    462 
    463 void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
    464 {
    465     collector.clearMatchedRules();
    466     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
    467 
    468     bool applyAuthorStyles = applyAuthorStylesOf(element);
    469     if (m_styleTree.hasOnlyScopedResolverForDocument()) {
    470         m_styleTree.scopedStyleResolverForDocument()->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, ignoreCascadeScope);
    471         collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    472         collector.sortAndTransferMatchedRules();
    473         return;
    474     }
    475 
    476     Vector<ScopedStyleResolver*, 8> resolvers;
    477     m_styleTree.resolveScopedStyles(element, resolvers);
    478 
    479     Vector<ScopedStyleResolver*, 8> resolversInShadowTree;
    480     m_styleTree.collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);
    481     if (!resolversInShadowTree.isEmpty()) {
    482         matchAuthorRulesForShadowHost(element, collector, includeEmptyRules, resolvers, resolversInShadowTree);
    483         return;
    484     }
    485 
    486     if (resolvers.isEmpty())
    487         return;
    488 
    489     CascadeScope cascadeScope = 0;
    490     CascadeOrder cascadeOrder = resolvers.size();
    491     for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
    492         ScopedStyleResolver* resolver = resolvers.at(i);
    493         // FIXME: Need to clarify how to treat style scoped.
    494         resolver->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->scopingNode().isShadowRoot() ? 0 : cascadeOrder);
    495     }
    496 
    497     collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    498     collector.sortAndTransferMatchedRules();
    499 }
    500 
    501 void StyleResolver::matchWatchSelectorRules(ElementRuleCollector& collector)
    502 {
    503     if (!m_watchedSelectorsRules)
    504         return;
    505 
    506     collector.clearMatchedRules();
    507     collector.matchedResult().ranges.lastUserRule = collector.matchedResult().matchedProperties.size() - 1;
    508 
    509     MatchRequest matchRequest(m_watchedSelectorsRules.get());
    510     RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange();
    511     collector.collectMatchingRules(matchRequest, ruleRange);
    512     collector.collectMatchingRulesForRegion(matchRequest, ruleRange);
    513 
    514     collector.sortAndTransferMatchedRules();
    515 }
    516 
    517 void StyleResolver::matchUARules(ElementRuleCollector& collector)
    518 {
    519     collector.setMatchingUARules(true);
    520 
    521     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
    522         ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
    523     matchUARules(collector, userAgentStyleSheet);
    524 
    525     // In quirks mode, we match rules from the quirks user agent sheet.
    526     if (document().inQuirksMode())
    527         matchUARules(collector, CSSDefaultStyleSheets::defaultQuirksStyle);
    528 
    529     // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
    530     if (document().isViewSource())
    531         matchUARules(collector, CSSDefaultStyleSheets::viewSourceStyle());
    532 
    533     collector.setMatchingUARules(false);
    534 
    535     matchWatchSelectorRules(collector);
    536 }
    537 
    538 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules)
    539 {
    540     collector.clearMatchedRules();
    541     collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1;
    542 
    543     RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange();
    544     collector.collectMatchingRules(MatchRequest(rules), ruleRange);
    545 
    546     collector.sortAndTransferMatchedRules();
    547 }
    548 
    549 void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollector& collector, bool includeSMILProperties)
    550 {
    551     matchUARules(collector);
    552 
    553     // Now check author rules, beginning first with presentational attributes mapped from HTML.
    554     if (state.element()->isStyledElement()) {
    555         collector.addElementStyleProperties(state.element()->presentationAttributeStyle());
    556 
    557         // Now we check additional mapped declarations.
    558         // Tables and table cells share an additional mapped rule that must be applied
    559         // after all attributes, since their mapped style depends on the values of multiple attributes.
    560         collector.addElementStyleProperties(state.element()->additionalPresentationAttributeStyle());
    561 
    562         if (state.element()->isHTMLElement()) {
    563             bool isAuto;
    564             TextDirection textDirection = toHTMLElement(state.element())->directionalityIfhasDirAutoAttribute(isAuto);
    565             if (isAuto)
    566                 collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
    567         }
    568     }
    569 
    570     matchAuthorRules(state.element(), collector, false);
    571 
    572     if (state.element()->isStyledElement()) {
    573         if (state.element()->inlineStyle()) {
    574             // Inline style is immutable as long as there is no CSSOM wrapper.
    575             bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMutable();
    576             collector.addElementStyleProperties(state.element()->inlineStyle(), isInlineStyleCacheable);
    577         }
    578 
    579         // Now check SMIL animation override style.
    580         if (includeSMILProperties && state.element()->isSVGElement())
    581             collector.addElementStyleProperties(toSVGElement(state.element())->animatedSMILStyleProperties(), false /* isCacheable */);
    582     }
    583 }
    584 
    585 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document, CSSFontSelector* fontSelector)
    586 {
    587     const Frame* frame = document.frame();
    588 
    589     // HTML5 states that seamless iframes should replace default CSS values
    590     // with values inherited from the containing iframe element. However,
    591     // some values (such as the case of designMode = "on") still need to
    592     // be set by this "document style".
    593     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
    594     bool seamlessWithParent = document.shouldDisplaySeamlesslyWithParent();
    595     if (seamlessWithParent) {
    596         RenderStyle* iframeStyle = document.seamlessParentIFrame()->renderStyle();
    597         if (iframeStyle)
    598             documentStyle->inheritFrom(iframeStyle);
    599     }
    600 
    601     // FIXME: It's not clear which values below we want to override in the seamless case!
    602     documentStyle->setDisplay(BLOCK);
    603     if (!seamlessWithParent) {
    604         documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder);
    605         documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1);
    606         documentStyle->setLocale(document.contentLanguage());
    607     }
    608     // This overrides any -webkit-user-modify inherited from the parent iframe.
    609     documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY);
    610 
    611     document.setStyleDependentState(documentStyle.get());
    612     return documentStyle.release();
    613 }
    614 
    615 // FIXME: This is duplicated with StyleAdjuster.cpp
    616 // Perhaps this should move onto ElementResolveContext or even Element?
    617 static inline bool isAtShadowBoundary(const Element* element)
    618 {
    619     if (!element)
    620         return false;
    621     ContainerNode* parentNode = element->parentNode();
    622     return parentNode && parentNode->isShadowRoot();
    623 }
    624 
    625 static inline void resetDirectionAndWritingModeOnDocument(Document& document)
    626 {
    627     document.setDirectionSetOnDocumentElement(false);
    628     document.setWritingModeSetOnDocumentElement(false);
    629 }
    630 
    631 static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features)
    632 {
    633     for (size_t i = 0; i < contentAttrValues.size(); ++i)
    634         features.attrsInRules.add(contentAttrValues[i]);
    635 }
    636 
    637 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior,
    638     RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
    639 {
    640     ASSERT(document().frame());
    641     ASSERT(documentSettings());
    642     ASSERT(!hasPendingAuthorStyleSheets());
    643     ASSERT(!m_needCollectFeatures);
    644 
    645     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
    646     // will vanish if a style recalc happens during loading.
    647     if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) {
    648         if (!s_styleNotYetAvailable) {
    649             s_styleNotYetAvailable = RenderStyle::create().leakRef();
    650             s_styleNotYetAvailable->setDisplay(NONE);
    651             s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector());
    652         }
    653         element->document().setHasNodesWithPlaceholderStyle();
    654         return s_styleNotYetAvailable;
    655     }
    656 
    657     didAccess();
    658 
    659     if (element == document().documentElement())
    660         resetDirectionAndWritingModeOnDocument(document());
    661     StyleResolverState state(document(), element, defaultParent, regionForStyling);
    662 
    663     if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoint() && state.parentStyle()) {
    664         SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this);
    665         if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle())
    666             return sharedStyle.release();
    667     }
    668 
    669     if (state.parentStyle()) {
    670         state.setStyle(RenderStyle::create());
    671         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
    672     } else {
    673         state.setStyle(defaultStyleForElement());
    674         state.setParentStyle(RenderStyle::clone(state.style()));
    675     }
    676     // contenteditable attribute (implemented by -webkit-user-modify) should
    677     // be propagated from shadow host to distributed node.
    678     if (state.distributedToInsertionPoint()) {
    679         if (Element* parent = element->parentElement()) {
    680             if (RenderStyle* styleOfShadowHost = parent->renderStyle())
    681                 state.style()->setUserModify(styleOfShadowHost->userModify());
    682         }
    683     }
    684 
    685     state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules());
    686 
    687     if (element->isLink()) {
    688         state.style()->setIsLink(true);
    689         EInsideLink linkState = state.elementLinkState();
    690         if (linkState != NotInsideLink) {
    691             bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
    692             if (forceVisited)
    693                 linkState = InsideVisitedLink;
    694         }
    695         state.style()->setInsideLink(linkState);
    696     }
    697 
    698     bool needsCollection = false;
    699     CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection);
    700     if (needsCollection) {
    701         collectFeatures();
    702         m_inspectorCSSOMWrappers.reset();
    703     }
    704 
    705     {
    706         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    707         collector.setRegionForStyling(regionForStyling);
    708 
    709         if (matchingBehavior == MatchOnlyUserAgentRules)
    710             matchUARules(collector);
    711         else
    712             matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL);
    713 
    714         applyMatchedProperties(state, collector.matchedResult());
    715 
    716         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
    717     }
    718     {
    719         StyleAdjuster adjuster(state.cachedUAStyle(), m_document.inQuirksMode());
    720         adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element);
    721     }
    722 
    723     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
    724     // important rules, but this currently happens here as we require adjustment to have happened
    725     // before deciding which properties to transition.
    726     applyAnimatedProperties(state, element);
    727 
    728     // FIXME: Shouldn't this be on RenderBody::styleDidChange?
    729     if (element->hasTagName(bodyTag))
    730         document().textLinkColors().setTextColor(state.style()->color());
    731 
    732     setAnimationUpdateIfNeeded(state, *element);
    733 
    734     // Now return the style.
    735     return state.takeStyle();
    736 }
    737 
    738 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const RenderStyle& elementStyle, RenderStyle* parentStyle, const StyleKeyframe* keyframe, const AtomicString& animationName)
    739 {
    740     ASSERT(document().frame());
    741     ASSERT(documentSettings());
    742     ASSERT(!hasPendingAuthorStyleSheets());
    743 
    744     if (element == document().documentElement())
    745         resetDirectionAndWritingModeOnDocument(document());
    746     StyleResolverState state(document(), element, parentStyle);
    747 
    748     MatchResult result;
    749     if (keyframe->properties())
    750         result.addMatchedProperties(keyframe->properties());
    751 
    752     ASSERT(!state.style());
    753 
    754     // Create the style
    755     state.setStyle(RenderStyle::clone(&elementStyle));
    756     state.setLineHeightValue(0);
    757 
    758     // Make sure that the CSSAnimationData for the animation to which this
    759     // keyframe belongs is first in the list. This makes sure that if the
    760     // animation-timing-function property is set for this keyframe, it will be
    761     // applied to the correct CSSAnimationData object. Note that objects other
    762     // than the first in the list are ignored when reading the timing function
    763     // value. See KeyframeValue::timingFunction().
    764     CSSAnimationDataList* animations = state.style()->accessAnimations();
    765     ASSERT(animations && !animations->isEmpty());
    766     while (animations->animation(0)->name() != animationName)
    767         animations->remove(0);
    768     ASSERT(!animations->isEmpty() && animations->animation(0)->name() == animationName);
    769 
    770     state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules());
    771 
    772     // We don't need to bother with !important. Since there is only ever one
    773     // decl, there's nothing to override. So just add the first properties.
    774     bool inheritedOnly = false;
    775     if (keyframe->properties()) {
    776         // FIXME: Can't keyframes contain variables?
    777         applyMatchedProperties<AnimationProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    778         applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    779     }
    780 
    781     // If our font got dirtied, go ahead and update it now.
    782     updateFont(state);
    783 
    784     // Line-height is set when we are sure we decided on the font-size
    785     if (state.lineHeightValue())
    786         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
    787 
    788     // Now do rest of the properties.
    789     if (keyframe->properties())
    790         applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    791 
    792     // If our font got dirtied by one of the non-essential font props,
    793     // go ahead and update it a second time.
    794     updateFont(state);
    795 
    796     // Start loading resources referenced by this style.
    797     m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
    798     document().styleEngine()->fontSelector()->loadPendingFonts();
    799 
    800     didAccess();
    801 
    802     return state.takeStyle();
    803 }
    804 
    805 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle& elementStyle, KeyframeList& list)
    806 {
    807     ASSERT(!RuntimeEnabledFeatures::webAnimationsCSSEnabled());
    808     list.clear();
    809 
    810     // Get the keyframesRule for this name
    811     if (!e || list.animationName().isEmpty())
    812         return;
    813 
    814     ASSERT(!hasPendingAuthorStyleSheets());
    815     const StyleRuleKeyframes* keyframesRule = CSSAnimations::matchScopedKeyframesRule(this, e, list.animationName().impl());
    816     if (!keyframesRule)
    817         return;
    818 
    819     // Construct and populate the style for each keyframe
    820     const AtomicString& name = list.animationName();
    821     const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
    822     for (unsigned i = 0; i < keyframes.size(); ++i) {
    823         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
    824         const StyleKeyframe* keyframe = keyframes[i].get();
    825 
    826         KeyframeValue keyframeValue(0, 0);
    827         keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, keyframe, name));
    828         keyframeValue.addProperties(keyframe->properties());
    829 
    830         // Add this keyframe style to all the indicated key times
    831         const Vector<double>& keys = keyframe->keys();
    832         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
    833             keyframeValue.setKey(keys[keyIndex]);
    834             list.insert(keyframeValue);
    835         }
    836     }
    837 
    838     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
    839     int initialListSize = list.size();
    840     if (initialListSize > 0 && list[0].key()) {
    841         static StyleKeyframe* zeroPercentKeyframe;
    842         if (!zeroPercentKeyframe) {
    843             zeroPercentKeyframe = StyleKeyframe::create().leakRef();
    844             zeroPercentKeyframe->setKeyText("0%");
    845         }
    846         KeyframeValue keyframeValue(0, 0);
    847         keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, zeroPercentKeyframe, name));
    848         keyframeValue.addProperties(zeroPercentKeyframe->properties());
    849         list.insert(keyframeValue);
    850     }
    851 
    852     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
    853     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
    854         static StyleKeyframe* hundredPercentKeyframe;
    855         if (!hundredPercentKeyframe) {
    856             hundredPercentKeyframe = StyleKeyframe::create().leakRef();
    857             hundredPercentKeyframe->setKeyText("100%");
    858         }
    859         KeyframeValue keyframeValue(1, 0);
    860         keyframeValue.setStyle(styleForKeyframe(e, elementStyle, 0, hundredPercentKeyframe, name));
    861         keyframeValue.addProperties(hundredPercentKeyframe->properties());
    862         list.insert(keyframeValue);
    863     }
    864 }
    865 
    866 // This function is used by the WebAnimations JavaScript API method animate().
    867 // FIXME: Remove this when animate() switches away from resolution-dependent parsing.
    868 PassRefPtr<KeyframeAnimationEffect> StyleResolver::createKeyframeAnimationEffect(Element& element, const Vector<RefPtr<MutableStylePropertySet> >& propertySetVector, KeyframeAnimationEffect::KeyframeVector& keyframes)
    869 {
    870     ASSERT(RuntimeEnabledFeatures::webAnimationsAPIEnabled());
    871     ASSERT(propertySetVector.size() == keyframes.size());
    872 
    873     StyleResolverState state(element.document(), &element);
    874     state.setStyle(RenderStyle::create());
    875 
    876     for (unsigned i = 0; i < propertySetVector.size(); ++i) {
    877         for (unsigned j = 0; j < propertySetVector[i]->propertyCount(); ++j) {
    878             CSSPropertyID id = propertySetVector[i]->propertyAt(j).id();
    879             StyleBuilder::applyProperty(id, state, propertySetVector[i]->getPropertyCSSValue(id).get());
    880             keyframes[i]->setPropertyValue(id, CSSAnimatableValueFactory::create(id, *state.style()).get());
    881         }
    882     }
    883     return KeyframeAnimationEffect::create(keyframes);
    884 }
    885 
    886 PassRefPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& element, PseudoId pseudoId)
    887 {
    888     RenderObject* renderer = element.renderer();
    889     if (!renderer)
    890         return 0;
    891 
    892     if (pseudoId < FIRST_INTERNAL_PSEUDOID && !renderer->style()->hasPseudoStyle(pseudoId))
    893         return 0;
    894 
    895     RenderStyle* parentStyle = renderer->style();
    896     StyleResolverState state(document(), &element, parentStyle);
    897     if (!pseudoStyleForElementInternal(element, pseudoId, parentStyle, state))
    898         return 0;
    899     RefPtr<RenderStyle> style = state.takeStyle();
    900     ASSERT(style);
    901 
    902     if (!element.needsPseudoElement(pseudoId, *style))
    903         return 0;
    904 
    905     renderer->style()->addCachedPseudoStyle(style.release());
    906     RefPtr<PseudoElement> pseudo = PseudoElement::create(&element, pseudoId);
    907 
    908     setAnimationUpdateIfNeeded(state, *pseudo);
    909     if (ActiveAnimations* activeAnimations = pseudo->activeAnimations())
    910         activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get());
    911     return pseudo.release();
    912 }
    913 
    914 bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state)
    915 {
    916     ASSERT(document().frame());
    917     ASSERT(documentSettings());
    918     ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED);
    919 
    920     if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
    921         state.setStyle(RenderStyle::create());
    922         state.style()->inheritFrom(state.parentStyle());
    923     } else {
    924         state.setStyle(defaultStyleForElement());
    925         state.setParentStyle(RenderStyle::clone(state.style()));
    926     }
    927 
    928     state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules());
    929 
    930     // Since we don't use pseudo-elements in any of our quirk/print
    931     // user agent rules, don't waste time walking those rules.
    932 
    933     {
    934         // Check UA, user and author rules.
    935         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    936         collector.setPseudoStyleRequest(pseudoStyleRequest);
    937 
    938         matchUARules(collector);
    939         matchAuthorRules(state.element(), collector, false);
    940 
    941         if (collector.matchedResult().matchedProperties.isEmpty())
    942             return false;
    943 
    944         state.style()->setStyleType(pseudoStyleRequest.pseudoId);
    945 
    946         applyMatchedProperties(state, collector.matchedResult());
    947 
    948         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
    949     }
    950     {
    951         StyleAdjuster adjuster(state.cachedUAStyle(), m_document.inQuirksMode());
    952         // FIXME: Passing 0 as the Element* introduces a lot of complexity
    953         // in the adjustRenderStyle code.
    954         adjuster.adjustRenderStyle(state.style(), state.parentStyle(), 0);
    955     }
    956 
    957     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
    958     // important rules, but this currently happens here as we require adjustment to have happened
    959     // before deciding which properties to transition.
    960     applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId));
    961 
    962     didAccess();
    963 
    964     return true;
    965 }
    966 
    967 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
    968 {
    969     ASSERT(parentStyle);
    970     if (!element)
    971         return 0;
    972 
    973     StyleResolverState state(document(), element, parentStyle);
    974     if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state))
    975         return 0;
    976 
    977     if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId))
    978         setAnimationUpdateIfNeeded(state, *pseudoElement);
    979 
    980     // Now return the style.
    981     return state.takeStyle();
    982 }
    983 
    984 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
    985 {
    986     ASSERT(!hasPendingAuthorStyleSheets());
    987     resetDirectionAndWritingModeOnDocument(document());
    988     StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
    989 
    990     state.setStyle(RenderStyle::create());
    991     const RenderStyle* rootElementStyle = state.rootElementStyle() ? state.rootElementStyle() : document().renderStyle();
    992     ASSERT(rootElementStyle);
    993     state.style()->inheritFrom(rootElementStyle);
    994 
    995     state.fontBuilder().initForStyleResolve(state.document(), state.style(), state.useSVGZoomRules());
    996 
    997     PageRuleCollector collector(rootElementStyle, pageIndex);
    998 
    999     collector.matchPageRules(CSSDefaultStyleSheets::defaultPrintStyle);
   1000 
   1001     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
   1002         scopedResolver->matchPageRules(collector);
   1003 
   1004     state.setLineHeightValue(0);
   1005     bool inheritedOnly = false;
   1006 
   1007     MatchResult& result = collector.matchedResult();
   1008     applyMatchedProperties<VariableDefinitions>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
   1009     applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
   1010 
   1011     // If our font got dirtied, go ahead and update it now.
   1012     updateFont(state);
   1013 
   1014     // Line-height is set when we are sure we decided on the font-size.
   1015     if (state.lineHeightValue())
   1016         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
   1017 
   1018     applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
   1019 
   1020     addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
   1021 
   1022     // Start loading resources referenced by this style.
   1023     m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
   1024     document().styleEngine()->fontSelector()->loadPendingFonts();
   1025 
   1026     didAccess();
   1027 
   1028     // Now return the style.
   1029     return state.takeStyle();
   1030 }
   1031 
   1032 void StyleResolver::collectViewportRules()
   1033 {
   1034     viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::defaultStyle, ViewportStyleResolver::UserAgentOrigin);
   1035 
   1036     if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this))
   1037         viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::defaultViewportStyle, ViewportStyleResolver::UserAgentOrigin);
   1038 
   1039     if (document().isMobileDocument())
   1040         viewportStyleResolver()->collectViewportRules(CSSDefaultStyleSheets::xhtmlMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin);
   1041 
   1042     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
   1043         scopedResolver->collectViewportRulesTo(this);
   1044 
   1045     viewportStyleResolver()->resolve();
   1046 }
   1047 
   1048 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
   1049 {
   1050     StyleResolverState state(document(), 0);
   1051     state.setStyle(RenderStyle::create());
   1052     state.fontBuilder().initForStyleResolve(document(), state.style(), state.useSVGZoomRules());
   1053     state.style()->setLineHeight(RenderStyle::initialLineHeight());
   1054     state.setLineHeightValue(0);
   1055     state.fontBuilder().setInitial(state.style()->effectiveZoom());
   1056     state.style()->font().update(document().styleEngine()->fontSelector());
   1057     return state.takeStyle();
   1058 }
   1059 
   1060 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
   1061 {
   1062     ASSERT(textNode);
   1063 
   1064     NodeRenderingTraversal::ParentDetails parentDetails;
   1065     Node* parentNode = NodeRenderingTraversal::parent(textNode, &parentDetails);
   1066     if (!parentNode || !parentNode->renderStyle() || parentDetails.resetStyleInheritance())
   1067         return defaultStyleForElement();
   1068     return parentNode->renderStyle();
   1069 }
   1070 
   1071 bool StyleResolver::checkRegionStyle(Element* regionElement)
   1072 {
   1073     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
   1074     // so all region rules are global by default. Verify whether that can stand or needs changing.
   1075     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument()) {
   1076         if (scopedResolver->checkRegionStyle(regionElement))
   1077             return true;
   1078     }
   1079     return false;
   1080 }
   1081 
   1082 void StyleResolver::updateFont(StyleResolverState& state)
   1083 {
   1084     state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style());
   1085 }
   1086 
   1087 PassRefPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude)
   1088 {
   1089     ASSERT(element);
   1090     StyleResolverState state(document(), element);
   1091     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
   1092     collector.setMode(SelectorChecker::CollectingStyleRules);
   1093     collectPseudoRulesForElement(element, collector, NOPSEUDO, rulesToInclude);
   1094     return collector.matchedStyleRuleList();
   1095 }
   1096 
   1097 PassRefPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude, ShouldIncludeStyleSheetInCSSOMWrapper includeDocument)
   1098 {
   1099     ASSERT(element);
   1100     StyleResolverState state(document(), element);
   1101     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style(), includeDocument);
   1102     collector.setMode(SelectorChecker::CollectingCSSRules);
   1103     collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude);
   1104     return collector.matchedCSSRuleList();
   1105 }
   1106 
   1107 PassRefPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude, ShouldIncludeStyleSheetInCSSOMWrapper includeDocument)
   1108 {
   1109     return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude, includeDocument);
   1110 }
   1111 
   1112 void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude)
   1113 {
   1114     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
   1115 
   1116     if (rulesToInclude & UAAndUserCSSRules)
   1117         matchUARules(collector);
   1118 
   1119     if (rulesToInclude & AuthorCSSRules) {
   1120         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
   1121         matchAuthorRules(element, collector, rulesToInclude & EmptyCSSRules);
   1122     }
   1123 }
   1124 
   1125 // -------------------------------------------------------------------------------------
   1126 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
   1127 
   1128 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement)
   1129 {
   1130     if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled())
   1131         return;
   1132 
   1133     const Element* element = state.element();
   1134     ASSERT(element);
   1135 
   1136     // The animating element may be this element, or its pseudo element. It is
   1137     // null when calculating the style for a potential pseudo element that has
   1138     // yet to be created.
   1139     ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element);
   1140 
   1141     if (!(animatingElement && animatingElement->hasActiveAnimations())
   1142         && !(state.style()->transitions() && !state.style()->transitions()->isEmpty())
   1143         && !(state.style()->animations() && !state.style()->animations()->isEmpty()))
   1144         return;
   1145 
   1146     state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this));
   1147     if (!state.animationUpdate())
   1148         return;
   1149 
   1150     const AnimationEffect::CompositableValueMap& compositableValuesForAnimations = state.animationUpdate()->compositableValuesForAnimations();
   1151     const AnimationEffect::CompositableValueMap& compositableValuesForTransitions = state.animationUpdate()->compositableValuesForTransitions();
   1152     applyAnimatedProperties<HighPriorityProperties>(state, compositableValuesForAnimations);
   1153     applyAnimatedProperties<HighPriorityProperties>(state, compositableValuesForTransitions);
   1154     applyAnimatedProperties<LowPriorityProperties>(state, compositableValuesForAnimations);
   1155     applyAnimatedProperties<LowPriorityProperties>(state, compositableValuesForTransitions);
   1156 
   1157     // If the animations/transitions change opacity or transform, we need to update
   1158     // the style to impose the stacking rules. Note that this is also
   1159     // done in StyleResolver::adjustRenderStyle().
   1160     RenderStyle* style = state.style();
   1161     if (style->hasAutoZIndex() && (style->opacity() < 1.0f || style->hasTransform()))
   1162         style->setZIndex(0);
   1163 }
   1164 
   1165 template <StyleResolver::StyleApplicationPass pass>
   1166 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const AnimationEffect::CompositableValueMap& compositableValues)
   1167 {
   1168     ASSERT(RuntimeEnabledFeatures::webAnimationsCSSEnabled());
   1169     ASSERT(pass != VariableDefinitions);
   1170     ASSERT(pass != AnimationProperties);
   1171 
   1172     for (AnimationEffect::CompositableValueMap::const_iterator iter = compositableValues.begin(); iter != compositableValues.end(); ++iter) {
   1173         CSSPropertyID property = iter->key;
   1174         if (!isPropertyForPass<pass>(property))
   1175             continue;
   1176         ASSERT_WITH_MESSAGE(!iter->value->dependsOnUnderlyingValue(), "Web Animations not yet implemented: An interface for compositing onto the underlying value.");
   1177         RefPtr<AnimatableValue> animatableValue = iter->value->compositeOnto(0);
   1178         AnimatedStyleBuilder::applyProperty(property, state, animatableValue.get());
   1179     }
   1180 }
   1181 
   1182 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
   1183 // FIXME: add incremental support for other region styling properties.
   1184 static inline bool isValidRegionStyleProperty(CSSPropertyID id)
   1185 {
   1186     switch (id) {
   1187     case CSSPropertyBackgroundColor:
   1188     case CSSPropertyColor:
   1189         return true;
   1190     default:
   1191         break;
   1192     }
   1193 
   1194     return false;
   1195 }
   1196 
   1197 static inline bool isValidCueStyleProperty(CSSPropertyID id)
   1198 {
   1199     switch (id) {
   1200     case CSSPropertyBackground:
   1201     case CSSPropertyBackgroundAttachment:
   1202     case CSSPropertyBackgroundClip:
   1203     case CSSPropertyBackgroundColor:
   1204     case CSSPropertyBackgroundImage:
   1205     case CSSPropertyBackgroundOrigin:
   1206     case CSSPropertyBackgroundPosition:
   1207     case CSSPropertyBackgroundPositionX:
   1208     case CSSPropertyBackgroundPositionY:
   1209     case CSSPropertyBackgroundRepeat:
   1210     case CSSPropertyBackgroundRepeatX:
   1211     case CSSPropertyBackgroundRepeatY:
   1212     case CSSPropertyBackgroundSize:
   1213     case CSSPropertyColor:
   1214     case CSSPropertyFont:
   1215     case CSSPropertyFontFamily:
   1216     case CSSPropertyFontSize:
   1217     case CSSPropertyFontStyle:
   1218     case CSSPropertyFontVariant:
   1219     case CSSPropertyFontWeight:
   1220     case CSSPropertyLineHeight:
   1221     case CSSPropertyOpacity:
   1222     case CSSPropertyOutline:
   1223     case CSSPropertyOutlineColor:
   1224     case CSSPropertyOutlineOffset:
   1225     case CSSPropertyOutlineStyle:
   1226     case CSSPropertyOutlineWidth:
   1227     case CSSPropertyVisibility:
   1228     case CSSPropertyWhiteSpace:
   1229     // FIXME: 'text-decoration' shorthand to be handled when available.
   1230     // See https://chromiumcodereview.appspot.com/19516002 for details.
   1231     case CSSPropertyTextDecoration:
   1232     case CSSPropertyTextShadow:
   1233     case CSSPropertyBorderStyle:
   1234         return true;
   1235     case CSSPropertyTextDecorationLine:
   1236     case CSSPropertyTextDecorationStyle:
   1237     case CSSPropertyTextDecorationColor:
   1238         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
   1239     default:
   1240         break;
   1241     }
   1242     return false;
   1243 }
   1244 
   1245 template <StyleResolver::StyleApplicationPass pass>
   1246 bool StyleResolver::isPropertyForPass(CSSPropertyID property)
   1247 {
   1248     COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_is_before_first_property);
   1249     const CSSPropertyID firstAnimationProperty = CSSPropertyDisplay;
   1250     const CSSPropertyID lastAnimationProperty = CSSPropertyTransitionTimingFunction;
   1251     COMPILE_ASSERT(firstCSSProperty == firstAnimationProperty, CSS_first_animation_property_should_be_first_property);
   1252     const CSSPropertyID firstHighPriorityProperty = CSSPropertyColor;
   1253     const CSSPropertyID lastHighPriorityProperty = CSSPropertyLineHeight;
   1254     COMPILE_ASSERT(lastAnimationProperty + 1 == firstHighPriorityProperty, CSS_color_is_first_high_priority_property);
   1255     COMPILE_ASSERT(CSSPropertyLineHeight == firstHighPriorityProperty + 17, CSS_line_height_is_end_of_high_prioity_property_range);
   1256     COMPILE_ASSERT(CSSPropertyZoom == lastHighPriorityProperty - 1, CSS_zoom_is_before_line_height);
   1257     switch (pass) {
   1258     case VariableDefinitions:
   1259         return property == CSSPropertyVariable;
   1260     case AnimationProperties:
   1261         return property >= firstAnimationProperty && property <= lastAnimationProperty;
   1262     case HighPriorityProperties:
   1263         return property >= firstHighPriorityProperty && property <= lastHighPriorityProperty;
   1264     case LowPriorityProperties:
   1265         return property > lastHighPriorityProperty;
   1266     }
   1267     ASSERT_NOT_REACHED();
   1268     return false;
   1269 }
   1270 
   1271 template <StyleResolver::StyleApplicationPass pass>
   1272 void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
   1273 {
   1274     ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || state.regionForStyling());
   1275     state.setCurrentRule(rule);
   1276 
   1277     unsigned propertyCount = properties->propertyCount();
   1278     for (unsigned i = 0; i < propertyCount; ++i) {
   1279         StylePropertySet::PropertyReference current = properties->propertyAt(i);
   1280         if (isImportant != current.isImportant())
   1281             continue;
   1282         if (inheritedOnly && !current.isInherited()) {
   1283             // If the property value is explicitly inherited, we need to apply further non-inherited properties
   1284             // as they might override the value inherited here. For this reason we don't allow declarations with
   1285             // explicitly inherited properties to be cached.
   1286             ASSERT(!current.value()->isInheritedValue());
   1287             continue;
   1288         }
   1289         CSSPropertyID property = current.id();
   1290 
   1291         if (propertyWhitelistType == PropertyWhitelistRegion && !isValidRegionStyleProperty(property))
   1292             continue;
   1293         if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property))
   1294             continue;
   1295         if (!isPropertyForPass<pass>(property))
   1296             continue;
   1297         if (pass == HighPriorityProperties && property == CSSPropertyLineHeight)
   1298             state.setLineHeightValue(current.value());
   1299         else
   1300             StyleBuilder::applyProperty(current.id(), state, current.value());
   1301     }
   1302 }
   1303 
   1304 template <StyleResolver::StyleApplicationPass pass>
   1305 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
   1306 {
   1307     if (startIndex == -1)
   1308         return;
   1309 
   1310     if (state.style()->insideLink() != NotInsideLink) {
   1311         for (int i = startIndex; i <= endIndex; ++i) {
   1312             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
   1313             unsigned linkMatchType = matchedProperties.linkMatchType;
   1314             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
   1315             state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
   1316             state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
   1317 
   1318             applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
   1319         }
   1320         state.setApplyPropertyToRegularStyle(true);
   1321         state.setApplyPropertyToVisitedLinkStyle(false);
   1322         return;
   1323     }
   1324     for (int i = startIndex; i <= endIndex; ++i) {
   1325         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
   1326         applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
   1327     }
   1328 }
   1329 
   1330 static unsigned computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
   1331 {
   1332     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
   1333 }
   1334 
   1335 void StyleResolver::invalidateMatchedPropertiesCache()
   1336 {
   1337     m_matchedPropertiesCache.clear();
   1338 }
   1339 
   1340 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult)
   1341 {
   1342     const Element* element = state.element();
   1343     ASSERT(element);
   1344 
   1345     INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply);
   1346 
   1347     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
   1348     bool applyInheritedOnly = false;
   1349     const CachedMatchedProperties* cachedMatchedProperties = 0;
   1350 
   1351     if (cacheHash && (cachedMatchedProperties = m_matchedPropertiesCache.find(cacheHash, state, matchResult))
   1352         && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
   1353         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit);
   1354         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
   1355         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
   1356         // element context. This is fast and saves memory by reusing the style data structures.
   1357         state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get());
   1358         if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
   1359             INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit);
   1360 
   1361             EInsideLink linkStatus = state.style()->insideLink();
   1362             // If the cache item parent style has identical inherited properties to the current parent style then the
   1363             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
   1364             state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get());
   1365 
   1366             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
   1367             state.style()->setInsideLink(linkStatus);
   1368             return;
   1369         }
   1370         applyInheritedOnly = true;
   1371     }
   1372 
   1373     // First apply all variable definitions, as they may be used during application of later properties.
   1374     applyMatchedProperties<VariableDefinitions>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1375     applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1376     applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1377     applyMatchedProperties<VariableDefinitions>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1378 
   1379     // Apply animation properties in order to apply animation results and trigger transitions below.
   1380     applyMatchedProperties<AnimationProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1381     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1382     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1383     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1384 
   1385     // Match transition-property / animation-name length by trimming and
   1386     // lengthening other transition / animation property lists
   1387     // FIXME: This is wrong because we shouldn't affect the computed values
   1388     state.style()->adjustAnimations();
   1389     state.style()->adjustTransitions();
   1390 
   1391     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
   1392     // high-priority properties first, i.e., those properties that other properties depend on.
   1393     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
   1394     // and (4) normal important.
   1395     state.setLineHeightValue(0);
   1396     applyMatchedProperties<HighPriorityProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1397     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1398     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1399     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1400 
   1401     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
   1402         state.fontBuilder().setFontDirty(true);
   1403         applyInheritedOnly = false;
   1404     }
   1405 
   1406     // If our font got dirtied, go ahead and update it now.
   1407     updateFont(state);
   1408 
   1409     // Line-height is set when we are sure we decided on the font-size.
   1410     if (state.lineHeightValue())
   1411         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
   1412 
   1413     // Many properties depend on the font. If it changes we just apply all properties.
   1414     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription())
   1415         applyInheritedOnly = false;
   1416 
   1417     // Now do the normal priority UA properties.
   1418     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1419 
   1420     // Cache the UA properties to pass them to RenderTheme in adjustRenderStyle.
   1421     state.cacheUserAgentBorderAndBackground();
   1422 
   1423     // Now do the author and user normal priority properties and all the !important properties.
   1424     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1425     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1426     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1427     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1428 
   1429     // Start loading resources referenced by this style.
   1430     m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
   1431     document().styleEngine()->fontSelector()->loadPendingFonts();
   1432 
   1433     if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
   1434         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded);
   1435         m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
   1436     }
   1437 
   1438     ASSERT(!state.fontBuilder().fontDirty());
   1439 }
   1440 
   1441 CSSPropertyValue::CSSPropertyValue(CSSPropertyID id, const StylePropertySet& propertySet)
   1442     : property(id), value(propertySet.getPropertyCSSValue(id).get())
   1443 { }
   1444 
   1445 void StyleResolver::enableStats(StatsReportType reportType)
   1446 {
   1447     if (m_styleResolverStats)
   1448         return;
   1449     m_styleResolverStats = StyleResolverStats::create();
   1450     m_styleResolverStatsTotals = StyleResolverStats::create();
   1451     if (reportType == ReportSlowStats) {
   1452         m_styleResolverStats->printMissedCandidateCount = true;
   1453         m_styleResolverStatsTotals->printMissedCandidateCount = true;
   1454     }
   1455 }
   1456 
   1457 void StyleResolver::disableStats()
   1458 {
   1459     m_styleResolverStatsSequence = 0;
   1460     m_styleResolverStats.clear();
   1461     m_styleResolverStatsTotals.clear();
   1462 }
   1463 
   1464 void StyleResolver::printStats()
   1465 {
   1466     if (!m_styleResolverStats)
   1467         return;
   1468     fprintf(stderr, "=== Style Resolver Stats (resolve #%u) (%s) ===\n", ++m_styleResolverStatsSequence, m_document.url().string().utf8().data());
   1469     fprintf(stderr, "%s\n", m_styleResolverStats->report().utf8().data());
   1470     fprintf(stderr, "== Totals ==\n");
   1471     fprintf(stderr, "%s\n", m_styleResolverStatsTotals->report().utf8().data());
   1472 }
   1473 
   1474 void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle* style)
   1475 {
   1476     StyleResolverState state(document(), document().documentElement(), style);
   1477     state.setStyle(style);
   1478 
   1479     state.fontBuilder().initForStyleResolve(document(), style, state.useSVGZoomRules());
   1480 
   1481     for (size_t i = 0; i < count; ++i) {
   1482         if (properties[i].value) {
   1483             // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
   1484             // which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122).
   1485             // The updateFont() call below updates the fontMetrics and ensure the proper setting of font-size and line-height.
   1486             switch (properties[i].property) {
   1487             case CSSPropertyFontSize:
   1488             case CSSPropertyLineHeight:
   1489                 updateFont(state);
   1490                 break;
   1491             default:
   1492                 break;
   1493             }
   1494             StyleBuilder::applyProperty(properties[i].property, state, properties[i].value);
   1495         }
   1496     }
   1497 }
   1498 
   1499 void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list)
   1500 {
   1501     for (size_t i = 0; i < list.size(); ++i)
   1502         m_viewportDependentMediaQueryResults.append(list[i]);
   1503 }
   1504 
   1505 bool StyleResolver::affectedByViewportChange() const
   1506 {
   1507     for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
   1508         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
   1509             return true;
   1510     }
   1511     return false;
   1512 }
   1513 
   1514 } // namespace WebCore
   1515