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