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