02ed22d1cfea79e6aba4055fa02637c33cb351ae
[WebKit-https.git] / Source / WebCore / css / CSSStyleSelector.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
4  * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
5  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
7  * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
8  * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
9  * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
10  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Library General Public
14  * License as published by the Free Software Foundation; either
15  * version 2 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public License
23  * along with this library; see the file COPYING.LIB.  If not, write to
24  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25  * Boston, MA 02110-1301, USA.
26  */
27
28 #include "config.h"
29 #include "CSSStyleSelector.h"
30
31 #include "Attribute.h"
32 #include "ContentData.h"
33 #include "CounterContent.h"
34 #include "CursorList.h"
35 #include "CSSBorderImageValue.h"
36 #include "CSSCursorImageValue.h"
37 #include "CSSFontFaceRule.h"
38 #include "CSSFontSelector.h"
39 #include "CSSImportRule.h"
40 #include "CSSLineBoxContainValue.h"
41 #include "CSSMediaRule.h"
42 #include "CSSPageRule.h"
43 #include "CSSParser.h"
44 #include "CSSPrimitiveValueMappings.h"
45 #include "CSSPropertyNames.h"
46 #include "CSSReflectValue.h"
47 #include "CSSRegionStyleRule.h"
48 #include "CSSRuleList.h"
49 #include "CSSSelector.h"
50 #include "CSSSelectorList.h"
51 #include "CSSStyleApplyProperty.h"
52 #include "CSSStyleRule.h"
53 #include "CSSStyleSheet.h"
54 #include "CSSTimingFunctionValue.h"
55 #include "CSSValueList.h"
56 #include "CachedImage.h"
57 #include "Counter.h"
58 #if ENABLE(CSS_FILTERS)
59 #include "FilterOperation.h"
60 #endif
61 #include "FontFamilyValue.h"
62 #include "FontFeatureValue.h"
63 #include "FontValue.h"
64 #include "Frame.h"
65 #include "FrameSelection.h"
66 #include "FrameView.h"
67 #include "HTMLDocument.h"
68 #include "HTMLElement.h"
69 #include "HTMLInputElement.h"
70 #include "HTMLNames.h"
71 #include "HTMLProgressElement.h"
72 #include "HTMLTextAreaElement.h"
73 #include "KeyframeList.h"
74 #include "LinkHash.h"
75 #include "LocaleToScriptMapping.h"
76 #include "Matrix3DTransformOperation.h"
77 #include "MatrixTransformOperation.h"
78 #include "MediaList.h"
79 #include "MediaQueryEvaluator.h"
80 #include "NodeRenderStyle.h"
81 #include "Page.h"
82 #include "PageGroup.h"
83 #include "Pair.h"
84 #include "PerspectiveTransformOperation.h"
85 #include "QuotesData.h"
86 #include "Rect.h"
87 #include "RenderScrollbar.h"
88 #include "RenderScrollbarTheme.h"
89 #include "RenderStyleConstants.h"
90 #include "RenderTheme.h"
91 #include "RotateTransformOperation.h"
92 #include "ScaleTransformOperation.h"
93 #include "SecurityOrigin.h"
94 #include "Settings.h"
95 #include "ShadowData.h"
96 #include "ShadowValue.h"
97 #include "SkewTransformOperation.h"
98 #include "StyleCachedImage.h"
99 #include "StylePendingImage.h"
100 #include "StyleGeneratedImage.h"
101 #include "StyleSheetList.h"
102 #include "Text.h"
103 #include "TransformationMatrix.h"
104 #include "TranslateTransformOperation.h"
105 #include "UserAgentStyleSheets.h"
106 #if ENABLE(CSS_FILTERS)
107 #include "WebKitCSSFilterValue.h"
108 #endif
109 #include "WebKitCSSKeyframeRule.h"
110 #include "WebKitCSSKeyframesRule.h"
111 #include "WebKitCSSTransformValue.h"
112 #include "WebKitFontFamilyNames.h"
113 #include "XMLNames.h"
114 #include <wtf/StdLibExtras.h>
115 #include <wtf/Vector.h>
116
117 #if ENABLE(DASHBOARD_SUPPORT)
118 #include "DashboardRegion.h"
119 #endif
120
121 #if ENABLE(SVG)
122 #include "SVGNames.h"
123 #endif
124
125 #if ENABLE(CSS_SHADERS)
126 #include "CustomFilterOperation.h"
127 #include "StyleCachedShader.h"
128 #include "StylePendingShader.h"
129 #include "StyleShader.h"
130 #include "WebKitCSSShaderValue.h"
131 #endif
132
133 using namespace std;
134
135 namespace WebCore {
136
137 using namespace HTMLNames;
138
139 #define HANDLE_INHERIT(prop, Prop) \
140 if (isInherit) { \
141     m_style->set##Prop(m_parentStyle->prop()); \
142     return; \
143 }
144
145 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
146 HANDLE_INHERIT(prop, Prop) \
147 if (isInitial) { \
148     m_style->set##Prop(RenderStyle::initial##Prop()); \
149     return; \
150 }
151
152 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
153 HANDLE_INHERIT(prop, Prop) \
154 if (isInitial) { \
155     m_style->set##Prop(RenderStyle::initial##Value());\
156     return;\
157 }
158
159 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
160 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
161 if (primitiveValue) \
162     m_style->set##Prop(*primitiveValue);
163
164 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(prop, Prop, Value) \
165 HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
166 if (primitiveValue) \
167     m_style->set##Prop(*primitiveValue);
168
169 #define HANDLE_INHERIT_COND(propID, prop, Prop) \
170 if (id == propID) { \
171     m_style->set##Prop(m_parentStyle->prop()); \
172     return; \
173 }
174
175 #define HANDLE_INHERIT_COND_WITH_BACKUP(propID, prop, propAlt, Prop) \
176 if (id == propID) { \
177     if (m_parentStyle->prop().isValid()) \
178         m_style->set##Prop(m_parentStyle->prop()); \
179     else \
180         m_style->set##Prop(m_parentStyle->propAlt()); \
181     return; \
182 }
183
184 #define HANDLE_INITIAL_COND(propID, Prop) \
185 if (id == propID) { \
186     m_style->set##Prop(RenderStyle::initial##Prop()); \
187     return; \
188 }
189
190 #define HANDLE_INITIAL_COND_WITH_VALUE(propID, Prop, Value) \
191 if (id == propID) { \
192     m_style->set##Prop(RenderStyle::initial##Value()); \
193     return; \
194 }
195
196 class RuleData {
197 public:
198     RuleData(CSSStyleRule*, CSSSelector*, unsigned position);
199
200     unsigned position() const { return m_position; }
201     CSSStyleRule* rule() const { return m_rule; }
202     CSSSelector* selector() const { return m_selector; }
203
204     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
205     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
206     bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
207     bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
208     unsigned specificity() const { return m_specificity; }
209     unsigned linkMatchType() const { return m_linkMatchType; }
210
211     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
212     static const unsigned maximumIdentifierCount = 4;
213     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
214
215 private:
216     CSSStyleRule* m_rule;
217     CSSSelector* m_selector;
218     unsigned m_specificity;
219     unsigned m_position : 26;
220     bool m_hasFastCheckableSelector : 1;
221     bool m_hasMultipartSelector : 1;
222     bool m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
223     bool m_containsUncommonAttributeSelector : 1;
224     unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
225     // Use plain array instead of a Vector to minimize memory overhead.
226     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
227 };
228
229 class RuleSet {
230     WTF_MAKE_NONCOPYABLE(RuleSet);
231 public:
232     RuleSet();
233     ~RuleSet();
234
235     typedef HashMap<AtomicStringImpl*, Vector<RuleData>*> AtomRuleMap;
236
237     void addRulesFromSheet(CSSStyleSheet*, const MediaQueryEvaluator&, CSSStyleSelector* = 0);
238
239     void addStyleRule(CSSStyleRule* item);
240     void addRule(CSSStyleRule* rule, CSSSelector* sel);
241     void addPageRule(CSSPageRule*);
242     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
243                       CSSStyleRule* rule, CSSSelector* sel);
244     void shrinkToFit();
245     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
246
247     void collectFeatures(CSSStyleSelector::Features&) const;
248
249     const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
250     const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
251     const Vector<RuleData>* tagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
252     const Vector<RuleData>* shadowPseudoElementRules(AtomicStringImpl* key) const { return m_shadowPseudoElementRules.get(key); }
253     const Vector<RuleData>* linkPseudoClassRules() const { return &m_linkPseudoClassRules; }
254     const Vector<RuleData>* focusPseudoClassRules() const { return &m_focusPseudoClassRules; }
255     const Vector<RuleData>* universalRules() const { return &m_universalRules; }
256     const Vector<RuleData>* pageRules() const { return &m_pageRules; }
257
258 public:
259     AtomRuleMap m_idRules;
260     AtomRuleMap m_classRules;
261     AtomRuleMap m_tagRules;
262     AtomRuleMap m_shadowPseudoElementRules;
263     Vector<RuleData> m_linkPseudoClassRules;
264     Vector<RuleData> m_focusPseudoClassRules;
265     Vector<RuleData> m_universalRules;
266     Vector<RuleData> m_pageRules;
267     unsigned m_ruleCount;
268     bool m_autoShrinkToFitEnabled;
269 };
270
271 static RuleSet* defaultStyle;
272 static RuleSet* defaultQuirksStyle;
273 static RuleSet* defaultPrintStyle;
274 static RuleSet* defaultViewSourceStyle;
275 static CSSStyleSheet* simpleDefaultStyleSheet;
276
277 static RuleSet* siblingRulesInDefaultStyle;
278 static RuleSet* uncommonAttributeRulesInDefaultStyle;
279
280 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable;
281
282 static void loadFullDefaultStyle();
283 static void loadSimpleDefaultStyle();
284 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
285 static const char* simpleUserAgentStyleSheet = "html,body,div{display:block}head{display:none}body{margin:8px}div:focus,span:focus{outline:auto 5px -webkit-focus-ring-color}a:-webkit-any-link{color:-webkit-link;text-decoration:underline}a:-webkit-any-link:active{color:-webkit-activelink}";
286
287 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
288 {
289     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
290 }
291
292 static inline void collectSpecialRulesInDefaultStyle()
293 {
294     CSSStyleSelector::Features features;
295     defaultStyle->collectFeatures(features);
296     ASSERT(features.idsInRules.isEmpty());
297     delete siblingRulesInDefaultStyle;
298     delete uncommonAttributeRulesInDefaultStyle;
299     siblingRulesInDefaultStyle = features.siblingRules.leakPtr();
300     uncommonAttributeRulesInDefaultStyle = features.uncommonAttributeRules.leakPtr();
301 }
302
303 static inline void assertNoSiblingRulesInDefaultStyle()
304 {
305 #ifndef NDEBUG
306     if (siblingRulesInDefaultStyle)
307         return;
308     collectSpecialRulesInDefaultStyle();
309     ASSERT(!siblingRulesInDefaultStyle);
310 #endif
311 }
312
313 static const MediaQueryEvaluator& screenEval()
314 {
315     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
316     return staticScreenEval;
317 }
318
319 static const MediaQueryEvaluator& printEval()
320 {
321     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
322     return staticPrintEval;
323 }
324
325 static CSSMutableStyleDeclaration* leftToRightDeclaration()
326 {
327     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, leftToRightDecl, (CSSMutableStyleDeclaration::create()));
328     if (!leftToRightDecl->length()) {
329         leftToRightDecl->setProperty(CSSPropertyDirection, "ltr", false, false);
330         leftToRightDecl->setStrictParsing(false);
331     }
332     return leftToRightDecl.get();
333 }
334
335 static CSSMutableStyleDeclaration* rightToLeftDeclaration()
336 {
337     DEFINE_STATIC_LOCAL(RefPtr<CSSMutableStyleDeclaration>, rightToLeftDecl, (CSSMutableStyleDeclaration::create()));
338     if (!rightToLeftDecl->length()) {
339         rightToLeftDecl->setProperty(CSSPropertyDirection, "rtl", false, false);
340         rightToLeftDecl->setStrictParsing(false);
341     }
342     return rightToLeftDecl.get();
343 }
344
345 CSSStyleSelector::CSSStyleSelector(Document* document, StyleSheetList* styleSheets, CSSStyleSheet* mappedElementSheet,
346                                    CSSStyleSheet* pageUserSheet, const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets, const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets,
347                                    bool strictParsing, bool matchAuthorAndUserStyles)
348     : m_backgroundData(BackgroundFillLayer)
349     , m_checker(document, strictParsing)
350     , m_element(0)
351     , m_styledElement(0)
352     , m_elementLinkState(NotInsideLink)
353     , m_fontDirty(false)
354     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
355     , m_sameOriginOnly(false)
356     , m_fontSelector(CSSFontSelector::create(document))
357     , m_applyPropertyToRegularStyle(true)
358     , m_applyPropertyToVisitedLinkStyle(false)
359     , m_applyProperty(CSSStyleApplyProperty::sharedCSSStyleApplyProperty())
360 #if ENABLE(CSS_SHADERS)
361     , m_hasPendingShaders(false)
362 #endif
363 {
364     Element* root = document->documentElement();
365
366     if (!defaultStyle) {
367         if (!root || elementCanUseSimpleDefaultStyle(root))
368             loadSimpleDefaultStyle();
369         else {
370             loadFullDefaultStyle();
371         }
372     }
373
374     // construct document root element default style. this is needed
375     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
376     // This is here instead of constructor, because when constructor is run,
377     // document doesn't have documentElement
378     // NOTE: this assumes that element that gets passed to styleForElement -call
379     // is always from the document that owns the style selector
380     FrameView* view = document->view();
381     if (view)
382         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
383     else
384         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
385
386     if (root)
387         m_rootDefaultStyle = styleForElement(root, 0, false, true); // don't ref, because the RenderStyle is allocated from global heap
388
389     if (m_rootDefaultStyle && view)
390         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
391
392     m_authorStyle = adoptPtr(new RuleSet);
393     // Adding rules from multiple sheets, shrink at the end.
394     m_authorStyle->disableAutoShrinkToFit();
395
396     // FIXME: This sucks! The user sheet is reparsed every time!
397     OwnPtr<RuleSet> tempUserStyle = adoptPtr(new RuleSet);
398     if (pageUserSheet)
399         tempUserStyle->addRulesFromSheet(pageUserSheet, *m_medium, this);
400     if (pageGroupUserSheets) {
401         unsigned length = pageGroupUserSheets->size();
402         for (unsigned i = 0; i < length; i++) {
403             if (pageGroupUserSheets->at(i)->isUserStyleSheet())
404                 tempUserStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
405             else
406                 m_authorStyle->addRulesFromSheet(pageGroupUserSheets->at(i).get(), *m_medium, this);
407         }
408     }
409     if (documentUserSheets) {
410         unsigned length = documentUserSheets->size();
411         for (unsigned i = 0; i < length; i++) {
412             if (documentUserSheets->at(i)->isUserStyleSheet())
413                 tempUserStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
414             else
415                 m_authorStyle->addRulesFromSheet(documentUserSheets->at(i).get(), *m_medium, this);
416         }
417     }
418
419     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
420         m_userStyle = tempUserStyle.release();
421
422     // Add rules from elements like SVG's <font-face>
423     if (mappedElementSheet)
424         m_authorStyle->addRulesFromSheet(mappedElementSheet, *m_medium, this);
425
426     // add stylesheets from document
427     unsigned length = styleSheets->length();
428     for (unsigned i = 0; i < length; i++) {
429         StyleSheet* sheet = styleSheets->item(i);
430         if (sheet->isCSSStyleSheet() && !sheet->disabled())
431             m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheet*>(sheet), *m_medium, this);
432     }
433     // Collect all ids and rules using sibling selectors (:first-child and similar)
434     // in the current set of stylesheets. Style sharing code uses this information to reject
435     // sharing candidates.
436     // Usually there are no sibling rules in the default style but the MathML sheet has some.
437     if (siblingRulesInDefaultStyle)
438         siblingRulesInDefaultStyle->collectFeatures(m_features);
439     if (uncommonAttributeRulesInDefaultStyle)
440         uncommonAttributeRulesInDefaultStyle->collectFeatures(m_features);
441     m_authorStyle->collectFeatures(m_features);
442     if (m_userStyle)
443         m_userStyle->collectFeatures(m_features);
444
445     m_authorStyle->shrinkToFit();
446     if (m_features.siblingRules)
447         m_features.siblingRules->shrinkToFit();
448     if (m_features.uncommonAttributeRules)
449         m_features.uncommonAttributeRules->shrinkToFit();
450
451     if (document->renderer() && document->renderer()->style())
452         document->renderer()->style()->font().update(fontSelector());
453 }
454
455 void CSSStyleSelector::addRegionStyleRule(PassRefPtr<CSSRegionStyleRule> regionStyleRule)
456 {
457     m_regionStyleRules.append(regionStyleRule);
458 }
459
460 // This is a simplified style setting function for keyframe styles
461 void CSSStyleSelector::addKeyframeStyle(PassRefPtr<WebKitCSSKeyframesRule> rule)
462 {
463     AtomicString s(rule->name());
464     m_keyframesRuleMap.add(s.impl(), rule);
465 }
466
467 CSSStyleSelector::~CSSStyleSelector()
468 {
469     m_fontSelector->clearDocument();
470     deleteAllValues(m_viewportDependentMediaQueryResults);
471 }
472
473 CSSStyleSelector::Features::Features()
474     : usesFirstLineRules(false)
475     , usesBeforeAfterRules(false)
476     , usesLinkRules(false)
477 {
478 }
479
480 CSSStyleSelector::Features::~Features()
481 {
482 }
483
484 static CSSStyleSheet* parseUASheet(const String& str)
485 {
486     CSSStyleSheet* sheet = CSSStyleSheet::create().leakRef(); // leak the sheet on purpose
487     sheet->parseString(str);
488     return sheet;
489 }
490
491 static CSSStyleSheet* parseUASheet(const char* characters, unsigned size)
492 {
493     return parseUASheet(String(characters, size));
494 }
495
496 static void loadFullDefaultStyle()
497 {
498     if (simpleDefaultStyleSheet) {
499         ASSERT(defaultStyle);
500         ASSERT(defaultPrintStyle == defaultStyle);
501         delete defaultStyle;
502         simpleDefaultStyleSheet->deref();
503         defaultStyle = new RuleSet;
504         defaultPrintStyle = new RuleSet;
505         simpleDefaultStyleSheet = 0;
506     } else {
507         ASSERT(!defaultStyle);
508         defaultStyle = new RuleSet;
509         defaultPrintStyle = new RuleSet;
510         defaultQuirksStyle = new RuleSet;
511     }
512
513     // Strict-mode rules.
514     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
515     CSSStyleSheet* defaultSheet = parseUASheet(defaultRules);
516     defaultStyle->addRulesFromSheet(defaultSheet, screenEval());
517     defaultPrintStyle->addRulesFromSheet(defaultSheet, printEval());
518
519     // Quirks-mode rules.
520     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
521     CSSStyleSheet* quirksSheet = parseUASheet(quirksRules);
522     defaultQuirksStyle->addRulesFromSheet(quirksSheet, screenEval());
523 }
524
525 static void loadSimpleDefaultStyle()
526 {
527     ASSERT(!defaultStyle);
528     ASSERT(!simpleDefaultStyleSheet);
529
530     defaultStyle = new RuleSet;
531     // There are no media-specific rules in the simple default style.
532     defaultPrintStyle = defaultStyle;
533     defaultQuirksStyle = new RuleSet;
534
535     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
536     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
537
538     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
539 }
540
541 static void loadViewSourceStyle()
542 {
543     ASSERT(!defaultViewSourceStyle);
544     defaultViewSourceStyle = new RuleSet;
545     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
546 }
547
548 static void ensureDefaultStyleSheetsForElement(Element* element)
549 {
550     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element)) {
551         loadFullDefaultStyle();
552         assertNoSiblingRulesInDefaultStyle();
553         collectSpecialRulesInDefaultStyle();
554     }
555
556 #if ENABLE(SVG)
557     static bool loadedSVGUserAgentSheet;
558     if (element->isSVGElement() && !loadedSVGUserAgentSheet) {
559         // SVG rules.
560         loadedSVGUserAgentSheet = true;
561         CSSStyleSheet* svgSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
562         defaultStyle->addRulesFromSheet(svgSheet, screenEval());
563         defaultPrintStyle->addRulesFromSheet(svgSheet, printEval());
564         assertNoSiblingRulesInDefaultStyle();
565         collectSpecialRulesInDefaultStyle();
566     }
567 #endif
568
569 #if ENABLE(MATHML)
570     static bool loadedMathMLUserAgentSheet;
571     if (element->isMathMLElement() && !loadedMathMLUserAgentSheet) {
572         // MathML rules.
573         loadedMathMLUserAgentSheet = true;
574         CSSStyleSheet* mathMLSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
575         defaultStyle->addRulesFromSheet(mathMLSheet, screenEval());
576         defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval());
577         // There are some sibling and uncommon attribute rules here.
578         collectSpecialRulesInDefaultStyle();
579     }
580 #endif
581
582 #if ENABLE(VIDEO)
583     static bool loadedMediaStyleSheet;
584     if (!loadedMediaStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
585         loadedMediaStyleSheet = true;
586         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
587         CSSStyleSheet* mediaControlsSheet = parseUASheet(mediaRules);
588         defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval());
589         defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval());
590         collectSpecialRulesInDefaultStyle();
591     }
592 #endif
593
594 #if ENABLE(FULLSCREEN_API)
595     static bool loadedFullScreenStyleSheet;
596     if (!loadedFullScreenStyleSheet && element->document()->webkitIsFullScreen()) {
597         loadedFullScreenStyleSheet = true;
598         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
599         CSSStyleSheet* fullscreenSheet = parseUASheet(fullscreenRules);
600         defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval());
601         defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval());
602         collectSpecialRulesInDefaultStyle();
603     }
604 #endif
605 }
606
607 CSSStyleSelector::MatchedStyleDeclaration::MatchedStyleDeclaration() 
608 {  
609     // Make sure all memory is zero initializes as we calculate hash over the bytes of this object.
610     memset(this, 0, sizeof(*this));
611 }
612
613 void CSSStyleSelector::addMatchedDeclaration(CSSMutableStyleDeclaration* styleDeclaration, unsigned linkMatchType)
614 {
615     m_matchedDecls.grow(m_matchedDecls.size() + 1);
616     MatchedStyleDeclaration& newDeclaration = m_matchedDecls.last();
617     newDeclaration.styleDeclaration = styleDeclaration;
618     newDeclaration.linkMatchType = linkMatchType;
619 }
620
621 void CSSStyleSelector::matchRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
622 {
623     m_matchedRules.clear();
624
625     if (!rules || !m_element)
626         return;
627
628     // We need to collect the rules for id, class, tag, and everything else into a buffer and
629     // then sort the buffer.
630     if (m_element->hasID())
631         matchRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
632     if (m_element->hasClass()) {
633         ASSERT(m_styledElement);
634         const SpaceSplitString& classNames = m_styledElement->classNames();
635         size_t size = classNames.size();
636         for (size_t i = 0; i < size; ++i)
637             matchRulesForList(rules->classRules(classNames[i].impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
638     }
639     const AtomicString& pseudoId = m_element->shadowPseudoId();
640     if (!pseudoId.isEmpty()) {
641         ASSERT(m_styledElement);
642         matchRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
643     }
644     if (m_element->isLink())
645         matchRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
646     if (m_checker.matchesFocusPseudoClass(m_element))
647         matchRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
648     matchRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, includeEmptyRules);
649     matchRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, includeEmptyRules);
650
651     // If we didn't match any rules, we're done.
652     if (m_matchedRules.isEmpty())
653         return;
654
655     // Sort the set of matched rules.
656     sortMatchedRules();
657
658     // Now transfer the set of matched rules over to our list of decls.
659     if (!m_checker.isCollectingRulesOnly()) {
660         // FIXME: This sucks, the inspector should get the style from the visited style itself.
661         bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
662         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
663             if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
664                 m_style->setAffectedByUncommonAttributeSelectors();
665             unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
666             if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
667                 linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
668             addMatchedDeclaration(m_matchedRules[i]->rule()->declaration(), linkMatchType);
669         }
670     } else {
671         for (unsigned i = 0; i < m_matchedRules.size(); i++) {
672             if (!m_ruleList)
673                 m_ruleList = CSSRuleList::create();
674             m_ruleList->append(m_matchedRules[i]->rule());
675         }
676     }
677 }
678
679 class MatchingUARulesScope {
680 public:
681     MatchingUARulesScope();
682     ~MatchingUARulesScope();
683
684     static bool isMatchingUARules();
685
686 private:
687     static bool m_matchingUARules;
688 };
689
690 MatchingUARulesScope::MatchingUARulesScope()
691 {
692     ASSERT(!m_matchingUARules);
693     m_matchingUARules = true;
694 }
695
696 MatchingUARulesScope::~MatchingUARulesScope()
697 {
698     m_matchingUARules = false;
699 }
700
701 inline bool MatchingUARulesScope::isMatchingUARules()
702 {
703     return m_matchingUARules;
704 }
705
706 bool MatchingUARulesScope::m_matchingUARules = false;
707
708 inline static bool matchesInTreeScope(TreeScope* treeScope, bool ruleReachesIntoShadowDOM)
709 {
710     return MatchingUARulesScope::isMatchingUARules() || treeScope->applyAuthorSheets() || ruleReachesIntoShadowDOM;
711 }
712
713 void CSSStyleSelector::matchRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, bool includeEmptyRules)
714 {
715     if (!rules)
716         return;
717     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
718     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
719     bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
720
721     unsigned size = rules->size();
722     for (unsigned i = 0; i < size; ++i) {
723         const RuleData& ruleData = rules->at(i);
724         if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
725             continue;
726         if (checkSelector(ruleData)) {
727             if (!matchesInTreeScope(m_element->treeScope(), m_checker.hasUnknownPseudoElements()))
728                 continue;
729             // If the rule has no properties to apply, then ignore it in the non-debug mode.
730             CSSStyleRule* rule = ruleData.rule();
731             CSSMutableStyleDeclaration* decl = rule->declaration();
732             if (!decl || (!decl->length() && !includeEmptyRules))
733                 continue;
734             if (m_sameOriginOnly && !m_checker.document()->securityOrigin()->canRequest(rule->baseURL()))
735                 continue;
736             // If we're matching normal rules, set a pseudo bit if
737             // we really just matched a pseudo-element.
738             if (m_dynamicPseudo != NOPSEUDO && m_checker.pseudoStyle() == NOPSEUDO) {
739                 if (m_checker.isCollectingRulesOnly())
740                     continue;
741                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
742                     m_style->setHasPseudoStyle(m_dynamicPseudo);
743             } else {
744                 // Update our first/last rule indices in the matched rules array.
745                 lastRuleIndex = m_matchedDecls.size() + m_matchedRules.size();
746                 if (firstRuleIndex == -1)
747                     firstRuleIndex = lastRuleIndex;
748
749                 // Add this rule to our list of matched rules.
750                 addMatchedRule(&ruleData);
751             }
752         }
753     }
754 }
755
756 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
757 {
758     unsigned specificity1 = r1->specificity();
759     unsigned specificity2 = r2->specificity();
760     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
761 }
762
763 void CSSStyleSelector::sortMatchedRules()
764 {
765     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
766 }
767
768 void CSSStyleSelector::matchAllRules(MatchResult& result)
769 {
770     matchUARules(result);
771
772     // Now we check user sheet rules.
773     if (m_matchAuthorAndUserStyles)
774         matchRules(m_userStyle.get(), result.firstUserRule, result.lastUserRule, false);
775         
776     // Now check author rules, beginning first with presentational attributes mapped from HTML.
777     if (m_styledElement) {
778         // Ask if the HTML element has mapped attributes.
779         if (m_styledElement->hasMappedAttributes()) {
780             // Walk our attribute list and add in each decl.
781             const NamedNodeMap* map = m_styledElement->attributeMap();
782             for (unsigned i = 0; i < map->length(); ++i) {
783                 Attribute* attr = map->attributeItem(i);
784                 if (attr->isMappedAttribute() && attr->decl()) {
785                     result.lastAuthorRule = m_matchedDecls.size();
786                     if (result.firstAuthorRule == -1)
787                         result.firstAuthorRule = result.lastAuthorRule;
788                     addMatchedDeclaration(attr->decl());
789                     result.isCacheable = false;
790                 }
791             }
792         }
793         
794         // Now we check additional mapped declarations.
795         // Tables and table cells share an additional mapped rule that must be applied
796         // after all attributes, since their mapped style depends on the values of multiple attributes.
797         if (m_styledElement->canHaveAdditionalAttributeStyleDecls()) {
798             m_additionalAttributeStyleDecls.clear();
799             m_styledElement->additionalAttributeStyleDecls(m_additionalAttributeStyleDecls);
800             if (!m_additionalAttributeStyleDecls.isEmpty()) {
801                 unsigned additionalDeclsSize = m_additionalAttributeStyleDecls.size();
802                 if (result.firstAuthorRule == -1)
803                     result.firstAuthorRule = m_matchedDecls.size();
804                 result.lastAuthorRule = m_matchedDecls.size() + additionalDeclsSize - 1;
805                 for (unsigned i = 0; i < additionalDeclsSize; ++i)
806                     addMatchedDeclaration(m_additionalAttributeStyleDecls[i]);
807                 result.isCacheable = false;
808             }
809         }
810         if (m_styledElement->isHTMLElement()) {
811             bool isAuto;
812             TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
813             if (isAuto)
814                 addMatchedDeclaration(textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
815         }
816     }
817     
818     // Check the rules in author sheets next.
819     if (m_matchAuthorAndUserStyles)
820         matchRules(m_authorStyle.get(), result.firstAuthorRule, result.lastAuthorRule, false);
821         
822     // Now check our inline style attribute.
823     if (m_matchAuthorAndUserStyles && m_styledElement) {
824         CSSMutableStyleDeclaration* inlineDecl = m_styledElement->inlineStyleDecl();
825         if (inlineDecl) {
826             result.lastAuthorRule = m_matchedDecls.size();
827             if (result.firstAuthorRule == -1)
828                 result.firstAuthorRule = result.lastAuthorRule;
829             addMatchedDeclaration(inlineDecl);
830             result.isCacheable = false;
831         }
832     }
833 }
834     
835 inline void CSSStyleSelector::initElement(Element* e)
836 {
837     if (m_element != e) {
838         m_element = e;
839         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
840         m_elementLinkState = m_checker.determineLinkState(m_element);
841         if (e && e == e->document()->documentElement()) {
842             e->document()->setDirectionSetOnDocumentElement(false);
843             e->document()->setWritingModeSetOnDocumentElement(false);
844         }
845     }
846 }
847
848 inline void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
849 {
850     m_checker.setPseudoStyle(pseudoID);
851
852     m_parentNode = e ? e->parentNodeForRenderingAndStyle() : 0;
853
854     if (parentStyle)
855         m_parentStyle = parentStyle;
856     else
857         m_parentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
858
859     Node* docElement = e ? e->document()->documentElement() : 0;
860     RenderStyle* docStyle = m_checker.document()->renderStyle();
861     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
862
863     m_style = 0;
864
865     m_matchedDecls.clear();
866
867     m_pendingImageProperties.clear();
868
869     m_ruleList = 0;
870
871     m_fontDirty = false;
872 }
873
874 static const unsigned cStyleSearchThreshold = 10;
875 static const unsigned cStyleSearchLevelThreshold = 10;
876
877 Node* CSSStyleSelector::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
878 {
879     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
880         return 0;
881     if (!parent || !parent->isStyledElement())
882         return 0;
883     StyledElement* p = static_cast<StyledElement*>(parent);
884     if (p->inlineStyleDecl())
885         return 0;
886     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
887         return 0;
888
889     RenderStyle* parentStyle = p->renderStyle();
890     unsigned subcount = 0;
891     Node* thisCousin = p;
892     Node* currentNode = p->previousSibling();
893
894     // Reserve the tries for this level. This effectively makes sure that the algorithm
895     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
896     visitedNodeCount += cStyleSearchThreshold;
897     while (thisCousin) {
898         while (currentNode) {
899             ++subcount;
900             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
901                 // Adjust for unused reserved tries.
902                 visitedNodeCount -= cStyleSearchThreshold - subcount;
903                 return currentNode->lastChild();
904             }
905             if (subcount >= cStyleSearchThreshold)
906                 return 0;
907             currentNode = currentNode->previousSibling();
908         }
909         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
910         thisCousin = currentNode;
911     }
912
913     return 0;
914 }
915
916 bool CSSStyleSelector::matchesRuleSet(RuleSet* ruleSet)
917 {
918     int firstSiblingRule = -1, lastSiblingRule = -1;
919     matchRules(ruleSet, firstSiblingRule, lastSiblingRule, false);
920     if (m_matchedDecls.isEmpty())
921         return false;
922     m_matchedDecls.clear();
923     return true;
924 }
925
926 bool CSSStyleSelector::canShareStyleWithControl(StyledElement* element) const
927 {
928 #if ENABLE(PROGRESS_TAG)
929     if (element->hasTagName(progressTag)) {
930         if (!m_element->hasTagName(progressTag))
931             return false;
932
933         HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
934         HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
935         if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
936             return false;
937
938         return true;
939     }
940 #endif
941
942     HTMLInputElement* thisInputElement = element->toInputElement();
943     HTMLInputElement* otherInputElement = m_element->toInputElement();
944
945     if (!thisInputElement || !otherInputElement)
946         return false;
947
948     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
949         return false;
950     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
951         return false;
952     if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
953         return false;
954     if (thisInputElement->required() != otherInputElement->required())
955         return false;
956
957     if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
958         return false;
959
960     if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
961         return false;
962
963     if (!m_element->document()->containsValidityStyleRules())
964         return false;
965
966     bool willValidate = element->willValidate();
967
968     if (willValidate != m_element->willValidate())
969         return false;
970
971     if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
972         return false;
973
974     if (element->isInRange() != m_element->isInRange())
975         return false;
976
977     if (element->isOutOfRange() != m_element->isOutOfRange())
978         return false;
979
980     return true;
981 }
982
983 bool CSSStyleSelector::canShareStyleWithElement(Node* node) const
984 {
985     if (!node->isStyledElement())
986         return false;
987
988     StyledElement* element = static_cast<StyledElement*>(node);
989     RenderStyle* style = element->renderStyle();
990
991     if (!style)
992         return false;
993     if (style->unique())
994         return false;
995     if (element->tagQName() != m_element->tagQName())
996         return false;
997     if (element->hasClass() != m_element->hasClass())
998         return false;
999     if (element->inlineStyleDecl())
1000         return false;
1001     if (element->hasMappedAttributes() != m_styledElement->hasMappedAttributes())
1002         return false;
1003     if (element->isLink() != m_element->isLink())
1004         return false;
1005     if (style->affectedByUncommonAttributeSelectors())
1006         return false;
1007     if (element->hovered() != m_element->hovered())
1008         return false;
1009     if (element->active() != m_element->active())
1010         return false;
1011     if (element->focused() != m_element->focused())
1012         return false;
1013     if (element->shadowPseudoId() != m_element->shadowPseudoId())
1014         return false;
1015     if (element == element->document()->cssTarget())
1016         return false;
1017     if (m_element == m_element->document()->cssTarget())
1018         return false;
1019     if (element->getAttribute(typeAttr) != m_element->getAttribute(typeAttr))
1020         return false;
1021     if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1022         return false;
1023     if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1024         return false;
1025     if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1026         return false;
1027     if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1028         return false;
1029
1030     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1031         return false;
1032
1033     bool isControl = element->isFormControlElement();
1034
1035     if (isControl != m_element->isFormControlElement())
1036         return false;
1037
1038     if (isControl && !canShareStyleWithControl(element))
1039         return false;
1040
1041     if (style->transitions() || style->animations())
1042         return false;
1043
1044 #if USE(ACCELERATED_COMPOSITING)
1045     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1046     // See comments in RenderObject::setStyle().
1047     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)
1048 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1049         // With proxying, the media elements are backed by a RenderEmbeddedObject.
1050         || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1051 #endif
1052         )
1053         return false;
1054 #endif
1055
1056     if (equalIgnoringCase(element->fastGetAttribute(dirAttr), "auto") || equalIgnoringCase(m_element->fastGetAttribute(dirAttr), "auto"))
1057         return false;
1058
1059     if (element->hasClass() && m_element->getAttribute(classAttr) != element->getAttribute(classAttr))
1060         return false;
1061
1062     if (element->hasMappedAttributes() && !element->attributeMap()->mappedMapsEquivalent(m_styledElement->attributeMap()))
1063         return false;
1064
1065     if (element->isLink() && m_elementLinkState != style->insideLink())
1066         return false;
1067
1068     return true;
1069 }
1070
1071 inline Node* CSSStyleSelector::findSiblingForStyleSharing(Node* node, unsigned& count) const
1072 {
1073     for (; node; node = node->previousSibling()) {
1074         if (!node->isElementNode())
1075             continue;
1076         if (canShareStyleWithElement(node))
1077             break;
1078         if (count++ == cStyleSearchThreshold)
1079             return 0;
1080     }
1081     return node;
1082 }
1083
1084 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1085 {
1086     return parentStyle->childrenAffectedByPositionalRules()
1087         || parentStyle->childrenAffectedByFirstChildRules()
1088         || parentStyle->childrenAffectedByLastChildRules() 
1089         || parentStyle->childrenAffectedByDirectAdjacentRules();
1090 }
1091
1092 RenderStyle* CSSStyleSelector::locateSharedStyle()
1093 {
1094     if (!m_styledElement || !m_parentStyle)
1095         return 0;
1096     // If the element has inline style it is probably unique.
1097     if (m_styledElement->inlineStyleDecl())
1098         return 0;
1099     // Ids stop style sharing if they show up in the stylesheets.
1100     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1101         return 0;
1102     if (parentStylePreventsSharing(m_parentStyle))
1103         return 0;
1104
1105     // Check previous siblings and their cousins.
1106     unsigned count = 0;
1107     unsigned visitedNodeCount = 0;
1108     Node* shareNode = 0;
1109     Node* cousinList = m_styledElement->previousSibling();
1110     while (cousinList) {
1111         shareNode = findSiblingForStyleSharing(cousinList, count);
1112         if (shareNode)
1113             break;
1114         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1115     }
1116
1117     // If we have exhausted all our budget or our cousins.
1118     if (!shareNode)
1119         return 0;
1120
1121     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1122     if (matchesRuleSet(m_features.siblingRules.get()))
1123         return 0;
1124     // Can't share if attribute rules apply.
1125     if (matchesRuleSet(m_features.uncommonAttributeRules.get()))
1126         return 0;
1127     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1128     if (parentStylePreventsSharing(m_parentStyle))
1129         return 0;
1130     return shareNode->renderStyle();
1131 }
1132
1133 void CSSStyleSelector::matchUARules(MatchResult& result)
1134 {
1135     MatchingUARulesScope scope;
1136
1137     // First we match rules from the user agent sheet.
1138     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1139         ? defaultPrintStyle : defaultStyle;
1140     matchRules(userAgentStyleSheet, result.firstUARule, result.lastUARule, false);
1141
1142     // In quirks mode, we match rules from the quirks user agent sheet.
1143     if (!m_checker.strictParsing())
1144         matchRules(defaultQuirksStyle, result.firstUARule, result.lastUARule, false);
1145
1146     // If document uses view source styles (in view source mode or in xml viewer mode), then we match rules from the view source style sheet.
1147     if (m_checker.document()->isViewSource()) {
1148         if (!defaultViewSourceStyle)
1149             loadViewSourceStyle();
1150         matchRules(defaultViewSourceStyle, result.firstUARule, result.lastUARule, false);
1151     }
1152 }
1153
1154 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1155 {
1156     Frame* frame = document->frame();
1157
1158     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1159     documentStyle->setDisplay(BLOCK);
1160     documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1161     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1162     documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1163     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1164
1165     Element* docElement = document->documentElement();
1166     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1167     if (docElementRenderer) {
1168         // Use the direction and writing-mode of the body to set the
1169         // viewport's direction and writing-mode unless the property is set on the document element.
1170         // If there is no body, then use the document element.
1171         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1172         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1173             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1174         else
1175             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1176         if (bodyRenderer && !document->directionSetOnDocumentElement())
1177             documentStyle->setDirection(bodyRenderer->style()->direction());
1178         else
1179             documentStyle->setDirection(docElementRenderer->style()->direction());
1180     }
1181
1182     if (frame) {
1183         if (Page* page = frame->page()) {
1184             const Page::Pagination& pagination = page->pagination();
1185             if (pagination.mode != Page::Pagination::Unpaginated) {
1186                 documentStyle->setColumnAxis(pagination.mode == Page::Pagination::HorizontallyPaginated ? HorizontalColumnAxis : VerticalColumnAxis);
1187                 documentStyle->setColumnGap(pagination.gap);
1188             }
1189         }
1190     }
1191
1192     FontDescription fontDescription;
1193     fontDescription.setUsePrinterFont(document->printing());
1194     if (Settings* settings = document->settings()) {
1195         fontDescription.setRenderingMode(settings->fontRenderingMode());
1196         const AtomicString& stdfont = settings->standardFontFamily();
1197         if (!stdfont.isEmpty()) {
1198             fontDescription.setGenericFamily(FontDescription::StandardFamily);
1199             fontDescription.firstFamily().setFamily(stdfont);
1200             fontDescription.firstFamily().appendFamily(0);
1201         }
1202         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1203         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1204         fontDescription.setSpecifiedSize(size);
1205         bool useSVGZoomRules = document->isSVGDocument();
1206         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1207     }
1208
1209     documentStyle->setFontDescription(fontDescription);
1210     documentStyle->font().update(0);
1211
1212     return documentStyle.release();
1213 }
1214
1215 static inline bool isAtShadowBoundary(Element* element)
1216 {
1217     if (!element)
1218         return false;
1219     ContainerNode* parentNode = element->parentNode();
1220     return parentNode && parentNode->isShadowRoot();
1221 }
1222
1223 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1224 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1225
1226 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
1227 {
1228     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1229     // will vanish if a style recalc happens during loading.
1230     if (allowSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1231         if (!s_styleNotYetAvailable) {
1232             s_styleNotYetAvailable = RenderStyle::create().leakRef();
1233             s_styleNotYetAvailable->setDisplay(NONE);
1234             s_styleNotYetAvailable->font().update(m_fontSelector);
1235         }
1236         element->document()->setHasNodesWithPlaceholderStyle();
1237         return s_styleNotYetAvailable;
1238     }
1239
1240     initElement(element);
1241     initForStyleResolve(element, defaultParent);
1242     if (allowSharing) {
1243         RenderStyle* sharedStyle = locateSharedStyle();
1244         if (sharedStyle)
1245             return sharedStyle;
1246     }
1247
1248     m_style = RenderStyle::create();
1249
1250     if (m_parentStyle)
1251         m_style->inheritFrom(m_parentStyle);
1252     else {
1253         m_parentStyle = style();
1254         // Make sure our fonts are initialized if we don't inherit them from our parent style.
1255         m_style->font().update(0);
1256     }
1257
1258     // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
1259     if (isAtShadowBoundary(element))
1260         m_style->setUserModify(RenderStyle::initialUserModify());
1261
1262     if (element->isLink()) {
1263         m_style->setIsLink(true);
1264         m_style->setInsideLink(m_elementLinkState);
1265     }
1266
1267     ensureDefaultStyleSheetsForElement(element);
1268
1269     MatchResult matchResult;
1270     if (resolveForRootDefault)
1271         matchUARules(matchResult);
1272     else
1273         matchAllRules(matchResult);
1274
1275     applyMatchedDeclarations(matchResult);
1276
1277     // Clean up our style object's display and text decorations (among other fixups).
1278     adjustRenderStyle(style(), m_parentStyle, element);
1279
1280     initElement(0); // Clear out for the next resolve.
1281
1282     // Now return the style.
1283     return m_style.release();
1284 }
1285
1286 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1287 {
1288     if (keyframeRule->style())
1289         addMatchedDeclaration(keyframeRule->style());
1290
1291     ASSERT(!m_style);
1292
1293     // Create the style
1294     m_style = RenderStyle::clone(elementStyle);
1295
1296     m_lineHeightValue = 0;
1297
1298     // We don't need to bother with !important. Since there is only ever one
1299     // decl, there's nothing to override. So just add the first properties.
1300     bool inheritedOnly = false;
1301     if (keyframeRule->style())
1302         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1303
1304     // If our font got dirtied, go ahead and update it now.
1305     updateFont();
1306
1307     // Line-height is set when we are sure we decided on the font-size
1308     if (m_lineHeightValue)
1309         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1310
1311     // Now do rest of the properties.
1312     if (keyframeRule->style())
1313         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1314
1315     // If our font got dirtied by one of the non-essential font props,
1316     // go ahead and update it a second time.
1317     updateFont();
1318
1319     // Start loading images referenced by this style.
1320     loadPendingImages();
1321     
1322 #if ENABLE(CSS_SHADERS)
1323     // Start loading the shaders referenced by this style.
1324     loadPendingShaders();
1325 #endif
1326
1327     // Add all the animating properties to the keyframe.
1328     if (keyframeRule->style()) {
1329         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1330         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1331             int property = (*it).id();
1332             // Timing-function within keyframes is special, because it is not animated; it just
1333             // describes the timing function between this keyframe and the next.
1334             if (property != CSSPropertyWebkitAnimationTimingFunction)
1335                 keyframe.addProperty(property);
1336         }
1337     }
1338
1339     return m_style.release();
1340 }
1341
1342 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1343 {
1344     list.clear();
1345
1346     // Get the keyframesRule for this name
1347     if (!e || list.animationName().isEmpty())
1348         return;
1349
1350     m_keyframesRuleMap.checkConsistency();
1351
1352     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1353         return;
1354
1355     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1356
1357     // Construct and populate the style for each keyframe
1358     for (unsigned i = 0; i < rule->length(); ++i) {
1359         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1360         initElement(e);
1361         initForStyleResolve(e);
1362
1363         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1364
1365         KeyframeValue keyframe(0, 0);
1366         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1367
1368         // Add this keyframe style to all the indicated key times
1369         Vector<float> keys;
1370         keyframeRule->getKeys(keys);
1371         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1372             keyframe.setKey(keys[keyIndex]);
1373             list.insert(keyframe);
1374         }
1375     }
1376
1377     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1378     int initialListSize = list.size();
1379     if (initialListSize > 0 && list[0].key() != 0) {
1380         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1381         keyframeRule->setKeyText("0%");
1382         KeyframeValue keyframe(0, 0);
1383         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1384         list.insert(keyframe);
1385     }
1386
1387     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1388     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1389         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1390         keyframeRule->setKeyText("100%");
1391         KeyframeValue keyframe(1, 0);
1392         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1393         list.insert(keyframe);
1394     }
1395 }
1396
1397 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1398 {
1399     if (!e)
1400         return 0;
1401
1402     initElement(e);
1403
1404     initForStyleResolve(e, parentStyle, pseudo);
1405     m_style = RenderStyle::create();
1406
1407     if (m_parentStyle)
1408         m_style->inheritFrom(m_parentStyle);
1409
1410     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1411     // those rules.
1412
1413     // Check UA, user and author rules.
1414     MatchResult matchResult;
1415     matchUARules(matchResult);
1416
1417     if (m_matchAuthorAndUserStyles) {
1418         matchRules(m_userStyle.get(), matchResult.firstUserRule, matchResult.lastUserRule, false);
1419         matchRules(m_authorStyle.get(), matchResult.firstAuthorRule, matchResult.lastAuthorRule, false);
1420     }
1421
1422     if (m_matchedDecls.isEmpty())
1423         return 0;
1424
1425     m_style->setStyleType(pseudo);
1426
1427     applyMatchedDeclarations(matchResult);
1428
1429     // Clean up our style object's display and text decorations (among other fixups).
1430     adjustRenderStyle(style(), parentStyle, 0);
1431
1432     // Start loading images referenced by this style.
1433     loadPendingImages();
1434
1435 #if ENABLE(CSS_SHADERS)
1436     // Start loading the shaders referenced by this style.
1437     loadPendingShaders();
1438 #endif
1439
1440     // Now return the style.
1441     return m_style.release();
1442 }
1443
1444 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1445 {
1446     initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1447
1448     m_style = RenderStyle::create();
1449     m_style->inheritFrom(m_rootElementStyle);
1450
1451     const bool isLeft = isLeftPage(pageIndex);
1452     const bool isFirst = isFirstPage(pageIndex);
1453     const String page = pageName(pageIndex);
1454     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1455     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1456     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1457     m_lineHeightValue = 0;
1458     bool inheritedOnly = false;
1459     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1460
1461     // If our font got dirtied, go ahead and update it now.
1462     updateFont();
1463
1464     // Line-height is set when we are sure we decided on the font-size.
1465     if (m_lineHeightValue)
1466         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1467
1468     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1469
1470     // Start loading images referenced by this style.
1471     loadPendingImages();
1472
1473 #if ENABLE(CSS_SHADERS)
1474     // Start loading the shaders referenced by this style.
1475     loadPendingShaders();
1476 #endif
1477
1478     // Now return the style.
1479     return m_style.release();
1480 }
1481
1482 static void addIntrinsicMargins(RenderStyle* style)
1483 {
1484     // Intrinsic margin value.
1485     const int intrinsicMargin = 2 * style->effectiveZoom();
1486
1487     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1488     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1489     if (style->width().isIntrinsicOrAuto()) {
1490         if (style->marginLeft().quirk())
1491             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1492         if (style->marginRight().quirk())
1493             style->setMarginRight(Length(intrinsicMargin, Fixed));
1494     }
1495
1496     if (style->height().isAuto()) {
1497         if (style->marginTop().quirk())
1498             style->setMarginTop(Length(intrinsicMargin, Fixed));
1499         if (style->marginBottom().quirk())
1500             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1501     }
1502 }
1503
1504 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1505 {
1506     // Cache our original display.
1507     style->setOriginalDisplay(style->display());
1508
1509     if (style->display() != NONE) {
1510         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1511         // property.
1512         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1513         // these tags to retain their display types.
1514         if (!m_checker.strictParsing() && e) {
1515             if (e->hasTagName(tdTag)) {
1516                 style->setDisplay(TABLE_CELL);
1517                 style->setFloating(NoFloat);
1518             }
1519             else if (e->hasTagName(tableTag))
1520                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1521         }
1522
1523         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1524             if (style->whiteSpace() == KHTML_NOWRAP) {
1525                 // Figure out if we are really nowrapping or if we should just
1526                 // use normal instead.  If the width of the cell is fixed, then
1527                 // we don't actually use NOWRAP.
1528                 if (style->width().isFixed())
1529                     style->setWhiteSpace(NORMAL);
1530                 else
1531                     style->setWhiteSpace(NOWRAP);
1532             }
1533         }
1534
1535         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1536         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1537             style->setTextAlign(TAAUTO);
1538
1539         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1540         // fix a crash where a site tries to position these objects.  They also never honor display.
1541         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1542             style->setPosition(StaticPosition);
1543             style->setDisplay(BLOCK);
1544         }
1545
1546         // Table headers with a text-align of auto will change the text-align to center.
1547         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1548             style->setTextAlign(CENTER);
1549
1550         if (e && e->hasTagName(legendTag))
1551             style->setDisplay(BLOCK);
1552
1553         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1554         // position or float an inline, compact, or run-in.  Cache the original display, since it
1555         // may be needed for positioned elements that have to compute their static normal flow
1556         // positions.  We also force inline-level roots to be block-level.
1557         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1558             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() ||
1559              (e && e->document()->documentElement() == e))) {
1560             if (style->display() == INLINE_TABLE)
1561                 style->setDisplay(TABLE);
1562             else if (style->display() == INLINE_BOX)
1563                 style->setDisplay(BOX);
1564             else if (style->display() == LIST_ITEM) {
1565                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1566                 // but only in quirks mode.
1567                 if (!m_checker.strictParsing() && style->isFloating())
1568                     style->setDisplay(BLOCK);
1569             }
1570             else
1571                 style->setDisplay(BLOCK);
1572         }
1573
1574         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1575         // clear how that should work.
1576         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1577             style->setDisplay(INLINE_BLOCK);
1578
1579         // After performing the display mutation, check table rows.  We do not honor position:relative on
1580         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1581         // on some sites).
1582         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1583              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1584              style->position() == RelativePosition)
1585             style->setPosition(StaticPosition);
1586
1587         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1588         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1589         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1590             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1591             || style->display() == TABLE_CELL)
1592             style->setWritingMode(parentStyle->writingMode());
1593
1594         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1595         // of block-flow to anything other than TopToBottomWritingMode.
1596         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1597         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1598             style->setWritingMode(TopToBottomWritingMode);
1599     }
1600
1601     // Make sure our z-index value is only applied if the object is positioned.
1602     if (style->position() == StaticPosition)
1603         style->setHasAutoZIndex();
1604
1605     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1606     // cases where objects that should be blended as a single unit end up with a non-transparent
1607     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1608     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f
1609         || style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect() || style->hasFilter()))
1610         style->setZIndex(0);
1611
1612     // Textarea considers overflow visible as auto.
1613     if (e && e->hasTagName(textareaTag)) {
1614         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1615         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1616     }
1617
1618     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1619     // tables, inline blocks, inline tables, run-ins, or shadow DOM.
1620     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1621         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
1622         style->setTextDecorationsInEffect(style->textDecoration());
1623     else
1624         style->addToTextDecorationsInEffect(style->textDecoration());
1625
1626     // If either overflow value is not visible, change to auto.
1627     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1628         style->setOverflowY(OMARQUEE);
1629     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1630         style->setOverflowX(OMARQUEE);
1631     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1632         style->setOverflowX(OAUTO);
1633     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1634         style->setOverflowY(OAUTO);
1635
1636     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1637     // FIXME: Eventually table sections will support auto and scroll.
1638     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1639         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1640         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1641             style->setOverflowX(OVISIBLE);
1642         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1643             style->setOverflowY(OVISIBLE);
1644     }
1645
1646     // Menulists should have visible overflow
1647     if (style->appearance() == MenulistPart) {
1648         style->setOverflowX(OVISIBLE);
1649         style->setOverflowY(OVISIBLE);
1650     }
1651
1652     // Cull out any useless layers and also repeat patterns into additional layers.
1653     style->adjustBackgroundLayers();
1654     style->adjustMaskLayers();
1655
1656     // Do the same for animations and transitions.
1657     style->adjustAnimations();
1658     style->adjustTransitions();
1659
1660     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1661     // alter fonts and heights/widths.
1662     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1663         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1664         // so we have to treat all image buttons as though they were explicitly sized.
1665         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1666             addIntrinsicMargins(style);
1667     }
1668
1669     // Let the theme also have a crack at adjusting the style.
1670     if (style->hasAppearance())
1671         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1672
1673     // If we have first-letter pseudo style, do not share this style.
1674     if (style->hasPseudoStyle(FIRST_LETTER))
1675         style->setUnique();
1676
1677 #if ENABLE(SVG)
1678     if (e && e->isSVGElement()) {
1679         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1680         if (style->overflowY() == OSCROLL)
1681             style->setOverflowY(OHIDDEN);
1682         else if (style->overflowY() == OAUTO)
1683             style->setOverflowY(OVISIBLE);
1684
1685         if (style->overflowX() == OSCROLL)
1686             style->setOverflowX(OHIDDEN);
1687         else if (style->overflowX() == OAUTO)
1688             style->setOverflowX(OVISIBLE);
1689
1690         // Only the root <svg> element in an SVG document fragment tree honors css position
1691         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1692             style->setPosition(RenderStyle::initialPosition());
1693     }
1694 #endif
1695 }
1696
1697 bool CSSStyleSelector::checkRegionStyle(Element* e)
1698 {
1699     m_checker.clearHasUnknownPseudoElements();
1700     m_checker.setPseudoStyle(NOPSEUDO);
1701
1702     for (Vector<RefPtr<CSSRegionStyleRule> >::iterator it = m_regionStyleRules.begin(); it != m_regionStyleRules.end(); ++it) {
1703         const CSSSelectorList& regionSelectorList = (*it)->selectorList();
1704         for (CSSSelector* s = regionSelectorList.first(); s; s = regionSelectorList.next(s)) {
1705             if (m_checker.checkSelector(s, e))
1706                 return true;
1707         }
1708     }
1709
1710     return false;
1711 }
1712
1713 void CSSStyleSelector::updateFont()
1714 {
1715     if (!m_fontDirty)
1716         return;
1717
1718     checkForTextSizeAdjust();
1719     checkForGenericFamilyChange(style(), m_parentStyle);
1720     checkForZoomChange(style(), m_parentStyle);
1721     m_style->font().update(m_fontSelector);
1722     m_fontDirty = false;
1723 }
1724
1725 void CSSStyleSelector::cacheBorderAndBackground()
1726 {
1727     m_hasUAAppearance = m_style->hasAppearance();
1728     if (m_hasUAAppearance) {
1729         m_borderData = m_style->border();
1730         m_backgroundData = *m_style->backgroundLayers();
1731         m_backgroundColor = m_style->backgroundColor();
1732     }
1733 }
1734
1735 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
1736 {
1737     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1738 }
1739
1740 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
1741 {
1742     if (!e || !e->document()->haveStylesheetsLoaded())
1743         return 0;
1744
1745     m_checker.setCollectingRulesOnly(true);
1746
1747     initElement(e);
1748     initForStyleResolve(e, 0, pseudoId);
1749
1750     MatchResult dummy;
1751     if (rulesToInclude & UAAndUserCSSRules) {
1752         // First we match rules from the user agent sheet.
1753         matchUARules(dummy);
1754
1755         // Now we check user sheet rules.
1756         if (m_matchAuthorAndUserStyles)
1757             matchRules(m_userStyle.get(), dummy.firstUserRule, dummy.lastUserRule, rulesToInclude & EmptyCSSRules);
1758     }
1759
1760     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1761         m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
1762
1763         // Check the rules in author sheets.
1764         matchRules(m_authorStyle.get(), dummy.firstAuthorRule, dummy.lastAuthorRule, rulesToInclude & EmptyCSSRules);
1765
1766         m_sameOriginOnly = false;
1767     }
1768
1769     m_checker.setCollectingRulesOnly(false);
1770
1771     return m_ruleList.release();
1772 }
1773
1774 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
1775 {
1776     m_dynamicPseudo = NOPSEUDO;
1777     m_checker.clearHasUnknownPseudoElements();
1778
1779     // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
1780     if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
1781         // We know this selector does not include any pseudo elements.
1782         if (m_checker.pseudoStyle() != NOPSEUDO)
1783             return false;
1784         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
1785         // This is limited to HTML only so we don't need to check the namespace.
1786         if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
1787             if (!ruleData.hasMultipartSelector())
1788                 return true;
1789         } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
1790             return false;
1791         if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
1792             return false;
1793         return m_checker.fastCheckSelector(ruleData.selector(), m_element);
1794     }
1795
1796     // Slow path.
1797     SelectorChecker::SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
1798     if (match != SelectorChecker::SelectorMatches)
1799         return false;
1800     if (m_checker.pseudoStyle() != NOPSEUDO && m_checker.pseudoStyle() != m_dynamicPseudo)
1801         return false;
1802     return true;
1803 }
1804
1805 // -----------------------------------------------------------------
1806
1807 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
1808 {
1809     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
1810     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
1811         return false;
1812     if (selector->m_match == CSSSelector::None)
1813         return true;
1814     if (selector->tag() != starAtom)
1815         return false;
1816     if (SelectorChecker::isCommonPseudoClassSelector(selector))
1817         return true;
1818     return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
1819 }
1820
1821 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
1822 {
1823     CSSSelectorList* selectorList = selector->selectorList();
1824     if (!selectorList)
1825         return false;
1826     for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
1827         if (subSelector->isAttributeSelector())
1828             return true;
1829     }
1830     return false;
1831 }
1832
1833 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
1834 {
1835     // These are explicitly tested for equality in canShareStyleWithElement.
1836     return attribute == typeAttr || attribute == readonlyAttr;
1837 }
1838
1839 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
1840 {
1841     while (selector) {
1842         // Allow certain common attributes (used in the default style) in the selectors that match the current element.
1843         if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
1844             return true;
1845         if (selectorListContainsUncommonAttributeSelector(selector))
1846             return true;
1847         if (selector->relation() != CSSSelector::SubSelector)
1848             break;
1849         selector = selector->tagHistory();
1850     };
1851
1852     for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
1853         if (selector->isAttributeSelector())
1854             return true;
1855         if (selectorListContainsUncommonAttributeSelector(selector))
1856             return true;
1857     }
1858     return false;
1859 }
1860
1861 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
1862     : m_rule(rule)
1863     , m_selector(selector)
1864     , m_specificity(selector->specificity())
1865     , m_position(position)
1866     , m_hasFastCheckableSelector(SelectorChecker::isFastCheckableSelector(selector))
1867     , m_hasMultipartSelector(selector->tagHistory())
1868     , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
1869     , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector))
1870     , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector))
1871 {
1872     SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
1873 }
1874
1875 RuleSet::RuleSet()
1876     : m_ruleCount(0)
1877     , m_autoShrinkToFitEnabled(true)
1878 {
1879 }
1880
1881 RuleSet::~RuleSet()
1882 {
1883     deleteAllValues(m_idRules);
1884     deleteAllValues(m_classRules);
1885     deleteAllValues(m_shadowPseudoElementRules);
1886     deleteAllValues(m_tagRules);
1887 }
1888
1889
1890 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1891                               CSSStyleRule* rule, CSSSelector* sel)
1892 {
1893     if (!key) return;
1894     Vector<RuleData>* rules = map.get(key);
1895     if (!rules) {
1896         rules = new Vector<RuleData>;
1897         map.set(key, rules);
1898     }
1899     rules->append(RuleData(rule, sel, m_ruleCount++));
1900 }
1901
1902 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1903 {
1904     if (sel->m_match == CSSSelector::Id) {
1905         addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
1906         return;
1907     }
1908     if (sel->m_match == CSSSelector::Class) {
1909         addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
1910         return;
1911     }
1912     if (sel->isUnknownPseudoElement()) {
1913         addToRuleSet(sel->value().impl(), m_shadowPseudoElementRules, rule, sel);
1914         return;
1915     }
1916     if (SelectorChecker::isCommonPseudoClassSelector(sel)) {
1917         RuleData ruleData(rule, sel, m_ruleCount++);
1918         switch (sel->pseudoType()) {
1919         case CSSSelector::PseudoLink:
1920         case CSSSelector::PseudoVisited:
1921         case CSSSelector::PseudoAnyLink:
1922             m_linkPseudoClassRules.append(ruleData);
1923             return;
1924         case CSSSelector::PseudoFocus:
1925             m_focusPseudoClassRules.append(ruleData);
1926             return;
1927         default:
1928             ASSERT_NOT_REACHED();
1929         }
1930         return;
1931     }
1932     const AtomicString& localName = sel->tag().localName();
1933     if (localName != starAtom) {
1934         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1935         return;
1936     }
1937
1938     m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
1939 }
1940
1941 void RuleSet::addPageRule(CSSPageRule* rule)
1942 {
1943     m_pageRules.append(RuleData(rule, rule->selectorList().first(), m_pageRules.size()));
1944 }
1945
1946 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
1947 {
1948     if (!sheet)
1949         return;
1950
1951     // No media implies "all", but if a media list exists it must
1952     // contain our current medium
1953     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
1954         return; // the style sheet doesn't apply
1955
1956     int len = sheet->length();
1957
1958     for (int i = 0; i < len; i++) {
1959         CSSRule* rule = sheet->item(i);
1960         if (rule->isStyleRule())
1961             addStyleRule(static_cast<CSSStyleRule*>(rule));
1962         else if (rule->isPageRule())
1963             addPageRule(static_cast<CSSPageRule*>(rule));
1964         else if (rule->isImportRule()) {
1965             CSSImportRule* import = static_cast<CSSImportRule*>(rule);
1966             if (!import->media() || medium.eval(import->media(), styleSelector))
1967                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
1968         }
1969         else if (rule->isMediaRule()) {
1970             CSSMediaRule* r = static_cast<CSSMediaRule*>(rule);
1971             CSSRuleList* rules = r->cssRules();
1972
1973             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
1974                 // Traverse child elements of the @media rule.
1975                 for (unsigned j = 0; j < rules->length(); j++) {
1976                     CSSRule *childItem = rules->item(j);
1977                     if (childItem->isStyleRule())
1978                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
1979                     else if (childItem->isPageRule())
1980                         addPageRule(static_cast<CSSPageRule*>(childItem));
1981                     else if (childItem->isFontFaceRule() && styleSelector) {
1982                         // Add this font face to our set.
1983                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
1984                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
1985                     } else if (childItem->isKeyframesRule() && styleSelector) {
1986                         // Add this keyframe rule to our set.
1987                         styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
1988                     }
1989                 }   // for rules
1990             }   // if rules
1991         } else if (rule->isFontFaceRule() && styleSelector) {
1992             // Add this font face to our set.
1993             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
1994             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
1995         } else if (rule->isKeyframesRule())
1996             styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule));
1997         else if (rule->isRegionStyleRule() && styleSelector)
1998             styleSelector->addRegionStyleRule(static_cast<CSSRegionStyleRule*>(rule));
1999     }
2000     if (m_autoShrinkToFitEnabled)
2001         shrinkToFit();
2002 }
2003
2004 void RuleSet::addStyleRule(CSSStyleRule* rule)
2005 {
2006     for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2007         addRule(rule, s);
2008 }
2009
2010 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
2011 {
2012     if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
2013         features.idsInRules.add(selector->value().impl());
2014     if (selector->isAttributeSelector())
2015         features.attrsInRules.add(selector->attribute().localName().impl());
2016     switch (selector->pseudoType()) {
2017     case CSSSelector::PseudoFirstLine:
2018         features.usesFirstLineRules = true;
2019         break;
2020     case CSSSelector::PseudoBefore:
2021     case CSSSelector::PseudoAfter:
2022         features.usesBeforeAfterRules = true;
2023         break;
2024     case CSSSelector::PseudoLink:
2025     case CSSSelector::PseudoVisited:
2026         features.usesLinkRules = true;
2027         break;
2028     default:
2029         break;
2030     }
2031 }
2032
2033 static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules)
2034 {
2035     unsigned size = rules.size();
2036     for (unsigned i = 0; i < size; ++i) {
2037         const RuleData& ruleData = rules[i];
2038         bool foundSiblingSelector = false;
2039         for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
2040             collectFeaturesFromSelector(features, selector);
2041
2042             if (CSSSelectorList* selectorList = selector->selectorList()) {
2043                 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2044                     if (selector->isSiblingSelector())
2045                         foundSiblingSelector = true;
2046                     collectFeaturesFromSelector(features, subSelector);
2047                 }
2048             } else if (selector->isSiblingSelector())
2049                 foundSiblingSelector = true;
2050         }
2051         if (foundSiblingSelector) {
2052             if (!features.siblingRules)
2053                 features.siblingRules = adoptPtr(new RuleSet);
2054             features.siblingRules->addRule(ruleData.rule(), ruleData.selector());
2055         }
2056         if (ruleData.containsUncommonAttributeSelector()) {
2057             if (!features.uncommonAttributeRules)
2058                 features.uncommonAttributeRules = adoptPtr(new RuleSet);
2059             features.uncommonAttributeRules->addRule(ruleData.rule(), ruleData.selector());
2060         }
2061     }
2062 }
2063
2064 void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const
2065 {
2066     AtomRuleMap::const_iterator end = m_idRules.end();
2067     for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
2068         collectFeaturesFromList(features, *it->second);
2069     end = m_classRules.end();
2070     for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
2071         collectFeaturesFromList(features, *it->second);
2072     end = m_tagRules.end();
2073     for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
2074         collectFeaturesFromList(features, *it->second);
2075     end = m_shadowPseudoElementRules.end();
2076     for (AtomRuleMap::const_iterator it = m_shadowPseudoElementRules.begin(); it != end; ++it)
2077         collectFeaturesFromList(features, *it->second);
2078     collectFeaturesFromList(features, m_linkPseudoClassRules);
2079     collectFeaturesFromList(features, m_focusPseudoClassRules);
2080     collectFeaturesFromList(features, m_universalRules);
2081 }
2082
2083 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
2084 {
2085     RuleSet::AtomRuleMap::iterator end = map.end();
2086     for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
2087         it->second->shrinkToFit();
2088 }
2089
2090 void RuleSet::shrinkToFit()
2091 {
2092     shrinkMapVectorsToFit(m_idRules);
2093     shrinkMapVectorsToFit(m_classRules);
2094     shrinkMapVectorsToFit(m_tagRules);
2095     shrinkMapVectorsToFit(m_shadowPseudoElementRules);
2096     m_linkPseudoClassRules.shrinkToFit();
2097     m_focusPseudoClassRules.shrinkToFit();
2098     m_universalRules.shrinkToFit();
2099     m_pageRules.shrinkToFit();
2100 }
2101
2102 // -------------------------------------------------------------------------------------
2103 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2104
2105 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
2106 {
2107     // This function is tolerant of a null style value. The only place style is used is in
2108     // length measurements, like 'ems' and 'px'. And in those cases style is only used
2109     // when the units are EMS or EXS. So we will just fail in those cases.
2110     Length l;
2111     if (!primitiveValue) {
2112         if (ok)
2113             *ok = false;
2114     } else {
2115         int type = primitiveValue->primitiveType();
2116
2117         if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
2118             if (ok)
2119                 *ok = false;
2120         } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2121             if (toFloat)
2122                 l = Length(primitiveValue->computeLength<double>(style, rootStyle, multiplier), Fixed);
2123             else
2124                 l = primitiveValue->computeLength<Length>(style, rootStyle, multiplier);
2125         }
2126         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2127             l = Length(primitiveValue->getDoubleValue(), Percent);
2128         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2129             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2130         else if (ok)
2131             *ok = false;
2132     }
2133     return l;
2134 }
2135
2136 static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2137 {
2138     return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
2139 }
2140
2141 static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2142 {
2143     return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
2144 }
2145
2146 template <bool applyFirst>
2147 void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant, bool& inheritedOnly)
2148 {
2149     CSSMutableStyleDeclaration::const_iterator end = styleDeclaration->end();
2150     for (CSSMutableStyleDeclaration::const_iterator it = styleDeclaration->begin(); it != end; ++it) {
2151         const CSSProperty& current = *it;
2152         if (isImportant != current.isImportant())
2153             continue;
2154         if (inheritedOnly && !current.isInherited()) {
2155             if (!current.value()->isInheritedValue())
2156                 continue;
2157             // If the property value is explicitly inherited, we need to apply further non-inherited properties
2158             // as they might override the value inherited here. This is really per-property but that is
2159             // probably not worth optimizing for.
2160             inheritedOnly = false;
2161         }
2162         int property = current.id();
2163         if (applyFirst) {
2164             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2165             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 16, CSS_zoom_is_end_of_first_prop_range);
2166             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2167             // give special priority to font-xxx, color properties, etc
2168             if (property > CSSPropertyLineHeight)
2169                 continue;
2170             // we apply line-height later
2171             if (property == CSSPropertyLineHeight) {
2172                 m_lineHeightValue = current.value();
2173                 continue;
2174             }
2175             applyProperty(current.id(), current.value());
2176             continue;
2177         }
2178         if (property > CSSPropertyLineHeight)
2179             applyProperty(current.id(), current.value());
2180     }
2181 }
2182
2183 template <bool applyFirst>
2184 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex, bool& inheritedOnly)
2185 {
2186     if (startIndex == -1)
2187         return;
2188
2189     if (m_style->insideLink() != NotInsideLink) {
2190         for (int i = startIndex; i <= endIndex; ++i) {
2191             CSSMutableStyleDeclaration* styleDeclaration = m_matchedDecls[i].styleDeclaration;
2192             unsigned linkMatchType = m_matchedDecls[i].linkMatchType;
2193             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2194             m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2195             m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2196
2197             applyDeclaration<applyFirst>(styleDeclaration, isImportant, inheritedOnly);
2198         }
2199         m_applyPropertyToRegularStyle = true;
2200         m_applyPropertyToVisitedLinkStyle = false;
2201         return;
2202     }
2203     for (int i = startIndex; i <= endIndex; ++i)
2204         applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration, isImportant, inheritedOnly);
2205 }
2206
2207 unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* declarations, unsigned size)
2208 {
2209     return StringHasher::hashMemory(declarations, sizeof(MatchedStyleDeclaration) * size);
2210 }
2211
2212 bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2213 {
2214     return a.firstUARule == b.firstUARule
2215         && a.lastUARule == b.lastUARule
2216         && a.firstAuthorRule == b.firstAuthorRule
2217         && a.lastAuthorRule == b.lastAuthorRule
2218         && a.firstUserRule == b.firstUserRule
2219         && a.lastUserRule == b.lastUserRule
2220         && a.isCacheable == b.isCacheable;
2221 }
2222
2223 bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2224 {
2225     return !(a == b);
2226 }
2227
2228 bool operator==(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2229 {
2230     return a.styleDeclaration == b.styleDeclaration && a.linkMatchType == b.linkMatchType;
2231 }
2232
2233 bool operator!=(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2234 {
2235     return !(a == b);
2236 }
2237
2238 const RenderStyle* CSSStyleSelector::findFromMatchedDeclarationCache(unsigned hash, const MatchResult& matchResult)
2239 {
2240     ASSERT(hash);
2241
2242     MatchedStyleDeclarationCache::iterator it = m_matchStyleDeclarationCache.find(hash);
2243     if (it == m_matchStyleDeclarationCache.end())
2244         return 0;
2245     MatchedStyleDeclarationCacheItem& cacheItem = it->second;
2246     ASSERT(cacheItem.matchResult.isCacheable);
2247     
2248     size_t size = m_matchedDecls.size();
2249     if (size != cacheItem.matchedStyleDeclarations.size())
2250         return 0;
2251     for (size_t i = 0; i < size; ++i) {
2252         if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i])
2253             return 0;
2254     }
2255     if (cacheItem.matchResult != matchResult)
2256         return 0;
2257     return cacheItem.renderStyle.get();
2258 }
2259
2260 void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, unsigned hash, const MatchResult& matchResult)
2261 {
2262     ASSERT(hash);
2263     MatchedStyleDeclarationCacheItem cacheItem;
2264     cacheItem.matchedStyleDeclarations.append(m_matchedDecls);
2265     cacheItem.matchResult = matchResult;
2266     // Note that we don't cache the original RenderStyle instance. It may be further modified.
2267     // The RenderStyle in the cache is really just a holder for the non-inherited substructures and never used as-is.
2268     cacheItem.renderStyle = RenderStyle::clone(style);
2269     m_matchStyleDeclarationCache.add(hash, cacheItem);
2270 }
2271
2272 static bool isCacheableInMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle)
2273 {
2274     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2275         return false;
2276     if (style->hasAppearance())
2277         return false;
2278     if (style->zoom() != RenderStyle::initialZoom())
2279         return false;
2280     return true;
2281 }
2282
2283 void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult)
2284 {
2285     unsigned cacheHash = matchResult.isCacheable ? computeDeclarationHash(m_matchedDecls.data(), m_matchedDecls.size()) : 0;
2286     bool applyInheritedOnly = false;
2287     const RenderStyle* cachedStyle = 0;
2288     if (cacheHash && (cachedStyle = findFromMatchedDeclarationCache(cacheHash, matchResult))) {
2289         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
2290         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
2291         // element context. This is fast and saves memory by reusing the style data structures.
2292         m_style->copyNonInheritedFrom(cachedStyle);
2293         applyInheritedOnly = true; 
2294     }
2295     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
2296     // high-priority properties first, i.e., those properties that other properties depend on.
2297     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
2298     // and (4) normal important.
2299     m_lineHeightValue = 0;
2300     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, applyInheritedOnly);
2301     applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2302     applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2303     applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2304
2305     if (cachedStyle && cachedStyle->effectiveZoom() != m_style->effectiveZoom()) {
2306         m_fontDirty = true;
2307         applyInheritedOnly = false;
2308     }
2309
2310     // If our font got dirtied, go ahead and update it now.
2311     updateFont();
2312
2313     // Line-height is set when we are sure we decided on the font-size.
2314     if (m_lineHeightValue)
2315         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2316
2317     // Many properties depend on the font. If it changes we just apply all properties.
2318     if (cachedStyle && cachedStyle->fontDescription() != m_style->fontDescription())
2319         applyInheritedOnly = false;
2320
2321     // Now do the normal priority UA properties.
2322     applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2323     
2324     // Cache our border and background so that we can examine them later.
2325     cacheBorderAndBackground();
2326     
2327     // Now do the author and user normal priority properties and all the !important properties.
2328     applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly);
2329     applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2330     applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2331     applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2332     
2333     loadPendingImages();
2334     
2335 #if ENABLE(CSS_SHADERS)
2336     loadPendingShaders();
2337 #endif
2338     
2339     ASSERT(!m_fontDirty);
2340     
2341     if (cachedStyle || !cacheHash)
2342         return;
2343     if (!isCacheableInMatchedDeclarationCache(m_style.get(), m_parentStyle))
2344         return;
2345     addToMatchedDeclarationCache(m_style.get(), cacheHash, matchResult);
2346 }
2347
2348 void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2349 {
2350     m_matchedRules.clear();
2351
2352     if (!rules)
2353         return;
2354
2355     matchPageRulesForList(rules->pageRules(), isLeftPage, isFirstPage, pageName);
2356
2357     // If we didn't match any rules, we're done.
2358     if (m_matchedRules.isEmpty())
2359         return;
2360
2361     // Sort the set of matched rules.
2362     sortMatchedRules();
2363
2364     // Now transfer the set of matched rules over to our list of decls.
2365     for (unsigned i = 0; i < m_matchedRules.size(); i++)
2366         addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
2367 }
2368
2369 void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2370 {
2371     if (!rules)
2372         return;
2373
2374     unsigned size = rules->size();
2375     for (unsigned i = 0; i < size; ++i) {
2376         const RuleData& ruleData = rules->at(i);
2377         CSSStyleRule* rule = ruleData.rule();
2378         const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
2379         if (selectorLocalName != starAtom && selectorLocalName != pageName)
2380             continue;
2381         CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
2382         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2383             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2384             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2385             continue;
2386
2387         // If the rule has no properties to apply, then ignore it.
2388         CSSMutableStyleDeclaration* decl = rule->declaration();
2389         if (!decl || !decl->length())
2390             continue;
2391
2392         // Add this rule to our list of matched rules.
2393         addMatchedRule(&ruleData);
2394     }
2395 }
2396
2397 bool CSSStyleSelector::isLeftPage(int pageIndex) const
2398 {
2399     bool isFirstPageLeft = false;
2400     if (!m_rootElementStyle->isLeftToRightDirection())
2401         isFirstPageLeft = true;
2402
2403     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
2404 }
2405
2406 bool CSSStyleSelector::isFirstPage(int pageIndex) const
2407 {
2408     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
2409     return (!pageIndex);
2410 }
2411
2412 String CSSStyleSelector::pageName(int /* pageIndex */) const
2413 {
2414     // FIXME: Implement page index to page name mapping.
2415     return "";
2416 }
2417
2418 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue* value, RenderStyle* style)
2419 {
2420     initElement(0);
2421     initForStyleResolve(0, style);
2422     m_style = style;
2423     applyPropertyToCurrentStyle(id, value);
2424 }
2425
2426 void CSSStyleSelector::applyPropertyToCurrentStyle(int id, CSSValue* value)
2427 {
2428     if (value)
2429         applyProperty(id, value);
2430 }
2431
2432 inline bool isValidVisitedLinkProperty(int id)
2433 {
2434     switch(static_cast<CSSPropertyID>(id)) {
2435         case CSSPropertyBackgroundColor:
2436         case CSSPropertyBorderLeftColor:
2437         case CSSPropertyBorderRightColor:
2438         case CSSPropertyBorderTopColor:
2439         case CSSPropertyBorderBottomColor:
2440         case CSSPropertyColor:
2441         case CSSPropertyOutlineColor:
2442         case CSSPropertyWebkitColumnRuleColor:
2443         case CSSPropertyWebkitTextEmphasisColor:
2444         case CSSPropertyWebkitTextFillColor:
2445         case CSSPropertyWebkitTextStrokeColor:
2446         // Also allow shorthands so that inherit/initial still work.
2447         case CSSPropertyBackground:
2448         case CSSPropertyBorderLeft:
2449         case CSSPropertyBorderRight:
2450         case CSSPropertyBorderTop:
2451         case CSSPropertyBorderBottom:
2452         case CSSPropertyOutline:
2453         case CSSPropertyWebkitColumnRule:
2454 #if ENABLE(SVG)
2455         case CSSPropertyFill:
2456         case CSSPropertyStroke:
2457 #endif
2458             return true;
2459         default:
2460             break;
2461     }
2462
2463     return false;
2464 }
2465
2466 class SVGDisplayPropertyGuard {
2467     WTF_MAKE_NONCOPYABLE(SVGDisplayPropertyGuard);
2468 public:
2469     SVGDisplayPropertyGuard(Element*, RenderStyle*);
2470     ~SVGDisplayPropertyGuard();
2471 private:
2472 #if ENABLE(SVG)
2473     RenderStyle* m_style;
2474     EDisplay m_originalDisplayPropertyValue;
2475 #endif
2476 };
2477
2478 #if !ENABLE(SVG)
2479 inline SVGDisplayPropertyGuard::SVGDisplayPropertyGuard(Element*, RenderStyle*)
2480 {
2481 }
2482
2483 inline SVGDisplayPropertyGuard::~SVGDisplayPropertyGuard()
2484 {
2485 }
2486 #else
2487 static inline bool isAcceptableForSVGElement(EDisplay displayPropertyValue)
2488 {
2489     return displayPropertyValue == INLINE || displayPropertyValue == BLOCK || displayPropertyValue == NONE;
2490 }
2491
2492 inline SVGDisplayPropertyGuard::SVGDisplayPropertyGuard(Element* element, RenderStyle* style)
2493 {
2494     if (!(element && element->isSVGElement() && style->styleType() == NOPSEUDO)) {
2495         m_originalDisplayPropertyValue = NONE;
2496         m_style = 0;
2497         return;
2498     }
2499     m_style = style;
2500     m_originalDisplayPropertyValue = style->display();
2501     ASSERT(isAcceptableForSVGElement(m_originalDisplayPropertyValue));
2502 }
2503
2504 inline SVGDisplayPropertyGuard::~SVGDisplayPropertyGuard()
2505 {
2506     if (!m_style || isAcceptableForSVGElement(m_style->display()))
2507         return;
2508     m_style->setDisplay(m_originalDisplayPropertyValue);
2509 }
2510 #endif
2511
2512
2513 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2514 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2515 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2516 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2517 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2518 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
2519 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
2520 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
2521 bool CSSStyleSelector::useSVGZoomRules()
2522 {
2523     return m_element && m_element->isSVGElement();
2524 }
2525
2526 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
2527 {
2528     bool isInherit = m_parentNode && value->isInheritedValue();
2529     bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
2530
2531     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2532
2533     if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2534         // Limit the properties that can be applied to only the ones honored by :visited.
2535         return;
2536     }
2537
2538     CSSPropertyID property = static_cast<CSSPropertyID>(id);
2539
2540     if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(property))
2541         m_parentStyle->setHasExplicitlyInheritedProperties();
2542
2543     // check lookup table for implementations and use when available
2544     const PropertyHandler& handler = m_applyProperty.propertyHandler(property);
2545     if (handler.isValid()) {
2546         if (isInherit)
2547             handler.applyInheritValue(this);
2548         else if (isInitial)
2549             handler.applyInitialValue(this);
2550         else
2551             handler.applyValue(this, value);
2552         return;
2553     }
2554
2555     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
2556
2557     float zoomFactor = m_style->effectiveZoom();
2558
2559     // What follows is a list that maps the CSS properties into their corresponding front-end
2560     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
2561     // are only hit when mapping "inherit" or "initial" into front-end values.
2562     switch (property) {
2563 // ident only properties
2564     case CSSPropertyBorderCollapse:
2565         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderCollapse, BorderCollapse)
2566         return;
2567     case CSSPropertyCaptionSide:
2568         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
2569         return;
2570     case CSSPropertyClear:
2571         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
2572         return;
2573     case CSSPropertyDisplay: {
2574         SVGDisplayPropertyGuard guard(m_element, m_style.get());
2575         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display)
2576         return;
2577     }
2578     case CSSPropertyEmptyCells:
2579         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
2580         return;
2581     case CSSPropertyFloat:
2582         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
2583         return;
2584     case CSSPropertyPageBreakBefore:
2585         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2586         return;
2587     case CSSPropertyPageBreakAfter:
2588         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2589         return;
2590     case CSSPropertyPageBreakInside:
2591         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2592         return;
2593     case CSSPropertyPosition:
2594         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
2595         return;
2596     case CSSPropertyTableLayout:
2597         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(tableLayout, TableLayout)
2598         return;
2599     case CSSPropertyUnicodeBidi:
2600         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
2601         return;
2602     case CSSPropertyTextTransform:
2603         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
2604         return;
2605     case CSSPropertyVisibility:
2606         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
2607         return;
2608     case CSSPropertyWhiteSpace:
2609         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
2610         return;
2611 // uri || inherit
2612     case CSSPropertyBorderImageSource:
2613     {
2614         HANDLE_INHERIT_AND_INITIAL(borderImageSource, BorderImageSource)
2615         m_style->setBorderImageSource(styleImage(CSSPropertyBorderImageSource, value));
2616         return;
2617     }
2618     case CSSPropertyWebkitMaskBoxImageSource:
2619     {
2620         HANDLE_INHERIT_AND_INITIAL(maskBoxImageSource, MaskBoxImageSource)
2621         m_style->setMaskBoxImageSource(styleImage(CSSPropertyWebkitMaskBoxImageSource, value));
2622         return;
2623     }
2624     case CSSPropertyWordBreak:
2625         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
2626         return;
2627     case CSSPropertyWordWrap:
2628         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
2629         return;
2630     case CSSPropertyWebkitNbspMode:
2631         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
2632         return;
2633     case CSSPropertyWebkitLineBreak:
2634         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
2635         return;
2636     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2637         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2638         return;
2639
2640     case CSSPropertyResize:
2641     {
2642         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2643
2644         if (!primitiveValue->getIdent())
2645             return;
2646
2647         EResize r = RESIZE_NONE;
2648         if (primitiveValue->getIdent() == CSSValueAuto) {
2649             if (Settings* settings = m_checker.document()->settings())
2650                 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2651         } else
2652             r = *primitiveValue;
2653
2654         m_style->setResize(r);
2655         return;
2656     }
2657     case CSSPropertyVerticalAlign:
2658     {
2659         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2660         if (!primitiveValue)
2661             return;
2662
2663         if (primitiveValue->getIdent()) {
2664           m_style->setVerticalAlign(*primitiveValue);
2665           return;
2666         }
2667
2668         int type = primitiveValue->primitiveType();
2669         Length length;
2670         if (CSSPrimitiveValue::isUnitTypeLength(type))
2671             length = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
2672         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2673             length = Length(primitiveValue->getDoubleValue(), Percent);
2674
2675         m_style->setVerticalAlign(LENGTH);
2676         m_style->setVerticalAlignLength(length);
2677         return;
2678     }
2679     case CSSPropertyFontSize:
2680     {
2681         FontDescription fontDescription = m_style->fontDescription();
2682         fontDescription.setKeywordSize(0);
2683         float oldSize = 0;
2684         float size = 0;
2685
2686         bool parentIsAbsoluteSize = false;
2687         if (m_parentNode) {
2688             oldSize = m_parentStyle->fontDescription().specifiedSize();
2689             parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
2690         }
2691
2692         if (isInherit) {
2693             size = oldSize;
2694             if (m_parentNode)
2695                 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
2696         } else if (isInitial) {
2697             size = fontSizeForKeyword(m_checker.document(), CSSValueMedium, fontDescription.useFixedDefaultSize());
2698             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
2699         } else if (primitiveValue->getIdent()) {
2700             // Keywords are being used.
2701             switch (primitiveValue->getIdent()) {
2702                 case CSSValueXxSmall:
2703                 case CSSValueXSmall:
2704                 case CSSValueSmall:
2705                 case CSSValueMedium:
2706                 case CSSValueLarge:
2707                 case CSSValueXLarge:
2708                 case CSSValueXxLarge:
2709                 case CSSValueWebkitXxxLarge:
2710                     size = fontSizeForKeyword(m_checker.document(), primitiveValue->getIdent(), fontDescription.useFixedDefaultSize());
2711                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
2712                     break;
2713                 case CSSValueLarger:
2714                     size = largerFontSize(oldSize, m_checker.document()->inQuirksMode());
2715                     break;
2716                 case CSSValueSmaller:
2717                     size = smallerFontSize(oldSize, m_checker.document()->inQuirksMode());
2718                     break;
2719                 default:
2720                     return;
2721             }
2722
2723             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize
2724                                               && (primitiveValue->getIdent() == CSSValueLarger
2725                                                   || primitiveValue->getIdent() == CSSValueSmaller));
2726         } else {
2727             int type = primitiveValue->primitiveType();
2728             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize
2729                                               || (type != CSSPrimitiveValue::CSS_PERCENTAGE
2730                                                   && type != CSSPrimitiveValue::CSS_EMS
2731                                                   && type != CSSPrimitiveValue::CSS_EXS
2732                                                   && type != CSSPrimitiveValue::CSS_REMS));
2733             if (CSSPrimitiveValue::isUnitTypeLength(type))
2734                 size = primitiveValue->computeLength<float>(m_parentStyle, m_rootElementStyle, 1.0, true);
2735             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2736                 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
2737             else
2738                 return;
2739         }
2740
2741         if (size < 0)
2742             return;
2743
2744         setFontSize(fontDescription, size);
2745         setFontDescription(fontDescription);
2746         return;
2747     }
2748
2749     case CSSPropertyWidows:
2750         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(widows, Widows)
2751         return;
2752     case CSSPropertyOrphans:
2753         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(orphans, Orphans)
2754         return;
2755 // length, percent, number
2756     case CSSPropertyLineHeight:
2757     {
2758         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
2759         if (!primitiveValue)
2760             return;
2761         Length lineHeight;
2762         int type = primitiveValue->primitiveType();
2763         if (primitiveValue->getIdent() == CSSValueNormal)
2764             lineHeight = Length(-100.0, Percent);
2765         else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2766             double multiplier = zoomFactor;
2767             if (m_style->textSizeAdjust()) {
2768                 if (Frame* frame = m_checker.document()->frame())
2769                     multiplier *= frame->textZoomFactor();
2770             }
2771             lineHeight = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, multiplier);
2772         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2773             lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
2774         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2775             lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2776         else
2777             return;
2778         m_style->setLineHeight(lineHeight);
2779         return;
2780     }
2781
2782 // string
2783     case CSSPropertyTextAlign:
2784     {
2785         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
2786         if (!primitiveValue)
2787             return;
2788         if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) {
2789             if (m_parentStyle->textAlign() == TASTART)
2790                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT);
2791             else if (m_parentStyle->textAlign() == TAEND)
2792                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT);
2793             else
2794                 m_style->setTextAlign(m_parentStyle->textAlign());
2795             return;
2796         }
2797         m_style->setTextAlign(*primitiveValue);
2798         return;
2799     }
2800
2801 // rect
2802     case CSSPropertyClip:
2803     {
2804         Length top;
2805         Length right;
2806         Length bottom;
2807         Length left;
2808         bool hasClip = true;
2809         if (isInherit) {
2810             if (m_parentStyle->hasClip()) {
2811                 top = m_parentStyle->clipTop();
2812                 right = m_parentStyle->clipRight();
2813                 bottom = m_parentStyle->clipBottom();
2814                 left = m_parentStyle->clipLeft();
2815             } else {
2816                 hasClip = false;
2817                 top = right = bottom = left = Length();
2818             }
2819         } else if (isInitial) {
2820             hasClip = false;
2821             top = right = bottom = left = Length();
2822         } else if (!primitiveValue) {
2823             return;
2824         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
2825             Rect* rect = primitiveValue->getRectValue();
2826             if (!rect)
2827                 return;
2828             top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
2829             right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
2830             bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
2831             left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
2832         } else if (primitiveValue->getIdent() != CSSValueAuto) {
2833             return;
2834         }
2835         m_style->setClip(top, right, bottom, left);
2836         m_style->setHasClip(hasClip);
2837
2838         // rect, ident
2839         return;
2840     }
2841
2842 // lists
2843     case CSSPropertyContent:
2844         // list of string, uri, counter, attr, i
2845     {
2846         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
2847         // note is a reminder that eventually "inherit" needs to be supported.
2848
2849         if (isInitial) {
2850             m_style->clearContent();
2851             return;
2852         }
2853
2854         if (!value->isValueList())
2855             return;
2856
2857         bool didSet = false;
2858         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2859             CSSValue* item = i.value();
2860             if (item->isImageGeneratorValue()) {
2861                 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
2862                 didSet = true;
2863             }
2864
2865             if (!item->isPrimitiveValue())
2866                 continue;
2867
2868             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2869             switch (contentValue->primitiveType()) {
2870             case CSSPrimitiveValue::CSS_STRING:
2871                 m_style->setContent(contentValue->getStringValue().impl(), didSet);
2872                 didSet = true;
2873                 break;
2874             case CSSPrimitiveValue::CSS_ATTR: {
2875                 // FIXME: Can a namespace be specified for an attr(foo)?
2876                 if (m_style->styleType() == NOPSEUDO)
2877                     m_style->setUnique();
2878                 else
2879                     m_parentStyle->setUnique();
2880                 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2881                 const AtomicString& value = m_element->getAttribute(attr);
2882                 m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2883                 didSet = true;
2884                 // register the fact that the attribute value affects the style
2885                 m_features.attrsInRules.add(attr.localName().impl());
2886                 break;
2887             }
2888             case CSSPrimitiveValue::CSS_URI: {
2889                 if (!contentValue->isImageValue())
2890                     break;
2891                 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
2892                 didSet = true;
2893                 break;
2894             }
2895             case CSSPrimitiveValue::CSS_COUNTER: {
2896                 Counter* counterValue = contentValue->getCounterValue();
2897                 EListStyleType listStyleType = NoneListStyle;
2898                 int listStyleIdent = counterValue->listStyleIdent();
2899                 if (listStyleIdent != CSSValueNone)
2900                     listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2901                 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
2902                 m_style->setContent(counter.release(), didSet);
2903                 didSet = true;
2904                 break;
2905             }
2906             case CSSPrimitiveValue::CSS_IDENT:
2907                 switch (contentValue->getIdent()) {
2908                 case CSSValueOpenQuote:
2909                     m_style->setContent(OPEN_QUOTE, didSet);
2910                     didSet = true;
2911                     break;
2912                 case CSSValueCloseQuote:
2913                     m_style->setContent(CLOSE_QUOTE, didSet);
2914                     didSet = true;
2915                     break;
2916                 case CSSValueNoOpenQuote:
2917                     m_style->setContent(NO_OPEN_QUOTE, didSet);
2918                     didSet = true;
2919                     break;
2920                 case CSSValueNoCloseQuote:
2921                     m_style->setContent(NO_CLOSE_QUOTE, didSet);
2922                     didSet = true;
2923                     break;
2924                 default:
2925                     // normal and none do not have any effect.
2926                     {}
2927                 }
2928             }
2929         }
2930         if (!didSet)
2931             m_style->clearContent();
2932         return;
2933     }
2934     case CSSPropertyQuotes:
2935         if (isInherit) {
2936             if (m_parentStyle)
2937                 m_style->setQuotes(m_parentStyle->quotes());
2938             return;
2939         }
2940         if (isInitial) {
2941             m_style->setQuotes(0);
2942             return;
2943         }
2944         if (value->isValueList()) {
2945             CSSValueList* list = static_cast<CSSValueList*>(value);
2946             QuotesData* data = QuotesData::create(list->length());
2947             if (!data)
2948                 return; // Out of memory
2949             String* quotes = data->data();
2950             for (CSSValueListIterator i = list; i.hasMore(); i.advance()) {
2951                 CSSValue* item = i.value();
2952                 ASSERT(item->isPrimitiveValue());
2953                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2954                 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
2955                 quotes[i.index()] = primitiveValue->getStringValue();
2956             }
2957             m_style->setQuotes(adoptRef(data));
2958         } else if (primitiveValue) {
2959             ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
2960             if (primitiveValue->getIdent() == CSSValueNone)
2961                 m_style->setQuotes(adoptRef(QuotesData::create(0)));
2962         }
2963         return;
2964     case CSSPropertyFontFamily: {
2965         // list of strings and ids
2966         if (isInherit) {
2967             FontDescription parentFontDescription = m_parentStyle->fontDescription();
2968             FontDescription fontDescription = m_style->fontDescription();
2969             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
2970             fontDescription.setFamily(parentFontDescription.firstFamily());
2971             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
2972             setFontDescription(fontDescription);
2973             return;
2974         } else if (isInitial) {
2975             FontDescription initialDesc = FontDescription();
2976             FontDescription fontDescription = m_style->fontDescription();
2977             // We need to adjust the size to account for the generic family change from monospace
2978             // to non-monospace.
2979             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
2980                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
2981             fontDescription.setGenericFamily(initialDesc.genericFamily());
2982             if (!initialDesc.firstFamily().familyIsEmpty())
2983                 fontDescription.setFamily(initialDesc.firstFamily());
2984             setFontDescription(fontDescription);
2985             return;
2986         }
2987
2988         if (!value->isValueList())
2989             return;
2990         FontDescription fontDescription = m_style->fontDescription();
2991         FontFamily& firstFamily = fontDescription.firstFamily();
2992         FontFamily* currFamily = 0;
2993
2994         // Before mapping in a new font-family property, we should reset the generic family.
2995         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
2996         fontDescription.setGenericFamily(FontDescription::NoFamily);
2997
2998         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2999             CSSValue* item = i.value();
3000             if (!item->isPrimitiveValue())
3001                 continue;
3002             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
3003             AtomicString face;
3004             Settings* settings = m_checker.document()->settings();
3005             if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
3006                 if (contentValue->isFontFamilyValue())
3007                     face = static_cast<FontFamilyValue*>(contentValue)->familyName();
3008             } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
3009                 switch (contentValue->getIdent()) {
3010                     case CSSValueWebkitBody:
3011                         face = settings->standardFontFamily();
3012                         break;
3013                     case CSSValueSerif:
3014                         face = serifFamily;
3015                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
3016                         break;
3017                     case CSSValueSansSerif:
3018                         face = sansSerifFamily;
3019                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3020                         break;
3021                     case CSSValueCursive:
3022                         face = cursiveFamily;
3023                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3024                         break;
3025                     case CSSValueFantasy:
3026                         face = fantasyFamily;
3027                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3028                         break;
3029                     case CSSValueMonospace:
3030                         face = monospaceFamily;
3031                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3032                         break;
3033                     case CSSValueWebkitPictograph:
3034                         face = pictographFamily;
3035                         fontDescription.setGenericFamily(FontDescription::PictographFamily);
3036                         break;
3037                 }
3038             }
3039
3040             if (!face.isEmpty()) {
3041                 if (!currFamily) {
3042                     // Filling in the first family.
3043                     firstFamily.setFamily(face);
3044                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
3045                     currFamily = &firstFamily;
3046                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
3047                 } else {
3048                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
3049                     newFamily->setFamily(face);
3050                     currFamily->appendFamily(newFamily);
3051                     currFamily = newFamily.get();
3052                 }
3053             }
3054         }
3055
3056         // We can't call useFixedDefaultSize() until all new font families have been added
3057         // If currFamily is non-zero then we set at least one family on this description.
3058         if (currFamily) {
3059             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
3060                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
3061
3062             setFontDescription(fontDescription);
3063         }
3064         return;
3065     }
3066     case CSSPropertyTextDecoration: {
3067         // list of ident
3068         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3069         ETextDecoration t = RenderStyle::initialTextDecoration();
3070         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3071             CSSValue* item = i.value();
3072             ASSERT(item->isPrimitiveValue());
3073             t |= *static_cast<CSSPrimitiveValue*>(item);
3074         }
3075         m_style->setTextDecoration(t);
3076         return;
3077     }
3078
3079     case CSSPropertyZoom:
3080     {
3081         // Reset the zoom in effect before we do anything.  This allows the setZoom method to accurately compute a new
3082         // zoom in effect.
3083         setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
3084
3085         if (isInherit)
3086             setZoom(m_parentStyle->zoom());
3087         else if (isInitial || primitiveValue->getIdent() == CSSValueNormal)
3088             setZoom(RenderStyle::initialZoom());
3089         else if (primitiveValue->getIdent() == CSSValueReset) {
3090             setEffectiveZoom(RenderStyle::initialZoom());
3091             setZoom(RenderStyle::initialZoom());
3092         } else if (primitiveValue->getIdent() == CSSValueDocument) {
3093             float docZoom = m_checker.document()->renderer()->style()->zoom();
3094             setEffectiveZoom(docZoom);
3095             setZoom(docZoom);
3096         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) {
3097             if (primitiveValue->getFloatValue())
3098                 setZoom(primitiveValue->getFloatValue() / 100.0f);
3099         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
3100             if (primitiveValue->getFloatValue())
3101                 setZoom(primitiveValue->getFloatValue());
3102         }
3103         return;
3104     }
3105 // shorthand properties
3106     case CSSPropertyBackground:
3107         if (isInitial) {
3108             m_style->clearBackgroundLayers();
3109             m_style->setBackgroundColor(Color());
3110         }
3111         else if (isInherit) {
3112             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3113             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3114         }
3115         return;
3116     case CSSPropertyWebkitMask:
3117         if (isInitial)
3118             m_style->clearMaskLayers();
3119         else if (isInherit)
3120             m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
3121         return;
3122     case CSSPropertyFont:
3123         if (isInherit) {
3124             FontDescription fontDescription = m_parentStyle->fontDescription();
3125             m_style->setLineHeight(m_parentStyle->lineHeight());
3126             m_lineHeightValue = 0;
3127             setFontDescription(fontDescription);
3128         } else if (isInitial) {
3129             Settings* settings = m_checker.document()->settings();
3130             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3131             if (!settings)
3132                 return;
3133             FontDescription fontDescription;
3134             fontDescription.setGenericFamily(FontDescription::StandardFamily);
3135             fontDescription.setRenderingMode(settings->fontRenderingMode());
3136             fontDescription.setUsePrinterFont(m_checker.document()->printing());
3137             const AtomicString& standardFontFamily = m_checker.document()->settings()->standardFontFamily();
3138             if (!standardFontFamily.isEmpty()) {
3139                 fontDescription.firstFamily().setFamily(standardFontFamily);
3140                 fontDescription.firstFamily().appendFamily(0);
3141             }
3142             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3143             setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueMedium, false));
3144             m_style->setLineHeight(RenderStyle::initialLineHeight());
3145             m_lineHeightValue = 0;
3146             setFontDescription(fontDescription);
3147         } else if (primitiveValue) {
3148             m_style->setLineHeight(RenderStyle::initialLineHeight());
3149             m_lineHeightValue = 0;
3150
3151             FontDescription fontDescription;
3152             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3153
3154             // Double-check and see if the theme did anything.  If not, don't bother updating the font.
3155             if (fontDescription.isAbsoluteSize()) {
3156                 // Make sure the rendering mode and printer font settings are updated.
3157                 Settings* settings = m_checker.document()->settings();
3158                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3159                 if (!settings)
3160                     return;
3161                 fontDescription.setRenderingMode(settings->fontRenderingMode());
3162                 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3163
3164                 // Handle the zoom factor.
3165                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3166                 setFontDescription(fontDescription);
3167             }
3168         } else if (value->isFontValue()) {
3169             FontValue *font = static_cast<FontValue*>(value);
3170             if (!font->style || !font->variant || !font->weight ||
3171                  !font->size || !font->lineHeight || !font->family)
3172                 return;
3173             applyProperty(CSSPropertyFontStyle, font->style.get());
3174             applyProperty(CSSPropertyFontVariant, font->variant.get());
3175             applyProperty(CSSPropertyFontWeight, font->weight.get());
3176             // The previous properties can dirty our font but they don't try to read the font's
3177             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3178             // need query the dirtied font's x-height to get the computed size. To be safe in this
3179             // case, let's just update the font now.
3180             updateFont();
3181             applyProperty(CSSPropertyFontSize, font->size.get());
3182
3183             m_lineHeightValue = font->lineHeight.get();
3184
3185             applyProperty(CSSPropertyFontFamily, font->family.get());
3186         }
3187         return;
3188
3189     case CSSPropertyOutline:
3190         if (isInherit) {
3191             m_style->setOutlineWidth(m_parentStyle->outlineWidth());
3192             m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
3193             m_style->setOutlineStyle(m_parentStyle->outlineStyle());
3194         }
3195         else if (isInitial)
3196             m_style->resetOutline();
3197         return;
3198
3199     // CSS3 Properties
3200     case CSSPropertyWebkitAppearance:
3201         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(appearance, Appearance)
3202         return;
3203     case CSSPropertyBorderImage:
3204     case CSSPropertyWebkitBorderImage:
3205     case CSSPropertyWebkitMaskBoxImage: {
3206         if (isInherit) {
3207             HANDLE_INHERIT_COND(CSSPropertyBorderImage, borderImage, BorderImage)
3208             HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
3209             HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
3210             return;
3211         } else if (isInitial) {
3212             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderImage, BorderImage, NinePieceImage)
3213             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
3214             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
3215             return;
3216         }
3217
3218         NinePieceImage image;
3219         if (property == CSSPropertyWebkitMaskBoxImage)
3220             image.setMaskDefaults();
3221         mapNinePieceImage(property, value, image);
3222
3223         if (id != CSSPropertyWebkitMaskBoxImage)
3224             m_style->setBorderImage(image);
3225         else
3226             m_style->setMaskBoxImage(image);
3227         return;
3228     }
3229     case CSSPropertyBorderImageOutset:
3230     case CSSPropertyWebkitMaskBoxImageOutset: {
3231         bool isBorderImage = id == CSSPropertyBorderImageOutset;
3232         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3233         if (isInherit)
3234             image.copyOutsetFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3235         else if (isInitial)
3236             image.setOutset(LengthBox());
3237         else
3238             image.setOutset(mapNinePieceImageQuad(value));
3239
3240         if (isBorderImage)
3241             m_style->setBorderImage(image);
3242         else
3243             m_style->setMaskBoxImage(image);
3244         return;
3245     }
3246     case CSSPropertyBorderImageRepeat:
3247     case CSSPropertyWebkitMaskBoxImageRepeat: {
3248         bool isBorderImage = id == CSSPropertyBorderImageRepeat;
3249         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3250         if (isInherit)
3251             image.copyRepeatFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3252         else if (isInitial) {
3253             image.setHorizontalRule(StretchImageRule);
3254             image.setVerticalRule(StretchImageRule);
3255         } else
3256             mapNinePieceImageRepeat(value, image);
3257
3258         if (isBorderImage)
3259             m_style->setBorderImage(image);
3260         else
3261             m_style->setMaskBoxImage(image);
3262         return;
3263     }
3264     case CSSPropertyBorderImageSlice:
3265     case CSSPropertyWebkitMaskBoxImageSlice: {
3266         bool isBorderImage = id == CSSPropertyBorderImageSlice;
3267         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3268         if (isInherit)
3269             image.copyImageSlicesFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3270         else if (isInitial) {
3271             // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
3272             image.setImageSlices(isBorderImage ? LengthBox(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent)) : LengthBox());
3273             image.setFill(false);
3274         } else
3275             mapNinePieceImageSlice(value, image);
3276
3277         if (isBorderImage)
3278             m_style->setBorderImage(image);
3279         else
3280             m_style->setMaskBoxImage(image);
3281         return;
3282     }
3283     case CSSPropertyBorderImageWidth:
3284     case CSSPropertyWebkitMaskBoxImageWidth: {
3285         bool isBorderImage = id == CSSPropertyBorderImageWidth;
3286         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3287         if (isInherit)
3288             image.copyBorderSlicesFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3289         else if (isInitial) {
3290             // Masks have a different initial value for slices. They use an 'auto' value rather than trying to fit to the border.
3291             image.setBorderSlices(isBorderImage ? LengthBox(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative)) : LengthBox());
3292         } else
3293             image.setBorderSlices(mapNinePieceImageQuad(value));
3294
3295         if (isBorderImage)
3296             m_style->setBorderImage(image);
3297         else
3298             m_style->setMaskBoxImage(image);
3299         return;
3300     }
3301     case CSSPropertyImageRendering:
3302         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(imageRendering, ImageRendering);
3303         return;
3304     case CSSPropertyTextShadow:
3305     case CSSPropertyBoxShadow:
3306     case CSSPropertyWebkitBoxShadow: {
3307         if (isInherit) {
3308             if (id == CSSPropertyTextShadow)
3309                 return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
3310             return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
3311         }
3312         if (isInitial || primitiveValue) // initial | none
3313             return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
3314
3315         if (!value->isValueList())
3316             return;
3317
3318         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3319             CSSValue* currValue = i.value();
3320             if (!currValue->isShadowValue())
3321                 continue;
3322             ShadowValue* item = static_cast<ShadowValue*>(currValue);
3323             int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3324             int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3325             int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3326             int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3327             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3328             Color color;
3329             if (item->color)
3330                 color = getColorFromPrimitiveValue(item->color.get());
3331             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3332             if (id == CSSPropertyTextShadow)
3333                 m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3334             else
3335                 m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3336         }
3337         return;
3338     }
3339     case CSSPropertyWebkitBoxReflect: {
3340         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3341         if (primitiveValue) {
3342             m_style->setBoxReflect(RenderStyle::initialBoxReflect());
3343             return;
3344         }
3345
3346         if (!value->isReflectValue())
3347             return;
3348
3349         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3350         RefPtr<StyleReflection> reflection = StyleReflection::create();
3351         reflection->setDirection(reflectValue->direction());
3352         if (reflectValue->offset()) {
3353             int type = reflectValue->offset()->primitiveType();
3354             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3355                 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
3356             else
3357                 reflection->setOffset(reflectValue->offset()->computeLength<Length>(style(), m_rootElementStyle, zoomFactor));
3358         }
3359         NinePieceImage mask;
3360         mask.setMaskDefaults();
3361         mapNinePieceImage(property, reflectValue->mask(), mask);
3362         reflection->setMask(mask);
3363
3364         m_style->setBoxReflect(reflection.release());
3365         return;
3366     }
3367     case CSSPropertyOpacity:
3368         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
3369         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3370             return; // Error case.
3371         // Clamp opacity to the range 0-1
3372         m_style->setOpacity(clampTo<float>(primitiveValue->getDoubleValue(), 0, 1));
3373         return;
3374     case CSSPropertyWebkitBoxAlign:
3375         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxAlign, BoxAlign)
3376         return;
3377     case CSSPropertySrc: // Only used in @font-face rules.
3378         return;
3379     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3380         return;
3381     case CSSPropertyWebkitBackfaceVisibility:
3382         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(backfaceVisibility, BackfaceVisibility)
3383         return;
3384     case CSSPropertyWebkitBoxDirection:
3385         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
3386         return;
3387     case CSSPropertyWebkitBoxLines:
3388         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
3389         return;
3390     case CSSPropertyWebkitBoxOrient:
3391         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
3392         return;
3393     case CSSPropertyWebkitBoxPack:
3394     {
3395         HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
3396         if (!primitiveValue)
3397             return;
3398         EBoxAlignment boxPack = *primitiveValue;
3399         if (boxPack != BSTRETCH && boxPack != BBASELINE)
3400             m_style->setBoxPack(boxPack);
3401         return;
3402     }
3403     case CSSPropertyWebkitBoxFlex:
3404         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlex, BoxFlex)
3405         return;
3406     case CSSPropertyWebkitBoxFlexGroup:
3407         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlexGroup, BoxFlexGroup)
3408         return;
3409     case CSSPropertyWebkitBoxOrdinalGroup:
3410         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrdinalGroup, BoxOrdinalGroup)
3411         return;
3412     case CSSPropertyBoxSizing:
3413         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxSizing, BoxSizing);
3414         return;
3415     case CSSPropertyWebkitColumnSpan:
3416         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnSpan, ColumnSpan)
3417         return;
3418     case CSSPropertyWebkitColumnRuleStyle:
3419         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
3420         return;
3421     case CSSPropertyWebkitColumnBreakBefore:
3422         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
3423         return;
3424     case CSSPropertyWebkitColumnBreakAfter:
3425         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
3426         return;
3427     case CSSPropertyWebkitColumnBreakInside:
3428         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
3429         return;
3430     case CSSPropertyWebkitColumnRule:
3431         if (isInherit) {
3432             m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
3433             m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
3434             m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
3435         }
3436         else if (isInitial)
3437             m_style->resetColumnRule();
3438         return;
3439     case CSSPropertyWebkitLineGrid:
3440         HANDLE_INHERIT_AND_INITIAL(lineGrid, LineGrid);
3441         if (primitiveValue->getIdent() == CSSValueNone)
3442             m_style->setLineGrid(nullAtom);
3443         else
3444             m_style->setLineGrid(primitiveValue->getStringValue());
3445         return;
3446     case CSSPropertyWebkitLineGridSnap:
3447         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(lineGridSnap, LineGridSnap)
3448         return;
3449     case CSSPropertyWebkitRegionBreakBefore:
3450         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakBefore, RegionBreakBefore, PageBreak)
3451         return;
3452     case CSSPropertyWebkitRegionBreakAfter:
3453         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakAfter, RegionBreakAfter, PageBreak)
3454         return;
3455     case CSSPropertyWebkitRegionBreakInside:
3456         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakInside, RegionBreakInside, PageBreak)
3457         return;
3458     case CSSPropertyWebkitMarquee:
3459         if (!m_parentNode || !value->isInheritedValue())
3460             return;
3461         m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
3462         m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
3463         m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
3464         m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
3465         m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
3466         return;
3467     case CSSPropertyWebkitMarqueeRepetition: {
3468         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3469         if (!primitiveValue)
3470             return;
3471         if (primitiveValue->getIdent() == CSSValueInfinite)
3472             m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
3473         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
3474             m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
3475         return;
3476     }
3477     case CSSPropertyWebkitMarqueeSpeed: {
3478         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3479         if (!primitiveValue)
3480             return;
3481         if (primitiveValue->getIdent()) {
3482             switch (primitiveValue->getIdent()) {
3483                 case CSSValueSlow:
3484                     m_style->setMarqueeSpeed(500); // 500 msec.
3485                     break;
3486                 case CSSValueNormal:
3487                     m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
3488                     break;
3489                 case CSSValueFast:
3490                     m_style->setMarqueeSpeed(10); // 10msec. Super fast.
3491                     break;
3492             }
3493         }
3494         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
3495             m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
3496         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
3497             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3498         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
3499             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3500         return;
3501     }
3502     case CSSPropertyWebkitMarqueeIncrement: {
3503         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3504         if (!primitiveValue)
3505             return;
3506         if (primitiveValue->getIdent()) {
3507             switch (primitiveValue->getIdent()) {
3508                 case CSSValueSmall:
3509                     m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3510                     break;
3511                 case CSSValueNormal:
3512                     m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3513                     break;
3514                 case CSSValueLarge:
3515                     m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3516                     break;
3517             }
3518         }
3519         else {
3520             bool ok = true;
3521             Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
3522             if (ok)
3523                 m_style->setMarqueeIncrement(marqueeLength);
3524         }
3525         return;
3526     }
3527     case CSSPropertyWebkitMarqueeStyle:
3528         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
3529         return;
3530     case CSSPropertyWebkitFlowInto:
3531         HANDLE_INHERIT_AND_INITIAL(flowThread, FlowThread);
3532         if (primitiveValue->getIdent() == CSSValueAuto)
3533             m_style->setFlowThread(nullAtom);
3534         else
3535             m_style->setFlowThread(primitiveValue->getStringValue());
3536         return;
3537     case CSSPropertyWebkitFlowFrom:
3538         HANDLE_INHERIT_AND_INITIAL(regionThread, RegionThread);
3539         if (primitiveValue->getIdent() == CSSValueNone)
3540             m_style->setRegionThread(nullAtom);
3541         else
3542             m_style->setRegionThread(primitiveValue->getStringValue());
3543         return;
3544     case CSSPropertyWebkitRegionOverflow:
3545         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(regionOverflow, RegionOverflow);
3546         return;
3547     case CSSPropertyWebkitMarqueeDirection:
3548         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
3549         return;
3550     case CSSPropertyWebkitUserDrag:
3551         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
3552         return;
3553     case CSSPropertyWebkitUserModify:
3554         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
3555         return;
3556     case CSSPropertyWebkitUserSelect:
3557         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
3558         return;
3559
3560     case CSSPropertyTextOverflow: {
3561         // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
3562         // work with WinIE-specific pages that use the property.
3563         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textOverflow, TextOverflow)
3564         return;
3565     }
3566     case CSSPropertyWebkitLineClamp: {
3567         HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
3568         if (!primitiveValue)
3569             return;
3570         int type = primitiveValue->primitiveType();
3571         if (type == CSSPrimitiveValue::CSS_NUMBER)
3572             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
3573         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3574             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
3575         return;
3576     }
3577     case CSSPropertyWebkitHyphens:
3578         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(hyphens, Hyphens);
3579         return;
3580     case CSSPropertyWebkitHyphenateLimitAfter: {
3581         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter);
3582         if (primitiveValue->getIdent() == CSSValueAuto)
3583             m_style->setHyphenationLimitAfter(-1);
3584         else
3585             m_style->setHyphenationLimitAfter(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3586         return;
3587     }
3588     case CSSPropertyWebkitHyphenateLimitBefore: {
3589         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore);
3590         if (primitiveValue->getIdent() == CSSValueAuto)
3591             m_style->setHyphenationLimitBefore(-1);
3592         else
3593             m_style->setHyphenationLimitBefore(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3594         return;
3595     }
3596     case CSSPropertyWebkitHyphenateLimitLines: {
3597         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitLines, HyphenationLimitLines);
3598         if (primitiveValue->getIdent() == CSSValueNoLimit)
3599             m_style->setHyphenationLimitLines(-1);
3600         else
3601             m_style->setHyphenationLimitLines(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3602         return;
3603     }
3604     case CSSPropertyWebkitLocale: {
3605         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3606         if (primitiveValue->getIdent() == CSSValueAuto)
3607             m_style->setLocale(nullAtom);
3608         else
3609             m_style->setLocale(primitiveValue->getStringValue());
3610         FontDescription fontDescription = m_style->fontDescription();
3611         fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
3612         setFontDescription(fontDescription);
3613         return;
3614     }
3615     case CSSPropertyWebkitBorderFit:
3616         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderFit, BorderFit);
3617         return;
3618     case CSSPropertyWebkitTextSizeAdjust: {
3619         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
3620         if (!primitiveValue || !primitiveValue->getIdent())
3621             return;
3622         setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
3623         return;
3624     }
3625     case CSSPropertyWebkitTextSecurity:
3626         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
3627         return;
3628
3629 #if ENABLE(DASHBOARD_SUPPORT)
3630     case CSSPropertyWebkitDashboardRegion: {
3631         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3632         if (!primitiveValue)
3633             return;
3634
3635         if (primitiveValue->getIdent() == CSSValueNone) {
3636             m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
3637             return;
3638         }
3639
3640         DashboardRegion *region = primitiveValue->getDashboardRegionValue();
3641         if (!region)
3642             return;
3643
3644         DashboardRegion *first = region;
3645         while (region) {
3646             Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
3647             Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
3648             Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
3649             Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
3650             if (region->m_isCircle)
3651                 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3652             else if (region->m_isRectangle)
3653                 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3654             region = region->m_next.get();
3655         }
3656
3657         m_element->document()->setHasDashboardRegions(true);
3658
3659         return;
3660     }
3661 #endif
3662     case CSSPropertyWebkitRtlOrdering:
3663         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(rtlOrdering, RTLOrdering)
3664         return;
3665     case CSSPropertyWebkitTextStrokeWidth: {
3666         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3667         float width = 0;
3668         switch (primitiveValue->getIdent()) {
3669             case CSSValueThin:
3670             case CSSValueMedium:
3671             case CSSValueThick: {
3672                 double result = 1.0 / 48;
3673                 if (primitiveValue->getIdent() == CSSValueMedium)
3674                     result *= 3;
3675                 else if (primitiveValue->getIdent() == CSSValueThick)
3676                     result *= 5;
3677                 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3678                 break;
3679             }
3680             default:
3681                 width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3682                 break;
3683         }
3684         m_style->setTextStrokeWidth(width);
3685         return;
3686     }
3687     case CSSPropertyWebkitTransform: {
3688         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3689         TransformOperations operations;
3690         createTransformOperations(value, style(), m_rootElementStyle, operations);
3691         m_style->setTransform(operations);
3692         return;
3693     }
3694     case CSSPropertyWebkitTransformStyle:
3695         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(transformStyle3D, TransformStyle3D)
3696         return;
3697     case CSSPropertyWebkitPrintColorAdjust:
3698         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(printColorAdjust, PrintColorAdjust);
3699         return;
3700     case CSSPropertyWebkitPerspective: {
3701         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3702         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3703             m_style->setPerspective(0);
3704             return;
3705         }
3706
3707         float perspectiveValue;
3708         int type = primitiveValue->primitiveType();
3709         if (CSSPrimitiveValue::isUnitTypeLength(type))
3710             perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3711         else if (type == CSSPrimitiveValue::CSS_NUMBER) {
3712             // For backward compatibility, treat valueless numbers as px.
3713             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3714         } else
3715             return;
3716
3717         if (perspectiveValue >= 0.0f)
3718             m_style->setPerspective(perspectiveValue);
3719         return;
3720     }
3721     case CSSPropertyWebkitAnimation:
3722         if (isInitial)
3723             m_style->clearAnimations();
3724         else if (isInherit)
3725             m_style->inheritAnimations(m_parentStyle->animations());
3726         return;
3727     case CSSPropertyWebkitTransition:
3728         if (isInitial)
3729             m_style->clearTransitions();
3730         else if (isInherit)
3731             m_style->inheritTransitions(m_parentStyle->transitions());
3732         return;
3733     case CSSPropertyPointerEvents:
3734     {
3735 #if ENABLE(DASHBOARD_SUPPORT)
3736         // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
3737         // pointer-events property by not applying it in Dashboard.
3738         Settings* settings = m_checker.document()->settings();
3739         if (settings && settings->usesDashboardBackwardCompatibilityMode())
3740             return;
3741 #endif
3742         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(pointerEvents, PointerEvents)
3743         return;
3744     }
3745 #if ENABLE(TOUCH_EVENTS)
3746     case CSSPropertyWebkitTapHighlightColor: {
3747         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
3748         if (!primitiveValue)
3749             break;
3750
3751         Color col = getColorFromPrimitiveValue(primitiveValue);
3752         m_style->setTapHighlightColor(col);
3753         return;
3754     }
3755 #endif
3756     case CSSPropertyWebkitColorCorrection:
3757         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(colorSpace, ColorSpace);
3758         return;
3759     case CSSPropertySize:
3760         applyPageSizeProperty(value);
3761         return;
3762     case CSSPropertySpeak:
3763         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(speak, Speak);
3764         return;
3765     case CSSPropertyInvalid:
3766         return;
3767     // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
3768     case CSSPropertyWebkitBorderEnd:
3769     case CSSPropertyWebkitBorderEndColor:
3770     case CSSPropertyWebkitBorderEndStyle:
3771     case CSSPropertyWebkitBorderEndWidth:
3772     case CSSPropertyWebkitBorderStart:
3773     case CSSPropertyWebkitBorderStartColor:
3774     case CSSPropertyWebkitBorderStartStyle:
3775     case CSSPropertyWebkitBorderStartWidth:
3776     case CSSPropertyWebkitBorderBefore:
3777     case CSSPropertyWebkitBorderBeforeColor:
3778     case CSSPropertyWebkitBorderBeforeStyle:
3779     case CSSPropertyWebkitBorderBeforeWidth:
3780     case CSSPropertyWebkitBorderAfter:
3781     case CSSPropertyWebkitBorderAfterColor:
3782     case CSSPropertyWebkitBorderAfterStyle:
3783     case CSSPropertyWebkitBorderAfterWidth:
3784     case CSSPropertyWebkitMarginEnd:
3785     case CSSPropertyWebkitMarginStart:
3786     case CSSPropertyWebkitMarginBefore:
3787     case CSSPropertyWebkitMarginAfter:
3788     case CSSPropertyWebkitMarginCollapse:
3789     case CSSPropertyWebkitMarginBeforeCollapse:
3790     case CSSPropertyWebkitMarginTopCollapse:
3791     case CSSPropertyWebkitMarginAfterCollapse:
3792     case CSSPropertyWebkitMarginBottomCollapse:
3793     case CSSPropertyWebkitPaddingEnd:
3794     case CSSPropertyWebkitPaddingStart:
3795     case CSSPropertyWebkitPaddingBefore:
3796     case CSSPropertyWebkitPaddingAfter:
3797     case CSSPropertyWebkitLogicalWidth:
3798     case CSSPropertyWebkitLogicalHeight:
3799     case CSSPropertyWebkitMinLogicalWidth:
3800     case CSSPropertyWebkitMinLogicalHeight:
3801     case CSSPropertyWebkitMaxLogicalWidth:
3802     case CSSPropertyWebkitMaxLogicalHeight:
3803     {
3804         int newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3805         ASSERT(newId != id);
3806         return applyProperty(newId, value);
3807     }
3808     case CSSPropertyFontStretch:
3809     case CSSPropertyPage:
3810     case CSSPropertyTextLineThrough:
3811     case CSSPropertyTextLineThroughColor:
3812     case CSSPropertyTextLineThroughMode:
3813     case CSSPropertyTextLineThroughStyle:
3814     case CSSPropertyTextLineThroughWidth:
3815     case CSSPropertyTextOverline:
3816     case CSSPropertyTextOverlineColor:
3817     case CSSPropertyTextOverlineMode:
3818     case CSSPropertyTextOverlineStyle:
3819     case CSSPropertyTextOverlineWidth:
3820     case CSSPropertyTextUnderline:
3821     case CSSPropertyTextUnderlineColor:
3822     case CSSPropertyTextUnderlineMode:
3823     case CSSPropertyTextUnderlineStyle:
3824     case CSSPropertyTextUnderlineWidth:
3825     case CSSPropertyWebkitAspectRatio:
3826     case CSSPropertyWebkitFontSizeDelta:
3827     case CSSPropertyWebkitTextDecorationsInEffect:
3828     case CSSPropertyWebkitTextStroke:
3829     case CSSPropertyWebkitTextEmphasis:
3830         return;
3831
3832     // CSS Text Layout Module Level 3: Vertical writing support
3833     case CSSPropertyWebkitWritingMode: {
3834         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
3835         if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
3836             m_element->document()->setWritingModeSetOnDocumentElement(true);
3837         FontDescription fontDescription = m_style->fontDescription();
3838         fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
3839         setFontDescription(fontDescription);
3840         return;
3841     }
3842
3843     case CSSPropertyWebkitLineBoxContain: {
3844         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
3845      &nb