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.
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.
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.
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.
30 #include "core/css/resolver/StyleResolver.h"
32 #include "core/CSSPropertyNames.h"
33 #include "core/HTMLNames.h"
34 #include "core/MediaTypeNames.h"
35 #include "core/StylePropertyShorthand.h"
36 #include "core/animation/ActiveAnimations.h"
37 #include "core/animation/Animation.h"
38 #include "core/animation/AnimationTimeline.h"
39 #include "core/animation/StyleInterpolation.h"
40 #include "core/animation/animatable/AnimatableValue.h"
41 #include "core/animation/css/CSSAnimatableValueFactory.h"
42 #include "core/animation/css/CSSAnimations.h"
43 #include "core/css/CSSCalculationValue.h"
44 #include "core/css/CSSDefaultStyleSheets.h"
45 #include "core/css/CSSFontSelector.h"
46 #include "core/css/CSSKeyframeRule.h"
47 #include "core/css/CSSKeyframesRule.h"
48 #include "core/css/CSSReflectValue.h"
49 #include "core/css/CSSRuleList.h"
50 #include "core/css/CSSSelector.h"
51 #include "core/css/CSSStyleRule.h"
52 #include "core/css/CSSValueList.h"
53 #include "core/css/CSSValuePool.h"
54 #include "core/css/ElementRuleCollector.h"
55 #include "core/css/FontFace.h"
56 #include "core/css/MediaQueryEvaluator.h"
57 #include "core/css/PageRuleCollector.h"
58 #include "core/css/StylePropertySet.h"
59 #include "core/css/StyleRuleImport.h"
60 #include "core/css/StyleSheetContents.h"
61 #include "core/css/resolver/AnimatedStyleBuilder.h"
62 #include "core/css/resolver/MatchResult.h"
63 #include "core/css/resolver/MediaQueryResult.h"
64 #include "core/css/resolver/SharedStyleFinder.h"
65 #include "core/css/resolver/StyleAdjuster.h"
66 #include "core/css/resolver/StyleResolverParentScope.h"
67 #include "core/css/resolver/StyleResolverState.h"
68 #include "core/css/resolver/StyleResolverStats.h"
69 #include "core/css/resolver/ViewportStyleResolver.h"
70 #include "core/dom/CSSSelectorWatch.h"
71 #include "core/dom/NodeRenderStyle.h"
72 #include "core/dom/StyleEngine.h"
73 #include "core/dom/Text.h"
74 #include "core/dom/shadow/ElementShadow.h"
75 #include "core/dom/shadow/ShadowRoot.h"
76 #include "core/frame/FrameView.h"
77 #include "core/frame/LocalFrame.h"
78 #include "core/html/HTMLIFrameElement.h"
79 #include "core/inspector/InspectorInstrumentation.h"
80 #include "core/rendering/RenderView.h"
81 #include "core/rendering/style/KeyframeList.h"
82 #include "core/svg/SVGDocumentExtensions.h"
83 #include "core/svg/SVGElement.h"
84 #include "core/svg/SVGFontFaceElement.h"
85 #include "platform/RuntimeEnabledFeatures.h"
86 #include "wtf/StdLibExtras.h"
90 using namespace blink;
92 void setAnimationUpdateIfNeeded(StyleResolverState& state, Element& element)
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());
104 using namespace HTMLNames;
106 RenderStyle* StyleResolver::s_styleNotYetAvailable;
108 static StylePropertySet* leftToRightDeclaration()
110 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(MutableStylePropertySet, leftToRightDecl, (MutableStylePropertySet::create()));
111 if (leftToRightDecl->isEmpty())
112 leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
113 return leftToRightDecl;
116 static StylePropertySet* rightToLeftDeclaration()
118 DEFINE_STATIC_REF_WILL_BE_PERSISTENT(MutableStylePropertySet, rightToLeftDecl, (MutableStylePropertySet::create()));
119 if (rightToLeftDecl->isEmpty())
120 rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
121 return rightToLeftDecl;
124 static void addFontFaceRule(Document* document, CSSFontSelector* cssFontSelector, const StyleRuleFontFace* fontFaceRule)
126 RefPtrWillBeRawPtr<FontFace> fontFace = FontFace::create(document, fontFaceRule);
128 cssFontSelector->fontFaceCache()->add(cssFontSelector, fontFaceRule, fontFace);
131 StyleResolver::StyleResolver(Document& document)
132 : m_document(document)
133 , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
134 , m_needCollectFeatures(false)
135 , m_printMediaType(false)
136 , m_styleResourceLoader(document.fetcher())
137 , m_styleSharingDepth(0)
138 , m_styleResolverStatsSequence(0)
141 FrameView* view = document.view();
143 m_medium = adoptPtr(new MediaQueryEvaluator(&view->frame()));
144 m_printMediaType = equalIgnoringCase(view->mediaType(), MediaTypeNames::print);
146 m_medium = adoptPtr(new MediaQueryEvaluator("all"));
149 initWatchedSelectorRules(CSSSelectorWatch::from(document).watchedCallbackSelectors());
151 #if ENABLE(SVG_FONTS)
152 if (document.svgExtensions()) {
153 const WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >& svgFontFaceElements = document.svgExtensions()->svgFontFaceElements();
154 WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator end = svgFontFaceElements.end();
155 for (WillBeHeapHashSet<RawPtrWillBeMember<SVGFontFaceElement> >::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
156 addFontFaceRule(&document, document.styleEngine()->fontSelector(), (*it)->fontFaceRule());
161 void StyleResolver::initWatchedSelectorRules(const WillBeHeapVector<RefPtrWillBeMember<StyleRule> >& watchedSelectors)
163 if (!watchedSelectors.size())
165 m_watchedSelectorsRules = RuleSet::create();
166 for (unsigned i = 0; i < watchedSelectors.size(); ++i)
167 m_watchedSelectorsRules->addStyleRule(watchedSelectors[i].get(), RuleHasNoSpecialState);
170 void StyleResolver::lazyAppendAuthorStyleSheets(unsigned firstNew, const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
172 unsigned size = styleSheets.size();
173 for (unsigned i = firstNew; i < size; ++i)
174 m_pendingStyleSheets.add(styleSheets[i].get());
177 void StyleResolver::removePendingAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
179 for (unsigned i = 0; i < styleSheets.size(); ++i)
180 m_pendingStyleSheets.remove(styleSheets[i].get());
183 void StyleResolver::appendCSSStyleSheet(CSSStyleSheet* cssSheet)
186 ASSERT(!cssSheet->disabled());
187 if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), &m_viewportDependentMediaQueryResults))
190 TreeScope* treeScope = ScopedStyleResolver::treeScopeFor(document(), cssSheet);
194 ScopedStyleResolver& resolver = treeScope->ensureScopedStyleResolver();
195 document().styleEngine()->addScopedStyleResolver(&resolver);
196 resolver.addRulesFromSheet(cssSheet, *m_medium, this);
199 void StyleResolver::appendPendingAuthorStyleSheets()
201 for (WillBeHeapListHashSet<RawPtrWillBeMember<CSSStyleSheet>, 16>::iterator it = m_pendingStyleSheets.begin(); it != m_pendingStyleSheets.end(); ++it)
202 appendCSSStyleSheet(*it);
204 m_pendingStyleSheets.clear();
205 finishAppendAuthorStyleSheets();
208 void StyleResolver::appendAuthorStyleSheets(const WillBeHeapVector<RefPtrWillBeMember<CSSStyleSheet> >& styleSheets)
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());
217 void StyleResolver::finishAppendAuthorStyleSheets()
221 if (document().renderView() && document().renderView()->style())
222 document().renderView()->style()->font().update(document().styleEngine()->fontSelector());
224 collectViewportRules();
226 document().styleEngine()->resetCSSFeatureFlags(m_features);
229 void StyleResolver::resetRuleFeatures()
231 // Need to recreate RuleFeatureSet.
233 m_siblingRuleSet.clear();
234 m_uncommonAttributeRuleSet.clear();
235 m_needCollectFeatures = true;
238 void StyleResolver::processScopedRules(const RuleSet& authorRules, CSSStyleSheet* parentStyleSheet, unsigned parentIndex, ContainerNode& scope)
240 const WillBeHeapVector<RawPtrWillBeMember<StyleRuleKeyframes> > keyframesRules = authorRules.keyframesRules();
241 ScopedStyleResolver* resolver = &scope.treeScope().ensureScopedStyleResolver();
242 document().styleEngine()->addScopedStyleResolver(resolver);
243 for (unsigned i = 0; i < keyframesRules.size(); ++i)
244 resolver->addKeyframeStyle(keyframesRules[i]);
246 m_treeBoundaryCrossingRules.addTreeBoundaryCrossingRules(authorRules, parentStyleSheet, parentIndex, scope);
248 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
249 if (scope.isDocumentNode()) {
250 const WillBeHeapVector<RawPtrWillBeMember<StyleRuleFontFace> > fontFaceRules = authorRules.fontFaceRules();
251 for (unsigned i = 0; i < fontFaceRules.size(); ++i)
252 addFontFaceRule(m_document, document().styleEngine()->fontSelector(), fontFaceRules[i]);
253 if (fontFaceRules.size())
254 invalidateMatchedPropertiesCache();
258 void StyleResolver::resetAuthorStyle(TreeScope& treeScope)
260 ScopedStyleResolver* resolver = treeScope.scopedStyleResolver();
264 m_treeBoundaryCrossingRules.reset(&treeScope.rootNode());
266 resolver->resetAuthorStyle();
268 if (treeScope.rootNode().isDocumentNode())
271 // resolver is going to be freed below.
272 document().styleEngine()->removeScopedStyleResolver(resolver);
273 treeScope.clearScopedStyleResolver();
276 static PassOwnPtrWillBeRawPtr<RuleSet> makeRuleSet(const WillBeHeapVector<RuleFeature>& rules)
278 size_t size = rules.size();
281 OwnPtrWillBeRawPtr<RuleSet> ruleSet = RuleSet::create();
282 for (size_t i = 0; i < size; ++i)
283 ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
284 return ruleSet.release();
287 void StyleResolver::collectFeatures()
290 // Collect all ids and rules using sibling selectors (:first-child and similar)
291 // in the current set of stylesheets. Style sharing code uses this information to reject
292 // sharing candidates.
293 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
294 if (defaultStyleSheets.defaultStyle())
295 m_features.add(defaultStyleSheets.defaultStyle()->features());
297 if (document().isViewSource())
298 m_features.add(defaultStyleSheets.defaultViewSourceStyle()->features());
300 if (document().isTransitionDocument())
301 m_features.add(defaultStyleSheets.defaultTransitionStyle()->features());
303 if (m_watchedSelectorsRules)
304 m_features.add(m_watchedSelectorsRules->features());
306 m_treeBoundaryCrossingRules.collectFeaturesTo(m_features);
308 document().styleEngine()->collectScopedStyleFeaturesTo(m_features);
310 m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
311 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
312 m_needCollectFeatures = false;
315 bool StyleResolver::hasRulesForId(const AtomicString& id) const
317 return m_features.hasSelectorForId(id);
320 void StyleResolver::addToStyleSharingList(Element& element)
322 // Never add elements to the style sharing list if we're not in a recalcStyle,
323 // otherwise we could leave stale pointers in there.
324 if (!document().inStyleRecalc())
326 INCREMENT_STYLE_STATS_COUNTER(*this, sharedStyleCandidates);
327 StyleSharingList& list = styleSharingList();
328 if (list.size() >= styleSharingListSize)
330 list.prepend(&element);
333 StyleSharingList& StyleResolver::styleSharingList()
335 m_styleSharingLists.resize(styleSharingMaxDepth);
337 // We never put things at depth 0 into the list since that's only the <html> element
338 // and it has no siblings or cousins to share with.
339 unsigned depth = std::max(std::min(m_styleSharingDepth, styleSharingMaxDepth), 1u) - 1u;
341 if (!m_styleSharingLists[depth])
342 m_styleSharingLists[depth] = adoptPtrWillBeNoop(new StyleSharingList);
343 return *m_styleSharingLists[depth];
346 void StyleResolver::clearStyleSharingList()
348 m_styleSharingLists.resize(0);
351 void StyleResolver::pushParentElement(Element& parent)
353 const ContainerNode* parentsParent = parent.parentOrShadowHostElement();
355 // We are not always invoked consistently. For example, script execution can cause us to enter
356 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
357 // Reset the stack in this case, or if we see a new root element.
358 // Otherwise just push the new parent.
359 if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
360 m_selectorFilter.setupParentStack(parent);
362 m_selectorFilter.pushParent(parent);
365 void StyleResolver::popParentElement(Element& parent)
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();
373 StyleResolver::~StyleResolver()
377 void StyleResolver::matchAuthorRulesForShadowHost(Element* element, ElementRuleCollector& collector, bool includeEmptyRules, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolversInShadowTree)
379 collector.clearMatchedRules();
380 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
382 CascadeScope cascadeScope = 0;
383 CascadeOrder cascadeOrder = 0;
385 for (int j = resolversInShadowTree.size() - 1; j >= 0; --j)
386 resolversInShadowTree.at(j)->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope, cascadeOrder++);
388 if (resolvers.isEmpty() || resolvers.first()->treeScope() != element->treeScope())
390 cascadeOrder += resolvers.size();
391 for (unsigned i = 0; i < resolvers.size(); ++i)
392 resolvers.at(i)->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, --cascadeOrder);
394 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
395 collector.sortAndTransferMatchedRules();
398 void StyleResolver::matchAuthorRules(Element* element, ElementRuleCollector& collector, bool includeEmptyRules)
400 collector.clearMatchedRules();
401 collector.matchedResult().ranges.lastAuthorRule = collector.matchedResult().matchedProperties.size() - 1;
403 if (document().styleEngine()->hasOnlyScopedResolverForDocument()) {
404 document().scopedStyleResolver()->collectMatchingAuthorRules(collector, includeEmptyRules, ignoreCascadeScope);
405 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
406 collector.sortAndTransferMatchedRules();
410 WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolvers;
411 resolveScopedStyles(element, resolvers);
413 WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8> resolversInShadowTree;
414 collectScopedResolversForHostedShadowTrees(element, resolversInShadowTree);
415 if (!resolversInShadowTree.isEmpty()) {
416 matchAuthorRulesForShadowHost(element, collector, includeEmptyRules, resolvers, resolversInShadowTree);
420 if (resolvers.isEmpty())
423 CascadeScope cascadeScope = 0;
424 CascadeOrder cascadeOrder = resolvers.size();
425 for (unsigned i = 0; i < resolvers.size(); ++i, --cascadeOrder) {
426 ScopedStyleResolver* resolver = resolvers.at(i);
427 // FIXME: Need to clarify how to treat style scoped.
428 resolver->collectMatchingAuthorRules(collector, includeEmptyRules, cascadeScope++, resolver->treeScope() == element->treeScope() && resolver->treeScope().rootNode().isShadowRoot() ? 0 : cascadeOrder);
431 m_treeBoundaryCrossingRules.collectTreeBoundaryCrossingRules(element, collector, includeEmptyRules);
432 collector.sortAndTransferMatchedRules();
435 void StyleResolver::matchUARules(ElementRuleCollector& collector)
437 collector.setMatchingUARules(true);
439 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
440 RuleSet* userAgentStyleSheet = m_printMediaType ? defaultStyleSheets.defaultPrintStyle() : defaultStyleSheets.defaultStyle();
441 matchUARules(collector, userAgentStyleSheet);
443 // In quirks mode, we match rules from the quirks user agent sheet.
444 if (document().inQuirksMode())
445 matchUARules(collector, defaultStyleSheets.defaultQuirksStyle());
447 // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
448 if (document().isViewSource())
449 matchUARules(collector, defaultStyleSheets.defaultViewSourceStyle());
451 if (document().isTransitionDocument())
452 matchUARules(collector, defaultStyleSheets.defaultTransitionStyle());
454 collector.setMatchingUARules(false);
457 void StyleResolver::matchUARules(ElementRuleCollector& collector, RuleSet* rules)
459 collector.clearMatchedRules();
460 collector.matchedResult().ranges.lastUARule = collector.matchedResult().matchedProperties.size() - 1;
462 RuleRange ruleRange = collector.matchedResult().ranges.UARuleRange();
463 collector.collectMatchingRules(MatchRequest(rules), ruleRange);
465 collector.sortAndTransferMatchedRules();
468 void StyleResolver::matchAllRules(StyleResolverState& state, ElementRuleCollector& collector, bool includeSMILProperties)
470 matchUARules(collector);
472 // Now check author rules, beginning first with presentational attributes mapped from HTML.
473 if (state.element()->isStyledElement()) {
474 collector.addElementStyleProperties(state.element()->presentationAttributeStyle());
476 // Now we check additional mapped declarations.
477 // Tables and table cells share an additional mapped rule that must be applied
478 // after all attributes, since their mapped style depends on the values of multiple attributes.
479 collector.addElementStyleProperties(state.element()->additionalPresentationAttributeStyle());
481 if (state.element()->isHTMLElement()) {
483 TextDirection textDirection = toHTMLElement(state.element())->directionalityIfhasDirAutoAttribute(isAuto);
485 collector.matchedResult().addMatchedProperties(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
489 matchAuthorRules(state.element(), collector, false);
491 if (state.element()->isStyledElement()) {
492 if (state.element()->inlineStyle()) {
493 // Inline style is immutable as long as there is no CSSOM wrapper.
494 bool isInlineStyleCacheable = !state.element()->inlineStyle()->isMutable();
495 collector.addElementStyleProperties(state.element()->inlineStyle(), isInlineStyleCacheable);
498 // Now check SMIL animation override style.
499 if (includeSMILProperties && state.element()->isSVGElement())
500 collector.addElementStyleProperties(toSVGElement(state.element())->animatedSMILStyleProperties(), false /* isCacheable */);
504 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document& document)
506 const LocalFrame* frame = document.frame();
508 RefPtr<RenderStyle> documentStyle = RenderStyle::create();
509 documentStyle->setDisplay(BLOCK);
510 documentStyle->setRTLOrdering(document.visuallyOrdered() ? VisualOrder : LogicalOrder);
511 documentStyle->setZoom(frame && !document.printing() ? frame->pageZoomFactor() : 1);
512 documentStyle->setLocale(document.contentLanguage());
513 documentStyle->setZIndex(0);
514 documentStyle->setUserModify(document.inDesignMode() ? READ_WRITE : READ_ONLY);
516 document.setupFontBuilder(documentStyle.get());
518 return documentStyle.release();
521 static inline void resetDirectionAndWritingModeOnDocument(Document& document)
523 document.setDirectionSetOnDocumentElement(false);
524 document.setWritingModeSetOnDocumentElement(false);
527 static void addContentAttrValuesToFeatures(const Vector<AtomicString>& contentAttrValues, RuleFeatureSet& features)
529 for (size_t i = 0; i < contentAttrValues.size(); ++i)
530 features.addContentAttr(contentAttrValues[i]);
533 void StyleResolver::adjustRenderStyle(StyleResolverState& state, Element* element)
535 StyleAdjuster adjuster(document().inQuirksMode());
536 adjuster.adjustRenderStyle(state.style(), state.parentStyle(), element, state.cachedUAStyle());
539 // Start loading resources referenced by this style.
540 void StyleResolver::loadPendingResources(StyleResolverState& state)
542 m_styleResourceLoader.loadPendingResources(state.style(), state.elementStyleResources());
543 document().styleEngine()->fontSelector()->fontLoader()->loadPendingFonts();
546 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent, StyleSharingBehavior sharingBehavior,
547 RuleMatchingBehavior matchingBehavior)
549 ASSERT(document().frame());
550 ASSERT(document().settings());
551 ASSERT(!hasPendingAuthorStyleSheets());
552 ASSERT(!m_needCollectFeatures);
554 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
555 // will vanish if a style recalc happens during loading.
556 if (sharingBehavior == AllowStyleSharing && !document().isRenderingReady() && !element->renderer()) {
557 if (!s_styleNotYetAvailable) {
558 s_styleNotYetAvailable = RenderStyle::create().leakRef();
559 s_styleNotYetAvailable->setDisplay(NONE);
560 s_styleNotYetAvailable->font().update(document().styleEngine()->fontSelector());
563 document().setHasNodesWithPlaceholderStyle();
564 return s_styleNotYetAvailable;
569 StyleResolverParentScope::ensureParentStackIsPushed();
571 if (element == document().documentElement())
572 resetDirectionAndWritingModeOnDocument(document());
573 StyleResolverState state(document(), element, defaultParent);
575 if (sharingBehavior == AllowStyleSharing && state.parentStyle()) {
576 SharedStyleFinder styleFinder(state.elementContext(), m_features, m_siblingRuleSet.get(), m_uncommonAttributeRuleSet.get(), *this);
577 if (RefPtr<RenderStyle> sharedStyle = styleFinder.findSharedStyle())
578 return sharedStyle.release();
581 if (state.parentStyle()) {
582 state.setStyle(RenderStyle::create());
583 state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
585 state.setStyle(defaultStyleForElement());
586 state.setParentStyle(RenderStyle::clone(state.style()));
588 // contenteditable attribute (implemented by -webkit-user-modify) should
589 // be propagated from shadow host to distributed node.
590 if (state.distributedToInsertionPoint()) {
591 if (Element* parent = element->parentElement()) {
592 if (RenderStyle* styleOfShadowHost = parent->renderStyle())
593 state.style()->setUserModify(styleOfShadowHost->userModify());
597 state.fontBuilder().initForStyleResolve(state.document(), state.style());
599 if (element->isLink()) {
600 state.style()->setIsLink(true);
601 EInsideLink linkState = state.elementLinkState();
602 if (linkState != NotInsideLink) {
603 bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
605 linkState = InsideVisitedLink;
607 state.style()->setInsideLink(linkState);
610 bool needsCollection = false;
611 CSSDefaultStyleSheets::instance().ensureDefaultStyleSheetsForElement(element, needsCollection);
616 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
618 matchAllRules(state, collector, matchingBehavior != MatchAllRulesExcludingSMIL);
620 applyMatchedProperties(state, collector.matchedResult());
621 applyCallbackSelectors(state);
623 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
626 // Cache our original display.
627 state.style()->setOriginalDisplay(state.style()->display());
629 adjustRenderStyle(state, element);
631 // FIXME: The CSSWG wants to specify that the effects of animations are applied before
632 // important rules, but this currently happens here as we require adjustment to have happened
633 // before deciding which properties to transition.
634 if (applyAnimatedProperties(state, element))
635 adjustRenderStyle(state, element);
637 if (isHTMLBodyElement(*element))
638 document().textLinkColors().setTextColor(state.style()->color());
640 setAnimationUpdateIfNeeded(state, *element);
642 if (state.style()->hasViewportUnits())
643 document().setHasViewportUnits();
645 // Now return the style.
646 return state.takeStyle();
649 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(Element& element, const RenderStyle& elementStyle, RenderStyle* parentStyle, const StyleKeyframe* keyframe, const AtomicString& animationName)
651 ASSERT(document().frame());
652 ASSERT(document().settings());
653 ASSERT(!hasPendingAuthorStyleSheets());
655 if (&element == document().documentElement())
656 resetDirectionAndWritingModeOnDocument(document());
657 StyleResolverState state(document(), &element, parentStyle);
660 result.addMatchedProperties(&keyframe->properties());
662 ASSERT(!state.style());
665 state.setStyle(RenderStyle::clone(&elementStyle));
666 state.setLineHeightValue(0);
668 state.fontBuilder().initForStyleResolve(state.document(), state.style());
670 // We don't need to bother with !important. Since there is only ever one
671 // decl, there's nothing to override. So just add the first properties.
672 // We also don't need to bother with animation properties since the only
673 // relevant one is animation-timing-function and we special-case that in
675 bool inheritedOnly = false;
676 applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
678 // If our font got dirtied, go ahead and update it now.
681 // Line-height is set when we are sure we decided on the font-size
682 if (state.lineHeightValue())
683 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
685 // Now do rest of the properties.
686 applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
688 loadPendingResources(state);
692 return state.takeStyle();
695 // This function is used by the WebAnimations JavaScript API method animate().
696 // FIXME: Remove this when animate() switches away from resolution-dependent parsing.
697 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(Element& element, CSSPropertyID property, CSSValue& value)
699 RefPtr<RenderStyle> style;
700 if (element.renderStyle())
701 style = RenderStyle::clone(element.renderStyle());
703 style = RenderStyle::create();
704 StyleResolverState state(element.document(), &element);
705 state.setStyle(style);
706 state.fontBuilder().initForStyleResolve(state.document(), state.style());
707 return createAnimatableValueSnapshot(state, property, value);
710 PassRefPtrWillBeRawPtr<AnimatableValue> StyleResolver::createAnimatableValueSnapshot(StyleResolverState& state, CSSPropertyID property, CSSValue& value)
712 StyleBuilder::applyProperty(property, state, &value);
713 return CSSAnimatableValueFactory::create(property, *state.style());
716 PassRefPtrWillBeRawPtr<PseudoElement> StyleResolver::createPseudoElementIfNeeded(Element& parent, PseudoId pseudoId)
718 RenderObject* parentRenderer = parent.renderer();
722 if (pseudoId < FIRST_INTERNAL_PSEUDOID && !parentRenderer->style()->hasPseudoStyle(pseudoId))
725 if (pseudoId == BACKDROP && !parent.isInTopLayer())
728 if (!parentRenderer->canHaveGeneratedChildren())
731 RenderStyle* parentStyle = parentRenderer->style();
732 if (RenderStyle* cachedStyle = parentStyle->getCachedPseudoStyle(pseudoId)) {
733 if (!pseudoElementRendererIsNeeded(cachedStyle))
735 return PseudoElement::create(&parent, pseudoId);
738 StyleResolverState state(document(), &parent, parentStyle);
739 if (!pseudoStyleForElementInternal(parent, pseudoId, parentStyle, state))
741 RefPtr<RenderStyle> style = state.takeStyle();
743 parentStyle->addCachedPseudoStyle(style);
745 if (!pseudoElementRendererIsNeeded(style.get()))
748 RefPtrWillBeRawPtr<PseudoElement> pseudo = PseudoElement::create(&parent, pseudoId);
750 setAnimationUpdateIfNeeded(state, *pseudo);
751 if (ActiveAnimations* activeAnimations = pseudo->activeAnimations())
752 activeAnimations->cssAnimations().maybeApplyPendingUpdate(pseudo.get());
753 return pseudo.release();
756 bool StyleResolver::pseudoStyleForElementInternal(Element& element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, StyleResolverState& state)
758 ASSERT(document().frame());
759 ASSERT(document().settings());
760 ASSERT(pseudoStyleRequest.pseudoId != FIRST_LINE_INHERITED);
762 StyleResolverParentScope::ensureParentStackIsPushed();
764 if (pseudoStyleRequest.allowsInheritance(state.parentStyle())) {
765 state.setStyle(RenderStyle::create());
766 state.style()->inheritFrom(state.parentStyle());
768 state.setStyle(defaultStyleForElement());
769 state.setParentStyle(RenderStyle::clone(state.style()));
772 state.style()->setStyleType(pseudoStyleRequest.pseudoId);
773 state.fontBuilder().initForStyleResolve(state.document(), state.style());
775 // Since we don't use pseudo-elements in any of our quirk/print
776 // user agent rules, don't waste time walking those rules.
779 // Check UA, user and author rules.
780 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
781 collector.setPseudoStyleRequest(pseudoStyleRequest);
783 matchUARules(collector);
784 matchAuthorRules(state.element(), collector, false);
786 if (collector.matchedResult().matchedProperties.isEmpty())
789 applyMatchedProperties(state, collector.matchedResult());
790 applyCallbackSelectors(state);
792 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
795 // Cache our original display.
796 state.style()->setOriginalDisplay(state.style()->display());
798 // FIXME: Passing 0 as the Element* introduces a lot of complexity
799 // in the adjustRenderStyle code.
800 adjustRenderStyle(state, 0);
802 // FIXME: The CSSWG wants to specify that the effects of animations are applied before
803 // important rules, but this currently happens here as we require adjustment to have happened
804 // before deciding which properties to transition.
805 if (applyAnimatedProperties(state, element.pseudoElement(pseudoStyleRequest.pseudoId)))
806 adjustRenderStyle(state, 0);
810 if (state.style()->hasViewportUnits())
811 document().setHasViewportUnits();
816 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
822 StyleResolverState state(document(), element, parentStyle);
823 if (!pseudoStyleForElementInternal(*element, pseudoStyleRequest, parentStyle, state)) {
824 if (pseudoStyleRequest.type == PseudoStyleRequest::ForRenderer)
826 return state.takeStyle();
829 if (PseudoElement* pseudoElement = element->pseudoElement(pseudoStyleRequest.pseudoId))
830 setAnimationUpdateIfNeeded(state, *pseudoElement);
832 // Now return the style.
833 return state.takeStyle();
836 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
838 ASSERT(!hasPendingAuthorStyleSheets());
839 resetDirectionAndWritingModeOnDocument(document());
840 StyleResolverState state(document(), document().documentElement()); // m_rootElementStyle will be set to the document style.
842 state.setStyle(RenderStyle::create());
843 const RenderStyle* rootElementStyle = state.rootElementStyle() ? state.rootElementStyle() : document().renderStyle();
844 ASSERT(rootElementStyle);
845 state.style()->inheritFrom(rootElementStyle);
847 state.fontBuilder().initForStyleResolve(state.document(), state.style());
849 PageRuleCollector collector(rootElementStyle, pageIndex);
851 collector.matchPageRules(CSSDefaultStyleSheets::instance().defaultPrintStyle());
853 if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver())
854 scopedResolver->matchPageRules(collector);
856 state.setLineHeightValue(0);
857 bool inheritedOnly = false;
859 MatchResult& result = collector.matchedResult();
860 applyMatchedProperties<HighPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
862 // If our font got dirtied, go ahead and update it now.
865 // Line-height is set when we are sure we decided on the font-size.
866 if (state.lineHeightValue())
867 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
869 applyMatchedProperties<LowPriorityProperties>(state, result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
871 addContentAttrValuesToFeatures(state.contentAttrValues(), m_features);
873 loadPendingResources(state);
877 // Now return the style.
878 return state.takeStyle();
881 void StyleResolver::collectViewportRules()
883 CSSDefaultStyleSheets& defaultStyleSheets = CSSDefaultStyleSheets::instance();
884 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultStyle(), ViewportStyleResolver::UserAgentOrigin);
886 if (!InspectorInstrumentation::applyViewportStyleOverride(&document(), this))
887 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultViewportStyle(), ViewportStyleResolver::UserAgentOrigin);
889 if (document().isMobileDocument())
890 viewportStyleResolver()->collectViewportRules(defaultStyleSheets.defaultXHTMLMobileProfileStyle(), ViewportStyleResolver::UserAgentOrigin);
892 if (ScopedStyleResolver* scopedResolver = document().scopedStyleResolver())
893 scopedResolver->collectViewportRulesTo(this);
895 viewportStyleResolver()->resolve();
898 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
900 StyleResolverState state(document(), 0);
901 state.setStyle(RenderStyle::create());
902 state.fontBuilder().initForStyleResolve(document(), state.style());
903 state.style()->setLineHeight(RenderStyle::initialLineHeight());
904 state.setLineHeightValue(0);
905 state.fontBuilder().setInitial(state.style()->effectiveZoom());
906 state.style()->font().update(document().styleEngine()->fontSelector());
907 return state.takeStyle();
910 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
914 Node* parentNode = NodeRenderingTraversal::parent(textNode);
915 if (!parentNode || !parentNode->renderStyle())
916 return defaultStyleForElement();
917 return parentNode->renderStyle();
920 void StyleResolver::updateFont(StyleResolverState& state)
922 state.fontBuilder().createFont(document().styleEngine()->fontSelector(), state.parentStyle(), state.style());
925 PassRefPtrWillBeRawPtr<StyleRuleList> StyleResolver::styleRulesForElement(Element* element, unsigned rulesToInclude)
928 StyleResolverState state(document(), element);
929 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
930 collector.setMode(SelectorChecker::CollectingStyleRules);
931 collectPseudoRulesForElement(element, collector, NOPSEUDO, rulesToInclude);
932 return collector.matchedStyleRuleList();
935 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::pseudoCSSRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
938 StyleResolverState state(document(), element);
939 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
940 collector.setMode(SelectorChecker::CollectingCSSRules);
941 collectPseudoRulesForElement(element, collector, pseudoId, rulesToInclude);
942 return collector.matchedCSSRuleList();
945 PassRefPtrWillBeRawPtr<CSSRuleList> StyleResolver::cssRulesForElement(Element* element, unsigned rulesToInclude)
947 return pseudoCSSRulesForElement(element, NOPSEUDO, rulesToInclude);
950 void StyleResolver::collectPseudoRulesForElement(Element* element, ElementRuleCollector& collector, PseudoId pseudoId, unsigned rulesToInclude)
952 collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
954 if (rulesToInclude & UAAndUserCSSRules)
955 matchUARules(collector);
957 if (rulesToInclude & AuthorCSSRules) {
958 collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
959 matchAuthorRules(element, collector, rulesToInclude & EmptyCSSRules);
963 // -------------------------------------------------------------------------------------
964 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
966 bool StyleResolver::applyAnimatedProperties(StyleResolverState& state, const Element* animatingElement)
968 Element* element = state.element();
971 // The animating element may be this element, or its pseudo element. It is
972 // null when calculating the style for a potential pseudo element that has
973 // yet to be created.
974 ASSERT(animatingElement == element || !animatingElement || animatingElement->parentOrShadowHostElement() == element);
976 if (!(animatingElement && animatingElement->hasActiveAnimations())
977 && !state.style()->transitions() && !state.style()->animations())
980 state.setAnimationUpdate(CSSAnimations::calculateUpdate(animatingElement, *element, *state.style(), state.parentStyle(), this));
981 if (!state.animationUpdate())
984 const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForAnimations = state.animationUpdate()->activeInterpolationsForAnimations();
985 const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolationsForTransitions = state.animationUpdate()->activeInterpolationsForTransitions();
986 applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForAnimations);
987 applyAnimatedProperties<HighPriorityProperties>(state, activeInterpolationsForTransitions);
991 applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForAnimations);
992 applyAnimatedProperties<LowPriorityProperties>(state, activeInterpolationsForTransitions);
994 // Start loading resources used by animations.
995 loadPendingResources(state);
997 ASSERT(!state.fontBuilder().fontDirty());
1002 static inline ScopedStyleResolver* scopedResolverFor(const Element* element)
1004 for (TreeScope* treeScope = &element->treeScope(); treeScope; treeScope = treeScope->parentTreeScope()) {
1005 if (ScopedStyleResolver* scopedStyleResolver = treeScope->scopedStyleResolver())
1006 return scopedStyleResolver;
1011 void StyleResolver::resolveScopedStyles(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers)
1013 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent())
1014 resolvers.append(scopedResolver);
1017 void StyleResolver::collectScopedResolversForHostedShadowTrees(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers)
1019 ElementShadow* shadow = element->shadow();
1023 // Adding scoped resolver for active shadow roots for shadow host styling.
1024 for (ShadowRoot* shadowRoot = shadow->youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) {
1025 if (shadowRoot->numberOfStyles() > 0) {
1026 if (ScopedStyleResolver* resolver = shadowRoot->scopedStyleResolver())
1027 resolvers.append(resolver);
1032 void StyleResolver::styleTreeResolveScopedKeyframesRules(const Element* element, WillBeHeapVector<RawPtrWillBeMember<ScopedStyleResolver>, 8>& resolvers)
1034 TreeScope& treeScope = element->treeScope();
1036 // Add resolvers for shadow roots hosted by the given element.
1037 collectScopedResolversForHostedShadowTrees(element, resolvers);
1039 // Add resolvers while walking up DOM tree from the given element.
1040 for (ScopedStyleResolver* scopedResolver = scopedResolverFor(element); scopedResolver; scopedResolver = scopedResolver->parent()) {
1041 if (scopedResolver->treeScope() == treeScope)
1042 resolvers.append(scopedResolver);
1046 template <StyleResolver::StyleApplicationPass pass>
1047 void StyleResolver::applyAnimatedProperties(StyleResolverState& state, const WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >& activeInterpolations)
1049 for (WillBeHeapHashMap<CSSPropertyID, RefPtrWillBeMember<Interpolation> >::const_iterator iter = activeInterpolations.begin(); iter != activeInterpolations.end(); ++iter) {
1050 CSSPropertyID property = iter->key;
1051 if (!isPropertyForPass<pass>(property))
1053 const StyleInterpolation* interpolation = toStyleInterpolation(iter->value.get());
1054 interpolation->apply(state);
1058 static inline bool isValidCueStyleProperty(CSSPropertyID id)
1061 case CSSPropertyBackground:
1062 case CSSPropertyBackgroundAttachment:
1063 case CSSPropertyBackgroundClip:
1064 case CSSPropertyBackgroundColor:
1065 case CSSPropertyBackgroundImage:
1066 case CSSPropertyBackgroundOrigin:
1067 case CSSPropertyBackgroundPosition:
1068 case CSSPropertyBackgroundPositionX:
1069 case CSSPropertyBackgroundPositionY:
1070 case CSSPropertyBackgroundRepeat:
1071 case CSSPropertyBackgroundRepeatX:
1072 case CSSPropertyBackgroundRepeatY:
1073 case CSSPropertyBackgroundSize:
1074 case CSSPropertyColor:
1075 case CSSPropertyFont:
1076 case CSSPropertyFontFamily:
1077 case CSSPropertyFontSize:
1078 case CSSPropertyFontStretch:
1079 case CSSPropertyFontStyle:
1080 case CSSPropertyFontVariant:
1081 case CSSPropertyFontWeight:
1082 case CSSPropertyLineHeight:
1083 case CSSPropertyOpacity:
1084 case CSSPropertyOutline:
1085 case CSSPropertyOutlineColor:
1086 case CSSPropertyOutlineOffset:
1087 case CSSPropertyOutlineStyle:
1088 case CSSPropertyOutlineWidth:
1089 case CSSPropertyVisibility:
1090 case CSSPropertyWhiteSpace:
1091 // FIXME: 'text-decoration' shorthand to be handled when available.
1092 // See https://chromiumcodereview.appspot.com/19516002 for details.
1093 case CSSPropertyTextDecoration:
1094 case CSSPropertyTextShadow:
1095 case CSSPropertyBorderStyle:
1097 case CSSPropertyTextDecorationLine:
1098 case CSSPropertyTextDecorationStyle:
1099 case CSSPropertyTextDecorationColor:
1100 return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
1107 static inline bool isValidFirstLetterStyleProperty(CSSPropertyID id)
1110 // Valid ::first-letter properties listed in spec:
1111 // http://www.w3.org/TR/css3-selectors/#application-in-css
1112 case CSSPropertyBackgroundAttachment:
1113 case CSSPropertyBackgroundBlendMode:
1114 case CSSPropertyBackgroundClip:
1115 case CSSPropertyBackgroundColor:
1116 case CSSPropertyBackgroundImage:
1117 case CSSPropertyBackgroundOrigin:
1118 case CSSPropertyBackgroundPosition:
1119 case CSSPropertyBackgroundPositionX:
1120 case CSSPropertyBackgroundPositionY:
1121 case CSSPropertyBackgroundRepeat:
1122 case CSSPropertyBackgroundRepeatX:
1123 case CSSPropertyBackgroundRepeatY:
1124 case CSSPropertyBackgroundSize:
1125 case CSSPropertyBorderBottomColor:
1126 case CSSPropertyBorderBottomLeftRadius:
1127 case CSSPropertyBorderBottomRightRadius:
1128 case CSSPropertyBorderBottomStyle:
1129 case CSSPropertyBorderBottomWidth:
1130 case CSSPropertyBorderImageOutset:
1131 case CSSPropertyBorderImageRepeat:
1132 case CSSPropertyBorderImageSlice:
1133 case CSSPropertyBorderImageSource:
1134 case CSSPropertyBorderImageWidth:
1135 case CSSPropertyBorderLeftColor:
1136 case CSSPropertyBorderLeftStyle:
1137 case CSSPropertyBorderLeftWidth:
1138 case CSSPropertyBorderRightColor:
1139 case CSSPropertyBorderRightStyle:
1140 case CSSPropertyBorderRightWidth:
1141 case CSSPropertyBorderTopColor:
1142 case CSSPropertyBorderTopLeftRadius:
1143 case CSSPropertyBorderTopRightRadius:
1144 case CSSPropertyBorderTopStyle:
1145 case CSSPropertyBorderTopWidth:
1146 case CSSPropertyColor:
1147 case CSSPropertyFloat:
1148 case CSSPropertyFont:
1149 case CSSPropertyFontFamily:
1150 case CSSPropertyFontKerning:
1151 case CSSPropertyFontSize:
1152 case CSSPropertyFontStretch:
1153 case CSSPropertyFontStyle:
1154 case CSSPropertyFontVariant:
1155 case CSSPropertyFontVariantLigatures:
1156 case CSSPropertyFontWeight:
1157 case CSSPropertyLetterSpacing:
1158 case CSSPropertyLineHeight:
1159 case CSSPropertyMarginBottom:
1160 case CSSPropertyMarginLeft:
1161 case CSSPropertyMarginRight:
1162 case CSSPropertyMarginTop:
1163 case CSSPropertyPaddingBottom:
1164 case CSSPropertyPaddingLeft:
1165 case CSSPropertyPaddingRight:
1166 case CSSPropertyPaddingTop:
1167 case CSSPropertyTextTransform:
1168 case CSSPropertyVerticalAlign:
1169 case CSSPropertyWebkitBackgroundClip:
1170 case CSSPropertyWebkitBackgroundComposite:
1171 case CSSPropertyWebkitBackgroundOrigin:
1172 case CSSPropertyWebkitBackgroundSize:
1173 case CSSPropertyWebkitBorderAfter:
1174 case CSSPropertyWebkitBorderAfterColor:
1175 case CSSPropertyWebkitBorderAfterStyle:
1176 case CSSPropertyWebkitBorderAfterWidth:
1177 case CSSPropertyWebkitBorderBefore:
1178 case CSSPropertyWebkitBorderBeforeColor:
1179 case CSSPropertyWebkitBorderBeforeStyle:
1180 case CSSPropertyWebkitBorderBeforeWidth:
1181 case CSSPropertyWebkitBorderEnd:
1182 case CSSPropertyWebkitBorderEndColor:
1183 case CSSPropertyWebkitBorderEndStyle:
1184 case CSSPropertyWebkitBorderEndWidth:
1185 case CSSPropertyWebkitBorderFit:
1186 case CSSPropertyWebkitBorderHorizontalSpacing:
1187 case CSSPropertyWebkitBorderImage:
1188 case CSSPropertyWebkitBorderRadius:
1189 case CSSPropertyWebkitBorderStart:
1190 case CSSPropertyWebkitBorderStartColor:
1191 case CSSPropertyWebkitBorderStartStyle:
1192 case CSSPropertyWebkitBorderStartWidth:
1193 case CSSPropertyWebkitBorderVerticalSpacing:
1194 case CSSPropertyWebkitFontSmoothing:
1195 case CSSPropertyWebkitMarginAfter:
1196 case CSSPropertyWebkitMarginAfterCollapse:
1197 case CSSPropertyWebkitMarginBefore:
1198 case CSSPropertyWebkitMarginBeforeCollapse:
1199 case CSSPropertyWebkitMarginBottomCollapse:
1200 case CSSPropertyWebkitMarginCollapse:
1201 case CSSPropertyWebkitMarginEnd:
1202 case CSSPropertyWebkitMarginStart:
1203 case CSSPropertyWebkitMarginTopCollapse:
1204 case CSSPropertyWordSpacing:
1206 case CSSPropertyTextDecorationColor:
1207 case CSSPropertyTextDecorationLine:
1208 case CSSPropertyTextDecorationStyle:
1209 return RuntimeEnabledFeatures::css3TextDecorationsEnabled();
1211 // text-shadow added in text decoration spec:
1212 // http://www.w3.org/TR/css-text-decor-3/#text-shadow-property
1213 case CSSPropertyTextShadow:
1214 // box-shadox added in CSS3 backgrounds spec:
1215 // http://www.w3.org/TR/css3-background/#placement
1216 case CSSPropertyBoxShadow:
1217 case CSSPropertyWebkitBoxShadow:
1218 // Properties that we currently support outside of spec.
1219 case CSSPropertyWebkitLineBoxContain:
1220 case CSSPropertyVisibility:
1228 // FIXME: Consider refactoring to create a new class which owns the following
1229 // first/last/range properties.
1230 // This method returns the first CSSPropertyId of high priority properties.
1231 // Other properties can depend on high priority properties. For example,
1232 // border-color property with currentColor value depends on color property.
1233 // All high priority properties are obtained by using
1234 // firstCSSPropertyId<HighPriorityProperties> and
1235 // lastCSSPropertyId<HighPriorityProperties>.
1236 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::HighPriorityProperties>()
1238 COMPILE_ASSERT(CSSPropertyColor == firstCSSProperty, CSS_color_is_first_high_priority_property);
1239 return CSSPropertyColor;
1242 // This method returns the last CSSPropertyId of high priority properties.
1243 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::HighPriorityProperties>()
1245 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyColor + 18, CSS_line_height_is_end_of_high_prioity_property_range);
1246 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyLineHeight - 1, CSS_zoom_is_before_line_height);
1247 return CSSPropertyLineHeight;
1250 // This method returns the first CSSPropertyId of remaining properties,
1251 // i.e. low priority properties. No properties depend on low priority
1252 // properties. So we don't need to resolve such properties quickly.
1253 // All low priority properties are obtained by using
1254 // firstCSSPropertyId<LowPriorityProperties> and
1255 // lastCSSPropertyId<LowPriorityProperties>.
1256 template<> CSSPropertyID StyleResolver::firstCSSPropertyId<StyleResolver::LowPriorityProperties>()
1258 COMPILE_ASSERT(CSSPropertyAlignContent == CSSPropertyLineHeight + 1, CSS_background_is_first_low_priority_property);
1259 return CSSPropertyAlignContent;
1262 // This method returns the last CSSPropertyId of low priority properties.
1263 template<> CSSPropertyID StyleResolver::lastCSSPropertyId<StyleResolver::LowPriorityProperties>()
1265 return static_cast<CSSPropertyID>(lastCSSProperty);
1268 template <StyleResolver::StyleApplicationPass pass>
1269 bool StyleResolver::isPropertyForPass(CSSPropertyID property)
1271 return firstCSSPropertyId<pass>() <= property && property <= lastCSSPropertyId<pass>();
1274 // This method expands the 'all' shorthand property to longhand properties
1275 // and applies the expanded longhand properties.
1276 template <StyleResolver::StyleApplicationPass pass>
1277 void StyleResolver::applyAllProperty(StyleResolverState& state, CSSValue* allValue)
1279 bool isUnsetValue = !allValue->isInitialValue() && !allValue->isInheritedValue();
1280 unsigned startCSSProperty = firstCSSPropertyId<pass>();
1281 unsigned endCSSProperty = lastCSSPropertyId<pass>();
1283 for (unsigned i = startCSSProperty; i <= endCSSProperty; ++i) {
1284 CSSPropertyID propertyId = static_cast<CSSPropertyID>(i);
1286 // StyleBuilder does not allow any expanded shorthands.
1287 if (isExpandedShorthandForAll(propertyId))
1290 // all shorthand spec says:
1291 // The all property is a shorthand that resets all CSS properties
1292 // except direction and unicode-bidi.
1293 // c.f. http://dev.w3.org/csswg/css-cascade/#all-shorthand
1294 // We skip applyProperty when a given property is unicode-bidi or
1296 if (!CSSProperty::isAffectedByAllProperty(propertyId))
1300 if (!isUnsetValue) {
1303 if (CSSPropertyMetadata::isInheritedProperty(propertyId))
1304 value = cssValuePool().createInheritedValue().get();
1306 value = cssValuePool().createExplicitInitialValue().get();
1308 StyleBuilder::applyProperty(propertyId, state, value);
1312 template <StyleResolver::StyleApplicationPass pass>
1313 void StyleResolver::applyProperties(StyleResolverState& state, const StylePropertySet* properties, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
1315 unsigned propertyCount = properties->propertyCount();
1316 for (unsigned i = 0; i < propertyCount; ++i) {
1317 StylePropertySet::PropertyReference current = properties->propertyAt(i);
1318 if (isImportant != current.isImportant())
1321 CSSPropertyID property = current.id();
1322 if (property == CSSPropertyAll) {
1323 applyAllProperty<pass>(state, current.value());
1327 if (inheritedOnly && !current.isInherited()) {
1328 // If the property value is explicitly inherited, we need to apply further non-inherited properties
1329 // as they might override the value inherited here. For this reason we don't allow declarations with
1330 // explicitly inherited properties to be cached.
1331 ASSERT(!current.value()->isInheritedValue());
1335 if (propertyWhitelistType == PropertyWhitelistCue && !isValidCueStyleProperty(property))
1337 if (propertyWhitelistType == PropertyWhitelistFirstLetter && !isValidFirstLetterStyleProperty(property))
1339 if (!isPropertyForPass<pass>(property))
1341 if (pass == HighPriorityProperties && property == CSSPropertyLineHeight)
1342 state.setLineHeightValue(current.value());
1344 StyleBuilder::applyProperty(current.id(), state, current.value());
1348 template <StyleResolver::StyleApplicationPass pass>
1349 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
1351 if (startIndex == -1)
1354 if (state.style()->insideLink() != NotInsideLink) {
1355 for (int i = startIndex; i <= endIndex; ++i) {
1356 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1357 unsigned linkMatchType = matchedProperties.m_types.linkMatchType;
1358 // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
1359 state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
1360 state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
1362 applyProperties<pass>(state, matchedProperties.properties.get(), isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.m_types.whitelistType));
1364 state.setApplyPropertyToRegularStyle(true);
1365 state.setApplyPropertyToVisitedLinkStyle(false);
1368 for (int i = startIndex; i <= endIndex; ++i) {
1369 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1370 applyProperties<pass>(state, matchedProperties.properties.get(), isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.m_types.whitelistType));
1374 static unsigned computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1376 return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1379 void StyleResolver::invalidateMatchedPropertiesCache()
1381 m_matchedPropertiesCache.clear();
1384 void StyleResolver::notifyResizeForViewportUnits()
1386 collectViewportRules();
1387 m_matchedPropertiesCache.clearViewportDependent();
1390 void StyleResolver::applyMatchedProperties(StyleResolverState& state, const MatchResult& matchResult)
1392 const Element* element = state.element();
1395 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyApply);
1397 unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
1398 bool applyInheritedOnly = false;
1399 const CachedMatchedProperties* cachedMatchedProperties = cacheHash ? m_matchedPropertiesCache.find(cacheHash, state, matchResult) : 0;
1401 if (cachedMatchedProperties && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
1402 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheHit);
1403 // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1404 // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
1405 // element context. This is fast and saves memory by reusing the style data structures.
1406 state.style()->copyNonInheritedFrom(cachedMatchedProperties->renderStyle.get());
1407 if (state.parentStyle()->inheritedDataShared(cachedMatchedProperties->parentRenderStyle.get()) && !isAtShadowBoundary(element)
1408 && (!state.distributedToInsertionPoint() || state.style()->userModify() == READ_ONLY)) {
1409 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheInheritedHit);
1411 EInsideLink linkStatus = state.style()->insideLink();
1412 // If the cache item parent style has identical inherited properties to the current parent style then the
1413 // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1414 state.style()->inheritFrom(cachedMatchedProperties->renderStyle.get());
1416 // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1417 state.style()->setInsideLink(linkStatus);
1420 applyInheritedOnly = true;
1423 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
1424 // high-priority properties first, i.e., those properties that other properties depend on.
1425 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1426 // and (4) normal important.
1427 state.setLineHeightValue(0);
1428 applyMatchedProperties<HighPriorityProperties>(state, matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1429 applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1430 applyMatchedProperties<HighPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1432 if (UNLIKELY(isSVGForeignObjectElement(element))) {
1433 // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should not be scaled again.
1435 // FIXME: The following hijacks the zoom property for foreignObject so that children of foreignObject get the
1436 // correct font-size in case of zooming. 'zoom' is part of HighPriorityProperties, along with other font-related
1437 // properties used as input to the FontBuilder, so resetting it here may cause the FontBuilder to recompute the
1438 // font used as inheritable font for foreignObject content. If we want to support zoom on foreignObject we'll
1439 // need to find another way of handling the SVG zoom model.
1440 state.setEffectiveZoom(RenderStyle::initialZoom());
1443 if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
1444 state.fontBuilder().setFontDirty(true);
1445 applyInheritedOnly = false;
1448 // If our font got dirtied, go ahead and update it now.
1451 // Line-height is set when we are sure we decided on the font-size.
1452 if (state.lineHeightValue())
1453 StyleBuilder::applyProperty(CSSPropertyLineHeight, state, state.lineHeightValue());
1455 // Many properties depend on the font. If it changes we just apply all properties.
1456 if (cachedMatchedProperties && cachedMatchedProperties->renderStyle->fontDescription() != state.style()->fontDescription())
1457 applyInheritedOnly = false;
1459 // Now do the normal priority UA properties.
1460 applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1462 // Cache the UA properties to pass them to RenderTheme in adjustRenderStyle.
1463 state.cacheUserAgentBorderAndBackground();
1465 // Now do the author and user normal priority properties and all the !important properties.
1466 applyMatchedProperties<LowPriorityProperties>(state, matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1467 applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1468 applyMatchedProperties<LowPriorityProperties>(state, matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1470 loadPendingResources(state);
1472 if (!cachedMatchedProperties && cacheHash && MatchedPropertiesCache::isCacheable(element, state.style(), state.parentStyle())) {
1473 INCREMENT_STYLE_STATS_COUNTER(*this, matchedPropertyCacheAdded);
1474 m_matchedPropertiesCache.add(state.style(), state.parentStyle(), cacheHash, matchResult);
1477 ASSERT(!state.fontBuilder().fontDirty());
1480 void StyleResolver::applyCallbackSelectors(StyleResolverState& state)
1482 if (!m_watchedSelectorsRules)
1485 ElementRuleCollector collector(state.elementContext(), m_selectorFilter, state.style());
1486 collector.setMode(SelectorChecker::CollectingStyleRules);
1488 MatchRequest matchRequest(m_watchedSelectorsRules.get(), true);
1489 RuleRange ruleRange = collector.matchedResult().ranges.authorRuleRange();
1490 collector.collectMatchingRules(matchRequest, ruleRange);
1491 collector.sortAndTransferMatchedRules();
1493 RefPtrWillBeRawPtr<StyleRuleList> rules = collector.matchedStyleRuleList();
1496 for (size_t i = 0; i < rules->m_list.size(); i++)
1497 state.style()->addCallbackSelector(rules->m_list[i]->selectorList().selectorsText());
1500 CSSPropertyValue::CSSPropertyValue(CSSPropertyID id, const StylePropertySet& propertySet)
1501 : property(id), value(propertySet.getPropertyCSSValue(id).get())
1504 void StyleResolver::enableStats(StatsReportType reportType)
1506 if (m_styleResolverStats)
1508 m_styleResolverStats = StyleResolverStats::create();
1509 m_styleResolverStatsTotals = StyleResolverStats::create();
1510 if (reportType == ReportSlowStats) {
1511 m_styleResolverStats->printMissedCandidateCount = true;
1512 m_styleResolverStatsTotals->printMissedCandidateCount = true;
1516 void StyleResolver::disableStats()
1518 m_styleResolverStatsSequence = 0;
1519 m_styleResolverStats.clear();
1520 m_styleResolverStatsTotals.clear();
1523 void StyleResolver::printStats()
1525 if (!m_styleResolverStats)
1527 fprintf(stderr, "=== Style Resolver Stats (resolve #%u) (%s) ===\n", ++m_styleResolverStatsSequence, document().url().string().utf8().data());
1528 fprintf(stderr, "%s\n", m_styleResolverStats->report().utf8().data());
1529 fprintf(stderr, "== Totals ==\n");
1530 fprintf(stderr, "%s\n", m_styleResolverStatsTotals->report().utf8().data());
1533 void StyleResolver::applyPropertiesToStyle(const CSSPropertyValue* properties, size_t count, RenderStyle* style)
1535 StyleResolverState state(document(), document().documentElement(), style);
1536 state.setStyle(style);
1538 state.fontBuilder().initForStyleResolve(document(), style);
1540 for (size_t i = 0; i < count; ++i) {
1541 if (properties[i].value) {
1542 // As described in BUG66291, setting font-size and line-height on a font may entail a CSSPrimitiveValue::computeLengthDouble call,
1543 // which assumes the fontMetrics are available for the affected font, otherwise a crash occurs (see http://trac.webkit.org/changeset/96122).
1544 // The updateFont() call below updates the fontMetrics and ensure the proper setting of font-size and line-height.
1545 switch (properties[i].property) {
1546 case CSSPropertyFontSize:
1547 case CSSPropertyLineHeight:
1553 StyleBuilder::applyProperty(properties[i].property, state, properties[i].value);
1558 void StyleResolver::addMediaQueryResults(const MediaQueryResultList& list)
1560 for (size_t i = 0; i < list.size(); ++i)
1561 m_viewportDependentMediaQueryResults.append(list[i]);
1564 bool StyleResolver::mediaQueryAffectedByViewportChange() const
1566 for (unsigned i = 0; i < m_viewportDependentMediaQueryResults.size(); ++i) {
1567 if (m_medium->eval(m_viewportDependentMediaQueryResults[i]->expression()) != m_viewportDependentMediaQueryResults[i]->result())
1573 void StyleResolver::trace(Visitor* visitor)
1576 visitor->trace(m_keyframesRuleMap);
1577 visitor->trace(m_matchedPropertiesCache);
1578 visitor->trace(m_viewportDependentMediaQueryResults);
1579 visitor->trace(m_selectorFilter);
1580 visitor->trace(m_viewportStyleResolver);
1581 visitor->trace(m_features);
1582 visitor->trace(m_siblingRuleSet);
1583 visitor->trace(m_uncommonAttributeRuleSet);
1584 visitor->trace(m_watchedSelectorsRules);
1585 visitor->trace(m_treeBoundaryCrossingRules);
1586 visitor->trace(m_styleSharingLists);
1587 visitor->trace(m_pendingStyleSheets);
1588 visitor->trace(m_document);
1592 } // namespace blink