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