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 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/)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
27 #include "CSSStyleSelector.h"
29 #include "Attribute.h"
30 #include "CSSBorderImageValue.h"
31 #include "CSSCursorImageValue.h"
32 #include "CSSFontFaceRule.h"
33 #include "CSSImportRule.h"
34 #include "CSSMediaRule.h"
35 #include "CSSPageRule.h"
36 #include "CSSParser.h"
37 #include "CSSPrimitiveValueMappings.h"
38 #include "CSSPropertyNames.h"
39 #include "CSSReflectValue.h"
40 #include "CSSRuleList.h"
41 #include "CSSSelector.h"
42 #include "CSSSelectorList.h"
43 #include "CSSStyleRule.h"
44 #include "CSSStyleSheet.h"
45 #include "CSSTimingFunctionValue.h"
46 #include "CSSValueList.h"
47 #include "CSSVariableDependentValue.h"
48 #include "CSSVariablesDeclaration.h"
49 #include "CSSVariablesRule.h"
50 #include "CachedImage.h"
52 #include "CounterContent.h"
53 #include "FocusController.h"
54 #include "FontFamilyValue.h"
55 #include "FontValue.h"
57 #include "FrameView.h"
58 #include "HTMLDocument.h"
59 #include "HTMLElement.h"
60 #include "HTMLInputElement.h"
61 #include "HTMLNames.h"
62 #include "HTMLTextAreaElement.h"
63 #include "KeyframeList.h"
65 #include "Matrix3DTransformOperation.h"
66 #include "MatrixTransformOperation.h"
67 #include "MediaList.h"
68 #include "MediaQueryEvaluator.h"
69 #include "NodeRenderStyle.h"
71 #include "PageGroup.h"
73 #include "PerspectiveTransformOperation.h"
75 #include "RenderScrollbar.h"
76 #include "RenderScrollbarTheme.h"
77 #include "RenderStyleConstants.h"
78 #include "RenderTheme.h"
79 #include "RotateTransformOperation.h"
80 #include "ScaleTransformOperation.h"
81 #include "SelectionController.h"
83 #include "ShadowValue.h"
84 #include "SkewTransformOperation.h"
85 #include "StyleCachedImage.h"
86 #include "StyleGeneratedImage.h"
87 #include "StyleSheetList.h"
89 #include "TransformationMatrix.h"
90 #include "TranslateTransformOperation.h"
91 #include "UserAgentStyleSheets.h"
92 #include "WebKitCSSKeyframeRule.h"
93 #include "WebKitCSSKeyframesRule.h"
94 #include "WebKitCSSTransformValue.h"
97 #include <wtf/StdLibExtras.h>
98 #include <wtf/Vector.h>
100 #if USE(PLATFORM_STRATEGIES)
101 #include "PlatformStrategies.h"
102 #include "VisitedLinkStrategy.h"
105 #if ENABLE(DASHBOARD_SUPPORT)
106 #include "DashboardRegion.h"
110 #include "XLinkNames.h"
111 #include "SVGNames.h"
115 #include "WMLNames.h"
119 #include <qwebhistoryinterface.h>
126 using namespace HTMLNames;
128 // #define STYLE_SHARING_STATS 1
130 #define HANDLE_INHERIT(prop, Prop) \
132 m_style->set##Prop(m_parentStyle->prop()); \
136 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
137 HANDLE_INHERIT(prop, Prop) \
139 m_style->set##Prop(RenderStyle::initial##Prop()); \
143 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
144 HANDLE_INHERIT(prop, Prop) \
146 m_style->set##Prop(RenderStyle::initial##Value());\
150 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
151 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
152 if (primitiveValue) \
153 m_style->set##Prop(*primitiveValue);
155 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
156 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
157 if (primitiveValue) \
158 m_style->set##Prop(*primitiveValue);
160 #define HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
162 FillLayer* currChild = m_style->access##LayerType##Layers(); \
163 FillLayer* prevChild = 0; \
164 const FillLayer* currParent = m_parentStyle->layerType##Layers(); \
165 while (currParent && currParent->is##Prop##Set()) { \
167 /* Need to make a new layer.*/ \
168 currChild = new FillLayer(LayerType##FillLayer); \
169 prevChild->setNext(currChild); \
171 currChild->set##Prop(currParent->prop()); \
172 prevChild = currChild; \
173 currChild = prevChild->next(); \
174 currParent = currParent->next(); \
177 while (currChild) { \
178 /* Reset any remaining layers to not have the property set. */ \
179 currChild->clear##Prop(); \
180 currChild = currChild->next(); \
182 } else if (isInitial) { \
183 FillLayer* currChild = m_style->access##LayerType##Layers(); \
184 currChild->set##Prop(FillLayer::initialFill##Prop(LayerType##FillLayer)); \
185 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
186 currChild->clear##Prop(); \
189 #define HANDLE_FILL_LAYER_VALUE(layerType, LayerType, prop, Prop, value) { \
190 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(layerType, LayerType, prop, Prop) \
191 if (isInherit || isInitial) \
193 FillLayer* currChild = m_style->access##LayerType##Layers(); \
194 FillLayer* prevChild = 0; \
195 if (value->isValueList()) { \
196 /* Walk each value and put it into a layer, creating new layers as needed. */ \
197 CSSValueList* valueList = static_cast<CSSValueList*>(value); \
198 for (unsigned int i = 0; i < valueList->length(); i++) { \
200 /* Need to make a new layer to hold this value */ \
201 currChild = new FillLayer(LayerType##FillLayer); \
202 prevChild->setNext(currChild); \
204 mapFill##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \
205 prevChild = currChild; \
206 currChild = currChild->next(); \
209 mapFill##Prop(currChild, value); \
210 currChild = currChild->next(); \
212 while (currChild) { \
213 /* Reset all remaining layers to not have the property set. */ \
214 currChild->clear##Prop(); \
215 currChild = currChild->next(); \
218 #define HANDLE_BACKGROUND_INHERIT_AND_INITIAL(prop, Prop) \
219 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(background, Background, prop, Prop)
221 #define HANDLE_BACKGROUND_VALUE(prop, Prop, value) \
222 HANDLE_FILL_LAYER_VALUE(background, Background, prop, Prop, value)
224 #define HANDLE_MASK_INHERIT_AND_INITIAL(prop, Prop) \
225 HANDLE_FILL_LAYER_INHERIT_AND_INITIAL(mask, Mask, prop, Prop)
227 #define HANDLE_MASK_VALUE(prop, Prop, value) \
228 HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value)
230 #define HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
232 AnimationList* list = m_style->accessAnimations(); \
233 const AnimationList* parentList = m_parentStyle->animations(); \
234 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
235 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
236 if (list->size() <= i) \
237 list->append(Animation::create()); \
238 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
241 /* Reset any remaining animations to not have the property set. */ \
242 for ( ; i < list->size(); ++i) \
243 list->animation(i)->clear##Prop(); \
244 } else if (isInitial) { \
245 AnimationList* list = m_style->accessAnimations(); \
246 if (list->isEmpty()) \
247 list->append(Animation::create()); \
248 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
249 for (size_t i = 1; i < list->size(); ++i) \
250 list->animation(0)->clear##Prop(); \
253 #define HANDLE_ANIMATION_VALUE(prop, Prop, value) { \
254 HANDLE_ANIMATION_INHERIT_AND_INITIAL(prop, Prop) \
255 if (isInherit || isInitial) \
257 AnimationList* list = m_style->accessAnimations(); \
258 size_t childIndex = 0; \
259 if (value->isValueList()) { \
260 /* Walk each value and put it into an animation, creating new animations as needed. */ \
261 CSSValueList* valueList = static_cast<CSSValueList*>(value); \
262 for (unsigned int i = 0; i < valueList->length(); i++) { \
263 if (childIndex <= list->size()) \
264 list->append(Animation::create()); \
265 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
269 if (list->isEmpty()) \
270 list->append(Animation::create()); \
271 mapAnimation##Prop(list->animation(childIndex), value); \
274 for ( ; childIndex < list->size(); ++childIndex) { \
275 /* Reset all remaining animations to not have the property set. */ \
276 list->animation(childIndex)->clear##Prop(); \
280 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
282 AnimationList* list = m_style->accessTransitions(); \
283 const AnimationList* parentList = m_parentStyle->transitions(); \
284 size_t i = 0, parentSize = parentList ? parentList->size() : 0; \
285 for ( ; i < parentSize && parentList->animation(i)->is##Prop##Set(); ++i) { \
286 if (list->size() <= i) \
287 list->append(Animation::create()); \
288 list->animation(i)->set##Prop(parentList->animation(i)->prop()); \
291 /* Reset any remaining transitions to not have the property set. */ \
292 for ( ; i < list->size(); ++i) \
293 list->animation(i)->clear##Prop(); \
294 } else if (isInitial) { \
295 AnimationList* list = m_style->accessTransitions(); \
296 if (list->isEmpty()) \
297 list->append(Animation::create()); \
298 list->animation(0)->set##Prop(Animation::initialAnimation##Prop()); \
299 for (size_t i = 1; i < list->size(); ++i) \
300 list->animation(0)->clear##Prop(); \
303 #define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
304 HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
305 if (isInherit || isInitial) \
307 AnimationList* list = m_style->accessTransitions(); \
308 size_t childIndex = 0; \
309 if (value->isValueList()) { \
310 /* Walk each value and put it into a transition, creating new animations as needed. */ \
311 CSSValueList* valueList = static_cast<CSSValueList*>(value); \
312 for (unsigned int i = 0; i < valueList->length(); i++) { \
313 if (childIndex <= list->size()) \
314 list->append(Animation::create()); \
315 mapAnimation##Prop(list->animation(childIndex), valueList->itemWithoutBoundsCheck(i)); \
319 if (list->isEmpty()) \
320 list->append(Animation::create()); \
321 mapAnimation##Prop(list->animation(childIndex), value); \
324 for ( ; childIndex < list->size(); ++childIndex) { \
325 /* Reset all remaining transitions to not have the property set. */ \
326 list->animation(childIndex)->clear##Prop(); \
330 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
331 if (id == propID) { \
332 m_style->set##Prop(m_parentStyle->prop()); \
336 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
337 if (id == propID) { \
338 if (m_parentStyle->prop().isValid()) \
339 m_style->set##Prop(m_parentStyle->prop()); \
341 m_style->set##Prop(m_parentStyle->propAlt()); \
345 #define HANDLE_INITIAL_COND(propID, Prop) \
346 if (id == propID) { \
347 m_style->set##Prop(RenderStyle::initial##Prop()); \
351 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
352 if (id == propID) { \
353 m_style->set##Prop(RenderStyle::initial##Value()); \
357 class CSSRuleSet : public Noncopyable {
362 typedef HashMap<AtomicStringImpl*, CSSRuleDataList*> AtomRuleMap;
364 void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
366 void addStyleRule(StyleBase* item);
367 void addRule(CSSStyleRule* rule, CSSSelector* sel);
368 void addPageRule(CSSStyleRule* rule, CSSSelector* sel);
369 void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
370 CSSStyleRule* rule, CSSSelector* sel);
372 CSSRuleDataList* getIDRules(AtomicStringImpl* key) { return m_idRules.get(key); }
373 CSSRuleDataList* getClassRules(AtomicStringImpl* key) { return m_classRules.get(key); }
374 CSSRuleDataList* getTagRules(AtomicStringImpl* key) { return m_tagRules.get(key); }
375 CSSRuleDataList* getUniversalRules() { return m_universalRules; }
376 CSSRuleDataList* getPageRules() { return m_pageRules; }
379 AtomRuleMap m_idRules;
380 AtomRuleMap m_classRules;
381 AtomRuleMap m_tagRules;
382 CSSRuleDataList* m_universalRules;
383 CSSRuleDataList* m_pageRules;
384 unsigned m_ruleCount;
385 unsigned m_pageRuleCount;
388 static CSSRuleSet* defaultStyle;
389 static CSSRuleSet* defaultQuirksStyle;
390 static CSSRuleSet* defaultPrintStyle;
391 static CSSRuleSet* defaultViewSourceStyle;
392 static CSSStyleSheet* simpleDefaultStyleSheet;
394 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
396 static void loadFullDefaultStyle();
397 static void loadSimpleDefaultStyle();
398 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
399 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}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}";
401 static bool elementCanUseSimpleDefaultStyle(Element* e)
403 return e->hasTagName(htmlTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
406 static const MediaQueryEvaluator& screenEval()
408 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
409 return staticScreenEval;
412 static const MediaQueryEvaluator& printEval()
414 DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
415 return staticPrintEval;
418 CSSStyleSelector::CSSStyleSelector(Document* doc, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
419 CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets,
420 bool strictParsing, bool matchAuthorAndUserStyles)
421 : m_backgroundData(BackgroundFillLayer)
422 , m_checker(doc, strictParsing)
425 , m_elementLinkState(NotInsideLink)
426 , m_fontSelector(CSSFontSelector::create(doc))
430 m_matchAuthorAndUserStyles = matchAuthorAndUserStyles;
432 Element* root = doc->documentElement();
435 if (!root || elementCanUseSimpleDefaultStyle(root))
436 loadSimpleDefaultStyle();
438 loadFullDefaultStyle();
443 // construct document root element default style. this is needed
444 // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
445 // This is here instead of constructor, because when constructor is run,
446 // document doesn't have documentElement
447 // NOTE: this assumes that element that gets passed to styleForElement -call
448 // is always from the document that owns the style selector
449 FrameView* view = doc->view();
451 m_medium = new MediaQueryEvaluator(view->mediaType());
453 m_medium = new MediaQueryEvaluator("all");
456 m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
458 if (m_rootDefaultStyle && view) {
460 m_medium = new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get());
463 // FIXME: This sucks! The user sheet is reparsed every time!
464 if (pageUserSheet || pageGroupUserSheets) {
465 m_userStyle = new CSSRuleSet();
467 m_userStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
468 if (pageGroupUserSheets) {
469 unsigned length = pageGroupUserSheets->size();
470 for (unsigned i = 0; i < length; i++)
471 m_userStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
475 // add stylesheets from document
476 m_authorStyle = new CSSRuleSet();
478 // Add rules from elements like SVG's <font-face>
479 if (mappedElementSheet)
480 m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
482 unsigned length = styleSheets->length();
483 for (unsigned i = 0; i < length; i++) {
484 StyleSheet* sheet = styleSheets->item(i);
485 if (sheet->isCSSStyleSheet() && !sheet->disabled())
486 m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
489 if (doc->renderer() && doc->renderer()->style())
490 doc->renderer()->style()->font().update(fontSelector());
493 // This is a simplified style setting function for keyframe styles
494 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
496 AtomicString s(rule->name());
497 m_keyframesRuleMap.add(s.impl(), rule);
500 void CSSStyleSelector::init()
503 m_matchedDecls.clear();
505 m_rootDefaultStyle = 0;
509 CSSStyleSelector::~CSSStyleSelector()
511 m_fontSelector->clearDocument();
513 delete m_authorStyle;
515 deleteAllValues(m_viewportDependentMediaQueryResults);
516 m_keyframesRuleMap.clear();
519 static CSSStyleSheet* parseUASheet(const String& str)
521 CSSStyleSheet* sheet = CSSStyleSheet::create().releaseRef(); // leak the sheet on purpose
522 sheet->parseString(str);
526 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
528 return parseUASheet(String(characters, size));
531 static void loadFullDefaultStyle()
533 if (simpleDefaultStyleSheet) {
534 ASSERT(defaultStyle);
536 simpleDefaultStyleSheet->deref();
537 defaultStyle = new CSSRuleSet;
538 simpleDefaultStyleSheet = 0;
540 ASSERT(!defaultStyle);
541 defaultStyle = new CSSRuleSet;
542 defaultPrintStyle = new CSSRuleSet;
543 defaultQuirksStyle = new CSSRuleSet;
546 // Strict-mode rules.
547 String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
548 CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
549 defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
550 defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
552 // Quirks-mode rules.
553 String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
554 CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
555 defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
558 static void loadSimpleDefaultStyle()
560 ASSERT(!defaultStyle);
561 ASSERT(!simpleDefaultStyleSheet);
563 defaultStyle = new CSSRuleSet;
564 defaultPrintStyle = new CSSRuleSet;
565 defaultQuirksStyle = new CSSRuleSet;
567 simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
568 defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
570 // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
573 static void loadViewSourceStyle()
575 ASSERT(!defaultViewSourceStyle);
576 defaultViewSourceStyle = new CSSRuleSet;
577 defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
580 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* decl)
582 if (!decl->hasVariableDependentValue()) {
583 m_matchedDecls.append(decl);
587 // See if we have already resolved the variables in this declaration.
588 CSSMutableStyleDeclaration* resolvedDecl = m_resolvedVariablesDeclarations.get(decl).get();
590 m_matchedDecls.append(resolvedDecl);
594 // If this declaration has any variables in it, then we need to make a cloned
595 // declaration with as many variables resolved as possible for this style selector's media.
596 RefPtr<CSSMutableStyleDeclaration> newDecl = CSSMutableStyleDeclaration::create(decl->parentRule());
597 m_matchedDecls.append(newDecl.get());
598 m_resolvedVariablesDeclarations.set(decl, newDecl);
600 HashSet<String> usedBlockVariables;
601 resolveVariablesForDeclaration(decl, newDecl.get(), usedBlockVariables);
604 void CSSStyleSelector::resolveVariablesForDeclaration(CSSMutableStyleDeclaration* decl, CSSMutableStyleDeclaration* newDecl, HashSet<String>& usedBlockVariables)
606 // Now iterate over the properties in the original declaration. As we resolve variables we'll end up
607 // mutating the new declaration (possibly expanding shorthands). The new declaration has no m_node
608 // though, so it can't mistakenly call setChanged on anything.
609 CSSMutableStyleDeclaration::const_iterator end = decl->end();
610 for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {
611 const CSSProperty& current = *it;
612 if (!current.value()->isVariableDependentValue()) {
613 // We can just add the parsed property directly.
614 newDecl->addParsedProperty(current);
617 CSSValueList* valueList = static_cast<CSSVariableDependentValue*>(current.value())->valueList();
620 CSSParserValueList resolvedValueList;
621 unsigned s = valueList->length();
622 bool fullyResolved = true;
623 for (unsigned i = 0; i < s; ++i) {
624 CSSValue* val = valueList->item(i);
625 CSSPrimitiveValue* primitiveValue = val->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(val) : 0;
626 if (primitiveValue && primitiveValue->isVariable()) {
627 CSSVariablesRule* rule = m_variablesMap.get(primitiveValue->getStringValue());
628 if (!rule || !rule->variables()) {
629 fullyResolved = false;
633 if (current.id() == CSSPropertyWebkitVariableDeclarationBlock && s == 1) {
634 fullyResolved = false;
635 if (!usedBlockVariables.contains(primitiveValue->getStringValue())) {
636 CSSMutableStyleDeclaration* declBlock = rule->variables()->getParsedVariableDeclarationBlock(primitiveValue->getStringValue());
638 usedBlockVariables.add(primitiveValue->getStringValue());
639 resolveVariablesForDeclaration(declBlock, newDecl, usedBlockVariables);
644 CSSValueList* resolvedVariable = rule->variables()->getParsedVariable(primitiveValue->getStringValue());
645 if (!resolvedVariable) {
646 fullyResolved = false;
649 unsigned valueSize = resolvedVariable->length();
650 for (unsigned j = 0; j < valueSize; ++j)
651 resolvedValueList.addValue(resolvedVariable->item(j)->parserValue());
653 resolvedValueList.addValue(val->parserValue());
659 // We now have a fully resolved new value list. We want the parser to use this value list
660 // and parse our new declaration.
661 CSSParser(m_checker.m_strictParsing).parsePropertyWithResolvedVariables(current.id(), current.isImportant(), newDecl, &resolvedValueList);
665 void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
667 m_matchedRules.clear();
669 if (!rules || !m_element)
672 // We need to collect the rules for id, class, tag, and everything else into a buffer and
673 // then sort the buffer.
674 if (m_element->hasID())
675 matchRulesForList(rules->getIDRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex);
676 if (m_element->hasClass()) {
677 ASSERT(m_styledElement);
678 const SpaceSplitString& classNames = m_styledElement->classNames();
679 size_t size = classNames.size();
680 for (size_t i = 0; i < size; ++i)
681 matchRulesForList(rules->getClassRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex);
683 matchRulesForList(rules->getTagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex);
684 matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
686 // If we didn't match any rules, we're done.
687 if (m_matchedRules.isEmpty())
690 // Sort the set of matched rules.
691 sortMatchedRules(0, m_matchedRules.size());
693 // Now transfer the set of matched rules over to our list of decls.
694 if (!m_checker.m_collectRulesOnly) {
695 for (unsigned i = 0; i < m_matchedRules.size(); i++)
696 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
698 for (unsigned i = 0; i < m_matchedRules.size(); i++) {
700 m_ruleList = CSSRuleList::create();
701 m_ruleList->append(m_matchedRules[i]->rule());
706 void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules, int& firstRuleIndex, int& lastRuleIndex)
711 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
712 CSSStyleRule* rule = d->rule();
713 if (checkSelector(d->selector())) {
714 // If the rule has no properties to apply, then ignore it.
715 CSSMutableStyleDeclaration* decl = rule->declaration();
716 if (!decl || !decl->length())
719 // If we're matching normal rules, set a pseudo bit if
720 // we really just matched a pseudo-element.
721 if (m_dynamicPseudo != NOPSEUDO && m_checker.m_pseudoStyle == NOPSEUDO) {
722 if (m_checker.m_collectRulesOnly)
724 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
725 m_style->setHasPseudoStyle(m_dynamicPseudo);
727 // Update our first/last rule indices in the matched rules array.
728 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
729 if (firstRuleIndex == -1)
730 firstRuleIndex = lastRuleIndex;
732 // Add this rule to our list of matched rules.
739 static bool operator >(CSSRuleData& r1, CSSRuleData& r2)
741 int spec1 = r1.selector()->specificity();
742 int spec2 = r2.selector()->specificity();
743 return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2;
746 static bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
751 void CSSStyleSelector::sortMatchedRules(unsigned start, unsigned end)
753 if (start >= end || (end - start == 1))
754 return; // Sanity check.
756 if (end - start <= 6) {
757 // Apply a bubble sort for smaller lists.
758 for (unsigned i = end - 1; i > start; i--) {
760 for (unsigned j = start; j < i; j++) {
761 CSSRuleData* elt = m_matchedRules[j];
762 CSSRuleData* elt2 = m_matchedRules[j + 1];
765 m_matchedRules[j] = elt2;
766 m_matchedRules[j + 1] = elt;
775 // Perform a merge sort for larger lists.
776 unsigned mid = (start + end) / 2;
777 sortMatchedRules(start, mid);
778 sortMatchedRules(mid, end);
780 CSSRuleData* elt = m_matchedRules[mid - 1];
781 CSSRuleData* elt2 = m_matchedRules[mid];
783 // Handle the fast common case (of equal specificity). The list may already
784 // be completely sorted.
788 // We have to merge sort. Ensure our merge buffer is big enough to hold
790 Vector<CSSRuleData*> rulesMergeBuffer;
791 rulesMergeBuffer.reserveInitialCapacity(end - start);
796 elt = m_matchedRules[i1];
797 elt2 = m_matchedRules[i2];
799 while (i1 < mid || i2 < end) {
800 if (i1 < mid && (i2 == end || *elt <= *elt2)) {
801 rulesMergeBuffer.append(elt);
803 elt = m_matchedRules[i1];
805 rulesMergeBuffer.append(elt2);
807 elt2 = m_matchedRules[i2];
811 for (unsigned i = start; i < end; i++)
812 m_matchedRules[i] = rulesMergeBuffer[i - start];
815 inline EInsideLink CSSStyleSelector::SelectorChecker::determineLinkState(Element* element) const
817 if (!element || !element->isLink())
818 return NotInsideLink;
819 return determineLinkStateSlowCase(element);
822 inline void CSSStyleSelector::initElement(Element* e)
824 if (m_element != e) {
826 m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
827 m_elementLinkState = m_checker.determineLinkState(m_element);
831 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
833 m_checker.m_pseudoStyle = pseudoID;
835 m_parentNode = e ? e->parentNode() : 0;
838 if (!m_parentNode && e && e->isSVGElement() && e->isShadowNode())
839 m_parentNode = e->shadowParentNode();
843 m_parentStyle = parentStyle;
845 m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
847 Node* docElement = e ? e->document()->documentElement() : 0;
848 RenderStyle* docStyle = m_checker.m_document->renderStyle();
849 m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
853 m_matchedDecls.clear();
860 static inline const AtomicString* linkAttribute(Node* node)
865 ASSERT(node->isElementNode());
866 Element* element = static_cast<Element*>(node);
867 if (element->isHTMLElement())
868 return &element->fastGetAttribute(hrefAttr);
871 if (element->isWMLElement()) {
872 // <anchor> elements don't have href attributes, but we still want to
873 // appear as link, so linkAttribute() has to return a non-null value!
874 if (element->hasTagName(WMLNames::anchorTag))
877 return &element->fastGetAttribute(hrefAttr);
882 if (element->isSVGElement())
883 return &element->fastGetAttribute(XLinkNames::hrefAttr);
889 CSSStyleSelector::SelectorChecker::SelectorChecker(Document* document, bool strictParsing)
890 : m_document(document)
891 , m_strictParsing(strictParsing)
892 , m_collectRulesOnly(false)
893 , m_pseudoStyle(NOPSEUDO)
894 , m_documentIsHTML(document->isHTMLDocument())
895 , m_matchVisitedPseudoClass(false)
899 EInsideLink CSSStyleSelector::SelectorChecker::determineLinkStateSlowCase(Element* element) const
901 ASSERT(element->isLink());
903 const AtomicString* attr = linkAttribute(element);
904 if (!attr || attr->isNull())
905 return NotInsideLink;
908 Vector<UChar, 512> url;
909 visitedURL(m_document->baseURL(), *attr, url);
911 return InsideUnvisitedLink;
913 // If the Qt4.4 interface for the history is used, we will have to fallback
914 // to the old global history.
915 QWebHistoryInterface* iface = QWebHistoryInterface::defaultInterface();
917 return iface->historyContains(QString(reinterpret_cast<QChar*>(url.data()), url.size())) ? InsideVisitedLink : InsideUnvisitedLink;
919 LinkHash hash = visitedLinkHash(url.data(), url.size());
921 return InsideUnvisitedLink;
923 LinkHash hash = visitedLinkHash(m_document->baseURL(), *attr);
925 return InsideUnvisitedLink;
928 Frame* frame = m_document->frame();
930 return InsideUnvisitedLink;
932 Page* page = frame->page();
934 return InsideUnvisitedLink;
936 m_linksCheckedForVisitedState.add(hash);
938 #if USE(PLATFORM_STRATEGIES)
939 return platformStrategies()->visitedLinkStrategy()->isLinkVisited(page, hash) ? InsideVisitedLink : InsideUnvisitedLink;
941 return page->group().isLinkVisited(hash) ? InsideVisitedLink : InsideUnvisitedLink;
945 bool CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* element) const
947 PseudoId dynamicPseudo = NOPSEUDO;
948 return checkSelector(sel, element, 0, dynamicPseudo, false, false) == SelectorMatches;
951 #ifdef STYLE_SHARING_STATS
952 static int fraction = 0;
953 static int total = 0;
956 static const unsigned cStyleSearchThreshold = 10;
958 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned depth)
960 if (parent && parent->isStyledElement()) {
961 StyledElement* p = static_cast<StyledElement*>(parent);
962 if (!p->inlineStyleDecl() && !p->hasID()) {
963 Node* r = p->previousSibling();
964 unsigned subcount = 0;
965 RenderStyle* st = p->renderStyle();
967 if (r->renderStyle() == st)
968 return r->lastChild();
969 if (subcount++ == cStyleSearchThreshold)
971 r = r->previousSibling();
973 if (!r && depth < cStyleSearchThreshold)
974 r = locateCousinList(parent->parentElement(), depth + 1);
976 if (r->renderStyle() == st)
977 return r->lastChild();
978 if (subcount++ == cStyleSearchThreshold)
980 r = r->previousSibling();
987 bool CSSStyleSelector::canShareStyleWithElement(Node* n)
989 if (n->isStyledElement()) {
990 StyledElement* s = static_cast<StyledElement*>(n);
991 RenderStyle* style = s->renderStyle();
992 if (style && !style->unique() &&
993 (s->tagQName() == m_element->tagQName()) && !s->hasID() &&
994 (s->hasClass() == m_element->hasClass()) && !s->inlineStyleDecl() &&
995 (s->hasMappedAttributes() == m_styledElement->hasMappedAttributes()) &&
996 (s->isLink() == m_element->isLink()) &&
997 !style->affectedByAttributeSelectors() &&
998 (s->hovered() == m_element->hovered()) &&
999 (s->active() == m_element->active()) &&
1000 (s->focused() == m_element->focused()) &&
1001 (s != s->document()->cssTarget() && m_element != m_element->document()->cssTarget()) &&
1002 (s->fastGetAttribute(typeAttr) == m_element->fastGetAttribute(typeAttr)) &&
1003 (s->fastGetAttribute(XMLNames::langAttr) == m_element->fastGetAttribute(XMLNames::langAttr)) &&
1004 (s->fastGetAttribute(langAttr) == m_element->fastGetAttribute(langAttr)) &&
1005 (s->fastGetAttribute(readonlyAttr) == m_element->fastGetAttribute(readonlyAttr)) &&
1006 (s->fastGetAttribute(cellpaddingAttr) == m_element->fastGetAttribute(cellpaddingAttr))) {
1007 bool isControl = s->isFormControlElement();
1008 if (isControl != m_element->isFormControlElement())
1011 InputElement* thisInputElement = toInputElement(s);
1012 InputElement* otherInputElement = toInputElement(m_element);
1013 if (thisInputElement && otherInputElement) {
1014 if ((thisInputElement->isAutofilled() != otherInputElement->isAutofilled()) ||
1015 (thisInputElement->isChecked() != otherInputElement->isChecked()) ||
1016 (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate()))
1021 if (s->isEnabledFormControl() != m_element->isEnabledFormControl())
1024 if (s->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1027 if (!m_element->document()->containsValidityStyleRules())
1030 bool willValidate = s->willValidate();
1031 if (willValidate != m_element->willValidate())
1034 if (willValidate && (s->isValidFormControlElement() != m_element->isValidFormControlElement()))
1038 if (style->transitions() || style->animations())
1041 bool classesMatch = true;
1042 if (s->hasClass()) {
1043 const AtomicString& class1 = m_element->fastGetAttribute(classAttr);
1044 const AtomicString& class2 = s->fastGetAttribute(classAttr);
1045 classesMatch = (class1 == class2);
1049 bool mappedAttrsMatch = true;
1050 if (s->hasMappedAttributes())
1051 mappedAttrsMatch = s->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap());
1052 if (mappedAttrsMatch) {
1054 if (m_elementLinkState != style->insideLink())
1065 ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
1067 if (m_styledElement && !m_styledElement->inlineStyleDecl() && !m_styledElement->hasID() && !m_styledElement->document()->usesSiblingRules()) {
1068 // Check previous siblings.
1071 for (n = m_element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1073 if (canShareStyleWithElement(n))
1074 return n->renderStyle();
1075 if (count++ == cStyleSearchThreshold)
1077 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1080 n = locateCousinList(m_element->parentElement());
1082 if (canShareStyleWithElement(n))
1083 return n->renderStyle();
1084 if (count++ == cStyleSearchThreshold)
1086 for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling()) { }
1092 void CSSStyleSelector::matchUARules(int& firstUARule, int& lastUARule)
1094 // First we match rules from the user agent sheet.
1095 CSSRuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1096 ? defaultPrintStyle : defaultStyle;
1097 matchRules(userAgentStyleSheet, firstUARule, lastUARule);
1099 // In quirks mode, we match rules from the quirks user agent sheet.
1100 if (!m_checker.m_strictParsing)
1101 matchRules(defaultQuirksStyle, firstUARule, lastUARule);
1103 // If we're in view source mode, then we match rules from the view source style sheet.
1104 if (m_checker.m_document->frame() && m_checker.m_document->frame()->inViewSourceMode()) {
1105 if (!defaultViewSourceStyle)
1106 loadViewSourceStyle();
1107 matchRules(defaultViewSourceStyle, firstUARule, lastUARule);
1111 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1113 FrameView* view = document->view();
1115 RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1116 documentStyle->setDisplay(BLOCK);
1117 documentStyle->setVisuallyOrdered(document->visuallyOrdered());
1118 documentStyle->setZoom(view ? view->pageZoomFactor() : 1);
1120 FontDescription fontDescription;
1121 fontDescription.setUsePrinterFont(document->printing());
1122 if (Settings* settings = document->settings()) {
1123 fontDescription.setRenderingMode(settings->fontRenderingMode());
1124 if (document->printing() && !settings->shouldPrintBackgrounds())
1125 documentStyle->setForceBackgroundsToWhite(true);
1126 const AtomicString& stdfont = settings->standardFontFamily();
1127 if (!stdfont.isEmpty()) {
1128 fontDescription.firstFamily().setFamily(stdfont);
1129 fontDescription.firstFamily().appendFamily(0);
1131 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1132 int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1133 fontDescription.setSpecifiedSize(size);
1134 bool useSVGZoomRules = document->isSVGDocument();
1135 fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1138 documentStyle->setFontDescription(fontDescription);
1139 documentStyle->font().update(0);
1140 if (document->inCompatMode())
1141 documentStyle->setHtmlHacks(true); // enable html specific rendering tricks
1143 return documentStyle.release();
1146 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1147 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1149 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* e, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault, bool matchVisitedPseudoClass)
1151 // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1152 // will vanish if a style recalc happens during loading.
1153 if (allowSharing && !e->document()->haveStylesheetsLoaded() && !e->renderer()) {
1154 if (!s_styleNotYetAvailable) {
1155 s_styleNotYetAvailable = RenderStyle::create().releaseRef();
1156 s_styleNotYetAvailable->ref();
1157 s_styleNotYetAvailable->setDisplay(NONE);
1158 s_styleNotYetAvailable->font().update(m_fontSelector);
1160 s_styleNotYetAvailable->ref();
1161 e->document()->setHasNodesWithPlaceholderStyle();
1162 return s_styleNotYetAvailable;
1167 RenderStyle* sharedStyle = locateSharedStyle();
1171 initForStyleResolve(e, defaultParent);
1173 // Compute our style allowing :visited to match first.
1174 RefPtr<RenderStyle> visitedStyle;
1175 if (!matchVisitedPseudoClass && m_parentStyle && (m_parentStyle->insideLink() || e->isLink()) && e->document()->usesLinkRules()) {
1176 // Fetch our parent style.
1177 RenderStyle* parentStyle = m_parentStyle;
1179 // Use the parent's visited style if one exists.
1180 RenderStyle* parentVisitedStyle = m_parentStyle->getCachedPseudoStyle(VISITED_LINK);
1181 if (parentVisitedStyle)
1182 parentStyle = parentVisitedStyle;
1184 visitedStyle = styleForElement(e, parentStyle, false, false, true);
1186 if (m_elementLinkState == InsideUnvisitedLink)
1187 visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that, since we don't need it.
1189 visitedStyle->setStyleType(VISITED_LINK);
1191 initForStyleResolve(e, defaultParent);
1194 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1196 m_style = RenderStyle::create();
1199 m_style->inheritFrom(m_parentStyle);
1201 m_parentStyle = style();
1204 m_style->setIsLink(true);
1205 m_style->setInsideLink(m_elementLinkState);
1208 if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(e))
1209 loadFullDefaultStyle();
1212 static bool loadedSVGUserAgentSheet;
1213 if (e->isSVGElement() && !loadedSVGUserAgentSheet) {
1215 loadedSVGUserAgentSheet = true;
1216 CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
1217 defaultStyle->addRulesFromSheet(svgSheet, screenEval());
1218 defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
1223 static bool loadedMathMLUserAgentSheet;
1224 if (e->isMathMLElement() && !loadedMathMLUserAgentSheet) {
1226 loadedMathMLUserAgentSheet = true;
1227 CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
1228 defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
1229 defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
1234 static bool loadedWMLUserAgentSheet;
1235 if (e->isWMLElement() && !loadedWMLUserAgentSheet) {
1237 loadedWMLUserAgentSheet = true;
1238 CSSStyleSheet* wmlSheet = parseUASheet(wmlUserAgentStyleSheet, sizeof(wmlUserAgentStyleSheet));
1239 defaultStyle->addRulesFromSheet(wmlSheet, screenEval());
1240 defaultPrintStyle->addRulesFromSheet(wmlSheet, printEval());
1245 static bool loadedMediaStyleSheet;
1246 if (!loadedMediaStyleSheet && (e->hasTagName(videoTag) || e->hasTagName(audioTag))) {
1247 loadedMediaStyleSheet = true;
1248 String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraMediaControlsStyleSheet();
1249 CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
1250 defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
1251 defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
1255 int firstUARule = -1, lastUARule = -1;
1256 int firstUserRule = -1, lastUserRule = -1;
1257 int firstAuthorRule = -1, lastAuthorRule = -1;
1258 matchUARules(firstUARule, lastUARule);
1260 if (!resolveForRootDefault) {
1261 // 4. Now we check user sheet rules.
1262 if (m_matchAuthorAndUserStyles)
1263 matchRules(m_userStyle, firstUserRule, lastUserRule);
1265 // 5. Now check author rules, beginning first with presentational attributes
1266 // mapped from HTML.
1267 if (m_styledElement) {
1268 // Ask if the HTML element has mapped attributes.
1269 if (m_styledElement->hasMappedAttributes()) {
1270 // Walk our attribute list and add in each decl.
1271 const NamedNodeMap* map = m_styledElement->attributeMap();
1272 for (unsigned i = 0; i < map->length(); i++) {
1273 Attribute* attr = map->attributeItem(i);
1274 if (attr->isMappedAttribute() && attr->decl()) {
1275 lastAuthorRule = m_matchedDecls.size();
1276 if (firstAuthorRule == -1)
1277 firstAuthorRule = lastAuthorRule;
1278 addMatchedDeclaration(attr->decl());
1283 // Now we check additional mapped declarations.
1284 // Tables and table cells share an additional mapped rule that must be applied
1285 // after all attributes, since their mapped style depends on the values of multiple attributes.
1286 if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
1287 m_additionalAttributeStyleDecls.clear();
1288 m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
1289 if (!m_additionalAttributeStyleDecls.isEmpty()) {
1290 unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
1291 if (firstAuthorRule == -1)
1292 firstAuthorRule = m_matchedDecls.size();
1293 lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
1294 for (unsigned i = 0; i < additionalDeclsSize; i++)
1295 addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
1300 // 6. Check the rules in author sheets next.
1301 if (m_matchAuthorAndUserStyles)
1302 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1304 // 7. Now check our inline style attribute.
1305 if (m_matchAuthorAndUserStyles && m_styledElement) {
1306 CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
1308 lastAuthorRule = m_matchedDecls.size();
1309 if (firstAuthorRule == -1)
1310 firstAuthorRule = lastAuthorRule;
1311 addMatchedDeclaration(inlineDecl);
1316 // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1317 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1319 // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
1320 // high-priority properties first, i.e., those properties that other properties depend on.
1321 // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1322 // and (4) normal important.
1323 m_lineHeightValue = 0;
1324 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1325 if (!resolveForRootDefault) {
1326 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1327 applyDeclarations<true>(true, firstUserRule, lastUserRule);
1329 applyDeclarations<true>(true, firstUARule, lastUARule);
1331 // If our font got dirtied, go ahead and update it now.
1335 // Line-height is set when we are sure we decided on the font-size
1336 if (m_lineHeightValue)
1337 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1339 // Now do the normal priority UA properties.
1340 applyDeclarations<false>(false, firstUARule, lastUARule);
1342 // Cache our border and background so that we can examine them later.
1343 cacheBorderAndBackground();
1345 // Now do the author and user normal priority properties and all the !important properties.
1346 if (!resolveForRootDefault) {
1347 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1348 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1349 applyDeclarations<false>(true, firstUserRule, lastUserRule);
1351 applyDeclarations<false>(true, firstUARule, lastUARule);
1353 // If our font got dirtied by one of the non-essential font props,
1354 // go ahead and update it a second time.
1358 // Clean up our style object's display and text decorations (among other fixups).
1359 adjustRenderStyle(style(), e);
1361 // If we have first-letter pseudo style, do not share this style
1362 if (m_style->hasPseudoStyle(FIRST_LETTER))
1363 m_style->setUnique();
1366 // Copy any pseudo bits that the visited style has to the primary style so that
1367 // pseudo element styles will continue to work for pseudo elements inside :visited
1369 for (unsigned pseudo = FIRST_PUBLIC_PSEUDOID; pseudo < FIRST_INTERNAL_PSEUDOID; ++pseudo) {
1370 if (visitedStyle->hasPseudoStyle(static_cast<PseudoId>(pseudo)))
1371 m_style->setHasPseudoStyle(static_cast<PseudoId>(pseudo));
1374 // Add the visited style off the main style.
1375 m_style->addCachedPseudoStyle(visitedStyle.release());
1378 if (!matchVisitedPseudoClass)
1379 initElement(0); // Clear out for the next resolve.
1381 // Now return the style.
1382 return m_style.release();
1385 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeList& list)
1387 if (keyframeRule->style())
1388 addMatchedDeclaration(keyframeRule->style());
1393 m_style = RenderStyle::clone(elementStyle);
1395 m_lineHeightValue = 0;
1397 // We don't need to bother with !important. Since there is only ever one
1398 // decl, there's nothing to override. So just add the first properties.
1399 if (keyframeRule->style())
1400 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1402 // If our font got dirtied, go ahead and update it now.
1406 // Line-height is set when we are sure we decided on the font-size
1407 if (m_lineHeightValue)
1408 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1410 // Now do rest of the properties.
1411 if (keyframeRule->style())
1412 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1414 // If our font got dirtied by one of the non-essential font props,
1415 // go ahead and update it a second time.
1419 // Add all the animating properties to the list
1420 if (keyframeRule->style()) {
1421 CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1422 for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1423 int property = (*it).id();
1424 // Timing-function within keyframes is special, because it is not animated; it just
1425 // describes the timing function between this keyframe and the next.
1426 if (property != CSSPropertyWebkitAnimationTimingFunction)
1427 list.addProperty(property);
1431 return m_style.release();
1434 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1438 // Get the keyframesRule for this name
1439 if (!e || list.animationName().isEmpty())
1442 m_keyframesRuleMap.checkConsistency();
1444 if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1447 const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1448 RefPtr<RenderStyle> keyframeStyle;
1450 // Construct and populate the style for each keyframe
1451 for (unsigned i = 0; i < rule->length(); ++i) {
1452 // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1454 initForStyleResolve(e);
1456 const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1458 keyframeStyle = styleForKeyframe(elementStyle, keyframeRule, list);
1460 // Add this keyframe style to all the indicated key times
1462 keyframeRule->getKeys(keys);
1463 for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1464 float key = keys[keyIndex];
1465 list.insert(key, keyframeStyle.get());
1467 keyframeStyle.release();
1470 // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1471 int initialListSize = list.size();
1472 if (initialListSize > 0 && list.beginKeyframes()->key() != 0) {
1473 RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create();
1474 keyframe->setKeyText("0%");
1475 keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list);
1476 list.insert(0, keyframeStyle.release());
1479 // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1480 if (initialListSize > 0 && (list.endKeyframes() - 1)->key() != 1) {
1481 RefPtr<WebKitCSSKeyframeRule> keyframe = WebKitCSSKeyframeRule::create();
1482 keyframe->setKeyText("100%");
1483 keyframeStyle = styleForKeyframe(elementStyle, keyframe.get(), list);
1484 list.insert(1, keyframeStyle.release());
1488 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle, bool matchVisitedPseudoClass)
1495 // Compute our :visited style first, so that we know whether or not we'll need to create a normal style just to hang it
1497 RefPtr<RenderStyle> visitedStyle;
1498 if (!matchVisitedPseudoClass && parentStyle && parentStyle->insideLink()) {
1499 // Fetch our parent style with :visited in effect.
1500 RenderStyle* parentVisitedStyle = parentStyle->getCachedPseudoStyle(VISITED_LINK);
1501 visitedStyle = pseudoStyleForElement(pseudo, e, parentVisitedStyle ? parentVisitedStyle : parentStyle, true);
1503 if (m_elementLinkState == InsideUnvisitedLink)
1504 visitedStyle = 0; // We made the style to avoid timing attacks. Just throw it away now that we did that.
1506 visitedStyle->setStyleType(VISITED_LINK);
1510 initForStyleResolve(e, parentStyle, pseudo);
1511 m_style = parentStyle;
1513 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1515 // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1518 // Check UA, user and author rules.
1519 int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
1520 matchUARules(firstUARule, lastUARule);
1522 if (m_matchAuthorAndUserStyles) {
1523 matchRules(m_userStyle, firstUserRule, lastUserRule);
1524 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1527 if (m_matchedDecls.isEmpty() && !visitedStyle)
1530 m_style = RenderStyle::create();
1532 m_style->inheritFrom(parentStyle);
1534 m_style->setStyleType(pseudo);
1536 m_lineHeightValue = 0;
1538 // Reset the value back before applying properties, so that -webkit-link knows what color to use.
1539 m_checker.m_matchVisitedPseudoClass = matchVisitedPseudoClass;
1541 // High-priority properties.
1542 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1543 applyDeclarations<true>(true, firstAuthorRule, lastAuthorRule);
1544 applyDeclarations<true>(true, firstUserRule, lastUserRule);
1545 applyDeclarations<true>(true, firstUARule, lastUARule);
1547 // If our font got dirtied, go ahead and update it now.
1551 // Line-height is set when we are sure we decided on the font-size
1552 if (m_lineHeightValue)
1553 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1555 // Now do the normal priority properties.
1556 applyDeclarations<false>(false, firstUARule, lastUARule);
1558 // Cache our border and background so that we can examine them later.
1559 cacheBorderAndBackground();
1561 applyDeclarations<false>(false, lastUARule + 1, m_matchedDecls.size() - 1);
1562 applyDeclarations<false>(true, firstAuthorRule, lastAuthorRule);
1563 applyDeclarations<false>(true, firstUserRule, lastUserRule);
1564 applyDeclarations<false>(true, firstUARule, lastUARule);
1566 // If our font got dirtied by one of the non-essential font props,
1567 // go ahead and update it a second time.
1571 // Clean up our style object's display and text decorations (among other fixups).
1572 adjustRenderStyle(style(), 0);
1574 // Hang our visited style off m_style.
1576 m_style->addCachedPseudoStyle(visitedStyle.release());
1578 // Now return the style.
1579 return m_style.release();
1582 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1584 initForStyleResolve(m_checker.m_document->body());
1586 m_style = RenderStyle::create();
1587 m_style->inheritFrom(m_rootElementStyle);
1589 const bool isLeft = isLeftPage(pageIndex);
1590 const bool isFirst = isFirstPage(pageIndex);
1591 const String page = pageName(pageIndex);
1592 matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1593 matchPageRules(m_userStyle, isLeft, isFirst, page);
1594 matchPageRules(m_authorStyle, isLeft, isFirst, page);
1595 m_lineHeightValue = 0;
1596 applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1);
1598 // If our font got dirtied, go ahead and update it now.
1602 // Line-height is set when we are sure we decided on the font-size
1603 if (m_lineHeightValue)
1604 applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1606 applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1);
1608 // Now return the style.
1609 return m_style.release();
1612 #if ENABLE(DATAGRID)
1614 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumn(DataGridColumn*, RenderStyle*)
1620 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForDataGridColumnHeader(DataGridColumn*, RenderStyle*)
1628 static void addIntrinsicMargins(RenderStyle* style)
1630 // Intrinsic margin value.
1631 const int intrinsicMargin = 2 * style->effectiveZoom();
1633 // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1634 // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1635 if (style->width().isIntrinsicOrAuto()) {
1636 if (style->marginLeft().quirk())
1637 style->setMarginLeft(Length(intrinsicMargin, Fixed));
1638 if (style->marginRight().quirk())
1639 style->setMarginRight(Length(intrinsicMargin, Fixed));
1642 if (style->height().isAuto()) {
1643 if (style->marginTop().quirk())
1644 style->setMarginTop(Length(intrinsicMargin, Fixed));
1645 if (style->marginBottom().quirk())
1646 style->setMarginBottom(Length(intrinsicMargin, Fixed));
1650 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, Element *e)
1652 // Cache our original display.
1653 style->setOriginalDisplay(style->display());
1655 if (style->display() != NONE) {
1656 // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1658 // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1659 // these tags to retain their display types.
1660 if (!m_checker.m_strictParsing && e) {
1661 if (e->hasTagName(tdTag)) {
1662 style->setDisplay(TABLE_CELL);
1663 style->setFloating(FNONE);
1665 else if (e->hasTagName(tableTag))
1666 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1669 if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1670 if (style->whiteSpace() == KHTML_NOWRAP) {
1671 // Figure out if we are really nowrapping or if we should just
1672 // use normal instead. If the width of the cell is fixed, then
1673 // we don't actually use NOWRAP.
1674 if (style->width().isFixed())
1675 style->setWhiteSpace(NORMAL);
1677 style->setWhiteSpace(NOWRAP);
1681 // Tables never support the -webkit-* values for text-align and will reset back to the default.
1682 if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1683 style->setTextAlign(TAAUTO);
1685 // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1686 // fix a crash where a site tries to position these objects. They also never honor display.
1687 if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1688 style->setPosition(StaticPosition);
1689 style->setDisplay(BLOCK);
1692 // Table headers with a text-align of auto will change the text-align to center.
1693 if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1694 style->setTextAlign(CENTER);
1696 if (e && e->hasTagName(legendTag))
1697 style->setDisplay(BLOCK);
1699 // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1700 // position or float an inline, compact, or run-in. Cache the original display, since it
1701 // may be needed for positioned elements that have to compute their static normal flow
1702 // positions. We also force inline-level roots to be block-level.
1703 if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1704 (style->position() == AbsolutePosition || style->position() == FixedPosition || style->floating() != FNONE ||
1705 (e && e->document()->documentElement() == e))) {
1706 if (style->display() == INLINE_TABLE)
1707 style->setDisplay(TABLE);
1708 else if (style->display() == INLINE_BOX)
1709 style->setDisplay(BOX);
1710 else if (style->display() == LIST_ITEM) {
1711 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1712 // but only in quirks mode.
1713 if (!m_checker.m_strictParsing && style->floating() != FNONE)
1714 style->setDisplay(BLOCK);
1717 style->setDisplay(BLOCK);
1720 // After performing the display mutation, check table rows. We do not honor position:relative on
1721 // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1723 if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP ||
1724 style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_CELL) &&
1725 style->position() == RelativePosition)
1726 style->setPosition(StaticPosition);
1729 // Make sure our z-index value is only applied if the object is positioned.
1730 if (style->position() == StaticPosition)
1731 style->setHasAutoZIndex();
1733 // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1734 // cases where objects that should be blended as a single unit end up with a non-transparent
1735 // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1736 if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f ||
1737 style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect()))
1738 style->setZIndex(0);
1740 // Button, legend, input, select and textarea all consider width values of 'auto' to be 'intrinsic'.
1741 // This will be important when we use block flows for all form controls.
1742 if (e && (e->hasTagName(legendTag) || e->hasTagName(buttonTag) || e->hasTagName(inputTag) ||
1743 e->hasTagName(selectTag) || e->hasTagName(textareaTag) || e->hasTagName(datagridTag)
1745 || e->hasTagName(WMLNames::insertedLegendTag)
1746 || e->hasTagName(WMLNames::inputTag)
1749 if (style->width().isAuto())
1750 style->setWidth(Length(Intrinsic));
1752 // Textarea considers overflow visible as auto.
1753 if (e && e->hasTagName(textareaTag)) {
1754 style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1755 style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1759 // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1760 // tables, inline blocks, inline tables, or run-ins.
1761 if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1762 || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX)
1763 style->setTextDecorationsInEffect(style->textDecoration());
1765 style->addToTextDecorationsInEffect(style->textDecoration());
1767 // If either overflow value is not visible, change to auto.
1768 if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1769 style->setOverflowY(OMARQUEE);
1770 else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1771 style->setOverflowX(OMARQUEE);
1772 else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1773 style->setOverflowX(OAUTO);
1774 else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1775 style->setOverflowY(OAUTO);
1777 // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1778 // FIXME: Eventually table sections will support auto and scroll.
1779 if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1780 style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1781 if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1782 style->setOverflowX(OVISIBLE);
1783 if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1784 style->setOverflowY(OVISIBLE);
1787 // Menulists should have visible overflow
1788 if (style->appearance() == MenulistPart) {
1789 style->setOverflowX(OVISIBLE);
1790 style->setOverflowY(OVISIBLE);
1793 // Cull out any useless layers and also repeat patterns into additional layers.
1794 style->adjustBackgroundLayers();
1795 style->adjustMaskLayers();
1797 // Do the same for animations and transitions.
1798 style->adjustAnimations();
1799 style->adjustTransitions();
1801 // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1802 // alter fonts and heights/widths.
1803 if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1804 // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1805 // so we have to treat all image buttons as though they were explicitly sized.
1806 if (!e->hasTagName(inputTag) || static_cast<HTMLInputElement*>(e)->inputType() != HTMLInputElement::IMAGE)
1807 addIntrinsicMargins(style);
1810 // Let the theme also have a crack at adjusting the style.
1811 if (style->hasAppearance())
1812 RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1815 if (e && e->isSVGElement()) {
1816 // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1817 if (style->overflowY() == OSCROLL)
1818 style->setOverflowY(OHIDDEN);
1819 else if (style->overflowY() == OAUTO)
1820 style->setOverflowY(OVISIBLE);
1822 if (style->overflowX() == OSCROLL)
1823 style->setOverflowX(OHIDDEN);
1824 else if (style->overflowX() == OAUTO)
1825 style->setOverflowX(OVISIBLE);
1827 // Only the root <svg> element in an SVG document fragment tree honors css position
1828 if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1829 style->setPosition(RenderStyle::initialPosition());
1834 void CSSStyleSelector::updateFont()
1836 checkForTextSizeAdjust();
1837 checkForGenericFamilyChange(style(), m_parentStyle);
1838 checkForZoomChange(style(), m_parentStyle);
1839 m_style->font().update(m_fontSelector);
1840 m_fontDirty = false;
1843 void CSSStyleSelector::cacheBorderAndBackground()
1845 m_hasUAAppearance = m_style->hasAppearance();
1846 if (m_hasUAAppearance) {
1847 m_borderData = m_style->border();
1848 m_backgroundData = *m_style->backgroundLayers();
1849 m_backgroundColor = m_style->backgroundColor();
1853 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, bool authorOnly)
1855 return pseudoStyleRulesForElement(e, NOPSEUDO, authorOnly);
1858 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, bool authorOnly)
1860 if (!e || !e->document()->haveStylesheetsLoaded())
1863 m_checker.m_collectRulesOnly = true;
1866 initForStyleResolve(e, 0, pseudoId);
1869 int firstUARule = -1, lastUARule = -1;
1870 // First we match rules from the user agent sheet.
1871 matchUARules(firstUARule, lastUARule);
1873 // Now we check user sheet rules.
1874 if (m_matchAuthorAndUserStyles) {
1875 int firstUserRule = -1, lastUserRule = -1;
1876 matchRules(m_userStyle, firstUserRule, lastUserRule);
1880 if (m_matchAuthorAndUserStyles) {
1881 // Check the rules in author sheets.
1882 int firstAuthorRule = -1, lastAuthorRule = -1;
1883 matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
1886 m_checker.m_collectRulesOnly = false;
1888 return m_ruleList.release();
1891 bool CSSStyleSelector::checkSelector(CSSSelector* sel)
1893 m_dynamicPseudo = NOPSEUDO;
1895 // Check the selector
1896 SelectorMatch match = m_checker.checkSelector(sel, m_element, &m_selectorAttrs, m_dynamicPseudo, false, false, style(), m_parentStyle);
1897 if (match != SelectorMatches)
1900 if (m_checker.m_pseudoStyle != NOPSEUDO && m_checker.m_pseudoStyle != m_dynamicPseudo)
1906 // Recursive check of selectors and combinators
1907 // It can return 3 different values:
1908 // * SelectorMatches - the selector matches the element e
1909 // * SelectorFailsLocally - the selector fails for the element e
1910 // * SelectorFailsCompletely - the selector fails for e and any sibling or ancestor of e
1911 CSSStyleSelector::SelectorMatch CSSStyleSelector::SelectorChecker::checkSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, bool encounteredLink, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
1914 // Spec: CSS2 selectors cannot be applied to the (conceptually) cloned DOM tree
1915 // because its contents are not part of the formal document structure.
1916 if (e->isSVGElement() && e->isShadowNode())
1917 return SelectorFailsCompletely;
1920 // first selector has to match
1921 if (!checkOneSelector(sel, e, selectorAttrs, dynamicPseudo, isSubSelector, elementStyle, elementParentStyle))
1922 return SelectorFailsLocally;
1924 // The rest of the selectors has to match
1925 CSSSelector::Relation relation = sel->relation();
1928 sel = sel->tagHistory();
1930 return SelectorMatches;
1932 if (relation != CSSSelector::SubSelector)
1933 // Bail-out if this selector is irrelevant for the pseudoStyle
1934 if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != dynamicPseudo)
1935 return SelectorFailsCompletely;
1937 // Check for nested links.
1938 if (m_matchVisitedPseudoClass && !isSubSelector) {
1939 RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
1940 if (currentStyle && currentStyle->insideLink() && e->isLink()) {
1941 if (encounteredLink)
1942 m_matchVisitedPseudoClass = false; // This link is not relevant to the style being resolved, so disable matching.
1944 encounteredLink = true;
1949 case CSSSelector::Descendant:
1951 Node* n = e->parentNode();
1952 if (!n || !n->isElementNode())
1953 return SelectorFailsCompletely;
1954 e = static_cast<Element*>(n);
1955 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
1956 if (match != SelectorFailsLocally)
1960 case CSSSelector::Child:
1962 Node* n = e->parentNode();
1963 if (!n || !n->isElementNode())
1964 return SelectorFailsCompletely;
1965 e = static_cast<Element*>(n);
1966 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
1968 case CSSSelector::DirectAdjacent:
1970 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
1971 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
1973 parentStyle->setChildrenAffectedByDirectAdjacentRules();
1975 Node* n = e->previousSibling();
1976 while (n && !n->isElementNode())
1977 n = n->previousSibling();
1979 return SelectorFailsLocally;
1980 e = static_cast<Element*>(n);
1981 m_matchVisitedPseudoClass = false;
1982 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
1984 case CSSSelector::IndirectAdjacent:
1985 if (!m_collectRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
1986 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
1988 parentStyle->setChildrenAffectedByForwardPositionalRules();
1991 Node* n = e->previousSibling();
1992 while (n && !n->isElementNode())
1993 n = n->previousSibling();
1995 return SelectorFailsLocally;
1996 e = static_cast<Element*>(n);
1997 m_matchVisitedPseudoClass = false;
1998 SelectorMatch match = checkSelector(sel, e, selectorAttrs, dynamicPseudo, false, encounteredLink);
1999 if (match != SelectorFailsLocally)
2003 case CSSSelector::SubSelector:
2004 // a selector is invalid if something follows a pseudo-element
2005 // We make an exception for scrollbar pseudo elements and allow a set of pseudo classes (but nothing else)
2006 // to follow the pseudo elements.
2007 if ((elementStyle || m_collectRulesOnly) && dynamicPseudo != NOPSEUDO && dynamicPseudo != SELECTION &&
2008 !((RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER) && sel->m_match == CSSSelector::PseudoClass))
2009 return SelectorFailsCompletely;
2010 return checkSelector(sel, e, selectorAttrs, dynamicPseudo, true, encounteredLink, elementStyle, elementParentStyle);
2013 return SelectorFailsCompletely;
2016 static void addLocalNameToSet(HashSet<AtomicStringImpl*>* set, const QualifiedName& qName)
2018 set->add(qName.localName().impl());
2021 static HashSet<AtomicStringImpl*>* createHtmlCaseInsensitiveAttributesSet()
2023 // This is the list of attributes in HTML 4.01 with values marked as "[CI]" or case-insensitive
2024 // Mozilla treats all other values as case-sensitive, thus so do we.
2025 HashSet<AtomicStringImpl*>* attrSet = new HashSet<AtomicStringImpl*>;
2027 addLocalNameToSet(attrSet, accept_charsetAttr);
2028 addLocalNameToSet(attrSet, acceptAttr);
2029 addLocalNameToSet(attrSet, alignAttr);
2030 addLocalNameToSet(attrSet, alinkAttr);
2031 addLocalNameToSet(attrSet, axisAttr);
2032 addLocalNameToSet(attrSet, bgcolorAttr);
2033 addLocalNameToSet(attrSet, charsetAttr);
2034 addLocalNameToSet(attrSet, checkedAttr);
2035 addLocalNameToSet(attrSet, clearAttr);
2036 addLocalNameToSet(attrSet, codetypeAttr);
2037 addLocalNameToSet(attrSet, colorAttr);
2038 addLocalNameToSet(attrSet, compactAttr);
2039 addLocalNameToSet(attrSet, declareAttr);
2040 addLocalNameToSet(attrSet, deferAttr);
2041 addLocalNameToSet(attrSet, dirAttr);
2042 addLocalNameToSet(attrSet, disabledAttr);
2043 addLocalNameToSet(attrSet, enctypeAttr);
2044 addLocalNameToSet(attrSet, faceAttr);
2045 addLocalNameToSet(attrSet, frameAttr);
2046 addLocalNameToSet(attrSet, hreflangAttr);
2047 addLocalNameToSet(attrSet, http_equivAttr);
2048 addLocalNameToSet(attrSet, langAttr);
2049 addLocalNameToSet(attrSet, languageAttr);
2050 addLocalNameToSet(attrSet, linkAttr);
2051 addLocalNameToSet(attrSet, mediaAttr);
2052 addLocalNameToSet(attrSet, methodAttr);
2053 addLocalNameToSet(attrSet, multipleAttr);
2054 addLocalNameToSet(attrSet, nohrefAttr);
2055 addLocalNameToSet(attrSet, noresizeAttr);
2056 addLocalNameToSet(attrSet, noshadeAttr);
2057 addLocalNameToSet(attrSet, nowrapAttr);
2058 addLocalNameToSet(attrSet, readonlyAttr);
2059 addLocalNameToSet(attrSet, relAttr);
2060 addLocalNameToSet(attrSet, revAttr);
2061 addLocalNameToSet(attrSet, rulesAttr);
2062 addLocalNameToSet(attrSet, scopeAttr);
2063 addLocalNameToSet(attrSet, scrollingAttr);
2064 addLocalNameToSet(attrSet, selectedAttr);
2065 addLocalNameToSet(attrSet, shapeAttr);
2066 addLocalNameToSet(attrSet, targetAttr);
2067 addLocalNameToSet(attrSet, textAttr);
2068 addLocalNameToSet(attrSet, typeAttr);
2069 addLocalNameToSet(attrSet, valignAttr);
2070 addLocalNameToSet(attrSet, valuetypeAttr);
2071 addLocalNameToSet(attrSet, vlinkAttr);
2076 static bool htmlAttributeHasCaseInsensitiveValue(const QualifiedName& attr)
2078 static HashSet<AtomicStringImpl*>* htmlCaseInsensitiveAttributesSet = createHtmlCaseInsensitiveAttributesSet();
2079 bool isPossibleHTMLAttr = !attr.hasPrefix() && (attr.namespaceURI() == nullAtom);
2080 return isPossibleHTMLAttr && htmlCaseInsensitiveAttributesSet->contains(attr.localName().impl());
2083 bool CSSStyleSelector::SelectorChecker::checkOneSelector(CSSSelector* sel, Element* e, HashSet<AtomicStringImpl*>* selectorAttrs, PseudoId& dynamicPseudo, bool isSubSelector, RenderStyle* elementStyle, RenderStyle* elementParentStyle) const
2088 if (sel->hasTag()) {
2089 const AtomicString& selLocalName = sel->m_tag.localName();
2090 if (selLocalName != starAtom && selLocalName != e->localName())
2092 const AtomicString& selNS = sel->m_tag.namespaceURI();
2093 if (selNS != starAtom && selNS != e->namespaceURI())
2097 if (sel->hasAttribute()) {
2098 if (sel->m_match == CSSSelector::Class)
2099 return e->hasClass() && static_cast<StyledElement*>(e)->classNames().contains(sel->m_value);
2101 if (sel->m_match == CSSSelector::Id)
2102 return e->hasID() && e->idForStyleResolution() == sel->m_value;
2104 const QualifiedName& attr = sel->attribute();
2106 // FIXME: Handle the case were elementStyle is 0.
2107 if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr))) {
2108 elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.
2110 selectorAttrs->add(attr.localName().impl());
2113 const AtomicString& value = e->getAttribute(attr);
2115 return false; // attribute is not set
2117 bool caseSensitive = !m_documentIsHTML || !htmlAttributeHasCaseInsensitiveValue(attr);
2119 switch (sel->m_match) {
2120 case CSSSelector::Exact:
2121 if (caseSensitive ? sel->m_value != value : !equalIgnoringCase(sel->m_value, value))
2124 case CSSSelector::List:
2126 // Ignore empty selectors or selectors containing spaces
2127 if (sel->m_value.contains(' ') || sel->m_value.isEmpty())
2130 int startSearchAt = 0;
2132 int foundPos = value.find(sel->m_value, startSearchAt, caseSensitive);
2135 if (foundPos == 0 || value[foundPos-1] == ' ') {
2136 unsigned endStr = foundPos + sel->m_value.length();
2137 if (endStr == value.length() || value[endStr] == ' ')
2138 break; // We found a match.
2141 // No match. Keep looking.
2142 startSearchAt = foundPos + 1;
2146 case CSSSelector::Contain:
2147 if (!value.contains(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2150 case CSSSelector::Begin:
2151 if (!value.startsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2154 case CSSSelector::End:
2155 if (!value.endsWith(sel->m_value, caseSensitive) || sel->m_value.isEmpty())
2158 case CSSSelector::Hyphen:
2159 if (value.length() < sel->m_value.length())
2161 if (!value.startsWith(sel->m_value, caseSensitive))
2163 // It they start the same, check for exact match or following '-':
2164 if (value.length() != sel->m_value.length() && value[sel->m_value.length()] != '-')
2167 case CSSSelector::PseudoClass:
2168 case CSSSelector::PseudoElement:
2174 if (sel->m_match == CSSSelector::PseudoClass) {
2175 // Handle :not up front.
2176 if (sel->pseudoType() == CSSSelector::PseudoNot) {
2177 // check the simple selector
2178 for (CSSSelector* subSel = sel->simpleSelector(); subSel; subSel = subSel->tagHistory()) {
2179 // :not cannot nest. I don't really know why this is a
2180 // restriction in CSS3, but it is, so let's honor it.
2181 // the parser enforces that this never occurs
2182 ASSERT(!subSel->simpleSelector());
2184 if (!checkOneSelector(subSel, e, selectorAttrs, dynamicPseudo, true, elementStyle, elementParentStyle))
2187 } else if (dynamicPseudo != NOPSEUDO && (RenderScrollbar::scrollbarForStyleResolve() || dynamicPseudo == SCROLLBAR_CORNER || dynamicPseudo == RESIZER)) {
2188 // CSS scrollbars match a specific subset of pseudo classes, and they have specialized rules for each
2189 // (since there are no elements involved).
2190 return checkScrollbarPseudoClass(sel, dynamicPseudo);
2191 } else if (dynamicPseudo == SELECTION) {
2192 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2193 return !m_document->page()->focusController()->isActive();
2196 // Normal element pseudo class checking.
2197 switch (sel->pseudoType()) {
2199 case CSSSelector::PseudoNot:
2200 break; // Already handled up above.
2201 case CSSSelector::PseudoEmpty: {
2203 for (Node* n = e->firstChild(); n; n = n->nextSibling()) {
2204 if (n->isElementNode()) {
2207 } else if (n->isTextNode()) {
2208 Text* textNode = static_cast<Text*>(n);
2209 if (!textNode->data().isEmpty()) {
2215 if (!m_collectRulesOnly) {
2217 elementStyle->setEmptyState(result);
2218 else if (e->renderStyle() && (e->document()->usesSiblingRules() || e->renderStyle()->unique()))
2219 e->renderStyle()->setEmptyState(result);
2223 case CSSSelector::PseudoFirstChild: {
2224 // first-child matches the first child that is an element
2225 if (e->parentNode() && e->parentNode()->isElementNode()) {
2226 bool result = false;
2227 Node* n = e->previousSibling();
2228 while (n && !n->isElementNode())
2229 n = n->previousSibling();
2232 if (!m_collectRulesOnly) {
2233 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2234 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2236 parentStyle->setChildrenAffectedByFirstChildRules();
2237 if (result && childStyle)
2238 childStyle->setFirstChildState();
2244 case CSSSelector::PseudoFirstOfType: {
2245 // first-of-type matches the first element of its type
2246 if (e->parentNode() && e->parentNode()->isElementNode()) {
2247 bool result = false;
2248 const QualifiedName& type = e->tagQName();
2249 Node* n = e->previousSibling();
2251 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2253 n = n->previousSibling();
2257 if (!m_collectRulesOnly) {
2258 RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
2260 parentStyle->setChildrenAffectedByForwardPositionalRules();
2266 case CSSSelector::PseudoLastChild: {
2267 // last-child matches the last child that is an element
2268 if (Element* parentElement = e->parentElement()) {
2269 bool result = false;
2270 if (parentElement->isFinishedParsingChildren()) {
2271 Node* n = e->nextSibling();
2272 while (n && !n->isElementNode())
2273 n = n->nextSibling();
2277 if (!m_collectRulesOnly) {
2278 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2279 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2281 parentStyle->setChildrenAffectedByLastChildRules();
2282 if (result && childStyle)
2283 childStyle->setLastChildState();
2289 case CSSSelector::PseudoLastOfType: {
2290 // last-of-type matches the last element of its type
2291 if (Element* parentElement = e->parentElement()) {
2292 if (!m_collectRulesOnly) {
2293 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2295 parentStyle->setChildrenAffectedByBackwardPositionalRules();
2297 if (!parentElement->isFinishedParsingChildren())
2299 bool result = false;
2300 const QualifiedName& type = e->tagQName();
2301 Node* n = e->nextSibling();
2303 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2305 n = n->nextSibling();
2313 case CSSSelector::PseudoOnlyChild: {
2314 if (Element* parentElement = e->parentElement()) {
2315 bool firstChild = false;
2316 bool lastChild = false;
2318 Node* n = e->previousSibling();
2319 while (n && !n->isElementNode())
2320 n = n->previousSibling();
2323 if (firstChild && parentElement->isFinishedParsingChildren()) {
2324 n = e->nextSibling();
2325 while (n && !n->isElementNode())
2326 n = n->nextSibling();
2330 if (!m_collectRulesOnly) {
2331 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2332 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2334 parentStyle->setChildrenAffectedByFirstChildRules();
2335 parentStyle->setChildrenAffectedByLastChildRules();
2337 if (firstChild && childStyle)
2338 childStyle->setFirstChildState();
2339 if (lastChild && childStyle)
2340 childStyle->setLastChildState();
2342 return firstChild && lastChild;
2346 case CSSSelector::PseudoOnlyOfType: {
2347 // FIXME: This selector is very slow.
2348 if (Element* parentElement = e->parentElement()) {
2349 if (!m_collectRulesOnly) {
2350 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2352 parentStyle->setChildrenAffectedByForwardPositionalRules();
2353 parentStyle->setChildrenAffectedByBackwardPositionalRules();
2356 if (!parentElement->isFinishedParsingChildren())
2358 bool firstChild = false;
2359 bool lastChild = false;
2360 const QualifiedName& type = e->tagQName();
2361 Node* n = e->previousSibling();
2363 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2365 n = n->previousSibling();
2370 n = e->nextSibling();
2372 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2374 n = n->nextSibling();
2379 return firstChild && lastChild;
2383 case CSSSelector::PseudoNthChild: {
2384 if (!sel->parseNth())
2386 if (Element* parentElement = e->parentElement()) {
2388 Node* n = e->previousSibling();
2390 if (n->isElementNode()) {
2391 RenderStyle* s = n->renderStyle();
2392 unsigned index = s ? s->childIndex() : 0;
2399 n = n->previousSibling();
2402 if (!m_collectRulesOnly) {
2403 RenderStyle* childStyle = elementStyle ? elementStyle : e->renderStyle();
2404 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2406 childStyle->setChildIndex(count);
2408 parentStyle->setChildrenAffectedByForwardPositionalRules();
2411 if (sel->matchNth(count))
2416 case CSSSelector::PseudoNthOfType: {
2417 if (!sel->parseNth())
2419 if (Element* parentElement = e->parentElement()) {
2421 const QualifiedName& type = e->tagQName();
2422 Node* n = e->previousSibling();
2424 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2426 n = n->previousSibling();
2429 if (!m_collectRulesOnly) {
2430 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2432 parentStyle->setChildrenAffectedByForwardPositionalRules();
2435 if (sel->matchNth(count))
2440 case CSSSelector::PseudoNthLastChild: {
2441 if (!sel->parseNth())
2443 if (Element* parentElement = e->parentElement()) {
2444 if (!m_collectRulesOnly) {
2445 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2447 parentStyle->setChildrenAffectedByBackwardPositionalRules();
2449 if (!parentElement->isFinishedParsingChildren())
2452 Node* n = e->nextSibling();
2454 if (n->isElementNode())
2456 n = n->nextSibling();
2458 if (sel->matchNth(count))
2463 case CSSSelector::PseudoNthLastOfType: {
2464 if (!sel->parseNth())
2466 if (Element* parentElement = e->parentElement()) {
2467 if (!m_collectRulesOnly) {
2468 RenderStyle* parentStyle = elementStyle ? elementParentStyle : parentElement->renderStyle();
2470 parentStyle->setChildrenAffectedByBackwardPositionalRules();
2472 if (!parentElement->isFinishedParsingChildren())
2475 const QualifiedName& type = e->tagQName();
2476 Node* n = e->nextSibling();
2478 if (n->isElementNode() && static_cast<Element*>(n)->hasTagName(type))
2480 n = n->nextSibling();
2482 if (sel->matchNth(count))
2487 case CSSSelector::PseudoTarget:
2488 if (e == e->document()->cssTarget())
2491 case CSSSelector::PseudoAnyLink:
2492 if (e && e->isLink())
2495 case CSSSelector::PseudoAutofill: {
2496 if (!e || !e->isFormControlElement())
2498 if (InputElement* inputElement = toInputElement(e))
2499 return inputElement->isAutofilled();
2502 case CSSSelector::PseudoLink:
2503 if (e && e->isLink())
2504 return !m_matchVisitedPseudoClass;
2506 case CSSSelector::PseudoVisited:
2507 if (e && e->isLink())
2508 return m_matchVisitedPseudoClass;
2510 case CSSSelector::PseudoDrag: {
2512 elementStyle->setAffectedByDragRules(true);
2513 else if (e->renderStyle())
2514 e->renderStyle()->setAffectedByDragRules(true);
2515 if (e->renderer() && e->renderer()->isDragging())
2519 case CSSSelector::PseudoFocus:
2520 if (e && e->focused() && e->document()->frame() && e->document()->frame()->selection()->isFocusedAndActive())
2523 case CSSSelector::PseudoHover: {
2524 // If we're in quirks mode, then hover should never match anchors with no
2525 // href and *:hover should not match anything. This is important for sites like wsj.com.
2526 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2528 elementStyle->setAffectedByHoverRules(true);
2529 else if (e->renderStyle())
2530 e->renderStyle()->setAffectedByHoverRules(true);
2536 case CSSSelector::PseudoActive:
2537 // If we're in quirks mode, then :active should never match anchors with no
2538 // href and *:active should not match anything.
2539 if (m_strictParsing || isSubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
2541 elementStyle->setAffectedByActiveRules(true);
2542 else if (e->renderStyle())
2543 e->renderStyle()->setAffectedByActiveRules(true);
2548 case CSSSelector::PseudoEnabled:
2549 if (e && e->isFormControlElement())
2550 return e->isEnabledFormControl();
2552 case CSSSelector::PseudoFullPageMedia:
2553 return e && e->document() && e->document()->isMediaDocument();
2555 case CSSSelector::PseudoDefault:
2556 return e && e->isDefaultButtonForForm();
2557 case CSSSelector::PseudoDisabled:
2558 if (e && e->isFormControlElement())
2559 return !e->isEnabledFormControl();
2561 case CSSSelector::PseudoReadOnly: {
2562 if (!e || !e->isFormControlElement())
2564 return e->isTextFormControl() && e->isReadOnlyFormControl();
2566 case CSSSelector::PseudoReadWrite: {
2567 if (!e || !e->isFormControlElement())
2569 return e->isTextFormControl() && !e->isReadOnlyFormControl();
2571 case CSSSelector::PseudoOptional:
2572 return e && e->isOptionalFormControl();
2573 case CSSSelector::PseudoRequired:
2574 return e && e->isRequiredFormControl();
2575 case CSSSelector::PseudoValid: {
2578 e->document()->setContainsValidityStyleRules();
2579 return e->willValidate() && e->isValidFormControlElement();
2580 } case CSSSelector::PseudoInvalid: {
2583 e->document()->setContainsValidityStyleRules();
2584 return e->willValidate() && !e->isValidFormControlElement();
2585 } case CSSSelector::PseudoChecked: {
2586 if (!e || !e->isFormControlElement())
2588 // Even though WinIE allows checked and indeterminate to co-exist, the CSS selector spec says that
2589 // you can't be both checked and indeterminate. We will behave like WinIE behind the scenes and just
2590 // obey the CSS spec here in the test for matching the pseudo.
2591 InputElement* inputElement = toInputElement(e);
2592 if (inputElement && inputElement->isChecked() && !inputElement->isIndeterminate())
2596 case CSSSelector::PseudoIndeterminate: {
2597 if (!e || !e->isFormControlElement())
2599 InputElement* inputElement = toInputElement(e);
2600 if (inputElement && inputElement->isIndeterminate())
2604 case CSSSelector::PseudoRoot:
2605 if (e == e->document()->documentElement())
2608 case CSSSelector::PseudoLang: {
2611 // The language property is inherited, so we iterate over the parents
2612 // to find the first language.
2613 while (n && value.isNull()) {
2614 if (n->isElementNode()) {
2615 // Spec: xml:lang takes precedence -- http://www.w3.org/TR/xhtml1/#C_7
2616 value = static_cast<Element*>(n)->fastGetAttribute(XMLNames::langAttr);
2618 value = static_cast<Element*>(n)->fastGetAttribute(langAttr);
2619 } else if (n->isDocumentNode())
2620 // checking the MIME content-language
2621 value = static_cast<Document*>(n)->contentLanguage();
2625 const AtomicString& argument = sel->argument();
2626 if (value.isNull() || !value.startsWith(argument, false))
2628 if (value.length() != argument.length() && value[argument.length()] != '-')
2632 case CSSSelector::PseudoUnknown:
2633 case CSSSelector::PseudoNotParsed:
2635 ASSERT_NOT_REACHED();
2640 if (sel->m_match == CSSSelector::PseudoElement) {
2641 if (!elementStyle && !m_collectRulesOnly)
2644 PseudoId pseudoId = CSSSelector::pseudoId(sel->pseudoType());
2645 if (pseudoId == FIRST_LETTER) {
2646 if (Document* document = e->document())
2647 document->setUsesFirstLetterRules(true);
2649 if (pseudoId != NOPSEUDO) {
2650 dynamicPseudo = pseudoId;
2653 ASSERT_NOT_REACHED();
2656 // ### add the rest of the checks...
2660 bool CSSStyleSelector::SelectorChecker::checkScrollbarPseudoClass(CSSSelector* sel, PseudoId&) const
2662 RenderScrollbar* scrollbar = RenderScrollbar::scrollbarForStyleResolve();
2663 ScrollbarPart part = RenderScrollbar::partForStyleResolve();
2665 // FIXME: This is a temporary hack for resizers and scrollbar corners. Eventually :window-inactive should become a real
2666 // pseudo class and just apply to everything.
2667 if (sel->pseudoType() == CSSSelector::PseudoWindowInactive)
2668 return !m_document->page()->focusController()->isActive();
2673 ASSERT(sel->m_match == CSSSelector::PseudoClass);
2674 switch (sel->pseudoType()) {
2675 case CSSSelector::PseudoEnabled:
2676 return scrollbar->enabled();
2677 case CSSSelector::PseudoDisabled:
2678 return !scrollbar->enabled();
2679 case CSSSelector::PseudoHover: {
2680 ScrollbarPart hoveredPart = scrollbar->hoveredPart();
2681 if (part == ScrollbarBGPart)
2682 return hoveredPart != NoPart;
2683 if (part == TrackBGPart)
2684 return hoveredPart == BackTrackPart || hoveredPart == ForwardTrackPart || hoveredPart == ThumbPart;
2685 return part == hoveredPart;
2687 case CSSSelector::PseudoActive: {
2688 ScrollbarPart pressedPart = scrollbar->pressedPart();
2689 if (part == ScrollbarBGPart)
2690 return pressedPart != NoPart;
2691 if (part == TrackBGPart)
2692 return pressedPart == BackTrackPart || pressedPart == ForwardTrackPart || pressedPart == ThumbPart;
2693 return part == pressedPart;
2695 case CSSSelector::PseudoHorizontal:
2696 return scrollbar->orientation() == HorizontalScrollbar;
2697 case CSSSelector::PseudoVertical:
2698 return scrollbar->orientation() == VerticalScrollbar;
2699 case CSSSelector::PseudoDecrement:
2700 return part == BackButtonStartPart || part == BackButtonEndPart || part == BackTrackPart;
2701 case CSSSelector::PseudoIncrement:
2702 return part == ForwardButtonStartPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
2703 case CSSSelector::PseudoStart:
2704 return part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart;
2705 case CSSSelector::PseudoEnd:
2706 return part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart;
2707 case CSSSelector::PseudoDoubleButton: {
2708 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2709 if (part == BackButtonStartPart || part == ForwardButtonStartPart || part == BackTrackPart)
2710 return buttonsPlacement == ScrollbarButtonsDoubleStart || buttonsPlacement == ScrollbarButtonsDoubleBoth;
2711 if (part == BackButtonEndPart || part == ForwardButtonEndPart || part == ForwardTrackPart)
2712 return buttonsPlacement == ScrollbarButtonsDoubleEnd || buttonsPlacement == ScrollbarButtonsDoubleBoth;
2715 case CSSSelector::PseudoSingleButton: {
2716 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2717 if (part == BackButtonStartPart || part == ForwardButtonEndPart || part == BackTrackPart || part == ForwardTrackPart)
2718 return buttonsPlacement == ScrollbarButtonsSingle;
2721 case CSSSelector::PseudoNoButton: {
2722 ScrollbarButtonsPlacement buttonsPlacement = scrollbar->theme()->buttonsPlacement();
2723 if (part == BackTrackPart)
2724 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleEnd;
2725 if (part == ForwardTrackPart)
2726 return buttonsPlacement == ScrollbarButtonsNone || buttonsPlacement == ScrollbarButtonsDoubleStart;
2729 case CSSSelector::PseudoCornerPresent:
2730 return scrollbar->client()->scrollbarCornerPresent();
2736 void CSSStyleSelector::addVariables(CSSVariablesRule* variables)
2738 CSSVariablesDeclaration* decl = variables->variables();
2741 unsigned size = decl->length();
2742 for (unsigned i = 0; i < size; ++i) {
2743 String name = decl->item(i);
2744 m_variablesMap.set(name, variables);
2748 CSSValue* CSSStyleSelector::resolveVariableDependentValue(CSSVariableDependentValue*)
2753 // -----------------------------------------------------------------
2755 CSSRuleSet::CSSRuleSet()
2757 m_universalRules = 0;
2760 m_pageRuleCount = 0;
2763 CSSRuleSet::~CSSRuleSet()
2765 deleteAllValues(m_idRules);
2766 deleteAllValues(m_classRules);
2767 deleteAllValues(m_tagRules);
2769 delete m_universalRules;
2774 void CSSRuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
2775 CSSStyleRule* rule, CSSSelector* sel)
2778 CSSRuleDataList* rules = map.get(key);
2780 rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
2781 map.set(key, rules);
2783 rules->append(m_ruleCount++, rule, sel);
2786 void CSSRuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
2788 if (sel->m_match == CSSSelector::Id) {
2789 addToRuleSet(sel->m_value.impl(), m_idRules, rule, sel);
2792 if (sel->m_match == CSSSelector::Class) {
2793 addToRuleSet(sel->m_value.impl(), m_classRules, rule, sel);
2797 const AtomicString& localName = sel->m_tag.localName();
2798 if (localName != starAtom) {
2799 addToRuleSet(localName.impl(), m_tagRules, rule, sel);
2803 // Just put it in the universal rule set.
2804 if (!m_universalRules)
2805 m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
2807 m_universalRules->append(m_ruleCount++, rule, sel);
2810 void CSSRuleSet::addPageRule(CSSStyleRule* rule, CSSSelector* sel)
2813 m_pageRules = new CSSRuleDataList(m_pageRuleCount++, rule, sel);
2815 m_pageRules->append(m_pageRuleCount++, rule, sel);
2818 void CSSRuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
2823 // No media implies "all", but if a media list exists it must
2824 // contain our current medium
2825 if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
2826 return; // the style sheet doesn't apply
2828 int len = sheet->length();
2830 for (int i = 0; i < len; i++) {
2831 StyleBase* item = sheet->item(i);
2832 if (item->isStyleRule()) {
2835 else if (item->isImportRule()) {
2836 CSSImportRule* import = static_cast<CSSImportRule*>(item);
2837 if (!import->media() || medium.eval(import->media(), styleSelector))
2838 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
2840 else if (item->isMediaRule()) {
2841 CSSMediaRule* r = static_cast<CSSMediaRule*>(item);
2842 CSSRuleList* rules = r->cssRules();
2844 if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
2845 // Traverse child elements of the @media rule.
2846 for (unsigned j = 0; j < rules->length(); j++) {
2847 CSSRule *childItem = rules->item(j);
2848 if (childItem->isStyleRule()) {
2849 // It is a StyleRule, so append it to our list
2850 addStyleRule(childItem);
2851 } else if (childItem->isFontFaceRule() && styleSelector) {
2852 // Add this font face to our set.
2853 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
2854 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2855 } else if (childItem->isKeyframesRule() && styleSelector) {
2856 // Add this keyframe rule to our set.
2857 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
2861 } else if (item->isFontFaceRule() && styleSelector) {
2862 // Add this font face to our set.
2863 const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(item);
2864 styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
2865 } else if (item->isVariablesRule()) {
2866 // Evaluate the media query and make sure it matches.
2867 CSSVariablesRule* variables = static_cast<CSSVariablesRule*>(item);
2868 if (!variables->media() || medium.eval(variables->media(), styleSelector))
2869 styleSelector->addVariables(variables);
2870 } else if (item->isKeyframesRule())
2871 styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(item));
2875 void CSSRuleSet::addStyleRule(StyleBase* item)
2877 if (item->isPageRule()) {
2878 CSSPageRule* pageRule = static_cast<CSSPageRule*>(item);
2879 addPageRule(pageRule, pageRule->selectorList().first());
2881 CSSStyleRule* rule = static_cast<CSSStyleRule*>(item);
2882 for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2887 // -------------------------------------------------------------------------------------
2888 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2890 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2892 // This function is tolerant of a null style value. The only place style is used is in
2893 // length measurements, like 'ems' and 'px'. And in those cases style is only used
2894 // when the units are EMS or EXS. So we will just fail in those cases.
2896 if (!primitiveValue) {
2900 int type = primitiveValue->primitiveType();
2902 if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
2905 } else if (CSSPrimitiveValue::isUnitTypeLength(type))
2906 l = Length(primitiveValue->computeLengthIntForLength(style, rootStyle, multiplier), Fixed);
2907 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2908 l = Length(primitiveValue->getDoubleValue(), Percent);
2909 else if (type == CSSPrimitiveValue::CSS_NUMBER)
2910 l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2917 template <bool applyFirst>
2918 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex)
2920 if (startIndex == -1)
2923 for (int i = startIndex; i <= endIndex; i++) {
2924 CSSMutableStyleDeclaration* decl = m_matchedDecls[i];
2925 CSSMutableStyleDeclaration::const_iterator end = decl->end();
2926 for (CSSMutableStyleDeclaration::const_iterator it = decl->begin(); it != end; ++it) {
2927 const CSSProperty& current = *it;
2928 if (isImportant == current.isImportant()) {
2929 int property = current.id();
2932 COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2933 COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 11, CSS_zoom_is_end_of_first_prop_range);
2934 COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2936 // give special priority to font-xxx, color properties, etc
2937 if (property <= CSSPropertyLineHeight) {
2938 // we apply line-height later
2939 if (property == CSSPropertyLineHeight)
2940 m_lineHeightValue = current.value();
2942 applyProperty(current.id(), current.value());
2945 if (property > CSSPropertyLineHeight)
2946 applyProperty(current.id(), current.value());
2953 void CSSStyleSelector::matchPageRules(CSSRuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2955 m_matchedRules.clear();
2960 matchPageRulesForList(rules->getPageRules(), isLeftPage, isFirstPage, pageName);
2962 // If we didn't match any rules, we're done.
2963 if (m_matchedRules.isEmpty())
2966 // Sort the set of matched rules.
2967 sortMatchedRules(0, m_matchedRules.size());
2969 // Now transfer the set of matched rules over to our list of decls.
2970 for (unsigned i = 0; i < m_matchedRules.size(); i++)
2971 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
2974 void CSSStyleSelector::matchPageRulesForList(CSSRuleDataList* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2979 for (CSSRuleData* d = rules->first(); d; d = d->next()) {
2980 CSSStyleRule* rule = d->rule();
2981 const AtomicString& selectorLocalName = d->selector()->m_tag.localName();
2982 if (selectorLocalName != starAtom && selectorLocalName != pageName)
2984 CSSSelector::PseudoType pseudoType = d->selector()->pseudoType();
2985 if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2986 || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2987 || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2990 // If the rule has no properties to apply, then ignore it.
2991 CSSMutableStyleDeclaration* decl = rule->declaration();
2992 if (!decl || !decl->length())
2995 // Add this rule to our list of matched rules.
3000 bool CSSStyleSelector::isLeftPage(int pageIndex) const
3002 bool isFirstPageLeft = false;
3003 if (m_rootElementStyle->direction() == RTL)
3004 isFirstPageLeft = true;
3006 return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
3009 bool CSSStyleSelector::isFirstPage(int pageIndex) const
3011 // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
3012 return (!pageIndex);
3015 String CSSStyleSelector::pageName(int /* pageIndex */) const
3017 // FIXME: Implement page index to page name mapping.
3021 static void applyCounterList(RenderStyle* style, CSSValueList* list, bool isReset)
3023 CounterDirectiveMap& map = style->accessCounterDirectives();
3024 typedef CounterDirectiveMap::iterator Iterator;
3026 Iterator end = map.end();
3027 for (Iterator it = map.begin(); it != end; ++it)
3029 it->second.m_reset = false;
3031 it->second.m_increment = false;
3033 int length = list ? list->length() : 0;
3034 for (int i = 0; i < length; ++i) {
3035 Pair* pair = static_cast<CSSPrimitiveValue*>(list->itemWithoutBoundsCheck(i))->getPairValue();
3036 AtomicString identifier = static_cast<CSSPrimitiveValue*>(pair->first())->getStringValue();
3037 // FIXME: What about overflow?
3038 int value = static_cast<CSSPrimitiveValue*>(pair->second())->getIntValue();
3039 CounterDirectives& directives = map.add(identifier.impl(), CounterDirectives()).first->second;
3041 directives.m_reset = true;
3042 directives.m_resetValue = value;
3044 if (directives.m_increment)
3045 directives.m_incrementValue += value;
3047 directives.m_increment = true;
3048 directives.m_incrementValue = value;
3054 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue *value, RenderStyle* style)
3057 initForStyleResolve(0, style);
3059 applyProperty(id, value);
3062 inline bool isValidVisitedLinkProperty(int id)
3064 switch(static_cast<CSSPropertyID>(id)) {
3065 case CSSPropertyBackgroundColor:
3066 case CSSPropertyBorderLeftColor:
3067 case CSSPropertyBorderRightColor:
3068 case CSSPropertyBorderTopColor:
3069 case CSSPropertyBorderBottomColor:
3070 case CSSPropertyColor:
3071 case CSSPropertyOutlineColor:
3072 case CSSPropertyWebkitColumnRuleColor:
3073 case CSSPropertyWebkitTextFillColor:
3074 case CSSPropertyWebkitTextStrokeColor:
3075 // Also allow shorthands so that inherit/initial still work.
3076 case CSSPropertyBackground:
3077 case CSSPropertyBorderLeft:
3078 case CSSPropertyBorderRight:
3079 case CSSPropertyBorderTop:
3080 case CSSPropertyBorderBottom:
3081 case CSSPropertyOutline:
3082 case CSSPropertyWebkitColumnRule:
3084 case CSSPropertyFill:
3085 case CSSPropertyStroke:
3095 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
3097 CSSPrimitiveValue* primitiveValue = 0;
3098 if (value->isPrimitiveValue())
3099 primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3101 float zoomFactor = m_style->effectiveZoom();
3103 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
3104 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
3105 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
3106 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
3107 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
3108 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
3109 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
3110 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
3111 bool useSVGZoomRules = m_element && m_element->isSVGElement();
3116 unsigned short valueType = value->cssValueType();
3118 bool isInherit = m_parentNode && valueType == CSSValue::CSS_INHERIT;
3119 bool isInitial = valueType == CSSValue::CSS_INITIAL || (!m_parentNode && valueType == CSSValue::CSS_INHERIT);
3121 id = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction());
3123 if (m_checker.m_matchVisitedPseudoClass && !isValidVisitedLinkProperty(id)) {
3124 // Limit the properties that can be applied to only the ones honored by :visited.
3128 // What follows is a list that maps the CSS properties into their corresponding front-end
3129 // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
3130 // are only hit when mapping "inherit" or "initial" into front-end values.
3131 switch (static_cast<CSSPropertyID>(id)) {
3132 // ident only properties
3133 case CSSPropertyBackgroundAttachment:
3134 HANDLE_BACKGROUND_VALUE(attachment, Attachment, value)
3136 case CSSPropertyBackgroundClip:
3137 case CSSPropertyWebkitBackgroundClip:
3138 HANDLE_BACKGROUND_VALUE(clip, Clip, value)
3140 case CSSPropertyWebkitBackgroundComposite:
3141 HANDLE_BACKGROUND_VALUE(composite, Composite, value)
3143 case CSSPropertyBackgroundOrigin:
3144 case CSSPropertyWebkitBackgroundOrigin:
3145 HANDLE_BACKGROUND_VALUE(origin, Origin, value)
3147 case CSSPropertyBackgroundSize:
3148 case CSSPropertyWebkitBackgroundSize:
3149 HANDLE_BACKGROUND_VALUE(size, Size, value)
3151 case CSSPropertyWebkitMaskAttachment:
3152 HANDLE_MASK_VALUE(attachment, Attachment, value)
3154 case CSSPropertyWebkitMaskClip:
3155 HANDLE_MASK_VALUE(clip, Clip, value)
3157 case CSSPropertyWebkitMaskComposite:
3158 HANDLE_MASK_VALUE(composite, Composite, value)
3160 case CSSPropertyWebkitMaskOrigin:
3161 HANDLE_MASK_VALUE(origin, Origin, value)
3163 case CSSPropertyWebkitMaskSize:
3164 HANDLE_MASK_VALUE(size, Size, value)
3166 case CSSPropertyBorderCollapse:
3167 HANDLE_INHERIT_AND_INITIAL(borderCollapse, BorderCollapse)
3168 if (!primitiveValue)
3170 switch (primitiveValue->getIdent()) {
3171 case CSSValueCollapse:
3172 m_style->setBorderCollapse(true);
3174 case CSSValueSeparate:
3175 m_style->setBorderCollapse(false);
3181 case CSSPropertyBorderTopStyle:
3182 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderTopStyle, BorderTopStyle, BorderStyle)
3184 case CSSPropertyBorderRightStyle:
3185 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderRightStyle, BorderRightStyle, BorderStyle)
3187 case CSSPropertyBorderBottomStyle:
3188 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderBottomStyle, BorderBottomStyle, BorderStyle)
3190 case CSSPropertyBorderLeftStyle:
3191 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(borderLeftStyle, BorderLeftStyle, BorderStyle)
3193 case CSSPropertyOutlineStyle:
3194 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(outlineStyle, OutlineStyle, BorderStyle)
3195 if (primitiveValue) {
3196 if (primitiveValue->getIdent() == CSSValueAuto)
3197 m_style->setOutlineStyle(DOTTED, true);
3199 m_style->setOutlineStyle(*primitiveValue);
3202 case CSSPropertyCaptionSide:
3203 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
3205 case CSSPropertyClear:
3206 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
3208 case CSSPropertyDirection:
3209 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(direction, Direction)
3211 case CSSPropertyDisplay:
3212 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display)
3214 if (primitiveValue) {
3215 if (primitiveValue->getIdent() == CSSValueWapMarquee) {
3216 // Initialize WAP Marquee style
3217 m_style->setOverflowX(OMARQUEE);
3218 m_style->setOverflowY(OMARQUEE);
3219 m_style->setWhiteSpace(NOWRAP);
3220 m_style->setMarqueeDirection(MLEFT);
3221 m_style->setMarqueeSpeed(85); // Normal speed
3222 m_style->setMarqueeLoopCount(1);
3223 m_style->setMarqueeBehavior(MSCROLL);
3226 m_style->setDisplay(m_parentStyle->display());
3228 m_style->setDisplay(*primitiveValue);
3230 m_style->setDisplay(*primitiveValue);
3234 case CSSPropertyEmptyCells:
3235 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
3237 case CSSPropertyFloat:
3238 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
3240 case CSSPropertyFontStyle:
3242 FontDescription fontDescription = m_style->fontDescription();
3244 fontDescription.setItalic(m_parentStyle->fontDescription().italic());
3246 fontDescription.setItalic(false);
3248 if (!primitiveValue)
3250 switch (primitiveValue->getIdent()) {
3251 case CSSValueOblique:
3252 // FIXME: oblique is the same as italic for the moment...
3253 case CSSValueItalic:
3254 fontDescription.setItalic(true);
3256 case CSSValueNormal:
3257 fontDescription.setItalic(false);
3263 if (m_style->setFontDescription(fontDescription))
3268 case CSSPropertyFontVariant:
3270 FontDescription fontDescription = m_style->fontDescription();
3272 fontDescription.setSmallCaps(m_parentStyle->fontDescription().smallCaps());
3274 fontDescription.setSmallCaps(false);
3276 if (!primitiveValue)
3278 int id = primitiveValue->getIdent();
3279 if (id == CSSValueNormal)
3280 fontDescription.setSmallCaps(false);
3281 else if (id == CSSValueSmallCaps)
3282 fontDescription.setSmallCaps(true);
3286 if (m_style->setFontDescription(fontDescription))
3291 case CSSPropertyFontWeight:
3293 FontDescription fontDescription = m_style->fontDescription();
3295 fontDescription.setWeight(m_parentStyle->fontDescription().weight());
3297 fontDescription.setWeight(FontWeightNormal);
3299 if (!primitiveValue)
3301 if (primitiveValue->getIdent()) {
3302 switch (primitiveValue->getIdent()) {
3303 case CSSValueBolder:
3304 fontDescription.setWeight(fontDescription.bolderWeight());
3306 case CSSValueLighter:
3307 fontDescription.setWeight(fontDescription.lighterWeight());
3311 fontDescription.setWeight(FontWeightBold);
3313 case CSSValueNormal:
3315 fontDescription.setWeight(FontWeightNormal);
3318 fontDescription.setWeight(FontWeight900);
3321 fontDescription.setWeight(FontWeight800);
3324 fontDescription.setWeight(FontWeight600);
3327 fontDescription.setWeight(FontWeight500);
3330 fontDescription.setWeight(FontWeight300);
3333 fontDescription.setWeight(FontWeight200);
3336 fontDescription.setWeight(FontWeight100);
3342 ASSERT_NOT_REACHED();
3344 if (m_style->setFontDescription(fontDescription))
3349 case CSSPropertyListStylePosition:
3350 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStylePosition, ListStylePosition)
3352 case CSSPropertyListStyleType:
3353 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(listStyleType, ListStyleType)
3355 case CSSPropertyOverflow:
3358 m_style->setOverflowX(m_parentStyle->overflowX());
3359 m_style->setOverflowY(m_parentStyle->overflowY());
3364 m_style->setOverflowX(RenderStyle::initialOverflowX());
3365 m_style->setOverflowY(RenderStyle::initialOverflowY());
3369 EOverflow o = *primitiveValue;
3371 m_style->setOverflowX(o);
3372 m_style->setOverflowY(o);
3376 case CSSPropertyOverflowX:
3377 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowX, OverflowX)
3379 case CSSPropertyOverflowY:
3380 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(overflowY, OverflowY)
3382 case CSSPropertyPageBreakBefore:
3383 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
3385 case CSSPropertyPageBreakAfter:
3386 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
3388 case CSSPropertyPageBreakInside: {
3389 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
3390 if (!primitiveValue)
3392 EPageBreak pageBreak = *primitiveValue;
3393 if (pageBreak != PBALWAYS)
3394 m_style->setPageBreakInside(pageBreak);
3398 case CSSPropertyPosition:
3399 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
3401 case CSSPropertyTableLayout: {
3402 HANDLE_INHERIT_AND_INITIAL(tableLayout, TableLayout)
3404 ETableLayout l = *primitiveValue;
3406 l = RenderStyle::initialTableLayout();
3408 m_style->setTableLayout(l);
3412 case CSSPropertyUnicodeBidi:
3413 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
3415 case CSSPropertyTextTransform:
3416 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
3418 case CSSPropertyVisibility:
3419 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
3421 case CSSPropertyWhiteSpace:
3422 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
3425 case CSSPropertyBackgroundPosition:
3426 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(xPosition, XPosition);
3427 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(yPosition, YPosition);
3429 case CSSPropertyBackgroundPositionX: {
3430 HANDLE_BACKGROUND_VALUE(xPosition, XPosition, value)
3433 case CSSPropertyBackgroundPositionY: {
3434 HANDLE_BACKGROUND_VALUE(yPosition, YPosition, value)
3437 case CSSPropertyWebkitMaskPosition:
3438 HANDLE_MASK_INHERIT_AND_INITIAL(xPosition, XPosition);
3439 HANDLE_MASK_INHERIT_AND_INITIAL(yPosition, YPosition);
3441 case CSSPropertyWebkitMaskPositionX: {
3442 HANDLE_MASK_VALUE(xPosition, XPosition, value)
3445 case CSSPropertyWebkitMaskPositionY: {
3446 HANDLE_MASK_VALUE(yPosition, YPosition, value)
3449 case CSSPropertyBackgroundRepeat:
3450 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatX, RepeatX);
3451 HANDLE_BACKGROUND_INHERIT_AND_INITIAL(repeatY, RepeatY);
3453 case CSSPropertyBackgroundRepeatX:
3454 HANDLE_BACKGROUND_VALUE(repeatX, RepeatX, value)
3456 case CSSPropertyBackgroundRepeatY:
3457 HANDLE_BACKGROUND_VALUE(repeatY, RepeatY, value)
3459 case CSSPropertyWebkitMaskRepeat:
3460 HANDLE_MASK_INHERIT_AND_INITIAL(repeatX, RepeatX);
3461 HANDLE_MASK_INHERIT_AND_INITIAL(repeatY, RepeatY);
3463 case CSSPropertyWebkitMaskRepeatX:
3464 HANDLE_MASK_VALUE(repeatX, RepeatX, value)
3466 case CSSPropertyWebkitMaskRepeatY:
3467 HANDLE_MASK_VALUE(repeatY, RepeatY, value)
3469 case CSSPropertyBorderSpacing: {
3471 m_style->setHorizontalBorderSpacing(m_parentStyle->horizontalBorderSpacing());
3472 m_style->setVerticalBorderSpacing(m_parentStyle->verticalBorderSpacing());
3474 else if (isInitial) {
3475 m_style->setHorizontalBorderSpacing(0);
3476 m_style->setVerticalBorderSpacing(0);
3480 case CSSPropertyWebkitBorderHorizontalSpacing: {
3481 HANDLE_INHERIT_AND_INITIAL(horizontalBorderSpacing, HorizontalBorderSpacing)
3482 if (!primitiveValue)
3484 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3485 m_style->setHorizontalBorderSpacing(spacing);
3488 case CSSPropertyWebkitBorderVerticalSpacing: {
3489 HANDLE_INHERIT_AND_INITIAL(verticalBorderSpacing, VerticalBorderSpacing)
3490 if (!primitiveValue)
3492 short spacing = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3493 m_style->setVerticalBorderSpacing(spacing);
3496 case CSSPropertyCursor:
3498 m_style->setCursor(m_parentStyle->cursor());
3499 m_style->setCursorList(m_parentStyle->cursors());
3502 m_style->clearCursorList();
3504 m_style->setCursor(RenderStyle::initialCursor());
3507 if (value->isValueList()) {
3508 CSSValueList* list = static_cast<CSSValueList*>(value);
3509 int len = list->length();
3510 m_style->setCursor(CURSOR_AUTO);
3511 for (int i = 0; i < len; i++) {
3512 CSSValue* item = list->itemWithoutBoundsCheck(i);
3513 if (!item->isPrimitiveValue())
3515 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
3516 int type = primitiveValue->primitiveType();
3517 if (type == CSSPrimitiveValue::CSS_URI) {
3518 CSSCursorImageValue* image = static_cast<CSSCursorImageValue*>(primitiveValue);
3519 if (image->updateIfSVGCursorIsUsed(m_element)) // Elements with SVG cursors are not allowed to share style.
3520 m_style->setUnique();
3521 // FIXME: Temporary clumsiness to pass off a CachedImage to an API that will eventually convert to using
3523 RefPtr<StyleCachedImage> styleCachedImage(image->cachedImage(m_element->document()->docLoader()));
3524 if (styleCachedImage)
3525 m_style->addCursor(styleCachedImage->cachedImage(), image->hotSpot());
3526 } else if (type == CSSPrimitiveValue::CSS_IDENT)
3527 m_style->setCursor(*primitiveValue);
3529 } else if (primitiveValue) {
3530 int type = primitiveValue->primitiveType();
3531 if (type == CSSPrimitiveValue::CSS_IDENT && m_style->cursor() != ECursor(*primitiveValue))
3532 m_style->setCursor(*primitiveValue);
3535 // colors || inherit
3536 case CSSPropertyColor:
3537 // If the 'currentColor' keyword is set on the 'color' property itself,
3538 // it is treated as 'color:inherit' at parse time
3539 if (primitiveValue && primitiveValue->getIdent() == CSSValueCurrentcolor)
3541 case CSSPropertyBackgroundColor:
3542 case CSSPropertyBorderTopColor:
3543 case CSSPropertyBorderRightColor:
3544 case CSSPropertyBorderBottomColor:
3545 case CSSPropertyBorderLeftColor:
3546 case CSSPropertyOutlineColor:
3547 case CSSPropertyWebkitColumnRuleColor:
3548 case CSSPropertyWebkitTextStrokeColor:
3549 case CSSPropertyWebkitTextFillColor: {
3552 HANDLE_INHERIT_COND(CSSPropertyBackgroundColor, backgroundColor, BackgroundColor)
3553 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderTopColor, borderTopColor, color, BorderTopColor)
3554 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderBottomColor, borderBottomColor, color, BorderBottomColor)
3555 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderRightColor, borderRightColor, color, BorderRightColor)
3556 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyBorderLeftColor, borderLeftColor, color, BorderLeftColor)
3557 HANDLE_INHERIT_COND(CSSPropertyColor, color, Color)
3558 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyOutlineColor, outlineColor, color, OutlineColor)
3559 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitColumnRuleColor, columnRuleColor, color, ColumnRuleColor)
3560 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextStrokeColor, textStrokeColor, color, TextStrokeColor)
3561 HANDLE_INHERIT_COND_WITH_BACKUP(CSSPropertyWebkitTextFillColor, textFillColor, color, TextFillColor)
3565 // The border/outline colors will just map to the invalid color |col| above. This will have the
3566 // effect of forcing the use of the currentColor when it comes time to draw the borders (and of
3567 // not painting the background since the color won't be valid).
3568 if (id == CSSPropertyColor)
3569 col = RenderStyle::initialColor();
3571 if (!primitiveValue)
3573 col = getColorFromPrimitiveValue(primitiveValue);
3577 case CSSPropertyBackgroundColor:
3578 m_style->setBackgroundColor(col);
3580 case CSSPropertyBorderTopColor:
3581 m_style->setBorderTopColor(col);
3583 case CSSPropertyBorderRightColor:
3584 m_style->setBorderRightColor(col);
3586 case CSSPropertyBorderBottomColor:
3587 m_style->setBorderBottomColor(col);
3589 case CSSPropertyBorderLeftColor:
3590 m_style->setBorderLeftColor(col);
3592 case CSSPropertyColor:
3593 m_style->setColor(col);
3595 case CSSPropertyOutlineColor:
3596 m_style->setOutlineColor(col);
3598 case CSSPropertyWebkitColumnRuleColor:
3599 m_style->setColumnRuleColor(col);
3601 case CSSPropertyWebkitTextStrokeColor:
3602 m_style->setTextStrokeColor(col);
3604 case CSSPropertyWebkitTextFillColor:
3605 m_style->setTextFillColor(col);
3613 case CSSPropertyBackgroundImage:
3614 HANDLE_BACKGROUND_VALUE(image, Image, value)
3616 case CSSPropertyWebkitMaskImage:
3617 HANDLE_MASK_VALUE(image, Image, value)
3619 case CSSPropertyListStyleImage:
3621 HANDLE_INHERIT_AND_INITIAL(listStyleImage, ListStyleImage)
3622 m_style->setListStyleImage(styleImage(value));
3627 case CSSPropertyBorderTopWidth:
3628 case CSSPropertyBorderRightWidth:
3629 case CSSPropertyBorderBottomWidth:
3630 case CSSPropertyBorderLeftWidth:
3631 case CSSPropertyOutlineWidth:
3632 case CSSPropertyWebkitColumnRuleWidth:
3635 HANDLE_INHERIT_COND(CSSPropertyBorderTopWidth, borderTopWidth, BorderTopWidth)
3636 HANDLE_INHERIT_COND(CSSPropertyBorderRightWidth, borderRightWidth, BorderRightWidth)
3637 HANDLE_INHERIT_COND(CSSPropertyBorderBottomWidth, borderBottomWidth, BorderBottomWidth)
3638 HANDLE_INHERIT_COND(CSSPropertyBorderLeftWidth, borderLeftWidth, BorderLeftWidth)
3639 HANDLE_INHERIT_COND(CSSPropertyOutlineWidth, outlineWidth, OutlineWidth)
3640 HANDLE_INHERIT_COND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, ColumnRuleWidth)
3643 else if (isInitial) {
3644 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopWidth, BorderTopWidth, BorderWidth)
3645 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderRightWidth, BorderRightWidth, BorderWidth)
3646 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomWidth, BorderBottomWidth, BorderWidth)
3647 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderLeftWidth, BorderLeftWidth, BorderWidth)
3648 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyOutlineWidth, OutlineWidth, BorderWidth)
3649 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitColumnRuleWidth, ColumnRuleWidth, BorderWidth)
3653 if (!primitiveValue)
3656 switch (primitiveValue->getIdent()) {
3660 case CSSValueMedium:
3666 case CSSValueInvalid:
3667 width = primitiveValue->computeLengthShort(style(), m_rootElementStyle, zoomFactor);
3673 if (width < 0) return;
3675 case CSSPropertyBorderTopWidth:
3676 m_style->setBorderTopWidth(width);
3678 case CSSPropertyBorderRightWidth:
3679 m_style->setBorderRightWidth(width);
3681 case CSSPropertyBorderBottomWidth:
3682 m_style->setBorderBottomWidth(width);
3684 case CSSPropertyBorderLeftWidth:
3685 m_style->setBorderLeftWidth(width);
3687 case CSSPropertyOutlineWidth:
3688 m_style->setOutlineWidth(width);
3690 case CSSPropertyWebkitColumnRuleWidth:
3691 m_style->setColumnRuleWidth(width);
3699 case CSSPropertyWebkitFontSmoothing: {
3700 FontDescription fontDescription = m_style->fontDescription();
3702 fontDescription.setFontSmoothing(m_parentStyle->fontDescription().fontSmoothing());
3704 fontDescription.setFontSmoothing(AutoSmoothing);
3706 if (!primitiveValue)
3708 int id = primitiveValue->getIdent();
3709 FontSmoothingMode smoothing;
3712 smoothing = AutoSmoothing;
3715 smoothing = NoSmoothing;
3717 case CSSValueAntialiased:
3718 smoothing = Antialiased;
3720 case CSSValueSubpixelAntialiased:
3721 smoothing = SubpixelAntialiased;
3724 ASSERT_NOT_REACHED();
3725 smoothing = AutoSmoothing;
3727 fontDescription.setFontSmoothing(smoothing);
3729 if (m_style->setFontDescription(fontDescription))
3734 case CSSPropertyLetterSpacing:
3735 case CSSPropertyWordSpacing:
3739 HANDLE_INHERIT_COND(CSSPropertyLetterSpacing, letterSpacing, LetterSpacing)
3740 HANDLE_INHERIT_COND(CSSPropertyWordSpacing, wordSpacing, WordSpacing)
3743 else if (isInitial) {
3744 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLetterSpacing, LetterSpacing, LetterWordSpacing)
3745 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWordSpacing, WordSpacing, LetterWordSpacing)
3750 if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
3753 if (!primitiveValue)
3755 width = primitiveValue->computeLengthInt(style(), m_rootElementStyle, useSVGZoomRules ? 1.0f : zoomFactor);
3758 case CSSPropertyLetterSpacing:
3759 m_style->setLetterSpacing(width);
3761 case CSSPropertyWordSpacing:
3762 m_style->setWordSpacing(width);
3764 // ### needs the definitions in renderstyle
3770 case CSSPropertyWordBreak:
3771 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
3773 case CSSPropertyWordWrap:
3774 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
3776 case CSSPropertyWebkitNbspMode:
3777 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
3779 case CSSPropertyWebkitLineBreak:
3780 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
3782 case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
3783 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
3786 case CSSPropertyResize:
3788 HANDLE_INHERIT_AND_INITIAL(resize, Resize)
3790 if (!primitiveValue->getIdent())
3793 EResize r = RESIZE_NONE;
3794 if (primitiveValue->getIdent() == CSSValueAuto) {
3795 if (Settings* settings = m_checker.m_document->settings())
3796 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
3798 r = *primitiveValue;
3800 m_style->setResize(r);
3805 case CSSPropertyMaxWidth:
3807 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone)
3809 case CSSPropertyTop:
3810 case CSSPropertyLeft:
3811 case CSSPropertyRight:
3812 case CSSPropertyBottom:
3813 case CSSPropertyWidth:
3814 case CSSPropertyMinWidth:
3815 case CSSPropertyMarginTop:
3816 case CSSPropertyMarginRight:
3817 case CSSPropertyMarginBottom:
3818 case CSSPropertyMarginLeft:
3820 if (id == CSSPropertyWidth || id == CSSPropertyMinWidth || id == CSSPropertyMaxWidth) {
3821 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
3822 l = Length(Intrinsic);
3825 else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
3826 l = Length(MinIntrinsic);
3830 if (id != CSSPropertyMaxWidth && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
3832 case CSSPropertyPaddingTop:
3833 case CSSPropertyPaddingRight:
3834 case CSSPropertyPaddingBottom:
3835 case CSSPropertyPaddingLeft:
3836 case CSSPropertyTextIndent:
3840 HANDLE_INHERIT_COND(CSSPropertyMaxWidth, maxWidth, MaxWidth)
3841 HANDLE_INHERIT_COND(CSSPropertyBottom, bottom, Bottom)
3842 HANDLE_INHERIT_COND(CSSPropertyTop, top, Top)
3843 HANDLE_INHERIT_COND(CSSPropertyLeft, left, Left)
3844 HANDLE_INHERIT_COND(CSSPropertyRight, right, Right)
3845 HANDLE_INHERIT_COND(CSSPropertyWidth, width, Width)
3846 HANDLE_INHERIT_COND(CSSPropertyMinWidth, minWidth, MinWidth)
3847 HANDLE_INHERIT_COND(CSSPropertyPaddingTop, paddingTop, PaddingTop)
3848 HANDLE_INHERIT_COND(CSSPropertyPaddingRight, paddingRight, PaddingRight)
3849 HANDLE_INHERIT_COND(CSSPropertyPaddingBottom, paddingBottom, PaddingBottom)
3850 HANDLE_INHERIT_COND(CSSPropertyPaddingLeft, paddingLeft, PaddingLeft)
3851 HANDLE_INHERIT_COND(CSSPropertyMarginTop, marginTop, MarginTop)
3852 HANDLE_INHERIT_COND(CSSPropertyMarginRight, marginRight, MarginRight)
3853 HANDLE_INHERIT_COND(CSSPropertyMarginBottom, marginBottom, MarginBottom)
3854 HANDLE_INHERIT_COND(CSSPropertyMarginLeft, marginLeft, MarginLeft)
3855 HANDLE_INHERIT_COND(CSSPropertyTextIndent, textIndent, TextIndent)
3858 else if (isInitial) {
3859 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxWidth, MaxWidth, MaxSize)
3860 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBottom, Bottom, Offset)
3861 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyTop, Top, Offset)
3862 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyLeft, Left, Offset)
3863 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyRight, Right, Offset)
3864 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWidth, Width, Size)
3865 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinWidth, MinWidth, MinSize)
3866 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingTop, PaddingTop, Padding)
3867 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingRight, PaddingRight, Padding)
3868 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingBottom, PaddingBottom, Padding)
3869 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyPaddingLeft, PaddingLeft, Padding)
3870 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginTop, MarginTop, Margin)
3871 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginRight, MarginRight, Margin)
3872 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginBottom, MarginBottom, Margin)
3873 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMarginLeft, MarginLeft, Margin)
3874 HANDLE_INITIAL_COND(CSSPropertyTextIndent, TextIndent)
3878 if (primitiveValue && !apply) {
3879 int type = primitiveValue->primitiveType();
3880 if (CSSPrimitiveValue::isUnitTypeLength(type))
3881 // Handle our quirky margin units if we have them.
3882 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed,
3883 primitiveValue->isQuirkValue());
3884 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3885 l = Length(primitiveValue->getDoubleValue(), Percent);
3892 case CSSPropertyMaxWidth:
3893 m_style->setMaxWidth(l);
3895 case CSSPropertyBottom:
3896 m_style->setBottom(l);
3898 case CSSPropertyTop:
3901 case CSSPropertyLeft:
3902 m_style->setLeft(l);
3904 case CSSPropertyRight:
3905 m_style->setRight(l);
3907 case CSSPropertyWidth:
3908 m_style->setWidth(l);
3910 case CSSPropertyMinWidth:
3911 m_style->setMinWidth(l);
3913 case CSSPropertyPaddingTop:
3914 m_style->setPaddingTop(l);
3916 case CSSPropertyPaddingRight:
3917 m_style->setPaddingRight(l);
3919 case CSSPropertyPaddingBottom:
3920 m_style->setPaddingBottom(l);
3922 case CSSPropertyPaddingLeft:
3923 m_style->setPaddingLeft(l);
3925 case CSSPropertyMarginTop:
3926 m_style->setMarginTop(l);
3928 case CSSPropertyMarginRight:
3929 m_style->setMarginRight(l);
3931 case CSSPropertyMarginBottom:
3932 m_style->setMarginBottom(l);
3934 case CSSPropertyMarginLeft:
3935 m_style->setMarginLeft(l);
3937 case CSSPropertyTextIndent:
3938 m_style->setTextIndent(l);
3946 case CSSPropertyMaxHeight:
3947 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3948 l = Length(undefinedLength, Fixed);
3951 case CSSPropertyHeight:
3952 case CSSPropertyMinHeight:
3953 if (primitiveValue && primitiveValue->getIdent() == CSSValueIntrinsic) {
3954 l = Length(Intrinsic);
3956 } else if (primitiveValue && primitiveValue->getIdent() == CSSValueMinIntrinsic) {
3957 l = Length(MinIntrinsic);
3959 } else if (id != CSSPropertyMaxHeight && primitiveValue && primitiveValue->getIdent() == CSSValueAuto)
3962 HANDLE_INHERIT_COND(CSSPropertyMaxHeight, maxHeight, MaxHeight)
3963 HANDLE_INHERIT_COND(CSSPropertyHeight, height, Height)
3964 HANDLE_INHERIT_COND(CSSPropertyMinHeight, minHeight, MinHeight)
3968 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMaxHeight, MaxHeight, MaxSize)
3969 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyHeight, Height, Size)
3970 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyMinHeight, MinHeight, MinSize)
3974 if (primitiveValue && !apply) {
3975 unsigned short type = primitiveValue->primitiveType();
3976 if (CSSPrimitiveValue::isUnitTypeLength(type))
3977 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
3978 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3979 l = Length(primitiveValue->getDoubleValue(), Percent);
3986 case CSSPropertyMaxHeight:
3987 m_style->setMaxHeight(l);
3989 case CSSPropertyHeight:
3990 m_style->setHeight(l);
3992 case CSSPropertyMinHeight:
3993 m_style->setMinHeight(l);
3998 case CSSPropertyVerticalAlign:
3999 HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
4000 if (!primitiveValue)
4002 if (primitiveValue->getIdent()) {
4003 EVerticalAlign align;
4005 switch (primitiveValue->getIdent()) {
4008 case CSSValueBottom:
4009 align = BOTTOM; break;
4010 case CSSValueMiddle:
4011 align = MIDDLE; break;
4012 case CSSValueBaseline:
4013 align = BASELINE; break;
4014 case CSSValueTextBottom:
4015 align = TEXT_BOTTOM; break;
4016 case CSSValueTextTop:
4017 align = TEXT_TOP; break;
4021 align = SUPER; break;
4022 case CSSValueWebkitBaselineMiddle:
4023 align = BASELINE_MIDDLE; break;
4027 m_style->setVerticalAlign(align);
4030 int type = primitiveValue->primitiveType();
4032 if (CSSPrimitiveValue::isUnitTypeLength(type))
4033 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
4034 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4035 l = Length(primitiveValue->getDoubleValue(), Percent);
4037 m_style->setVerticalAlign(LENGTH);
4038 m_style->setVerticalAlignLength(l);
4042 case CSSPropertyFontSize:
4044 FontDescription fontDescription = m_style->fontDescription();
4045 fontDescription.setKeywordSize(0);
4049 bool parentIsAbsoluteSize = false;
4051 oldSize = m_parentStyle->fontDescription().specifiedSize();
4052 parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
4058 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
4059 } else if (isInitial) {
4060 size = fontSizeForKeyword(m_checker.m_document, CSSValueMedium, fontDescription.useFixedDefaultSize());
4061 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
4062 } else if (primitiveValue->getIdent()) {
4063 // Keywords are being used.
4064 switch (primitiveValue->getIdent()) {
4065 case CSSValueXxSmall:
4066 case CSSValueXSmall:
4068 case CSSValueMedium:
4070 case CSSValueXLarge:
4071 case CSSValueXxLarge:
4072 case CSSValueWebkitXxxLarge:
4073 size = fontSizeForKeyword(m_checker.m_document, primitiveValue->getIdent(), fontDescription.useFixedDefaultSize());
4074 fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
4076 case CSSValueLarger:
4077 size = largerFontSize(oldSize, m_style->htmlHacks());
4079 case CSSValueSmaller:
4080 size = smallerFontSize(oldSize, m_style->htmlHacks());
4086 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize &&
4087 (primitiveValue->getIdent() == CSSValueLarger ||
4088 primitiveValue->getIdent() == CSSValueSmaller));
4090 int type = primitiveValue->primitiveType();
4091 fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize ||
4092 (type != CSSPrimitiveValue::CSS_PERCENTAGE &&
4093 type != CSSPrimitiveValue::CSS_EMS &&
4094 type != CSSPrimitiveValue::CSS_EXS &&
4095 type != CSSPrimitiveValue::CSS_REMS));
4096 if (CSSPrimitiveValue::isUnitTypeLength(type))
4097 size = primitiveValue->computeLengthFloat(m_parentStyle, m_rootElementStyle, true);
4098 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4099 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
4107 setFontSize(fontDescription, size);
4108 if (m_style->setFontDescription(fontDescription))
4113 case CSSPropertyZIndex: {
4115 if (m_parentStyle->hasAutoZIndex())
4116 m_style->setHasAutoZIndex();
4118 m_style->setZIndex(m_parentStyle->zIndex());
4120 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
4121 m_style->setHasAutoZIndex();
4125 // FIXME: Should clamp all sorts of other integer properties too.
4126 const double minIntAsDouble = INT_MIN;
4127 const double maxIntAsDouble = INT_MAX;
4128 m_style->setZIndex(static_cast<int>(max(minIntAsDouble, min(primitiveValue->getDoubleValue(), maxIntAsDouble))));
4131 case CSSPropertyWidows:
4133 HANDLE_INHERIT_AND_INITIAL(widows, Widows)
4134 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4136 m_style->setWidows(primitiveValue->getIntValue());
4140 case CSSPropertyOrphans:
4142 HANDLE_INHERIT_AND_INITIAL(orphans, Orphans)
4143 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4145 m_style->setOrphans(primitiveValue->getIntValue());
4149 // length, percent, number
4150 case CSSPropertyLineHeight:
4152 HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
4153 if (!primitiveValue)
4156 int type = primitiveValue->primitiveType();
4157 if (primitiveValue->getIdent() == CSSValueNormal)
4158 lineHeight = Length(-100.0, Percent);
4159 else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
4160 double multiplier = zoomFactor;
4161 if (m_style->textSizeAdjust()) {
4162 if (FrameView* view = m_checker.m_document->view()) {
4163 if (view->shouldApplyTextZoom())
4164 multiplier *= view->textZoomFactor();
4167 lineHeight = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, multiplier), Fixed);
4168 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4169 lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
4170 else if (type == CSSPrimitiveValue::CSS_NUMBER)
4171 lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
4174 m_style->setLineHeight(lineHeight);
4179 case CSSPropertyTextAlign:
4181 HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
4182 if (!primitiveValue)
4184 int id = primitiveValue->getIdent();
4185 if (id == CSSValueStart)
4186 m_style->setTextAlign(m_style->direction() == LTR ? LEFT : RIGHT);
4187 else if (id == CSSValueEnd)
4188 m_style->setTextAlign(m_style->direction() == LTR ? RIGHT : LEFT);
4190 m_style->setTextAlign(*primitiveValue);
4195 case CSSPropertyClip:
4201 bool hasClip = true;
4203 if (m_parentStyle->hasClip()) {
4204 top = m_parentStyle->clipTop();
4205 right = m_parentStyle->clipRight();
4206 bottom = m_parentStyle->clipBottom();
4207 left = m_parentStyle->clipLeft();
4210 top = right = bottom = left = Length();
4212 } else if (isInitial) {
4214 top = right = bottom = left = Length();
4215 } else if (!primitiveValue) {
4217 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
4218 Rect* rect = primitiveValue->getRectValue();
4221 top = convertToLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
4222 right = convertToLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
4223 bottom = convertToLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
4224 left = convertToLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
4225 } else if (primitiveValue->getIdent() != CSSValueAuto) {
4228 m_style->setClip(top, right, bottom, left);
4229 m_style->setHasClip(hasClip);
4236 case CSSPropertyContent:
4237 // list of string, uri, counter, attr, i
4239 // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
4240 // note is a reminder that eventually "inherit" needs to be supported.
4243 m_style->clearContent();
4247 if (!value->isValueList())
4250 CSSValueList* list = static_cast<CSSValueList*>(value);
4251 int len = list->length();
4253 bool didSet = false;
4254 for (int i = 0; i < len; i++) {
4255 CSSValue* item = list->itemWithoutBoundsCheck(i);
4256 if (item->isImageGeneratorValue()) {
4257 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
4261 if (!item->isPrimitiveValue())
4264 CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item);
4265 switch (val->primitiveType()) {
4266 case CSSPrimitiveValue::CSS_STRING:
4267 m_style->setContent(val->getStringValue().impl(), didSet);
4270 case CSSPrimitiveValue::CSS_ATTR: {
4271 // FIXME: Can a namespace be specified for an attr(foo)?
4272 if (m_style->styleType() == NOPSEUDO)
4273 m_style->setUnique();
4275 m_parentStyle->setUnique();
4276 QualifiedName attr(nullAtom, val->getStringValue().impl(), nullAtom);
4277 m_style->setContent(m_element->getAttribute(attr).impl(), didSet);
4279 // register the fact that the attribute value affects the style
4280 m_selectorAttrs.add(attr.localName().impl());
4283 case CSSPrimitiveValue::CSS_URI: {
4284 CSSImageValue* image = static_cast<CSSImageValue*>(val);
4285 m_style->setContent(image->cachedImage(m_element->document()->docLoader()), didSet);
4289 case CSSPrimitiveValue::CSS_COUNTER: {
4290 Counter* counterValue = val->getCounterValue();
4291 CounterContent* counter = new CounterContent(counterValue->identifier(),
4292 (EListStyleType)counterValue->listStyleNumber(), counterValue->separator());
4293 m_style->setContent(counter, didSet);
4299 m_style->clearContent();
4303 case CSSPropertyCounterIncrement:
4304 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, false);
4306 case CSSPropertyCounterReset:
4307 applyCounterList(style(), value->isValueList() ? static_cast<CSSValueList*>(value) : 0, true);
4310 case CSSPropertyFontFamily: {
4311 // list of strings and ids
4313 FontDescription parentFontDescription = m_parentStyle->fontDescription();
4314 FontDescription fontDescription = m_style->fontDescription();
4315 fontDescription.setGenericFamily(parentFontDescription.genericFamily());
4316 fontDescription.setFamily(parentFontDescription.firstFamily());
4317 fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
4318 if (m_style->setFontDescription(fontDescription))
4321 } else if (isInitial) {
4322 FontDescription initialDesc = FontDescription();
4323 FontDescription fontDescription = m_style->fontDescription();
4324 // We need to adjust the size to account for the generic family change from monospace
4325 // to non-monospace.
4326 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
4327 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
4328 fontDescription.setGenericFamily(initialDesc.genericFamily());
4329 if (!initialDesc.firstFamily().familyIsEmpty())
4330 fontDescription.setFamily(initialDesc.firstFamily());
4331 if (m_style->setFontDescription(fontDescription))
4336 if (!value->isValueList())
4338 FontDescription fontDescription = m_style->fontDescription();
4339 CSSValueList* list = static_cast<CSSValueList*>(value);
4340 int len = list->length();
4341 FontFamily& firstFamily = fontDescription.firstFamily();
4342 FontFamily* currFamily = 0;
4344 // Before mapping in a new font-family property, we should reset the generic family.
4345 bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
4346 fontDescription.setGenericFamily(FontDescription::NoFamily);
4348 for (int i = 0; i < len; i++) {
4349 CSSValue* item = list->itemWithoutBoundsCheck(i);
4350 if (!item->isPrimitiveValue())
4352 CSSPrimitiveValue* val = static_cast<CSSPrimitiveValue*>(item);
4354 Settings* settings = m_checker.m_document->settings();
4355 if (val->primitiveType() == CSSPrimitiveValue::CSS_STRING)
4356 face = static_cast<FontFamilyValue*>(val)->familyName();
4357 else if (val->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
4358 switch (val->getIdent()) {
4359 case CSSValueWebkitBody:
4360 face = settings->standardFontFamily();
4363 face = "-webkit-serif";
4364 fontDescription.setGenericFamily(FontDescription::SerifFamily);
4366 case CSSValueSansSerif:
4367 face = "-webkit-sans-serif";
4368 fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
4370 case CSSValueCursive:
4371 face = "-webkit-cursive";
4372 fontDescription.setGenericFamily(FontDescription::CursiveFamily);
4374 case CSSValueFantasy:
4375 face = "-webkit-fantasy";
4376 fontDescription.setGenericFamily(FontDescription::FantasyFamily);
4378 case CSSValueMonospace:
4379 face = "-webkit-monospace";
4380 fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
4385 if (!face.isEmpty()) {
4387 // Filling in the first family.
4388 firstFamily.setFamily(face);
4389 firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
4390 currFamily = &firstFamily;
4391 fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
4393 RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
4394 newFamily->setFamily(face);
4395 currFamily->appendFamily(newFamily);
4396 currFamily = newFamily.get();
4401 // We can't call useFixedDefaultSize() until all new font families have been added
4402 // If currFamily is non-zero then we set at least one family on this description.
4404 if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
4405 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
4407 if (m_style->setFontDescription(fontDescription))
4412 case CSSPropertyTextDecoration: {
4414 HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
4415 int t = RenderStyle::initialTextDecoration();
4416 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
4419 if (!value->isValueList()) return;
4420 CSSValueList *list = static_cast<CSSValueList*>(value);
4421 int len = list->length();
4422 for (int i = 0; i < len; i++)
4424 CSSValue *item = list->itemWithoutBoundsCheck(i);
4425 if (!item->isPrimitiveValue()) continue;
4426 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
4427 switch (primitiveValue->getIdent()) {
4430 case CSSValueUnderline:
4431 t |= UNDERLINE; break;
4432 case CSSValueOverline:
4433 t |= OVERLINE; break;
4434 case CSSValueLineThrough:
4435 t |= LINE_THROUGH; break;
4444 m_style->setTextDecoration(t);
4448 case CSSPropertyZoom:
4450 // Reset the zoom in effect before we do anything. This allows the setZoom method to accurately compute a new
4452 m_style->setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
4454 // Now we can handle inherit and initial.
4455 HANDLE_INHERIT_AND_INITIAL(zoom, Zoom)
4457 // Handle normal/reset, numbers and percentages.
4458 int type = primitiveValue->primitiveType();
4459 if (primitiveValue->getIdent() == CSSValueNormal)
4460 m_style->setZoom(RenderStyle::initialZoom());
4461 else if (primitiveValue->getIdent() == CSSValueReset) {
4462 m_style->setEffectiveZoom(RenderStyle::initialZoom());
4463 m_style->setZoom(RenderStyle::initialZoom());
4464 } else if (primitiveValue->getIdent() == CSSValueDocument) {
4465 float docZoom = m_checker.m_document->renderer()->style()->zoom();
4466 m_style->setEffectiveZoom(docZoom);
4467 m_style->setZoom(docZoom);
4468 } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE) {
4469 if (primitiveValue->getFloatValue())
4470 m_style->setZoom(primitiveValue->getFloatValue() / 100.0f);
4471 } else if (type == CSSPrimitiveValue::CSS_NUMBER) {
4472 if (primitiveValue->getFloatValue())
4473 m_style->setZoom(primitiveValue->getFloatValue());
4479 // shorthand properties
4480 case CSSPropertyBackground:
4482 m_style->clearBackgroundLayers();
4483 m_style->setBackgroundColor(Color());
4485 else if (isInherit) {
4486 m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
4487 m_style->setBackgroundColor(m_parentStyle->backgroundColor());
4490 case CSSPropertyWebkitMask:
4492 m_style->clearMaskLayers();
4494 m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
4497 case CSSPropertyBorder:
4498 case CSSPropertyBorderStyle:
4499 case CSSPropertyBorderWidth:
4500 case CSSPropertyBorderColor:
4501 if (id == CSSPropertyBorder || id == CSSPropertyBorderColor)
4504 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
4505 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
4506 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
4507 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor(): m_parentStyle->color());
4509 else if (isInitial) {
4510 m_style->setBorderTopColor(Color()); // Reset to invalid color so currentColor is used instead.
4511 m_style->setBorderBottomColor(Color());
4512 m_style->setBorderLeftColor(Color());
4513 m_style->setBorderRightColor(Color());
4516 if (id == CSSPropertyBorder || id == CSSPropertyBorderStyle)
4519 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
4520 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
4521 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
4522 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
4524 else if (isInitial) {
4525 m_style->setBorderTopStyle(RenderStyle::initialBorderStyle());
4526 m_style->setBorderBottomStyle(RenderStyle::initialBorderStyle());
4527 m_style->setBorderLeftStyle(RenderStyle::initialBorderStyle());
4528 m_style->setBorderRightStyle(RenderStyle::initialBorderStyle());
4531 if (id == CSSPropertyBorder || id == CSSPropertyBorderWidth)
4534 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
4535 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
4536 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
4537 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
4539 else if (isInitial) {
4540 m_style->setBorderTopWidth(RenderStyle::initialBorderWidth());
4541 m_style->setBorderBottomWidth(RenderStyle::initialBorderWidth());
4542 m_style->setBorderLeftWidth(RenderStyle::initialBorderWidth());
4543 m_style->setBorderRightWidth(RenderStyle::initialBorderWidth());
4547 case CSSPropertyBorderTop:
4549 m_style->setBorderTopColor(m_parentStyle->borderTopColor().isValid() ? m_parentStyle->borderTopColor() : m_parentStyle->color());
4550 m_style->setBorderTopStyle(m_parentStyle->borderTopStyle());
4551 m_style->setBorderTopWidth(m_parentStyle->borderTopWidth());
4554 m_style->resetBorderTop();
4556 case CSSPropertyBorderRight:
4558 m_style->setBorderRightColor(m_parentStyle->borderRightColor().isValid() ? m_parentStyle->borderRightColor() : m_parentStyle->color());
4559 m_style->setBorderRightStyle(m_parentStyle->borderRightStyle());
4560 m_style->setBorderRightWidth(m_parentStyle->borderRightWidth());
4563 m_style->resetBorderRight();
4565 case CSSPropertyBorderBottom:
4567 m_style->setBorderBottomColor(m_parentStyle->borderBottomColor().isValid() ? m_parentStyle->borderBottomColor() : m_parentStyle->color());
4568 m_style->setBorderBottomStyle(m_parentStyle->borderBottomStyle());
4569 m_style->setBorderBottomWidth(m_parentStyle->borderBottomWidth());
4572 m_style->resetBorderBottom();
4574 case CSSPropertyBorderLeft:
4576 m_style->setBorderLeftColor(m_parentStyle->borderLeftColor().isValid() ? m_parentStyle->borderLeftColor() : m_parentStyle->color());
4577 m_style->setBorderLeftStyle(m_parentStyle->borderLeftStyle());
4578 m_style->setBorderLeftWidth(m_parentStyle->borderLeftWidth());
4581 m_style->resetBorderLeft();
4583 case CSSPropertyMargin:
4585 m_style->setMarginTop(m_parentStyle->marginTop());
4586 m_style->setMarginBottom(m_parentStyle->marginBottom());
4587 m_style->setMarginLeft(m_parentStyle->marginLeft());
4588 m_style->setMarginRight(m_parentStyle->marginRight());
4591 m_style->resetMargin();
4593 case CSSPropertyPadding:
4595 m_style->setPaddingTop(m_parentStyle->paddingTop());
4596 m_style->setPaddingBottom(m_parentStyle->paddingBottom());
4597 m_style->setPaddingLeft(m_parentStyle->paddingLeft());
4598 m_style->setPaddingRight(m_parentStyle->paddingRight());
4601 m_style->resetPadding();
4603 case CSSPropertyFont:
4605 FontDescription fontDescription = m_parentStyle->fontDescription();
4606 m_style->setLineHeight(m_parentStyle->lineHeight());
4607 m_lineHeightValue = 0;
4608 if (m_style->setFontDescription(fontDescription))
4610 } else if (isInitial) {
4611 Settings* settings = m_checker.m_document->settings();
4612 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
4615 FontDescription fontDescription;
4616 fontDescription.setGenericFamily(FontDescription::StandardFamily);
4617 fontDescription.setRenderingMode(settings->fontRenderingMode());
4618 fontDescription.setUsePrinterFont(m_checker.m_document->printing());
4619 const AtomicString& standardFontFamily = m_checker.m_document->settings()->standardFontFamily();
4620 if (!standardFontFamily.isEmpty()) {
4621 fontDescription.firstFamily().setFamily(standardFontFamily);
4622 fontDescription.firstFamily().appendFamily(0);
4624 fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
4625 setFontSize(fontDescription, fontSizeForKeyword(m_checker.m_document, CSSValueMedium, false));
4626 m_style->setLineHeight(RenderStyle::initialLineHeight());
4627 m_lineHeightValue = 0;
4628 if (m_style->setFontDescription(fontDescription))
4630 } else if (primitiveValue) {
4631 m_style->setLineHeight(RenderStyle::initialLineHeight());
4632 m_lineHeightValue = 0;
4634 FontDescription fontDescription;
4635 RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
4637 // Double-check and see if the theme did anything. If not, don't bother updating the font.
4638 if (fontDescription.isAbsoluteSize()) {
4639 // Make sure the rendering mode and printer font settings are updated.
4640 Settings* settings = m_checker.m_document->settings();
4641 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
4644 fontDescription.setRenderingMode(settings->fontRenderingMode());
4645 fontDescription.setUsePrinterFont(m_checker.m_document->printing());
4647 // Handle the zoom factor.
4648 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules));
4649 if (m_style->setFontDescription(fontDescription))
4652 } else if (value->isFontValue()) {
4653 FontValue *font = static_cast<FontValue*>(value);
4654 if (!font->style || !font->variant || !font->weight ||
4655 !font->size || !font->lineHeight || !font->family)
4657 applyProperty(CSSPropertyFontStyle, font->style.get());
4658 applyProperty(CSSPropertyFontVariant, font->variant.get());
4659 applyProperty(CSSPropertyFontWeight, font->weight.get());
4660 applyProperty(CSSPropertyFontSize, font->size.get());
4662 m_lineHeightValue = font->lineHeight.get();
4664 applyProperty(CSSPropertyFontFamily, font->family.get());
4668 case CSSPropertyListStyle:
4670 m_style->setListStyleType(m_parentStyle->listStyleType());
4671 m_style->setListStyleImage(m_parentStyle->listStyleImage());
4672 m_style->setListStylePosition(m_parentStyle->listStylePosition());
4674 else if (isInitial) {
4675 m_style->setListStyleType(RenderStyle::initialListStyleType());
4676 m_style->setListStyleImage(RenderStyle::initialListStyleImage());
4677 m_style->setListStylePosition(RenderStyle::initialListStylePosition());
4680 case CSSPropertyOutline:
4682 m_style->setOutlineWidth(m_parentStyle->outlineWidth());
4683 m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
4684 m_style->setOutlineStyle(m_parentStyle->outlineStyle());
4687 m_style->resetOutline();
4691 case CSSPropertyWebkitAppearance: {
4692 HANDLE_INHERIT_AND_INITIAL(appearance, Appearance)
4693 if (!primitiveValue)
4695 m_style->setAppearance(*primitiveValue);
4698 case CSSPropertyWebkitBinding: {
4700 if (isInitial || (primitiveValue && primitiveValue->getIdent() == CSSValueNone)) {
4701 m_style->deleteBindingURIs();
4704 else if (isInherit) {
4705 if (m_parentStyle->bindingURIs())
4706 m_style->inheritBindingURIs(m_parentStyle->bindingURIs());
4708 m_style->deleteBindingURIs();
4712 if (!value->isValueList()) return;
4713 CSSValueList* list = static_cast<CSSValueList*>(value);
4714 bool firstBinding = true;
4715 for (unsigned int i = 0; i < list->length(); i++) {
4716 CSSValue *item = list->itemWithoutBoundsCheck(i);
4717 CSSPrimitiveValue *val = static_cast<CSSPrimitiveValue*>(item);
4718 if (val->primitiveType() == CSSPrimitiveValue::CSS_URI) {
4720 firstBinding = false;
4721 m_style->deleteBindingURIs();
4723 m_style->addBindingURI(val->getStringValue());
4730 case CSSPropertyWebkitBorderImage:
4731 case CSSPropertyWebkitMaskBoxImage: {
4733 HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
4734 HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
4736 } else if (isInitial) {
4737 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
4738 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
4742 NinePieceImage image;
4743 mapNinePieceImage(value, image);
4745 if (id == CSSPropertyWebkitBorderImage)
4746 m_style->setBorderImage(image);
4748 m_style->setMaskBoxImage(image);
4752 case CSSPropertyBorderRadius:
4753 case CSSPropertyWebkitBorderRadius:
4755 m_style->setBorderTopLeftRadius(m_parentStyle->borderTopLeftRadius());
4756 m_style->setBorderTopRightRadius(m_parentStyle->borderTopRightRadius());
4757 m_style->setBorderBottomLeftRadius(m_parentStyle->borderBottomLeftRadius());
4758 m_style->setBorderBottomRightRadius(m_parentStyle->borderBottomRightRadius());
4762 m_style->resetBorderRadius();
4766 case CSSPropertyBorderTopLeftRadius:
4767 case CSSPropertyBorderTopRightRadius:
4768 case CSSPropertyBorderBottomLeftRadius:
4769 case CSSPropertyBorderBottomRightRadius: {
4771 HANDLE_INHERIT_COND(CSSPropertyBorderTopLeftRadius, borderTopLeftRadius, BorderTopLeftRadius)
4772 HANDLE_INHERIT_COND(CSSPropertyBorderTopRightRadius, borderTopRightRadius, BorderTopRightRadius)
4773 HANDLE_INHERIT_COND(CSSPropertyBorderBottomLeftRadius, borderBottomLeftRadius, BorderBottomLeftRadius)
4774 HANDLE_INHERIT_COND(CSSPropertyBorderBottomRightRadius, borderBottomRightRadius, BorderBottomRightRadius)
4779 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopLeftRadius, BorderTopLeftRadius, BorderRadius)
4780 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderTopRightRadius, BorderTopRightRadius, BorderRadius)
4781 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomLeftRadius, BorderBottomLeftRadius, BorderRadius)
4782 HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderBottomRightRadius, BorderBottomRightRadius, BorderRadius)
4786 if (!primitiveValue)
4789 Pair* pair = primitiveValue->getPairValue();
4793 int width = pair->first()->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
4794 int height = pair->second()->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
4795 if (width < 0 || height < 0)
4799 height = 0; // Null out the other value.
4800 else if (height == 0)
4801 width = 0; // Null out the other value.
4803 IntSize size(width, height);
4805 case CSSPropertyBorderTopLeftRadius:
4806 m_style->setBorderTopLeftRadius(size);
4808 case CSSPropertyBorderTopRightRadius:
4809 m_style->setBorderTopRightRadius(size);
4811 case CSSPropertyBorderBottomLeftRadius:
4812 m_style->setBorderBottomLeftRadius(size);
4814 case CSSPropertyBorderBottomRightRadius:
4815 m_style->setBorderBottomRightRadius(size);
4818 m_style->setBorderRadius(size);
4824 case CSSPropertyOutlineOffset:
4825 HANDLE_INHERIT_AND_INITIAL(outlineOffset, OutlineOffset)
4826 m_style->setOutlineOffset(primitiveValue->computeLengthInt(style(), m_rootElementStyle, zoomFactor));
4828 case CSSPropertyTextRendering: {
4829 FontDescription fontDescription = m_style->fontDescription();
4831 fontDescription.setTextRenderingMode(m_parentStyle->fontDescription().textRenderingMode());
4833 fontDescription.setTextRenderingMode(AutoTextRendering);
4835 if (!primitiveValue)
4837 fontDescription.setTextRenderingMode(*primitiveValue);
4839 if (m_style->setFontDescription(fontDescription))
4843 case CSSPropertyTextShadow:
4844 case CSSPropertyWebkitBoxShadow: {
4846 if (id == CSSPropertyTextShadow)
4847 return m_style->setTextShadow(m_parentStyle->textShadow() ? new ShadowData(*m_parentStyle->textShadow()) : 0);
4848 return m_style->setBoxShadow(m_parentStyle->boxShadow() ? new ShadowData(*m_parentStyle->boxShadow()) : 0);
4850 if (isInitial || primitiveValue) // initial | none
4851 return id == CSSPropertyTextShadow ? m_style->setTextShadow(0) : m_style->setBoxShadow(0);
4853 if (!value->isValueList())
4856 CSSValueList *list = static_cast<CSSValueList*>(value);
4857 int len = list->length();
4858 for (int i = 0; i < len; i++) {
4859 ShadowValue* item = static_cast<ShadowValue*>(list->itemWithoutBoundsCheck(i));
4860 int x = item->x->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
4861 int y = item->y->computeLengthInt(style(), m_rootElementStyle, zoomFactor);
4862 int blur = item->blur ? item->blur->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
4863 int spread = item->spread ? item->spread->computeLengthInt(style(), m_rootElementStyle, zoomFactor) : 0;
4864 ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
4867 color = getColorFromPrimitiveValue(item->color.get());
4868 ShadowData* shadowData = new ShadowData(x, y, blur, spread, shadowStyle, color.isValid() ? color : Color::transparent);
4869 if (id == CSSPropertyTextShadow)
4870 m_style->setTextShadow(shadowData, i != 0);
4872 m_style->setBoxShadow(shadowData, i != 0);
4876 case CSSPropertyWebkitBoxReflect: {
4877 HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
4878 if (primitiveValue) {
4879 m_style->setBoxReflect(RenderStyle::initialBoxReflect());
4882 CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
4883 RefPtr<StyleReflection> reflection = StyleReflection::create();
4884 reflection->setDirection(reflectValue->direction());
4885 if (reflectValue->offset()) {
4886 int type = reflectValue->offset()->primitiveType();
4887 if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
4888 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
4890 reflection->setOffset(Length(reflectValue->offset()->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed));
4892 NinePieceImage mask;
4893 mapNinePieceImage(reflectValue->mask(), mask);
4894 reflection->setMask(mask);
4896 m_style->setBoxReflect(reflection.release());
4899 case CSSPropertyOpacity:
4900 HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
4901 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4902 return; // Error case.
4903 // Clamp opacity to the range 0-1
4904 m_style->setOpacity(min(1.0f, max(0.0f, primitiveValue->getFloatValue())));
4906 case CSSPropertyWebkitBoxAlign:
4908 HANDLE_INHERIT_AND_INITIAL(boxAlign, BoxAlign)
4909 if (!primitiveValue)
4911 EBoxAlignment boxAlignment = *primitiveValue;
4912 if (boxAlignment != BJUSTIFY)
4913 m_style->setBoxAlign(boxAlignment);
4916 case CSSPropertySrc: // Only used in @font-face rules.
4918 case CSSPropertyUnicodeRange: // Only used in @font-face rules.
4920 case CSSPropertyWebkitBackfaceVisibility:
4921 HANDLE_INHERIT_AND_INITIAL(backfaceVisibility, BackfaceVisibility)
4923 m_style->setBackfaceVisibility((primitiveValue->getIdent() == CSSValueVisible) ? BackfaceVisibilityVisible : BackfaceVisibilityHidden);
4925 case CSSPropertyWebkitBoxDirection:
4926 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
4928 case CSSPropertyWebkitBoxLines:
4929 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
4931 case CSSPropertyWebkitBoxOrient:
4932 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
4934 case CSSPropertyWebkitBoxPack:
4936 HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
4937 if (!primitiveValue)
4939 EBoxAlignment boxPack = *primitiveValue;
4940 if (boxPack != BSTRETCH && boxPack != BBASELINE)
4941 m_style->setBoxPack(boxPack);
4944 case CSSPropertyWebkitBoxFlex:
4945 HANDLE_INHERIT_AND_INITIAL(boxFlex, BoxFlex)
4946 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4947 return; // Error case.
4948 m_style->setBoxFlex(primitiveValue->getFloatValue());
4950 case CSSPropertyWebkitBoxFlexGroup:
4951 HANDLE_INHERIT_AND_INITIAL(boxFlexGroup, BoxFlexGroup)
4952 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4953 return; // Error case.
4954 m_style->setBoxFlexGroup((unsigned int)(primitiveValue->getDoubleValue()));
4956 case CSSPropertyWebkitBoxOrdinalGroup:
4957 HANDLE_INHERIT_AND_INITIAL(boxOrdinalGroup, BoxOrdinalGroup)
4958 if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
4959 return; // Error case.
4960 m_style->setBoxOrdinalGroup((unsigned int)(primitiveValue->getDoubleValue()));
4962 case CSSPropertyWebkitBoxSizing:
4963 HANDLE_INHERIT_AND_INITIAL(boxSizing, BoxSizing)
4964 if (!primitiveValue)
4966 if (primitiveValue->getIdent() == CSSValueContentBox)
4967 m_style->setBoxSizing(CONTENT_BOX);
4969 m_style->setBoxSizing(BORDER_BOX);
4971 case CSSPropertyWebkitColumnCount: {
4973 if (m_parentStyle->hasAutoColumnCount())
4974 m_style->setHasAutoColumnCount();
4976 m_style->setColumnCount(m_parentStyle->columnCount());
4978 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
4979 m_style->setHasAutoColumnCount();
4982 m_style->setColumnCount(static_cast<unsigned short>(primitiveValue->getDoubleValue()));
4985 case CSSPropertyWebkitColumnGap: {
4987 if (m_parentStyle->hasNormalColumnGap())
4988 m_style->setHasNormalColumnGap();
4990 m_style->setColumnGap(m_parentStyle->columnGap());
4992 } else if (isInitial || primitiveValue->getIdent() == CSSValueNormal) {
4993 m_style->setHasNormalColumnGap();
4996 m_style->setColumnGap(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
4999 case CSSPropertyWebkitColumnSpan: {
5000 HANDLE_INHERIT_AND_INITIAL(columnSpan, ColumnSpan)
5001 m_style->setColumnSpan(primitiveValue->getIdent() == CSSValueAll);
5004 case CSSPropertyWebkitColumnWidth: {
5006 if (m_parentStyle->hasAutoColumnWidth())
5007 m_style->setHasAutoColumnWidth();
5009 m_style->setColumnWidth(m_parentStyle->columnWidth());
5011 } else if (isInitial || primitiveValue->getIdent() == CSSValueAuto) {
5012 m_style->setHasAutoColumnWidth();
5015 m_style->setColumnWidth(primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor));
5018 case CSSPropertyWebkitColumnRuleStyle:
5019 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
5021 case CSSPropertyWebkitColumnBreakBefore:
5022 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
5024 case CSSPropertyWebkitColumnBreakAfter:
5025 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
5027 case CSSPropertyWebkitColumnBreakInside: {
5028 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
5029 EPageBreak pb = *primitiveValue;
5031 m_style->setColumnBreakInside(pb);
5034 case CSSPropertyWebkitColumnRule:
5036 m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
5037 m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
5038 m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
5041 m_style->resetColumnRule();
5043 case CSSPropertyWebkitColumns:
5045 if (m_parentStyle->hasAutoColumnWidth())
5046 m_style->setHasAutoColumnWidth();
5048 m_style->setColumnWidth(m_parentStyle->columnWidth());
5049 m_style->setColumnCount(m_parentStyle->columnCount());
5050 } else if (isInitial) {
5051 m_style->setHasAutoColumnWidth();
5052 m_style->setColumnCount(RenderStyle::initialColumnCount());
5055 case CSSPropertyWebkitMarquee:
5056 if (valueType != CSSValue::CSS_INHERIT || !m_parentNode) return;
5057 m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
5058 m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
5059 m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
5060 m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
5061 m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
5064 case CSSPropertyWapMarqueeLoop:
5066 case CSSPropertyWebkitMarqueeRepetition: {
5067 HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
5068 if (!primitiveValue)
5070 if (primitiveValue->getIdent() == CSSValueInfinite)
5071 m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
5072 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
5073 m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
5077 case CSSPropertyWapMarqueeSpeed:
5079 case CSSPropertyWebkitMarqueeSpeed: {
5080 HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
5081 if (!primitiveValue)
5083 if (primitiveValue->getIdent()) {
5084 switch (primitiveValue->getIdent()) {
5086 m_style->setMarqueeSpeed(500); // 500 msec.
5088 case CSSValueNormal:
5089 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
5092 m_style->setMarqueeSpeed(10); // 10msec. Super fast.
5096 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
5097 m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
5098 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
5099 m_style->setMarqueeSpeed(primitiveValue->getIntValue());
5100 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
5101 m_style->setMarqueeSpeed(primitiveValue->getIntValue());
5104 case CSSPropertyWebkitMarqueeIncrement: {
5105 HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
5106 if (!primitiveValue)
5108 if (primitiveValue->getIdent()) {
5109 switch (primitiveValue->getIdent()) {
5111 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
5113 case CSSValueNormal:
5114 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
5117 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
5123 Length l = convertToLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
5125 m_style->setMarqueeIncrement(l);
5130 case CSSPropertyWapMarqueeStyle:
5132 case CSSPropertyWebkitMarqueeStyle:
5133 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
5136 case CSSPropertyWapMarqueeDir:
5137 HANDLE_INHERIT_AND_INITIAL(marqueeDirection, MarqueeDirection)
5138 if (primitiveValue && primitiveValue->getIdent()) {
5139 switch (primitiveValue->getIdent()) {
5141 m_style->setMarqueeDirection(MRIGHT);
5144 m_style->setMarqueeDirection(MLEFT);
5147 m_style->setMarqueeDirection(*primitiveValue);
5153 case CSSPropertyWebkitMarqueeDirection:
5154 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
5156 case CSSPropertyWebkitUserDrag:
5157 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
5159 case CSSPropertyWebkitUserModify:
5160 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
5162 case CSSPropertyWebkitUserSelect:
5163 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
5166 case CSSPropertyTextOverflow: {
5167 // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
5168 // work with WinIE-specific pages that use the property.
5169 HANDLE_INHERIT_AND_INITIAL(textOverflow, TextOverflow)
5170 if (!primitiveValue || !primitiveValue->getIdent())
5172 m_style->setTextOverflow(primitiveValue->getIdent() == CSSValueEllipsis);
5175 case CSSPropertyWebkitMarginCollapse: {
5177 m_style->setMarginTopCollapse(m_parentStyle->marginTopCollapse());
5178 m_style->setMarginBottomCollapse(m_parentStyle->marginBottomCollapse());
5180 else if (isInitial) {
5181 m_style->setMarginTopCollapse(MCOLLAPSE);
5182 m_style->setMarginBottomCollapse(MCOLLAPSE);
5187 case CSSPropertyWebkitMarginTopCollapse:
5188 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginTopCollapse, MarginTopCollapse)
5190 case CSSPropertyWebkitMarginBottomCollapse:
5191 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marginBottomCollapse, MarginBottomCollapse)
5193 case CSSPropertyWebkitLineClamp: {
5194 HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
5195 if (!primitiveValue)
5197 int type = primitiveValue->primitiveType();
5198 if (type == CSSPrimitiveValue::CSS_NUMBER)
5199 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
5200 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5201 m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
5204 case CSSPropertyWebkitHighlight: {
5205 HANDLE_INHERIT_AND_INITIAL(highlight, Highlight);
5206 if (primitiveValue->getIdent() == CSSValueNone)
5207 m_style->setHighlight(nullAtom);
5209 m_style->setHighlight(primitiveValue->getStringValue());
5212 case CSSPropertyWebkitHyphens: {
5213 HANDLE_INHERIT_AND_INITIAL(hyphens, Hyphens);
5214 m_style->setHyphens(*primitiveValue);
5217 case CSSPropertyWebkitHyphenateCharacter: {
5218 HANDLE_INHERIT_AND_INITIAL(hyphenationString, HyphenationString);
5219 if (primitiveValue->getIdent() == CSSValueAuto)
5220 m_style->setHyphenationString(nullAtom);
5222 m_style->setHyphenationString(primitiveValue->getStringValue());
5225 case CSSPropertyWebkitHyphenateLocale: {
5226 HANDLE_INHERIT_AND_INITIAL(hyphenationLocale, HyphenationLocale);
5227 if (primitiveValue->getIdent() == CSSValueAuto)
5228 m_style->setHyphenationLocale(nullAtom);
5230 m_style->setHyphenationLocale(primitiveValue->getStringValue());
5233 case CSSPropertyWebkitBorderFit: {
5234 HANDLE_INHERIT_AND_INITIAL(borderFit, BorderFit);
5235 if (primitiveValue->getIdent() == CSSValueBorder)
5236 m_style->setBorderFit(BorderFitBorder);
5238 m_style->setBorderFit(BorderFitLines);
5241 case CSSPropertyWebkitTextSizeAdjust: {
5242 HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
5243 if (!primitiveValue || !primitiveValue->getIdent()) return;
5244 m_style->setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
5248 case CSSPropertyWebkitTextSecurity:
5249 HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
5252 #if ENABLE(DASHBOARD_SUPPORT)
5253 case CSSPropertyWebkitDashboardRegion: {
5254 HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
5255 if (!primitiveValue)
5258 if (primitiveValue->getIdent() == CSSValueNone) {
5259 m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
5263 DashboardRegion *region = primitiveValue->getDashboardRegionValue();
5267 DashboardRegion *first = region;
5269 Length top = convertToLength(region->top(), style(), m_rootElementStyle);
5270 Length right = convertToLength(region->right(), style(), m_rootElementStyle);
5271 Length bottom = convertToLength(region->bottom(), style(), m_rootElementStyle);
5272 Length left = convertToLength(region->left(), style(), m_rootElementStyle);
5273 if (region->m_isCircle)
5274 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
5275 else if (region->m_isRectangle)
5276 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
5277 region = region->m_next.get();
5280 m_element->document()->setHasDashboardRegions(true);
5285 case CSSPropertyWebkitRtlOrdering:
5286 HANDLE_INHERIT_AND_INITIAL(visuallyOrdered, VisuallyOrdered)
5287 if (!primitiveValue || !primitiveValue->getIdent())
5289 m_style->setVisuallyOrdered(primitiveValue->getIdent() == CSSValueVisual);
5291 case CSSPropertyWebkitTextStrokeWidth: {
5292 HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
5294 switch (primitiveValue->getIdent()) {
5296 case CSSValueMedium:
5297 case CSSValueThick: {
5298 double result = 1.0 / 48;
5299 if (primitiveValue->getIdent() == CSSValueMedium)
5301 else if (primitiveValue->getIdent() == CSSValueThick)
5303 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5307 width = primitiveValue->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5310 m_style->setTextStrokeWidth(width);
5313 case CSSPropertyWebkitTransform: {
5314 HANDLE_INHERIT_AND_INITIAL(transform, Transform);
5315 TransformOperations operations;
5316 createTransformOperations(value, style(), m_rootElementStyle, operations);
5317 m_style->setTransform(operations);
5320 case CSSPropertyWebkitTransformOrigin:
5321 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
5322 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
5323 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
5325 case CSSPropertyWebkitTransformOriginX: {
5326 HANDLE_INHERIT_AND_INITIAL(transformOriginX, TransformOriginX)
5327 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5329 int type = primitiveValue->primitiveType();
5330 if (CSSPrimitiveValue::isUnitTypeLength(type))
5331 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5332 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5333 l = Length(primitiveValue->getDoubleValue(), Percent);
5336 m_style->setTransformOriginX(l);
5339 case CSSPropertyWebkitTransformOriginY: {
5340 HANDLE_INHERIT_AND_INITIAL(transformOriginY, TransformOriginY)
5341 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5343 int type = primitiveValue->primitiveType();
5344 if (CSSPrimitiveValue::isUnitTypeLength(type))
5345 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5346 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5347 l = Length(primitiveValue->getDoubleValue(), Percent);
5350 m_style->setTransformOriginY(l);
5353 case CSSPropertyWebkitTransformOriginZ: {
5354 HANDLE_INHERIT_AND_INITIAL(transformOriginZ, TransformOriginZ)
5355 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5357 int type = primitiveValue->primitiveType();
5358 if (CSSPrimitiveValue::isUnitTypeLength(type))
5359 f = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle));
5362 m_style->setTransformOriginZ(f);
5365 case CSSPropertyWebkitTransformStyle:
5366 HANDLE_INHERIT_AND_INITIAL(transformStyle3D, TransformStyle3D)
5368 m_style->setTransformStyle3D((primitiveValue->getIdent() == CSSValuePreserve3d) ? TransformStyle3DPreserve3D : TransformStyle3DFlat);
5370 case CSSPropertyWebkitPerspective: {
5371 HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
5372 if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
5373 m_style->setPerspective(0);
5377 float perspectiveValue;
5378 int type = primitiveValue->primitiveType();
5379 if (CSSPrimitiveValue::isUnitTypeLength(type))
5380 perspectiveValue = static_cast<float>(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor));
5381 else if (type == CSSPrimitiveValue::CSS_NUMBER) {
5382 // For backward compatibility, treat valueless numbers as px.
5383 perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLengthFloat(style(), m_rootElementStyle, zoomFactor);
5387 if (perspectiveValue >= 0.0f)
5388 m_style->setPerspective(perspectiveValue);
5391 case CSSPropertyWebkitPerspectiveOrigin:
5392 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
5393 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
5395 case CSSPropertyWebkitPerspectiveOriginX: {
5396 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginX, PerspectiveOriginX)
5397 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5399 int type = primitiveValue->primitiveType();
5400 if (CSSPrimitiveValue::isUnitTypeLength(type))
5401 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5402 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5403 l = Length(primitiveValue->getDoubleValue(), Percent);
5406 m_style->setPerspectiveOriginX(l);
5409 case CSSPropertyWebkitPerspectiveOriginY: {
5410 HANDLE_INHERIT_AND_INITIAL(perspectiveOriginY, PerspectiveOriginY)
5411 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5413 int type = primitiveValue->primitiveType();
5414 if (CSSPrimitiveValue::isUnitTypeLength(type))
5415 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5416 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5417 l = Length(primitiveValue->getDoubleValue(), Percent);
5420 m_style->setPerspectiveOriginY(l);
5423 case CSSPropertyWebkitAnimation:
5425 m_style->clearAnimations();
5427 m_style->inheritAnimations(m_parentStyle->animations());
5429 case CSSPropertyWebkitAnimationDelay:
5430 HANDLE_ANIMATION_VALUE(delay, Delay, value)
5432 case CSSPropertyWebkitAnimationDirection:
5433 HANDLE_ANIMATION_VALUE(direction, Direction, value)
5435 case CSSPropertyWebkitAnimationDuration:
5436 HANDLE_ANIMATION_VALUE(duration, Duration, value)
5438 case CSSPropertyWebkitAnimationFillMode:
5439 HANDLE_ANIMATION_VALUE(fillMode, FillMode, value)
5441 case CSSPropertyWebkitAnimationIterationCount:
5442 HANDLE_ANIMATION_VALUE(iterationCount, IterationCount, value)
5444 case CSSPropertyWebkitAnimationName:
5445 HANDLE_ANIMATION_VALUE(name, Name, value)
5447 case CSSPropertyWebkitAnimationPlayState:
5448 HANDLE_ANIMATION_VALUE(playState, PlayState, value)
5450 case CSSPropertyWebkitAnimationTimingFunction:
5451 HANDLE_ANIMATION_VALUE(timingFunction, TimingFunction, value)
5453 case CSSPropertyWebkitTransition:
5455 m_style->clearTransitions();
5457 m_style->inheritTransitions(m_parentStyle->transitions());
5459 case CSSPropertyWebkitTransitionDelay:
5460 HANDLE_TRANSITION_VALUE(delay, Delay, value)
5462 case CSSPropertyWebkitTransitionDuration:
5463 HANDLE_TRANSITION_VALUE(duration, Duration, value)
5465 case CSSPropertyWebkitTransitionProperty:
5466 HANDLE_TRANSITION_VALUE(property, Property, value)
5468 case CSSPropertyWebkitTransitionTimingFunction:
5469 HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value)
5471 case CSSPropertyPointerEvents:
5473 #if ENABLE(DASHBOARD_SUPPORT)
5474 // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
5475 // pointer-events property by not applying it in Dashboard.
5476 Settings* settings = m_checker.m_document->settings();
5477 if (settings && settings->usesDashboardBackwardCompatibilityMode())
5480 HANDLE_INHERIT_AND_INITIAL(pointerEvents, PointerEvents)
5481 if (!primitiveValue)
5483 m_style->setPointerEvents(*primitiveValue);
5486 case CSSPropertyWebkitColorCorrection:
5488 m_style->setColorSpace(m_parentStyle->colorSpace());
5490 m_style->setColorSpace(DeviceColorSpace);
5492 if (!primitiveValue)
5494 m_style->setColorSpace(*primitiveValue);
5497 case CSSPropertySize:
5498 applyPageSizeProperty(value);
5500 case CSSPropertyInvalid:
5503 // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
5504 case CSSPropertyWebkitBorderEnd:
5505 case CSSPropertyWebkitBorderEndColor:
5506 case CSSPropertyWebkitBorderEndStyle:
5507 case CSSPropertyWebkitBorderEndWidth:
5508 case CSSPropertyWebkitBorderStart:
5509 case CSSPropertyWebkitBorderStartColor:
5510 case CSSPropertyWebkitBorderStartStyle:
5511 case CSSPropertyWebkitBorderStartWidth:
5512 case CSSPropertyWebkitMarginEnd:
5513 case CSSPropertyWebkitMarginStart:
5514 case CSSPropertyWebkitPaddingEnd:
5515 case CSSPropertyWebkitPaddingStart:
5516 ASSERT_NOT_REACHED();
5519 case CSSPropertyFontStretch:
5520 case CSSPropertyPage:
5521 case CSSPropertyQuotes:
5522 case CSSPropertyTextLineThrough:
5523 case CSSPropertyTextLineThroughColor:
5524 case CSSPropertyTextLineThroughMode:
5525 case CSSPropertyTextLineThroughStyle:
5526 case CSSPropertyTextLineThroughWidth:
5527 case CSSPropertyTextOverline:
5528 case CSSPropertyTextOverlineColor:
5529 case CSSPropertyTextOverlineMode:
5530 case CSSPropertyTextOverlineStyle:
5531 case CSSPropertyTextOverlineWidth:
5532 case CSSPropertyTextUnderline:
5533 case CSSPropertyTextUnderlineColor:
5534 case CSSPropertyTextUnderlineMode:
5535 case CSSPropertyTextUnderlineStyle:
5536 case CSSPropertyTextUnderlineWidth:
5537 case CSSPropertyWebkitFontSizeDelta:
5538 case CSSPropertyWebkitTextDecorationsInEffect:
5539 case CSSPropertyWebkitTextStroke:
5540 case CSSPropertyWebkitVariableDeclarationBlock:
5543 case CSSPropertyWapInputFormat:
5544 if (primitiveValue && m_element->hasTagName(WebCore::inputTag)) {
5545 String mask = primitiveValue->getStringValue();
5546 static_cast<HTMLInputElement*>(m_element)->setWapInputFormat(mask);
5550 case CSSPropertyWapInputRequired:
5551 if (primitiveValue && m_element->isFormControlElement()) {
5552 HTMLFormControlElement* element = static_cast<HTMLFormControlElement*>(m_element);
5553 bool required = primitiveValue->getStringValue() == "true";
5554 element->setRequired(required);
5559 #ifdef ANDROID_CSS_TAP_HIGHLIGHT_COLOR
5560 case CSSPropertyWebkitTapHighlightColor: {
5561 HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
5562 if (!primitiveValue)
5565 Color col = getColorFromPrimitiveValue(primitiveValue).blendWithWhite();
5566 m_style->setTapHighlightColor(col);
5573 // Try the SVG properties
5574 applySVGProperty(id, value);
5579 void CSSStyleSelector::applyPageSizeProperty(CSSValue* value)
5581 m_style->resetPageSizeType();
5582 if (!value->isValueList())
5584 CSSValueList* valueList = static_cast<CSSValueList*>(value);
5587 PageSizeType pageSizeType = PAGE_SIZE_AUTO;
5588 switch (valueList->length()) {
5590 // <length>{2} | <page-size> <orientation>
5591 pageSizeType = PAGE_SIZE_RESOLVED;
5592 if (!valueList->item(0)->isPrimitiveValue() || !valueList->item(1)->isPrimitiveValue())
5594 CSSPrimitiveValue* primitiveValue0 = static_cast<CSSPrimitiveValue*>(valueList->item(0));
5595 CSSPrimitiveValue* primitiveValue1 = static_cast<CSSPrimitiveValue*>(valueList->item(1));
5596 int type0 = primitiveValue0->primitiveType();
5597 int type1 = primitiveValue1->primitiveType();
5598 if (CSSPrimitiveValue::isUnitTypeLength(type0)) {
5600 if (!CSSPrimitiveValue::isUnitTypeLength(type1))
5602 width = Length(primitiveValue0->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
5603 height = Length(primitiveValue1->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
5605 // <page-size> <orientation>
5606 // The value order is guaranteed. See CSSParser::parseSizeParameter.
5607 if (!pageSizeFromName(primitiveValue0, primitiveValue1, width, height))
5613 // <length> | auto | <page-size> | [ portrait | landscape]
5614 if (!valueList->item(0)->isPrimitiveValue())
5616 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(valueList->item(0));
5617 int type = primitiveValue->primitiveType();
5618 if (CSSPrimitiveValue::isUnitTypeLength(type)) {
5620 pageSizeType = PAGE_SIZE_RESOLVED;
5621 width = height = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
5623 if (type != CSSPrimitiveValue::CSS_IDENT)
5625 switch (primitiveValue->getIdent()) {
5627 pageSizeType = PAGE_SIZE_AUTO;
5629 case CSSValuePortrait:
5630 pageSizeType = PAGE_SIZE_AUTO_PORTRAIT;
5632 case CSSValueLandscape:
5633 pageSizeType = PAGE_SIZE_AUTO_LANDSCAPE;
5637 pageSizeType = PAGE_SIZE_RESOLVED;
5638 if (!pageSizeFromName(primitiveValue, 0, width, height))
5647 m_style->setPageSizeType(pageSizeType);
5648 m_style->setPageSize(LengthSize(width, height));
5652 bool CSSStyleSelector::pageSizeFromName(CSSPrimitiveValue* pageSizeName, CSSPrimitiveValue* pageOrientation, Length& width, Length& height)
5654 static const Length a5Width = mmLength(148), a5Height = mmLength(210);
5655 static const Length a4Width = mmLength(210), a4Height = mmLength(297);
5656 static const Length a3Width = mmLength(297), a3Height = mmLength(420);
5657 static const Length b5Width = mmLength(176), b5Height = mmLength(250);
5658 static const Length b4Width = mmLength(250), b4Height = mmLength(353);
5659 static const Length letterWidth = inchLength(8.5), letterHeight = inchLength(11);
5660 static const Length legalWidth = inchLength(8.5), legalHeight = inchLength(14);
5661 static const Length ledgerWidth = inchLength(11), ledgerHeight = inchLength(17);
5663 if (!pageSizeName || pageSizeName->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
5666 switch (pageSizeName->getIdent()) {
5687 case CSSValueLetter:
5688 width = letterWidth;
5689 height = letterHeight;
5693 height = legalHeight;
5695 case CSSValueLedger:
5696 width = ledgerWidth;
5697 height = ledgerHeight;
5703 if (pageOrientation) {
5704 if (pageOrientation->primitiveType() != CSSPrimitiveValue::CSS_IDENT)
5706 switch (pageOrientation->getIdent()) {
5707 case CSSValueLandscape:
5708 std::swap(width, height);
5710 case CSSValuePortrait:
5720 Length CSSStyleSelector::mmLength(double mm)
5722 return Length(CSSPrimitiveValue::create(mm, CSSPrimitiveValue::CSS_MM)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
5725 Length CSSStyleSelector::inchLength(double inch)
5727 return Length(CSSPrimitiveValue::create(inch, CSSPrimitiveValue::CSS_IN)->computeLengthIntForLength(style(), m_rootElementStyle), Fixed);
5730 void CSSStyleSelector::mapFillAttachment(FillLayer* layer, CSSValue* value)
5732 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5733 layer->setAttachment(FillLayer::initialFillAttachment(layer->type()));
5737 if (!value->isPrimitiveValue())
5740 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5741 switch (primitiveValue->getIdent()) {
5743 layer->setAttachment(FixedBackgroundAttachment);
5745 case CSSValueScroll:
5746 layer->setAttachment(ScrollBackgroundAttachment);
5749 layer->setAttachment(LocalBackgroundAttachment);
5756 void CSSStyleSelector::mapFillClip(FillLayer* layer, CSSValue* value)
5758 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5759 layer->setClip(FillLayer::initialFillClip(layer->type()));
5763 if (!value->isPrimitiveValue())
5766 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5767 layer->setClip(*primitiveValue);
5770 void CSSStyleSelector::mapFillComposite(FillLayer* layer, CSSValue* value)
5772 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5773 layer->setComposite(FillLayer::initialFillComposite(layer->type()));
5777 if (!value->isPrimitiveValue())
5780 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5781 layer->setComposite(*primitiveValue);
5784 void CSSStyleSelector::mapFillOrigin(FillLayer* layer, CSSValue* value)
5786 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5787 layer->setOrigin(FillLayer::initialFillOrigin(layer->type()));
5791 if (!value->isPrimitiveValue())
5794 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5795 layer->setOrigin(*primitiveValue);
5798 StyleImage* CSSStyleSelector::styleImage(CSSValue* value)
5800 if (value->isImageValue())
5801 return static_cast<CSSImageValue*>(value)->cachedImage(m_element->document()->docLoader());
5802 if (value->isImageGeneratorValue())
5803 return static_cast<CSSImageGeneratorValue*>(value)->generatedImage();
5807 void CSSStyleSelector::mapFillImage(FillLayer* layer, CSSValue* value)
5809 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5810 layer->setImage(FillLayer::initialFillImage(layer->type()));
5814 layer->setImage(styleImage(value));
5817 void CSSStyleSelector::mapFillRepeatX(FillLayer* layer, CSSValue* value)
5819 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5820 layer->setRepeatX(FillLayer::initialFillRepeatX(layer->type()));
5824 if (!value->isPrimitiveValue())
5827 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5828 layer->setRepeatX(*primitiveValue);
5831 void CSSStyleSelector::mapFillRepeatY(FillLayer* layer, CSSValue* value)
5833 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5834 layer->setRepeatY(FillLayer::initialFillRepeatY(layer->type()));
5838 if (!value->isPrimitiveValue())
5841 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5842 layer->setRepeatY(*primitiveValue);
5845 void CSSStyleSelector::mapFillSize(FillLayer* layer, CSSValue* value)
5847 if (!value->isPrimitiveValue()) {
5848 layer->setSizeType(SizeNone);
5852 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5853 if (primitiveValue->getIdent() == CSSValueContain)
5854 layer->setSizeType(Contain);
5855 else if (primitiveValue->getIdent() == CSSValueCover)
5856 layer->setSizeType(Cover);
5858 layer->setSizeType(SizeLength);
5860 LengthSize b = FillLayer::initialFillSizeLength(layer->type());
5862 if (value->cssValueType() == CSSValue::CSS_INITIAL || primitiveValue->getIdent() == CSSValueContain
5863 || primitiveValue->getIdent() == CSSValueCover) {
5864 layer->setSizeLength(b);
5868 Pair* pair = primitiveValue->getPairValue();
5872 CSSPrimitiveValue* first = static_cast<CSSPrimitiveValue*>(pair->first());
5873 CSSPrimitiveValue* second = static_cast<CSSPrimitiveValue*>(pair->second());
5875 if (!first || !second)
5878 Length firstLength, secondLength;
5879 int firstType = first->primitiveType();
5880 int secondType = second->primitiveType();
5882 float zoomFactor = m_style->effectiveZoom();
5884 if (firstType == CSSPrimitiveValue::CSS_UNKNOWN)
5885 firstLength = Length(Auto);
5886 else if (CSSPrimitiveValue::isUnitTypeLength(firstType))
5887 firstLength = Length(first->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5888 else if (firstType == CSSPrimitiveValue::CSS_PERCENTAGE)
5889 firstLength = Length(first->getDoubleValue(), Percent);
5893 if (secondType == CSSPrimitiveValue::CSS_UNKNOWN)
5894 secondLength = Length(Auto);
5895 else if (CSSPrimitiveValue::isUnitTypeLength(secondType))
5896 secondLength = Length(second->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5897 else if (secondType == CSSPrimitiveValue::CSS_PERCENTAGE)
5898 secondLength = Length(second->getDoubleValue(), Percent);
5902 b.setWidth(firstLength);
5903 b.setHeight(secondLength);
5904 layer->setSizeLength(b);
5907 void CSSStyleSelector::mapFillXPosition(FillLayer* layer, CSSValue* value)
5909 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5910 layer->setXPosition(FillLayer::initialFillXPosition(layer->type()));
5914 if (!value->isPrimitiveValue())
5917 float zoomFactor = m_style->effectiveZoom();
5919 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5921 int type = primitiveValue->primitiveType();
5922 if (CSSPrimitiveValue::isUnitTypeLength(type))
5923 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5924 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5925 l = Length(primitiveValue->getDoubleValue(), Percent);
5928 layer->setXPosition(l);
5931 void CSSStyleSelector::mapFillYPosition(FillLayer* layer, CSSValue* value)
5933 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5934 layer->setYPosition(FillLayer::initialFillYPosition(layer->type()));
5938 if (!value->isPrimitiveValue())
5941 float zoomFactor = m_style->effectiveZoom();
5943 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5945 int type = primitiveValue->primitiveType();
5946 if (CSSPrimitiveValue::isUnitTypeLength(type))
5947 l = Length(primitiveValue->computeLengthIntForLength(style(), m_rootElementStyle, zoomFactor), Fixed);
5948 else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
5949 l = Length(primitiveValue->getDoubleValue(), Percent);
5952 layer->setYPosition(l);
5955 void CSSStyleSelector::mapAnimationDelay(Animation* animation, CSSValue* value)
5957 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5958 animation->setDelay(Animation::initialAnimationDelay());
5962 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5963 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
5964 animation->setDelay(primitiveValue->getFloatValue());
5966 animation->setDelay(primitiveValue->getFloatValue()/1000.0f);
5969 void CSSStyleSelector::mapAnimationDirection(Animation* layer, CSSValue* value)
5971 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5972 layer->setDirection(Animation::initialAnimationDirection());
5976 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5977 layer->setDirection(primitiveValue->getIdent() == CSSValueAlternate ? Animation::AnimationDirectionAlternate : Animation::AnimationDirectionNormal);
5980 void CSSStyleSelector::mapAnimationDuration(Animation* animation, CSSValue* value)
5982 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5983 animation->setDuration(Animation::initialAnimationDuration());
5987 if (!value->isPrimitiveValue())
5990 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5991 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
5992 animation->setDuration(primitiveValue->getFloatValue());
5993 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
5994 animation->setDuration(primitiveValue->getFloatValue()/1000.0f);
5997 void CSSStyleSelector::mapAnimationFillMode(Animation* layer, CSSValue* value)
5999 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6000 layer->setFillMode(Animation::initialAnimationFillMode());
6004 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6005 switch (primitiveValue->getIdent()) {
6007 layer->setFillMode(AnimationFillModeNone);
6009 case CSSValueForwards:
6010 layer->setFillMode(AnimationFillModeForwards);
6012 case CSSValueBackwards:
6013 layer->setFillMode(AnimationFillModeBackwards);
6016 layer->setFillMode(AnimationFillModeBoth);
6021 void CSSStyleSelector::mapAnimationIterationCount(Animation* animation, CSSValue* value)
6023 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6024 animation->setIterationCount(Animation::initialAnimationIterationCount());
6028 if (!value->isPrimitiveValue())
6031 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6032 if (primitiveValue->getIdent() == CSSValueInfinite)
6033 animation->setIterationCount(-1);
6035 animation->setIterationCount(int(primitiveValue->getFloatValue()));
6038 void CSSStyleSelector::mapAnimationName(Animation* layer, CSSValue* value)
6040 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6041 layer->setName(Animation::initialAnimationName());
6045 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6047 if (primitiveValue->getIdent() == CSSValueNone)
6048 layer->setIsNoneAnimation(true);
6050 layer->setName(primitiveValue->getStringValue());
6053 void CSSStyleSelector::mapAnimationPlayState(Animation* layer, CSSValue* value)
6055 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6056 layer->setPlayState(Animation::initialAnimationPlayState());
6060 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6061 EAnimPlayState playState = (primitiveValue->getIdent() == CSSValuePaused) ? AnimPlayStatePaused : AnimPlayStatePlaying;
6062 layer->setPlayState(playState);
6065 void CSSStyleSelector::mapAnimationProperty(Animation* animation, CSSValue* value)
6067 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6068 animation->setProperty(Animation::initialAnimationProperty());
6072 if (!value->isPrimitiveValue())
6075 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6076 if (primitiveValue->getIdent() == CSSValueAll)
6077 animation->setProperty(cAnimateAll);
6078 else if (primitiveValue->getIdent() == CSSValueNone)
6079 animation->setProperty(cAnimateNone);
6081 animation->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
6084 void CSSStyleSelector::mapAnimationTimingFunction(Animation* animation, CSSValue* value)
6086 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
6087 animation->setTimingFunction(Animation::initialAnimationTimingFunction());
6091 if (value->isPrimitiveValue()) {
6092 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
6093 switch (primitiveValue->getIdent()) {
6094 case CSSValueLinear:
6095 animation->setTimingFunction(TimingFunction(LinearTimingFunction, 0.0, 0.0, 1.0, 1.0));
6098 animation->setTimingFunction(TimingFunction());
6100 case CSSValueEaseIn:
6101 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 1.0, 1.0));
6103 case CSSValueEaseOut:
6104 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.0, 0.0, 0.58, 1.0));
6106 case CSSValueEaseInOut:
6107 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, 0.42, 0.0, 0.58, 1.0));
6113 if (value->isTimingFunctionValue()) {
6114 CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
6115 animation->setTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2()));
6119 void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image)
6121 // If we're a primitive value, then we are "none" and don't need to alter the empty image at all.
6122 if (!value || value->isPrimitiveValue())
6125 // Retrieve the border image value.
6126 CSSBorderImageValue* borderImage = static_cast<CSSBorderImageValue*>(value);
6128 // Set the image (this kicks off the load).
6129 image.setImage(styleImage(borderImage->imageValue()));
6131 // Set up a length box to represent our image slices.
6133 Rect* r = borderImage->m_imageSliceRect.get();
6134 if (r->top()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6135 l.m_top = Length(r->top()->getDoubleValue(), Percent);
6137 l.m_top = Length(r->top()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6138 if (r->bottom()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6139 l.m_bottom = Length(r->bottom()->getDoubleValue(), Percent);
6141 l.m_bottom = Length((int)r->bottom()->getFloatValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6142 if (r->left()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6143 l.m_left = Length(r->left()->getDoubleValue(), Percent);
6145 l.m_left = Length(r->left()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6146 if (r->right()->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
6147 l.m_right = Length(r->right()->getDoubleValue(), Percent);
6149 l.m_right = Length(r->right()->getIntValue(CSSPrimitiveValue::CSS_NUMBER), Fixed);
6152 // Set the appropriate rules for stretch/round/repeat of the slices
6153 ENinePieceImageRule horizontalRule;
6154 switch (borderImage->m_horizontalSizeRule) {
6155 case CSSValueStretch:
6156 horizontalRule = StretchImageRule;
6159 horizontalRule = RoundImageRule;
6161 default: // CSSValueRepeat
6162 horizontalRule = RepeatImageRule;
6165 image.setHorizontalRule(horizontalRule);
6167 ENinePieceImageRule verticalRule;
6168 switch (borderImage->m_verticalSizeRule) {
6169 case CSSValueStretch:
6170 verticalRule = StretchImageRule;
6173 verticalRule = RoundImageRule;
6175 default: // CSSValueRepeat
6176 verticalRule = RepeatImageRule;
6179 image.setVerticalRule(verticalRule);
6182 void CSSStyleSelector::checkForTextSizeAdjust()
6184 if (m_style->textSizeAdjust())
6187 FontDescription newFontDescription(m_style->fontDescription());
6188 newFontDescription.setComputedSize(newFontDescription.specifiedSize());
6189 m_style->setFontDescription(newFontDescription);
6192 void CSSStyleSelector::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
6194 if (style->effectiveZoom() == parentStyle->effectiveZoom())
6197 const FontDescription& childFont = style->fontDescription();
6198 FontDescription newFontDescription(childFont);
6199 setFontSize(newFontDescription, childFont.specifiedSize());
6200 style->setFontDescription(newFontDescription);
6203 void CSSStyleSelector::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
6205 const FontDescription& childFont = style->fontDescription();
6207 if (childFont.isAbsoluteSize() || !parentStyle)
6210 const FontDescription& parentFont = parentStyle->fontDescription();
6211 if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
6214 // For now, lump all families but monospace together.
6215 if (childFont.genericFamily() != FontDescription::MonospaceFamily &&
6216 parentFont.genericFamily() != FontDescription::MonospaceFamily)
6219 // We know the parent is monospace or the child is monospace, and that font
6220 // size was unspecified. We want to scale our font size as appropriate.
6221 // If the font uses a keyword size, then we refetch from the table rather than
6222 // multiplying by our scale factor.
6224 if (childFont.keywordSize())
6225 size = fontSizeForKeyword(m_checker.m_document, CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize());
6227 Settings* settings = m_checker.m_document->settings();
6228 float fixedScaleFactor = settings
6229 ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
6231 size = parentFont.useFixedDefaultSize() ?
6232 childFont.specifiedSize() / fixedScaleFactor :
6233 childFont.specifiedSize() * fixedScaleFactor;
6236 FontDescription newFontDescription(childFont);
6237 setFontSize(newFontDescription, size);
6238 style->setFontDescription(newFontDescription);
6241 void CSSStyleSelector::setFontSize(FontDescription& fontDescription, float size)
6243 fontDescription.setSpecifiedSize(size);
6245 bool useSVGZoomRules = m_element && m_element->isSVGElement();
6246 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.m_document, m_style.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
6249 float CSSStyleSelector::getComputedSizeFromSpecifiedSize(Document* document, RenderStyle* style, bool isAbsoluteSize, float specifiedSize, bool useSVGZoomRules)
6251 float zoomFactor = 1.0f;
6252 if (!useSVGZoomRules) {
6253 zoomFactor = style->effectiveZoom();
6254 if (document->view() && document->view()->shouldApplyTextZoom())
6255 zoomFactor *= document->view()->textZoomFactor();
6258 // We support two types of minimum font size. The first is a hard override that applies to
6259 // all fonts. This is "minSize." The second type of minimum font size is a "smart minimum"
6260 // that is applied only when the Web page can't know what size it really asked for, e.g.,
6261 // when it uses logical sizes like "small" or expresses the font-size as a percentage of
6262 // the user's default font setting.
6264 // With the smart minimum, we never want to get smaller than the minimum font size to keep fonts readable.
6265 // However we always allow the page to set an explicit pixel size that is smaller,
6266 // since sites will mis-render otherwise (e.g., http://www.gamespot.com with a 9px minimum).
6268 Settings* settings = document->settings();
6272 int minSize = settings->minimumFontSize();
6273 int minLogicalSize = settings->minimumLogicalFontSize();
6274 float zoomedSize = specifiedSize * zoomFactor;
6276 // Apply the hard minimum first. We only apply the hard minimum if after zooming we're still too small.
6277 if (zoomedSize < minSize)
6278 zoomedSize = minSize;
6280 // Now apply the "smart minimum." This minimum is also only applied if we're still too small
6281 // after zooming. The font size must either be relative to the user default or the original size
6282 // must have been acceptable. In other words, we only apply the smart minimum whenever we're positive
6283 // doing so won't disrupt the layout.
6284 if (zoomedSize < minLogicalSize && (specifiedSize >= minLogicalSize || !isAbsoluteSize))
6285 zoomedSize = minLogicalSize;
6287 // Also clamp to a reasonable maximum to prevent insane font sizes from causing crashes on various
6288 // platforms (I'm looking at you, Windows.)
6289 return min(1000000.0f, max(zoomedSize, 1.0f));
6292 const int fontSizeTableMax = 16;
6293 const int fontSizeTableMin = 9;
6294 const int totalKeywords = 8;
6296 // WinIE/Nav4 table for font sizes. Designed to match the legacy font mapping system of HTML.
6297 static const int quirksFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
6299 { 9, 9, 9, 9, 11, 14, 18, 28 },
6300 { 9, 9, 9, 10, 12, 15, 20, 31 },
6301 { 9, 9, 9, 11, 13, 17, 22, 34 },
6302 { 9, 9, 10, 12, 14, 18, 24, 37 },
6303 { 9, 9, 10, 13, 16, 20, 26, 40 }, // fixed font default (13)
6304 { 9, 9, 11, 14, 17, 21, 28, 42 },
6305 { 9, 10, 12, 15, 17, 23, 30, 45 },
6306 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
6308 // HTML 1 2 3 4 5 6 7
6309 // CSS xxs xs s m l xl xxl
6313 // Strict mode table matches MacIE and Mozilla's settings exactly.
6314 static const int strictFontSizeTable[fontSizeTableMax - fontSizeTableMin + 1][totalKeywords] =
6316 { 9, 9, 9, 9, 11, 14, 18, 27 },
6317 { 9, 9, 9, 10, 12, 15, 20, 30 },
6318 { 9, 9, 10, 11, 13, 17, 22, 33 },
6319 { 9, 9, 10, 12, 14, 18, 24, 36 },
6320 { 9, 10, 12, 13, 16, 20, 26, 39 }, // fixed font default (13)
6321 { 9, 10, 12, 14, 17, 21, 28, 42 },
6322 { 9, 10, 13, 15, 18, 23, 30, 45 },
6323 { 9, 10, 13, 16, 18, 24, 32, 48 } // proportional font default (16)
6325 // HTML 1 2 3 4 5 6 7
6326 // CSS xxs xs s m l xl xxl
6330 // For values outside the range of the table, we use Todd Fahrner's suggested scale
6331 // factors for each keyword value.
6332 static const float fontSizeFactors[totalKeywords] = { 0.60f, 0.75f, 0.89f, 1.0f, 1.2f, 1.5f, 2.0f, 3.0f };
6334 float CSSStyleSelector::fontSizeForKeyword(Document* document, int keyword, bool fixed)
6336 Settings* settings = document->settings();
6340 bool quirksMode = document->inCompatMode();
6341 int mediumSize = fixed ? settings->defaultFixedFontSize() : settings->defaultFontSize();
6342 if (mediumSize >= fontSizeTableMin && mediumSize <= fontSizeTableMax) {
6343 // Look up the entry in the table.
6344 int row = mediumSize - fontSizeTableMin;
6345 int col = (keyword - CSSValueXxSmall);
6346 return quirksMode ? quirksFontSizeTable[row][col] : strictFontSizeTable[row][col];
6349 // Value is outside the range of the table. Apply the scale factor instead.
6350 float minLogicalSize = max(settings->minimumLogicalFontSize(), 1);
6351 return max(fontSizeFactors[keyword - CSSValueXxSmall]*mediumSize, minLogicalSize);
6354 float CSSStyleSelector::largerFontSize(float size, bool) const
6356 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale up to
6357 // the next size level.
6361 float CSSStyleSelector::smallerFontSize(float size, bool) const
6363 // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
6364 // the next size level.
6368 static Color colorForCSSValue(int cssValueId)
6375 static const ColorValue colorValues[] = {
6376 { CSSValueAqua, 0xFF00FFFF },
6377 { CSSValueBlack, 0xFF000000 },
6378 { CSSValueBlue, 0xFF0000FF },
6379 { CSSValueFuchsia, 0xFFFF00FF },
6380 { CSSValueGray, 0xFF808080 },
6381 { CSSValueGreen, 0xFF008000 },
6382 { CSSValueGrey, 0xFF808080 },
6383 { CSSValueLime, 0xFF00FF00 },
6384 { CSSValueMaroon, 0xFF800000 },
6385 { CSSValueNavy, 0xFF000080 },
6386 { CSSValueOlive, 0xFF808000 },
6387 { CSSValueOrange, 0xFFFFA500 },
6388 { CSSValuePurple, 0xFF800080 },
6389 { CSSValueRed, 0xFFFF0000 },
6390 { CSSValueSilver, 0xFFC0C0C0 },
6391 { CSSValueTeal, 0xFF008080 },
6392 { CSSValueTransparent, 0x00000000 },
6393 { CSSValueWhite, 0xFFFFFFFF },
6394 { CSSValueYellow, 0xFFFFFF00 },
6398 for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
6399 if (col->cssValueId == cssValueId)
6402 return RenderTheme::defaultTheme()->systemColor(cssValueId);
6405 Color CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValue* primitiveValue)
6408 int ident = primitiveValue->getIdent();
6410 if (ident == CSSValueWebkitText)
6411 col = m_element->document()->textColor();
6412 else if (ident == CSSValueWebkitLink)
6413 col = m_element->isLink() && m_checker.m_matchVisitedPseudoClass ? m_element->document()->visitedLinkColor() : m_element->document()->linkColor();
6414 else if (ident == CSSValueWebkitActivelink)
6415 col = m_element->document()->activeLinkColor();
6416 else if (ident == CSSValueWebkitFocusRingColor)
6417 col = RenderTheme::focusRingColor();
6418 else if (ident == CSSValueCurrentcolor)
6419 col = m_style->color();
6421 col = colorForCSSValue(ident);
6422 } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
6423 col.setRGB(primitiveValue->getRGBA32Value());
6427 bool CSSStyleSelector::hasSelectorForAttribute(const AtomicString &attrname)
6429 return m_selectorAttrs.contains(attrname.impl());
6432 void CSSStyleSelector::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
6434 m_viewportDependentMediaQueryResults.append(new MediaQueryResult(*expr, result));
6437 bool CSSStyleSelector::affectedByViewportChange() const
6439 unsigned s = m_viewportDependentMediaQueryResults.size();
6440 for (unsigned i = 0; i < s; i++) {
6441 if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
6447 void CSSStyleSelector::SelectorChecker::allVisitedStateChanged()
6449 if (m_linksCheckedForVisitedState.isEmpty())
6451 for (Node* node = m_document; node; node = node->traverseNextNode()) {
6453 node->setNeedsStyleRecalc();
6457 void CSSStyleSelector::SelectorChecker::visitedStateChanged(LinkHash visitedHash)
6459 if (!m_linksCheckedForVisitedState.contains(visitedHash))
6461 for (Node* node = m_document; node; node = node->traverseNextNode()) {
6462 const AtomicString* attr = linkAttribute(node);
6463 if (attr && visitedLinkHash(m_document->baseURL(), *attr) == visitedHash)
6464 node->setNeedsStyleRecalc();
6468 static TransformOperation::OperationType getTransformOperationType(WebKitCSSTransformValue::TransformOperationType type)
6471 case WebKitCSSTransformValue::ScaleTransformOperation: return TransformOperation::SCALE;
6472 case WebKitCSSTransformValue::ScaleXTransformOperation: return TransformOperation::SCALE_X;
6473 case WebKitCSSTransformValue::ScaleYTransformOperation: return TransformOperation::SCALE_Y;
6474 case WebKitCSSTransformValue::ScaleZTransformOperation: return TransformOperation::SCALE_Z;
6475 case WebKitCSSTransformValue::Scale3DTransformOperation: return TransformOperation::SCALE_3D;
6476 case WebKitCSSTransformValue::TranslateTransformOperation: return TransformOperation::TRANSLATE;
6477 case WebKitCSSTransformValue::TranslateXTransformOperation: return TransformOperation::TRANSLATE_X;
6478 case WebKitCSSTransformValue::TranslateYTransformOperation: return TransformOperation::TRANSLATE_Y;
6479 case WebKitCSSTransformValue::TranslateZTransformOperation: return TransformOperation::TRANSLATE_Z;
6480 case WebKitCSSTransformValue::Translate3DTransformOperation: return TransformOperation::TRANSLATE_3D;
6481 case WebKitCSSTransformValue::RotateTransformOperation: return TransformOperation::ROTATE;
6482 case WebKitCSSTransformValue::RotateXTransformOperation: return TransformOperation::ROTATE_X;
6483 case WebKitCSSTransformValue::RotateYTransformOperation: return TransformOperation::ROTATE_Y;
6484 case WebKitCSSTransformValue::RotateZTransformOperation: return TransformOperation::ROTATE_Z;
6485 case WebKitCSSTransformValue::Rotate3DTransformOperation: return TransformOperation::ROTATE_3D;
6486 case WebKitCSSTransformValue::SkewTransformOperation: return TransformOperation::SKEW;
6487 case WebKitCSSTransformValue::SkewXTransformOperation: return TransformOperation::SKEW_X;
6488 case WebKitCSSTransformValue::SkewYTransformOperation: return TransformOperation::SKEW_Y;
6489 case WebKitCSSTransformValue::MatrixTransformOperation: return TransformOperation::MATRIX;
6490 case WebKitCSSTransformValue::Matrix3DTransformOperation: return TransformOperation::MATRIX_3D;
6491 case WebKitCSSTransformValue::PerspectiveTransformOperation: return TransformOperation::PERSPECTIVE;
6492 case WebKitCSSTransformValue::UnknownTransformOperation: return TransformOperation::NONE;
6494 return TransformOperation::NONE;
6497 bool CSSStyleSelector::createTransformOperations(CSSValue* inValue, RenderStyle* style, RenderStyle* rootStyle, TransformOperations& outOperations)
6499 float zoomFactor = style ? style->effectiveZoom() : 1;
6501 TransformOperations operations;
6502 if (inValue && !inValue->isPrimitiveValue()) {
6503 CSSValueList* list = static_cast<CSSValueList*>(inValue);
6504 unsigned size = list->length();
6505 for (unsigned i = 0; i < size; i++) {
6506 WebKitCSSTransformValue* val = static_cast<WebKitCSSTransformValue*>(list->itemWithoutBoundsCheck(i));
6508 CSSPrimitiveValue* firstValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(0));
6510 switch (val->operationType()) {
6511 case WebKitCSSTransformValue::ScaleTransformOperation:
6512 case WebKitCSSTransformValue::ScaleXTransformOperation:
6513 case WebKitCSSTransformValue::ScaleYTransformOperation: {
6516 if (val->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
6517 sy = firstValue->getDoubleValue();
6519 sx = firstValue->getDoubleValue();
6520 if (val->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
6521 if (val->length() > 1) {
6522 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6523 sy = secondValue->getDoubleValue();
6528 operations.operations().append(ScaleTransformOperation::create(sx, sy, 1.0, getTransformOperationType(val->operationType())));
6531 case WebKitCSSTransformValue::ScaleZTransformOperation:
6532 case WebKitCSSTransformValue::Scale3DTransformOperation: {
6536 if (val->operationType() == WebKitCSSTransformValue::ScaleZTransformOperation)
6537 sz = firstValue->getDoubleValue();
6538 else if (val->operationType() == WebKitCSSTransformValue::ScaleYTransformOperation)
6539 sy = firstValue->getDoubleValue();
6541 sx = firstValue->getDoubleValue();
6542 if (val->operationType() != WebKitCSSTransformValue::ScaleXTransformOperation) {
6543 if (val->length() > 2) {
6544 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2));
6545 sz = thirdValue->getDoubleValue();
6547 if (val->length() > 1) {
6548 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6549 sy = secondValue->getDoubleValue();
6554 operations.operations().append(ScaleTransformOperation::create(sx, sy, sz, getTransformOperationType(val->operationType())));
6557 case WebKitCSSTransformValue::TranslateTransformOperation:
6558 case WebKitCSSTransformValue::TranslateXTransformOperation:
6559 case WebKitCSSTransformValue::TranslateYTransformOperation: {
6561 Length tx = Length(0, Fixed);
6562 Length ty = Length(0, Fixed);
6563 if (val->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
6564 ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok);
6566 tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok);
6567 if (val->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
6568 if (val->length() > 1) {
6569 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6570 ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok);
6578 operations.operations().append(TranslateTransformOperation::create(tx, ty, Length(0, Fixed), getTransformOperationType(val->operationType())));
6581 case WebKitCSSTransformValue::TranslateZTransformOperation:
6582 case WebKitCSSTransformValue::Translate3DTransformOperation: {
6584 Length tx = Length(0, Fixed);
6585 Length ty = Length(0, Fixed);
6586 Length tz = Length(0, Fixed);
6587 if (val->operationType() == WebKitCSSTransformValue::TranslateZTransformOperation)
6588 tz = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok);
6589 else if (val->operationType() == WebKitCSSTransformValue::TranslateYTransformOperation)
6590 ty = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok);
6592 tx = convertToLength(firstValue, style, rootStyle, zoomFactor, &ok);
6593 if (val->operationType() != WebKitCSSTransformValue::TranslateXTransformOperation) {
6594 if (val->length() > 2) {
6595 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2));
6596 tz = convertToLength(thirdValue, style, rootStyle, zoomFactor, &ok);
6598 if (val->length() > 1) {
6599 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6600 ty = convertToLength(secondValue, style, rootStyle, zoomFactor, &ok);
6608 operations.operations().append(TranslateTransformOperation::create(tx, ty, tz, getTransformOperationType(val->operationType())));
6611 case WebKitCSSTransformValue::RotateTransformOperation: {
6612 double angle = firstValue->getDoubleValue();
6613 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
6614 angle = rad2deg(angle);
6615 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
6616 angle = grad2deg(angle);
6617 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
6618 angle = turn2deg(angle);
6620 operations.operations().append(RotateTransformOperation::create(0, 0, 1, angle, getTransformOperationType(val->operationType())));
6623 case WebKitCSSTransformValue::RotateXTransformOperation:
6624 case WebKitCSSTransformValue::RotateYTransformOperation:
6625 case WebKitCSSTransformValue::RotateZTransformOperation: {
6629 double angle = firstValue->getDoubleValue();
6630 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
6631 angle = rad2deg(angle);
6632 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
6633 angle = grad2deg(angle);
6635 if (val->operationType() == WebKitCSSTransformValue::RotateXTransformOperation)
6637 else if (val->operationType() == WebKitCSSTransformValue::RotateYTransformOperation)
6641 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(val->operationType())));
6644 case WebKitCSSTransformValue::Rotate3DTransformOperation: {
6645 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6646 CSSPrimitiveValue* thirdValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2));
6647 CSSPrimitiveValue* fourthValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3));
6648 double x = firstValue->getDoubleValue();
6649 double y = secondValue->getDoubleValue();
6650 double z = thirdValue->getDoubleValue();
6651 double angle = fourthValue->getDoubleValue();
6652 if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
6653 angle = rad2deg(angle);
6654 else if (fourthValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
6655 angle = grad2deg(angle);
6656 operations.operations().append(RotateTransformOperation::create(x, y, z, angle, getTransformOperationType(val->operationType())));
6659 case WebKitCSSTransformValue::SkewTransformOperation:
6660 case WebKitCSSTransformValue::SkewXTransformOperation:
6661 case WebKitCSSTransformValue::SkewYTransformOperation: {
6664 double angle = firstValue->getDoubleValue();
6665 if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
6666 angle = rad2deg(angle);
6667 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
6668 angle = grad2deg(angle);
6669 else if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
6670 angle = turn2deg(angle);
6671 if (val->operationType() == WebKitCSSTransformValue::SkewYTransformOperation)
6675 if (val->operationType() == WebKitCSSTransformValue::SkewTransformOperation) {
6676 if (val->length() > 1) {
6677 CSSPrimitiveValue* secondValue = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1));
6678 angleY = secondValue->getDoubleValue();
6679 if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_RAD)
6680 angleY = rad2deg(angleY);
6681 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_GRAD)
6682 angleY = grad2deg(angleY);
6683 else if (secondValue->primitiveType() == CSSPrimitiveValue::CSS_TURN)
6684 angleY = turn2deg(angleY);
6688 operations.operations().append(SkewTransformOperation::create(angleX, angleY, getTransformOperationType(val->operationType())));
6691 case WebKitCSSTransformValue::MatrixTransformOperation: {
6692 double a = firstValue->getDoubleValue();
6693 double b = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1))->getDoubleValue();
6694 double c = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2))->getDoubleValue();
6695 double d = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3))->getDoubleValue();
6696 double e = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(4))->getDoubleValue();
6697 double f = static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(5))->getDoubleValue();
6698 operations.operations().append(MatrixTransformOperation::create(a, b, c, d, e, f));
6701 case WebKitCSSTransformValue::Matrix3DTransformOperation: {
6702 TransformationMatrix matrix(static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(0))->getDoubleValue(),
6703 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(1))->getDoubleValue(),
6704 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(2))->getDoubleValue(),
6705 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(3))->getDoubleValue(),
6706 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(4))->getDoubleValue(),
6707 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(5))->getDoubleValue(),
6708 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(6))->getDoubleValue(),
6709 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(7))->getDoubleValue(),
6710 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(8))->getDoubleValue(),
6711 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(9))->getDoubleValue(),
6712 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(10))->getDoubleValue(),
6713 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(11))->getDoubleValue(),
6714 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(12))->getDoubleValue(),
6715 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(13))->getDoubleValue(),
6716 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(14))->getDoubleValue(),
6717 static_cast<CSSPrimitiveValue*>(val->itemWithoutBoundsCheck(15))->getDoubleValue());
6718 operations.operations().append(Matrix3DTransformOperation::create(matrix));
6721 case WebKitCSSTransformValue::PerspectiveTransformOperation: {
6722 double p = firstValue->getDoubleValue();
6725 operations.operations().append(PerspectiveTransformOperation::create(p));
6728 case WebKitCSSTransformValue::UnknownTransformOperation:
6729 ASSERT_NOT_REACHED();
6734 outOperations = operations;
6738 } // namespace WebCore