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 "ContentData.h"
35 #include "CounterContent.h"
36 #include "CSSBorderImageValue.h"
37 #include "CSSCursorImageValue.h"
38 #include "CSSFontFaceRule.h"
39 #include "CSSFontSelector.h"
40 #include "CSSImportRule.h"
41 #include "CSSLineBoxContainValue.h"
42 #include "CSSMediaRule.h"
43 #include "CSSPageRule.h"
44 #include "CSSParser.h"
45 #include "CSSPrimitiveValueMappings.h"
46 #include "CSSPropertyNames.h"
47 #include "CSSReflectValue.h"
48 #include "CSSRuleList.h"
49 #include "CSSSelector.h"
50 #include "CSSSelectorList.h"
51 #include "CSSStyleApplyProperty.h"
52 #include "CSSStyleRule.h"
53 #include "CSSStyleSheet.h"
54 #include "CSSTimingFunctionValue.h"
55 #include "CSSValueList.h"
56 #include "CursorList.h"
57 #include "FontFamilyValue.h"
58 #include "FontFeatureValue.h"
59 #include "FontValue.h"
61 #include "FrameSelection.h"
62 #include "FrameView.h"
63 #include "HTMLDocument.h"
64 #include "HTMLElement.h"
65 #include "HTMLInputElement.h"
66 #include "HTMLNames.h"
67 #include "HTMLProgressElement.h"
68 #include "HTMLTextAreaElement.h"
69 #include "InspectorInstrumentation.h"
70 #include "KeyframeList.h"
72 #include "LocaleToScriptMapping.h"
73 #include "Matrix3DTransformOperation.h"
74 #include "MatrixTransformOperation.h"
75 #include "MediaList.h"
76 #include "MediaQueryEvaluator.h"
77 #include "NodeRenderStyle.h"
79 #include "PageGroup.h"
81 #include "PerspectiveTransformOperation.h"
82 #include "QuotesData.h"
84 #include "RenderScrollbar.h"
85 #include "RenderScrollbarTheme.h"
86 #include "RenderStyleConstants.h"
87 #include "RenderTheme.h"
88 #include "RotateTransformOperation.h"
89 #include "ScaleTransformOperation.h"
90 #include "SecurityOrigin.h"
92 #include "ShadowData.h"
93 #include "ShadowValue.h"
94 #include "SkewTransformOperation.h"
95 #include "StyleCachedImage.h"
96 #include "StylePendingImage.h"
97 #include "StyleGeneratedImage.h"
98 #include "StyleSheetList.h"
100 #include "TransformationMatrix.h"
101 #include "TranslateTransformOperation.h"
102 #include "UserAgentStyleSheets.h"
103 #include "WebKitCSSKeyframeRule.h"
104 #include "WebKitCSSKeyframesRule.h"
105 #include "WebKitCSSRegionRule.h"
106 #include "WebKitCSSTransformValue.h"
107 #include "WebKitFontFamilyNames.h"
108 #include "XMLNames.h"
109 #include <wtf/StdLibExtras.h>
110 #include <wtf/Vector.h>
112 #if ENABLE(CSS_FILTERS)
113 #include "FilterOperation.h"
114 #include "WebKitCSSFilterValue.h"
117 #if ENABLE(DASHBOARD_SUPPORT)
118 #include "DashboardRegion.h"
122 #include "SVGNames.h"
125 #if ENABLE(CSS_SHADERS)
126 #include "CustomFilterOperation.h"
127 #include "StyleCachedShader.h"
128 #include "StyleCustomFilterProgram.h"
129 #include "StylePendingShader.h"
130 #include "StyleShader.h"
131 #include "WebKitCSSShaderValue.h"
138 using namespace HTMLNames;
140 #define HANDLE_INHERIT(prop, Prop) \
142 m_style->set##Prop(m_parentStyle->prop()); \
146 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
147 HANDLE_INHERIT(prop, Prop) \
149 m_style->set##Prop(RenderStyle::initial##Prop()); \
153 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
154 HANDLE_INHERIT(prop, Prop) \
156 m_style->set##Prop(RenderStyle::initial##Value());\
160 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
161 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
162 if (primitiveValue) \
163 m_style->set##Prop(*primitiveValue);
165 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
166 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
167 if (primitiveValue) \
168 m_style->set##Prop(*primitiveValue);
172 RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
174 unsigned position() const { return m_position; }
175 CSSStyleRule* rule() const { return m_rule; }
176 CSSSelector* selector() const { return m_selector; }
178 bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
179 bool hasMultipartSelector() const { return m_hasMultipartSelector; }
180 bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
181 bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
182 unsigned specificity() const { return m_specificity; }
183 unsigned linkMatchType() const { return m_linkMatchType; }
185 // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
186 static const unsigned maximumIdentifierCount = 4;
187 const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
190 CSSStyleRule* m_rule;
191 CSSSelector* m_selector;
192 unsigned m_specificity;
193 // This number was picked fairly arbitrarily. We can probably lower it if we need to.
194 // Some simple testing showed <100,000 RuleData's on large sites.
195 unsigned m_position : 26;
196 unsigned m_hasFastCheckableSelector : 1;
197 unsigned m_hasMultipartSelector : 1;
198 unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
199 unsigned m_containsUncommonAttributeSelector : 1;
200 unsigned m_linkMatchType : 2; // SelectorChecker::LinkMatchMask
201 // Use plain array instead of a Vector to minimize memory overhead.
202 unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
205 struct SameSizeAsRuleData {
213 COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
216 WTF_MAKE_NONCOPYABLE(RuleSet);
220 typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
222 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
224 void addStyleRule(CSSStyleRule* item);
225 void addRule(CSSStyleRule* rule, CSSSelector* sel);
226 void addPageRule(CSSPageRule*);
227 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, CSSStyleRule*, CSSSelector*);
229 void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
231 void collectFeatures(CSSStyleSelector::Features&) const;
233 const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
234 const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
235 const Vector<RuleData>* tagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
236 const Vector<RuleData>* shadowPseudoElementRules(AtomicStringImpl* key) const { return m_shadowPseudoElementRules.get(key); }
237 const Vector<RuleData>* linkPseudoClassRules() const { return &m_linkPseudoClassRules; }
238 const Vector<RuleData>* focusPseudoClassRules() const { return &m_focusPseudoClassRules; }
239 const Vector<RuleData>* universalRules() const { return &m_universalRules; }
240 const Vector<RuleData>* pageRules() const { return &m_pageRules; }
243 AtomRuleMap m_idRules;
244 AtomRuleMap m_classRules;
245 AtomRuleMap m_tagRules;
246 AtomRuleMap m_shadowPseudoElementRules;
247 Vector<RuleData> m_linkPseudoClassRules;
248 Vector<RuleData> m_focusPseudoClassRules;
249 Vector<RuleData> m_universalRules;
250 Vector<RuleData> m_pageRules;
251 unsigned m_ruleCount;
252 bool m_autoShrinkToFitEnabled;
255 static RuleSet* defaultStyle;
256 static RuleSet* defaultQuirksStyle;
257 static RuleSet* defaultPrintStyle;
258 static RuleSet* defaultViewSourceStyle;
259 static CSSStyleSheet* simpleDefaultStyleSheet;
261 static RuleSet* siblingRulesInDefaultStyle;
262 static RuleSet* uncommonAttributeRulesInDefaultStyle;
264 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
266 static void loadFullDefaultStyle();
267 static void loadSimpleDefaultStyle();
268 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
269 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}";
271 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
273 return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
276 static inline void collectSpecialRulesInDefaultStyle()
278 CSSStyleSelector::Features features;
279 defaultStyle->collectFeatures(features);
280 ASSERT(features.idsInRules.isEmpty());
281 delete siblingRulesInDefaultStyle;
282 delete uncommonAttributeRulesInDefaultStyle;
283 siblingRulesInDefaultStyle = features.siblingRules.leakPtr();
284 uncommonAttributeRulesInDefaultStyle = features.uncommonAttributeRules.leakPtr();
287 static inline void assertNoSiblingRulesInDefaultStyle()
290 if (siblingRulesInDefaultStyle)
292 collectSpecialRulesInDefaultStyle();
293 ASSERT(!siblingRulesInDefaultStyle);
297 static const MediaQueryEvaluator& screenEval()
299 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
300 return staticScreenEval;
303 static const MediaQueryEvaluator& printEval()
305 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
306 return staticPrintEval;
309 static CSSMutableStyleDeclaration* leftToRightDeclaration()
311 DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
312 if (!leftToRightDecl->length()) {
313 leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false);
314 leftToRightDecl->setStrictParsing(false);
316 return leftToRightDecl.get();
319 static CSSMutableStyleDeclaration* rightToLeftDeclaration()
321 DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create()));
322 if (!rightToLeftDecl->length()) {
323 rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false);
324 rightToLeftDecl->setStrictParsing(false);
326 return rightToLeftDecl.get();
329 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
330 CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets,
331 bool strictParsing, bool matchAuthorAndUserStyles)
332 : m_hasUAAppearance(false)
333 , m_backgroundData(BackgroundFillLayer)
334 , m_matchedDeclarationCacheAdditionsSinceLastSweep(0)
335 , m_checker(document, strictParsing)
337 , m_rootElementStyle(0)
340 , m_elementLinkState(NotInsideLink)
342 , m_lineHeightValue(0)
344 , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
345 , m_sameOriginOnly(false)
346 , m_fontSelector(CSSFontSelector::create(document))
347 , m_applyPropertyToRegularStyle(true)
348 , m_applyPropertyToVisitedLinkStyle(false)
349 , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
350 #if ENABLE(CSS_SHADERS)
351 , m_hasPendingShaders(false)
354 Element* root = document->documentElement();
357 if (!root || elementCanUseSimpleDefaultStyle(root))
358 loadSimpleDefaultStyle();
360 loadFullDefaultStyle();
364 // construct document root element default style. this is needed
365 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
366 // This is here instead of constructor, because when constructor is run,
367 // document doesn't have documentElement
368 // NOTE: this assumes that element that gets passed to styleForElement -call
369 // is always from the document that owns the style selector
370 FrameView* view = document->view();
372 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
374 m_medium = adoptPtr(new MediaQueryEvaluator("all"));
377 m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
379 if (m_rootDefaultStyle && view)
380 m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
382 m_authorStyle = adoptPtr(new RuleSet);
383 // Adding rules from multiple sheets, shrink at the end.
384 m_authorStyle->disableAutoShrinkToFit();
386 // FIXME: This sucks! The user sheet is reparsed every time!
387 OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
389 tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
390 if (pageGroupUserSheets) {
391 unsigned length = pageGroupUserSheets->size();
392 for (unsigned i = 0; i < length; i++) {
393 if (pageGroupUserSheets->at(i)->isUserStyleSheet())
394 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
396 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
399 if (documentUserSheets) {
400 unsigned length = documentUserSheets->size();
401 for (unsigned i = 0; i < length; i++) {
402 if (documentUserSheets->at(i)->isUserStyleSheet())
403 tempUserStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
405 m_authorStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
409 if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
410 m_userStyle = tempUserStyle.release();
412 // Add rules from elements like SVG's <font-face>
413 if (mappedElementSheet)
414 m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
416 // add stylesheets from document
417 unsigned length = styleSheets->length();
418 for (unsigned i = 0; i < length; i++) {
419 StyleSheet* sheet = styleSheets->item(i);
420 if (sheet->isCSSStyleSheet() && !sheet->disabled())
421 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
423 m_authorStyle->shrinkToFit();
427 if (document->renderer() && document->renderer()->style())
428 document->renderer()->style()->font().update(fontSelector());
431 void CSSStyleSelector::collectFeatures()
433 // Collect all ids and rules using sibling selectors (:first-child and similar)
434 // in the current set of stylesheets. Style sharing code uses this information to reject
435 // sharing candidates.
436 // Usually there are no sibling rules in the default style but the MathML sheet has some.
437 if (siblingRulesInDefaultStyle)
438 siblingRulesInDefaultStyle->collectFeatures(m_features);
439 if (uncommonAttributeRulesInDefaultStyle)
440 uncommonAttributeRulesInDefaultStyle->collectFeatures(m_features);
441 m_authorStyle->collectFeatures(m_features);
443 m_userStyle->collectFeatures(m_features);
444 if (m_features.siblingRules)
445 m_features.siblingRules->shrinkToFit();
446 if (m_features.uncommonAttributeRules)
447 m_features.uncommonAttributeRules->shrinkToFit();
450 void CSSStyleSelector::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets)
452 // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
453 // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
454 unsigned size = stylesheets.size();
455 for (unsigned i = firstNew; i < size; ++i) {
456 if (!stylesheets[i]->isCSSStyleSheet() || stylesheets[i]->disabled())
458 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(stylesheets[i].get()), *m_medium, this);
460 m_authorStyle->shrinkToFit();
461 // FIXME: This really only needs to collect the features from the newly added sheets.
465 if (document()->renderer() && document()->renderer()->style())
466 document()->renderer()->style()->font().update(fontSelector());
469 void CSSStyleSelector::addRegionRule(PassRefPtr<WebKitCSSRegionRule> regionStyleRule)
471 m_regionStyleRules.append(regionStyleRule);
474 // This is a simplified style setting function for keyframe styles
475 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
477 AtomicString s(rule->name());
478 m_keyframesRuleMap.set(s.impl(), rule);
481 CSSStyleSelector::~CSSStyleSelector()
483 m_fontSelector->clearDocument();
486 void CSSStyleSelector::sweepMatchedDeclarationCache()
488 // Look for cache entries containing a style declaration with a single ref and remove them.
489 // This may happen when an element attribute mutation causes it to swap out its Attribute::decl()
490 // for another CSSMappedAttributeDeclaration, potentially leaving this cache with the last ref.
491 Vector<unsigned, 16> toRemove;
492 MatchedStyleDeclarationCache::iterator it = m_matchedStyleDeclarationCache.begin();
493 MatchedStyleDeclarationCache::iterator end = m_matchedStyleDeclarationCache.end();
494 for (; it != end; ++it) {
495 Vector<MatchedStyleDeclaration>& matchedStyleDeclarations = it->second.matchedStyleDeclarations;
496 for (size_t i = 0; i < matchedStyleDeclarations.size(); ++i) {
497 if (matchedStyleDeclarations[i].styleDeclaration->hasOneRef()) {
498 toRemove.append(it->first);
503 for (size_t i = 0; i < toRemove.size(); ++i)
504 m_matchedStyleDeclarationCache.remove(toRemove[i]);
507 CSSStyleSelector::Features::Features()
508 : usesFirstLineRules(false)
509 , usesBeforeAfterRules(false)
510 , usesLinkRules(false)
514 CSSStyleSelector::Features::~Features()
518 void CSSStyleSelector::Features::clear()
521 attrsInRules.clear();
522 siblingRules.clear();
523 uncommonAttributeRules.clear();
524 usesFirstLineRules = false;
525 usesBeforeAfterRules = false;
526 usesLinkRules = false;
529 static CSSStyleSheet* parseUASheet(const String& str)
531 CSSStyleSheet* sheet = CSSStyleSheet::create().leakRef(); // leak the sheet on purpose
532 sheet->parseString(str);
536 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
538 return parseUASheet(String(characters, size));
541 static void loadFullDefaultStyle()
543 if (simpleDefaultStyleSheet) {
544 ASSERT(defaultStyle);
545 ASSERT(defaultPrintStyle == defaultStyle);
547 simpleDefaultStyleSheet->deref();
548 defaultStyle = new RuleSet;
549 defaultPrintStyle = new RuleSet;
550 simpleDefaultStyleSheet = 0;
552 ASSERT(!defaultStyle);
553 defaultStyle = new RuleSet;
554 defaultPrintStyle = new RuleSet;
555 defaultQuirksStyle = new RuleSet;
558 // Strict-mode rules.
559 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
560 CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
561 defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
562 defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
564 // Quirks-mode rules.
565 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
566 CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
567 defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
570 static void loadSimpleDefaultStyle()
572 ASSERT(!defaultStyle);
573 ASSERT(!simpleDefaultStyleSheet);
575 defaultStyle = new RuleSet;
576 // There are no media-specific rules in the simple default style.
577 defaultPrintStyle = defaultStyle;
578 defaultQuirksStyle = new RuleSet;
580 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
581 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
583 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
586 static void loadViewSourceStyle()
588 ASSERT(!defaultViewSourceStyle);
589 defaultViewSourceStyle = new RuleSet;
590 defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
593 static void ensureDefaultStyleSheetsForElement(Element* element)
595 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) {
596 loadFullDefaultStyle();
597 assertNoSiblingRulesInDefaultStyle();
598 collectSpecialRulesInDefaultStyle();
602 static bool loadedSVGUserAgentSheet;
603 if (element->isSVGElement() && !loadedSVGUserAgentSheet) {
605 loadedSVGUserAgentSheet = true;
606 CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
607 defaultStyle->addRulesFromSheet(svgSheet, screenEval());
608 defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
609 assertNoSiblingRulesInDefaultStyle();
610 collectSpecialRulesInDefaultStyle();
615 static bool loadedMathMLUserAgentSheet;
616 if (element->isMathMLElement() && !loadedMathMLUserAgentSheet) {
618 loadedMathMLUserAgentSheet = true;
619 CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
620 defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
621 defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
622 // There are some sibling and uncommon attribute rules here.
623 collectSpecialRulesInDefaultStyle();
628 static bool loadedMediaStyleSheet;
629 if (!loadedMediaStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
630 loadedMediaStyleSheet = true;
631 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
632 CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
633 defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
634 defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
635 collectSpecialRulesInDefaultStyle();
639 #if ENABLE(FULLSCREEN_API)
640 static bool loadedFullScreenStyleSheet;
641 if (!loadedFullScreenStyleSheet && element->document()->webkitIsFullScreen()) {
642 loadedFullScreenStyleSheet = true;
643 String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
644 CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
645 defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
646 defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
647 collectSpecialRulesInDefaultStyle();
652 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* styleDeclaration, unsigned linkMatchType)
654 m_matchedDecls.grow(m_matchedDecls.size() + 1);
655 MatchedStyleDeclaration& newDeclaration = m_matchedDecls.last();
656 newDeclaration.styleDeclaration = styleDeclaration;
657 newDeclaration.linkMatchType = linkMatchType;
660 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
662 m_matchedRules.clear();
664 if (!rules || !m_element)
667 // We need to collect the rules for id, class, tag, and everything else into a buffer and
668 // then sort the buffer.
669 if (m_element->hasID())
670 matchRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
671 if (m_element->hasClass()) {
672 ASSERT(m_styledElement);
673 const SpaceSplitString& classNames = m_styledElement->classNames();
674 size_t size = classNames.size();
675 for (size_t i = 0; i < size; ++i)
676 matchRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
678 const AtomicString& pseudoId = m_element->shadowPseudoId();
679 if (!pseudoId.isEmpty()) {
680 ASSERT(m_styledElement);
681 matchRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
683 if (m_element->isLink())
684 matchRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
685 if (m_checker.matchesFocusPseudoClass(m_element))
686 matchRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
687 matchRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
688 matchRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
690 if (m_matchedRules.isEmpty())
695 if (m_checker.isCollectingRulesOnly()) {
697 m_ruleList = CSSRuleList::create();
698 for (unsigned i = 0; i < m_matchedRules.size(); ++i)
699 m_ruleList->append(m_matchedRules[i]->rule());
703 // Now transfer the set of matched rules over to our list of declarations.
704 // FIXME: This sucks, the inspector should get the style from the visited style itself.
705 bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
706 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
707 if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
708 m_style->setAffectedByUncommonAttributeSelectors();
709 unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
710 if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
711 linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
712 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration(), linkMatchType);
716 class MatchingUARulesScope {
718 MatchingUARulesScope();
719 ~MatchingUARulesScope();
721 static bool isMatchingUARules();
724 static bool m_matchingUARules;
727 MatchingUARulesScope::MatchingUARulesScope()
729 ASSERT(!m_matchingUARules);
730 m_matchingUARules = true;
733 MatchingUARulesScope::~MatchingUARulesScope()
735 m_matchingUARules = false;
738 inline bool MatchingUARulesScope::isMatchingUARules()
740 return m_matchingUARules;
743 bool MatchingUARulesScope::m_matchingUARules = false;
745 inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesIntoShadowDOM)
747 return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM;
750 void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
754 // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
755 // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
756 bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
758 unsigned size = rules->size();
759 for (unsigned i = 0; i < size; ++i) {
760 const RuleData& ruleData = rules->at(i);
761 if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
764 CSSStyleRule* rule = ruleData.rule();
765 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
766 if (checkSelector(ruleData)) {
767 if (!matchesInTreeScope(m_element->treeScope(), m_checker.hasUnknownPseudoElements())) {
768 InspectorInstrumentation::didMatchRule(cookie, false);
771 // If the rule has no properties to apply, then ignore it in the non-debug mode.
772 CSSMutableStyleDeclaration* decl = rule->declaration();
773 if (!decl || (!decl->length() && !includeEmptyRules)) {
774 InspectorInstrumentation::didMatchRule(cookie, false);
777 if (m_sameOriginOnly && !m_checker.document()->securityOrigin()->canRequest(rule->baseURL())) {
778 InspectorInstrumentation::didMatchRule(cookie, false);
781 // If we're matching normal rules, set a pseudo bit if
782 // we really just matched a pseudo-element.
783 if (m_dynamicPseudo != NOPSEUDO && m_checker.pseudoStyle() == NOPSEUDO) {
784 if (m_checker.isCollectingRulesOnly()) {
785 InspectorInstrumentation::didMatchRule(cookie, false);
788 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
789 m_style->setHasPseudoStyle(m_dynamicPseudo);
791 // Update our first/last rule indices in the matched rules array.
792 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
793 if (firstRuleIndex == -1)
794 firstRuleIndex = lastRuleIndex;
796 // Add this rule to our list of matched rules.
797 addMatchedRule(&ruleData);
798 InspectorInstrumentation::didMatchRule(cookie, true);
802 InspectorInstrumentation::didMatchRule(cookie, false);
806 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
808 unsigned specificity1 = r1->specificity();
809 unsigned specificity2 = r2->specificity();
810 return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
813 void CSSStyleSelector::sortMatchedRules()
815 std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
818 void CSSStyleSelector::matchAllRules(MatchResult& result)
820 matchUARules(result);
822 // Now we check user sheet rules.
823 if (m_matchAuthorAndUserStyles)
824 matchRules(m_userStyle.get(), result.firstUserRule, result.lastUserRule, false);
826 // Now check author rules, beginning first with presentational attributes mapped from HTML.
827 if (m_styledElement) {
828 // Ask if the HTML element has mapped attributes.
829 if (m_styledElement->hasMappedAttributes()) {
830 // Walk our attribute list and add in each decl.
831 const NamedNodeMap* map = m_styledElement->attributeMap();
832 for (unsigned i = 0; i < map->length(); ++i) {
833 Attribute* attr = map->attributeItem(i);
835 ASSERT(attr->isMappedAttribute());
836 result.lastAuthorRule = m_matchedDecls.size();
837 if (result.firstAuthorRule == -1)
838 result.firstAuthorRule = result.lastAuthorRule;
839 addMatchedDeclaration(attr->decl());
844 // Now we check additional mapped declarations.
845 // Tables and table cells share an additional mapped rule that must be applied
846 // after all attributes, since their mapped style depends on the values of multiple attributes.
847 if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
848 Vector<CSSMutableStyleDeclaration*> additionalAttributeStyleDecls;
849 m_styledElement->additionalAttributeStyleDecls(additionalAttributeStyleDecls);
850 if (!additionalAttributeStyleDecls.isEmpty()) {
851 unsigned additionalDeclsSize = additionalAttributeStyleDecls.size();
852 if (result.firstAuthorRule == -1)
853 result.firstAuthorRule = m_matchedDecls.size();
854 result.lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
855 for (unsigned i = 0; i < additionalDeclsSize; ++i)
856 addMatchedDeclaration(additionalAttributeStyleDecls[i]);
857 result.isCacheable = false;
860 if (m_styledElement->isHTMLElement()) {
862 TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
864 addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
868 // Check the rules in author sheets next.
869 if (m_matchAuthorAndUserStyles)
870 matchRules(m_authorStyle.get(), result.firstAuthorRule, result.lastAuthorRule, false);
872 // Now check our inline style attribute.
873 if (m_matchAuthorAndUserStyles && m_styledElement) {
874 CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
876 result.lastAuthorRule = m_matchedDecls.size();
877 if (result.firstAuthorRule == -1)
878 result.firstAuthorRule = result.lastAuthorRule;
879 addMatchedDeclaration(inlineDecl);
880 result.isCacheable = false;
885 inline void CSSStyleSelector::initElement(Element* e)
887 if (m_element != e) {
889 m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
890 m_elementLinkState = m_checker.determineLinkState(m_element);
891 if (e && e == e->document()->documentElement()) {
892 e->document()->setDirectionSetOnDocumentElement(false);
893 e->document()->setWritingModeSetOnDocumentElement(false);
898 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
900 m_checker.setPseudoStyle(pseudoID);
902 m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
905 m_parentStyle = parentStyle;
907 m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
909 Node* docElement = e ? e->document()->documentElement() : 0;
910 RenderStyle* docStyle = m_checker.document()->renderStyle();
911 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
915 m_matchedDecls.clear();
917 m_pendingImageProperties.clear();
924 static const unsigned cStyleSearchThreshold = 10;
925 static const unsigned cStyleSearchLevelThreshold = 10;
927 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
929 if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
931 if (!parent || !parent->isStyledElement())
933 StyledElement* p = static_cast<StyledElement*>(parent);
934 if (p->inlineStyleDecl())
936 if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
939 RenderStyle* parentStyle = p->renderStyle();
940 unsigned subcount = 0;
941 Node* thisCousin = p;
942 Node* currentNode = p->previousSibling();
944 // Reserve the tries for this level. This effectively makes sure that the algorithm
945 // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
946 visitedNodeCount += cStyleSearchThreshold;
948 while (currentNode) {
950 if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
951 // Adjust for unused reserved tries.
952 visitedNodeCount -= cStyleSearchThreshold - subcount;
953 return currentNode->lastChild();
955 if (subcount >= cStyleSearchThreshold)
957 currentNode = currentNode->previousSibling();
959 currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
960 thisCousin = currentNode;
966 bool CSSStyleSelector::matchesRuleSet(RuleSet* ruleSet)
968 int firstSiblingRule = -1, lastSiblingRule = -1;
969 matchRules(ruleSet, firstSiblingRule, lastSiblingRule, false);
970 if (m_matchedDecls.isEmpty())
972 m_matchedDecls.clear();
976 bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const
978 #if ENABLE(PROGRESS_TAG)
979 if (element->hasTagName(progressTag)) {
980 if (!m_element->hasTagName(progressTag))
983 HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
984 HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
985 if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
992 HTMLInputElement* thisInputElement = element->toInputElement();
993 HTMLInputElement* otherInputElement = m_element->toInputElement();
995 if (!thisInputElement || !otherInputElement)
998 if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1000 if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
1002 if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1004 if (thisInputElement->required() != otherInputElement->required())
1007 if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1010 if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1013 if (!m_element->document()->containsValidityStyleRules())
1016 bool willValidate = element->willValidate();
1018 if (willValidate != m_element->willValidate())
1021 if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1024 if (element->isInRange() != m_element->isInRange())
1027 if (element->isOutOfRange() != m_element->isOutOfRange())
1033 bool CSSStyleSelector::canShareStyleWithElement(StyledElement* element) const
1035 RenderStyle* style = element->renderStyle();
1039 if (style->unique())
1041 if (element->tagQName() != m_element->tagQName())
1043 if (element->hasClass() != m_element->hasClass())
1045 if (element->inlineStyleDecl())
1047 if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
1049 if (element->isLink() != m_element->isLink())
1051 if (style->affectedByUncommonAttributeSelectors())
1053 if (element->hovered() != m_element->hovered())
1055 if (element->active() != m_element->active())
1057 if (element->focused() != m_element->focused())
1059 if (element->shadowPseudoId() != m_element->shadowPseudoId())
1061 if (element == element->document()->cssTarget())
1063 if (m_element == m_element->document()->cssTarget())
1065 if (element->getAttribute(typeAttr) != m_element->getAttribute(typeAttr))
1067 if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1069 if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1071 if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1073 if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1076 if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1079 bool isControl = element->isFormControlElement();
1081 if (isControl != m_element->isFormControlElement())
1084 if (isControl && !canShareStyleWithControl(element))
1087 if (style->transitions() || style->animations())
1090 #if USE(ACCELERATED_COMPOSITING)
1091 // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1092 // See comments in RenderObject::setStyle().
1093 if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)
1094 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1095 // With proxying, the media elements are backed by a RenderEmbeddedObject.
1096 || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1102 if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
1105 if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr))
1108 if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
1111 if (element->isLink() && m_elementLinkState != style->insideLink())
1117 inline StyledElement* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
1119 for (; node; node = node->previousSibling()) {
1120 if (!node->isStyledElement())
1122 if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
1124 if (count++ == cStyleSearchThreshold)
1127 return static_cast<StyledElement*>(node);
1130 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1132 return parentStyle->childrenAffectedByPositionalRules()
1133 || parentStyle->childrenAffectedByFirstChildRules()
1134 || parentStyle->childrenAffectedByLastChildRules()
1135 || parentStyle->childrenAffectedByDirectAdjacentRules();
1138 RenderStyle* CSSStyleSelector::locateSharedStyle()
1140 if (!m_styledElement || !m_parentStyle)
1142 // If the element has inline style it is probably unique.
1143 if (m_styledElement->inlineStyleDecl())
1145 // Ids stop style sharing if they show up in the stylesheets.
1146 if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1148 if (parentStylePreventsSharing(m_parentStyle))
1151 // Check previous siblings and their cousins.
1153 unsigned visitedNodeCount = 0;
1154 StyledElement* shareElement = 0;
1155 Node* cousinList = m_styledElement->previousSibling();
1156 while (cousinList) {
1157 shareElement = findSiblingForStyleSharing(cousinList, count);
1160 cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1163 // If we have exhausted all our budget or our cousins.
1167 // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1168 if (matchesRuleSet(m_features.siblingRules.get()))
1170 // Can't share if attribute rules apply.
1171 if (matchesRuleSet(m_features.uncommonAttributeRules.get()))
1173 // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1174 if (parentStylePreventsSharing(m_parentStyle))
1176 return shareElement->renderStyle();
1179 void CSSStyleSelector::matchUARules(MatchResult& result)
1181 MatchingUARulesScope scope;
1183 // First we match rules from the user agent sheet.
1184 if (simpleDefaultStyleSheet)
1185 result.isCacheable = false;
1186 RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1187 ? defaultPrintStyle : defaultStyle;
1188 matchRules(userAgentStyleSheet, result.firstUARule, result.lastUARule, false);
1190 // In quirks mode, we match rules from the quirks user agent sheet.
1191 if (!m_checker.strictParsing())
1192 matchRules(defaultQuirksStyle, result.firstUARule, result.lastUARule, false);
1194 // 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.
1195 if (m_checker.document()->isViewSource()) {
1196 if (!defaultViewSourceStyle)
1197 loadViewSourceStyle();
1198 matchRules(defaultViewSourceStyle, result.firstUARule, result.lastUARule, false);
1202 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document, CSSFontSelector* fontSelector)
1204 Frame* frame = document->frame();
1206 RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1207 documentStyle->setDisplay(BLOCK);
1208 documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1209 documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1210 documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1211 documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1213 Element* docElement = document->documentElement();
1214 RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1215 if (docElementRenderer) {
1216 // Use the direction and writing-mode of the body to set the
1217 // viewport's direction and writing-mode unless the property is set on the document element.
1218 // If there is no body, then use the document element.
1219 RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1220 if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1221 documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1223 documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1224 if (bodyRenderer && !document->directionSetOnDocumentElement())
1225 documentStyle->setDirection(bodyRenderer->style()->direction());
1227 documentStyle->setDirection(docElementRenderer->style()->direction());
1231 if (Page* page = frame->page()) {
1232 const Page::Pagination& pagination = page->pagination();
1233 if (pagination.mode != Page::Pagination::Unpaginated) {
1234 documentStyle->setColumnAxis(pagination.mode == Page::Pagination::HorizontallyPaginated ? HorizontalColumnAxis : VerticalColumnAxis);
1235 documentStyle->setColumnGap(pagination.gap);
1240 FontDescription fontDescription;
1241 fontDescription.setUsePrinterFont(document->printing());
1242 if (Settings* settings = document->settings()) {
1243 fontDescription.setRenderingMode(settings->fontRenderingMode());
1244 const AtomicString& stdfont = settings->standardFontFamily();
1245 if (!stdfont.isEmpty()) {
1246 fontDescription.setGenericFamily(FontDescription::StandardFamily);
1247 fontDescription.firstFamily().setFamily(stdfont);
1248 fontDescription.firstFamily().appendFamily(0);
1250 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1251 int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1252 fontDescription.setSpecifiedSize(size);
1253 bool useSVGZoomRules = document->isSVGDocument();
1254 fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1257 documentStyle->setFontDescription(fontDescription);
1258 documentStyle->font().update(fontSelector);
1260 return documentStyle.release();
1263 static inline bool isAtShadowBoundary(Element* element)
1267 ContainerNode* parentNode = element->parentNode();
1268 return parentNode && parentNode->isShadowRoot();
1271 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1272 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1274 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
1276 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1277 // will vanish if a style recalc happens during loading.
1278 if (allowSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1279 if (!s_styleNotYetAvailable) {
1280 s_styleNotYetAvailable = RenderStyle::create().leakRef();
1281 s_styleNotYetAvailable->setDisplay(NONE);
1282 s_styleNotYetAvailable->font().update(m_fontSelector);
1284 element->document()->setHasNodesWithPlaceholderStyle();
1285 return s_styleNotYetAvailable;
1288 initElement(element);
1289 initForStyleResolve(element, defaultParent);
1291 RenderStyle* sharedStyle = locateSharedStyle();
1296 m_style = RenderStyle::create();
1299 m_style->inheritFrom(m_parentStyle);
1301 m_parentStyle = style();
1302 // Make sure our fonts are initialized if we don't inherit them from our parent style.
1303 m_style->font().update(0);
1306 // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
1307 if (isAtShadowBoundary(element))
1308 m_style->setUserModify(RenderStyle::initialUserModify());
1310 if (element->isLink()) {
1311 m_style->setIsLink(true);
1312 m_style->setInsideLink(m_elementLinkState);
1315 ensureDefaultStyleSheetsForElement(element);
1317 MatchResult matchResult;
1318 if (resolveForRootDefault)
1319 matchUARules(matchResult);
1321 matchAllRules(matchResult);
1323 applyMatchedDeclarations(matchResult);
1325 // Clean up our style object's display and text decorations (among other fixups).
1326 adjustRenderStyle(style(), m_parentStyle, element);
1328 initElement(0); // Clear out for the next resolve.
1330 // Now return the style.
1331 return m_style.release();
1334 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1336 if (keyframeRule->style())
1337 addMatchedDeclaration(keyframeRule->style());
1342 m_style = RenderStyle::clone(elementStyle);
1344 m_lineHeightValue = 0;
1346 // We don't need to bother with !important. Since there is only ever one
1347 // decl, there's nothing to override. So just add the first properties.
1348 bool inheritedOnly = false;
1349 if (keyframeRule->style())
1350 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1352 // If our font got dirtied, go ahead and update it now.
1355 // Line-height is set when we are sure we decided on the font-size
1356 if (m_lineHeightValue)
1357 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1359 // Now do rest of the properties.
1360 if (keyframeRule->style())
1361 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1363 // If our font got dirtied by one of the non-essential font props,
1364 // go ahead and update it a second time.
1367 // Start loading images referenced by this style.
1368 loadPendingImages();
1370 #if ENABLE(CSS_SHADERS)
1371 // Start loading the shaders referenced by this style.
1372 loadPendingShaders();
1375 // Add all the animating properties to the keyframe.
1376 if (keyframeRule->style()) {
1377 CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1378 for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1379 int property = (*it).id();
1380 // Timing-function within keyframes is special, because it is not animated; it just
1381 // describes the timing function between this keyframe and the next.
1382 if (property != CSSPropertyWebkitAnimationTimingFunction)
1383 keyframe.addProperty(property);
1387 return m_style.release();
1390 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1394 // Get the keyframesRule for this name
1395 if (!e || list.animationName().isEmpty())
1398 m_keyframesRuleMap.checkConsistency();
1400 KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
1401 if (it == m_keyframesRuleMap.end())
1404 const WebKitCSSKeyframesRule* rule = it->second.get();
1406 // Construct and populate the style for each keyframe
1407 for (unsigned i = 0; i < rule->length(); ++i) {
1408 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1410 initForStyleResolve(e);
1412 const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1414 KeyframeValue keyframe(0, 0);
1415 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1417 // Add this keyframe style to all the indicated key times
1419 keyframeRule->getKeys(keys);
1420 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1421 keyframe.setKey(keys[keyIndex]);
1422 list.insert(keyframe);
1426 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1427 int initialListSize = list.size();
1428 if (initialListSize > 0 && list[0].key() != 0) {
1429 RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1430 keyframeRule->setKeyText("0%");
1431 KeyframeValue keyframe(0, 0);
1432 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1433 list.insert(keyframe);
1436 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1437 if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1438 RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1439 keyframeRule->setKeyText("100%");
1440 KeyframeValue keyframe(1, 0);
1441 keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1442 list.insert(keyframe);
1446 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1453 initForStyleResolve(e, parentStyle, pseudo);
1454 m_style = RenderStyle::create();
1457 m_style->inheritFrom(m_parentStyle);
1459 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1462 // Check UA, user and author rules.
1463 MatchResult matchResult;
1464 matchUARules(matchResult);
1466 if (m_matchAuthorAndUserStyles) {
1467 matchRules(m_userStyle.get(), matchResult.firstUserRule, matchResult.lastUserRule, false);
1468 matchRules(m_authorStyle.get(), matchResult.firstAuthorRule, matchResult.lastAuthorRule, false);
1471 if (m_matchedDecls.isEmpty())
1474 m_style->setStyleType(pseudo);
1476 applyMatchedDeclarations(matchResult);
1478 // Clean up our style object's display and text decorations (among other fixups).
1479 adjustRenderStyle(style(), parentStyle, 0);
1481 // Start loading images referenced by this style.
1482 loadPendingImages();
1484 #if ENABLE(CSS_SHADERS)
1485 // Start loading the shaders referenced by this style.
1486 loadPendingShaders();
1489 // Now return the style.
1490 return m_style.release();
1493 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1495 initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1497 m_style = RenderStyle::create();
1498 m_style->inheritFrom(m_rootElementStyle);
1500 const bool isLeft = isLeftPage(pageIndex);
1501 const bool isFirst = isFirstPage(pageIndex);
1502 const String page = pageName(pageIndex);
1503 matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1504 matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1505 matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1506 m_lineHeightValue = 0;
1507 bool inheritedOnly = false;
1508 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1510 // If our font got dirtied, go ahead and update it now.
1513 // Line-height is set when we are sure we decided on the font-size.
1514 if (m_lineHeightValue)
1515 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1517 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1519 // Start loading images referenced by this style.
1520 loadPendingImages();
1522 #if ENABLE(CSS_SHADERS)
1523 // Start loading the shaders referenced by this style.
1524 loadPendingShaders();
1527 // Now return the style.
1528 return m_style.release();
1531 static void addIntrinsicMargins(RenderStyle* style)
1533 // Intrinsic margin value.
1534 const int intrinsicMargin = 2 * style->effectiveZoom();
1536 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1537 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1538 if (style->width().isIntrinsicOrAuto()) {
1539 if (style->marginLeft().quirk())
1540 style->setMarginLeft(Length(intrinsicMargin, Fixed));
1541 if (style->marginRight().quirk())
1542 style->setMarginRight(Length(intrinsicMargin, Fixed));
1545 if (style->height().isAuto()) {
1546 if (style->marginTop().quirk())
1547 style->setMarginTop(Length(intrinsicMargin, Fixed));
1548 if (style->marginBottom().quirk())
1549 style->setMarginBottom(Length(intrinsicMargin, Fixed));
1553 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1555 // Cache our original display.
1556 style->setOriginalDisplay(style->display());
1558 if (style->display() != NONE) {
1559 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1561 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1562 // these tags to retain their display types.
1563 if (!m_checker.strictParsing() && e) {
1564 if (e->hasTagName(tdTag)) {
1565 style->setDisplay(TABLE_CELL);
1566 style->setFloating(NoFloat);
1568 else if (e->hasTagName(tableTag))
1569 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1572 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1573 if (style->whiteSpace() == KHTML_NOWRAP) {
1574 // Figure out if we are really nowrapping or if we should just
1575 // use normal instead. If the width of the cell is fixed, then
1576 // we don't actually use NOWRAP.
1577 if (style->width().isFixed())
1578 style->setWhiteSpace(NORMAL);
1580 style->setWhiteSpace(NOWRAP);
1584 // Tables never support the -webkit-* values for text-align and will reset back to the default.
1585 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1586 style->setTextAlign(TAAUTO);
1588 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1589 // fix a crash where a site tries to position these objects. They also never honor display.
1590 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1591 style->setPosition(StaticPosition);
1592 style->setDisplay(BLOCK);
1595 // Table headers with a text-align of auto will change the text-align to center.
1596 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1597 style->setTextAlign(CENTER);
1599 if (e && e->hasTagName(legendTag))
1600 style->setDisplay(BLOCK);
1602 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1603 // position or float an inline, compact, or run-in. Cache the original display, since it
1604 // may be needed for positioned elements that have to compute their static normal flow
1605 // positions. We also force inline-level roots to be block-level.
1606 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1607 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() ||
1608 (e && e->document()->documentElement() == e))) {
1609 if (style->display() == INLINE_TABLE)
1610 style->setDisplay(TABLE);
1611 else if (style->display() == INLINE_BOX)
1612 style->setDisplay(BOX);
1613 else if (style->display() == LIST_ITEM) {
1614 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1615 // but only in quirks mode.
1616 if (!m_checker.strictParsing() && style->isFloating())
1617 style->setDisplay(BLOCK);
1620 style->setDisplay(BLOCK);
1623 // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1624 // clear how that should work.
1625 if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1626 style->setDisplay(INLINE_BLOCK);
1628 // After performing the display mutation, check table rows. We do not honor position:relative on
1629 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1631 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1632 || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1633 style->position() == RelativePosition)
1634 style->setPosition(StaticPosition);
1636 // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1637 // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1638 if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1639 || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1640 || style->display() == TABLE_CELL)
1641 style->setWritingMode(parentStyle->writingMode());
1643 // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1644 // of block-flow to anything other than TopToBottomWritingMode.
1645 // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1646 if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1647 style->setWritingMode(TopToBottomWritingMode);
1650 // Make sure our z-index value is only applied if the object is positioned.
1651 if (style->position() == StaticPosition)
1652 style->setHasAutoZIndex();
1654 // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1655 // cases where objects that should be blended as a single unit end up with a non-transparent
1656 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1657 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f
1658 || style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect() || style->hasFilter()))
1659 style->setZIndex(0);
1661 // Textarea considers overflow visible as auto.
1662 if (e && e->hasTagName(textareaTag)) {
1663 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1664 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1667 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1668 // tables, inline blocks, inline tables, run-ins, or shadow DOM.
1669 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1670 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
1671 style->setTextDecorationsInEffect(style->textDecoration());
1673 style->addToTextDecorationsInEffect(style->textDecoration());
1675 // If either overflow value is not visible, change to auto.
1676 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1677 style->setOverflowY(OMARQUEE);
1678 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1679 style->setOverflowX(OMARQUEE);
1680 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1681 style->setOverflowX(OAUTO);
1682 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1683 style->setOverflowY(OAUTO);
1685 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1686 // FIXME: Eventually table sections will support auto and scroll.
1687 if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1688 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1689 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1690 style->setOverflowX(OVISIBLE);
1691 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1692 style->setOverflowY(OVISIBLE);
1695 // Menulists should have visible overflow
1696 if (style->appearance() == MenulistPart) {
1697 style->setOverflowX(OVISIBLE);
1698 style->setOverflowY(OVISIBLE);
1701 // Cull out any useless layers and also repeat patterns into additional layers.
1702 style->adjustBackgroundLayers();
1703 style->adjustMaskLayers();
1705 // Do the same for animations and transitions.
1706 style->adjustAnimations();
1707 style->adjustTransitions();
1709 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1710 // alter fonts and heights/widths.
1711 if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1712 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1713 // so we have to treat all image buttons as though they were explicitly sized.
1714 if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1715 addIntrinsicMargins(style);
1718 // Let the theme also have a crack at adjusting the style.
1719 if (style->hasAppearance())
1720 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1722 // If we have first-letter pseudo style, do not share this style.
1723 if (style->hasPseudoStyle(FIRST_LETTER))
1727 if (e && e->isSVGElement()) {
1728 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1729 if (style->overflowY() == OSCROLL)
1730 style->setOverflowY(OHIDDEN);
1731 else if (style->overflowY() == OAUTO)
1732 style->setOverflowY(OVISIBLE);
1734 if (style->overflowX() == OSCROLL)
1735 style->setOverflowX(OHIDDEN);
1736 else if (style->overflowX() == OAUTO)
1737 style->setOverflowX(OVISIBLE);
1739 // Only the root <svg> element in an SVG document fragment tree honors css position
1740 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1741 style->setPosition(RenderStyle::initialPosition());
1746 bool CSSStyleSelector::checkRegionStyle(Element* e)
1748 m_checker.clearHasUnknownPseudoElements();
1749 m_checker.setPseudoStyle(NOPSEUDO);
1751 for (Vector<RefPtr<WebKitCSSRegionRule> >::iterator it = m_regionStyleRules.begin(); it != m_regionStyleRules.end(); ++it) {
1752 const CSSSelectorList& regionSelectorList = (*it)->selectorList();
1753 for (CSSSelector* s = regionSelectorList.first(); s; s = regionSelectorList.next(s)) {
1754 if (m_checker.checkSelector(s, e))
1762 void CSSStyleSelector::updateFont()
1767 checkForTextSizeAdjust();
1768 checkForGenericFamilyChange(style(), m_parentStyle);
1769 checkForZoomChange(style(), m_parentStyle);
1770 m_style->font().update(m_fontSelector);
1771 m_fontDirty = false;
1774 void CSSStyleSelector::cacheBorderAndBackground()
1776 m_hasUAAppearance = m_style->hasAppearance();
1777 if (m_hasUAAppearance) {
1778 m_borderData = m_style->border();
1779 m_backgroundData = *m_style->backgroundLayers();
1780 m_backgroundColor = m_style->backgroundColor();
1784 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
1786 return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1789 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
1791 if (!e || !e->document()->haveStylesheetsLoaded())
1794 m_checker.setCollectingRulesOnly(true);
1797 initForStyleResolve(e, 0, pseudoId);
1800 if (rulesToInclude & UAAndUserCSSRules) {
1801 // First we match rules from the user agent sheet.
1802 matchUARules(dummy);
1804 // Now we check user sheet rules.
1805 if (m_matchAuthorAndUserStyles)
1806 matchRules(m_userStyle.get(), dummy.firstUserRule, dummy.lastUserRule, rulesToInclude & EmptyCSSRules);
1809 if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1810 m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
1812 // Check the rules in author sheets.
1813 matchRules(m_authorStyle.get(), dummy.firstAuthorRule, dummy.lastAuthorRule, rulesToInclude & EmptyCSSRules);
1815 m_sameOriginOnly = false;
1818 m_checker.setCollectingRulesOnly(false);
1820 return m_ruleList.release();
1823 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
1825 m_dynamicPseudo = NOPSEUDO;
1826 m_checker.clearHasUnknownPseudoElements();
1828 // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
1829 if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
1830 // We know this selector does not include any pseudo elements.
1831 if (m_checker.pseudoStyle() != NOPSEUDO)
1833 // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
1834 // This is limited to HTML only so we don't need to check the namespace.
1835 if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
1836 if (!ruleData.hasMultipartSelector())
1838 } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
1840 if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
1842 return m_checker.fastCheckSelector(ruleData.selector(), m_element);
1846 SelectorChecker::SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
1847 if (match != SelectorChecker::SelectorMatches)
1849 if (m_checker.pseudoStyle() != NOPSEUDO && m_checker.pseudoStyle() != m_dynamicPseudo)
1854 bool CSSStyleSelector::determineStylesheetSelectorScopes(CSSStyleSheet* stylesheet, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes)
1856 ASSERT(!stylesheet->isLoading());
1858 size_t size = stylesheet->length();
1859 for (size_t i = 0; i < size; i++) {
1860 CSSRule* rule = stylesheet->item(i);
1861 if (rule->isStyleRule()) {
1862 CSSStyleRule* styleRule = static_cast<CSSStyleRule*>(rule);
1863 if (!SelectorChecker::determineSelectorScopes(styleRule->selectorList(), idScopes, classScopes))
1867 if (rule->isImportRule()) {
1868 CSSImportRule* importRule = static_cast<CSSImportRule*>(rule);
1869 if (importRule->styleSheet()) {
1870 if (!determineStylesheetSelectorScopes(importRule->styleSheet(), idScopes, classScopes))
1875 // FIXME: Media rules and maybe some others could be allowed.
1881 // -----------------------------------------------------------------
1883 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
1885 const AtomicString& selectorNamespace = selector->tag().namespaceURI();
1886 if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
1888 if (selector->m_match == CSSSelector::None)
1890 if (selector->tag() != starAtom)
1892 if (SelectorChecker::isCommonPseudoClassSelector(selector))
1894 return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
1897 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
1899 CSSSelectorList* selectorList = selector->selectorList();
1902 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
1903 if (subSelector->isAttributeSelector())
1909 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
1911 // These are explicitly tested for equality in canShareStyleWithElement.
1912 return attribute == typeAttr || attribute == readonlyAttr;
1915 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
1918 // Allow certain common attributes (used in the default style) in the selectors that match the current element.
1919 if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
1921 if (selectorListContainsUncommonAttributeSelector(selector))
1923 if (selector->relation() != CSSSelector::SubSelector)
1925 selector = selector->tagHistory();
1928 for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
1929 if (selector->isAttributeSelector())
1931 if (selectorListContainsUncommonAttributeSelector(selector))
1937 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
1939 , m_selector(selector)
1940 , m_specificity(selector->specificity())
1941 , m_position(position)
1942 , m_hasFastCheckableSelector(SelectorChecker::isFastCheckableSelector(selector))
1943 , m_hasMultipartSelector(!!selector->tagHistory())
1944 , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
1945 , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector))
1946 , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector))
1948 SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
1953 , m_autoShrinkToFitEnabled(true)
1957 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, CSSStyleRule* rule, CSSSelector* selector)
1961 OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).first->second;
1963 rules = adoptPtr(new Vector<RuleData>);
1964 rules->append(RuleData(rule, selector, m_ruleCount++));
1967 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1969 if (sel->m_match == CSSSelector::Id) {
1970 addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
1973 if (sel->m_match == CSSSelector::Class) {
1974 addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
1977 if (sel->isUnknownPseudoElement()) {
1978 addToRuleSet(sel->value().impl(), m_shadowPseudoElementRules, rule, sel);
1981 if (SelectorChecker::isCommonPseudoClassSelector(sel)) {
1982 RuleData ruleData(rule, sel, m_ruleCount++);
1983 switch (sel->pseudoType()) {
1984 case CSSSelector::PseudoLink:
1985 case CSSSelector::PseudoVisited:
1986 case CSSSelector::PseudoAnyLink:
1987 m_linkPseudoClassRules.append(ruleData);
1989 case CSSSelector::PseudoFocus:
1990 m_focusPseudoClassRules.append(ruleData);
1993 ASSERT_NOT_REACHED();
1997 const AtomicString& localName = sel->tag().localName();
1998 if (localName != starAtom) {
1999 addToRuleSet(localName.impl(), m_tagRules, rule, sel);
2003 m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
2006 void RuleSet::addPageRule(CSSPageRule* rule)
2008 m_pageRules.append(RuleData(rule, rule->selectorList().first(), m_pageRules.size()));
2011 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
2015 // No media implies "all", but if a media list exists it must
2016 // contain our current medium
2017 if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
2018 return; // the style sheet doesn't apply
2020 int len = sheet->length();
2022 for (int i = 0; i < len; i++) {
2023 CSSRule* rule = sheet->item(i);
2024 if (rule->isStyleRule())
2025 addStyleRule(static_cast<CSSStyleRule*>(rule));
2026 else if (rule->isPageRule())
2027 addPageRule(static_cast<CSSPageRule*>(rule));
2028 else if (rule->isImportRule()) {
2029 CSSImportRule* import = static_cast<CSSImportRule*>(rule);
2030 if (import->styleSheet() && (!import->media() || medium.eval(import->media(), styleSelector)))
2031 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
2033 else if (rule->isMediaRule()) {
2034 CSSMediaRule* r = static_cast<CSSMediaRule*>(rule);
2035 CSSRuleList* rules = r->cssRules();
2037 if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
2038 // Traverse child elements of the @media rule.
2039 for (unsigned j = 0; j < rules->length(); j++) {
2040 CSSRule *childItem = rules->item(j);
2041 if (childItem->isStyleRule())
2042 addStyleRule(static_cast<CSSStyleRule*>(childItem));
2043 else if (childItem->isPageRule())
2044 addPageRule(static_cast<CSSPageRule*>(childItem));
2045 else if (childItem->isFontFaceRule() && styleSelector) {
2046 // Add this font face to our set.
2047 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
2048 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2049 styleSelector->invalidateMatchedDeclarationCache();
2050 } else if (childItem->isKeyframesRule() && styleSelector) {
2051 // Add this keyframe rule to our set.
2052 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
2056 } else if (rule->isFontFaceRule() && styleSelector) {
2057 // Add this font face to our set.
2058 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
2059 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2060 styleSelector->invalidateMatchedDeclarationCache();
2061 } else if (rule->isKeyframesRule())
2062 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule));
2063 else if (rule->isRegionRule() && styleSelector)
2064 styleSelector->addRegionRule(static_cast<WebKitCSSRegionRule*>(rule));
2066 if (m_autoShrinkToFitEnabled)
2070 void RuleSet::addStyleRule(CSSStyleRule* rule)
2072 for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2076 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
2078 if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
2079 features.idsInRules.add(selector->value().impl());
2080 if (selector->isAttributeSelector())
2081 features.attrsInRules.add(selector->attribute().localName().impl());
2082 switch (selector->pseudoType()) {
2083 case CSSSelector::PseudoFirstLine:
2084 features.usesFirstLineRules = true;
2086 case CSSSelector::PseudoBefore:
2087 case CSSSelector::PseudoAfter:
2088 features.usesBeforeAfterRules = true;
2090 case CSSSelector::PseudoLink:
2091 case CSSSelector::PseudoVisited:
2092 features.usesLinkRules = true;
2099 static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules)
2101 unsigned size = rules.size();
2102 for (unsigned i = 0; i < size; ++i) {
2103 const RuleData& ruleData = rules[i];
2104 bool foundSiblingSelector = false;
2105 for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
2106 collectFeaturesFromSelector(features, selector);
2108 if (CSSSelectorList* selectorList = selector->selectorList()) {
2109 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2110 if (selector->isSiblingSelector())
2111 foundSiblingSelector = true;
2112 collectFeaturesFromSelector(features, subSelector);
2114 } else if (selector->isSiblingSelector())
2115 foundSiblingSelector = true;
2117 if (foundSiblingSelector) {
2118 if (!features.siblingRules)
2119 features.siblingRules = adoptPtr(new RuleSet);
2120 features.siblingRules->addRule(ruleData.rule(), ruleData.selector());
2122 if (ruleData.containsUncommonAttributeSelector()) {
2123 if (!features.uncommonAttributeRules)
2124 features.uncommonAttributeRules = adoptPtr(new RuleSet);
2125 features.uncommonAttributeRules->addRule(ruleData.rule(), ruleData.selector());
2130 void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const
2132 AtomRuleMap::const_iterator end = m_idRules.end();
2133 for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
2134 collectFeaturesFromList(features, *it->second);
2135 end = m_classRules.end();
2136 for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
2137 collectFeaturesFromList(features, *it->second);
2138 end = m_tagRules.end();
2139 for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
2140 collectFeaturesFromList(features, *it->second);
2141 end = m_shadowPseudoElementRules.end();
2142 for (AtomRuleMap::const_iterator it = m_shadowPseudoElementRules.begin(); it != end; ++it)
2143 collectFeaturesFromList(features, *it->second);
2144 collectFeaturesFromList(features, m_linkPseudoClassRules);
2145 collectFeaturesFromList(features, m_focusPseudoClassRules);
2146 collectFeaturesFromList(features, m_universalRules);
2149 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
2151 RuleSet::AtomRuleMap::iterator end = map.end();
2152 for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
2153 it->second->shrinkToFit();
2156 void RuleSet::shrinkToFit()
2158 shrinkMapVectorsToFit(m_idRules);
2159 shrinkMapVectorsToFit(m_classRules);
2160 shrinkMapVectorsToFit(m_tagRules);
2161 shrinkMapVectorsToFit(m_shadowPseudoElementRules);
2162 m_linkPseudoClassRules.shrinkToFit();
2163 m_focusPseudoClassRules.shrinkToFit();
2164 m_universalRules.shrinkToFit();
2165 m_pageRules.shrinkToFit();
2168 // -------------------------------------------------------------------------------------
2169 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2171 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
2173 // This function is tolerant of a null style value. The only place style is used is in
2174 // length measurements, like 'ems' and 'px'. And in those cases style is only used
2175 // when the units are EMS or EXS. So we will just fail in those cases.
2177 if (!primitiveValue) {
2181 int type = primitiveValue->primitiveType();
2183 if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
2186 } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2188 l = Length(primitiveValue->computeLength<double>(style, rootStyle, multiplier), Fixed);
2190 l = primitiveValue->computeLength<Length>(style, rootStyle, multiplier);
2192 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2193 l = Length(primitiveValue->getDoubleValue(), Percent);
2194 else if (type == CSSPrimitiveValue::CSS_NUMBER)
2195 l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2202 static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2204 return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
2207 static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2209 return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
2212 template <bool applyFirst>
2213 void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant, bool inheritedOnly)
2215 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), styleDeclaration->parentRule());
2216 CSSMutableStyleDeclaration::const_iterator end = styleDeclaration->end();
2217 for (CSSMutableStyleDeclaration::const_iterator it = styleDeclaration->begin(); it != end; ++it) {
2218 const CSSProperty& current = *it;
2219 if (isImportant != current.isImportant())
2221 if (inheritedOnly && !current.isInherited()) {
2222 // If the property value is explicitly inherited, we need to apply further non-inherited properties
2223 // as they might override the value inherited here. For this reason we don't allow declarations with
2224 // explicitly inherited properties to be cached.
2225 ASSERT(!current.value()->isInheritedValue());
2228 int property = current.id();
2230 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2231 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is_end_of_first_prop_range);
2232 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2233 // give special priority to font-xxx, color properties, etc
2234 if (property > CSSPropertyLineHeight)
2236 // we apply line-height later
2237 if (property == CSSPropertyLineHeight) {
2238 m_lineHeightValue = current.value();
2241 applyProperty(current.id(), current.value());
2244 if (property > CSSPropertyLineHeight)
2245 applyProperty(current.id(), current.value());
2247 InspectorInstrumentation::didProcessRule(cookie);
2250 template <bool applyFirst>
2251 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
2253 if (startIndex == -1)
2256 if (m_style->insideLink() != NotInsideLink) {
2257 for (int i = startIndex; i <= endIndex; ++i) {
2258 CSSMutableStyleDeclaration* styleDeclaration = m_matchedDecls[i].styleDeclaration.get();
2259 unsigned linkMatchType = m_matchedDecls[i].linkMatchType;
2260 // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2261 m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2262 m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2264 applyDeclaration<applyFirst>(styleDeclaration, isImportant, inheritedOnly);
2266 m_applyPropertyToRegularStyle = true;
2267 m_applyPropertyToVisitedLinkStyle = false;
2270 for (int i = startIndex; i <= endIndex; ++i)
2271 applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration.get(), isImportant, inheritedOnly);
2274 unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* declarations, unsigned size)
2276 return StringHasher::hashMemory(declarations, sizeof(MatchedStyleDeclaration) * size);
2279 bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2281 return a.firstUARule == b.firstUARule
2282 && a.lastUARule == b.lastUARule
2283 && a.firstAuthorRule == b.firstAuthorRule
2284 && a.lastAuthorRule == b.lastAuthorRule
2285 && a.firstUserRule == b.firstUserRule
2286 && a.lastUserRule == b.lastUserRule
2287 && a.isCacheable == b.isCacheable;
2290 bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2295 bool operator==(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2297 return a.styleDeclaration == b.styleDeclaration && a.linkMatchType == b.linkMatchType;
2300 bool operator!=(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2305 const CSSStyleSelector::MatchedStyleDeclarationCacheItem* CSSStyleSelector::findFromMatchedDeclarationCache(unsigned hash, const MatchResult& matchResult)
2309 MatchedStyleDeclarationCache::iterator it = m_matchedStyleDeclarationCache.find(hash);
2310 if (it == m_matchedStyleDeclarationCache.end())
2312 MatchedStyleDeclarationCacheItem& cacheItem = it->second;
2313 ASSERT(cacheItem.matchResult.isCacheable);
2315 size_t size = m_matchedDecls.size();
2316 if (size != cacheItem.matchedStyleDeclarations.size())
2318 for (size_t i = 0; i < size; ++i) {
2319 if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i])
2322 if (cacheItem.matchResult != matchResult)
2327 void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
2329 static unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
2330 if (++m_matchedDeclarationCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps) {
2331 sweepMatchedDeclarationCache();
2332 m_matchedDeclarationCacheAdditionsSinceLastSweep = 0;
2336 MatchedStyleDeclarationCacheItem cacheItem;
2337 cacheItem.matchedStyleDeclarations.append(m_matchedDecls);
2338 cacheItem.matchResult = matchResult;
2339 // Note that we don't cache the original RenderStyle instance. It may be further modified.
2340 // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
2341 cacheItem.renderStyle = RenderStyle::clone(style);
2342 cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
2343 m_matchedStyleDeclarationCache.add(hash, cacheItem);
2346 void CSSStyleSelector::invalidateMatchedDeclarationCache()
2348 m_matchedStyleDeclarationCache.clear();
2351 static bool isCacheableInMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle)
2353 if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2355 if (style->hasAppearance())
2357 if (style->zoom() != RenderStyle::initialZoom())
2359 // The cache assumes static knowledge about which properties are inherited.
2360 if (parentStyle->hasExplicitlyInheritedProperties())
2365 void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult)
2367 unsigned cacheHash = matchResult.isCacheable ? computeDeclarationHash(m_matchedDecls.data(), m_matchedDecls.size()) : 0;
2368 bool applyInheritedOnly = false;
2369 const MatchedStyleDeclarationCacheItem* cacheItem = 0;
2370 if (cacheHash && (cacheItem = findFromMatchedDeclarationCache(cacheHash, matchResult))) {
2371 // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
2372 // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the
2373 // element context. This is fast and saves memory by reusing the style data structures.
2374 m_style->copyNonInheritedFrom(cacheItem->renderStyle.get());
2375 if (m_parentStyle->inheritedDataShared(cacheItem->parentRenderStyle.get())) {
2376 EInsideLink linkStatus = m_style->insideLink();
2377 // If the cache item parent style has identical inherited properties to the current parent style then the
2378 // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
2379 m_style->inheritFrom(cacheItem->renderStyle.get());
2380 // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
2381 m_style->setInsideLink(linkStatus);
2384 applyInheritedOnly = true;
2386 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
2387 // high-priority properties first, i.e., those properties that other properties depend on.
2388 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
2389 // and (4) normal important.
2390 m_lineHeightValue = 0;
2391 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, applyInheritedOnly);
2392 applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2393 applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2394 applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2396 if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) {
2398 applyInheritedOnly = false;
2401 // If our font got dirtied, go ahead and update it now.
2404 // Line-height is set when we are sure we decided on the font-size.
2405 if (m_lineHeightValue)
2406 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2408 // Many properties depend on the font. If it changes we just apply all properties.
2409 if (cacheItem && cacheItem->renderStyle->fontDescription() != m_style->fontDescription())
2410 applyInheritedOnly = false;
2412 // Now do the normal priority UA properties.
2413 applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2415 // Cache our border and background so that we can examine them later.
2416 cacheBorderAndBackground();
2418 // Now do the author and user normal priority properties and all the !important properties.
2419 applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly);
2420 applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2421 applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2422 applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2424 loadPendingImages();
2426 #if ENABLE(CSS_SHADERS)
2427 loadPendingShaders();
2430 ASSERT(!m_fontDirty);
2432 if (cacheItem || !cacheHash)
2434 if (!isCacheableInMatchedDeclarationCache(m_style.get(), m_parentStyle))
2436 addToMatchedDeclarationCache(m_style.get(), m_parentStyle, cacheHash, matchResult);
2439 void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2441 m_matchedRules.clear();
2446 matchPageRulesForList(rules->pageRules(), isLeftPage, isFirstPage, pageName);
2448 // If we didn't match any rules, we're done.
2449 if (m_matchedRules.isEmpty())
2452 // Sort the set of matched rules.
2455 // Now transfer the set of matched rules over to our list of decls.
2456 for (unsigned i = 0; i < m_matchedRules.size(); i++)
2457 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
2460 void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2465 unsigned size = rules->size();
2466 for (unsigned i = 0; i < size; ++i) {
2467 const RuleData& ruleData = rules->at(i);
2468 CSSStyleRule* rule = ruleData.rule();
2469 const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
2470 if (selectorLocalName != starAtom && selectorLocalName != pageName)
2472 CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
2473 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2474 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2475 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2478 // If the rule has no properties to apply, then ignore it.
2479 CSSMutableStyleDeclaration* decl = rule->declaration();
2480 if (!decl || !decl->length())
2483 // Add this rule to our list of matched rules.
2484 addMatchedRule(&ruleData);
2488 bool CSSStyleSelector::isLeftPage(int pageIndex) const
2490 bool isFirstPageLeft = false;
2491 if (!m_rootElementStyle->isLeftToRightDirection())
2492 isFirstPageLeft = true;
2494 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
2497 bool CSSStyleSelector::isFirstPage(int pageIndex) const
2499 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
2500 return (!pageIndex);
2503 String CSSStyleSelector::pageName(int /* pageIndex */) const
2505 // FIXME: Implement page index to page name mapping.
2509 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue* value, RenderStyle* style)
2512 initForStyleResolve(0, style);
2514 applyPropertyToCurrentStyle(id, value);
2517 void CSSStyleSelector::applyPropertyToCurrentStyle(int id, CSSValue* value)
2520 applyProperty(id, value);
2523 inline bool isValidVisitedLinkProperty(int id)
2525 switch(static_cast<CSSPropertyID>(id)) {
2526 case CSSPropertyBackgroundColor:
2527 case CSSPropertyBorderLeftColor:
2528 case CSSPropertyBorderRightColor:
2529 case CSSPropertyBorderTopColor:
2530 case CSSPropertyBorderBottomColor:
2531 case CSSPropertyColor:
2532 case CSSPropertyOutlineColor:
2533 case CSSPropertyWebkitColumnRuleColor:
2534 case CSSPropertyWebkitTextEmphasisColor:
2535 case CSSPropertyWebkitTextFillColor:
2536 case CSSPropertyWebkitTextStrokeColor:
2537 // Also allow shorthands so that inherit/initial still work.
2538 case CSSPropertyBackground:
2539 case CSSPropertyBorderLeft:
2540 case CSSPropertyBorderRight:
2541 case CSSPropertyBorderTop:
2542 case CSSPropertyBorderBottom:
2543 case CSSPropertyOutline:
2544 case CSSPropertyWebkitColumnRule:
2546 case CSSPropertyFill:
2547 case CSSPropertyStroke:
2557 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2558 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2559 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2560 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2561 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2562 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
2563 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
2564 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
2565 bool CSSStyleSelector::useSVGZoomRules()
2567 return m_element && m_element->isSVGElement();
2570 #if ENABLE(CSS_GRID_LAYOUT)
2572 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, CSSStyleSelector* selector, Length& length)
2574 if (primitiveValue->getIdent() == CSSValueAuto) {
2579 int type = primitiveValue->primitiveType();
2580 if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2581 length = primitiveValue->computeLength<Length>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
2582 length.setQuirk(primitiveValue->isQuirkValue());
2586 if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
2587 length = Length(primitiveValue->getDoubleValue(), Percent);
2594 static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, CSSStyleSelector* selector)
2597 if (value->isPrimitiveValue()) {
2598 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2599 if (primitiveValue->getIdent() == CSSValueNone) {
2600 lengths.append(Length(Undefined));
2606 if (value->isValueList()) {
2607 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2608 CSSValue* currValue = i.value();
2609 if (!currValue->isPrimitiveValue())
2613 if (!createGridTrackBreadth(static_cast<CSSPrimitiveValue*>(currValue), selector, length))
2616 lengths.append(length);
2625 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
2627 bool isInherit = m_parentNode && value->isInheritedValue();
2628 bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
2630 ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2632 if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2633 // Limit the properties that can be applied to only the ones honored by :visited.
2637 CSSPropertyID property = static_cast<CSSPropertyID>(id);
2639 if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(property))
2640 m_parentStyle->setHasExplicitlyInheritedProperties();
2642 // check lookup table for implementations and use when available
2643 const PropertyHandler& handler = m_applyProperty.propertyHandler(property);
2644 if (handler.isValid()) {
2646 handler.applyInheritValue(this);
2648 handler.applyInitialValue(this);
2650 handler.applyValue(this, value);
2654 CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
2656 float zoomFactor = m_style->effectiveZoom();
2658 // What follows is a list that maps the CSS properties into their corresponding front-end
2659 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
2660 // are only hit when mapping "inherit" or "initial" into front-end values.
2662 // ident only properties
2663 case CSSPropertyBorderCollapse:
2664 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderCollapse, BorderCollapse)
2666 case CSSPropertyCaptionSide:
2667 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
2669 case CSSPropertyClear:
2670 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
2672 case CSSPropertyEmptyCells:
2673 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
2675 case CSSPropertyFloat:
2676 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
2678 case CSSPropertyPageBreakBefore:
2679 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2681 case CSSPropertyPageBreakAfter:
2682 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2684 case CSSPropertyPageBreakInside:
2685 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2687 case CSSPropertyPosition:
2688 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
2690 case CSSPropertyTableLayout:
2691 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(tableLayout, TableLayout)
2693 case CSSPropertyUnicodeBidi:
2694 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
2696 case CSSPropertyTextTransform:
2697 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
2699 case CSSPropertyVisibility:
2700 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
2702 case CSSPropertyWhiteSpace:
2703 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
2706 case CSSPropertyWordBreak:
2707 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
2709 case CSSPropertyWordWrap:
2710 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
2712 case CSSPropertyWebkitNbspMode:
2713 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
2715 case CSSPropertyWebkitLineBreak:
2716 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
2718 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2719 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2721 case CSSPropertyWidows:
2722 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(widows, Widows)
2724 case CSSPropertyOrphans:
2725 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(orphans, Orphans)
2728 case CSSPropertyClip:
2734 bool hasClip = true;
2736 if (m_parentStyle->hasClip()) {
2737 top = m_parentStyle->clipTop();
2738 right = m_parentStyle->clipRight();
2739 bottom = m_parentStyle->clipBottom();
2740 left = m_parentStyle->clipLeft();
2743 top = right = bottom = left = Length();
2745 } else if (isInitial) {
2747 top = right = bottom = left = Length();
2748 } else if (!primitiveValue) {
2750 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
2751 Rect* rect = primitiveValue->getRectValue();
2754 top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
2755 right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
2756 bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
2757 left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
2758 } else if (primitiveValue->getIdent() != CSSValueAuto) {
2761 m_style->setClip(top, right, bottom, left);
2762 m_style->setHasClip(hasClip);
2769 case CSSPropertyContent:
2770 // list of string, uri, counter, attr, i
2772 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2773 // note is a reminder that eventually "inherit" needs to be supported.
2776 m_style->clearContent();
2780 if (!value->isValueList())
2783 bool didSet = false;
2784 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2785 CSSValue* item = i.value();
2786 if (item->isImageGeneratorValue()) {
2787 m_style->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
2791 if (!item->isPrimitiveValue())
2794 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2795 switch (contentValue->primitiveType()) {
2796 case CSSPrimitiveValue::CSS_STRING:
2797 m_style->setContent(contentValue->getStringValue().impl(), didSet);
2800 case CSSPrimitiveValue::CSS_ATTR: {
2801 // FIXME: Can a namespace be specified for an attr(foo)?
2802 if (m_style->styleType() == NOPSEUDO)
2803 m_style->setUnique();
2805 m_parentStyle->setUnique();
2806 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2807 const AtomicString& value = m_element->getAttribute(attr);
2808 m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2810 // register the fact that the attribute value affects the style
2811 m_features.attrsInRules.add(attr.localName().impl());
2814 case CSSPrimitiveValue::CSS_URI: {
2815 if (!contentValue->isImageValue())
2817 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
2821 case CSSPrimitiveValue::CSS_COUNTER: {
2822 Counter* counterValue = contentValue->getCounterValue();
2823 EListStyleType listStyleType = NoneListStyle;
2824 int listStyleIdent = counterValue->listStyleIdent();
2825 if (listStyleIdent != CSSValueNone)
2826 listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2827 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
2828 m_style->setContent(counter.release(), didSet);
2832 case CSSPrimitiveValue::CSS_IDENT:
2833 switch (contentValue->getIdent()) {
2834 case CSSValueOpenQuote:
2835 m_style->setContent(OPEN_QUOTE, didSet);
2838 case CSSValueCloseQuote:
2839 m_style->setContent(CLOSE_QUOTE, didSet);
2842 case CSSValueNoOpenQuote:
2843 m_style->setContent(NO_OPEN_QUOTE, didSet);
2846 case CSSValueNoCloseQuote:
2847 m_style->setContent(NO_CLOSE_QUOTE, didSet);
2851 // normal and none do not have any effect.
2857 m_style->clearContent();
2860 case CSSPropertyQuotes:
2863 m_style->setQuotes(m_parentStyle->quotes());
2867 m_style->setQuotes(0);
2870 if (value->isValueList()) {
2871 CSSValueList* list = static_cast<CSSValueList*>(value);
2872 QuotesData* data = QuotesData::create(list->length());
2874 return; // Out of memory
2875 String* quotes = data->data();
2876 for (CSSValueListIterator i = list; i.hasMore(); i.advance()) {
2877 CSSValue* item = i.value();
2878 ASSERT(item->isPrimitiveValue());
2879 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2880 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
2881 quotes[i.index()] = primitiveValue->getStringValue();
2883 m_style->setQuotes(adoptRef(data));
2884 } else if (primitiveValue) {
2885 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
2886 if (primitiveValue->getIdent() == CSSValueNone)
2887 m_style->setQuotes(adoptRef(QuotesData::create(0)));
2890 case CSSPropertyFontFamily: {
2891 // list of strings and ids
2893 FontDescription parentFontDescription = m_parentStyle->fontDescription();
2894 FontDescription fontDescription = m_style->fontDescription();
2895 fontDescription.setGenericFamily(parentFontDescription.genericFamily());
2896 fontDescription.setFamily(parentFontDescription.firstFamily());
2897 fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
2898 setFontDescription(fontDescription);
2900 } else if (isInitial) {
2901 FontDescription initialDesc = FontDescription();
2902 FontDescription fontDescription = m_style->fontDescription();
2903 // We need to adjust the size to account for the generic family change from monospace
2904 // to non-monospace.
2905 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
2906 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
2907 fontDescription.setGenericFamily(initialDesc.genericFamily());
2908 if (!initialDesc.firstFamily().familyIsEmpty())
2909 fontDescription.setFamily(initialDesc.firstFamily());
2910 setFontDescription(fontDescription);
2914 if (!value->isValueList())
2916 FontDescription fontDescription = m_style->fontDescription();
2917 FontFamily& firstFamily = fontDescription.firstFamily();
2918 FontFamily* currFamily = 0;
2920 // Before mapping in a new font-family property, we should reset the generic family.
2921 bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
2922 fontDescription.setGenericFamily(FontDescription::NoFamily);
2924 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2925 CSSValue* item = i.value();
2926 if (!item->isPrimitiveValue())
2928 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2930 Settings* settings = m_checker.document()->settings();
2931 if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
2932 if (contentValue->isFontFamilyValue())
2933 face = static_cast<FontFamilyValue*>(contentValue)->familyName();
2934 } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
2935 switch (contentValue->getIdent()) {
2936 case CSSValueWebkitBody:
2937 face = settings->standardFontFamily();
2941 fontDescription.setGenericFamily(FontDescription::SerifFamily);
2943 case CSSValueSansSerif:
2944 face = sansSerifFamily;
2945 fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
2947 case CSSValueCursive:
2948 face = cursiveFamily;
2949 fontDescription.setGenericFamily(FontDescription::CursiveFamily);
2951 case CSSValueFantasy:
2952 face = fantasyFamily;
2953 fontDescription.setGenericFamily(FontDescription::FantasyFamily);
2955 case CSSValueMonospace:
2956 face = monospaceFamily;
2957 fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
2959 case CSSValueWebkitPictograph:
2960 face = pictographFamily;
2961 fontDescription.setGenericFamily(FontDescription::PictographFamily);
2966 if (!face.isEmpty()) {
2968 // Filling in the first family.
2969 firstFamily.setFamily(face);
2970 firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
2971 currFamily = &firstFamily;
2972 fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
2974 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
2975 newFamily->setFamily(face);
2976 currFamily->appendFamily(newFamily);
2977 currFamily = newFamily.get();
2982 // We can't call useFixedDefaultSize() until all new font families have been added
2983 // If currFamily is non-zero then we set at least one family on this description.
2985 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
2986 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
2988 setFontDescription(fontDescription);
2992 // shorthand properties
2993 case CSSPropertyBackground:
2995 m_style->clearBackgroundLayers();
2996 m_style->setBackgroundColor(Color());
2998 else if (isInherit) {
2999 m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3000 m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3003 case CSSPropertyWebkitMask:
3005 m_style->clearMaskLayers();
3007 m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
3009 case CSSPropertyFont:
3011 FontDescription fontDescription = m_parentStyle->fontDescription();
3012 m_style->setLineHeight(m_parentStyle->lineHeight());
3013 m_lineHeightValue = 0;
3014 setFontDescription(fontDescription);
3015 } else if (isInitial) {
3016 Settings* settings = m_checker.document()->settings();
3017 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3020 FontDescription fontDescription;
3021 fontDescription.setGenericFamily(FontDescription::StandardFamily);
3022 fontDescription.setRenderingMode(settings->fontRenderingMode());
3023 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3024 const AtomicString& standardFontFamily = m_checker.document()->settings()->standardFontFamily();
3025 if (!standardFontFamily.isEmpty()) {
3026 fontDescription.firstFamily().setFamily(standardFontFamily);
3027 fontDescription.firstFamily().appendFamily(0);
3029 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3030 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueMedium, false));
3031 m_style->setLineHeight(RenderStyle::initialLineHeight());
3032 m_lineHeightValue = 0;
3033 setFontDescription(fontDescription);
3034 } else if (primitiveValue) {
3035 m_style->setLineHeight(RenderStyle::initialLineHeight());
3036 m_lineHeightValue = 0;
3038 FontDescription fontDescription;
3039 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3041 // Double-check and see if the theme did anything. If not, don't bother updating the font.
3042 if (fontDescription.isAbsoluteSize()) {
3043 // Make sure the rendering mode and printer font settings are updated.
3044 Settings* settings = m_checker.document()->settings();
3045 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3048 fontDescription.setRenderingMode(settings->fontRenderingMode());
3049 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3051 // Handle the zoom factor.
3052 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3053 setFontDescription(fontDescription);
3055 } else if (value->isFontValue()) {
3056 FontValue *font = static_cast<FontValue*>(value);
3057 if (!font->style || !font->variant || !font->weight ||
3058 !font->size || !font->lineHeight || !font->family)
3060 applyProperty(CSSPropertyFontStyle, font->style.get());
3061 applyProperty(CSSPropertyFontVariant, font->variant.get());
3062 applyProperty(CSSPropertyFontWeight, font->weight.get());
3063 // The previous properties can dirty our font but they don't try to read the font's
3064 // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3065 // need query the dirtied font's x-height to get the computed size. To be safe in this
3066 // case, let's just update the font now.
3068 applyProperty(CSSPropertyFontSize, font->size.get());
3070 m_lineHeightValue = font->lineHeight.get();
3072 applyProperty(CSSPropertyFontFamily, font->family.get());
3077 case CSSPropertyWebkitAppearance:
3078 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(appearance, Appearance)
3080 case CSSPropertyImageRendering:
3081 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(imageRendering, ImageRendering);
3083 case CSSPropertyTextShadow:
3084 case CSSPropertyBoxShadow:
3085 case CSSPropertyWebkitBoxShadow: {
3087 if (id == CSSPropertyTextShadow)
3088 return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
3089 return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
3091 if (isInitial || primitiveValue) // initial | none
3092 return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
3094 if (!value->isValueList())
3097 for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3098 CSSValue* currValue = i.value();
3099 if (!currValue->isShadowValue())
3101 ShadowValue* item = static_cast<ShadowValue*>(currValue);
3102 int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3103 int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3104 int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3105 int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3106 ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3109 color = colorFromPrimitiveValue(item->color.get());
3110 OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3111 if (id == CSSPropertyTextShadow)
3112 m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3114 m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3118 case CSSPropertyWebkitBoxReflect: {
3119 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3120 if (primitiveValue) {
3121 m_style->setBoxReflect(RenderStyle::initialBoxReflect());
3125 if (!value->isReflectValue())
3128 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3129 RefPtr<StyleReflection> reflection = StyleReflection::create();
3130 reflection->setDirection(reflectValue->direction());
3131 if (reflectValue->offset()) {
3132 int type = reflectValue->offset()->primitiveType();
3133 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3134 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
3136 reflection->setOffset(reflectValue->offset()->computeLength<Length>(style(), m_rootElementStyle, zoomFactor));
3138 NinePieceImage mask;
3139 mask.setMaskDefaults();
3140 mapNinePieceImage(property, reflectValue->mask(), mask);
3141 reflection->setMask(mask);
3143 m_style->setBoxReflect(reflection.release());
3146 case CSSPropertyOpacity:
3147 HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
3148 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3149 return; // Error case.
3150 // Clamp opacity to the range 0-1
3151 m_style->setOpacity(clampTo<float>(primitiveValue->getDoubleValue(), 0, 1));
3153 case CSSPropertyWebkitBoxAlign:
3154 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxAlign, BoxAlign)
3156 case CSSPropertySrc: // Only used in @font-face rules.
3158 case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3160 case CSSPropertyWebkitBackfaceVisibility:
3161 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(backfaceVisibility, BackfaceVisibility)
3163 case CSSPropertyWebkitBoxDirection:
3164 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
3166 case CSSPropertyWebkitBoxLines:
3167 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
3169 case CSSPropertyWebkitBoxOrient:
3170 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
3172 case CSSPropertyWebkitBoxPack:
3173 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxPack, BoxPack)
3175 case CSSPropertyWebkitBoxFlex:
3176 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlex, BoxFlex)
3178 case CSSPropertyWebkitBoxFlexGroup:
3179 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlexGroup, BoxFlexGroup)
3181 case CSSPropertyWebkitBoxOrdinalGroup:
3182 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrdinalGroup, BoxOrdinalGroup)
3184 case CSSPropertyBoxSizing:
3185 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxSizing, BoxSizing);
3187 case CSSPropertyWebkitColumnSpan:
3188 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnSpan, ColumnSpan)
3190 case CSSPropertyWebkitColumnRuleStyle:
3191 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
3193 case CSSPropertyWebkitColumnBreakBefore:
3194 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
3196 case CSSPropertyWebkitColumnBreakAfter:
3197 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
3199 case CSSPropertyWebkitColumnBreakInside:
3200 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
3202 case CSSPropertyWebkitColumnRule:
3204 m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
3205 m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
3206 m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
3209 m_style->resetColumnRule();
3211 case CSSPropertyWebkitRegionBreakBefore:
3212 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakBefore, RegionBreakBefore, PageBreak)
3214 case CSSPropertyWebkitRegionBreakAfter:
3215 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakAfter, RegionBreakAfter, PageBreak)
3217 case CSSPropertyWebkitRegionBreakInside:
3218 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakInside, RegionBreakInside, PageBreak)
3220 case CSSPropertyWebkitMarquee:
3221 if (!m_parentNode || !value->isInheritedValue())
3223 m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
3224 m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
3225 m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
3226 m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
3227 m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
3229 case CSSPropertyWebkitMarqueeRepetition: {
3230 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3231 if (!primitiveValue)
3233 if (primitiveValue->getIdent() == CSSValueInfinite)
3234 m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
3235 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
3236 m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
3239 case CSSPropertyWebkitMarqueeSpeed: {
3240 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3241 if (!primitiveValue)
3243 if (primitiveValue->getIdent()) {
3244 switch (primitiveValue->getIdent()) {
3246 m_style->setMarqueeSpeed(500); // 500 msec.
3248 case CSSValueNormal:
3249 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
3252 m_style->setMarqueeSpeed(10); // 10msec. Super fast.
3256 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
3257 m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
3258 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
3259 m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3260 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
3261 m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3264 case CSSPropertyWebkitMarqueeIncrement: {
3265 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3266 if (!primitiveValue)
3268 if (primitiveValue->getIdent()) {
3269 switch (primitiveValue->getIdent()) {
3271 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3273 case CSSValueNormal:
3274 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3277 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3283 Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
3285 m_style->setMarqueeIncrement(marqueeLength);
3289 case CSSPropertyWebkitMarqueeStyle:
3290 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
3292 case CSSPropertyWebkitRegionOverflow:
3293 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(regionOverflow, RegionOverflow);
3295 case CSSPropertyWebkitMarqueeDirection:
3296 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
3298 case CSSPropertyWebkitUserDrag:
3299 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
3301 case CSSPropertyWebkitUserModify:
3302 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
3304 case CSSPropertyWebkitUserSelect:
3305 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
3308 case CSSPropertyTextOverflow: {
3309 // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
3310 // work with WinIE-specific pages that use the property.
3311 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textOverflow, TextOverflow)
3314 case CSSPropertyWebkitLineClamp: {
3315 HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
3316 if (!primitiveValue)
3318 int type = primitiveValue->primitiveType();
3319 if (type == CSSPrimitiveValue::CSS_NUMBER)
3320 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
3321 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3322 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
3325 case CSSPropertyWebkitHyphens:
3326 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(hyphens, Hyphens);
3328 case CSSPropertyWebkitLocale: {
3329 HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3330 if (primitiveValue->getIdent() == CSSValueAuto)
3331 m_style->setLocale(nullAtom);
3333 m_style->setLocale(primitiveValue->getStringValue());
3334 FontDescription fontDescription = m_style->fontDescription();
3335 fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
3336 setFontDescription(fontDescription);
3339 case CSSPropertyWebkitBorderFit:
3340 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderFit, BorderFit);
3342 case CSSPropertyWebkitTextSizeAdjust: {
3343 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
3344 if (!primitiveValue || !primitiveValue->getIdent())
3346 setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
3349 case CSSPropertyWebkitTextSecurity:
3350 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
3353 #if ENABLE(DASHBOARD_SUPPORT)
3354 case CSSPropertyWebkitDashboardRegion: {
3355 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3356 if (!primitiveValue)
3359 if (primitiveValue->getIdent() == CSSValueNone) {
3360 m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
3364 DashboardRegion *region = primitiveValue->getDashboardRegionValue();
3368 DashboardRegion *first = region;
3370 Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
3371 Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
3372 Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
3373 Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
3374 if (region->m_isCircle)
3375 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3376 else if (region->m_isRectangle)
3377 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3378 region = region->m_next.get();
3381 m_element->document()->setHasDashboardRegions(true);
3386 case CSSPropertyWebkitRtlOrdering:
3387 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(rtlOrdering, RTLOrdering)
3389 case CSSPropertyWebkitTextStrokeWidth: {
3390 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3392 switch (primitiveValue->getIdent()) {
3394 case CSSValueMedium:
3395 case CSSValueThick: {
3396 double result = 1.0 / 48;
3397 if (primitiveValue->getIdent() == CSSValueMedium)
3399 else if (primitiveValue->getIdent() == CSSValueThick)
3401 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3405 width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3408 m_style->setTextStrokeWidth(width);
3411 case CSSPropertyWebkitTransform: {
3412 HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3413 TransformOperations operations;
3414 createTransformOperations(value, style(), m_rootElementStyle, operations);
3415 m_style->setTransform(operations);
3418 case CSSPropertyWebkitTransformStyle:
3419 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(transformStyle3D, TransformStyle3D)
3421 case CSSPropertyWebkitPrintColorAdjust:
3422 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(printColorAdjust, PrintColorAdjust);
3424 case CSSPropertyWebkitPerspective: {
3425 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3426 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3427 m_style->setPerspective(0);
3431 float perspectiveValue;
3432 int type = primitiveValue->primitiveType();
3433 if (CSSPrimitiveValue::isUnitTypeLength(type))
3434 perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3435 else if (type == CSSPrimitiveValue::CSS_NUMBER) {
3436 // For backward compatibility, treat valueless numbers as px.
3437 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3441 if (perspectiveValue >= 0.0f)
3442 m_style->setPerspective(perspectiveValue);
3445 case CSSPropertyWebkitAnimation:
3447 m_style->clearAnimations();
3449 m_style->inheritAnimations(m_parentStyle->animations());
3451 case CSSPropertyWebkitTransition:
3453 m_style->clearTransitions();
3455 m_style->inheritTransitions(m_parentStyle->transitions());
3457 case CSSPropertyPointerEvents:
3459 #if ENABLE(DASHBOARD_SUPPORT)
3460 // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
3461 // pointer-events property by not applying it in Dashboard.
3462 Settings* settings = m_checker.document()->settings();
3463 if (settings && settings->usesDashboardBackwardCompatibilityMode())
3466 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(pointerEvents, PointerEvents)
3469 #if ENABLE(TOUCH_EVENTS)
3470 case CSSPropertyWebkitTapHighlightColor: {
3471 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
3472 if (!primitiveValue)
3475 Color col = colorFromPrimitiveValue(primitiveValue);
3476 m_style->setTapHighlightColor(col);
3480 case CSSPropertyWebkitColorCorrection:
3481 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(colorSpace, ColorSpace);
3483 case CSSPropertySpeak:
3484 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(speak, Speak);
3486 case CSSPropertyInvalid:
3488 // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
3489 case CSSPropertyWebkitBorderEnd:
3490 case CSSPropertyWebkitBorderEndColor:
3491 case CSSPropertyWebkitBorderEndStyle:
3492 case CSSPropertyWebkitBorderEndWidth:
3493 case CSSPropertyWebkitBorderStart:
3494 case CSSPropertyWebkitBorderStartColor:
3495 case CSSPropertyWebkitBorderStartStyle:
3496 case CSSPropertyWebkitBorderStartWidth:
3497 case CSSPropertyWebkitBorderBefore:
3498 case CSSPropertyWebkitBorderBeforeColor:
3499 case CSSPropertyWebkitBorderBeforeStyle:
3500 case CSSPropertyWebkitBorderBeforeWidth:
3501 case CSSPropertyWebkitBorderAfter:
3502 case CSSPropertyWebkitBorderAfterColor:
3503 case CSSPropertyWebkitBorderAfterStyle:
3504 case CSSPropertyWebkitBorderAfterWidth:
3505 case CSSPropertyWebkitMarginEnd:
3506 case CSSPropertyWebkitMarginStart:
3507 case CSSPropertyWebkitMarginBefore:
3508 case CSSPropertyWebkitMarginAfter:
3509 case CSSPropertyWebkitMarginCollapse:
3510 case CSSPropertyWebkitMarginBeforeCollapse:
3511 case CSSPropertyWebkitMarginTopCollapse:
3512 case CSSPropertyWebkitMarginAfterCollapse:
3513 case CSSPropertyWebkitMarginBottomCollapse:
3514 case CSSPropertyWebkitPaddingEnd:
3515 case CSSPropertyWebkitPaddingStart:
3516 case CSSPropertyWebkitPaddingBefore:
3517 case CSSPropertyWebkitPaddingAfter:
3518 case CSSPropertyWebkitLogicalWidth:
3519 case CSSPropertyWebkitLogicalHeight:
3520 case CSSPropertyWebkitMinLogicalWidth:
3521 case CSSPropertyWebkitMinLogicalHeight:
3522 case CSSPropertyWebkitMaxLogicalWidth:
3523 case CSSPropertyWebkitMaxLogicalHeight:
3525 int newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3526 ASSERT(newId != id);
3527 return applyProperty(newId, value);
3529 case CSSPropertyFontStretch:
3530 case CSSPropertyPage:
3531 case CSSPropertyTextLineThrough:
3532 case CSSPropertyTextLineThroughColor:
3533 case CSSPropertyTextLineThroughMode:
3534 case CSSPropertyTextLineThroughStyle:
3535 case CSSPropertyTextLineThroughWidth:
3536 case CSSPropertyTextOverline:
3537 case CSSPropertyTextOverlineColor:
3538 case CSSPropertyTextOverlineMode:
3539 case CSSPropertyTextOverlineStyle:
3540 case CSSPropertyTextOverlineWidth:
3541 case CSSPropertyTextUnderline:
3542 case CSSPropertyTextUnderlineColor:
3543 case CSSPropertyTextUnderlineMode:
3544 case CSSPropertyTextUnderlineStyle:
3545 case CSSPropertyTextUnderlineWidth:
3546 case CSSPropertyWebkitFontSizeDelta:
3547 case CSSPropertyWebkitTextDecorationsInEffect:
3548 case CSSPropertyWebkitTextStroke:
3549 case CSSPropertyWebkitTextEmphasis:
3552 // CSS Text Layout Module Level 3: Vertical writing support
3553 case CSSPropertyWebkitWritingMode: {
3554 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
3555 if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
3556 m_element->document()->setWritingModeSetOnDocumentElement(true);
3557 FontDescription fontDescription = m_style->fontDescription();
3558 fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
3559 setFontDescription(fontDescription);
3563 case CSSPropertyWebkitLineBoxContain: {
3564 HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
3565 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3566 m_style->setLineBoxContain(LineBoxContainNone);
3570 if (!value->isCSSLineBoxContainValue())
3573 CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
3574 m_style->setLineBoxContain(lineBoxContainValue->value());
3578 case CSSPropertyWebkitColumnAxis:
3579 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnAxis, ColumnAxis);
3582 case CSSPropertyWebkitWrapShapeInside:
3583 HANDLE_INHERIT_AND_INITIAL(wrapShapeInside, WrapShapeInside);
3584 if (!primitiveValue)
3586 if (primitiveValue->getIdent() == CSSValueAuto)
3587 m_style->setWrapShapeInside(0);
3588 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE)
3589 m_style->setWrapShapeInside(primitiveValue->getShapeValue());
3592 case CSSPropertyWebkitWrapShapeOutside:
3593 HANDLE_INHERIT_AND_INITIAL(wrapShapeOutside, WrapShapeOutside);
3594 if (!primitiveValue)
3596 if (primitiveValue->getIdent() == CSSValueAuto)
3597 m_style->setWrapShapeOutside(0);
3598 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_SHAPE)
3599 m_style->setWrapShapeOutside(primitiveValue->getShapeValue());
3602 // CSS Fonts Module Level 3
3603 case CSSPropertyWebkitFontFeatureSettings: {
3604 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
3605 setFontDescription(m_style->fontDescription().makeNormalFeatureSettings());
3609 if (!value->isValueList())
3612 FontDescription fontDescription = m_style->fontDescription();
3613 CSSValueList* list = static_cast<CSSValueList*>(value);
3614 RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
3615 int len = list->length();
3616 for (int i = 0; i < len; ++i) {
3617 CSSValue* item = list->itemWithoutBoundsCheck(i);
3618 if (!item->isFontFeatureValue())
3620 FontFeatureValue* feature = static_cast<FontFeatureValue*>(item);
3621 settings->append(FontFeature(feature->tag(), feature->value()));
3623 fontDescription.setFeatureSettings(settings.release());
3624 setFontDescription(fontDescription);
3628 #if ENABLE(CSS_FILTERS)
3629 case CSSPropertyWebkitFilter: {
3630 HANDLE_INHERIT_AND_INITIAL(filter, Filter);
3631 FilterOperations operations;
3632 createFilterOperations(value, style(), m_rootElementStyle, operations);
3633 m_style->setFilter(operations);
3637 #if ENABLE(CSS_GRID_LAYOUT)
3638 case CSSPropertyWebkitGridColumns: {
3639 Vector<Length> lengths;
3640 if (!createGridTrackList(value, lengths, this))
3642 m_style->setGridColumns(lengths);
3645 case CSSPropertyWebkitGridRows: {
3646 Vector<Length> lengths;
3647 if (!createGridTrackList(value, lengths, this))
3649 m_style->setGridRows(lengths);
3654 // These properties are implemented in the CSSStyleApplyProperty lookup table.
3655 case CSSPropertyColor:
3656 case CSSPropertyDirection:
3657 case CSSPropertyDisplay:
3658 case CSSPropertyBackgroundAttachment:
3659 case CSSPropertyBackgroundClip:
3660 case CSSPropertyWebkitBackgroundClip:
3661 case CSSPropertyWebkitBackgroundComposite:
3662 case CSSPropertyBackgroundOrigin:
3663 case CSSPropertyWebkitBackgroundOrigin:
3664 case CSSPropertyBackgroundImage:
3665 case CSSPropertyWebkitAspectRatio:
3666 case CSSPropertyBackgroundSize:
3667 case CSSPropertyWebkitBackgroundSize:
3668 case CSSPropertyWebkitMaskAttachment:
3669 case CSSPropertyWebkitMaskClip:
3670 case CSSPropertyWebkitMaskComposite:
3671 case CSSPropertyWebkitMaskOrigin:
3672 case CSSPropertyWebkitMaskImage:
3673 case CSSPropertyWebkitMaskSize:
3674 case CSSPropertyBackgroundColor:
3675 case CSSPropertyBorderBottomColor:
3676 case CSSPropertyBorderLeftColor:
3677 case CSSPropertyBorderRightColor:
3678 case CSSPropertyBorderTopColor:
3679 case CSSPropertyBorderTopStyle:
3680 case CSSPropertyBorderRightStyle:
3681 case CSSPropertyBorderBottomStyle:
3682 case CSSPropertyBorderLeftStyle:
3683 case CSSPropertyBorderTopWidth:
3684 case CSSPropertyBorderRightWidth:
3685 case CSSPropertyBorderBottomWidth:
3686 case CSSPropertyBorderLeftWidth:
3687 case CSSPropertyBorder:
3688 case CSSPropertyBorderStyle:
3689 case CSSPropertyBorderWidth:
3690 case CSSPropertyBorderColor:
3691 case CSSPropertyBorderImage:
3692 case CSSPropertyWebkitBorderImage:
3693 case CSSPropertyWebkitMaskBoxImage:
3694 case CSSPropertyBorderImageOutset:
3695 case CSSPropertyWebkitMaskBoxImageOutset:
3696 case CSSPropertyBorderImageRepeat:
3697 case CSSPropertyWebkitMaskBoxImageRepeat:
3698 case CSSPropertyBorderImageSlice:
3699 case CSSPropertyWebkitMaskBoxImageSlice:
3700 case CSSPropertyBorderImageWidth:
3701 case CSSPropertyWebkitMaskBoxImageWidth:
3702 case CSSPropertyBorderImageSource:
3703 case CSSPropertyWebkitMaskBoxImageSource:
3704 case CSSPropertyBorderTop:
3705 case CSSPropertyBorderRight:
3706 case CSSPropertyBorderBottom:
3707 case CSSPropertyBorderLeft:
3708 case CSSPropertyBorderRadius:
3709 case CSSPropertyWebkitBorderRadius:
3710 case CSSPropertyBorderTopLeftRadius:
3711 case CSSPropertyBorderTopRightRadius:
3712 case CSSPropertyBorderBottomLeftRadius:
3713 case CSSPropertyBorderBottomRightRadius:
3714 case CSSPropertyBorderSpacing:
3715 case CSSPropertyWebkitBorderHorizontalSpacing:
3716 case CSSPropertyWebkitBorderVerticalSpacing:
3717 case CSSPropertyCounterIncrement:
3718 case CSSPropertyCounterReset:
3719 case CSSPropertyLetterSpacing:
3720 case CSSPropertyWordSpacing:
3721 case CSSPropertyWebkitFlexOrder:
3722 case CSSPropertyWebkitFlexPack:
3723 case CSSPropertyWebkitFlexItemAlign:
3724 case CSSPropertyWebkitFlexDirection:
3725 case CSSPropertyWebkitFlexFlow:
3726 case CSSPropertyWebkitFlexWrap:
3727 case CSSPropertyFontSize:
3728 case CSSPropertyFontStyle:
3729 case CSSPropertyFontVariant:
3730 case CSSPropertyTextRendering:
3731 case CSSPropertyWebkitTextOrientation:
3732 case CSSPropertyWebkitFontSmoothing:
3733 case CSSPropertyFontWeight:
3734 case CSSPropertyOutline:
3735 case CSSPropertyOutlineStyle:
3736 case CSSPropertyOutlineWidth:
3737 case CSSPropertyOutlineOffset:
3738 case CSSPropertyWebkitColumnRuleWidth:
3739 case CSSPropertyOutlineColor:
3740 case CSSPropertyWebkitColumnRuleColor:
3741 case CSSPropertyWebkitTextEmphasisColor:
3742 case CSSPropertyWebkitTextFillColor:
3743 case CSSPropertyWebkitTextStrokeColor:
3744 case CSSPropertyBackgroundPosition:
3745 case CSSPropertyBackgroundPositionX:
3746 case CSSPropertyBackgroundPositionY:
3747 case CSSPropertyWebkitMaskPosition:
3748 case CSSPropertyWebkitMaskPositionX:
3749 case CSSPropertyWebkitMaskPositionY:
3750 case CSSPropertyBackgroundRepeat:
3751 case CSSPropertyBackgroundRepeatX:
3752 case CSSPropertyBackgroundRepeatY:
3753 case CSSPropertyWebkitMaskRepeat:
3754 case CSSPropertyWebkitMaskRepeatX:
3755 case CSSPropertyWebkitMaskRepeatY:
3756 case CSSPropertyOverflow:
3757 case CSSPropertyOverflowX:
3758 case CSSPropertyOverflowY:
3759 case CSSPropertyMaxWidth:
3760 case CSSPropertyTop:
3761 case CSSPropertyLeft:
3762 case CSSPropertyRight:
3763 case CSSPropertyBottom:
3764 case CSSPropertyWidth:
3765 case CSSPropertyMinWidth:
3766 case CSSPropertyLineHeight:
3767 case CSSPropertyListStyle:
3768 case CSSPropertyListStyleImage:
3769 case CSSPropertyListStylePosition:
3770 case CSSPropertyListStyleType:
3771 case CSSPropertyMarginTop:
3772 case CSSPropertyMarginRight:
3773 case CSSPropertyMarginBottom:
3774 case CSSPropertyMarginLeft:
3775 case CSSPropertyMargin:
3776 case CSSPropertyPaddingTop:
3777 case CSSPropertyPaddingRight:
3778 case CSSPropertyPaddingBottom:
3779 case CSSPropertyPaddingLeft:
3780 case CSSPropertyPadding:
3781 case CSSPropertyResize:
3782 case CSSPropertySize:
3783 case CSSPropertyTextAlign:
3784 case CSSPropertyTextDecoration:
3785 case CSSPropertyTextIndent:
3786 case CSSPropertyMaxHeight:
3787 case CSSPropertyHeight:
3788 case CSSPropertyMinHeight:
3789 case CSSPropertyVerticalAlign:
3790 case CSSPropertyWebkitTransformOriginX:
3791 case CSSPropertyWebkitTransformOriginY:
3792 case CSSPropertyWebkitTransformOriginZ:
3793 case CSSPropertyWebkitTransformOrigin:
3794 case CSSPropertyWebkitPerspectiveOriginX:
3795 case CSSPropertyWebkitPerspectiveOriginY:
3796 case CSSPropertyWebkitPerspectiveOrigin:
3797 case CSSPropertyWebkitAnimationDelay:
3798 case CSSPropertyWebkitAnimationDirection:
3799 case CSSPropertyWebkitAnimationDuration:
3800 case CSSPropertyWebkitAnimationFillMode:
3801 case CSSPropertyWebkitAnimationIterationCount:
3802 case CSSPropertyWebkitAnimationName:
3803 case CSSPropertyWebkitAnimationPlayState:
3804 case CSSPropertyWebkitAnimationTimingFunction:
3805 case CSSPropertyWebkitTransitionDelay:
3806 case CSSPropertyWebkitTransitionDuration:
3807 case CSSPropertyWebkitTransitionProperty:
3808 case CSSPropertyWebkitTransitionTimingFunction:
3809 case CSSPropertyCursor:
3810 case CSSPropertyWebkitColumns:
3811 case CSSPropertyWebkitColumnCount:
3812 case CSSPropertyWebkitColumnGap:
3813 case CSSPropertyWebkitColumnWidth:
3814 case CSSPropertyWebkitFlowInto:
3815 case CSSPropertyWebkitFlowFrom:
3816 case CSSPropertyWebkitFontKerning:
3817 case CSSPropertyWebkitHighlight:
3818 case CSSPropertyWebkitHyphenateCharacter:
3819 case CSSPropertyWebkitHyphenateLimitAfter:
3820 case CSSPropertyWebkitHyphenateLimitBefore:
3821 case CSSPropertyWebkitHyphenateLimitLines:
3822 case CSSPropertyWebkitLineGrid:
3823 case CSSPropertyWebkitLineGridSnap:
3824 case CSSPropertyWebkitTextCombine:
3825 case CSSPropertyWebkitTextEmphasisPosition:
3826 case CSSPropertyWebkitTextEmphasisStyle:
3827 case CSSPropertyWebkitWrapMargin:
3828 case CSSPropertyWebkitWrapPadding:
3829 case CSSPropertyWebkitWrapFlow:
3830 case CSSPropertyWebkitWrapThrough:
3831 case CSSPropertyWebkitWrap:
3832 case CSSPropertyZIndex:
3833 case CSSPropertyZoom:
3834 ASSERT_NOT_REACHED();
3838 // Try the SVG properties
3839 applySVGProperty(id, value);
3845 void CSSStyleSelector::mapFillAttachment(CSSPropertyID, FillLayer* layer, CSSValue* value)
3847 if (value->isInitialValue()) {
3848 layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
3852 if (!value->isPrimitiveValue())
3855 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3856 switch (primitiveValue->getIdent()) {
3858 layer->setAttachment(FixedBackgroundAttachment);
3860 case CSSValueScroll:
3861 layer->setAttachment(ScrollBackgroundAttachment);
3864 layer->setAttachment(LocalBackgroundAttachment);
3871 void CSSStyleSelector::mapFillClip(CSSPropertyID, FillLayer* layer, CSSValue* value)