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