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 "core/CSSPropertyNames.h"
     33 #include "core/HTMLNames.h"
     34 #include "core/StylePropertyShorthand.h"
     35 #include "core/animation/ActiveAnimations.h"
     36 #include "core/animation/AnimatableValue.h"
     37 #include "core/animation/Animation.h"
     38 #include "core/animation/AnimationTimeline.h"
     39 #include "core/animation/css/CSSAnimatableValueFactory.h"
     40 #include "core/animation/css/CSSAnimations.h"
     41 #include "core/animation/interpolation/StyleInterpolation.h"
     42 #include "core/css/CSSCalculationValue.h"
     43 #include "core/css/CSSDefaultStyleSheets.h"
     44 #include "core/css/CSSFontSelector.h"
     45 #include "core/css/CSSKeyframeRule.h"
     46 #include "core/css/CSSKeyframesRule.h"
     47 #include "core/css/CSSReflectValue.h"
     48 #include "core/css/CSSRuleList.h"
     49 #include "core/css/CSSSelector.h"
     50 #include "core/css/CSSStyleRule.h"
     51 #include "core/css/CSSValueList.h"
     52 #include "core/css/CSSValuePool.h"
     53 #include "core/css/ElementRuleCollector.h"
     54 #include "core/css/FontFace.h"
     55 #include "core/css/MediaQueryEvaluator.h"
     56 #include "core/css/PageRuleCollector.h"
     57 #include "core/css/StylePropertySet.h"
     58 #include "core/css/StyleRuleImport.h"
     59 #include "core/css/StyleSheetContents.h"
     60 #include "core/css/parser/BisonCSSParser.h"
     61 #include "core/css/resolver/AnimatedStyleBuilder.h"
     62 #include "core/css/resolver/MatchResult.h"
     63 #include "core/css/resolver/MediaQueryResult.h"
     64 #include "core/css/resolver/SharedStyleFinder.h"
     65 #include "core/css/resolver/StyleAdjuster.h"
     66 #include "core/css/resolver/StyleResolverParentScope.h"
     67 #include "core/css/resolver/StyleResolverState.h"
     68 #include "core/css/resolver/StyleResolverStats.h"
     69 #include "core/css/resolver/ViewportStyleResolver.h"
     70 #include "core/dom/CSSSelectorWatch.h"
     71 #include "core/dom/NodeRenderStyle.h"
     72 #include "core/dom/StyleEngine.h"
     73 #include "core/dom/Text.h"
     74 #include "core/dom/shadow/ElementShadow.h"
     75 #include "core/dom/shadow/ShadowRoot.h"
     76 #include "core/frame/FrameView.h"
     77 #include "core/frame/LocalFrame.h"
     78 #include "core/html/HTMLIFrameElement.h"
     79 #include "core/inspector/InspectorInstrumentation.h"
     80 #include "core/rendering/RenderView.h"
     81 #include "core/rendering/style/KeyframeList.h"
     82 #include "core/svg/SVGDocumentExtensions.h"
     83 #include "core/svg/SVGElement.h"
     84 #include "core/svg/SVGFontFaceElement.h"
     85 #include "platform/RuntimeEnabledFeatures.h"
     86 #include "wtf/StdLibExtras.h"
     87 
     88 namespace {
     89 
     90 using namespace WebCore;
     91 
     92 void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element)
     93 {
     94     // If any changes to CSS Animations were detected, stash the update away for application after the
     95     // render object is updated if we're in the appropriate scope.
     96     if (state.animationUpdate())
     97         element.ensureActiveAnimations().cssAnimations().setPendingUpdate(state.takeAnimationUpdate());
     98 }
     99 
    100 } // namespace
    101 
    102 namespace WebCore {
    103 
    104 using namespace HTMLNames;
    105 
    106 RenderStyle* StyleResolver::s_styleNotYetAvailable;
    107 
    108 static StylePropertySet* leftToRightDeclaration()
    109 {
    110     DEFINE_STATIC_REF(MutableStylePropertySet, leftToRightDecl, (MutableStylePropertySet::create()));
    111     if (leftToRightDecl->isEmpty())
    112         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
    113     return leftToRightDecl;
    114 }
    115 
    116 static StylePropertySet* rightToLeftDeclaration()
    117 {
    118     DEFINE_STATIC_REF(MutableStylePropertySet, rightToLeftDecl, (MutableStylePropertySet::create()));
    119     if (rightToLeftDecl->isEmpty())
    120         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
    121     return rightToLeftDecl;
    122 }
    123 
    124 static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule)
    125 {
    126     RefPtrWillBeRawPtr<FontFace> fontFace = FontFace::create(document, fontFaceRule);
    127     if (fontFace)
    128         cssFontSelector->fontFaceCache()->add(cssFontSelector, fontFaceRule, fontFace);
    129 }
    130 
    131 StyleResolver::StyleResolver(Document& document)
    132     : m_document(document)
    133     , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
    134     , m_needCollectFeatures(false)
    135     , m_styleResourceLoader(document.fetcher())
    136     , m_styleSharingDepth(0)
    137     , m_styleResolverStatsSequence(0)
    138     , m_accessCount(0)
    139 {
    140     FrameView* view = document.view();
    141     if (view)
    142         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), &view->frame()));
    143     else
    144         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
    145 
    146     m_styleTree.clear();
    147 
    148     initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors());
    149 
    150 #if ENABLE(SVG_FONTS)
    151     if (document.svgExtensions()) {
    152         const WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements();
    153         WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator end = svgFontFaceElements.end();
    154         for (WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
    155             addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule());
    156     }
    157 #endif
    158 }
    159 
    160 void StyleResolver::initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors)
    161 {
    162     if (!watchedSelectors.size())
    163         return;
    164     m_watchedSelectorsRules = RuleSet::create();
    165     for (unsigned i = 0; i < watchedSelectors.size(); ++i)
    166         m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState);
    167 }
    168 
    169 void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
    170 {
    171     unsigned size = styleSheets.size();
    172     for (unsigned i = firstNew; i < size; ++i)
    173         m_pendingStyleSheets.add(styleSheets[i].get());
    174 }
    175 
    176 void StyleResolver::removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
    177 {
    178     for (unsigned i = 0; i < styleSheets.size(); ++i)
    179         m_pendingStyleSheets.remove(styleSheets[i].get());
    180 }
    181 
    182 void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet)
    183 {
    184     ASSERT(cssSheet);
    185     ASSERT(!cssSheet->disabled());
    186     if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults))
    187         return;
    188 
    189     ContainerNode* scopingNode = ScopedStyleResolver::scopingNodeFor(document(), cssSheet);
    190     if (!scopingNode)
    191         return;
    192 
    193     ScopedStyleResolver* resolver = ensureScopedStyleResolver(scopingNode);
    194     ASSERT(resolver);
    195     resolver->addRulesFromSheet(cssSheet, *m_medium, this);
    196 }
    197 
    198 void StyleResolver::appendPendingAuthorStyleSheets()
    199 {
    200     setBuildScopedStyleTreeInDocumentOrder(false);
    201     for (WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it)
    202         appendCSSStyleSheet(*it);
    203 
    204     m_pendingStyleSheets.clear();
    205     finishAppendAuthorStyleSheets();
    206 }
    207 
    208 void StyleResolver::appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
    209 {
    210     // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
    211     // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
    212     unsigned size = styleSheets.size();
    213     for (unsigned i = 0; i < size; ++i)
    214         appendCSSStyleSheet(styleSheets[i].get());
    215 }
    216 
    217 void StyleResolver::finishAppendAuthorStyleSheets()
    218 {
    219     collectFeatures();
    220 
    221     if (document().renderView() && document().renderView()->style())
    222         document().renderView()->style()->font().update(document().styleEngine()->fontSelector());
    223 
    224     collectViewportRules();
    225 
    226     document().styleEngine()->resetCSSFeatureFlags(m_features);
    227 }
    228 
    229 void StyleResolver::resetRuleFeatures()
    230 {
    231     // Need to recreate RuleFeatureSet.
    232     m_features.clear();
    233     m_siblingRuleSet.clear();
    234     m_uncommonAttributeRuleSet.clear();
    235     m_needCollectFeatures = true;
    236 }
    237 
    238 void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, ContainerNode& scope)
    239 {
    240     const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules();
    241     for (unsigned i = 0; i < keyframesRules.size(); ++i)
    242         ensureScopedStyleResolver(&scope)->addKeyframeStyle(keyframesRules[i]);
    243 
    244     m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, scope, parentStyleSheet);
    245 
    246     // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
    247     if (scope.isDocumentNode()) {
    248         const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > fontFaceRules = authorRules.fontFaceRules();
    249         for (unsigned i = 0; i < fontFaceRules.size(); ++i)
    250             addFontFaceRule(&m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]);
    251         if (fontFaceRules.size())
    252             invalidateMatchedPropertiesCache();
    253     }
    254 }
    255 
    256 void StyleResolver::resetAuthorStyle(const ContainerNode* scopingNode)
    257 {
    258     ScopedStyleResolver* resolver = scopingNode ? m_styleTree.lookupScopedStyleResolverFor(scopingNode) : m_styleTree.scopedStyleResolverForDocument();
    259     if (!resolver)
    260         return;
    261 
    262     m_treeBoundaryCrossingRules.reset(scopingNode);
    263 
    264     resolver->resetAuthorStyle();
    265     resetRuleFeatures();
    266     if (!scopingNode)
    267         return;
    268 
    269     m_styleTree.remove(scopingNode);
    270 }
    271 
    272 static PassOwnPtrWillBeRawPtr<RuleSet> makeRuleSet(const WillBeHeapVector<RuleFeature>& rules)
    273 {
    274     size_t size = rules.size();
    275     if (!size)
    276         return nullptr;
    277     OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
    278     for (size_t i = 0; i < size; ++i)
    279         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
    280     return ruleSet.release();
    281 }
    282 
    283 void StyleResolver::collectFeatures()
    284 {
    285     m_features.clear();
    286     // Collect all ids and rules using sibling selectors (:first-child and similar)
    287     // in the current set of stylesheets. Style sharing code uses this information to reject
    288     // sharing candidates.
    289     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
    290     if (defaultStyleSheets.defaultStyle())
    291         m_features.add(defaultStyleSheets.defaultStyle()->features());
    292 
    293     if (document().isViewSource())
    294         m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features());
    295 
    296     if (document().isTransitionDocument())
    297         m_features.add(defaultStyleSheets.defaultTransitionStyle()->features());
    298 
    299     if (m_watchedSelectorsRules)
    300         m_features.add(m_watchedSelectorsRules->features());
    301 
    302     m_treeBoundaryCrossingRules.collectFeaturesTo(m_features);
    303 
    304     m_styleTree.collectFeaturesTo(m_features);
    305 
    306     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
    307     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
    308     m_needCollectFeatures = false;
    309 }
    310 
    311 bool StyleResolver::hasRulesForId(const AtomicString& id) const
    312 {
    313     return m_features.hasSelectorForId(id);
    314 }
    315 
    316 void StyleResolver::addToStyleSharingList(Element& element)
    317 {
    318     // Never add elements to the style sharing list if we're not in a recalcStyle,
    319     // otherwise we could leave stale pointers in there.
    320     if (!document().inStyleRecalc())
    321         return;
    322     INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates);
    323     StyleSharingList& list = styleSharingList();
    324     if (list.size() >= styleSharingListSize)
    325         list.remove(--list.end());
    326     list.prepend(&element);
    327 }
    328 
    329 StyleSharingList& StyleResolver::styleSharingList()
    330 {
    331     m_styleSharingLists.resize(styleSharingMaxDepth);
    332 
    333     // We never put things at depth 0 into the list since that's only the <html> element
    334     // and it has no siblings or cousins to share with.
    335     unsigned depth = std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u;
    336     ASSERT(depth >= 0);
    337 
    338     if (!m_styleSharingLists[depth])
    339         m_styleSharingLists[depth] = adoptPtr(new StyleSharingList);
    340     return *m_styleSharingLists[depth];
    341 }
    342 
    343 void StyleResolver::clearStyleSharingList()
    344 {
    345     m_styleSharingLists.resize(0);
    346 }
    347 
    348 void StyleResolver::pushParentElement(Element& parent)
    349 {
    350     const ContainerNode* parentsParent = parent.parentOrShadowHostElement();
    351 
    352     // We are not always invoked consistently. For example, script execution can cause us to enter
    353     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
    354     // Reset the stack in this case, or if we see a new root element.
    355     // Otherwise just push the new parent.
    356     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
    357         m_selectorFilter.setupParentStack(parent);
    358     else
    359         m_selectorFilter.pushParent(parent);
    360 
    361     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
    362     m_styleTree.pushStyleCache(parent, parent.parentOrShadowHostNode());
    363 }
    364 
    365 void StyleResolver::popParentElement(Element& parent)
    366 {
    367     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
    368     // Pause maintaining the stack in this case.
    369     if (m_selectorFilter.parentStackIsConsistent(&parent))
    370         m_selectorFilter.popParent();
    371 
    372     m_styleTree.popStyleCache(parent);
    373 }
    374 
    375 void StyleResolver::pushParentShadowRoot(const ShadowRoot& shadowRoot)
    376 {
    377     ASSERT(shadowRoot.host());
    378     m_styleTree.pushStyleCache(shadowRoot, shadowRoot.host());
    379 }
    380 
    381 void StyleResolver::popParentShadowRoot(const ShadowRoot& shadowRoot)
    382 {
    383     ASSERT(shadowRoot.host());
    384     m_styleTree.popStyleCache(shadowRoot);
    385 }
    386 
    387 StyleResolver::~StyleResolver()
    388 {
    389 }
    390 
    391 static inline bool applyAuthorStylesOf(const Element* element)
    392 {
    393     return element->treeScope().applyAuthorStyles();
    394 }
    395 
    396 void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, Vector<ScopedStyleResolver*, 8>& resolvers, Vector<ScopedStyleResolver*, 8>& resolversInShadowTree)
    397 {
    398     collector.clearMatchedRules();
    399     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
    400 
    401     CascadeScope cascadeScope = 0;
    402     CascadeOrder cascadeOrder = 0;
    403     bool applyAuthorStyles = applyAuthorStylesOf(element);
    404 
    405     for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
    406         resolversInShadowTree.at(j)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope, cascadeOrder++);
    407 
    408     if (resolvers.isEmpty() || resolvers.first()->treeScope() != element->treeScope())
    409         ++cascadeScope;
    410     cascadeOrder += resolvers.size();
    411     for (unsigned i = 0; i < resolvers.size(); ++i)
    412         resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, --cascadeOrder);
    413 
    414     m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    415     collector.sortAndTransferMatchedRules();
    416 }
    417 
    418 void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
    419 {
    420     collector.clearMatchedRules();
    421     collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
    422 
    423     bool applyAuthorStyles = applyAuthorStylesOf(element);
    424     if (m_styleTree.hasOnlyScopedResolverForDocument()) {
    425         m_styleTree.scopedStyleResolverForDocument()->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, ignoreCascadeScope);
    426         m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    427         collector.sortAndTransferMatchedRules();
    428         return;
    429     }
    430 
    431     Vector<ScopedStyleResolver*, 8> resolvers;
    432     m_styleTree.resolveScopedStyles(element, resolvers);
    433 
    434     Vector<ScopedStyleResolver*, 8> resolversInShadowTree;
    435     m_styleTree.collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);
    436     if (!resolversInShadowTree.isEmpty()) {
    437         matchAuthorRulesForShadowHost(element, collector, includeEmptyRules, resolvers, resolversInShadowTree);
    438         return;
    439     }
    440 
    441     if (resolvers.isEmpty())
    442         return;
    443 
    444     CascadeScope cascadeScope = 0;
    445     CascadeOrder cascadeOrder = resolvers.size();
    446     for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
    447         ScopedStyleResolver* resolver = resolvers.at(i);
    448         // FIXME: Need to clarify how to treat style scoped.
    449         resolver->collectMatchingAuthorRules(collector, includeEmptyRules, applyAuthorStyles, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->scopingNode().isShadowRoot() ? 0 : cascadeOrder);
    450     }
    451 
    452     m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
    453     collector.sortAndTransferMatchedRules();
    454 }
    455 
    456 void StyleResolver::matchWatchSelectorRules(ElementRuleCollector& collector)
    457 {
    458     if (!m_watchedSelectorsRules)
    459         return;
    460 
    461     collector.clearMatchedRules();
    462     collector.matchedResult().ranges.lastUserRule = collector.matchedResult().matchedProperties.size() - 1;
    463 
    464     MatchRequest matchRequest(m_watchedSelectorsRules.get());
    465     RuleRange ruleRange = collector.matchedResult().ranges.userRuleRange();
    466     collector.collectMatchingRules(matchRequest, ruleRange);
    467 
    468     collector.sortAndTransferMatchedRules();
    469 }
    470 
    471 void StyleResolver::matchUARules(ElementRuleCollector& collector)
    472 {
    473     collector.setMatchingUARules(true);
    474 
    475     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
    476     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
    477         ? defaultStyleSheets.defaultPrintStyle() : defaultStyleSheets.defaultStyle();
    478     matchUARules(collector, userAgentStyleSheet);
    479 
    480     // In quirks mode, we match rules from the quirks user agent sheet.
    481     if (document().inQuirksMode())
    482         matchUARules(collector, defaultStyleSheets.defaultQuirksStyle());
    483 
    484     // 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.
    485     if (document().isViewSource())
    486         matchUARules(collector, defaultStyleSheets.defaultViewSourceStyle());
    487 
    488     if (document().isTransitionDocument())
    489         matchUARules(collector, defaultStyleSheets.defaultTransitionStyle());
    490 
    491     collector.setMatchingUARules(false);
    492 
    493     matchWatchSelectorRules(collector);
    494 }
    495 
    496 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules)
    497 {
    498     collector.clearMatchedRules();
    499     collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1;
    500 
    501     RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange();
    502     collector.collectMatchingRules(MatchRequest(rules), ruleRange);
    503 
    504     collector.sortAndTransferMatchedRules();
    505 }
    506 
    507 void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollector& collector, bool includeSMILProperties)
    508 {
    509     matchUARules(collector);
    510 
    511     // Now check author rules, beginning first with presentational attributes mapped from HTML.
    512     if (state.element()->isStyledElement()) {
    513         collector.addElementStyleProperties(state.element()->presentationAttributeStyle());
    514 
    515         // Now we check additional mapped declarations.
    516         // Tables and table cells share an additional mapped rule that must be applied
    517         // after all attributes, since their mapped style depends on the values of multiple attributes.
    518         collector.addElementStyleProperties(state.element()->additionalPresentationAttributeStyle());
    519 
    520         if (state.element()->isHTMLElement()) {
    521             bool isAuto;
    522             TextDirection textDirection = toHTMLElement(state.element())->directionalityIfhasDirAutoAttribute(isAuto);
    523             if (isAuto)
    524                 collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
    525         }
    526     }
    527 
    528     matchAuthorRules(state.element(), collector, false);
    529 
    530     if (state.element()->isStyledElement()) {
    531         if (state.element()->inlineStyle()) {
    532             // Inline style is immutable as long as there is no CSSOM wrapper.
    533             bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMutable();
    534             collector.addElementStyleProperties(state.element()->inlineStyle(), isInlineStyleCacheable);
    535         }
    536 
    537         // Now check SMIL animation override style.
    538         if (includeSMILProperties && state.element()->isSVGElement())
    539             collector.addElementStyleProperties(toSVGElement(state.element())->animatedSMILStyleProperties(), false /* isCacheable */);
    540     }
    541 }
    542 
    543 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document)
    544 {
    545     const LocalFrame* frame = document.frame();
    546 
    547     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
    548     documentStyle->setDisplay(BLOCK);
    549     documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder);
    550     documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1);
    551     documentStyle->setLocale(document.contentLanguage());
    552     documentStyle->setZIndex(0);
    553     documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY);
    554 
    555     document.setupFontBuilder(documentStyle.get());
    556 
    557     return documentStyle.release();
    558 }
    559 
    560 // FIXME: This is duplicated with StyleAdjuster.cpp
    561 // Perhaps this should move onto ElementResolveContext or even Element?
    562 static inline bool isAtShadowBoundary(const Element* element)
    563 {
    564     if (!element)
    565         return false;
    566     ContainerNode* parentNode = element->parentNode();
    567     return parentNode && parentNode->isShadowRoot();
    568 }
    569 
    570 static inline void resetDirectionAndWritingModeOnDocument(Document& document)
    571 {
    572     document.setDirectionSetOnDocumentElement(false);
    573     document.setWritingModeSetOnDocumentElement(false);
    574 }
    575 
    576 static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features)
    577 {
    578     for (size_t i = 0; i < contentAttrValues.size(); ++i)
    579         features.addContentAttr(contentAttrValues[i]);
    580 }
    581 
    582 void StyleResolver::adjustRenderStyle(StyleResolverState& state, Element* element)
    583 {
    584     StyleAdjuster adjuster(m_document.inQuirksMode());
    585     adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element, state.cachedUAStyle());
    586 }
    587 
    588 // Start loading resources referenced by this style.
    589 void StyleResolver::loadPendingResources(StyleResolverState& state)
    590 {
    591     m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
    592     document().styleEngine()->fontSelector()->fontLoader()->loadPendingFonts();
    593 }
    594 
    595 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior,
    596     RuleMatchingBehavior matchingBehavior)
    597 {
    598     ASSERT(document().frame());
    599     ASSERT(documentSettings());
    600     ASSERT(!hasPendingAuthorStyleSheets());
    601     ASSERT(!m_needCollectFeatures);
    602 
    603     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
    604     // will vanish if a style recalc happens during loading.
    605     if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() && !element->renderer()) {
    606         if (!s_styleNotYetAvailable) {
    607             s_styleNotYetAvailable = RenderStyle::create().leakRef();
    608             s_styleNotYetAvailable->setDisplay(NONE);
    609             s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector());
    610         }
    611 
    612         document().setHasNodesWithPlaceholderStyle();
    613         return s_styleNotYetAvailable;
    614     }
    615 
    616     didAccess();
    617 
    618     StyleResolverParentScope::ensureParentStackIsPushed();
    619 
    620     if (element == document().documentElement())
    621         resetDirectionAndWritingModeOnDocument(document());
    622     StyleResolverState state(document(), element, defaultParent);
    623 
    624     if (sharingBehavior == AllowStyleSharing && state.parentStyle()) {
    625         SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this);
    626         if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle())
    627             return sharedStyle.release();
    628     }
    629 
    630     if (state.parentStyle()) {
    631         state.setStyle(RenderStyle::create());
    632         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
    633     } else {
    634         state.setStyle(defaultStyleForElement());
    635         state.setParentStyle(RenderStyle::clone(state.style()));
    636     }
    637     // contenteditable attribute (implemented by -webkit-user-modify) should
    638     // be propagated from shadow host to distributed node.
    639     if (state.distributedToInsertionPoint()) {
    640         if (Element* parent = element->parentElement()) {
    641             if (RenderStyle* styleOfShadowHost = parent->renderStyle())
    642                 state.style()->setUserModify(styleOfShadowHost->userModify());
    643         }
    644     }
    645 
    646     state.fontBuilder().initForStyleResolve(state.document(), state.style());
    647 
    648     if (element->isLink()) {
    649         state.style()->setIsLink(true);
    650         EInsideLink linkState = state.elementLinkState();
    651         if (linkState != NotInsideLink) {
    652             bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
    653             if (forceVisited)
    654                 linkState = InsideVisitedLink;
    655         }
    656         state.style()->setInsideLink(linkState);
    657     }
    658 
    659     bool needsCollection = false;
    660     CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element, needsCollection);
    661     if (needsCollection)
    662         collectFeatures();
    663 
    664     {
    665         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    666 
    667         matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL);
    668 
    669         applyMatchedProperties(state, collector.matchedResult());
    670 
    671         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
    672     }
    673 
    674     // Cache our original display.
    675     state.style()->setOriginalDisplay(state.style()->display());
    676 
    677     adjustRenderStyle(state, element);
    678 
    679     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
    680     // important rules, but this currently happens here as we require adjustment to have happened
    681     // before deciding which properties to transition.
    682     if (applyAnimatedProperties(state, element))
    683         adjustRenderStyle(state, element);
    684 
    685     // FIXME: Shouldn't this be on RenderBody::styleDidChange?
    686     if (isHTMLBodyElement(*element))
    687         document().textLinkColors().setTextColor(state.style()->color());
    688 
    689     setAnimationUpdateIfNeeded(state, *element);
    690 
    691     if (state.style()->hasViewportUnits())
    692         document().setHasViewportUnits();
    693 
    694     // Now return the style.
    695     return state.takeStyle();
    696 }
    697 
    698 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element* element, const RenderStyle& elementStyle, RenderStyle* parentStyle, const StyleKeyframe* keyframe, const AtomicString& animationName)
    699 {
    700     ASSERT(document().frame());
    701     ASSERT(documentSettings());
    702     ASSERT(!hasPendingAuthorStyleSheets());
    703 
    704     if (element == document().documentElement())
    705         resetDirectionAndWritingModeOnDocument(document());
    706     StyleResolverState state(document(), element, parentStyle);
    707 
    708     MatchResult result;
    709     result.addMatchedProperties(&keyframe->properties());
    710 
    711     ASSERT(!state.style());
    712 
    713     // Create the style
    714     state.setStyle(RenderStyle::clone(&elementStyle));
    715     state.setLineHeightValue(0);
    716 
    717     state.fontBuilder().initForStyleResolve(state.document(), state.style());
    718 
    719     // We don't need to bother with !important. Since there is only ever one
    720     // decl, there's nothing to override. So just add the first properties.
    721     // We also don't need to bother with animation properties since the only
    722     // relevant one is animation-timing-function and we special-case that in
    723     // CSSAnimations.cpp
    724     bool inheritedOnly = false;
    725     applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    726 
    727     // If our font got dirtied, go ahead and update it now.
    728     updateFont(state);
    729 
    730     // Line-height is set when we are sure we decided on the font-size
    731     if (state.lineHeightValue())
    732         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
    733 
    734     // Now do rest of the properties.
    735     applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    736 
    737     // If our font got dirtied by one of the non-essential font props,
    738     // go ahead and update it a second time.
    739     updateFont(state);
    740 
    741     loadPendingResources(state);
    742 
    743     didAccess();
    744 
    745     return state.takeStyle();
    746 }
    747 
    748 // This function is used by the WebAnimations JavaScript API method animate().
    749 // FIXME: Remove this when animate() switches away from resolution-dependent parsing.
    750 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(Element& element, CSSPropertyID property, CSSValue& value)
    751 {
    752     RefPtr<RenderStyle> style;
    753     if (element.renderStyle())
    754         style = RenderStyle::clone(element.renderStyle());
    755     else
    756         style = RenderStyle::create();
    757     StyleResolverState state(element.document(), &element);
    758     state.setStyle(style);
    759     state.fontBuilder().initForStyleResolve(state.document(), state.style());
    760     return createAnimatableValueSnapshot(state, property, value);
    761 }
    762 
    763 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(StyleResolverState& state, CSSPropertyID property, CSSValue& value)
    764 {
    765     StyleBuilder::applyProperty(property, state, &value);
    766     return CSSAnimatableValueFactory::create(property, *state.style());
    767 }
    768 
    769 PassRefPtrWillBeRawPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& parent, PseudoId pseudoId)
    770 {
    771     RenderObject* parentRenderer = parent.renderer();
    772     if (!parentRenderer)
    773         return nullptr;
    774 
    775     if (pseudoId < FIRST_INTERNAL_PSEUDOID && !parentRenderer->style()->hasPseudoStyle(pseudoId))
    776         return nullptr;
    777 
    778     if (pseudoId == BACKDROP && !parent.isInTopLayer())
    779         return nullptr;
    780 
    781     if (!parentRenderer->canHaveGeneratedChildren())
    782         return nullptr;
    783 
    784     RenderStyle* parentStyle = parentRenderer->style();
    785     if (RenderStyle* cachedStyle = parentStyle->getCachedPseudoStyle(pseudoId)) {
    786         if (!pseudoElementRendererIsNeeded(cachedStyle))
    787             return nullptr;
    788         return PseudoElement::create(&parent, pseudoId);
    789     }
    790 
    791     StyleResolverState state(document(), &parent, parentStyle);
    792     if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state))
    793         return nullptr;
    794     RefPtr<RenderStyle> style = state.takeStyle();
    795     ASSERT(style);
    796     parentStyle->addCachedPseudoStyle(style);
    797 
    798     if (!pseudoElementRendererIsNeeded(style.get()))
    799         return nullptr;
    800 
    801     RefPtrWillBeRawPtr<PseudoElement> pseudo = PseudoElement::create(&parent, pseudoId);
    802 
    803     setAnimationUpdateIfNeeded(state, *pseudo);
    804     if (ActiveAnimations* activeAnimations = pseudo->activeAnimations())
    805         activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get());
    806     return pseudo.release();
    807 }
    808 
    809 bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state)
    810 {
    811     ASSERT(document().frame());
    812     ASSERT(documentSettings());
    813     ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED);
    814 
    815     StyleResolverParentScope::ensureParentStackIsPushed();
    816 
    817     if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
    818         state.setStyle(RenderStyle::create());
    819         state.style()->inheritFrom(state.parentStyle());
    820     } else {
    821         state.setStyle(defaultStyleForElement());
    822         state.setParentStyle(RenderStyle::clone(state.style()));
    823     }
    824 
    825     state.fontBuilder().initForStyleResolve(state.document(), state.style());
    826 
    827     // Since we don't use pseudo-elements in any of our quirk/print
    828     // user agent rules, don't waste time walking those rules.
    829 
    830     {
    831         // Check UA, user and author rules.
    832         ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    833         collector.setPseudoStyleRequest(pseudoStyleRequest);
    834 
    835         matchUARules(collector);
    836         matchAuthorRules(state.element(), collector, false);
    837 
    838         if (collector.matchedResult().matchedProperties.isEmpty())
    839             return false;
    840 
    841         state.style()->setStyleType(pseudoStyleRequest.pseudoId);
    842 
    843         applyMatchedProperties(state, collector.matchedResult());
    844 
    845         addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
    846     }
    847 
    848     // Cache our original display.
    849     state.style()->setOriginalDisplay(state.style()->display());
    850 
    851     // FIXME: Passing 0 as the Element* introduces a lot of complexity
    852     // in the adjustRenderStyle code.
    853     adjustRenderStyle(state, 0);
    854 
    855     // FIXME: The CSSWG wants to specify that the effects of animations are applied before
    856     // important rules, but this currently happens here as we require adjustment to have happened
    857     // before deciding which properties to transition.
    858     if (applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId)))
    859         adjustRenderStyle(state, 0);
    860 
    861     didAccess();
    862 
    863     if (state.style()->hasViewportUnits())
    864         document().setHasViewportUnits();
    865 
    866     return true;
    867 }
    868 
    869 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
    870 {
    871     ASSERT(parentStyle);
    872     if (!element)
    873         return nullptr;
    874 
    875     StyleResolverState state(document(), element, parentStyle);
    876     if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state))
    877         return nullptr;
    878 
    879     if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId))
    880         setAnimationUpdateIfNeeded(state, *pseudoElement);
    881 
    882     // Now return the style.
    883     return state.takeStyle();
    884 }
    885 
    886 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
    887 {
    888     ASSERT(!hasPendingAuthorStyleSheets());
    889     resetDirectionAndWritingModeOnDocument(document());
    890     StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
    891 
    892     state.setStyle(RenderStyle::create());
    893     const RenderStyle* rootElementStyle = state.rootElementStyle() ? state.rootElementStyle() : document().renderStyle();
    894     ASSERT(rootElementStyle);
    895     state.style()->inheritFrom(rootElementStyle);
    896 
    897     state.fontBuilder().initForStyleResolve(state.document(), state.style());
    898 
    899     PageRuleCollector collector(rootElementStyle, pageIndex);
    900 
    901     collector.matchPageRules(CSSDefaultStyleSheets::instance().defaultPrintStyle());
    902 
    903     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
    904         scopedResolver->matchPageRules(collector);
    905 
    906     state.setLineHeightValue(0);
    907     bool inheritedOnly = false;
    908 
    909     MatchResult& result = collector.matchedResult();
    910     applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    911 
    912     // If our font got dirtied, go ahead and update it now.
    913     updateFont(state);
    914 
    915     // Line-height is set when we are sure we decided on the font-size.
    916     if (state.lineHeightValue())
    917         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
    918 
    919     applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
    920 
    921     addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
    922 
    923     loadPendingResources(state);
    924 
    925     didAccess();
    926 
    927     // Now return the style.
    928     return state.takeStyle();
    929 }
    930 
    931 void StyleResolver::collectViewportRules()
    932 {
    933     CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
    934     viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultStyle(), ViewportStyleResolver::UserAgentOrigin);
    935 
    936     if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this))
    937         viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultViewportStyle(), ViewportStyleResolver::UserAgentOrigin);
    938 
    939     if (document().isMobileDocument())
    940         viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin);
    941 
    942     if (ScopedStyleResolver* scopedResolver = m_styleTree.scopedStyleResolverForDocument())
    943         scopedResolver->collectViewportRulesTo(this);
    944 
    945     viewportStyleResolver()->resolve();
    946 }
    947 
    948 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
    949 {
    950     StyleResolverState state(document(), 0);
    951     state.setStyle(RenderStyle::create());
    952     state.fontBuilder().initForStyleResolve(document(), state.style());
    953     state.style()->setLineHeight(RenderStyle::initialLineHeight());
    954     state.setLineHeightValue(0);
    955     state.fontBuilder().setInitial(state.style()->effectiveZoom());
    956     state.style()->font().update(document().styleEngine()->fontSelector());
    957     return state.takeStyle();
    958 }
    959 
    960 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
    961 {
    962     ASSERT(textNode);
    963 
    964     NodeRenderingTraversal::ParentDetails parentDetails;
    965     Node* parentNode = NodeRenderingTraversal::parent(textNode, &parentDetails);
    966     if (!parentNode || !parentNode->renderStyle())
    967         return defaultStyleForElement();
    968     return parentNode->renderStyle();
    969 }
    970 
    971 void StyleResolver::updateFont(StyleResolverState& state)
    972 {
    973     state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style());
    974     if (state.fontBuilder().fontSizeHasViewportUnits())
    975         state.style()->setHasViewportUnits();
    976 }
    977 
    978 PassRefPtrWillBeRawPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude)
    979 {
    980     ASSERT(element);
    981     StyleResolverState state(document(), element);
    982     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    983     collector.setMode(SelectorChecker::CollectingStyleRules);
    984     collectPseudoRulesForElement(element, collector, NOPSEUDO, rulesToInclude);
    985     return collector.matchedStyleRuleList();
    986 }
    987 
    988 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
    989 {
    990     ASSERT(element);
    991     StyleResolverState state(document(), element);
    992     ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
    993     collector.setMode(SelectorChecker::CollectingCSSRules);
    994     collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude);
    995     return collector.matchedCSSRuleList();
    996 }
    997 
    998 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude)
    999 {
   1000     return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude);
   1001 }
   1002 
   1003 void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude)
   1004 {
   1005     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
   1006 
   1007     if (rulesToInclude & UAAndUserCSSRules)
   1008         matchUARules(collector);
   1009 
   1010     if (rulesToInclude & AuthorCSSRules) {
   1011         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
   1012         matchAuthorRules(element, collector, rulesToInclude & EmptyCSSRules);
   1013     }
   1014 }
   1015 
   1016 // -------------------------------------------------------------------------------------
   1017 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
   1018 
   1019 bool StyleResolver::applyAnimatedProperties(StyleResolverState& state, Element* animatingElement)
   1020 {
   1021     const Element* element = state.element();
   1022     ASSERT(element);
   1023 
   1024     // The animating element may be this element, or its pseudo element. It is
   1025     // null when calculating the style for a potential pseudo element that has
   1026     // yet to be created.
   1027     ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element);
   1028 
   1029     if (!(animatingElement && animatingElement->hasActiveAnimations())
   1030         && !state.style()->transitions() && !state.style()->animations())
   1031         return false;
   1032 
   1033     state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this));
   1034     if (!state.animationUpdate())
   1035         return false;
   1036 
   1037     const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations = state.animationUpdate()->activeInterpolationsForAnimations();
   1038     const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions = state.animationUpdate()->activeInterpolationsForTransitions();
   1039     applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForAnimations);
   1040     applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForTransitions);
   1041 
   1042     updateFont(state);
   1043 
   1044     applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForAnimations);
   1045     applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForTransitions);
   1046 
   1047     // Start loading resources used by animations.
   1048     loadPendingResources(state);
   1049 
   1050     ASSERT(!state.fontBuilder().fontDirty());
   1051 
   1052     return true;
   1053 }
   1054 
   1055 template <StyleResolver::StyleApplicationPass pass>
   1056 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolations)
   1057 {
   1058     ASSERT(pass != AnimationProperties);
   1059 
   1060     for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = activeInterpolations.begin(); iter != activeInterpolations.end(); ++iter) {
   1061         CSSPropertyID property = iter->key;
   1062         if (!isPropertyForPass<pass>(property))
   1063             continue;
   1064         const StyleInterpolation* interpolation = toStyleInterpolation(iter->value.get());
   1065         interpolation->apply(state);
   1066     }
   1067 }
   1068 
   1069 static inline bool isValidCueStyleProperty(CSSPropertyID id)
   1070 {
   1071     switch (id) {
   1072     case CSSPropertyBackground:
   1073     case CSSPropertyBackgroundAttachment:
   1074     case CSSPropertyBackgroundClip:
   1075     case CSSPropertyBackgroundColor:
   1076     case CSSPropertyBackgroundImage:
   1077     case CSSPropertyBackgroundOrigin:
   1078     case CSSPropertyBackgroundPosition:
   1079     case CSSPropertyBackgroundPositionX:
   1080     case CSSPropertyBackgroundPositionY:
   1081     case CSSPropertyBackgroundRepeat:
   1082     case CSSPropertyBackgroundRepeatX:
   1083     case CSSPropertyBackgroundRepeatY:
   1084     case CSSPropertyBackgroundSize:
   1085     case CSSPropertyColor:
   1086     case CSSPropertyFont:
   1087     case CSSPropertyFontFamily:
   1088     case CSSPropertyFontSize:
   1089     case CSSPropertyFontStyle:
   1090     case CSSPropertyFontVariant:
   1091     case CSSPropertyFontWeight:
   1092     case CSSPropertyLineHeight:
   1093     case CSSPropertyOpacity:
   1094     case CSSPropertyOutline:
   1095     case CSSPropertyOutlineColor:
   1096     case CSSPropertyOutlineOffset:
   1097     case CSSPropertyOutlineStyle:
   1098     case CSSPropertyOutlineWidth:
   1099     case CSSPropertyVisibility:
   1100     case CSSPropertyWhiteSpace:
   1101     // FIXME: 'text-decoration' shorthand to be handled when available.
   1102     // See https://chromiumcodereview.appspot.com/19516002 for details.
   1103     case CSSPropertyTextDecoration:
   1104     case CSSPropertyTextShadow:
   1105     case CSSPropertyBorderStyle:
   1106         return true;
   1107     case CSSPropertyTextDecorationLine:
   1108     case CSSPropertyTextDecorationStyle:
   1109     case CSSPropertyTextDecorationColor:
   1110         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
   1111     default:
   1112         break;
   1113     }
   1114     return false;
   1115 }
   1116 
   1117 static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id)
   1118 {
   1119     switch (id) {
   1120     // Valid ::first-letter properties listed in spec:
   1121     // http://www.w3.org/TR/css3-selectors/#application-in-css
   1122     case CSSPropertyBackgroundAttachment:
   1123     case CSSPropertyBackgroundBlendMode:
   1124     case CSSPropertyBackgroundClip:
   1125     case CSSPropertyBackgroundColor:
   1126     case CSSPropertyBackgroundImage:
   1127     case CSSPropertyBackgroundOrigin:
   1128     case CSSPropertyBackgroundPosition:
   1129     case CSSPropertyBackgroundPositionX:
   1130     case CSSPropertyBackgroundPositionY:
   1131     case CSSPropertyBackgroundRepeat:
   1132     case CSSPropertyBackgroundRepeatX:
   1133     case CSSPropertyBackgroundRepeatY:
   1134     case CSSPropertyBackgroundSize:
   1135     case CSSPropertyBorderBottomColor:
   1136     case CSSPropertyBorderBottomLeftRadius:
   1137     case CSSPropertyBorderBottomRightRadius:
   1138     case CSSPropertyBorderBottomStyle:
   1139     case CSSPropertyBorderBottomWidth:
   1140     case CSSPropertyBorderImageOutset:
   1141     case CSSPropertyBorderImageRepeat:
   1142     case CSSPropertyBorderImageSlice:
   1143     case CSSPropertyBorderImageSource:
   1144     case CSSPropertyBorderImageWidth:
   1145     case CSSPropertyBorderLeftColor:
   1146     case CSSPropertyBorderLeftStyle:
   1147     case CSSPropertyBorderLeftWidth:
   1148     case CSSPropertyBorderRightColor:
   1149     case CSSPropertyBorderRightStyle:
   1150     case CSSPropertyBorderRightWidth:
   1151     case CSSPropertyBorderTopColor:
   1152     case CSSPropertyBorderTopLeftRadius:
   1153     case CSSPropertyBorderTopRightRadius:
   1154     case CSSPropertyBorderTopStyle:
   1155     case CSSPropertyBorderTopWidth:
   1156     case CSSPropertyColor:
   1157     case CSSPropertyFloat:
   1158     case CSSPropertyFont:
   1159     case CSSPropertyFontFamily:
   1160     case CSSPropertyFontKerning:
   1161     case CSSPropertyFontSize:
   1162     case CSSPropertyFontStretch:
   1163     case CSSPropertyFontStyle:
   1164     case CSSPropertyFontVariant:
   1165     case CSSPropertyFontVariantLigatures:
   1166     case CSSPropertyFontWeight:
   1167     case CSSPropertyLetterSpacing:
   1168     case CSSPropertyLineHeight:
   1169     case CSSPropertyMarginBottom:
   1170     case CSSPropertyMarginLeft:
   1171     case CSSPropertyMarginRight:
   1172     case CSSPropertyMarginTop:
   1173     case CSSPropertyPaddingBottom:
   1174     case CSSPropertyPaddingLeft:
   1175     case CSSPropertyPaddingRight:
   1176     case CSSPropertyPaddingTop:
   1177     case CSSPropertyTextTransform:
   1178     case CSSPropertyVerticalAlign:
   1179     case CSSPropertyWebkitBackgroundClip:
   1180     case CSSPropertyWebkitBackgroundComposite:
   1181     case CSSPropertyWebkitBackgroundOrigin:
   1182     case CSSPropertyWebkitBackgroundSize:
   1183     case CSSPropertyWebkitBorderAfter:
   1184     case CSSPropertyWebkitBorderAfterColor:
   1185     case CSSPropertyWebkitBorderAfterStyle:
   1186     case CSSPropertyWebkitBorderAfterWidth:
   1187     case CSSPropertyWebkitBorderBefore:
   1188     case CSSPropertyWebkitBorderBeforeColor:
   1189     case CSSPropertyWebkitBorderBeforeStyle:
   1190     case CSSPropertyWebkitBorderBeforeWidth:
   1191     case CSSPropertyWebkitBorderEnd:
   1192     case CSSPropertyWebkitBorderEndColor:
   1193     case CSSPropertyWebkitBorderEndStyle:
   1194     case CSSPropertyWebkitBorderEndWidth:
   1195     case CSSPropertyWebkitBorderFit:
   1196     case CSSPropertyWebkitBorderHorizontalSpacing:
   1197     case CSSPropertyWebkitBorderImage:
   1198     case CSSPropertyWebkitBorderRadius:
   1199     case CSSPropertyWebkitBorderStart:
   1200     case CSSPropertyWebkitBorderStartColor:
   1201     case CSSPropertyWebkitBorderStartStyle:
   1202     case CSSPropertyWebkitBorderStartWidth:
   1203     case CSSPropertyWebkitBorderVerticalSpacing:
   1204     case CSSPropertyWebkitFontSmoothing:
   1205     case CSSPropertyWebkitMarginAfter:
   1206     case CSSPropertyWebkitMarginAfterCollapse:
   1207     case CSSPropertyWebkitMarginBefore:
   1208     case CSSPropertyWebkitMarginBeforeCollapse:
   1209     case CSSPropertyWebkitMarginBottomCollapse:
   1210     case CSSPropertyWebkitMarginCollapse:
   1211     case CSSPropertyWebkitMarginEnd:
   1212     case CSSPropertyWebkitMarginStart:
   1213     case CSSPropertyWebkitMarginTopCollapse:
   1214     case CSSPropertyWordSpacing:
   1215         return true;
   1216     case CSSPropertyTextDecorationColor:
   1217     case CSSPropertyTextDecorationLine:
   1218     case CSSPropertyTextDecorationStyle:
   1219         return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
   1220 
   1221     // text-shadow added in text decoration spec:
   1222     // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
   1223     case CSSPropertyTextShadow:
   1224     // box-shadox added in CSS3 backgrounds spec:
   1225     // http://www.w3.org/TR/css3-background/#placement
   1226     case CSSPropertyBoxShadow:
   1227     case CSSPropertyWebkitBoxShadow:
   1228     // Properties that we currently support outside of spec.
   1229     case CSSPropertyWebkitLineBoxContain:
   1230     case CSSPropertyVisibility:
   1231         return true;
   1232 
   1233     default:
   1234         return false;
   1235     }
   1236 }
   1237 
   1238 // FIXME: Consider refactoring to create a new class which owns the following
   1239 // first/last/range properties.
   1240 // This method returns the first CSSPropertyId of properties which generate
   1241 // animations. All animation properties are obtained by using
   1242 // firstCSSPropertyId<AnimationProperties> and
   1243 // lastCSSPropertyId<AnimationProperties>.
   1244 // c.f. //src/third_party/WebKit/Source/core/css/CSSPropertyNames.in.
   1245 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::AnimationProperties>()
   1246 {
   1247     COMPILE_ASSERT(firstCSSProperty == CSSPropertyDisplay, CSS_first_animation_property_should_be_first_property);
   1248     return CSSPropertyDisplay;
   1249 }
   1250 
   1251 // This method returns the first CSSPropertyId of properties which generate
   1252 // animations.
   1253 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::AnimationProperties>()
   1254 {
   1255     COMPILE_ASSERT(CSSPropertyTransitionTimingFunction == CSSPropertyColor - 1, CSS_transition_timing_is_last_animation_property);
   1256     return CSSPropertyTransitionTimingFunction;
   1257 }
   1258 
   1259 // This method returns the first CSSPropertyId of high priority properties.
   1260 // Other properties can depend on high priority properties. For example,
   1261 // border-color property with currentColor value depends on color property.
   1262 // All high priority properties are obtained by using
   1263 // firstCSSPropertyId<HighPriorityProperties> and
   1264 // lastCSSPropertyId<HighPriorityProperties>.
   1265 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::HighPriorityProperties>()
   1266 {
   1267     COMPILE_ASSERT(CSSPropertyTransitionTimingFunction + 1 == CSSPropertyColor, CSS_color_is_first_high_priority_property);
   1268     return CSSPropertyColor;
   1269 }
   1270 
   1271 // This method returns the last CSSPropertyId of high priority properties.
   1272 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::HighPriorityProperties>()
   1273 {
   1274     COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyColor + 17, CSS_line_height_is_end_of_high_prioity_property_range);
   1275     COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyLineHeight - 1, CSS_zoom_is_before_line_height);
   1276     return CSSPropertyLineHeight;
   1277 }
   1278 
   1279 // This method returns the first CSSPropertyId of remaining properties,
   1280 // i.e. low priority properties. No properties depend on low priority
   1281 // properties. So we don't need to resolve such properties quickly.
   1282 // All low priority properties are obtained by using
   1283 // firstCSSPropertyId<LowPriorityProperties> and
   1284 // lastCSSPropertyId<LowPriorityProperties>.
   1285 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::LowPriorityProperties>()
   1286 {
   1287     COMPILE_ASSERT(CSSPropertyBackground == CSSPropertyLineHeight + 1, CSS_background_is_first_low_priority_property);
   1288     return CSSPropertyBackground;
   1289 }
   1290 
   1291 // This method returns the last CSSPropertyId of low priority properties.
   1292 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::LowPriorityProperties>()
   1293 {
   1294     return static_cast<CSSPropertyID>(lastCSSProperty);
   1295 }
   1296 
   1297 template <StyleResolver::StyleApplicationPass pass>
   1298 bool StyleResolver::isPropertyForPass(CSSPropertyID property)
   1299 {
   1300     return firstCSSPropertyId<pass>() <= property && property <= lastCSSPropertyId<pass>();
   1301 }
   1302 
   1303 // This method expands all shorthand property to longhand properties
   1304 // considering StyleApplicationPass, and apply each expanded longhand property.
   1305 // For example, if StyleApplicationPass is AnimationProperties, all shorthand
   1306 // is expaneded to display, -webkit-animation, -webkit-animation-delay, ...,
   1307 // transition-timing-function. So each property's value will be applied
   1308 // according to all's value (initial, inherit or unset).
   1309 template <StyleResolver::StyleApplicationPass pass>
   1310 void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue)
   1311 {
   1312     bool isUnsetValue = !allValue->isInitialValue() && !allValue->isInheritedValue();
   1313     unsigned startCSSProperty = firstCSSPropertyId<pass>();
   1314     unsigned endCSSProperty = lastCSSPropertyId<pass>();
   1315 
   1316     for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) {
   1317         CSSPropertyID propertyId = static_cast<CSSPropertyID>(i);
   1318 
   1319         // StyleBuilder does not allow any expanded shorthands.
   1320         if (isExpandedShorthandForAll(propertyId))
   1321             continue;
   1322 
   1323         // all shorthand spec says:
   1324         // The all property is a shorthand that resets all CSS properties
   1325         // except direction and unicode-bidi.
   1326         // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
   1327         // We skip applyProperty when a given property is unicode-bidi or
   1328         // direction.
   1329         if (!CSSProperty::isAffectedByAllProperty(propertyId))
   1330             continue;
   1331 
   1332         CSSValue* value;
   1333         if (!isUnsetValue) {
   1334             value = allValue;
   1335         } else {
   1336             if (CSSProperty::isInheritedProperty(propertyId))
   1337                 value = cssValuePool().createInheritedValue().get();
   1338             else
   1339                 value = cssValuePool().createExplicitInitialValue().get();
   1340         }
   1341         StyleBuilder::applyProperty(propertyId, state, value);
   1342     }
   1343 }
   1344 
   1345 template <StyleResolver::StyleApplicationPass pass>
   1346 void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
   1347 {
   1348     state.setCurrentRule(rule);
   1349 
   1350     unsigned propertyCount = properties->propertyCount();
   1351     for (unsigned i = 0; i < propertyCount; ++i) {
   1352         StylePropertySet::PropertyReference current = properties->propertyAt(i);
   1353         if (isImportant != current.isImportant())
   1354             continue;
   1355 
   1356         CSSPropertyID property = current.id();
   1357         if (property == CSSPropertyAll) {
   1358             applyAllProperty<pass>(state, current.value());
   1359             continue;
   1360         }
   1361 
   1362         if (inheritedOnly && !current.isInherited()) {
   1363             // If the property value is explicitly inherited, we need to apply further non-inherited properties
   1364             // as they might override the value inherited here. For this reason we don't allow declarations with
   1365             // explicitly inherited properties to be cached.
   1366             ASSERT(!current.value()->isInheritedValue());
   1367             continue;
   1368         }
   1369 
   1370         if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property))
   1371             continue;
   1372         if (propertyWhitelistType == PropertyWhitelistFirstLetter && !isValidFirstLetterStyleProperty(property))
   1373             continue;
   1374         if (!isPropertyForPass<pass>(property))
   1375             continue;
   1376         if (pass == HighPriorityProperties && property == CSSPropertyLineHeight)
   1377             state.setLineHeightValue(current.value());
   1378         else
   1379             StyleBuilder::applyProperty(current.id(), state, current.value());
   1380     }
   1381 }
   1382 
   1383 template <StyleResolver::StyleApplicationPass pass>
   1384 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
   1385 {
   1386     if (startIndex == -1)
   1387         return;
   1388 
   1389     if (state.style()->insideLink() != NotInsideLink) {
   1390         for (int i = startIndex; i <= endIndex; ++i) {
   1391             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
   1392             unsigned linkMatchType = matchedProperties.linkMatchType;
   1393             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
   1394             state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
   1395             state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
   1396 
   1397             applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
   1398         }
   1399         state.setApplyPropertyToRegularStyle(true);
   1400         state.setApplyPropertyToVisitedLinkStyle(false);
   1401         return;
   1402     }
   1403     for (int i = startIndex; i <= endIndex; ++i) {
   1404         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
   1405         applyProperties<pass>(state, matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
   1406     }
   1407 }
   1408 
   1409 static unsigned computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
   1410 {
   1411     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
   1412 }
   1413 
   1414 void StyleResolver::invalidateMatchedPropertiesCache()
   1415 {
   1416     m_matchedPropertiesCache.clear();
   1417 }
   1418 
   1419 void StyleResolver::notifyResizeForViewportUnits()
   1420 {
   1421     collectViewportRules();
   1422     m_matchedPropertiesCache.clearViewportDependent();
   1423 }
   1424 
   1425 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult)
   1426 {
   1427     const Element* element = state.element();
   1428     ASSERT(element);
   1429 
   1430     INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply);
   1431 
   1432     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
   1433     bool applyInheritedOnly = false;
   1434     const CachedMatchedProperties* cachedMatchedProperties = 0;
   1435 
   1436     if (cacheHash && (cachedMatchedProperties = m_matchedPropertiesCache.find(cacheHash, state, matchResult))
   1437         && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
   1438         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit);
   1439         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
   1440         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
   1441         // element context. This is fast and saves memory by reusing the style data structures.
   1442         state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get());
   1443         if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element)
   1444             && (!state.distributedToInsertionPoint() || state.style()->userModify() == READ_ONLY)) {
   1445             INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit);
   1446 
   1447             EInsideLink linkStatus = state.style()->insideLink();
   1448             // If the cache item parent style has identical inherited properties to the current parent style then the
   1449             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
   1450             state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get());
   1451 
   1452             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
   1453             state.style()->setInsideLink(linkStatus);
   1454             return;
   1455         }
   1456         applyInheritedOnly = true;
   1457     }
   1458 
   1459     // Apply animation properties in order to apply animation results and trigger transitions below.
   1460     applyMatchedProperties<AnimationProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1461     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1462     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1463     applyMatchedProperties<AnimationProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1464 
   1465     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
   1466     // high-priority properties first, i.e., those properties that other properties depend on.
   1467     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
   1468     // and (4) normal important.
   1469     state.setLineHeightValue(0);
   1470     applyMatchedProperties<HighPriorityProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1471     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1472     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1473     applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1474 
   1475     if (UNLIKELY(isSVGForeignObjectElement(element))) {
   1476         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should not be scaled again.
   1477         //
   1478         // FIXME: The following hijacks the zoom property for foreignObject so that children of foreignObject get the
   1479         // correct font-size in case of zooming. 'zoom' is part of HighPriorityProperties, along with other font-related
   1480         // properties used as input to the FontBuilder, so resetting it here may cause the FontBuilder to recompute the
   1481         // font used as inheritable font for foreignObject content. If we want to support zoom on foreignObject we'll
   1482         // need to find another way of handling the SVG zoom model.
   1483         state.setEffectiveZoom(RenderStyle::initialZoom());
   1484     }
   1485 
   1486     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
   1487         state.fontBuilder().setFontDirty(true);
   1488         applyInheritedOnly = false;
   1489     }
   1490 
   1491     // If our font got dirtied, go ahead and update it now.
   1492     updateFont(state);
   1493 
   1494     // Line-height is set when we are sure we decided on the font-size.
   1495     if (state.lineHeightValue())
   1496         StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
   1497 
   1498     // Many properties depend on the font. If it changes we just apply all properties.
   1499     if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription())
   1500         applyInheritedOnly = false;
   1501 
   1502     // Now do the normal priority UA properties.
   1503     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1504 
   1505     // Cache the UA properties to pass them to RenderTheme in adjustRenderStyle.
   1506     state.cacheUserAgentBorderAndBackground();
   1507 
   1508     // Now do the author and user normal priority properties and all the !important properties.
   1509     applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
   1510     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
   1511     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
   1512     applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
   1513 
   1514     loadPendingResources(state);
   1515 
   1516     if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
   1517         INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded);
   1518         m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
   1519     }
   1520 
   1521     ASSERT(!state.fontBuilder().fontDirty());
   1522 }
   1523 
   1524 CSSPropertyValue::CSSPropertyValue(CSSPropertyID id, const StylePropertySet& propertySet)
   1525     : property(id), value(propertySet.getPropertyCSSValue(id).get())
   1526 { }
   1527 
   1528 void StyleResolver::enableStats(StatsReportType reportType)
   1529 {
   1530     if (m_styleResolverStats)
   1531         return;
   1532     m_styleResolverStats = StyleResolverStats::create();
   1533     m_styleResolverStatsTotals = StyleResolverStats::create();
   1534     if (reportType == ReportSlowStats) {
   1535         m_styleResolverStats->printMissedCandidateCount = true;
   1536         m_styleResolverStatsTotals->printMissedCandidateCount = true;
   1537     }
   1538 }
   1539 
   1540 void StyleResolver::disableStats()
   1541 {
   1542     m_styleResolverStatsSequence = 0;
   1543     m_styleResolverStats.clear();
   1544     m_styleResolverStatsTotals.clear();
   1545 }
   1546 
   1547 void StyleResolver::printStats()
   1548 {
   1549     if (!m_styleResolverStats)
   1550         return;
   1551     fprintf(stderr, "=== Style Resolver Stats (resolve #%u) (%s) ===\n", ++m_styleResolverStatsSequence, m_document.url().string().utf8().data());
   1552     fprintf(stderr, "%s\n", m_styleResolverStats->report().utf8().data());
   1553     fprintf(stderr, "== Totals ==\n");
   1554     fprintf(stderr, "%s\n", m_styleResolverStatsTotals->report().utf8().data());
   1555 }
   1556 
   1557 void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle* style)
   1558 {
   1559     StyleResolverState state(document(), document().documentElement(), style);
   1560     state.setStyle(style);
   1561 
   1562     state.fontBuilder().initForStyleResolve(document(), style);
   1563 
   1564     for (size_t i = 0; i < count; ++i) {
   1565         if (properties[i].value) {
   1566             // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
   1567             // which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122).
   1568             // The updateFont() call below updates the fontMetrics and ensure the proper setting of font-size and line-height.
   1569             switch (properties[i].property) {
   1570             case CSSPropertyFontSize:
   1571             case CSSPropertyLineHeight:
   1572                 updateFont(state);
   1573                 break;
   1574             default:
   1575                 break;
   1576             }
   1577             StyleBuilder::applyProperty(properties[i].property, state, properties[i].value);
   1578         }
   1579     }
   1580 }
   1581 
   1582 void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list)
   1583 {
   1584     for (size_t i = 0; i < list.size(); ++i)
   1585         m_viewportDependentMediaQueryResults.append(list[i]);
   1586 }
   1587 
   1588 bool StyleResolver::mediaQueryAffectedByViewportChange() const
   1589 {
   1590     for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
   1591         if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) != m_viewportDependentMediaQueryResults[i]->result())
   1592             return true;
   1593     }
   1594     return false;
   1595 }
   1596 
   1597 void StyleResolver::trace(Visitor* visitor)
   1598 {
   1599     visitor->trace(m_keyframesRuleMap);
   1600     visitor->trace(m_viewportDependentMediaQueryResults);
   1601     visitor->trace(m_viewportStyleResolver);
   1602     visitor->trace(m_features);
   1603     visitor->trace(m_siblingRuleSet);
   1604     visitor->trace(m_uncommonAttributeRuleSet);
   1605     visitor->trace(m_watchedSelectorsRules);
   1606     visitor->trace(m_treeBoundaryCrossingRules);
   1607     visitor->trace(m_pendingStyleSheets);
   1608 }
   1609 
   1610 } // namespace WebCore
   1611