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 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.
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
22 * You should have received a copy of the GNU Library General Public License
23 * along with this library; see the file COPYING.LIB. If not, write to
24 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 * Boston, MA 02110-1301, USA.
29 #include "CSSStyleSelector.h"
31 #include "Attribute.h"
32 #include "CachedImage.h"
33 #include "CalculationValue.h"
34 #include "ContentData.h"
36 #include "CounterContent.h"
37 #include "CSSBorderImage.h"
38 #include "CSSCalculationValue.h"
39 #include "CSSCursorImageValue.h"
40 #include "CSSFontFaceRule.h"
41 #include "CSSFontSelector.h"
42 #include "CSSImportRule.h"
43 #include "CSSLineBoxContainValue.h"
44 #include "CSSMediaRule.h"
45 #include "CSSPageRule.h"
46 #include "CSSParser.h"
47 #include "CSSPrimitiveValueMappings.h"
48 #include "CSSPropertyNames.h"
49 #include "CSSReflectValue.h"
50 #include "CSSRuleList.h"
51 #include "CSSSelector.h"
52 #include "CSSSelectorList.h"
53 #include "CSSStyleApplyProperty.h"
54 #include "CSSStyleRule.h"
55 #include "CSSStyleSheet.h"
56 #include "CSSTimingFunctionValue.h"
57 #include "CSSValueList.h"
58 #include "CursorList.h"
59 #include "FontFeatureValue.h"
60 #include "FontValue.h"
62 #include "FrameSelection.h"
63 #include "FrameView.h"
64 #include "HTMLDocument.h"
65 #include "HTMLElement.h"
66 #include "HTMLInputElement.h"
67 #include "HTMLNames.h"
68 #include "HTMLOptionElement.h"
69 #include "HTMLProgressElement.h"
70 #include "HTMLStyleElement.h"
71 #include "HTMLTextAreaElement.h"
72 #include "InspectorInstrumentation.h"
73 #include "KeyframeList.h"
75 #include "LocaleToScriptMapping.h"
76 #include "Matrix3DTransformOperation.h"
77 #include "MatrixTransformOperation.h"
78 #include "MediaList.h"
79 #include "MediaQueryEvaluator.h"
80 #include "NodeRenderStyle.h"
82 #include "PageGroup.h"
84 #include "PerspectiveTransformOperation.h"
85 #include "QuotesData.h"
87 #include "RenderRegion.h"
88 #include "RenderScrollbar.h"
89 #include "RenderScrollbarTheme.h"
90 #include "RenderStyleConstants.h"
91 #include "RenderTheme.h"
92 #include "RotateTransformOperation.h"
93 #include "RuntimeEnabledFeatures.h"
94 #include "SVGDocumentExtensions.h"
95 #include "SVGFontFaceElement.h"
96 #include "ScaleTransformOperation.h"
97 #include "SecurityOrigin.h"
99 #include "ShadowData.h"
100 #include "ShadowRoot.h"
101 #include "ShadowValue.h"
102 #include "SkewTransformOperation.h"
103 #include "StyleCachedImage.h"
104 #include "StylePendingImage.h"
105 #include "StyleRule.h"
106 #include "StyleGeneratedImage.h"
107 #include "StyleSheetList.h"
109 #include "TransformationMatrix.h"
110 #include "TranslateTransformOperation.h"
111 #include "UserAgentStyleSheets.h"
112 #include "WebKitCSSKeyframeRule.h"
113 #include "WebKitCSSKeyframesRule.h"
114 #include "WebKitCSSRegionRule.h"
115 #include "WebKitCSSTransformValue.h"
116 #include "WebKitFontFamilyNames.h"
117 #include "XMLNames.h"
118 #include <wtf/StdLibExtras.h>
119 #include <wtf/Vector.h>
121 #if ENABLE(CSS_FILTERS)
122 #include "FilterOperation.h"
123 #include "WebKitCSSFilterValue.h"
126 #if ENABLE(DASHBOARD_SUPPORT)
127 #include "DashboardRegion.h"
131 #include "SVGElement.h"
132 #include "SVGNames.h"
135 #if ENABLE(CSS_SHADERS)
136 #include "CustomFilterNumberParameter.h"
137 #include "CustomFilterOperation.h"
138 #include "CustomFilterParameter.h"
139 #include "StyleCachedShader.h"
140 #include "StyleCustomFilterProgram.h"
141 #include "StylePendingShader.h"
142 #include "StyleShader.h"
143 #include "WebKitCSSShaderValue.h"
146 #if ENABLE(CSS_IMAGE_SET)
147 #include "CSSImageSetValue.h"
148 #include "StyleCachedImageSet.h"
155 using namespace HTMLNames;
157 #define HANDLE_INHERIT(prop, Prop) \
159 m_style->set##Prop(m_parentStyle->prop()); \
163 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
164 HANDLE_INHERIT(prop, Prop) \
166 m_style->set##Prop(RenderStyle::initial##Prop()); \
170 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
171 HANDLE_INHERIT(prop, Prop) \
173 m_style->set##Prop(RenderStyle::initial##Value());\
177 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
178 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
179 if (primitiveValue) \
180 m_style->set##Prop(*primitiveValue);
184 RuleData(StyleRule*, CSSSelector*, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule);
186 unsigned position() const { return m_position; }
187 StyleRule* rule() const { return m_rule; }
188 CSSSelector* selector() const { return m_selector; }
190 bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
191 bool hasMultipartSelector() const { return m_hasMultipartSelector; }
192 bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
193 bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
194 unsigned specificity() const { return m_specificity; }
195 unsigned linkMatchType() const { return m_linkMatchType; }
196 bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
197 bool isInRegionRule() const { return m_isInRegionRule; }
199 // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
200 static const unsigned maximumIdentifierCount = 4;
201 const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
205 CSSSelector* m_selector;
206 unsigned m_specificity;
207 // This number was picked fairly arbitrarily. We can probably lower it if we need to.
208 // Some simple testing showed <100,000 RuleData's on large sites.
209 unsigned m_position : 24;
210 unsigned m_hasFastCheckableSelector : 1;
211 unsigned m_hasMultipartSelector : 1;
212 unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
213 unsigned m_containsUncommonAttributeSelector : 1;
214 unsigned m_linkMatchType : 2; // SelectorChecker::LinkMatchMask
215 unsigned m_hasDocumentSecurityOrigin : 1;
216 unsigned m_isInRegionRule : 1;
217 // Use plain array instead of a Vector to minimize memory overhead.
218 unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
221 struct SameSizeAsRuleData {
229 COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
232 WTF_MAKE_NONCOPYABLE(RuleSet);
234 static PassOwnPtr<RuleSet> create() { return adoptPtr(new RuleSet); }
236 typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
238 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0, const ContainerNode* = 0);
240 void addStyleRule(StyleRule*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
241 void addRule(StyleRule*, CSSSelector*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
242 void addPageRule(CSSPageRule*);
243 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&);
244 void addRegionRule(WebKitCSSRegionRule*, bool hasDocumentSecurityOrigin);
246 void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
248 const CSSStyleSelector::Features& features() const { return m_features; }
250 const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
251 const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
252 const Vector<RuleData>* tagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
253 const Vector<RuleData>* shadowPseudoElementRules(AtomicStringImpl* key) const { return m_shadowPseudoElementRules.get(key); }
254 const Vector<RuleData>* linkPseudoClassRules() const { return &m_linkPseudoClassRules; }
255 const Vector<RuleData>* focusPseudoClassRules() const { return &m_focusPseudoClassRules; }
256 const Vector<RuleData>* universalRules() const { return &m_universalRules; }
257 const Vector<CSSPageRule*>& pageRules() const { return m_pageRules; }
262 AtomRuleMap m_idRules;
263 AtomRuleMap m_classRules;
264 AtomRuleMap m_tagRules;
265 AtomRuleMap m_shadowPseudoElementRules;
266 Vector<RuleData> m_linkPseudoClassRules;
267 Vector<RuleData> m_focusPseudoClassRules;
268 Vector<RuleData> m_universalRules;
269 Vector<CSSPageRule*> m_pageRules;
270 unsigned m_ruleCount;
271 bool m_autoShrinkToFitEnabled;
272 CSSStyleSelector::Features m_features;
274 struct RuleSetSelectorPair {
275 RuleSetSelectorPair(CSSSelector* selector, PassOwnPtr<RuleSet> ruleSet) : selector(selector), ruleSet(ruleSet) { }
276 RuleSetSelectorPair(const RuleSetSelectorPair& rs) : selector(rs.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&rs)->ruleSet.release()) { }
277 CSSSelector* selector;
278 OwnPtr<RuleSet> ruleSet;
281 Vector<RuleSetSelectorPair> m_regionSelectorsAndRuleSets;
284 static RuleSet* defaultStyle;
285 static RuleSet* defaultQuirksStyle;
286 static RuleSet* defaultPrintStyle;
287 static RuleSet* defaultViewSourceStyle;
288 static CSSStyleSheet* simpleDefaultStyleSheet;
289 static CSSStyleSheet* defaultStyleSheet;
290 static CSSStyleSheet* quirksStyleSheet;
291 static CSSStyleSheet* svgStyleSheet;
292 static CSSStyleSheet* mathMLStyleSheet;
293 static CSSStyleSheet* mediaControlsStyleSheet;
294 static CSSStyleSheet* fullscreenStyleSheet;
296 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
298 static void loadFullDefaultStyle();
299 static void loadSimpleDefaultStyle();
300 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >&, CSSStyleSheet*);
302 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
303 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
305 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
307 return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
310 static const MediaQueryEvaluator& screenEval()
312 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
313 return staticScreenEval;
316 static const MediaQueryEvaluator& printEval()
318 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
319 return staticPrintEval;
322 static StylePropertySet* leftToRightDeclaration()
324 DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
325 if (leftToRightDecl->isEmpty())
326 leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
327 return leftToRightDecl.get();
330 static StylePropertySet* rightToLeftDeclaration()
332 DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
333 if (rightToLeftDecl->isEmpty())
334 rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
335 return rightToLeftDecl.get();
338 CSSStyleSelector::CSSStyleSelector(Document* document, bool matchAuthorAndUserStyles)
339 : m_hasUAAppearance(false)
340 , m_backgroundData(BackgroundFillLayer)
341 , m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
342 , m_checker(document, !document->inQuirksMode())
344 , m_rootElementStyle(0)
347 , m_regionForStyling(0)
348 , m_elementLinkState(NotInsideLink)
350 , m_lineHeightValue(0)
352 , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
353 , m_sameOriginOnly(false)
354 , m_fontSelector(CSSFontSelector::create(document))
355 , m_applyPropertyToRegularStyle(true)
356 , m_applyPropertyToVisitedLinkStyle(false)
357 , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
358 #if ENABLE(CSS_SHADERS)
359 , m_hasPendingShaders(false)
361 #if ENABLE(STYLE_SCOPED)
362 , m_scopeStackParent(0)
365 Element* root = document->documentElement();
368 if (!root || elementCanUseSimpleDefaultStyle(root))
369 loadSimpleDefaultStyle();
371 loadFullDefaultStyle();
375 // construct document root element default style. this is needed
376 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
377 // This is here instead of constructor, because when constructor is run,
378 // document doesn't have documentElement
379 // NOTE: this assumes that element that gets passed to styleForElement -call
380 // is always from the document that owns the style selector
381 FrameView* view = document->view();
383 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
385 m_medium = adoptPtr(new MediaQueryEvaluator("all"));
388 m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
390 if (m_rootDefaultStyle && view)
391 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
393 m_authorStyle = RuleSet::create();
394 // Adding rules from multiple sheets, shrink at the end.
395 // Adding global rules from multiple sheets, shrink at the end.
396 // Note that there usually is only 1 sheet for scoped rules, so auto-shrink-to-fit is fine.
397 m_authorStyle->disableAutoShrinkToFit();
399 // FIXME: This sucks! The user sheet is reparsed every time!
400 OwnPtr<RuleSet> tempUserStyle = RuleSet::create();
401 if (CSSStyleSheet* pageUserSheet = document->pageUserSheet())
402 tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
403 if (const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = document->pageGroupUserSheets()) {
404 unsigned length = pageGroupUserSheets->size();
405 for (unsigned i = 0; i < length; i++) {
406 if (pageGroupUserSheets->at(i)->isUserStyleSheet())
407 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
409 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
412 if (const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = document->documentUserSheets()) {
413 unsigned length = documentUserSheets->size();
414 for (unsigned i = 0; i < length; i++) {
415 if (documentUserSheets->at(i)->isUserStyleSheet())
416 tempUserStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
418 m_authorStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
422 if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
423 m_userStyle = tempUserStyle.release();
425 #if ENABLE(SVG_FONTS)
426 if (document->svgExtensions()) {
427 const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
428 HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
429 for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
430 fontSelector()->addFontFaceRule((*it)->fontFaceRule());
434 appendAuthorStylesheets(0, document->styleSheets()->vector());
437 static PassOwnPtr<RuleSet> makeRuleSet(const Vector<CSSStyleSelector::RuleFeature>& rules)
439 size_t size = rules.size();
442 OwnPtr<RuleSet> ruleSet = RuleSet::create();
443 for (size_t i = 0; i < size; ++i)
444 ruleSet->addRule(rules[i].rule, rules[i].selector, rules[i].hasDocumentSecurityOrigin, false);
445 return ruleSet.release();
448 void CSSStyleSelector::collectFeatures()
451 // Collect all ids and rules using sibling selectors (:first-child and similar)
452 // in the current set of stylesheets. Style sharing code uses this information to reject
453 // sharing candidates.
454 m_features.add(defaultStyle->features());
455 m_features.add(m_authorStyle->features());
456 #if ENABLE(STYLE_SCOPED)
457 for (ScopedRuleSetMap::iterator it = m_scopedAuthorStyles.begin(); it != m_scopedAuthorStyles.end(); ++it)
458 m_features.add(it->second->features());
461 m_features.add(m_userStyle->features());
463 m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
464 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
467 #if ENABLE(STYLE_SCOPED)
468 const ContainerNode* CSSStyleSelector::determineScope(const CSSStyleSheet* sheet)
472 if (!RuntimeEnabledFeatures::styleScopedEnabled())
475 Node* ownerNode = sheet->findStyleSheetOwnerNode();
476 if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag))
479 HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
480 if (!styleElement->scoped())
483 ContainerNode* parent = styleElement->parentNode();
487 return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
490 inline RuleSet* CSSStyleSelector::ruleSetForScope(const ContainerNode* scope) const
492 if (!scope->hasScopedHTMLStyleChild())
494 ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(scope);
495 return it != m_scopedAuthorStyles.end() ? it->second.get() : 0;
499 void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets)
501 // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
502 // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
503 unsigned size = stylesheets.size();
504 for (unsigned i = firstNew; i < size; ++i) {
505 if (!stylesheets[i]->isCSSStyleSheet() || stylesheets[i]->disabled())
507 CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get());
508 #if ENABLE(STYLE_SCOPED)
509 const ContainerNode* scope = determineScope(cssSheet);
511 ScopedRuleSetMap::AddResult addResult = m_scopedAuthorStyles.add(scope, nullptr);
512 if (addResult.isNewEntry)
513 addResult.iterator->second = RuleSet::create();
514 addResult.iterator->second->addRulesFromSheet(cssSheet, *m_medium, this, scope);
518 m_authorStyle->addRulesFromSheet(cssSheet, *m_medium, this);
519 if (!m_styleRuleToCSSOMWrapperMap.isEmpty())
520 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, cssSheet);
522 m_authorStyle->shrinkToFit();
525 if (document()->renderer() && document()->renderer()->style())
526 document()->renderer()->style()->font().update(fontSelector());
529 #if ENABLE(STYLE_SCOPED)
530 void CSSStyleSelector::setupScopeStack(const ContainerNode* parent)
532 // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
533 ASSERT(!m_scopedAuthorStyles.isEmpty());
535 m_scopeStack.shrink(0);
536 for (; parent; parent = parent->parentOrHostNode()) {
537 RuleSet* ruleSet = ruleSetForScope(parent);
539 m_scopeStack.append(ScopeStackFrame(parent, ruleSet));
541 m_scopeStack.reverse();
542 m_scopeStackParent = parent;
545 void CSSStyleSelector::pushScope(const ContainerNode* scope, const ContainerNode* scopeParent)
547 // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
548 if (m_scopedAuthorStyles.isEmpty()) {
549 ASSERT(!m_scopeStackParent);
550 ASSERT(m_scopeStack.isEmpty());
553 // In some wacky cases during style resolve we may get invoked for random elements.
554 // Recreate the whole scoping element stack in such cases.
555 if (!scopeStackIsConsistent(scopeParent)) {
556 setupScopeStack(scope);
559 // Otherwise just push the parent onto the stack.
560 RuleSet* ruleSet = ruleSetForScope(scope);
562 m_scopeStack.append(ScopeStackFrame(scope, ruleSet));
563 m_scopeStackParent = scope;
566 void CSSStyleSelector::popScope(const ContainerNode* scope)
568 // Only bother to update the scoping element stack if it is consistent.
569 if (scopeStackIsConsistent(scope)) {
570 m_scopeStack.removeLast();
571 m_scopeStackParent = scope->parentOrHostNode();
576 void CSSStyleSelector::pushParentElement(Element* parent)
578 const ContainerNode* parentsParent = parent->parentOrHostElement();
580 // We are not always invoked consistently. For example, script execution can cause us to enter
581 // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
582 // Reset the stack in this case, or if we see a new root element.
583 // Otherwise just push the new parent.
584 if (!parentsParent || m_checker.parentStackIsEmpty())
585 m_checker.setupParentStack(parent);
587 m_checker.pushParent(parent);
589 // Note: We mustn't skip ShadowRoot nodes for the scope stack.
590 pushScope(parent, parent->parentOrHostNode());
593 void CSSStyleSelector::popParentElement(Element* parent)
595 // Note that we may get invoked for some random elements in some wacky cases during style resolve.
596 // Pause maintaining the stack in this case.
597 if (m_checker.parentStackIsConsistent(parent))
598 m_checker.popParent();
602 void CSSStyleSelector::pushParentShadowRoot(const ShadowRoot* shadowRoot)
604 ASSERT(shadowRoot->host());
605 pushScope(shadowRoot, shadowRoot->host());
608 void CSSStyleSelector::popParentShadowRoot(const ShadowRoot* shadowRoot)
610 ASSERT(shadowRoot->host());
611 popScope(shadowRoot);
614 // This is a simplified style setting function for keyframe styles
615 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
617 AtomicString s(rule->name());
618 m_keyframesRuleMap.set(s.impl(), rule);
621 CSSStyleSelector::~CSSStyleSelector()
623 m_fontSelector->clearDocument();
626 void CSSStyleSelector::sweepMatchedPropertiesCache()
628 // Look for cache entries containing a style declaration with a single ref and remove them.
629 // This may happen when an element attribute mutation causes it to swap out its Attribute::decl()
630 // for another CSSMappedAttributeDeclaration, potentially leaving this cache with the last ref.
631 Vector<unsigned, 16> toRemove;
632 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
633 MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
634 for (; it != end; ++it) {
635 Vector<MatchedProperties>& matchedProperties = it->second.matchedProperties;
636 for (size_t i = 0; i < matchedProperties.size(); ++i) {
637 if (matchedProperties[i].properties->hasOneRef()) {
638 toRemove.append(it->first);
643 for (size_t i = 0; i < toRemove.size(); ++i)
644 m_matchedPropertiesCache.remove(toRemove[i]);
647 CSSStyleSelector::Features::Features()
648 : usesFirstLineRules(false)
649 , usesBeforeAfterRules(false)
650 , usesLinkRules(false)
654 CSSStyleSelector::Features::~Features()
658 void CSSStyleSelector::Features::add(const CSSStyleSelector::Features& other)
660 HashSet<AtomicStringImpl*>::iterator end = other.idsInRules.end();
661 for (HashSet<AtomicStringImpl*>::iterator it = other.idsInRules.begin(); it != end; ++it)
663 end = other.attrsInRules.end();
664 for (HashSet<AtomicStringImpl*>::iterator it = other.attrsInRules.begin(); it != end; ++it)
665 attrsInRules.add(*it);
666 siblingRules.append(other.siblingRules);
667 uncommonAttributeRules.append(other.uncommonAttributeRules);
668 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
669 usesBeforeAfterRules = usesBeforeAfterRules || other.usesBeforeAfterRules;
670 usesLinkRules = usesLinkRules || other.usesLinkRules;
673 void CSSStyleSelector::Features::clear()
676 attrsInRules.clear();
677 siblingRules.clear();
678 uncommonAttributeRules.clear();
679 usesFirstLineRules = false;
680 usesBeforeAfterRules = false;
681 usesLinkRules = false;
684 static CSSStyleSheet* parseUASheet(const String& str)
686 CSSStyleSheet* sheet = CSSStyleSheet::create().leakRef(); // leak the sheet on purpose
687 sheet->parseString(str);
691 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
693 return parseUASheet(String(characters, size));
696 static void loadFullDefaultStyle()
698 if (simpleDefaultStyleSheet) {
699 ASSERT(defaultStyle);
700 ASSERT(defaultPrintStyle == defaultStyle);
702 simpleDefaultStyleSheet->deref();
703 defaultStyle = RuleSet::create().leakPtr();
704 defaultPrintStyle = RuleSet::create().leakPtr();
705 simpleDefaultStyleSheet = 0;
707 ASSERT(!defaultStyle);
708 defaultStyle = RuleSet::create().leakPtr();
709 defaultPrintStyle = RuleSet::create().leakPtr();
710 defaultQuirksStyle = RuleSet::create().leakPtr();
713 // Strict-mode rules.
714 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
715 defaultStyleSheet = parseUASheet(defaultRules);
716 defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval());
717 defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval());
719 // Quirks-mode rules.
720 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
721 quirksStyleSheet = parseUASheet(quirksRules);
722 defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval());
725 static void loadSimpleDefaultStyle()
727 ASSERT(!defaultStyle);
728 ASSERT(!simpleDefaultStyleSheet);
730 defaultStyle = RuleSet::create().leakPtr();
731 // There are no media-specific rules in the simple default style.
732 defaultPrintStyle = defaultStyle;
733 defaultQuirksStyle = RuleSet::create().leakPtr();
735 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
736 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
738 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
741 static void loadViewSourceStyle()
743 ASSERT(!defaultViewSourceStyle);
744 defaultViewSourceStyle = RuleSet::create().leakPtr();
745 defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
748 static void ensureDefaultStyleSheetsForElement(Element* element)
750 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element))
751 loadFullDefaultStyle();
754 if (element->isSVGElement() && !svgStyleSheet) {
756 svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
757 defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval());
758 defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval());
763 if (element->isMathMLElement() && !mathMLStyleSheet) {
765 mathMLStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
766 defaultStyle->addRulesFromSheet(mathMLStyleSheet, screenEval());
767 defaultPrintStyle->addRulesFromSheet(mathMLStyleSheet, printEval());
772 if (!mediaControlsStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
773 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
774 mediaControlsStyleSheet = parseUASheet(mediaRules);
775 defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval());
776 defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval());
780 #if ENABLE(FULLSCREEN_API)
781 if (!fullscreenStyleSheet && element->document()->webkitIsFullScreen()) {
782 String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
783 fullscreenStyleSheet = parseUASheet(fullscreenRules);
784 defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
785 defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
789 ASSERT(defaultStyle->features().idsInRules.isEmpty());
790 ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty());
793 void CSSStyleSelector::addMatchedProperties(MatchResult& matchResult, StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, bool inRegionRule)
795 matchResult.matchedProperties.grow(matchResult.matchedProperties.size() + 1);
796 MatchedProperties& newProperties = matchResult.matchedProperties.last();
797 newProperties.properties = properties;
798 newProperties.linkMatchType = linkMatchType;
799 newProperties.isInRegionRule = inRegionRule;
800 matchResult.matchedRules.append(rule);
803 inline void CSSStyleSelector::addElementStyleProperties(MatchResult& result, StylePropertySet* propertySet, bool isCacheable)
807 result.ranges.lastAuthorRule = result.matchedProperties.size();
808 if (result.ranges.firstAuthorRule == -1)
809 result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
810 addMatchedProperties(result, propertySet);
812 result.isCacheable = false;
815 void CSSStyleSelector::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
820 // We need to collect the rules for id, class, tag, and everything else into a buffer and
821 // then sort the buffer.
822 if (m_element->hasID())
823 collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, options);
824 if (m_element->hasClass()) {
825 ASSERT(m_styledElement);
826 const SpaceSplitString& classNames = m_styledElement->classNames();
827 size_t size = classNames.size();
828 for (size_t i = 0; i < size; ++i)
829 collectMatchingRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, options);
831 const AtomicString& pseudoId = m_element->shadowPseudoId();
832 if (!pseudoId.isEmpty()) {
833 ASSERT(m_styledElement);
834 collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
836 if (m_element->isLink())
837 collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
838 if (m_checker.matchesFocusPseudoClass(m_element))
839 collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
840 collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, options);
841 collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, options);
844 void CSSStyleSelector::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
846 if (!m_regionForStyling)
849 unsigned size = rules->m_regionSelectorsAndRuleSets.size();
850 for (unsigned i = 0; i < size; ++i) {
851 CSSSelector* regionSelector = rules->m_regionSelectorsAndRuleSets.at(i).selector;
852 if (checkRegionSelector(regionSelector, static_cast<Element*>(m_regionForStyling->node()))) {
853 RuleSet* regionRules = rules->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
855 collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, options);
860 void CSSStyleSelector::sortAndTransferMatchedRules(MatchResult& result)
862 if (m_matchedRules.isEmpty())
867 if (m_checker.isCollectingRulesOnly()) {
869 m_ruleList = StaticCSSRuleList::create();
870 for (unsigned i = 0; i < m_matchedRules.size(); ++i)
871 m_ruleList->rules().append(m_matchedRules[i]->rule()->ensureCSSStyleRule());
875 // Now transfer the set of matched rules over to our list of declarations.
876 // FIXME: This sucks, the inspector should get the style from the visited style itself.
877 bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
878 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
879 if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
880 m_style->setAffectedByUncommonAttributeSelectors();
881 unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
882 if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
883 linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
884 addMatchedProperties(result, m_matchedRules[i]->rule()->properties(), m_matchedRules[i]->rule(), linkMatchType, m_matchedRules[i]->isInRegionRule());
888 void CSSStyleSelector::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
890 #if ENABLE(STYLE_SCOPED)
891 if (m_scopedAuthorStyles.isEmpty())
894 MatchOptions options(includeEmptyRules);
896 // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
897 const ContainerNode* parent = m_element->parentOrHostNode();
898 if (!scopeStackIsConsistent(parent))
899 setupScopeStack(parent);
900 for (size_t i = m_scopeStack.size(); i; --i) {
901 const ScopeStackFrame& frame = m_scopeStack[i - 1];
902 options.scope = frame.m_scope;
903 collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
904 collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
906 // Also include the current element.
907 RuleSet* ruleSet = ruleSetForScope(m_element);
909 options.scope = m_element;
910 collectMatchingRules(ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
911 collectMatchingRulesForRegion(ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
914 UNUSED_PARAM(result);
915 UNUSED_PARAM(includeEmptyRules);
919 void CSSStyleSelector::matchAuthorRules(MatchResult& result, bool includeEmptyRules)
921 m_matchedRules.clear();
922 result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
927 // Match global author rules.
928 MatchOptions options(includeEmptyRules);
929 collectMatchingRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
930 collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
932 matchScopedAuthorRules(result, includeEmptyRules);
934 sortAndTransferMatchedRules(result);
937 void CSSStyleSelector::matchUserRules(MatchResult& result, bool includeEmptyRules)
942 m_matchedRules.clear();
944 result.ranges.lastUserRule = result.matchedProperties.size() - 1;
945 collectMatchingRules(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
946 collectMatchingRulesForRegion(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
948 sortAndTransferMatchedRules(result);
951 void CSSStyleSelector::matchUARules(MatchResult& result, RuleSet* rules)
953 m_matchedRules.clear();
955 result.ranges.lastUARule = result.matchedProperties.size() - 1;
956 collectMatchingRules(rules, result.ranges.firstUARule, result.ranges.lastUARule, false);
958 sortAndTransferMatchedRules(result);
961 class MatchingUARulesScope {
963 MatchingUARulesScope();
964 ~MatchingUARulesScope();
966 static bool isMatchingUARules();
969 static bool m_matchingUARules;
972 MatchingUARulesScope::MatchingUARulesScope()
974 ASSERT(!m_matchingUARules);
975 m_matchingUARules = true;
978 MatchingUARulesScope::~MatchingUARulesScope()
980 m_matchingUARules = false;
983 inline bool MatchingUARulesScope::isMatchingUARules()
985 return m_matchingUARules;
988 bool MatchingUARulesScope::m_matchingUARules = false;
990 void CSSStyleSelector::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
994 // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
995 // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
996 bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
998 unsigned size = rules->size();
999 for (unsigned i = 0; i < size; ++i) {
1000 const RuleData& ruleData = rules->at(i);
1001 if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
1004 StyleRule* rule = ruleData.rule();
1005 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
1006 #if ENABLE(STYLE_SCOPED)
1007 if (checkSelector(ruleData, options.scope)) {
1009 if (checkSelector(ruleData)) {
1011 // Check whether the rule is applicable in the current tree scope. Criteria for this:
1012 // a) it's a UA rule
1013 // b) the tree scope allows author rules
1014 // c) the rules comes from a scoped style sheet within the same tree scope
1015 // d) the rule contains shadow-ID pseudo elements
1016 TreeScope* treeScope = m_element->treeScope();
1017 if (!MatchingUARulesScope::isMatchingUARules()
1018 && !treeScope->applyAuthorSheets()
1019 #if ENABLE(STYLE_SCOPED)
1020 && (!options.scope || options.scope->treeScope() != treeScope)
1022 && !m_checker.hasUnknownPseudoElements()) {
1024 InspectorInstrumentation::didMatchRule(cookie, false);
1027 // If the rule has no properties to apply, then ignore it in the non-debug mode.
1028 StylePropertySet* properties = rule->properties();
1029 if (!properties || (properties->isEmpty() && !options.includeEmptyRules)) {
1030 InspectorInstrumentation::didMatchRule(cookie, false);
1033 // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
1034 if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) {
1035 InspectorInstrumentation::didMatchRule(cookie, false);
1038 // If we're matching normal rules, set a pseudo bit if
1039 // we really just matched a pseudo-element.
1040 if (m_dynamicPseudo != NOPSEUDO && m_checker.pseudoStyle() == NOPSEUDO) {
1041 if (m_checker.isCollectingRulesOnly()) {
1042 InspectorInstrumentation::didMatchRule(cookie, false);
1045 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
1046 m_style->setHasPseudoStyle(m_dynamicPseudo);
1048 // Update our first/last rule indices in the matched rules array.
1050 if (firstRuleIndex == -1)
1051 firstRuleIndex = lastRuleIndex;
1053 // Add this rule to our list of matched rules.
1054 addMatchedRule(&ruleData);
1055 InspectorInstrumentation::didMatchRule(cookie, true);
1059 InspectorInstrumentation::didMatchRule(cookie, false);
1063 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
1065 unsigned specificity1 = r1->specificity();
1066 unsigned specificity2 = r2->specificity();
1067 return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
1070 void CSSStyleSelector::sortMatchedRules()
1072 std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
1075 void CSSStyleSelector::matchAllRules(MatchResult& result)
1077 matchUARules(result);
1079 // Now we check user sheet rules.
1080 if (m_matchAuthorAndUserStyles)
1081 matchUserRules(result, false);
1083 // Now check author rules, beginning first with presentational attributes mapped from HTML.
1084 if (m_styledElement) {
1085 addElementStyleProperties(result, m_styledElement->attributeStyle());
1087 // Now we check additional mapped declarations.
1088 // Tables and table cells share an additional mapped rule that must be applied
1089 // after all attributes, since their mapped style depends on the values of multiple attributes.
1090 addElementStyleProperties(result, m_styledElement->additionalAttributeStyle());
1092 if (m_styledElement->isHTMLElement()) {
1094 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
1096 addMatchedProperties(result, textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
1100 // Check the rules in author sheets next.
1101 if (m_matchAuthorAndUserStyles)
1102 matchAuthorRules(result, false);
1104 // Now check our inline style attribute.
1105 if (m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->inlineStyle()) {
1106 // Inline style is immutable as long as there is no CSSOM wrapper.
1107 // FIXME: Media control shadow trees seem to have problems with caching.
1108 bool isInlineStyleCacheable = !m_styledElement->inlineStyle()->isMutable() && !m_styledElement->isInShadowTree();
1110 addElementStyleProperties(result, const_cast<StylePropertySet*>(m_styledElement->inlineStyle()), isInlineStyleCacheable);
1114 // Now check SMIL animation override style.
1115 if (m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->isSVGElement())
1116 addElementStyleProperties(result, static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties(), false /* isCacheable */);
1120 inline void CSSStyleSelector::initElement(Element* e)
1122 if (m_element != e) {
1124 m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
1125 m_elementLinkState = m_checker.determineLinkState(m_element);
1126 if (e && e == e->document()->documentElement()) {
1127 e->document()->setDirectionSetOnDocumentElement(false);
1128 e->document()->setWritingModeSetOnDocumentElement(false);
1133 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
1135 m_checker.setPseudoStyle(pseudoID);
1137 m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
1140 m_parentStyle = parentStyle;
1142 m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
1144 Node* docElement = e ? e->document()->documentElement() : 0;
1145 RenderStyle* docStyle = m_checker.document()->renderStyle();
1146 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
1150 m_pendingImageProperties.clear();
1154 m_fontDirty = false;
1157 static const unsigned cStyleSearchThreshold = 10;
1158 static const unsigned cStyleSearchLevelThreshold = 10;
1160 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
1162 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
1164 if (!parent || !parent->isStyledElement())
1166 #if ENABLE(STYLE_SCOPED)
1167 if (parent->hasScopedHTMLStyleChild())
1170 StyledElement* p = static_cast<StyledElement*>(parent);
1171 if (p->inlineStyle())
1174 if (p->isSVGElement() && static_cast<SVGElement*>(p)->animatedSMILStyleProperties())
1177 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
1180 RenderStyle* parentStyle = p->renderStyle();
1181 unsigned subcount = 0;
1182 Node* thisCousin = p;
1183 Node* currentNode = p->previousSibling();
1185 // Reserve the tries for this level. This effectively makes sure that the algorithm
1186 // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
1187 visitedNodeCount += cStyleSearchThreshold;
1188 while (thisCousin) {
1189 while (currentNode) {
1191 if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
1192 // Adjust for unused reserved tries.
1193 visitedNodeCount -= cStyleSearchThreshold - subcount;
1194 return currentNode->lastChild();
1196 if (subcount >= cStyleSearchThreshold)
1198 currentNode = currentNode->previousSibling();
1200 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
1201 thisCousin = currentNode;
1207 bool CSSStyleSelector::matchesRuleSet(RuleSet* ruleSet)
1211 m_matchedRules.clear();
1213 int firstRuleIndex = -1, lastRuleIndex = -1;
1214 collectMatchingRules(ruleSet, firstRuleIndex, lastRuleIndex, false);
1216 if (m_matchedRules.isEmpty())
1218 m_matchedRules.clear();
1222 bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const
1224 HTMLInputElement* thisInputElement = element->toInputElement();
1225 HTMLInputElement* otherInputElement = m_element->toInputElement();
1227 if (!thisInputElement || !otherInputElement)
1230 if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1232 if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
1234 if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1236 if (thisInputElement->required() != otherInputElement->required())
1239 if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1242 if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1245 if (m_element->document()->containsValidityStyleRules()) {
1246 bool willValidate = element->willValidate();
1248 if (willValidate != m_element->willValidate())
1251 if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1254 if (element->isInRange() != m_element->isInRange())
1257 if (element->isOutOfRange() != m_element->isOutOfRange())
1264 // This function makes some assumptions that only make sense for attribute styles (we only compare CSSProperty::id() and CSSProperty::value().)
1265 static inline bool attributeStylesEqual(StylePropertySet* a, StylePropertySet* b)
1269 if (a->propertyCount() != b->propertyCount())
1271 unsigned propertyCount = a->propertyCount();
1272 for (unsigned i = 0; i < propertyCount; ++i) {
1273 const CSSProperty& aProperty = a->propertyAt(i);
1275 for (j = 0; j < propertyCount; ++j) {
1276 const CSSProperty& bProperty = b->propertyAt(j);
1277 if (aProperty.id() != bProperty.id())
1279 // We could get a few more hits by comparing cssText() here, but that gets expensive quickly.
1280 if (aProperty.value() != bProperty.value())
1284 if (j == propertyCount)
1290 inline bool elementHasDirectionAuto(Element* element)
1292 return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
1295 bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const
1297 RenderStyle* style = element->renderStyle();
1301 if (style->unique())
1303 if (element->tagQName() != m_element->tagQName())
1305 if (element->hasClass() != m_element->hasClass())
1307 if (element->inlineStyle())
1310 if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
1313 if (!!element->attributeStyle() != !!m_styledElement->attributeStyle())
1315 StylePropertySet* additionalAttributeStyleA = element->additionalAttributeStyle();
1316 StylePropertySet* additionalAttributeStyleB = m_styledElement->additionalAttributeStyle();
1317 if (!additionalAttributeStyleA != !additionalAttributeStyleB)
1319 if (element->isLink() != m_element->isLink())
1321 if (style->affectedByUncommonAttributeSelectors())
1323 if (element->hovered() != m_element->hovered())
1325 if (element->active() != m_element->active())
1327 if (element->focused() != m_element->focused())
1329 if (element->shadowPseudoId() != m_element->shadowPseudoId())
1331 if (element == element->document()->cssTarget())
1333 if (m_element == m_element->document()->cssTarget())
1335 if (element->getAttribute(typeAttr) != m_element->getAttribute(typeAttr))
1337 if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1339 if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1341 if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1343 if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1346 if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1349 #if ENABLE(STYLE_SCOPED)
1350 if (element->hasScopedHTMLStyleChild())
1354 #if ENABLE(PROGRESS_TAG)
1355 if (element->hasTagName(progressTag)) {
1356 if (!m_element->hasTagName(progressTag))
1359 HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
1360 HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
1361 if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
1366 if (element->hasTagName(optionTag))
1369 bool isControl = element->isFormControlElement();
1371 if (isControl != m_element->isFormControlElement())
1374 if (isControl && !canShareStyleWithControl(element))
1377 if (style->transitions() || style->animations())
1380 #if USE(ACCELERATED_COMPOSITING)
1381 // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1382 // See comments in RenderObject::setStyle().
1383 if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)
1384 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1385 // With proxying, the media elements are backed by a RenderEmbeddedObject.
1386 || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1392 if (elementHasDirectionAuto(element) || elementHasDirectionAuto(m_element))
1395 if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr))
1398 if (element->attributeStyle() && !attributeStylesEqual(element->attributeStyle(), m_styledElement->attributeStyle()))
1401 if (additionalAttributeStyleA && !attributeStylesEqual(additionalAttributeStyleA, additionalAttributeStyleB))
1404 if (element->isLink() && m_elementLinkState != style->insideLink())
1410 inline StyledElement* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
1412 for (; node; node = node->previousSibling()) {
1413 if (!node->isStyledElement())
1415 if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
1417 if (count++ == cStyleSearchThreshold)
1420 return static_cast<StyledElement*>(node);
1423 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1425 return parentStyle->childrenAffectedByPositionalRules()
1426 || parentStyle->childrenAffectedByFirstChildRules()
1427 || parentStyle->childrenAffectedByLastChildRules()
1428 || parentStyle->childrenAffectedByDirectAdjacentRules();
1431 RenderStyle* CSSStyleSelector::locateSharedStyle()
1433 if (!m_styledElement || !m_parentStyle)
1435 // If the element has inline style it is probably unique.
1436 if (m_styledElement->inlineStyle())
1439 if (m_styledElement->isSVGElement() && static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties())
1442 // Ids stop style sharing if they show up in the stylesheets.
1443 if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1445 if (parentStylePreventsSharing(m_parentStyle))
1447 #if ENABLE(STYLE_SCOPED)
1448 if (m_styledElement->hasScopedHTMLStyleChild())
1452 // Check previous siblings and their cousins.
1454 unsigned visitedNodeCount = 0;
1455 StyledElement* shareElement = 0;
1456 Node* cousinList = m_styledElement->previousSibling();
1457 while (cousinList) {
1458 shareElement = findSiblingForStyleSharing(cousinList, count);
1461 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1464 // If we have exhausted all our budget or our cousins.
1468 // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1469 if (matchesRuleSet(m_siblingRuleSet.get()))
1471 // Can't share if attribute rules apply.
1472 if (matchesRuleSet(m_uncommonAttributeRuleSet.get()))
1474 // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1475 if (parentStylePreventsSharing(m_parentStyle))
1477 return shareElement->renderStyle();
1480 void CSSStyleSelector::matchUARules(MatchResult& result)
1482 MatchingUARulesScope scope;
1484 // First we match rules from the user agent sheet.
1485 if (simpleDefaultStyleSheet)
1486 result.isCacheable = false;
1487 RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1488 ? defaultPrintStyle : defaultStyle;
1489 matchUARules(result, userAgentStyleSheet);
1491 // In quirks mode, we match rules from the quirks user agent sheet.
1492 if (!m_checker.strictParsing())
1493 matchUARules(result, defaultQuirksStyle);
1495 // 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.
1496 if (m_checker.document()->isViewSource()) {
1497 if (!defaultViewSourceStyle)
1498 loadViewSourceStyle();
1499 matchUARules(result, defaultViewSourceStyle);
1503 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document, CSSFontSelector* fontSelector)
1505 Frame* frame = document->frame();
1507 RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1508 documentStyle->setDisplay(BLOCK);
1509 documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1510 documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomFactor() : 1);
1511 documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1512 documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1513 documentStyle->setLocale(document->contentLanguage());
1515 Element* docElement = document->documentElement();
1516 RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1517 if (docElementRenderer) {
1518 // Use the direction and writing-mode of the body to set the
1519 // viewport's direction and writing-mode unless the property is set on the document element.
1520 // If there is no body, then use the document element.
1521 RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1522 if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1523 documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1525 documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1526 if (bodyRenderer && !document->directionSetOnDocumentElement())
1527 documentStyle->setDirection(bodyRenderer->style()->direction());
1529 documentStyle->setDirection(docElementRenderer->style()->direction());
1533 if (Page* page = frame->page()) {
1534 const Page::Pagination& pagination = page->pagination();
1535 if (pagination.mode != Page::Pagination::Unpaginated) {
1536 documentStyle->setColumnAxis(pagination.mode == Page::Pagination::HorizontallyPaginated ? HorizontalColumnAxis : VerticalColumnAxis);
1537 documentStyle->setColumnGap(pagination.gap);
1542 FontDescription fontDescription;
1543 fontDescription.setUsePrinterFont(document->printing());
1544 fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
1545 if (Settings* settings = document->settings()) {
1546 fontDescription.setRenderingMode(settings->fontRenderingMode());
1547 const AtomicString& standardFont = settings->standardFontFamily(fontDescription.script());
1548 if (!standardFont.isEmpty()) {
1549 fontDescription.setGenericFamily(FontDescription::StandardFamily);
1550 fontDescription.firstFamily().setFamily(standardFont);
1551 fontDescription.firstFamily().appendFamily(0);
1553 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1554 int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1555 fontDescription.setSpecifiedSize(size);
1556 bool useSVGZoomRules = document->isSVGDocument();
1557 fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1560 documentStyle->setFontDescription(fontDescription);
1561 documentStyle->font().update(fontSelector);
1563 return documentStyle.release();
1566 static inline bool isAtShadowBoundary(Element* element)
1570 ContainerNode* parentNode = element->parentNode();
1571 return parentNode && parentNode->isShadowRoot();
1574 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent,
1575 StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
1577 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1578 // will vanish if a style recalc happens during loading.
1579 if (sharingBehavior == AllowStyleSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1580 if (!s_styleNotYetAvailable) {
1581 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1582 s_styleNotYetAvailable->setDisplay(NONE);
1583 s_styleNotYetAvailable->font().update(m_fontSelector);
1585 element->document()->setHasNodesWithPlaceholderStyle();
1586 return s_styleNotYetAvailable;
1589 initElement(element);
1590 initForStyleResolve(element, defaultParent);
1591 m_regionForStyling = regionForStyling;
1592 if (sharingBehavior == AllowStyleSharing) {
1593 RenderStyle* sharedStyle = locateSharedStyle();
1598 m_style = RenderStyle::create();
1601 m_style->inheritFrom(m_parentStyle);
1603 m_parentStyle = style();
1604 // Make sure our fonts are initialized if we don't inherit them from our parent style.
1605 m_style->font().update(0);
1608 // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
1609 if (isAtShadowBoundary(element))
1610 m_style->setUserModify(RenderStyle::initialUserModify());
1612 if (element->isLink()) {
1613 m_style->setIsLink(true);
1614 m_style->setInsideLink(m_elementLinkState);
1617 ensureDefaultStyleSheetsForElement(element);
1619 MatchResult matchResult;
1620 if (matchingBehavior == MatchOnlyUserAgentRules)
1621 matchUARules(matchResult);
1623 matchAllRules(matchResult);
1625 applyMatchedProperties(matchResult);
1627 // Clean up our style object's display and text decorations (among other fixups).
1628 adjustRenderStyle(style(), m_parentStyle, element);
1630 initElement(0); // Clear out for the next resolve.
1632 // Now return the style.
1633 return m_style.release();
1636 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
1639 if (keyframe->properties())
1640 addMatchedProperties(result, keyframe->properties());
1645 m_style = RenderStyle::clone(elementStyle);
1647 m_lineHeightValue = 0;
1649 // We don't need to bother with !important. Since there is only ever one
1650 // decl, there's nothing to override. So just add the first properties.
1651 bool inheritedOnly = false;
1652 if (keyframe->properties())
1653 applyMatchedProperties<true>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1655 // If our font got dirtied, go ahead and update it now.
1658 // Line-height is set when we are sure we decided on the font-size
1659 if (m_lineHeightValue)
1660 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1662 // Now do rest of the properties.
1663 if (keyframe->properties())
1664 applyMatchedProperties<false>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1666 // If our font got dirtied by one of the non-essential font props,
1667 // go ahead and update it a second time.
1670 // Start loading images referenced by this style.
1671 loadPendingImages();
1673 #if ENABLE(CSS_SHADERS)
1674 // Start loading the shaders referenced by this style.
1675 loadPendingShaders();
1678 // Add all the animating properties to the keyframe.
1679 if (StylePropertySet* styleDeclaration = keyframe->properties()) {
1680 unsigned propertyCount = styleDeclaration->propertyCount();
1681 for (unsigned i = 0; i < propertyCount; ++i) {
1682 int property = styleDeclaration->propertyAt(i).id();
1683 // Timing-function within keyframes is special, because it is not animated; it just
1684 // describes the timing function between this keyframe and the next.
1685 if (property != CSSPropertyWebkitAnimationTimingFunction)
1686 keyframeValue.addProperty(property);
1690 return m_style.release();
1693 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1697 // Get the keyframesRule for this name
1698 if (!e || list.animationName().isEmpty())
1701 m_keyframesRuleMap.checkConsistency();
1703 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
1704 if (it == m_keyframesRuleMap.end())
1707 const WebKitCSSKeyframesRule* keyframesRule = it->second.get();
1709 // Construct and populate the style for each keyframe
1710 const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
1711 for (unsigned i = 0; i < keyframes.size(); ++i) {
1712 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1714 initForStyleResolve(e);
1716 const StyleKeyframe* keyframe = keyframes[i].get();
1718 KeyframeValue keyframeValue(0, 0);
1719 keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
1721 // Add this keyframe style to all the indicated key times
1723 keyframe->getKeys(keys);
1724 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1725 keyframeValue.setKey(keys[keyIndex]);
1726 list.insert(keyframeValue);
1730 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1731 int initialListSize = list.size();
1732 if (initialListSize > 0 && list[0].key() != 0) {
1733 static StyleKeyframe* zeroPercentKeyframe;
1734 if (!zeroPercentKeyframe) {
1735 zeroPercentKeyframe = StyleKeyframe::create().leakRef();
1736 zeroPercentKeyframe->setKeyText("0%");
1738 KeyframeValue keyframeValue(0, 0);
1739 keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
1740 list.insert(keyframeValue);
1743 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1744 if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1745 static StyleKeyframe* hundredPercentKeyframe;
1746 if (!hundredPercentKeyframe) {
1747 hundredPercentKeyframe = StyleKeyframe::create().leakRef();
1748 hundredPercentKeyframe->setKeyText("100%");
1750 KeyframeValue keyframeValue(1, 0);
1751 keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
1752 list.insert(keyframeValue);
1756 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1763 initForStyleResolve(e, parentStyle, pseudo);
1764 m_style = RenderStyle::create();
1767 m_style->inheritFrom(m_parentStyle);
1769 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1772 // Check UA, user and author rules.
1773 MatchResult matchResult;
1774 matchUARules(matchResult);
1776 if (m_matchAuthorAndUserStyles) {
1777 matchUserRules(matchResult, false);
1778 matchAuthorRules(matchResult, false);
1781 if (matchResult.matchedProperties.isEmpty())
1784 m_style->setStyleType(pseudo);
1786 applyMatchedProperties(matchResult);
1788 // Clean up our style object's display and text decorations (among other fixups).
1789 adjustRenderStyle(style(), parentStyle, 0);
1791 // Start loading images referenced by this style.
1792 loadPendingImages();
1794 #if ENABLE(CSS_SHADERS)
1795 // Start loading the shaders referenced by this style.
1796 loadPendingShaders();
1799 // Now return the style.
1800 return m_style.release();
1803 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1805 initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1807 m_style = RenderStyle::create();
1808 m_style->inheritFrom(m_rootElementStyle);
1810 const bool isLeft = isLeftPage(pageIndex);
1811 const bool isFirst = isFirstPage(pageIndex);
1812 const String page = pageName(pageIndex);
1815 matchPageRules(result, defaultPrintStyle, isLeft, isFirst, page);
1816 matchPageRules(result, m_userStyle.get(), isLeft, isFirst, page);
1817 // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
1818 matchPageRules(result, m_authorStyle.get(), isLeft, isFirst, page);
1819 m_lineHeightValue = 0;
1820 bool inheritedOnly = false;
1821 applyMatchedProperties<true>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1823 // If our font got dirtied, go ahead and update it now.
1826 // Line-height is set when we are sure we decided on the font-size.
1827 if (m_lineHeightValue)
1828 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1830 applyMatchedProperties<false>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1832 // Start loading images referenced by this style.
1833 loadPendingImages();
1835 #if ENABLE(CSS_SHADERS)
1836 // Start loading the shaders referenced by this style.
1837 loadPendingShaders();
1840 // Now return the style.
1841 return m_style.release();
1844 static void addIntrinsicMargins(RenderStyle* style)
1846 // Intrinsic margin value.
1847 const int intrinsicMargin = 2 * style->effectiveZoom();
1849 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1850 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1851 if (style->width().isIntrinsicOrAuto()) {
1852 if (style->marginLeft().quirk())
1853 style->setMarginLeft(Length(intrinsicMargin, Fixed));
1854 if (style->marginRight().quirk())
1855 style->setMarginRight(Length(intrinsicMargin, Fixed));
1858 if (style->height().isAuto()) {
1859 if (style->marginTop().quirk())
1860 style->setMarginTop(Length(intrinsicMargin, Fixed));
1861 if (style->marginBottom().quirk())
1862 style->setMarginBottom(Length(intrinsicMargin, Fixed));
1866 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
1873 #if ENABLE(CSS_GRID_LAYOUT)
1879 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
1880 if (!strictParsing && isFloating)
1887 case INLINE_FLEXBOX:
1889 #if ENABLE(CSS_GRID_LAYOUT)
1898 case TABLE_ROW_GROUP:
1899 case TABLE_HEADER_GROUP:
1900 case TABLE_FOOTER_GROUP:
1902 case TABLE_COLUMN_GROUP:
1908 ASSERT_NOT_REACHED();
1911 ASSERT_NOT_REACHED();
1915 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1917 // Cache our original display.
1918 style->setOriginalDisplay(style->display());
1920 if (style->display() != NONE) {
1921 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1923 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1924 // these tags to retain their display types.
1925 if (!m_checker.strictParsing() && e) {
1926 if (e->hasTagName(tdTag)) {
1927 style->setDisplay(TABLE_CELL);
1928 style->setFloating(NoFloat);
1930 else if (e->hasTagName(tableTag))
1931 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1934 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1935 if (style->whiteSpace() == KHTML_NOWRAP) {
1936 // Figure out if we are really nowrapping or if we should just
1937 // use normal instead. If the width of the cell is fixed, then
1938 // we don't actually use NOWRAP.
1939 if (style->width().isFixed())
1940 style->setWhiteSpace(NORMAL);
1942 style->setWhiteSpace(NOWRAP);
1946 // Tables never support the -webkit-* values for text-align and will reset back to the default.
1947 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1948 style->setTextAlign(TAAUTO);
1950 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1951 // fix a crash where a site tries to position these objects. They also never honor display.
1952 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1953 style->setPosition(StaticPosition);
1954 style->setDisplay(BLOCK);
1957 // Table headers with a text-align of auto will change the text-align to center.
1958 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1959 style->setTextAlign(CENTER);
1961 if (e && e->hasTagName(legendTag))
1962 style->setDisplay(BLOCK);
1964 // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1965 if (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() || (e && e->document()->documentElement() == e))
1966 style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), m_checker.strictParsing()));
1968 // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1969 // clear how that should work.
1970 if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1971 style->setDisplay(INLINE_BLOCK);
1973 // After performing the display mutation, check table rows. We do not honor position:relative on
1974 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1976 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1977 || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1978 style->position() == RelativePosition)
1979 style->setPosition(StaticPosition);
1981 // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1982 // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1983 if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1984 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1985 || style->display() == TABLE_CELL)
1986 style->setWritingMode(parentStyle->writingMode());
1988 // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1989 // of block-flow to anything other than TopToBottomWritingMode.
1990 // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1991 if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1992 style->setWritingMode(TopToBottomWritingMode);
1995 // Make sure our z-index value is only applied if the object is positioned.
1996 if (style->position() == StaticPosition)
1997 style->setHasAutoZIndex();
1999 // Auto z-index becomes 0 for the root element and transparent objects. This prevents
2000 // cases where objects that should be blended as a single unit end up with a non-transparent
2001 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
2002 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f
2003 || style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect() || style->hasFilter()
2004 #if ENABLE(OVERFLOW_SCROLLING)
2005 // Touch overflow scrolling creates a stacking context.
2006 || style->useTouchOverflowScrolling()
2009 style->setZIndex(0);
2011 // Textarea considers overflow visible as auto.
2012 if (e && e->hasTagName(textareaTag)) {
2013 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
2014 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
2017 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
2018 // tables, inline blocks, inline tables, run-ins, or shadow DOM.
2019 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
2020 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
2021 style->setTextDecorationsInEffect(style->textDecoration());
2023 style->addToTextDecorationsInEffect(style->textDecoration());
2025 // If either overflow value is not visible, change to auto.
2026 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
2027 style->setOverflowY(OMARQUEE);
2028 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
2029 style->setOverflowX(OMARQUEE);
2030 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
2031 style->setOverflowX(OAUTO);
2032 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
2033 style->setOverflowY(OAUTO);
2035 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
2036 // FIXME: Eventually table sections will support auto and scroll.
2037 if (style->display() == TABLE || style->display() == INLINE_TABLE ||
2038 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
2039 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
2040 style->setOverflowX(OVISIBLE);
2041 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
2042 style->setOverflowY(OVISIBLE);
2045 // Menulists should have visible overflow
2046 if (style->appearance() == MenulistPart) {
2047 style->setOverflowX(OVISIBLE);
2048 style->setOverflowY(OVISIBLE);
2051 // Cull out any useless layers and also repeat patterns into additional layers.
2052 style->adjustBackgroundLayers();
2053 style->adjustMaskLayers();
2055 // Do the same for animations and transitions.
2056 style->adjustAnimations();
2057 style->adjustTransitions();
2059 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
2060 // alter fonts and heights/widths.
2061 if (e && e->isFormControlElement() && style->fontSize() >= 11) {
2062 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
2063 // so we have to treat all image buttons as though they were explicitly sized.
2064 if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
2065 addIntrinsicMargins(style);
2068 // Let the theme also have a crack at adjusting the style.
2069 if (style->hasAppearance())
2070 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
2072 // If we have first-letter pseudo style, do not share this style.
2073 if (style->hasPseudoStyle(FIRST_LETTER))
2077 if (e && e->isSVGElement()) {
2078 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
2079 if (style->overflowY() == OSCROLL)
2080 style->setOverflowY(OHIDDEN);
2081 else if (style->overflowY() == OAUTO)
2082 style->setOverflowY(OVISIBLE);
2084 if (style->overflowX() == OSCROLL)
2085 style->setOverflowX(OHIDDEN);
2086 else if (style->overflowX() == OAUTO)
2087 style->setOverflowX(OVISIBLE);
2089 // Only the root <svg> element in an SVG document fragment tree honors css position
2090 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
2091 style->setPosition(RenderStyle::initialPosition());
2093 // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
2094 // not be scaled again.
2095 if (e->hasTagName(SVGNames::foreignObjectTag))
2096 style->setEffectiveZoom(RenderStyle::initialZoom());
2101 bool CSSStyleSelector::checkRegionStyle(Element* regionElement)
2103 // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
2104 // so all region rules are global by default. Verify whether that can stand or needs changing.
2106 unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size();
2107 for (unsigned i = 0; i < rulesSize; ++i) {
2108 ASSERT(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2109 if (checkRegionSelector(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2114 rulesSize = m_userStyle->m_regionSelectorsAndRuleSets.size();
2115 for (unsigned i = 0; i < rulesSize; ++i) {
2116 ASSERT(m_userStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2117 if (checkRegionSelector(m_userStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2125 void CSSStyleSelector::updateFont()
2130 checkForTextSizeAdjust();
2131 checkForGenericFamilyChange(style(), m_parentStyle);
2132 checkForZoomChange(style(), m_parentStyle);
2133 m_style->font().update(m_fontSelector);
2134 m_fontDirty = false;
2137 void CSSStyleSelector::cacheBorderAndBackground()
2139 m_hasUAAppearance = m_style->hasAppearance();
2140 if (m_hasUAAppearance) {
2141 m_borderData = m_style->border();
2142 m_backgroundData = *m_style->backgroundLayers();
2143 m_backgroundColor = m_style->backgroundColor();
2147 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
2149 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
2152 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
2154 if (!e || !e->document()->haveStylesheetsLoaded())
2157 m_checker.setCollectingRulesOnly(true);
2160 initForStyleResolve(e, 0, pseudoId);
2163 if (rulesToInclude & UAAndUserCSSRules) {
2164 // First we match rules from the user agent sheet.
2165 matchUARules(dummy);
2167 // Now we check user sheet rules.
2168 if (m_matchAuthorAndUserStyles)
2169 matchUserRules(dummy, rulesToInclude & EmptyCSSRules);
2172 if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
2173 m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
2175 // Check the rules in author sheets.
2176 matchAuthorRules(dummy, rulesToInclude & EmptyCSSRules);
2178 m_sameOriginOnly = false;
2181 m_checker.setCollectingRulesOnly(false);
2183 return m_ruleList.release();
2186 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData, const ContainerNode* scope)
2188 m_dynamicPseudo = NOPSEUDO;
2189 m_checker.clearHasUnknownPseudoElements();
2191 if (ruleData.hasFastCheckableSelector()) {
2192 // We know this selector does not include any pseudo elements.
2193 if (m_checker.pseudoStyle() != NOPSEUDO)
2195 // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
2196 // This is limited to HTML only so we don't need to check the namespace.
2197 if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
2198 if (!ruleData.hasMultipartSelector())
2200 } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
2202 if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
2204 return m_checker.fastCheckSelector(ruleData.selector(), m_element);
2208 SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled);
2209 context.elementStyle = style();
2210 context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
2211 context.scope = scope;
2212 SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo);
2213 if (match != SelectorChecker::SelectorMatches)
2215 if (m_checker.pseudoStyle() != NOPSEUDO && m_checker.pseudoStyle() != m_dynamicPseudo)
2220 bool CSSStyleSelector::checkRegionSelector(CSSSelector* regionSelector, Element* regionElement)
2222 if (!regionSelector || !regionElement)
2225 m_checker.clearHasUnknownPseudoElements();
2226 m_checker.setPseudoStyle(NOPSEUDO);
2228 for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s))
2229 if (m_checker.checkSelector(s, regionElement))
2235 bool CSSStyleSelector::determineStylesheetSelectorScopes(CSSStyleSheet* stylesheet, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes)
2237 ASSERT(!stylesheet->isLoading());
2239 const Vector<RefPtr<CSSImportRule> >& importRules = stylesheet->importRules();
2240 for (unsigned i = 0; i < importRules.size(); ++i) {
2241 if (!importRules[i]->styleSheet())
2243 if (!determineStylesheetSelectorScopes(importRules[i]->styleSheet(), idScopes, classScopes))
2247 const Vector<RefPtr<CSSRule> >& rules = stylesheet->childRules();
2248 for (unsigned i = 0; i < rules.size(); i++) {
2249 CSSRule* rule = rules[i].get();
2250 if (rule->isStyleRule()) {
2251 StyleRule* styleRule = static_cast<CSSStyleRule*>(rule)->styleRule();
2252 if (!SelectorChecker::determineSelectorScopes(styleRule->selectorList(), idScopes, classScopes))
2256 // FIXME: Media rules and maybe some others could be allowed.
2262 // -----------------------------------------------------------------
2264 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
2266 const AtomicString& selectorNamespace = selector->tag().namespaceURI();
2267 if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
2269 if (selector->m_match == CSSSelector::None)
2271 if (selector->tag() != starAtom)
2273 if (SelectorChecker::isCommonPseudoClassSelector(selector))
2275 return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
2278 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
2280 CSSSelectorList* selectorList = selector->selectorList();
2283 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2284 if (subSelector->isAttributeSelector())
2290 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
2292 // These are explicitly tested for equality in canShareStyleWithElement.
2293 return attribute == typeAttr || attribute == readonlyAttr;
2296 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
2299 // Allow certain common attributes (used in the default style) in the selectors that match the current element.
2300 if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
2302 if (selectorListContainsUncommonAttributeSelector(selector))
2304 if (selector->relation() != CSSSelector::SubSelector)
2306 selector = selector->tagHistory();
2309 for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
2310 if (selector->isAttributeSelector())
2312 if (selectorListContainsUncommonAttributeSelector(selector))
2318 RuleData::RuleData(StyleRule* rule, CSSSelector* selector, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
2320 , m_selector(selector)
2321 , m_specificity(selector->specificity())
2322 , m_position(position)
2323 , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector))
2324 , m_hasMultipartSelector(!!selector->tagHistory())
2325 , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
2326 , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector))
2327 , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector))
2328 , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin)
2329 , m_isInRegionRule(inRegionRule)
2331 SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
2336 , m_autoShrinkToFitEnabled(true)
2340 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
2342 if (selector->m_match == CSSSelector::Id)
2343 features.idsInRules.add(selector->value().impl());
2344 if (selector->isAttributeSelector())
2345 features.attrsInRules.add(selector->attribute().localName().impl());
2346 switch (selector->pseudoType()) {
2347 case CSSSelector::PseudoFirstLine:
2348 features.usesFirstLineRules = true;
2350 case CSSSelector::PseudoBefore:
2351 case CSSSelector::PseudoAfter:
2352 features.usesBeforeAfterRules = true;
2354 case CSSSelector::PseudoLink:
2355 case CSSSelector::PseudoVisited:
2356 features.usesLinkRules = true;
2363 static void collectFeaturesFromRuleData(CSSStyleSelector::Features& features, const RuleData& ruleData)
2365 bool foundSiblingSelector = false;
2366 for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
2367 collectFeaturesFromSelector(features, selector);
2369 if (CSSSelectorList* selectorList = selector->selectorList()) {
2370 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2371 if (!foundSiblingSelector && selector->isSiblingSelector())
2372 foundSiblingSelector = true;
2373 collectFeaturesFromSelector(features, subSelector);
2375 } else if (!foundSiblingSelector && selector->isSiblingSelector())
2376 foundSiblingSelector = true;
2378 if (foundSiblingSelector)
2379 features.siblingRules.append(CSSStyleSelector::RuleFeature(ruleData.rule(), ruleData.selector(), ruleData.hasDocumentSecurityOrigin()));
2380 if (ruleData.containsUncommonAttributeSelector())
2381 features.uncommonAttributeRules.append(CSSStyleSelector::RuleFeature(ruleData.rule(), ruleData.selector(), ruleData.hasDocumentSecurityOrigin()));
2384 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleData& ruleData)
2388 OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).iterator->second;
2390 rules = adoptPtr(new Vector<RuleData>);
2391 rules->append(ruleData);
2394 void RuleSet::addRule(StyleRule* rule, CSSSelector* selector, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
2396 RuleData ruleData(rule, selector, m_ruleCount++, hasDocumentSecurityOrigin, canUseFastCheckSelector, inRegionRule);
2397 collectFeaturesFromRuleData(m_features, ruleData);
2399 if (selector->m_match == CSSSelector::Id) {
2400 addToRuleSet(selector->value().impl(), m_idRules, ruleData);
2403 if (selector->m_match == CSSSelector::Class) {
2404 addToRuleSet(selector->value().impl(), m_classRules, ruleData);
2407 if (selector->isUnknownPseudoElement()) {
2408 addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData);
2411 if (SelectorChecker::isCommonPseudoClassSelector(selector)) {
2412 switch (selector->pseudoType()) {
2413 case CSSSelector::PseudoLink:
2414 case CSSSelector::PseudoVisited:
2415 case CSSSelector::PseudoAnyLink:
2416 m_linkPseudoClassRules.append(ruleData);
2418 case CSSSelector::PseudoFocus:
2419 m_focusPseudoClassRules.append(ruleData);
2422 ASSERT_NOT_REACHED();
2426 const AtomicString& localName = selector->tag().localName();
2427 if (localName != starAtom) {
2428 addToRuleSet(localName.impl(), m_tagRules, ruleData);
2431 m_universalRules.append(ruleData);
2434 void RuleSet::addPageRule(CSSPageRule* rule)
2436 m_pageRules.append(rule);
2439 void RuleSet::addRegionRule(WebKitCSSRegionRule* regionRule, bool hasDocumentSecurityOrigin)
2441 OwnPtr<RuleSet> regionRuleSet = RuleSet::create();
2442 // The region rule set should take into account the position inside the parent rule set.
2443 // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from
2444 // the stylesheet that contains the region block.
2445 regionRuleSet->m_ruleCount = m_ruleCount;
2447 // Collect the region rules into a rule set
2448 unsigned rulesSize = regionRule->ruleCount();
2449 for (unsigned i = 0; i < rulesSize; ++i) {
2450 CSSRule* regionStylingRule = regionRule->ruleAt(i);
2451 if (regionStylingRule->isStyleRule())
2452 regionRuleSet->addStyleRule(static_cast<CSSStyleRule*>(regionStylingRule)->styleRule(), hasDocumentSecurityOrigin, true, true);
2454 // Update the "global" rule count so that proper order is maintained
2455 m_ruleCount = regionRuleSet->m_ruleCount;
2457 m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), regionRuleSet.release()));
2460 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector, const ContainerNode* scope)
2464 // No media implies "all", but if a media list exists it must
2465 // contain our current medium
2466 if (sheet->mediaQueries() && !medium.eval(sheet->mediaQueries(), styleSelector))
2467 return; // the style sheet doesn't apply
2469 const Vector<RefPtr<CSSImportRule> >& importRules = sheet->importRules();
2470 for (unsigned i = 0; i < importRules.size(); ++i) {
2471 CSSImportRule* importRule = importRules[i].get();
2472 if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), styleSelector)))
2473 addRulesFromSheet(importRule->styleSheet(), medium, styleSelector, scope);
2475 bool hasDocumentSecurityOrigin = styleSelector && styleSelector->document()->securityOrigin()->canRequest(sheet->baseURL());
2477 const Vector<RefPtr<CSSRule> >& rules = sheet->childRules();
2478 for (unsigned i = 0; i < rules.size(); ++i) {
2479 CSSRule* rule = rules[i].get();
2481 ASSERT(!rule->isImportRule());
2482 if (rule->isStyleRule())
2483 addStyleRule(static_cast<CSSStyleRule*>(rule)->styleRule(), hasDocumentSecurityOrigin, !scope);
2484 else if (rule->isPageRule())
2485 addPageRule(static_cast<CSSPageRule*>(rule));
2486 else if (rule->isMediaRule()) {
2487 CSSMediaRule* mediaRule = static_cast<CSSMediaRule*>(rule);
2489 if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), styleSelector)) && mediaRule->ruleCount()) {
2490 // Traverse child elements of the @media rule.
2491 for (unsigned j = 0; j < mediaRule->ruleCount(); j++) {
2492 CSSRule* childRule = mediaRule->ruleAt(j);
2493 if (childRule->isStyleRule())
2494 addStyleRule(static_cast<CSSStyleRule*>(childRule)->styleRule(), hasDocumentSecurityOrigin, !scope);
2495 else if (childRule->isPageRule())
2496 addPageRule(static_cast<CSSPageRule*>(childRule));
2497 else if (childRule->isFontFaceRule() && styleSelector) {
2498 // Add this font face to our set.
2499 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
2502 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childRule);
2503 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2504 styleSelector->invalidateMatchedPropertiesCache();
2505 } else if (childRule->isKeyframesRule() && styleSelector) {
2506 // Add this keyframe rule to our set.
2507 // FIXME(BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
2510 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childRule));
2514 } else if (rule->isFontFaceRule() && styleSelector) {
2515 // Add this font face to our set.
2516 // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
2519 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
2520 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2521 styleSelector->invalidateMatchedPropertiesCache();
2522 } else if (rule->isKeyframesRule()) {
2523 // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
2526 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule));
2527 } else if (rule->isRegionRule() && styleSelector) {
2528 // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment.
2531 addRegionRule(static_cast<WebKitCSSRegionRule*>(rule), hasDocumentSecurityOrigin);
2534 if (m_autoShrinkToFitEnabled)
2538 void RuleSet::addStyleRule(StyleRule* rule, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule)
2540 for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2541 addRule(rule, s, hasDocumentSecurityOrigin, canUseFastCheckSelector, isInRegionRule);
2544 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
2546 RuleSet::AtomRuleMap::iterator end = map.end();
2547 for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
2548 it->second->shrinkToFit();
2551 void RuleSet::shrinkToFit()
2553 shrinkMapVectorsToFit(m_idRules);
2554 shrinkMapVectorsToFit(m_classRules);
2555 shrinkMapVectorsToFit(m_tagRules);
2556 shrinkMapVectorsToFit(m_shadowPseudoElementRules);
2557 m_linkPseudoClassRules.shrinkToFit();
2558 m_focusPseudoClassRules.shrinkToFit();
2559 m_universalRules.shrinkToFit();
2560 m_pageRules.shrinkToFit();
2563 // -------------------------------------------------------------------------------------
2564 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2566 Length CSSStyleSelector::convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2568 return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2571 Length CSSStyleSelector::convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2573 return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2576 template <bool applyFirst>
2577 void CSSStyleSelector::applyProperties(const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, bool filterRegionProperties)
2579 ASSERT(!filterRegionProperties || m_regionForStyling);
2580 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), rule);
2582 unsigned propertyCount = properties->propertyCount();
2583 for (unsigned i = 0; i < propertyCount; ++i) {
2584 const CSSProperty& current = properties->propertyAt(i);
2585 if (isImportant != current.isImportant())
2587 if (inheritedOnly && !current.isInherited()) {
2588 // If the property value is explicitly inherited, we need to apply further non-inherited properties
2589 // as they might override the value inherited here. For this reason we don't allow declarations with
2590 // explicitly inherited properties to be cached.
2591 ASSERT(!current.value()->isInheritedValue());
2594 int property = current.id();
2596 if (filterRegionProperties && !CSSStyleSelector::isValidRegionStyleProperty(property))
2600 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2601 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range);
2602 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2603 // give special priority to font-xxx, color properties, etc
2604 if (property > CSSPropertyLineHeight)
2606 // we apply line-height later
2607 if (property == CSSPropertyLineHeight) {
2608 m_lineHeightValue = current.value();
2611 applyProperty(current.id(), current.value());
2614 if (property > CSSPropertyLineHeight)
2615 applyProperty(current.id(), current.value());
2617 InspectorInstrumentation::didProcessRule(cookie);
2620 template <bool applyFirst>
2621 void CSSStyleSelector::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
2623 if (startIndex == -1)
2626 if (m_style->insideLink() != NotInsideLink) {
2627 for (int i = startIndex; i <= endIndex; ++i) {
2628 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2629 unsigned linkMatchType = matchedProperties.linkMatchType;
2630 // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2631 m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2632 m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2634 applyProperties<applyFirst>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2636 m_applyPropertyToRegularStyle = true;
2637 m_applyPropertyToVisitedLinkStyle = false;
2640 for (int i = startIndex; i <= endIndex; ++i) {
2641 const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2642 applyProperties<applyFirst>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2646 unsigned CSSStyleSelector::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
2649 return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
2652 bool operator==(const CSSStyleSelector::MatchRanges& a, const CSSStyleSelector::MatchRanges& b)
2654 return a.firstUARule == b.firstUARule
2655 && a.lastUARule == b.lastUARule
2656 && a.firstAuthorRule == b.firstAuthorRule
2657 && a.lastAuthorRule == b.lastAuthorRule
2658 && a.firstUserRule == b.firstUserRule
2659 && a.lastUserRule == b.lastUserRule;
2662 bool operator!=(const CSSStyleSelector::MatchRanges& a, const CSSStyleSelector::MatchRanges& b)
2667 bool operator==(const CSSStyleSelector::MatchedProperties& a, const CSSStyleSelector::MatchedProperties& b)
2669 return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
2672 bool operator!=(const CSSStyleSelector::MatchedProperties& a, const CSSStyleSelector::MatchedProperties& b)
2677 const CSSStyleSelector::MatchedPropertiesCacheItem* CSSStyleSelector::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
2681 MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
2682 if (it == m_matchedPropertiesCache.end())
2684 MatchedPropertiesCacheItem& cacheItem = it->second;
2686 size_t size = matchResult.matchedProperties.size();
2687 if (size != cacheItem.matchedProperties.size())
2689 for (size_t i = 0; i < size; ++i) {
2690 if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
2693 if (cacheItem.ranges != matchResult.ranges)
2698 void CSSStyleSelector::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
2700 static unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
2701 if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps) {
2702 sweepMatchedPropertiesCache();
2703 m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
2707 MatchedPropertiesCacheItem cacheItem;
2708 cacheItem.matchedProperties.append(matchResult.matchedProperties);
2709 cacheItem.ranges = matchResult.ranges;
2710 // Note that we don't cache the original RenderStyle instance. It may be further modified.
2711 // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
2712 cacheItem.renderStyle = RenderStyle::clone(style);
2713 cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
2714 m_matchedPropertiesCache.add(hash, cacheItem);
2717 void CSSStyleSelector::invalidateMatchedPropertiesCache()
2719 m_matchedPropertiesCache.clear();
2722 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
2724 // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
2725 if (element == element->document()->documentElement() && element->document()->writingModeSetOnDocumentElement())
2727 if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2729 if (style->hasAppearance())
2731 if (style->zoom() != RenderStyle::initialZoom())
2733 // The cache assumes static knowledge about which properties are inherited.
2734 if (parentStyle->hasExplicitlyInheritedProperties())
2739 void CSSStyleSelector::applyMatchedProperties(const MatchResult& matchResult)
2741 unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
2742 bool applyInheritedOnly = false;
2743 const MatchedPropertiesCacheItem* cacheItem = 0;
2744 if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
2745 // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
2746 // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
2747 // element context. This is fast and saves memory by reusing the style data structures.
2748 m_style->copyNonInheritedFrom(cacheItem->renderStyle.get());
2749 if (m_parentStyle->inheritedDataShared(cacheItem->parentRenderStyle.get())) {
2750 EInsideLink linkStatus = m_style->insideLink();
2751 // If the cache item parent style has identical inherited properties to the current parent style then the
2752 // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
2753 m_style->inheritFrom(cacheItem->renderStyle.get());
2754 // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
2755 m_style->setInsideLink(linkStatus);
2758 applyInheritedOnly = true;
2760 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
2761 // high-priority properties first, i.e., those properties that other properties depend on.
2762 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
2763 // and (4) normal important.
2764 m_lineHeightValue = 0;
2765 applyMatchedProperties<true>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
2766 applyMatchedProperties<true>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
2767 applyMatchedProperties<true>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
2768 applyMatchedProperties<true>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2770 if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) {
2772 applyInheritedOnly = false;
2775 // If our font got dirtied, go ahead and update it now.
2778 // Line-height is set when we are sure we decided on the font-size.
2779 if (m_lineHeightValue)
2780 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2782 // Many properties depend on the font. If it changes we just apply all properties.
2783 if (cacheItem && cacheItem->renderStyle->fontDescription() != m_style->fontDescription())
2784 applyInheritedOnly = false;
2786 // Now do the normal priority UA properties.
2787 applyMatchedProperties<false>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2789 // Cache our border and background so that we can examine them later.
2790 cacheBorderAndBackground();
2792 // Now do the author and user normal priority properties and all the !important properties.
2793 applyMatchedProperties<false>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
2794 applyMatchedProperties<false>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
2795 applyMatchedProperties<false>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
2796 applyMatchedProperties<false>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2798 loadPendingImages();
2800 #if ENABLE(CSS_SHADERS)
2801 loadPendingShaders();
2804 ASSERT(!m_fontDirty);
2806 if (cacheItem || !cacheHash)
2808 if (!isCacheableInMatchedPropertiesCache(m_element, m_style.get(), m_parentStyle))
2810 addToMatchedPropertiesCache(m_style.get(), m_parentStyle, cacheHash, matchResult);
2813 static inline bool comparePageRules(const CSSPageRule* r1, const CSSPageRule* r2)
2815 return r1->selector()->specificity() < r2->selector()->specificity();
2818 void CSSStyleSelector::matchPageRules(MatchResult& result, RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2823 Vector<CSSPageRule*> matchedPageRules;
2824 matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
2825 if (matchedPageRules.isEmpty())
2828 std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
2830 for (unsigned i = 0; i < matchedPageRules.size(); i++)
2831 addMatchedProperties(result, matchedPageRules[i]->properties());
2834 void CSSStyleSelector::matchPageRulesForList(Vector<CSSPageRule*>& matchedRules, const Vector<CSSPageRule*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2836 unsigned size = rules.size();
2837 for (unsigned i = 0; i < size; ++i) {
2838 CSSPageRule* rule = rules[i];
2839 const AtomicString& selectorLocalName = rule->selector()->tag().localName();
2840 if (selectorLocalName != starAtom && selectorLocalName != pageName)
2842 CSSSelector::PseudoType pseudoType = rule->selector()->pseudoType();
2843 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2844 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2845 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2848 // If the rule has no properties to apply, then ignore it.
2849 StylePropertySet* properties = rule->properties();
2850 if (!properties || properties->isEmpty())
2853 // Add this rule to our list of matched rules.
2854 matchedRules.append(rule);
2858 bool CSSStyleSelector::isLeftPage(int pageIndex) const
2860 bool isFirstPageLeft = false;
2861 if (!m_rootElementStyle->isLeftToRightDirection())
2862 isFirstPageLeft = true;
2864 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
2867 bool CSSStyleSelector::isFirstPage(int pageIndex) const
2869 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
2870 return (!pageIndex);
2873 String CSSStyleSelector::pageName(int /* pageIndex */) const
2875 // FIXME: Implement page index to page name mapping.
2879 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, CSSRuleList* ruleList)
2881 unsigned size = ruleList->length();
2882 for (unsigned i = 0; i < size; ++i) {
2883 CSSRule* cssRule = ruleList->item(i);
2884 if (cssRule->isImportRule())
2885 collectCSSOMWrappers(wrapperMap, static_cast<CSSImportRule*>(cssRule)->styleSheet());
2886 else if (cssRule->isMediaRule())
2887 collectCSSOMWrappers(wrapperMap, static_cast<CSSMediaRule*>(cssRule)->cssRules());
2888 else if (cssRule->isRegionRule())
2889 collectCSSOMWrappers(wrapperMap, static_cast<WebKitCSSRegionRule*>(cssRule)->cssRules());
2890 else if (cssRule->isStyleRule()) {
2891 CSSStyleRule* cssStyleRule = static_cast<CSSStyleRule*>(cssRule);
2892 wrapperMap.add(cssStyleRule->styleRule(), cssStyleRule);
2897 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, CSSStyleSheet* styleSheet)
2901 collectCSSOMWrappers(wrapperMap, styleSheet->cssRules().get());
2904 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, Document* document)
2906 const Vector<RefPtr<StyleSheet> >& styleSheets = document->styleSheets()->vector();
2907 for (unsigned i = 0; i < styleSheets.size(); ++i) {
2908 StyleSheet* styleSheet = styleSheets[i].get();
2909 if (!styleSheet->isCSSStyleSheet())
2911 collectCSSOMWrappers(wrapperMap, static_cast<CSSStyleSheet*>(styleSheet));
2913 collectCSSOMWrappers(wrapperMap, document->pageUserSheet());
2916 CSSStyleRule* CSSStyleSelector::ensureFullCSSOMWrapperForInspector(StyleRule* rule)
2918 if (m_styleRuleToCSSOMWrapperMap.isEmpty()) {
2919 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, simpleDefaultStyleSheet);
2920 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, defaultStyleSheet);
2921 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, quirksStyleSheet);
2922 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, svgStyleSheet);
2923 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, mathMLStyleSheet);
2924 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, mediaControlsStyleSheet);
2925 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, fullscreenStyleSheet);
2927 collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, document());
2929 return m_styleRuleToCSSOMWrapperMap.get(rule).get();
2932 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue* value, RenderStyle* style)
2935 initForStyleResolve(0, style);
2937 applyPropertyToCurrentStyle(id, value);
2940 void CSSStyleSelector::applyPropertyToCurrentStyle(int id, CSSValue* value)
2943 applyProperty(id, value);
2946 inline bool isValidVisitedLinkProperty(int id)
2948 switch(static_cast<CSSPropertyID>(id)) {
2949 case CSSPropertyBackgroundColor:
2950 case CSSPropertyBorderLeftColor:
2951 case CSSPropertyBorderRightColor:
2952 case CSSPropertyBorderTopColor:
2953 case CSSPropertyBorderBottomColor:
2954 case CSSPropertyColor:
2955 case CSSPropertyOutlineColor:
2956 case CSSPropertyWebkitColumnRuleColor:
2957 case CSSPropertyWebkitTextEmphasisColor:
2958 case CSSPropertyWebkitTextFillColor:
2959 case CSSPropertyWebkitTextStrokeColor:
2960 // Also allow shorthands so that inherit/initial still work.
2961 case CSSPropertyBackground:
2962 case CSSPropertyBorderLeft:
2963 case CSSPropertyBorderRight:
2964 case CSSPropertyBorderTop:
2965 case CSSPropertyBorderBottom:
2966 case CSSPropertyOutline:
2967 case CSSPropertyWebkitColumnRule:
2969 case CSSPropertyFill:
2970 case CSSPropertyStroke:
2980 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
2981 // FIXME: add incremental support for other region styling properties.
2982 inline bool CSSStyleSelector::isValidRegionStyleProperty(int id)
2984 switch (static_cast<CSSPropertyID>(id)) {
2985 case CSSPropertyBackgroundColor:
2994 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2995 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2996 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2997 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2998 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2999 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
3000 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
3001 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
3002 bool CSSStyleSelector::useSVGZoomRules()
3004 return m_element && m_element->isSVGElement();
3007 #if ENABLE(CSS_GRID_LAYOUT)
3009 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, CSSStyleSelector* selector, Length& length)
3011 Length workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
3012 if (workingLength.isUndefined())
3015 if (primitiveValue->isLength())
3016 workingLength.setQuirk(primitiveValue->isQuirkValue());
3018 length = workingLength;
3022 static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, CSSStyleSelector* selector)
3025 if (value->isPrimitiveValue()) {
3026 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3027 if (primitiveValue->getIdent() == CSSValueNone) {
3028 lengths.append(Length(Undefined));
3034 if (value->isValueList()) {
3035 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3036 CSSValue* currValue = i.value();
3037 if (!currValue->isPrimitiveValue())
3041 if (!createGridTrackBreadth(static_cast<CSSPrimitiveValue*>(currValue), selector, length))
3044 lengths.append(length);
3053 static bool createGridPosition(CSSValue* value, Length& position)
3055 // For now, we only accept: <integer> | 'auto'
3056 if (!value->isPrimitiveValue())
3059 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3060 if (primitiveValue->getIdent() == CSSValueAuto)
3063 ASSERT(primitiveValue->isNumber());
3064 position.setValue(primitiveValue->getIntValue());
3069 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
3071 bool isInherit = m_parentNode && value->isInheritedValue();
3072 bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
3074 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
3076 if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
3077 // Limit the properties that can be applied to only the ones honored by :visited.
3081 CSSPropertyID property = static_cast<CSSPropertyID>(id);
3083 if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(property))
3084 m_parentStyle->setHasExplicitlyInheritedProperties();
3086 // check lookup table for implementations and use when available
3087 const PropertyHandler& handler = m_applyProperty.propertyHandler(property);
3088 if (handler.isValid()) {
3090 handler.applyInheritValue(this);
3092 handler.applyInitialValue(this);
3094 handler.applyValue(this, value);
3098 CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
3100 float zoomFactor = m_style->effectiveZoom();
3102 // What follows is a list that maps the CSS properties into their corresponding front-end
3103 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
3104 // are only hit when mapping "inherit" or "initial" into front-end values.
3107 case CSSPropertyContent:
3108 // list of string, uri, counter, attr, i
3110 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
3111 // note is a reminder that eventually "inherit" needs to be supported.
3114 m_style->clearContent();
3118 if (!value->isValueList())
3121 bool didSet = false;
3122 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3123 CSSValue* item = i.value();
3124 if (item->isImageGeneratorValue()) {
3125 m_style->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
3127 #if ENABLE(CSS_IMAGE_SET)
3128 } else if (item->isImageSetValue()) {
3129 m_style->setContent(setOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageSetValue*>(item)), didSet);
3134 if (item->isImageValue()) {
3135 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(item)), didSet);
3140 if (!item->isPrimitiveValue())
3143 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
3145 if (contentValue->isString()) {
3146 m_style->setContent(contentValue->getStringValue().impl(), didSet);
3148 } else if (contentValue->isAttr()) {
3149 // FIXME: Can a namespace be specified for an attr(foo)?
3150 if (m_style->styleType() == NOPSEUDO)
3151 m_style->setUnique();
3153 m_parentStyle->setUnique();
3154 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
3155 const AtomicString& value = m_element->getAttribute(attr);
3156 m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
3158 // register the fact that the attribute value affects the style
3159 m_features.attrsInRules.add(attr.localName().impl());
3160 } else if (contentValue->isCounter()) {
3161 Counter* counterValue = contentValue->getCounterValue();
3162 EListStyleType listStyleType = NoneListStyle;
3163 int listStyleIdent = counterValue->listStyleIdent();
3164 if (listStyleIdent != CSSValueNone)
3165 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
3166 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
3167 m_style->setContent(counter.release(), didSet);
3170 switch (contentValue->getIdent()) {
3171 case CSSValueOpenQuote:
3172 m_style->setContent(OPEN_QUOTE, didSet);
3175 case CSSValueCloseQuote:
3176 m_style->setContent(CLOSE_QUOTE, didSet);
3179 case CSSValueNoOpenQuote:
3180 m_style->setContent(NO_OPEN_QUOTE, didSet);
3183 case CSSValueNoCloseQuote:
3184 m_style->setContent(NO_CLOSE_QUOTE, didSet);
3188 // normal and none do not have any effect.
3194 m_style->clearContent();
3197 case CSSPropertyQuotes:
3200 m_style->setQuotes(m_parentStyle->quotes());
3204 m_style->setQuotes(0);
3207 if (value->isValueList()) {
3208 CSSValueList* list = static_cast<CSSValueList*>(value);
3209 QuotesData* data = QuotesData::create(list->length());
3211 return; // Out of memory
3212 String* quotes = data->data();
3213 for (CSSValueListIterator i = list; i.hasMore(); i.advance()) {
3214 CSSValue* item = i.value();
3215 ASSERT(item->isPrimitiveValue());
3216 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3217 ASSERT(primitiveValue->isString());
3218 quotes[i.index()] = primitiveValue->getStringValue();
3220 m_style->setQuotes(adoptRef(data));
3221 } else if (primitiveValue) {
3222 ASSERT(primitiveValue->isIdent());
3223 if (primitiveValue->getIdent() == CSSValueNone)
3224 m_style->setQuotes(adoptRef(QuotesData::create(0)));
3227 case CSSPropertyFontFamily: {
3228 // list of strings and ids
3230 FontDescription parentFontDescription = m_parentStyle->fontDescription();
3231 FontDescription fontDescription = m_style->fontDescription();
3232 fontDescription.setGenericFamily(parentFontDescription.genericFamily());
3233 fontDescription.setFamily(parentFontDescription.firstFamily());
3234 fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
3235 setFontDescription(fontDescription);
3237 } else if (isInitial) {
3238 FontDescription initialDesc = FontDescription();
3239 FontDescription fontDescription = m_style->fontDescription();
3240 // We need to adjust the size to account for the generic family change from monospace
3241 // to non-monospace.
3242 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
3243 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
3244 fontDescription.setGenericFamily(initialDesc.genericFamily());
3245 if (!initialDesc.firstFamily().familyIsEmpty())
3246 fontDescription.setFamily(initialDesc.firstFamily());
3247 setFontDescription(fontDescription);
3251 if (!value->isValueList())
3253 FontDescription fontDescription = m_style->fontDescription();
3254 FontFamily& firstFamily = fontDescription.firstFamily();
3255 FontFamily* currFamily = 0;
3257 // Before mapping in a new font-family property, we should reset the generic family.
3258 bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
3259 fontDescription.setGenericFamily(FontDescription::NoFamily);
3261 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3262 CSSValue* item = i.value();
3263 if (!item->isPrimitiveValue())
3265 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
3267 Settings* settings = m_checker.document()->settings();
3268 if (contentValue->isString())
3269 face = contentValue->getStringValue();
3270 else if (settings) {
3271 switch (contentValue->getIdent()) {
3272 case CSSValueWebkitBody:
3273 face = settings->standardFontFamily();
3277 fontDescription.setGenericFamily(FontDescription::SerifFamily);
3279 case CSSValueSansSerif:
3280 face = sansSerifFamily;
3281 fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3283 case CSSValueCursive:
3284 face = cursiveFamily;
3285 fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3287 case CSSValueFantasy:
3288 face = fantasyFamily;
3289 fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3291 case CSSValueMonospace:
3292 face = monospaceFamily;
3293 fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3295 case CSSValueWebkitPictograph:
3296 face = pictographFamily;
3297 fontDescription.setGenericFamily(FontDescription::PictographFamily);
3302 if (!face.isEmpty()) {
3304 // Filling in the first family.
3305 firstFamily.setFamily(face);
3306 firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
3307 currFamily = &firstFamily;
3308 fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
3310 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
3311 newFamily->setFamily(face);
3312 currFamily->appendFamily(newFamily);
3313 currFamily = newFamily.get();
3318 // We can't call useFixedDefaultSize() until all new font families have been added
3319 // If currFamily is non-zero then we set at least one family on this description.
3321 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
3322 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
3324 setFontDescription(fontDescription);
3328 // shorthand properties
3329 case CSSPropertyBackground:
3331 m_style->clearBackgroundLayers();
3332 m_style->setBackgroundColor(Color());
3334 else if (isInherit) {
3335 m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3336 m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3339 case CSSPropertyWebkitMask:
3341 m_style->clearMaskLayers();
3343 m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
3345 case CSSPropertyFont:
3347 FontDescription fontDescription = m_parentStyle->fontDescription();
3348 m_style->setLineHeight(m_parentStyle->lineHeight());
3349 m_lineHeightValue = 0;
3350 setFontDescription(fontDescription);
3351 } else if (isInitial) {
3352 Settings* settings = m_checker.document()->settings();
3353 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3356 FontDescription fontDescription;
3357 fontDescription.setGenericFamily(FontDescription::StandardFamily);
3358 fontDescription.setRenderingMode(settings->fontRenderingMode());
3359 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3360 const AtomicString& standardFontFamily = m_checker.document()->settings()->standardFontFamily();
3361 if (!standardFontFamily.isEmpty()) {
3362 fontDescription.firstFamily().setFamily(standardFontFamily);
3363 fontDescription.firstFamily().appendFamily(0);
3365 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3366 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueMedium, false));
3367 m_style->setLineHeight(RenderStyle::initialLineHeight());
3368 m_lineHeightValue = 0;
3369 setFontDescription(fontDescription);
3370 } else if (primitiveValue) {
3371 m_style->setLineHeight(RenderStyle::initialLineHeight());
3372 m_lineHeightValue = 0;
3374 FontDescription fontDescription;
3375 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3377 // Double-check and see if the theme did anything. If not, don't bother updating the font.
3378 if (fontDescription.isAbsoluteSize()) {
3379 // Make sure the rendering mode and printer font settings are updated.
3380 Settings* settings = m_checker.document()->settings();
3381 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3384 fontDescription.setRenderingMode(settings->fontRenderingMode());
3385 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3387 // Handle the zoom factor.
3388 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3389 setFontDescription(fontDescription);
3391 } else if (value->isFontValue()) {
3392 FontValue *font = static_cast<FontValue*>(value);
3393 if (!font->style || !font->variant || !font->weight ||
3394 !font->size || !font->lineHeight || !font->family)
3396 applyProperty(CSSPropertyFontStyle, font->style.get());
3397 applyProperty(CSSPropertyFontVariant, font->variant.get());
3398 applyProperty(CSSPropertyFontWeight, font->weight.get());
3399 // The previous properties can dirty our font but they don't try to read the font's
3400 // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3401 // need query the dirtied font's x-height to get the computed size. To be safe in this
3402 // case, let's just update the font now.
3404 applyProperty(CSSPropertyFontSize, font->size.get());
3406 m_lineHeightValue = font->lineHeight.get();
3408 applyProperty(CSSPropertyFontFamily, font->family.get());
3413 case CSSPropertyTextShadow:
3414 case CSSPropertyBoxShadow:
3415 case CSSPropertyWebkitBoxShadow: {
3417 if (id == CSSPropertyTextShadow)
3418 return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
3419 return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
3421 if (isInitial || primitiveValue) // initial | none
3422 return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
3424 if (!value->isValueList())
3427 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3428 CSSValue* currValue = i.value();
3429 if (!currValue->isShadowValue())
3431 ShadowValue* item = static_cast<ShadowValue*>(currValue);
3432 int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3433 int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3434 int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3435 int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3436 ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3439 color = colorFromPrimitiveValue(item->color.get());
3440 OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3441 if (id == CSSPropertyTextShadow)
3442 m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3444 m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3448 case CSSPropertyWebkitBoxReflect: {
3449 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3450 if (primitiveValue) {
3451 m_style->setBoxReflect(RenderStyle::initialBoxReflect());
3455 if (!value->isReflectValue())
3458 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3459 RefPtr<StyleReflection> reflection = StyleReflection::create();
3460 reflection->setDirection(reflectValue->direction());
3461 if (reflectValue->offset())
3462 reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(style(), m_rootElementStyle, zoomFactor));
3463 NinePieceImage mask;
3464 mask.setMaskDefaults();
3465 mapNinePieceImage(property, reflectValue->mask(), mask);
3466 reflection->setMask(mask);
3468 m_style->setBoxReflect(reflection.release());
3471 case CSSPropertyOpacity:
3472 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(opacity, Opacity)
3474 case CSSPropertySrc: // Only used in @font-face rules.
3476 case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3478 case CSSPropertyWebkitColumnRule:
3480 m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
3481 m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
3482 m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
3485 m_style->resetColumnRule();
3487 case CSSPropertyWebkitMarquee:
3488 if (!m_parentNode || !value->isInheritedValue())
3490 m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
3491 m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
3492 m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
3493 m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
3494 m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
3496 case CSSPropertyWebkitMarqueeRepetition: {
3497 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3498 if (!primitiveValue)
3500 if (primitiveValue->getIdent() == CSSValueInfinite)
3501 m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
3502 else if (primitiveValue->isNumber())
3503 m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
3506 case CSSPropertyWebkitMarqueeSpeed: {
3507 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3508 if (!primitiveValue)
3510 if (int ident = primitiveValue->getIdent()) {
3513 m_style->setMarqueeSpeed(500); // 500 msec.
3515 case CSSValueNormal:
3516 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
3519 m_style->setMarqueeSpeed(10); // 10msec. Super fast.
3522 } else if (primitiveValue->isTime())
3523 m_style->setMarqueeSpeed(primitiveValue->computeTime<int, CSSPrimitiveValue::Milliseconds>());
3524 else if (primitiveValue->isNumber()) // For scrollamount support.
3525 m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3528 case CSSPropertyWebkitMarqueeIncrement: {
3529 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3530 if (!primitiveValue)
3532 if (primitiveValue->getIdent()) {
3533 switch (primitiveValue->getIdent()) {
3535 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3537 case CSSValueNormal:
3538 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3541 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3545 Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle);
3546 if (!marqueeLength.isUndefined())
3547 m_style->setMarqueeIncrement(marqueeLength);
3551 case CSSPropertyWebkitLineClamp:
3552 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(lineClamp, LineClamp)
3554 case CSSPropertyWebkitLocale: {
3555 HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3556 if (primitiveValue->getIdent() == CSSValueAuto)
3557 m_style->setLocale(nullAtom);
3559 m_style->setLocale(primitiveValue->getStringValue());
3560 FontDescription fontDescription = m_style->fontDescription();
3561 fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
3562 setFontDescription(fontDescription);
3565 case CSSPropertyWebkitTextSizeAdjust: {
3566 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
3567 if (!primitiveValue || !primitiveValue->getIdent())
3569 setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
3572 #if ENABLE(DASHBOARD_SUPPORT)
3573 case CSSPropertyWebkitDashboardRegion: {
3574 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3575 if (!primitiveValue)
3578 if (primitiveValue->getIdent() == CSSValueNone) {
3579 m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
3583 DashboardRegion *region = primitiveValue->getDashboardRegionValue();
3587 DashboardRegion *first = region;
3589 Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
3590 Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
3591 Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
3592 Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
3594 if (top.isUndefined())
3596 if (right.isUndefined())
3598 if (bottom.isUndefined())
3600 if (left.isUndefined())
3603 if (region->m_isCircle)
3604 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3605 else if (region->m_isRectangle)
3606 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3607 region = region->m_next.get();
3610 m_element->document()->setHasDashboardRegions(true);
3615 case CSSPropertyWebkitTextStrokeWidth: {
3616 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3618 switch (primitiveValue->getIdent()) {
3620 case CSSValueMedium:
3621 case CSSValueThick: {
3622 double result = 1.0 / 48;
3623 if (primitiveValue->getIdent() == CSSValueMedium)
3625 else if (primitiveValue->getIdent() == CSSValueThick)
3627 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3631 width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3634 m_style->setTextStrokeWidth(width);
3637 case CSSPropertyWebkitTransform: {
3638 HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3639 TransformOperations operations;
3640 createTransformOperations(value, style(), m_rootElementStyle, operations);
3641 m_style->setTransform(operations);
3644 case CSSPropertyWebkitPerspective: {
3645 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3646 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3647 m_style->setPerspective(0);
3651 float perspectiveValue;
3652 if (primitiveValue->isLength())
3653 perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3654 else if (primitiveValue->isNumber()) {
3655 // For backward compatibility, treat valueless numbers as px.
3656 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3660 if (perspectiveValue >= 0.0f)
3661 m_style->setPerspective(perspectiveValue);
3664 case CSSPropertyWebkitAnimation:
3666 m_style->clearAnimations();
3668 m_style->inheritAnimations(m_parentStyle->animations());
3670 case CSSPropertyWebkitTransition:
3672 m_style->clearTransitions();
3674 m_style->inheritTransitions(m_parentStyle->transitions());
3676 case CSSPropertyPointerEvents:
3678 #if ENABLE(DASHBOARD_SUPPORT)
3679 // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
3680 // pointer-events property by not applying it in Dashboard.
3681 Settings* settings = m_checker.document()->settings();
3682 if (settings && settings->usesDashboardBackwardCompatibilityMode())
3685 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(pointerEvents, PointerEvents)
3688 #if ENABLE(TOUCH_EVENTS)
3689 case CSSPropertyWebkitTapHighlightColor: {
3690 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
3691 if (!primitiveValue)
3694 Color col = colorFromPrimitiveValue(primitiveValue);
3695 m_style->setTapHighlightColor(col);
3699 #if ENABLE(OVERFLOW_SCROLLING)
3700 case CSSPropertyWebkitOverflowScrolling: {
3701 HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
3702 if (!primitiveValue)
3704 m_style->setUseTouchOverflowScrolling(primitiveValue->getIdent() == CSSValueTouch);
3708 case CSSPropertyInvalid:
3710 // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
3711 case CSSPropertyWebkitBorderEnd:
3712 case CSSPropertyWebkitBorderEndColor:
3713 case CSSPropertyWebkitBorderEndStyle:
3714 case CSSPropertyWebkitBorderEndWidth:
3715 case CSSPropertyWebkitBorderStart:
3716 case CSSPropertyWebkitBorderStartColor:
3717 case CSSPropertyWebkitBorderStartStyle:
3718 case CSSPropertyWebkitBorderStartWidth:
3719 case CSSPropertyWebkitBorderBefore:
3720 case CSSPropertyWebkitBorderBeforeColor:
3721 case CSSPropertyWebkitBorderBeforeStyle:
3722 case CSSPropertyWebkitBorderBeforeWidth:
3723 case CSSPropertyWebkitBorderAfter:
3724 case CSSPropertyWebkitBorderAfterColor:
3725 case CSSPropertyWebkitBorderAfterStyle:
3726 case CSSPropertyWebkitBorderAfterWidth:
3727 case CSSPropertyWebkitMarginEnd:
3728 case CSSPropertyWebkitMarginStart:
3729 case CSSPropertyWebkitMarginBefore:
3730 case CSSPropertyWebkitMarginAfter:
3731 case CSSPropertyWebkitMarginCollapse:
3732 case CSSPropertyWebkitMarginBeforeCollapse:
3733 case CSSPropertyWebkitMarginTopCollapse:
3734 case CSSPropertyWebkitMarginAfterCollapse:
3735 case CSSPropertyWebkitMarginBottomCollapse:
3736 case CSSPropertyWebkitPaddingEnd:
3737 case CSSPropertyWebkitPaddingStart:
3738 case CSSPropertyWebkitPaddingBefore:
3739 case CSSPropertyWebkitPaddingAfter:
3740 case CSSPropertyWebkitLogicalWidth:
3741 case CSSPropertyWebkitLogicalHeight:
3742 case CSSPropertyWebkitMinLogicalWidth:
3743 case CSSPropertyWebkitMinLogicalHeight:
3744 case CSSPropertyWebkitMaxLogicalWidth:
3745 case CSSPropertyWebkitMaxLogicalHeight:
3747 int newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3748 ASSERT(newId != id);
3749 return applyProperty(newId, value);
3751 case CSSPropertyFontStretch:
3752 case CSSPropertyPage:
3753 case CSSPropertyTextLineThrough:
3754 case CSSPropertyTextLineThroughColor:
3755 case CSSPropertyTextLineThroughMode:
3756 case CSSPropertyTextLineThroughStyle:
3757 case CSSPropertyTextLineThroughWidth:
3758 case CSSPropertyTextOverline:
3759 case CSSPropertyTextOverlineColor:
3760 case CSSPropertyTextOverlineMode:
3761 case CSSPropertyTextOverlineStyle:
3762 case CSSPropertyTextOverlineWidth:
3763 case CSSPropertyTextUnderline:
3764 case CSSPropertyTextUnderlineColor:
3765 case CSSPropertyTextUnderlineMode:
3766 case CSSPropertyTextUnderlineStyle:
3767 case CSSPropertyTextUnderlineWidth:
3768 case CSSPropertyWebkitFontSizeDelta:
3769 case CSSPropertyWebkitTextDecorationsInEffect:
3770 case CSSPropertyWebkitTextStroke:
3771 case CSSPropertyWebkitTextEmphasis:
3774 // CSS Text Layout Module Level 3: Vertical writing support
3775 case CSSPropertyWebkitWritingMode: {
3776 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
3777 // FIXME: It is not ok to modify document state while applying style.
3778 if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
3779 m_element->document()->setWritingModeSetOnDocumentElement(true);
3780 FontDescription fontDescription = m_style->fontDescription();
3781 fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
3782 setFontDescription(fontDescription);
3786 case CSSPropertyWebkitLineBoxContain: {
3787 HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
3788 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3789 m_style->setLineBoxContain(LineBoxContainNone);
3793 if (!value->isCSSLineBoxContainValue())
3796 CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
3797 m_style->setLineBoxContain(lineBoxContainValue->value());
3801 case CSSPropertyWebkitShapeInside:
3802 HANDLE_INHERIT_AND_INITIAL(wrapShapeInside, WrapShapeInside);
3803 if (!primitiveValue)
3805 if (primitiveValue->getIdent() == CSSValueAuto)
3806 m_style->setWrapShapeInside(0);
3807 else if (primitiveValue->isShape())
3808 m_style->setWrapShapeInside(primitiveValue->getShapeValue());
3811 case CSSPropertyWebkitShapeOutside:
3812 HANDLE_INHERIT_AND_INITIAL(wrapShapeOutside, WrapShapeOutside);
3813 if (!primitiveValue)
3815 if (primitiveValue->getIdent() == CSSValueAuto)
3816 m_style->setWrapShapeOutside(0);
3817 else if (primitiveValue->isShape())
3818 m_style->setWrapShapeOutside(primitiveValue->getShapeValue());
3821 // CSS Fonts Module Level 3
3822 case CSSPropertyWebkitFontFeatureSettings: {
3823 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
3824 setFontDescription(m_style->fontDescription().makeNormalFeatureSettings());
3828 if (!value->isValueList())
3831 FontDescription fontDescription = m_style->fontDescription();
3832 CSSValueList* list = static_cast<CSSValueList*>(value);
3833 RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
3834 int len = list->length();
3835 for (int i = 0; i < len; ++i) {
3836 CSSValue* item = list->itemWithoutBoundsCheck(i);
3837 if (!item->isFontFeatureValue())
3839 FontFeatureValue* feature = static_cast<FontFeatureValue*>(item);
3840 settings->append(FontFeature(feature->tag(), feature->value()));
3842 fontDescription.setFeatureSettings(settings.release());
3843 setFontDescription(fontDescription);
3847 #if ENABLE(CSS_FILTERS)
3848 case CSSPropertyWebkitFilter: {
3849 HANDLE_INHERIT_AND_INITIAL(filter, Filter);
3850 FilterOperations operations;
3851 if (createFilterOperations(value, style(), m_rootElementStyle, operations))
3852 m_style->setFilter(operations);
3856 #if ENABLE(CSS_GRID_LAYOUT)
3857 case CSSPropertyWebkitGridColumns: {
3858 Vector<Length> lengths;
3859 if (!createGridTrackList(value, lengths, this))
3861 m_style->setGridColumns(lengths);
3864 case CSSPropertyWebkitGridRows: {
3865 Vector<Length> lengths;
3866 if (!createGridTrackList(value, lengths, this))
3868 m_style->setGridRows(lengths);
3872 case CSSPropertyWebkitGridColumn: {
3874 if (!createGridPosition(value, column))
3876 m_style->setGridItemColumn(column);
3879 case CSSPropertyWebkitGridRow: {
3881 if (!createGridPosition(value, row))
3883 m_style->setGridItemRow(row);
3888 // These properties are implemented in the CSSStyleApplyProperty lookup table.
3889 case CSSPropertyBackgroundAttachment: