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