d3d528953fa1b52721a131649c730638775c22a8
[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 "CachedImage.h"
33 #include "ContentData.h"
34 #include "Counter.h"
35 #include "CounterContent.h"
36 #include "CSSBorderImageValue.h"
37 #include "CSSCursorImageValue.h"
38 #include "CSSFontFaceRule.h"
39 #include "CSSFontSelector.h"
40 #include "CSSImportRule.h"
41 #include "CSSLineBoxContainValue.h"
42 #include "CSSMediaRule.h"
43 #include "CSSPageRule.h"
44 #include "CSSParser.h"
45 #include "CSSPrimitiveValueMappings.h"
46 #include "CSSPropertyNames.h"
47 #include "CSSReflectValue.h"
48 #include "CSSRegionStyleRule.h"
49 #include "CSSRuleList.h"
50 #include "CSSSelector.h"
51 #include "CSSSelectorList.h"
52 #include "CSSStyleApplyProperty.h"
53 #include "CSSStyleRule.h"
54 #include "CSSStyleSheet.h"
55 #include "CSSTimingFunctionValue.h"
56 #include "CSSValueList.h"
57 #include "CursorList.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     if (simpleDefaultStyleSheet)
1139         result.isCacheable = false;
1140     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1141         ? defaultPrintStyle : defaultStyle;
1142     matchRules(userAgentStyleSheet, result.firstUARule, result.lastUARule, false);
1143
1144     // In quirks mode, we match rules from the quirks user agent sheet.
1145     if (!m_checker.strictParsing())
1146         matchRules(defaultQuirksStyle, result.firstUARule, result.lastUARule, false);
1147
1148     // 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.
1149     if (m_checker.document()->isViewSource()) {
1150         if (!defaultViewSourceStyle)
1151             loadViewSourceStyle();
1152         matchRules(defaultViewSourceStyle, result.firstUARule, result.lastUARule, false);
1153     }
1154 }
1155
1156 PassRefPtr<RenderStyle> CSSStyleSelector::styleForDocument(Document* document)
1157 {
1158     Frame* frame = document->frame();
1159
1160     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1161     documentStyle->setDisplay(BLOCK);
1162     documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1163     documentStyle->setZoom(frame ? frame->pageZoomFactor() : 1);
1164     documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1165     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1166
1167     Element* docElement = document->documentElement();
1168     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1169     if (docElementRenderer) {
1170         // Use the direction and writing-mode of the body to set the
1171         // viewport's direction and writing-mode unless the property is set on the document element.
1172         // If there is no body, then use the document element.
1173         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1174         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1175             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1176         else
1177             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1178         if (bodyRenderer && !document->directionSetOnDocumentElement())
1179             documentStyle->setDirection(bodyRenderer->style()->direction());
1180         else
1181             documentStyle->setDirection(docElementRenderer->style()->direction());
1182     }
1183
1184     if (frame) {
1185         if (Page* page = frame->page()) {
1186             const Page::Pagination& pagination = page->pagination();
1187             if (pagination.mode != Page::Pagination::Unpaginated) {
1188                 documentStyle->setColumnAxis(pagination.mode == Page::Pagination::HorizontallyPaginated ? HorizontalColumnAxis : VerticalColumnAxis);
1189                 documentStyle->setColumnGap(pagination.gap);
1190             }
1191         }
1192     }
1193
1194     FontDescription fontDescription;
1195     fontDescription.setUsePrinterFont(document->printing());
1196     if (Settings* settings = document->settings()) {
1197         fontDescription.setRenderingMode(settings->fontRenderingMode());
1198         const AtomicString& stdfont = settings->standardFontFamily();
1199         if (!stdfont.isEmpty()) {
1200             fontDescription.setGenericFamily(FontDescription::StandardFamily);
1201             fontDescription.firstFamily().setFamily(stdfont);
1202             fontDescription.firstFamily().appendFamily(0);
1203         }
1204         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1205         int size = CSSStyleSelector::fontSizeForKeyword(document, CSSValueMedium, false);
1206         fontDescription.setSpecifiedSize(size);
1207         bool useSVGZoomRules = document->isSVGDocument();
1208         fontDescription.setComputedSize(CSSStyleSelector::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1209     }
1210
1211     documentStyle->setFontDescription(fontDescription);
1212     documentStyle->font().update(0);
1213
1214     return documentStyle.release();
1215 }
1216
1217 static inline bool isAtShadowBoundary(Element* element)
1218 {
1219     if (!element)
1220         return false;
1221     ContainerNode* parentNode = element->parentNode();
1222     return parentNode && parentNode->isShadowRoot();
1223 }
1224
1225 // If resolveForRootDefault is true, style based on user agent style sheet only. This is used in media queries, where
1226 // relative units are interpreted according to document root element style, styled only with UA stylesheet
1227
1228 PassRefPtr<RenderStyle> CSSStyleSelector::styleForElement(Element* element, RenderStyle* defaultParent, bool allowSharing, bool resolveForRootDefault)
1229 {
1230     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1231     // will vanish if a style recalc happens during loading.
1232     if (allowSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1233         if (!s_styleNotYetAvailable) {
1234             s_styleNotYetAvailable = RenderStyle::create().leakRef();
1235             s_styleNotYetAvailable->setDisplay(NONE);
1236             s_styleNotYetAvailable->font().update(m_fontSelector);
1237         }
1238         element->document()->setHasNodesWithPlaceholderStyle();
1239         return s_styleNotYetAvailable;
1240     }
1241
1242     initElement(element);
1243     initForStyleResolve(element, defaultParent);
1244     if (allowSharing) {
1245         RenderStyle* sharedStyle = locateSharedStyle();
1246         if (sharedStyle)
1247             return sharedStyle;
1248     }
1249
1250     m_style = RenderStyle::create();
1251
1252     if (m_parentStyle)
1253         m_style->inheritFrom(m_parentStyle);
1254     else {
1255         m_parentStyle = style();
1256         // Make sure our fonts are initialized if we don't inherit them from our parent style.
1257         m_style->font().update(0);
1258     }
1259
1260     // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
1261     if (isAtShadowBoundary(element))
1262         m_style->setUserModify(RenderStyle::initialUserModify());
1263
1264     if (element->isLink()) {
1265         m_style->setIsLink(true);
1266         m_style->setInsideLink(m_elementLinkState);
1267     }
1268
1269     ensureDefaultStyleSheetsForElement(element);
1270
1271     MatchResult matchResult;
1272     if (resolveForRootDefault)
1273         matchUARules(matchResult);
1274     else
1275         matchAllRules(matchResult);
1276
1277     applyMatchedDeclarations(matchResult);
1278
1279     // Clean up our style object's display and text decorations (among other fixups).
1280     adjustRenderStyle(style(), m_parentStyle, element);
1281
1282     initElement(0); // Clear out for the next resolve.
1283
1284     // Now return the style.
1285     return m_style.release();
1286 }
1287
1288 PassRefPtr<RenderStyle> CSSStyleSelector::styleForKeyframe(const RenderStyle* elementStyle, const WebKitCSSKeyframeRule* keyframeRule, KeyframeValue& keyframe)
1289 {
1290     if (keyframeRule->style())
1291         addMatchedDeclaration(keyframeRule->style());
1292
1293     ASSERT(!m_style);
1294
1295     // Create the style
1296     m_style = RenderStyle::clone(elementStyle);
1297
1298     m_lineHeightValue = 0;
1299
1300     // We don't need to bother with !important. Since there is only ever one
1301     // decl, there's nothing to override. So just add the first properties.
1302     bool inheritedOnly = false;
1303     if (keyframeRule->style())
1304         applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1305
1306     // If our font got dirtied, go ahead and update it now.
1307     updateFont();
1308
1309     // Line-height is set when we are sure we decided on the font-size
1310     if (m_lineHeightValue)
1311         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1312
1313     // Now do rest of the properties.
1314     if (keyframeRule->style())
1315         applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1316
1317     // If our font got dirtied by one of the non-essential font props,
1318     // go ahead and update it a second time.
1319     updateFont();
1320
1321     // Start loading images referenced by this style.
1322     loadPendingImages();
1323     
1324 #if ENABLE(CSS_SHADERS)
1325     // Start loading the shaders referenced by this style.
1326     loadPendingShaders();
1327 #endif
1328
1329     // Add all the animating properties to the keyframe.
1330     if (keyframeRule->style()) {
1331         CSSMutableStyleDeclaration::const_iterator end = keyframeRule->style()->end();
1332         for (CSSMutableStyleDeclaration::const_iterator it = keyframeRule->style()->begin(); it != end; ++it) {
1333             int property = (*it).id();
1334             // Timing-function within keyframes is special, because it is not animated; it just
1335             // describes the timing function between this keyframe and the next.
1336             if (property != CSSPropertyWebkitAnimationTimingFunction)
1337                 keyframe.addProperty(property);
1338         }
1339     }
1340
1341     return m_style.release();
1342 }
1343
1344 void CSSStyleSelector::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1345 {
1346     list.clear();
1347
1348     // Get the keyframesRule for this name
1349     if (!e || list.animationName().isEmpty())
1350         return;
1351
1352     m_keyframesRuleMap.checkConsistency();
1353
1354     if (!m_keyframesRuleMap.contains(list.animationName().impl()))
1355         return;
1356
1357     const WebKitCSSKeyframesRule* rule = m_keyframesRuleMap.find(list.animationName().impl()).get()->second.get();
1358
1359     // Construct and populate the style for each keyframe
1360     for (unsigned i = 0; i < rule->length(); ++i) {
1361         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1362         initElement(e);
1363         initForStyleResolve(e);
1364
1365         const WebKitCSSKeyframeRule* keyframeRule = rule->item(i);
1366
1367         KeyframeValue keyframe(0, 0);
1368         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule, keyframe));
1369
1370         // Add this keyframe style to all the indicated key times
1371         Vector<float> keys;
1372         keyframeRule->getKeys(keys);
1373         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1374             keyframe.setKey(keys[keyIndex]);
1375             list.insert(keyframe);
1376         }
1377     }
1378
1379     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1380     int initialListSize = list.size();
1381     if (initialListSize > 0 && list[0].key() != 0) {
1382         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1383         keyframeRule->setKeyText("0%");
1384         KeyframeValue keyframe(0, 0);
1385         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1386         list.insert(keyframe);
1387     }
1388
1389     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1390     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1391         RefPtr<WebKitCSSKeyframeRule> keyframeRule = WebKitCSSKeyframeRule::create();
1392         keyframeRule->setKeyText("100%");
1393         KeyframeValue keyframe(1, 0);
1394         keyframe.setStyle(styleForKeyframe(elementStyle, keyframeRule.get(), keyframe));
1395         list.insert(keyframe);
1396     }
1397 }
1398
1399 PassRefPtr<RenderStyle> CSSStyleSelector::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1400 {
1401     if (!e)
1402         return 0;
1403
1404     initElement(e);
1405
1406     initForStyleResolve(e, parentStyle, pseudo);
1407     m_style = RenderStyle::create();
1408
1409     if (m_parentStyle)
1410         m_style->inheritFrom(m_parentStyle);
1411
1412     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1413     // those rules.
1414
1415     // Check UA, user and author rules.
1416     MatchResult matchResult;
1417     matchUARules(matchResult);
1418
1419     if (m_matchAuthorAndUserStyles) {
1420         matchRules(m_userStyle.get(), matchResult.firstUserRule, matchResult.lastUserRule, false);
1421         matchRules(m_authorStyle.get(), matchResult.firstAuthorRule, matchResult.lastAuthorRule, false);
1422     }
1423
1424     if (m_matchedDecls.isEmpty())
1425         return 0;
1426
1427     m_style->setStyleType(pseudo);
1428
1429     applyMatchedDeclarations(matchResult);
1430
1431     // Clean up our style object's display and text decorations (among other fixups).
1432     adjustRenderStyle(style(), parentStyle, 0);
1433
1434     // Start loading images referenced by this style.
1435     loadPendingImages();
1436
1437 #if ENABLE(CSS_SHADERS)
1438     // Start loading the shaders referenced by this style.
1439     loadPendingShaders();
1440 #endif
1441
1442     // Now return the style.
1443     return m_style.release();
1444 }
1445
1446 PassRefPtr<RenderStyle> CSSStyleSelector::styleForPage(int pageIndex)
1447 {
1448     initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1449
1450     m_style = RenderStyle::create();
1451     m_style->inheritFrom(m_rootElementStyle);
1452
1453     const bool isLeft = isLeftPage(pageIndex);
1454     const bool isFirst = isFirstPage(pageIndex);
1455     const String page = pageName(pageIndex);
1456     matchPageRules(defaultPrintStyle, isLeft, isFirst, page);
1457     matchPageRules(m_userStyle.get(), isLeft, isFirst, page);
1458     matchPageRules(m_authorStyle.get(), isLeft, isFirst, page);
1459     m_lineHeightValue = 0;
1460     bool inheritedOnly = false;
1461     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1462
1463     // If our font got dirtied, go ahead and update it now.
1464     updateFont();
1465
1466     // Line-height is set when we are sure we decided on the font-size.
1467     if (m_lineHeightValue)
1468         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1469
1470     applyDeclarations<false>(false, 0, m_matchedDecls.size() - 1, inheritedOnly);
1471
1472     // Start loading images referenced by this style.
1473     loadPendingImages();
1474
1475 #if ENABLE(CSS_SHADERS)
1476     // Start loading the shaders referenced by this style.
1477     loadPendingShaders();
1478 #endif
1479
1480     // Now return the style.
1481     return m_style.release();
1482 }
1483
1484 static void addIntrinsicMargins(RenderStyle* style)
1485 {
1486     // Intrinsic margin value.
1487     const int intrinsicMargin = 2 * style->effectiveZoom();
1488
1489     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1490     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1491     if (style->width().isIntrinsicOrAuto()) {
1492         if (style->marginLeft().quirk())
1493             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1494         if (style->marginRight().quirk())
1495             style->setMarginRight(Length(intrinsicMargin, Fixed));
1496     }
1497
1498     if (style->height().isAuto()) {
1499         if (style->marginTop().quirk())
1500             style->setMarginTop(Length(intrinsicMargin, Fixed));
1501         if (style->marginBottom().quirk())
1502             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1503     }
1504 }
1505
1506 void CSSStyleSelector::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1507 {
1508     // Cache our original display.
1509     style->setOriginalDisplay(style->display());
1510
1511     if (style->display() != NONE) {
1512         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1513         // property.
1514         // Sites also commonly use display:inline/block on <td>s and <table>s.  In quirks mode we force
1515         // these tags to retain their display types.
1516         if (!m_checker.strictParsing() && e) {
1517             if (e->hasTagName(tdTag)) {
1518                 style->setDisplay(TABLE_CELL);
1519                 style->setFloating(NoFloat);
1520             }
1521             else if (e->hasTagName(tableTag))
1522                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1523         }
1524
1525         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1526             if (style->whiteSpace() == KHTML_NOWRAP) {
1527                 // Figure out if we are really nowrapping or if we should just
1528                 // use normal instead.  If the width of the cell is fixed, then
1529                 // we don't actually use NOWRAP.
1530                 if (style->width().isFixed())
1531                     style->setWhiteSpace(NORMAL);
1532                 else
1533                     style->setWhiteSpace(NOWRAP);
1534             }
1535         }
1536
1537         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1538         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1539             style->setTextAlign(TAAUTO);
1540
1541         // Frames and framesets never honor position:relative or position:absolute.  This is necessary to
1542         // fix a crash where a site tries to position these objects.  They also never honor display.
1543         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1544             style->setPosition(StaticPosition);
1545             style->setDisplay(BLOCK);
1546         }
1547
1548         // Table headers with a text-align of auto will change the text-align to center.
1549         if (e && e->hasTagName(thTag) && style->textAlign() == TAAUTO)
1550             style->setTextAlign(CENTER);
1551
1552         if (e && e->hasTagName(legendTag))
1553             style->setDisplay(BLOCK);
1554
1555         // Mutate the display to BLOCK or TABLE for certain cases, e.g., if someone attempts to
1556         // position or float an inline, compact, or run-in.  Cache the original display, since it
1557         // may be needed for positioned elements that have to compute their static normal flow
1558         // positions.  We also force inline-level roots to be block-level.
1559         if (style->display() != BLOCK && style->display() != TABLE && style->display() != BOX &&
1560             (style->position() == AbsolutePosition || style->position() == FixedPosition || style->isFloating() ||
1561              (e && e->document()->documentElement() == e))) {
1562             if (style->display() == INLINE_TABLE)
1563                 style->setDisplay(TABLE);
1564             else if (style->display() == INLINE_BOX)
1565                 style->setDisplay(BOX);
1566             else if (style->display() == LIST_ITEM) {
1567                 // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk,
1568                 // but only in quirks mode.
1569                 if (!m_checker.strictParsing() && style->isFloating())
1570                     style->setDisplay(BLOCK);
1571             }
1572             else
1573                 style->setDisplay(BLOCK);
1574         }
1575
1576         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1577         // clear how that should work.
1578         if (style->display() == INLINE && style->styleType() == NOPSEUDO && parentStyle && style->writingMode() != parentStyle->writingMode())
1579             style->setDisplay(INLINE_BLOCK);
1580
1581         // After performing the display mutation, check table rows.  We do not honor position:relative on
1582         // table rows or cells.  This has been established in CSS2.1 (and caused a crash in containingBlock()
1583         // on some sites).
1584         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1585              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW) &&
1586              style->position() == RelativePosition)
1587             style->setPosition(StaticPosition);
1588
1589         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1590         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1591         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1592             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1593             || style->display() == TABLE_CELL)
1594             style->setWritingMode(parentStyle->writingMode());
1595
1596         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1597         // of block-flow to anything other than TopToBottomWritingMode.
1598         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1599         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1600             style->setWritingMode(TopToBottomWritingMode);
1601     }
1602
1603     // Make sure our z-index value is only applied if the object is positioned.
1604     if (style->position() == StaticPosition)
1605         style->setHasAutoZIndex();
1606
1607     // Auto z-index becomes 0 for the root element and transparent objects.  This prevents
1608     // cases where objects that should be blended as a single unit end up with a non-transparent
1609     // object wedged in between them.  Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1610     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e) || style->opacity() < 1.0f
1611         || style->hasTransformRelatedProperty() || style->hasMask() || style->boxReflect() || style->hasFilter()))
1612         style->setZIndex(0);
1613
1614     // Textarea considers overflow visible as auto.
1615     if (e && e->hasTagName(textareaTag)) {
1616         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1617         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1618     }
1619
1620     // Finally update our text decorations in effect, but don't allow text-decoration to percolate through
1621     // tables, inline blocks, inline tables, run-ins, or shadow DOM.
1622     if (style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1623         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e))
1624         style->setTextDecorationsInEffect(style->textDecoration());
1625     else
1626         style->addToTextDecorationsInEffect(style->textDecoration());
1627
1628     // If either overflow value is not visible, change to auto.
1629     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1630         style->setOverflowY(OMARQUEE);
1631     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1632         style->setOverflowX(OMARQUEE);
1633     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE)
1634         style->setOverflowX(OAUTO);
1635     else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1636         style->setOverflowY(OAUTO);
1637
1638     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1639     // FIXME: Eventually table sections will support auto and scroll.
1640     if (style->display() == TABLE || style->display() == INLINE_TABLE ||
1641         style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1642         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1643             style->setOverflowX(OVISIBLE);
1644         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1645             style->setOverflowY(OVISIBLE);
1646     }
1647
1648     // Menulists should have visible overflow
1649     if (style->appearance() == MenulistPart) {
1650         style->setOverflowX(OVISIBLE);
1651         style->setOverflowY(OVISIBLE);
1652     }
1653
1654     // Cull out any useless layers and also repeat patterns into additional layers.
1655     style->adjustBackgroundLayers();
1656     style->adjustMaskLayers();
1657
1658     // Do the same for animations and transitions.
1659     style->adjustAnimations();
1660     style->adjustTransitions();
1661
1662     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1663     // alter fonts and heights/widths.
1664     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1665         // Don't apply intrinsic margins to image buttons.  The designer knows how big the images are,
1666         // so we have to treat all image buttons as though they were explicitly sized.
1667         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1668             addIntrinsicMargins(style);
1669     }
1670
1671     // Let the theme also have a crack at adjusting the style.
1672     if (style->hasAppearance())
1673         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
1674
1675     // If we have first-letter pseudo style, do not share this style.
1676     if (style->hasPseudoStyle(FIRST_LETTER))
1677         style->setUnique();
1678
1679 #if ENABLE(SVG)
1680     if (e && e->isSVGElement()) {
1681         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1682         if (style->overflowY() == OSCROLL)
1683             style->setOverflowY(OHIDDEN);
1684         else if (style->overflowY() == OAUTO)
1685             style->setOverflowY(OVISIBLE);
1686
1687         if (style->overflowX() == OSCROLL)
1688             style->setOverflowX(OHIDDEN);
1689         else if (style->overflowX() == OAUTO)
1690             style->setOverflowX(OVISIBLE);
1691
1692         // Only the root <svg> element in an SVG document fragment tree honors css position
1693         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1694             style->setPosition(RenderStyle::initialPosition());
1695     }
1696 #endif
1697 }
1698
1699 bool CSSStyleSelector::checkRegionStyle(Element* e)
1700 {
1701     m_checker.clearHasUnknownPseudoElements();
1702     m_checker.setPseudoStyle(NOPSEUDO);
1703
1704     for (Vector<RefPtr<CSSRegionStyleRule> >::iterator it = m_regionStyleRules.begin(); it != m_regionStyleRules.end(); ++it) {
1705         const CSSSelectorList& regionSelectorList = (*it)->selectorList();
1706         for (CSSSelector* s = regionSelectorList.first(); s; s = regionSelectorList.next(s)) {
1707             if (m_checker.checkSelector(s, e))
1708                 return true;
1709         }
1710     }
1711
1712     return false;
1713 }
1714
1715 void CSSStyleSelector::updateFont()
1716 {
1717     if (!m_fontDirty)
1718         return;
1719
1720     checkForTextSizeAdjust();
1721     checkForGenericFamilyChange(style(), m_parentStyle);
1722     checkForZoomChange(style(), m_parentStyle);
1723     m_style->font().update(m_fontSelector);
1724     m_fontDirty = false;
1725 }
1726
1727 void CSSStyleSelector::cacheBorderAndBackground()
1728 {
1729     m_hasUAAppearance = m_style->hasAppearance();
1730     if (m_hasUAAppearance) {
1731         m_borderData = m_style->border();
1732         m_backgroundData = *m_style->backgroundLayers();
1733         m_backgroundColor = m_style->backgroundColor();
1734     }
1735 }
1736
1737 PassRefPtr<CSSRuleList> CSSStyleSelector::styleRulesForElement(Element* e, unsigned rulesToInclude)
1738 {
1739     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1740 }
1741
1742 PassRefPtr<CSSRuleList> CSSStyleSelector::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
1743 {
1744     if (!e || !e->document()->haveStylesheetsLoaded())
1745         return 0;
1746
1747     m_checker.setCollectingRulesOnly(true);
1748
1749     initElement(e);
1750     initForStyleResolve(e, 0, pseudoId);
1751
1752     MatchResult dummy;
1753     if (rulesToInclude & UAAndUserCSSRules) {
1754         // First we match rules from the user agent sheet.
1755         matchUARules(dummy);
1756
1757         // Now we check user sheet rules.
1758         if (m_matchAuthorAndUserStyles)
1759             matchRules(m_userStyle.get(), dummy.firstUserRule, dummy.lastUserRule, rulesToInclude & EmptyCSSRules);
1760     }
1761
1762     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1763         m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
1764
1765         // Check the rules in author sheets.
1766         matchRules(m_authorStyle.get(), dummy.firstAuthorRule, dummy.lastAuthorRule, rulesToInclude & EmptyCSSRules);
1767
1768         m_sameOriginOnly = false;
1769     }
1770
1771     m_checker.setCollectingRulesOnly(false);
1772
1773     return m_ruleList.release();
1774 }
1775
1776 inline bool CSSStyleSelector::checkSelector(const RuleData& ruleData)
1777 {
1778     m_dynamicPseudo = NOPSEUDO;
1779     m_checker.clearHasUnknownPseudoElements();
1780
1781     // Let the slow path handle SVG as it has some additional rules regarding shadow trees.
1782     if (ruleData.hasFastCheckableSelector() && !m_element->isSVGElement()) {
1783         // We know this selector does not include any pseudo elements.
1784         if (m_checker.pseudoStyle() != NOPSEUDO)
1785             return false;
1786         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
1787         // This is limited to HTML only so we don't need to check the namespace.
1788         if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
1789             if (!ruleData.hasMultipartSelector())
1790                 return true;
1791         } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
1792             return false;
1793         if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
1794             return false;
1795         return m_checker.fastCheckSelector(ruleData.selector(), m_element);
1796     }
1797
1798     // Slow path.
1799     SelectorChecker::SelectorMatch match = m_checker.checkSelector(ruleData.selector(), m_element, m_dynamicPseudo, false, SelectorChecker::VisitedMatchEnabled, style(), m_parentNode ? m_parentNode->renderStyle() : 0);
1800     if (match != SelectorChecker::SelectorMatches)
1801         return false;
1802     if (m_checker.pseudoStyle() != NOPSEUDO && m_checker.pseudoStyle() != m_dynamicPseudo)
1803         return false;
1804     return true;
1805 }
1806
1807 // -----------------------------------------------------------------
1808
1809 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
1810 {
1811     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
1812     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
1813         return false;
1814     if (selector->m_match == CSSSelector::None)
1815         return true;
1816     if (selector->tag() != starAtom)
1817         return false;
1818     if (SelectorChecker::isCommonPseudoClassSelector(selector))
1819         return true;
1820     return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
1821 }
1822
1823 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
1824 {
1825     CSSSelectorList* selectorList = selector->selectorList();
1826     if (!selectorList)
1827         return false;
1828     for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
1829         if (subSelector->isAttributeSelector())
1830             return true;
1831     }
1832     return false;
1833 }
1834
1835 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
1836 {
1837     // These are explicitly tested for equality in canShareStyleWithElement.
1838     return attribute == typeAttr || attribute == readonlyAttr;
1839 }
1840
1841 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
1842 {
1843     while (selector) {
1844         // Allow certain common attributes (used in the default style) in the selectors that match the current element.
1845         if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
1846             return true;
1847         if (selectorListContainsUncommonAttributeSelector(selector))
1848             return true;
1849         if (selector->relation() != CSSSelector::SubSelector)
1850             break;
1851         selector = selector->tagHistory();
1852     };
1853
1854     for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) {
1855         if (selector->isAttributeSelector())
1856             return true;
1857         if (selectorListContainsUncommonAttributeSelector(selector))
1858             return true;
1859     }
1860     return false;
1861 }
1862
1863 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position)
1864     : m_rule(rule)
1865     , m_selector(selector)
1866     , m_specificity(selector->specificity())
1867     , m_position(position)
1868     , m_hasFastCheckableSelector(SelectorChecker::isFastCheckableSelector(selector))
1869     , m_hasMultipartSelector(selector->tagHistory())
1870     , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector))
1871     , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector))
1872     , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector))
1873 {
1874     SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
1875 }
1876
1877 RuleSet::RuleSet()
1878     : m_ruleCount(0)
1879     , m_autoShrinkToFitEnabled(true)
1880 {
1881 }
1882
1883 RuleSet::~RuleSet()
1884 {
1885     deleteAllValues(m_idRules);
1886     deleteAllValues(m_classRules);
1887     deleteAllValues(m_shadowPseudoElementRules);
1888     deleteAllValues(m_tagRules);
1889 }
1890
1891
1892 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map,
1893                               CSSStyleRule* rule, CSSSelector* sel)
1894 {
1895     if (!key) return;
1896     Vector<RuleData>* rules = map.get(key);
1897     if (!rules) {
1898         rules = new Vector<RuleData>;
1899         map.set(key, rules);
1900     }
1901     rules->append(RuleData(rule, sel, m_ruleCount++));
1902 }
1903
1904 void RuleSet::addRule(CSSStyleRule* rule, CSSSelector* sel)
1905 {
1906     if (sel->m_match == CSSSelector::Id) {
1907         addToRuleSet(sel->value().impl(), m_idRules, rule, sel);
1908         return;
1909     }
1910     if (sel->m_match == CSSSelector::Class) {
1911         addToRuleSet(sel->value().impl(), m_classRules, rule, sel);
1912         return;
1913     }
1914     if (sel->isUnknownPseudoElement()) {
1915         addToRuleSet(sel->value().impl(), m_shadowPseudoElementRules, rule, sel);
1916         return;
1917     }
1918     if (SelectorChecker::isCommonPseudoClassSelector(sel)) {
1919         RuleData ruleData(rule, sel, m_ruleCount++);
1920         switch (sel->pseudoType()) {
1921         case CSSSelector::PseudoLink:
1922         case CSSSelector::PseudoVisited:
1923         case CSSSelector::PseudoAnyLink:
1924             m_linkPseudoClassRules.append(ruleData);
1925             return;
1926         case CSSSelector::PseudoFocus:
1927             m_focusPseudoClassRules.append(ruleData);
1928             return;
1929         default:
1930             ASSERT_NOT_REACHED();
1931         }
1932         return;
1933     }
1934     const AtomicString& localName = sel->tag().localName();
1935     if (localName != starAtom) {
1936         addToRuleSet(localName.impl(), m_tagRules, rule, sel);
1937         return;
1938     }
1939
1940     m_universalRules.append(RuleData(rule, sel, m_ruleCount++));
1941 }
1942
1943 void RuleSet::addPageRule(CSSPageRule* rule)
1944 {
1945     m_pageRules.append(RuleData(rule, rule->selectorList().first(), m_pageRules.size()));
1946 }
1947
1948 void RuleSet::addRulesFromSheet(CSSStyleSheet* sheet, const MediaQueryEvaluator& medium, CSSStyleSelector* styleSelector)
1949 {
1950     if (!sheet)
1951         return;
1952
1953     // No media implies "all", but if a media list exists it must
1954     // contain our current medium
1955     if (sheet->media() && !medium.eval(sheet->media(), styleSelector))
1956         return; // the style sheet doesn't apply
1957
1958     int len = sheet->length();
1959
1960     for (int i = 0; i < len; i++) {
1961         CSSRule* rule = sheet->item(i);
1962         if (rule->isStyleRule())
1963             addStyleRule(static_cast<CSSStyleRule*>(rule));
1964         else if (rule->isPageRule())
1965             addPageRule(static_cast<CSSPageRule*>(rule));
1966         else if (rule->isImportRule()) {
1967             CSSImportRule* import = static_cast<CSSImportRule*>(rule);
1968             if (!import->media() || medium.eval(import->media(), styleSelector))
1969                 addRulesFromSheet(import->styleSheet(), medium, styleSelector);
1970         }
1971         else if (rule->isMediaRule()) {
1972             CSSMediaRule* r = static_cast<CSSMediaRule*>(rule);
1973             CSSRuleList* rules = r->cssRules();
1974
1975             if ((!r->media() || medium.eval(r->media(), styleSelector)) && rules) {
1976                 // Traverse child elements of the @media rule.
1977                 for (unsigned j = 0; j < rules->length(); j++) {
1978                     CSSRule *childItem = rules->item(j);
1979                     if (childItem->isStyleRule())
1980                         addStyleRule(static_cast<CSSStyleRule*>(childItem));
1981                     else if (childItem->isPageRule())
1982                         addPageRule(static_cast<CSSPageRule*>(childItem));
1983                     else if (childItem->isFontFaceRule() && styleSelector) {
1984                         // Add this font face to our set.
1985                         const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(childItem);
1986                         styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
1987                     } else if (childItem->isKeyframesRule() && styleSelector) {
1988                         // Add this keyframe rule to our set.
1989                         styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(childItem));
1990                     }
1991                 }   // for rules
1992             }   // if rules
1993         } else if (rule->isFontFaceRule() && styleSelector) {
1994             // Add this font face to our set.
1995             const CSSFontFaceRule* fontFaceRule = static_cast<CSSFontFaceRule*>(rule);
1996             styleSelector->fontSelector()->addFontFaceRule(fontFaceRule);
1997         } else if (rule->isKeyframesRule())
1998             styleSelector->addKeyframeStyle(static_cast<WebKitCSSKeyframesRule*>(rule));
1999         else if (rule->isRegionStyleRule() && styleSelector)
2000             styleSelector->addRegionStyleRule(static_cast<CSSRegionStyleRule*>(rule));
2001     }
2002     if (m_autoShrinkToFitEnabled)
2003         shrinkToFit();
2004 }
2005
2006 void RuleSet::addStyleRule(CSSStyleRule* rule)
2007 {
2008     for (CSSSelector* s = rule->selectorList().first(); s; s = CSSSelectorList::next(s))
2009         addRule(rule, s);
2010 }
2011
2012 static inline void collectFeaturesFromSelector(CSSStyleSelector::Features& features, const CSSSelector* selector)
2013 {
2014     if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty())
2015         features.idsInRules.add(selector->value().impl());
2016     if (selector->isAttributeSelector())
2017         features.attrsInRules.add(selector->attribute().localName().impl());
2018     switch (selector->pseudoType()) {
2019     case CSSSelector::PseudoFirstLine:
2020         features.usesFirstLineRules = true;
2021         break;
2022     case CSSSelector::PseudoBefore:
2023     case CSSSelector::PseudoAfter:
2024         features.usesBeforeAfterRules = true;
2025         break;
2026     case CSSSelector::PseudoLink:
2027     case CSSSelector::PseudoVisited:
2028         features.usesLinkRules = true;
2029         break;
2030     default:
2031         break;
2032     }
2033 }
2034
2035 static void collectFeaturesFromList(CSSStyleSelector::Features& features, const Vector<RuleData>& rules)
2036 {
2037     unsigned size = rules.size();
2038     for (unsigned i = 0; i < size; ++i) {
2039         const RuleData& ruleData = rules[i];
2040         bool foundSiblingSelector = false;
2041         for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
2042             collectFeaturesFromSelector(features, selector);
2043
2044             if (CSSSelectorList* selectorList = selector->selectorList()) {
2045                 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2046                     if (selector->isSiblingSelector())
2047                         foundSiblingSelector = true;
2048                     collectFeaturesFromSelector(features, subSelector);
2049                 }
2050             } else if (selector->isSiblingSelector())
2051                 foundSiblingSelector = true;
2052         }
2053         if (foundSiblingSelector) {
2054             if (!features.siblingRules)
2055                 features.siblingRules = adoptPtr(new RuleSet);
2056             features.siblingRules->addRule(ruleData.rule(), ruleData.selector());
2057         }
2058         if (ruleData.containsUncommonAttributeSelector()) {
2059             if (!features.uncommonAttributeRules)
2060                 features.uncommonAttributeRules = adoptPtr(new RuleSet);
2061             features.uncommonAttributeRules->addRule(ruleData.rule(), ruleData.selector());
2062         }
2063     }
2064 }
2065
2066 void RuleSet::collectFeatures(CSSStyleSelector::Features& features) const
2067 {
2068     AtomRuleMap::const_iterator end = m_idRules.end();
2069     for (AtomRuleMap::const_iterator it = m_idRules.begin(); it != end; ++it)
2070         collectFeaturesFromList(features, *it->second);
2071     end = m_classRules.end();
2072     for (AtomRuleMap::const_iterator it = m_classRules.begin(); it != end; ++it)
2073         collectFeaturesFromList(features, *it->second);
2074     end = m_tagRules.end();
2075     for (AtomRuleMap::const_iterator it = m_tagRules.begin(); it != end; ++it)
2076         collectFeaturesFromList(features, *it->second);
2077     end = m_shadowPseudoElementRules.end();
2078     for (AtomRuleMap::const_iterator it = m_shadowPseudoElementRules.begin(); it != end; ++it)
2079         collectFeaturesFromList(features, *it->second);
2080     collectFeaturesFromList(features, m_linkPseudoClassRules);
2081     collectFeaturesFromList(features, m_focusPseudoClassRules);
2082     collectFeaturesFromList(features, m_universalRules);
2083 }
2084
2085 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
2086 {
2087     RuleSet::AtomRuleMap::iterator end = map.end();
2088     for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
2089         it->second->shrinkToFit();
2090 }
2091
2092 void RuleSet::shrinkToFit()
2093 {
2094     shrinkMapVectorsToFit(m_idRules);
2095     shrinkMapVectorsToFit(m_classRules);
2096     shrinkMapVectorsToFit(m_tagRules);
2097     shrinkMapVectorsToFit(m_shadowPseudoElementRules);
2098     m_linkPseudoClassRules.shrinkToFit();
2099     m_focusPseudoClassRules.shrinkToFit();
2100     m_universalRules.shrinkToFit();
2101     m_pageRules.shrinkToFit();
2102 }
2103
2104 // -------------------------------------------------------------------------------------
2105 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2106
2107 static Length convertToLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, bool toFloat, double multiplier = 1, bool *ok = 0)
2108 {
2109     // This function is tolerant of a null style value. The only place style is used is in
2110     // length measurements, like 'ems' and 'px'. And in those cases style is only used
2111     // when the units are EMS or EXS. So we will just fail in those cases.
2112     Length l;
2113     if (!primitiveValue) {
2114         if (ok)
2115             *ok = false;
2116     } else {
2117         int type = primitiveValue->primitiveType();
2118
2119         if (!style && (type == CSSPrimitiveValue::CSS_EMS || type == CSSPrimitiveValue::CSS_EXS || type == CSSPrimitiveValue::CSS_REMS)) {
2120             if (ok)
2121                 *ok = false;
2122         } else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2123             if (toFloat)
2124                 l = Length(primitiveValue->computeLength<double>(style, rootStyle, multiplier), Fixed);
2125             else
2126                 l = primitiveValue->computeLength<Length>(style, rootStyle, multiplier);
2127         }
2128         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2129             l = Length(primitiveValue->getDoubleValue(), Percent);
2130         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2131             l = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2132         else if (ok)
2133             *ok = false;
2134     }
2135     return l;
2136 }
2137
2138 static Length convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2139 {
2140     return convertToLength(primitiveValue, style, rootStyle, false, multiplier, ok);
2141 }
2142
2143 static Length convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier = 1, bool *ok = 0)
2144 {
2145     return convertToLength(primitiveValue, style, rootStyle, true, multiplier, ok);
2146 }
2147
2148 template <bool applyFirst>
2149 void CSSStyleSelector::applyDeclaration(CSSMutableStyleDeclaration* styleDeclaration, bool isImportant, bool& inheritedOnly)
2150 {
2151     CSSMutableStyleDeclaration::const_iterator end = styleDeclaration->end();
2152     for (CSSMutableStyleDeclaration::const_iterator it = styleDeclaration->begin(); it != end; ++it) {
2153         const CSSProperty& current = *it;
2154         if (isImportant != current.isImportant())
2155             continue;
2156         if (inheritedOnly && !current.isInherited()) {
2157             if (!current.value()->isInheritedValue())
2158                 continue;
2159             // If the property value is explicitly inherited, we need to apply further non-inherited properties
2160             // as they might override the value inherited here. This is really per-property but that is
2161             // probably not worth optimizing for.
2162             inheritedOnly = false;
2163         }
2164         int property = current.id();
2165         if (applyFirst) {
2166             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2167             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 16, CSS_zoom_is_end_of_first_prop_range);
2168             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2169             // give special priority to font-xxx, color properties, etc
2170             if (property > CSSPropertyLineHeight)
2171                 continue;
2172             // we apply line-height later
2173             if (property == CSSPropertyLineHeight) {
2174                 m_lineHeightValue = current.value();
2175                 continue;
2176             }
2177             applyProperty(current.id(), current.value());
2178             continue;
2179         }
2180         if (property > CSSPropertyLineHeight)
2181             applyProperty(current.id(), current.value());
2182     }
2183 }
2184
2185 template <bool applyFirst>
2186 void CSSStyleSelector::applyDeclarations(bool isImportant, int startIndex, int endIndex, bool& inheritedOnly)
2187 {
2188     if (startIndex == -1)
2189         return;
2190
2191     if (m_style->insideLink() != NotInsideLink) {
2192         for (int i = startIndex; i <= endIndex; ++i) {
2193             CSSMutableStyleDeclaration* styleDeclaration = m_matchedDecls[i].styleDeclaration;
2194             unsigned linkMatchType = m_matchedDecls[i].linkMatchType;
2195             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2196             m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2197             m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2198
2199             applyDeclaration<applyFirst>(styleDeclaration, isImportant, inheritedOnly);
2200         }
2201         m_applyPropertyToRegularStyle = true;
2202         m_applyPropertyToVisitedLinkStyle = false;
2203         return;
2204     }
2205     for (int i = startIndex; i <= endIndex; ++i)
2206         applyDeclaration<applyFirst>(m_matchedDecls[i].styleDeclaration, isImportant, inheritedOnly);
2207 }
2208
2209 unsigned CSSStyleSelector::computeDeclarationHash(MatchedStyleDeclaration* declarations, unsigned size)
2210 {
2211     return StringHasher::hashMemory(declarations, sizeof(MatchedStyleDeclaration) * size);
2212 }
2213
2214 bool operator==(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2215 {
2216     return a.firstUARule == b.firstUARule
2217         && a.lastUARule == b.lastUARule
2218         && a.firstAuthorRule == b.firstAuthorRule
2219         && a.lastAuthorRule == b.lastAuthorRule
2220         && a.firstUserRule == b.firstUserRule
2221         && a.lastUserRule == b.lastUserRule
2222         && a.isCacheable == b.isCacheable;
2223 }
2224
2225 bool operator!=(const CSSStyleSelector::MatchResult& a, const CSSStyleSelector::MatchResult& b)
2226 {
2227     return !(a == b);
2228 }
2229
2230 bool operator==(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2231 {
2232     return a.styleDeclaration == b.styleDeclaration && a.linkMatchType == b.linkMatchType;
2233 }
2234
2235 bool operator!=(const CSSStyleSelector::MatchedStyleDeclaration& a, const CSSStyleSelector::MatchedStyleDeclaration& b)
2236 {
2237     return !(a == b);
2238 }
2239
2240 const RenderStyle* CSSStyleSelector::findFromMatchedDeclarationCache(unsigned hash, const MatchResult& matchResult)
2241 {
2242     ASSERT(hash);
2243
2244     MatchedStyleDeclarationCache::iterator it = m_matchStyleDeclarationCache.find(hash);
2245     if (it == m_matchStyleDeclarationCache.end())
2246         return 0;
2247     MatchedStyleDeclarationCacheItem& cacheItem = it->second;
2248     ASSERT(cacheItem.matchResult.isCacheable);
2249     
2250     size_t size = m_matchedDecls.size();
2251     if (size != cacheItem.matchedStyleDeclarations.size())
2252         return 0;
2253     for (size_t i = 0; i < size; ++i) {
2254         if (m_matchedDecls[i] != cacheItem.matchedStyleDeclarations[i])
2255             return 0;
2256     }
2257     if (cacheItem.matchResult != matchResult)
2258         return 0;
2259     return cacheItem.renderStyle.get();
2260 }
2261
2262 void CSSStyleSelector::addToMatchedDeclarationCache(const RenderStyle* style, unsigned hash, const MatchResult& matchResult)
2263 {
2264     ASSERT(hash);
2265     MatchedStyleDeclarationCacheItem cacheItem;
2266     cacheItem.matchedStyleDeclarations.append(m_matchedDecls);
2267     cacheItem.matchResult = matchResult;
2268     // Note that we don't cache the original RenderStyle instance. It may be further modified.
2269     // The RenderStyle in the cache is really just a holder for the non-inherited substructures and never used as-is.
2270     cacheItem.renderStyle = RenderStyle::clone(style);
2271     m_matchStyleDeclarationCache.add(hash, cacheItem);
2272 }
2273
2274 static bool isCacheableInMatchedDeclarationCache(const RenderStyle* style, const RenderStyle* parentStyle)
2275 {
2276     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2277         return false;
2278     if (style->hasAppearance())
2279         return false;
2280     if (style->zoom() != RenderStyle::initialZoom())
2281         return false;
2282     return true;
2283 }
2284
2285 void CSSStyleSelector::applyMatchedDeclarations(const MatchResult& matchResult)
2286 {
2287     unsigned cacheHash = matchResult.isCacheable ? computeDeclarationHash(m_matchedDecls.data(), m_matchedDecls.size()) : 0;
2288     bool applyInheritedOnly = false;
2289     const RenderStyle* cachedStyle = 0;
2290     if (cacheHash && (cachedStyle = findFromMatchedDeclarationCache(cacheHash, matchResult))) {
2291         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
2292         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
2293         // element context. This is fast and saves memory by reusing the style data structures.
2294         m_style->copyNonInheritedFrom(cachedStyle);
2295         applyInheritedOnly = true; 
2296     }
2297     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
2298     // high-priority properties first, i.e., those properties that other properties depend on.
2299     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
2300     // and (4) normal important.
2301     m_lineHeightValue = 0;
2302     applyDeclarations<true>(false, 0, m_matchedDecls.size() - 1, applyInheritedOnly);
2303     applyDeclarations<true>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2304     applyDeclarations<true>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2305     applyDeclarations<true>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2306
2307     if (cachedStyle && cachedStyle->effectiveZoom() != m_style->effectiveZoom()) {
2308         m_fontDirty = true;
2309         applyInheritedOnly = false;
2310     }
2311
2312     // If our font got dirtied, go ahead and update it now.
2313     updateFont();
2314
2315     // Line-height is set when we are sure we decided on the font-size.
2316     if (m_lineHeightValue)
2317         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2318
2319     // Many properties depend on the font. If it changes we just apply all properties.
2320     if (cachedStyle && cachedStyle->fontDescription() != m_style->fontDescription())
2321         applyInheritedOnly = false;
2322
2323     // Now do the normal priority UA properties.
2324     applyDeclarations<false>(false, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2325     
2326     // Cache our border and background so that we can examine them later.
2327     cacheBorderAndBackground();
2328     
2329     // Now do the author and user normal priority properties and all the !important properties.
2330     applyDeclarations<false>(false, matchResult.lastUARule + 1, m_matchedDecls.size() - 1, applyInheritedOnly);
2331     applyDeclarations<false>(true, matchResult.firstAuthorRule, matchResult.lastAuthorRule, applyInheritedOnly);
2332     applyDeclarations<false>(true, matchResult.firstUserRule, matchResult.lastUserRule, applyInheritedOnly);
2333     applyDeclarations<false>(true, matchResult.firstUARule, matchResult.lastUARule, applyInheritedOnly);
2334     
2335     loadPendingImages();
2336     
2337 #if ENABLE(CSS_SHADERS)
2338     loadPendingShaders();
2339 #endif
2340     
2341     ASSERT(!m_fontDirty);
2342     
2343     if (cachedStyle || !cacheHash)
2344         return;
2345     if (!isCacheableInMatchedDeclarationCache(m_style.get(), m_parentStyle))
2346         return;
2347     addToMatchedDeclarationCache(m_style.get(), cacheHash, matchResult);
2348 }
2349
2350 void CSSStyleSelector::matchPageRules(RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2351 {
2352     m_matchedRules.clear();
2353
2354     if (!rules)
2355         return;
2356
2357     matchPageRulesForList(rules->pageRules(), isLeftPage, isFirstPage, pageName);
2358
2359     // If we didn't match any rules, we're done.
2360     if (m_matchedRules.isEmpty())
2361         return;
2362
2363     // Sort the set of matched rules.
2364     sortMatchedRules();
2365
2366     // Now transfer the set of matched rules over to our list of decls.
2367     for (unsigned i = 0; i < m_matchedRules.size(); i++)
2368         addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
2369 }
2370
2371 void CSSStyleSelector::matchPageRulesForList(const Vector<RuleData>* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2372 {
2373     if (!rules)
2374         return;
2375
2376     unsigned size = rules->size();
2377     for (unsigned i = 0; i < size; ++i) {
2378         const RuleData& ruleData = rules->at(i);
2379         CSSStyleRule* rule = ruleData.rule();
2380         const AtomicString& selectorLocalName = ruleData.selector()->tag().localName();
2381         if (selectorLocalName != starAtom && selectorLocalName != pageName)
2382             continue;
2383         CSSSelector::PseudoType pseudoType = ruleData.selector()->pseudoType();
2384         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2385             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2386             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2387             continue;
2388
2389         // If the rule has no properties to apply, then ignore it.
2390         CSSMutableStyleDeclaration* decl = rule->declaration();
2391         if (!decl || !decl->length())
2392             continue;
2393
2394         // Add this rule to our list of matched rules.
2395         addMatchedRule(&ruleData);
2396     }
2397 }
2398
2399 bool CSSStyleSelector::isLeftPage(int pageIndex) const
2400 {
2401     bool isFirstPageLeft = false;
2402     if (!m_rootElementStyle->isLeftToRightDirection())
2403         isFirstPageLeft = true;
2404
2405     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
2406 }
2407
2408 bool CSSStyleSelector::isFirstPage(int pageIndex) const
2409 {
2410     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
2411     return (!pageIndex);
2412 }
2413
2414 String CSSStyleSelector::pageName(int /* pageIndex */) const
2415 {
2416     // FIXME: Implement page index to page name mapping.
2417     return "";
2418 }
2419
2420 void CSSStyleSelector::applyPropertyToStyle(int id, CSSValue* value, RenderStyle* style)
2421 {
2422     initElement(0);
2423     initForStyleResolve(0, style);
2424     m_style = style;
2425     applyPropertyToCurrentStyle(id, value);
2426 }
2427
2428 void CSSStyleSelector::applyPropertyToCurrentStyle(int id, CSSValue* value)
2429 {
2430     if (value)
2431         applyProperty(id, value);
2432 }
2433
2434 inline bool isValidVisitedLinkProperty(int id)
2435 {
2436     switch(static_cast<CSSPropertyID>(id)) {
2437         case CSSPropertyBackgroundColor:
2438         case CSSPropertyBorderLeftColor:
2439         case CSSPropertyBorderRightColor:
2440         case CSSPropertyBorderTopColor:
2441         case CSSPropertyBorderBottomColor:
2442         case CSSPropertyColor:
2443         case CSSPropertyOutlineColor:
2444         case CSSPropertyWebkitColumnRuleColor:
2445         case CSSPropertyWebkitTextEmphasisColor:
2446         case CSSPropertyWebkitTextFillColor:
2447         case CSSPropertyWebkitTextStrokeColor:
2448         // Also allow shorthands so that inherit/initial still work.
2449         case CSSPropertyBackground:
2450         case CSSPropertyBorderLeft:
2451         case CSSPropertyBorderRight:
2452         case CSSPropertyBorderTop:
2453         case CSSPropertyBorderBottom:
2454         case CSSPropertyOutline:
2455         case CSSPropertyWebkitColumnRule:
2456 #if ENABLE(SVG)
2457         case CSSPropertyFill:
2458         case CSSPropertyStroke:
2459 #endif
2460             return true;
2461         default:
2462             break;
2463     }
2464
2465     return false;
2466 }
2467
2468 class SVGDisplayPropertyGuard {
2469     WTF_MAKE_NONCOPYABLE(SVGDisplayPropertyGuard);
2470 public:
2471     SVGDisplayPropertyGuard(Element*, RenderStyle*);
2472     ~SVGDisplayPropertyGuard();
2473 private:
2474 #if ENABLE(SVG)
2475     RenderStyle* m_style;
2476     EDisplay m_originalDisplayPropertyValue;
2477 #endif
2478 };
2479
2480 #if !ENABLE(SVG)
2481 inline SVGDisplayPropertyGuard::SVGDisplayPropertyGuard(Element*, RenderStyle*)
2482 {
2483 }
2484
2485 inline SVGDisplayPropertyGuard::~SVGDisplayPropertyGuard()
2486 {
2487 }
2488 #else
2489 static inline bool isAcceptableForSVGElement(EDisplay displayPropertyValue)
2490 {
2491     return displayPropertyValue == INLINE || displayPropertyValue == BLOCK || displayPropertyValue == NONE;
2492 }
2493
2494 inline SVGDisplayPropertyGuard::SVGDisplayPropertyGuard(Element* element, RenderStyle* style)
2495 {
2496     if (!(element && element->isSVGElement() && style->styleType() == NOPSEUDO)) {
2497         m_originalDisplayPropertyValue = NONE;
2498         m_style = 0;
2499         return;
2500     }
2501     m_style = style;
2502     m_originalDisplayPropertyValue = style->display();
2503     ASSERT(isAcceptableForSVGElement(m_originalDisplayPropertyValue));
2504 }
2505
2506 inline SVGDisplayPropertyGuard::~SVGDisplayPropertyGuard()
2507 {
2508     if (!m_style || isAcceptableForSVGElement(m_style->display()))
2509         return;
2510     m_style->setDisplay(m_originalDisplayPropertyValue);
2511 }
2512 #endif
2513
2514
2515 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2516 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2517 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2518 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2519 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2520 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
2521 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
2522 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
2523 bool CSSStyleSelector::useSVGZoomRules()
2524 {
2525     return m_element && m_element->isSVGElement();
2526 }
2527
2528 void CSSStyleSelector::applyProperty(int id, CSSValue *value)
2529 {
2530     bool isInherit = m_parentNode && value->isInheritedValue();
2531     bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
2532
2533     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2534
2535     if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2536         // Limit the properties that can be applied to only the ones honored by :visited.
2537         return;
2538     }
2539
2540     CSSPropertyID property = static_cast<CSSPropertyID>(id);
2541
2542     if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(property))
2543         m_parentStyle->setHasExplicitlyInheritedProperties();
2544
2545     // check lookup table for implementations and use when available
2546     const PropertyHandler& handler = m_applyProperty.propertyHandler(property);
2547     if (handler.isValid()) {
2548         if (isInherit)
2549             handler.applyInheritValue(this);
2550         else if (isInitial)
2551             handler.applyInitialValue(this);
2552         else
2553             handler.applyValue(this, value);
2554         return;
2555     }
2556
2557     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
2558
2559     float zoomFactor = m_style->effectiveZoom();
2560
2561     // What follows is a list that maps the CSS properties into their corresponding front-end
2562     // RenderStyle values.  Shorthands (e.g. border, background) occur in this list as well and
2563     // are only hit when mapping "inherit" or "initial" into front-end values.
2564     switch (property) {
2565 // ident only properties
2566     case CSSPropertyBorderCollapse:
2567         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderCollapse, BorderCollapse)
2568         return;
2569     case CSSPropertyCaptionSide:
2570         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(captionSide, CaptionSide)
2571         return;
2572     case CSSPropertyClear:
2573         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(clear, Clear)
2574         return;
2575     case CSSPropertyDisplay: {
2576         SVGDisplayPropertyGuard guard(m_element, m_style.get());
2577         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(display, Display)
2578         return;
2579     }
2580     case CSSPropertyEmptyCells:
2581         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(emptyCells, EmptyCells)
2582         return;
2583     case CSSPropertyFloat:
2584         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(floating, Floating)
2585         return;
2586     case CSSPropertyPageBreakBefore:
2587         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakBefore, PageBreakBefore, PageBreak)
2588         return;
2589     case CSSPropertyPageBreakAfter:
2590         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakAfter, PageBreakAfter, PageBreak)
2591         return;
2592     case CSSPropertyPageBreakInside:
2593         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(pageBreakInside, PageBreakInside, PageBreak)
2594         return;
2595     case CSSPropertyPosition:
2596         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(position, Position)
2597         return;
2598     case CSSPropertyTableLayout:
2599         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(tableLayout, TableLayout)
2600         return;
2601     case CSSPropertyUnicodeBidi:
2602         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(unicodeBidi, UnicodeBidi)
2603         return;
2604     case CSSPropertyTextTransform:
2605         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textTransform, TextTransform)
2606         return;
2607     case CSSPropertyVisibility:
2608         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(visibility, Visibility)
2609         return;
2610     case CSSPropertyWhiteSpace:
2611         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(whiteSpace, WhiteSpace)
2612         return;
2613 // uri || inherit
2614     case CSSPropertyBorderImageSource:
2615     {
2616         HANDLE_INHERIT_AND_INITIAL(borderImageSource, BorderImageSource)
2617         m_style->setBorderImageSource(styleImage(CSSPropertyBorderImageSource, value));
2618         return;
2619     }
2620     case CSSPropertyWebkitMaskBoxImageSource:
2621     {
2622         HANDLE_INHERIT_AND_INITIAL(maskBoxImageSource, MaskBoxImageSource)
2623         m_style->setMaskBoxImageSource(styleImage(CSSPropertyWebkitMaskBoxImageSource, value));
2624         return;
2625     }
2626     case CSSPropertyWordBreak:
2627         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordBreak, WordBreak)
2628         return;
2629     case CSSPropertyWordWrap:
2630         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(wordWrap, WordWrap)
2631         return;
2632     case CSSPropertyWebkitNbspMode:
2633         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(nbspMode, NBSPMode)
2634         return;
2635     case CSSPropertyWebkitLineBreak:
2636         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(khtmlLineBreak, KHTMLLineBreak)
2637         return;
2638     case CSSPropertyWebkitMatchNearestMailBlockquoteColor:
2639         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(matchNearestMailBlockquoteColor, MatchNearestMailBlockquoteColor)
2640         return;
2641
2642     case CSSPropertyResize:
2643     {
2644         HANDLE_INHERIT_AND_INITIAL(resize, Resize)
2645
2646         if (!primitiveValue->getIdent())
2647             return;
2648
2649         EResize r = RESIZE_NONE;
2650         if (primitiveValue->getIdent() == CSSValueAuto) {
2651             if (Settings* settings = m_checker.document()->settings())
2652                 r = settings->textAreasAreResizable() ? RESIZE_BOTH : RESIZE_NONE;
2653         } else
2654             r = *primitiveValue;
2655
2656         m_style->setResize(r);
2657         return;
2658     }
2659     case CSSPropertyVerticalAlign:
2660     {
2661         HANDLE_INHERIT_AND_INITIAL(verticalAlign, VerticalAlign)
2662         if (!primitiveValue)
2663             return;
2664
2665         if (primitiveValue->getIdent()) {
2666           m_style->setVerticalAlign(*primitiveValue);
2667           return;
2668         }
2669
2670         int type = primitiveValue->primitiveType();
2671         Length length;
2672         if (CSSPrimitiveValue::isUnitTypeLength(type))
2673             length = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, zoomFactor);
2674         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2675             length = Length(primitiveValue->getDoubleValue(), Percent);
2676
2677         m_style->setVerticalAlign(LENGTH);
2678         m_style->setVerticalAlignLength(length);
2679         return;
2680     }
2681     case CSSPropertyFontSize:
2682     {
2683         FontDescription fontDescription = m_style->fontDescription();
2684         fontDescription.setKeywordSize(0);
2685         float oldSize = 0;
2686         float size = 0;
2687
2688         bool parentIsAbsoluteSize = false;
2689         if (m_parentNode) {
2690             oldSize = m_parentStyle->fontDescription().specifiedSize();
2691             parentIsAbsoluteSize = m_parentStyle->fontDescription().isAbsoluteSize();
2692         }
2693
2694         if (isInherit) {
2695             size = oldSize;
2696             if (m_parentNode)
2697                 fontDescription.setKeywordSize(m_parentStyle->fontDescription().keywordSize());
2698         } else if (isInitial) {
2699             size = fontSizeForKeyword(m_checker.document(), CSSValueMedium, fontDescription.useFixedDefaultSize());
2700             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
2701         } else if (primitiveValue->getIdent()) {
2702             // Keywords are being used.
2703             switch (primitiveValue->getIdent()) {
2704                 case CSSValueXxSmall:
2705                 case CSSValueXSmall:
2706                 case CSSValueSmall:
2707                 case CSSValueMedium:
2708                 case CSSValueLarge:
2709                 case CSSValueXLarge:
2710                 case CSSValueXxLarge:
2711                 case CSSValueWebkitXxxLarge:
2712                     size = fontSizeForKeyword(m_checker.document(), primitiveValue->getIdent(), fontDescription.useFixedDefaultSize());
2713                     fontDescription.setKeywordSize(primitiveValue->getIdent() - CSSValueXxSmall + 1);
2714                     break;
2715                 case CSSValueLarger:
2716                     size = largerFontSize(oldSize, m_checker.document()->inQuirksMode());
2717                     break;
2718                 case CSSValueSmaller:
2719                     size = smallerFontSize(oldSize, m_checker.document()->inQuirksMode());
2720                     break;
2721                 default:
2722                     return;
2723             }
2724
2725             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize
2726                                               && (primitiveValue->getIdent() == CSSValueLarger
2727                                                   || primitiveValue->getIdent() == CSSValueSmaller));
2728         } else {
2729             int type = primitiveValue->primitiveType();
2730             fontDescription.setIsAbsoluteSize(parentIsAbsoluteSize
2731                                               || (type != CSSPrimitiveValue::CSS_PERCENTAGE
2732                                                   && type != CSSPrimitiveValue::CSS_EMS
2733                                                   && type != CSSPrimitiveValue::CSS_EXS
2734                                                   && type != CSSPrimitiveValue::CSS_REMS));
2735             if (CSSPrimitiveValue::isUnitTypeLength(type))
2736                 size = primitiveValue->computeLength<float>(m_parentStyle, m_rootElementStyle, 1.0, true);
2737             else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2738                 size = (primitiveValue->getFloatValue() * oldSize) / 100.0f;
2739             else
2740                 return;
2741         }
2742
2743         if (size < 0)
2744             return;
2745
2746         setFontSize(fontDescription, size);
2747         setFontDescription(fontDescription);
2748         return;
2749     }
2750
2751     case CSSPropertyWidows:
2752         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(widows, Widows)
2753         return;
2754     case CSSPropertyOrphans:
2755         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(orphans, Orphans)
2756         return;
2757 // length, percent, number
2758     case CSSPropertyLineHeight:
2759     {
2760         HANDLE_INHERIT_AND_INITIAL(lineHeight, LineHeight)
2761         if (!primitiveValue)
2762             return;
2763         Length lineHeight;
2764         int type = primitiveValue->primitiveType();
2765         if (primitiveValue->getIdent() == CSSValueNormal)
2766             lineHeight = Length(-100.0, Percent);
2767         else if (CSSPrimitiveValue::isUnitTypeLength(type)) {
2768             double multiplier = zoomFactor;
2769             if (m_style->textSizeAdjust()) {
2770                 if (Frame* frame = m_checker.document()->frame())
2771                     multiplier *= frame->textZoomFactor();
2772             }
2773             lineHeight = primitiveValue->computeLength<Length>(style(), m_rootElementStyle, multiplier);
2774         } else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
2775             lineHeight = Length((m_style->fontSize() * primitiveValue->getIntValue()) / 100, Fixed);
2776         else if (type == CSSPrimitiveValue::CSS_NUMBER)
2777             lineHeight = Length(primitiveValue->getDoubleValue() * 100.0, Percent);
2778         else
2779             return;
2780         m_style->setLineHeight(lineHeight);
2781         return;
2782     }
2783
2784 // string
2785     case CSSPropertyTextAlign:
2786     {
2787         HANDLE_INHERIT_AND_INITIAL(textAlign, TextAlign)
2788         if (!primitiveValue)
2789             return;
2790         if (primitiveValue->getIdent() == CSSValueWebkitMatchParent) {
2791             if (m_parentStyle->textAlign() == TASTART)
2792                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? LEFT : RIGHT);
2793             else if (m_parentStyle->textAlign() == TAEND)
2794                 m_style->setTextAlign(m_parentStyle->isLeftToRightDirection() ? RIGHT : LEFT);
2795             else
2796                 m_style->setTextAlign(m_parentStyle->textAlign());
2797             return;
2798         }
2799         m_style->setTextAlign(*primitiveValue);
2800         return;
2801     }
2802
2803 // rect
2804     case CSSPropertyClip:
2805     {
2806         Length top;
2807         Length right;
2808         Length bottom;
2809         Length left;
2810         bool hasClip = true;
2811         if (isInherit) {
2812             if (m_parentStyle->hasClip()) {
2813                 top = m_parentStyle->clipTop();
2814                 right = m_parentStyle->clipRight();
2815                 bottom = m_parentStyle->clipBottom();
2816                 left = m_parentStyle->clipLeft();
2817             } else {
2818                 hasClip = false;
2819                 top = right = bottom = left = Length();
2820             }
2821         } else if (isInitial) {
2822             hasClip = false;
2823             top = right = bottom = left = Length();
2824         } else if (!primitiveValue) {
2825             return;
2826         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RECT) {
2827             Rect* rect = primitiveValue->getRectValue();
2828             if (!rect)
2829                 return;
2830             top = convertToIntLength(rect->top(), style(), m_rootElementStyle, zoomFactor);
2831             right = convertToIntLength(rect->right(), style(), m_rootElementStyle, zoomFactor);
2832             bottom = convertToIntLength(rect->bottom(), style(), m_rootElementStyle, zoomFactor);
2833             left = convertToIntLength(rect->left(), style(), m_rootElementStyle, zoomFactor);
2834         } else if (primitiveValue->getIdent() != CSSValueAuto) {
2835             return;
2836         }
2837         m_style->setClip(top, right, bottom, left);
2838         m_style->setHasClip(hasClip);
2839
2840         // rect, ident
2841         return;
2842     }
2843
2844 // lists
2845     case CSSPropertyContent:
2846         // list of string, uri, counter, attr, i
2847     {
2848         // FIXME: In CSS3, it will be possible to inherit content.  In CSS2 it is not.  This
2849         // note is a reminder that eventually "inherit" needs to be supported.
2850
2851         if (isInitial) {
2852             m_style->clearContent();
2853             return;
2854         }
2855
2856         if (!value->isValueList())
2857             return;
2858
2859         bool didSet = false;
2860         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2861             CSSValue* item = i.value();
2862             if (item->isImageGeneratorValue()) {
2863                 m_style->setContent(static_cast<CSSImageGeneratorValue*>(item)->generatedImage(), didSet);
2864                 didSet = true;
2865             }
2866
2867             if (!item->isPrimitiveValue())
2868                 continue;
2869
2870             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2871             switch (contentValue->primitiveType()) {
2872             case CSSPrimitiveValue::CSS_STRING:
2873                 m_style->setContent(contentValue->getStringValue().impl(), didSet);
2874                 didSet = true;
2875                 break;
2876             case CSSPrimitiveValue::CSS_ATTR: {
2877                 // FIXME: Can a namespace be specified for an attr(foo)?
2878                 if (m_style->styleType() == NOPSEUDO)
2879                     m_style->setUnique();
2880                 else
2881                     m_parentStyle->setUnique();
2882                 QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2883                 const AtomicString& value = m_element->getAttribute(attr);
2884                 m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2885                 didSet = true;
2886                 // register the fact that the attribute value affects the style
2887                 m_features.attrsInRules.add(attr.localName().impl());
2888                 break;
2889             }
2890             case CSSPrimitiveValue::CSS_URI: {
2891                 if (!contentValue->isImageValue())
2892                     break;
2893                 m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(contentValue)), didSet);
2894                 didSet = true;
2895                 break;
2896             }
2897             case CSSPrimitiveValue::CSS_COUNTER: {
2898                 Counter* counterValue = contentValue->getCounterValue();
2899                 EListStyleType listStyleType = NoneListStyle;
2900                 int listStyleIdent = counterValue->listStyleIdent();
2901                 if (listStyleIdent != CSSValueNone)
2902                     listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2903                 OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
2904                 m_style->setContent(counter.release(), didSet);
2905                 didSet = true;
2906                 break;
2907             }
2908             case CSSPrimitiveValue::CSS_IDENT:
2909                 switch (contentValue->getIdent()) {
2910                 case CSSValueOpenQuote:
2911                     m_style->setContent(OPEN_QUOTE, didSet);
2912                     didSet = true;
2913                     break;
2914                 case CSSValueCloseQuote:
2915                     m_style->setContent(CLOSE_QUOTE, didSet);
2916                     didSet = true;
2917                     break;
2918                 case CSSValueNoOpenQuote:
2919                     m_style->setContent(NO_OPEN_QUOTE, didSet);
2920                     didSet = true;
2921                     break;
2922                 case CSSValueNoCloseQuote:
2923                     m_style->setContent(NO_CLOSE_QUOTE, didSet);
2924                     didSet = true;
2925                     break;
2926                 default:
2927                     // normal and none do not have any effect.
2928                     {}
2929                 }
2930             }
2931         }
2932         if (!didSet)
2933             m_style->clearContent();
2934         return;
2935     }
2936     case CSSPropertyQuotes:
2937         if (isInherit) {
2938             if (m_parentStyle)
2939                 m_style->setQuotes(m_parentStyle->quotes());
2940             return;
2941         }
2942         if (isInitial) {
2943             m_style->setQuotes(0);
2944             return;
2945         }
2946         if (value->isValueList()) {
2947             CSSValueList* list = static_cast<CSSValueList*>(value);
2948             QuotesData* data = QuotesData::create(list->length());
2949             if (!data)
2950                 return; // Out of memory
2951             String* quotes = data->data();
2952             for (CSSValueListIterator i = list; i.hasMore(); i.advance()) {
2953                 CSSValue* item = i.value();
2954                 ASSERT(item->isPrimitiveValue());
2955                 primitiveValue = static_cast<CSSPrimitiveValue*>(item);
2956                 ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_STRING);
2957                 quotes[i.index()] = primitiveValue->getStringValue();
2958             }
2959             m_style->setQuotes(adoptRef(data));
2960         } else if (primitiveValue) {
2961             ASSERT(primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT);
2962             if (primitiveValue->getIdent() == CSSValueNone)
2963                 m_style->setQuotes(adoptRef(QuotesData::create(0)));
2964         }
2965         return;
2966     case CSSPropertyFontFamily: {
2967         // list of strings and ids
2968         if (isInherit) {
2969             FontDescription parentFontDescription = m_parentStyle->fontDescription();
2970             FontDescription fontDescription = m_style->fontDescription();
2971             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
2972             fontDescription.setFamily(parentFontDescription.firstFamily());
2973             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
2974             setFontDescription(fontDescription);
2975             return;
2976         } else if (isInitial) {
2977             FontDescription initialDesc = FontDescription();
2978             FontDescription fontDescription = m_style->fontDescription();
2979             // We need to adjust the size to account for the generic family change from monospace
2980             // to non-monospace.
2981             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
2982                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
2983             fontDescription.setGenericFamily(initialDesc.genericFamily());
2984             if (!initialDesc.firstFamily().familyIsEmpty())
2985                 fontDescription.setFamily(initialDesc.firstFamily());
2986             setFontDescription(fontDescription);
2987             return;
2988         }
2989
2990         if (!value->isValueList())
2991             return;
2992         FontDescription fontDescription = m_style->fontDescription();
2993         FontFamily& firstFamily = fontDescription.firstFamily();
2994         FontFamily* currFamily = 0;
2995
2996         // Before mapping in a new font-family property, we should reset the generic family.
2997         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
2998         fontDescription.setGenericFamily(FontDescription::NoFamily);
2999
3000         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3001             CSSValue* item = i.value();
3002             if (!item->isPrimitiveValue())
3003                 continue;
3004             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
3005             AtomicString face;
3006             Settings* settings = m_checker.document()->settings();
3007             if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_STRING) {
3008                 if (contentValue->isFontFamilyValue())
3009                     face = static_cast<FontFamilyValue*>(contentValue)->familyName();
3010             } else if (contentValue->primitiveType() == CSSPrimitiveValue::CSS_IDENT && settings) {
3011                 switch (contentValue->getIdent()) {
3012                     case CSSValueWebkitBody:
3013                         face = settings->standardFontFamily();
3014                         break;
3015                     case CSSValueSerif:
3016                         face = serifFamily;
3017                         fontDescription.setGenericFamily(FontDescription::SerifFamily);
3018                         break;
3019                     case CSSValueSansSerif:
3020                         face = sansSerifFamily;
3021                         fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3022                         break;
3023                     case CSSValueCursive:
3024                         face = cursiveFamily;
3025                         fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3026                         break;
3027                     case CSSValueFantasy:
3028                         face = fantasyFamily;
3029                         fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3030                         break;
3031                     case CSSValueMonospace:
3032                         face = monospaceFamily;
3033                         fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3034                         break;
3035                     case CSSValueWebkitPictograph:
3036                         face = pictographFamily;
3037                         fontDescription.setGenericFamily(FontDescription::PictographFamily);
3038                         break;
3039                 }
3040             }
3041
3042             if (!face.isEmpty()) {
3043                 if (!currFamily) {
3044                     // Filling in the first family.
3045                     firstFamily.setFamily(face);
3046                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
3047                     currFamily = &firstFamily;
3048                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
3049                 } else {
3050                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
3051                     newFamily->setFamily(face);
3052                     currFamily->appendFamily(newFamily);
3053                     currFamily = newFamily.get();
3054                 }
3055             }
3056         }
3057
3058         // We can't call useFixedDefaultSize() until all new font families have been added
3059         // If currFamily is non-zero then we set at least one family on this description.
3060         if (currFamily) {
3061             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
3062                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
3063
3064             setFontDescription(fontDescription);
3065         }
3066         return;
3067     }
3068     case CSSPropertyTextDecoration: {
3069         // list of ident
3070         HANDLE_INHERIT_AND_INITIAL(textDecoration, TextDecoration)
3071         ETextDecoration t = RenderStyle::initialTextDecoration();
3072         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3073             CSSValue* item = i.value();
3074             ASSERT(item->isPrimitiveValue());
3075             t |= *static_cast<CSSPrimitiveValue*>(item);
3076         }
3077         m_style->setTextDecoration(t);
3078         return;
3079     }
3080
3081     case CSSPropertyZoom:
3082     {
3083         // Reset the zoom in effect before we do anything.  This allows the setZoom method to accurately compute a new
3084         // zoom in effect.
3085         setEffectiveZoom(m_parentStyle ? m_parentStyle->effectiveZoom() : RenderStyle::initialZoom());
3086
3087         if (isInherit)
3088             setZoom(m_parentStyle->zoom());
3089         else if (isInitial || primitiveValue->getIdent() == CSSValueNormal)
3090             setZoom(RenderStyle::initialZoom());
3091         else if (primitiveValue->getIdent() == CSSValueReset) {
3092             setEffectiveZoom(RenderStyle::initialZoom());
3093             setZoom(RenderStyle::initialZoom());
3094         } else if (primitiveValue->getIdent() == CSSValueDocument) {
3095             float docZoom = m_checker.document()->renderer()->style()->zoom();
3096             setEffectiveZoom(docZoom);
3097             setZoom(docZoom);
3098         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE) {
3099             if (primitiveValue->getFloatValue())
3100                 setZoom(primitiveValue->getFloatValue() / 100.0f);
3101         } else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) {
3102             if (primitiveValue->getFloatValue())
3103                 setZoom(primitiveValue->getFloatValue());
3104         }
3105         return;
3106     }
3107 // shorthand properties
3108     case CSSPropertyBackground:
3109         if (isInitial) {
3110             m_style->clearBackgroundLayers();
3111             m_style->setBackgroundColor(Color());
3112         }
3113         else if (isInherit) {
3114             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3115             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3116         }
3117         return;
3118     case CSSPropertyWebkitMask:
3119         if (isInitial)
3120             m_style->clearMaskLayers();
3121         else if (isInherit)
3122             m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
3123         return;
3124     case CSSPropertyFont:
3125         if (isInherit) {
3126             FontDescription fontDescription = m_parentStyle->fontDescription();
3127             m_style->setLineHeight(m_parentStyle->lineHeight());
3128             m_lineHeightValue = 0;
3129             setFontDescription(fontDescription);
3130         } else if (isInitial) {
3131             Settings* settings = m_checker.document()->settings();
3132             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3133             if (!settings)
3134                 return;
3135             FontDescription fontDescription;
3136             fontDescription.setGenericFamily(FontDescription::StandardFamily);
3137             fontDescription.setRenderingMode(settings->fontRenderingMode());
3138             fontDescription.setUsePrinterFont(m_checker.document()->printing());
3139             const AtomicString& standardFontFamily = m_checker.document()->settings()->standardFontFamily();
3140             if (!standardFontFamily.isEmpty()) {
3141                 fontDescription.firstFamily().setFamily(standardFontFamily);
3142                 fontDescription.firstFamily().appendFamily(0);
3143             }
3144             fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3145             setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueMedium, false));
3146             m_style->setLineHeight(RenderStyle::initialLineHeight());
3147             m_lineHeightValue = 0;
3148             setFontDescription(fontDescription);
3149         } else if (primitiveValue) {
3150             m_style->setLineHeight(RenderStyle::initialLineHeight());
3151             m_lineHeightValue = 0;
3152
3153             FontDescription fontDescription;
3154             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3155
3156             // Double-check and see if the theme did anything.  If not, don't bother updating the font.
3157             if (fontDescription.isAbsoluteSize()) {
3158                 // Make sure the rendering mode and printer font settings are updated.
3159                 Settings* settings = m_checker.document()->settings();
3160                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3161                 if (!settings)
3162                     return;
3163                 fontDescription.setRenderingMode(settings->fontRenderingMode());
3164                 fontDescription.setUsePrinterFont(m_checker.document()->printing());
3165
3166                 // Handle the zoom factor.
3167                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3168                 setFontDescription(fontDescription);
3169             }
3170         } else if (value->isFontValue()) {
3171             FontValue *font = static_cast<FontValue*>(value);
3172             if (!font->style || !font->variant || !font->weight ||
3173                  !font->size || !font->lineHeight || !font->family)
3174                 return;
3175             applyProperty(CSSPropertyFontStyle, font->style.get());
3176             applyProperty(CSSPropertyFontVariant, font->variant.get());
3177             applyProperty(CSSPropertyFontWeight, font->weight.get());
3178             // The previous properties can dirty our font but they don't try to read the font's
3179             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3180             // need query the dirtied font's x-height to get the computed size. To be safe in this
3181             // case, let's just update the font now.
3182             updateFont();
3183             applyProperty(CSSPropertyFontSize, font->size.get());
3184
3185             m_lineHeightValue = font->lineHeight.get();
3186
3187             applyProperty(CSSPropertyFontFamily, font->family.get());
3188         }
3189         return;
3190
3191     case CSSPropertyOutline:
3192         if (isInherit) {
3193             m_style->setOutlineWidth(m_parentStyle->outlineWidth());
3194             m_style->setOutlineColor(m_parentStyle->outlineColor().isValid() ? m_parentStyle->outlineColor() : m_parentStyle->color());
3195             m_style->setOutlineStyle(m_parentStyle->outlineStyle());
3196         }
3197         else if (isInitial)
3198             m_style->resetOutline();
3199         return;
3200
3201     // CSS3 Properties
3202     case CSSPropertyWebkitAppearance:
3203         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(appearance, Appearance)
3204         return;
3205     case CSSPropertyBorderImage:
3206     case CSSPropertyWebkitBorderImage:
3207     case CSSPropertyWebkitMaskBoxImage: {
3208         if (isInherit) {
3209             HANDLE_INHERIT_COND(CSSPropertyBorderImage, borderImage, BorderImage)
3210             HANDLE_INHERIT_COND(CSSPropertyWebkitBorderImage, borderImage, BorderImage)
3211             HANDLE_INHERIT_COND(CSSPropertyWebkitMaskBoxImage, maskBoxImage, MaskBoxImage)
3212             return;
3213         } else if (isInitial) {
3214             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyBorderImage, BorderImage, NinePieceImage)
3215             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitBorderImage, BorderImage, NinePieceImage)
3216             HANDLE_INITIAL_COND_WITH_VALUE(CSSPropertyWebkitMaskBoxImage, MaskBoxImage, NinePieceImage)
3217             return;
3218         }
3219
3220         NinePieceImage image;
3221         if (property == CSSPropertyWebkitMaskBoxImage)
3222             image.setMaskDefaults();
3223         mapNinePieceImage(property, value, image);
3224
3225         if (id != CSSPropertyWebkitMaskBoxImage)
3226             m_style->setBorderImage(image);
3227         else
3228             m_style->setMaskBoxImage(image);
3229         return;
3230     }
3231     case CSSPropertyBorderImageOutset:
3232     case CSSPropertyWebkitMaskBoxImageOutset: {
3233         bool isBorderImage = id == CSSPropertyBorderImageOutset;
3234         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3235         if (isInherit)
3236             image.copyOutsetFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3237         else if (isInitial)
3238             image.setOutset(LengthBox());
3239         else
3240             image.setOutset(mapNinePieceImageQuad(value));
3241
3242         if (isBorderImage)
3243             m_style->setBorderImage(image);
3244         else
3245             m_style->setMaskBoxImage(image);
3246         return;
3247     }
3248     case CSSPropertyBorderImageRepeat:
3249     case CSSPropertyWebkitMaskBoxImageRepeat: {
3250         bool isBorderImage = id == CSSPropertyBorderImageRepeat;
3251         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3252         if (isInherit)
3253             image.copyRepeatFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3254         else if (isInitial) {
3255             image.setHorizontalRule(StretchImageRule);
3256             image.setVerticalRule(StretchImageRule);
3257         } else
3258             mapNinePieceImageRepeat(value, image);
3259
3260         if (isBorderImage)
3261             m_style->setBorderImage(image);
3262         else
3263             m_style->setMaskBoxImage(image);
3264         return;
3265     }
3266     case CSSPropertyBorderImageSlice:
3267     case CSSPropertyWebkitMaskBoxImageSlice: {
3268         bool isBorderImage = id == CSSPropertyBorderImageSlice;
3269         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3270         if (isInherit)
3271             image.copyImageSlicesFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3272         else if (isInitial) {
3273             // Masks have a different initial value for slices. Preserve the value of 0 for backwards compatibility.
3274             image.setImageSlices(isBorderImage ? LengthBox(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent)) : LengthBox());
3275             image.setFill(false);
3276         } else
3277             mapNinePieceImageSlice(value, image);
3278
3279         if (isBorderImage)
3280             m_style->setBorderImage(image);
3281         else
3282             m_style->setMaskBoxImage(image);
3283         return;
3284     }
3285     case CSSPropertyBorderImageWidth:
3286     case CSSPropertyWebkitMaskBoxImageWidth: {
3287         bool isBorderImage = id == CSSPropertyBorderImageWidth;
3288         NinePieceImage image(isBorderImage ? m_style->borderImage() : m_style->maskBoxImage());
3289         if (isInherit)
3290             image.copyBorderSlicesFrom(isBorderImage ? m_parentStyle->borderImage() : m_parentStyle->maskBoxImage());
3291         else if (isInitial) {
3292             // Masks have a different initial value for slices. They use an 'auto' value rather than trying to fit to the border.
3293             image.setBorderSlices(isBorderImage ? LengthBox(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative)) : LengthBox());
3294         } else
3295             image.setBorderSlices(mapNinePieceImageQuad(value));
3296
3297         if (isBorderImage)
3298             m_style->setBorderImage(image);
3299         else
3300             m_style->setMaskBoxImage(image);
3301         return;
3302     }
3303     case CSSPropertyImageRendering:
3304         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(imageRendering, ImageRendering);
3305         return;
3306     case CSSPropertyTextShadow:
3307     case CSSPropertyBoxShadow:
3308     case CSSPropertyWebkitBoxShadow: {
3309         if (isInherit) {
3310             if (id == CSSPropertyTextShadow)
3311                 return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
3312             return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
3313         }
3314         if (isInitial || primitiveValue) // initial | none
3315             return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
3316
3317         if (!value->isValueList())
3318             return;
3319
3320         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3321             CSSValue* currValue = i.value();
3322             if (!currValue->isShadowValue())
3323                 continue;
3324             ShadowValue* item = static_cast<ShadowValue*>(currValue);
3325             int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3326             int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3327             int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3328             int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3329             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3330             Color color;
3331             if (item->color)
3332                 color = getColorFromPrimitiveValue(item->color.get());
3333             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(x, y, blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3334             if (id == CSSPropertyTextShadow)
3335                 m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3336             else
3337                 m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3338         }
3339         return;
3340     }
3341     case CSSPropertyWebkitBoxReflect: {
3342         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3343         if (primitiveValue) {
3344             m_style->setBoxReflect(RenderStyle::initialBoxReflect());
3345             return;
3346         }
3347
3348         if (!value->isReflectValue())
3349             return;
3350
3351         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3352         RefPtr<StyleReflection> reflection = StyleReflection::create();
3353         reflection->setDirection(reflectValue->direction());
3354         if (reflectValue->offset()) {
3355             int type = reflectValue->offset()->primitiveType();
3356             if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3357                 reflection->setOffset(Length(reflectValue->offset()->getDoubleValue(), Percent));
3358             else
3359                 reflection->setOffset(reflectValue->offset()->computeLength<Length>(style(), m_rootElementStyle, zoomFactor));
3360         }
3361         NinePieceImage mask;
3362         mask.setMaskDefaults();
3363         mapNinePieceImage(property, reflectValue->mask(), mask);
3364         reflection->setMask(mask);
3365
3366         m_style->setBoxReflect(reflection.release());
3367         return;
3368     }
3369     case CSSPropertyOpacity:
3370         HANDLE_INHERIT_AND_INITIAL(opacity, Opacity)
3371         if (!primitiveValue || primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3372             return; // Error case.
3373         // Clamp opacity to the range 0-1
3374         m_style->setOpacity(clampTo<float>(primitiveValue->getDoubleValue(), 0, 1));
3375         return;
3376     case CSSPropertyWebkitBoxAlign:
3377         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxAlign, BoxAlign)
3378         return;
3379     case CSSPropertySrc: // Only used in @font-face rules.
3380         return;
3381     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3382         return;
3383     case CSSPropertyWebkitBackfaceVisibility:
3384         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(backfaceVisibility, BackfaceVisibility)
3385         return;
3386     case CSSPropertyWebkitBoxDirection:
3387         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxDirection, BoxDirection)
3388         return;
3389     case CSSPropertyWebkitBoxLines:
3390         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxLines, BoxLines)
3391         return;
3392     case CSSPropertyWebkitBoxOrient:
3393         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrient, BoxOrient)
3394         return;
3395     case CSSPropertyWebkitBoxPack:
3396     {
3397         HANDLE_INHERIT_AND_INITIAL(boxPack, BoxPack)
3398         if (!primitiveValue)
3399             return;
3400         EBoxAlignment boxPack = *primitiveValue;
3401         if (boxPack != BSTRETCH && boxPack != BBASELINE)
3402             m_style->setBoxPack(boxPack);
3403         return;
3404     }
3405     case CSSPropertyWebkitBoxFlex:
3406         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlex, BoxFlex)
3407         return;
3408     case CSSPropertyWebkitBoxFlexGroup:
3409         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxFlexGroup, BoxFlexGroup)
3410         return;
3411     case CSSPropertyWebkitBoxOrdinalGroup:
3412         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxOrdinalGroup, BoxOrdinalGroup)
3413         return;
3414     case CSSPropertyBoxSizing:
3415         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(boxSizing, BoxSizing);
3416         return;
3417     case CSSPropertyWebkitColumnSpan:
3418         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(columnSpan, ColumnSpan)
3419         return;
3420     case CSSPropertyWebkitColumnRuleStyle:
3421         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnRuleStyle, ColumnRuleStyle, BorderStyle)
3422         return;
3423     case CSSPropertyWebkitColumnBreakBefore:
3424         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakBefore, ColumnBreakBefore, PageBreak)
3425         return;
3426     case CSSPropertyWebkitColumnBreakAfter:
3427         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakAfter, ColumnBreakAfter, PageBreak)
3428         return;
3429     case CSSPropertyWebkitColumnBreakInside:
3430         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(columnBreakInside, ColumnBreakInside, PageBreak)
3431         return;
3432     case CSSPropertyWebkitColumnRule:
3433         if (isInherit) {
3434             m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
3435             m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
3436             m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
3437         }
3438         else if (isInitial)
3439             m_style->resetColumnRule();
3440         return;
3441     case CSSPropertyWebkitLineGrid:
3442         HANDLE_INHERIT_AND_INITIAL(lineGrid, LineGrid);
3443         if (primitiveValue->getIdent() == CSSValueNone)
3444             m_style->setLineGrid(nullAtom);
3445         else
3446             m_style->setLineGrid(primitiveValue->getStringValue());
3447         return;
3448     case CSSPropertyWebkitLineGridSnap:
3449         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(lineGridSnap, LineGridSnap)
3450         return;
3451     case CSSPropertyWebkitRegionBreakBefore:
3452         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakBefore, RegionBreakBefore, PageBreak)
3453         return;
3454     case CSSPropertyWebkitRegionBreakAfter:
3455         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakAfter, RegionBreakAfter, PageBreak)
3456         return;
3457     case CSSPropertyWebkitRegionBreakInside:
3458         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE_WITH_VALUE(regionBreakInside, RegionBreakInside, PageBreak)
3459         return;
3460     case CSSPropertyWebkitMarquee:
3461         if (!m_parentNode || !value->isInheritedValue())
3462             return;
3463         m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
3464         m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
3465         m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
3466         m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
3467         m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
3468         return;
3469     case CSSPropertyWebkitMarqueeRepetition: {
3470         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3471         if (!primitiveValue)
3472             return;
3473         if (primitiveValue->getIdent() == CSSValueInfinite)
3474             m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
3475         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
3476             m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
3477         return;
3478     }
3479     case CSSPropertyWebkitMarqueeSpeed: {
3480         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3481         if (!primitiveValue)
3482             return;
3483         if (primitiveValue->getIdent()) {
3484             switch (primitiveValue->getIdent()) {
3485                 case CSSValueSlow:
3486                     m_style->setMarqueeSpeed(500); // 500 msec.
3487                     break;
3488                 case CSSValueNormal:
3489                     m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
3490                     break;
3491                 case CSSValueFast:
3492                     m_style->setMarqueeSpeed(10); // 10msec. Super fast.
3493                     break;
3494             }
3495         }
3496         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
3497             m_style->setMarqueeSpeed(1000 * primitiveValue->getIntValue());
3498         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
3499             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3500         else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER) // For scrollamount support.
3501             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3502         return;
3503     }
3504     case CSSPropertyWebkitMarqueeIncrement: {
3505         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3506         if (!primitiveValue)
3507             return;
3508         if (primitiveValue->getIdent()) {
3509             switch (primitiveValue->getIdent()) {
3510                 case CSSValueSmall:
3511                     m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3512                     break;
3513                 case CSSValueNormal:
3514                     m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3515                     break;
3516                 case CSSValueLarge:
3517                     m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3518                     break;
3519             }
3520         }
3521         else {
3522             bool ok = true;
3523             Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle, 1, &ok);
3524             if (ok)
3525                 m_style->setMarqueeIncrement(marqueeLength);
3526         }
3527         return;
3528     }
3529     case CSSPropertyWebkitMarqueeStyle:
3530         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeBehavior, MarqueeBehavior)
3531         return;
3532     case CSSPropertyWebkitFlowInto:
3533         HANDLE_INHERIT_AND_INITIAL(flowThread, FlowThread);
3534         if (primitiveValue->getIdent() == CSSValueAuto)
3535             m_style->setFlowThread(nullAtom);
3536         else
3537             m_style->setFlowThread(primitiveValue->getStringValue());
3538         return;
3539     case CSSPropertyWebkitFlowFrom:
3540         HANDLE_INHERIT_AND_INITIAL(regionThread, RegionThread);
3541         if (primitiveValue->getIdent() == CSSValueNone)
3542             m_style->setRegionThread(nullAtom);
3543         else
3544             m_style->setRegionThread(primitiveValue->getStringValue());
3545         return;
3546     case CSSPropertyWebkitRegionOverflow:
3547         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(regionOverflow, RegionOverflow);
3548         return;
3549     case CSSPropertyWebkitMarqueeDirection:
3550         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(marqueeDirection, MarqueeDirection)
3551         return;
3552     case CSSPropertyWebkitUserDrag:
3553         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userDrag, UserDrag)
3554         return;
3555     case CSSPropertyWebkitUserModify:
3556         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userModify, UserModify)
3557         return;
3558     case CSSPropertyWebkitUserSelect:
3559         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(userSelect, UserSelect)
3560         return;
3561
3562     case CSSPropertyTextOverflow: {
3563         // This property is supported by WinIE, and so we leave off the "-webkit-" in order to
3564         // work with WinIE-specific pages that use the property.
3565         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textOverflow, TextOverflow)
3566         return;
3567     }
3568     case CSSPropertyWebkitLineClamp: {
3569         HANDLE_INHERIT_AND_INITIAL(lineClamp, LineClamp)
3570         if (!primitiveValue)
3571             return;
3572         int type = primitiveValue->primitiveType();
3573         if (type == CSSPrimitiveValue::CSS_NUMBER)
3574             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_NUMBER), LineClampLineCount));
3575         else if (type == CSSPrimitiveValue::CSS_PERCENTAGE)
3576             m_style->setLineClamp(LineClampValue(primitiveValue->getIntValue(CSSPrimitiveValue::CSS_PERCENTAGE), LineClampPercentage));
3577         return;
3578     }
3579     case CSSPropertyWebkitHyphens:
3580         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(hyphens, Hyphens);
3581         return;
3582     case CSSPropertyWebkitHyphenateLimitAfter: {
3583         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitAfter, HyphenationLimitAfter);
3584         if (primitiveValue->getIdent() == CSSValueAuto)
3585             m_style->setHyphenationLimitAfter(-1);
3586         else
3587             m_style->setHyphenationLimitAfter(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3588         return;
3589     }
3590     case CSSPropertyWebkitHyphenateLimitBefore: {
3591         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitBefore, HyphenationLimitBefore);
3592         if (primitiveValue->getIdent() == CSSValueAuto)
3593             m_style->setHyphenationLimitBefore(-1);
3594         else
3595             m_style->setHyphenationLimitBefore(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3596         return;
3597     }
3598     case CSSPropertyWebkitHyphenateLimitLines: {
3599         HANDLE_INHERIT_AND_INITIAL(hyphenationLimitLines, HyphenationLimitLines);
3600         if (primitiveValue->getIdent() == CSSValueNoLimit)
3601             m_style->setHyphenationLimitLines(-1);
3602         else
3603             m_style->setHyphenationLimitLines(primitiveValue->getValue<short>(CSSPrimitiveValue::CSS_NUMBER));
3604         return;
3605     }
3606     case CSSPropertyWebkitLocale: {
3607         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3608         if (primitiveValue->getIdent() == CSSValueAuto)
3609             m_style->setLocale(nullAtom);
3610         else
3611             m_style->setLocale(primitiveValue->getStringValue());
3612         FontDescription fontDescription = m_style->fontDescription();
3613         fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
3614         setFontDescription(fontDescription);
3615         return;
3616     }
3617     case CSSPropertyWebkitBorderFit:
3618         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(borderFit, BorderFit);
3619         return;
3620     case CSSPropertyWebkitTextSizeAdjust: {
3621         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
3622         if (!primitiveValue || !primitiveValue->getIdent())
3623             return;
3624         setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
3625         return;
3626     }
3627     case CSSPropertyWebkitTextSecurity:
3628         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textSecurity, TextSecurity)
3629         return;
3630
3631 #if ENABLE(DASHBOARD_SUPPORT)
3632     case CSSPropertyWebkitDashboardRegion: {
3633         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3634         if (!primitiveValue)
3635             return;
3636
3637         if (primitiveValue->getIdent() == CSSValueNone) {
3638             m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
3639             return;
3640         }
3641
3642         DashboardRegion *region = primitiveValue->getDashboardRegionValue();
3643         if (!region)
3644             return;
3645
3646         DashboardRegion *first = region;
3647         while (region) {
3648             Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
3649             Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
3650             Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
3651             Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
3652             if (region->m_isCircle)
3653                 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3654             else if (region->m_isRectangle)
3655                 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3656             region = region->m_next.get();
3657         }
3658
3659         m_element->document()->setHasDashboardRegions(true);
3660
3661         return;
3662     }
3663 #endif
3664     case CSSPropertyWebkitRtlOrdering:
3665         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(rtlOrdering, RTLOrdering)
3666         return;
3667     case CSSPropertyWebkitTextStrokeWidth: {
3668         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3669         float width = 0;
3670         switch (primitiveValue->getIdent()) {
3671             case CSSValueThin:
3672             case CSSValueMedium:
3673             case CSSValueThick: {
3674                 double result = 1.0 / 48;
3675                 if (primitiveValue->getIdent() == CSSValueMedium)
3676                     result *= 3;
3677                 else if (primitiveValue->getIdent() == CSSValueThick)
3678                     result *= 5;
3679                 width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3680                 break;
3681             }
3682             default:
3683                 width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3684                 break;
3685         }
3686         m_style->setTextStrokeWidth(width);
3687         return;
3688     }
3689     case CSSPropertyWebkitTransform: {
3690         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3691         TransformOperations operations;
3692         createTransformOperations(value, style(), m_rootElementStyle, operations);
3693         m_style->setTransform(operations);
3694         return;
3695     }
3696     case CSSPropertyWebkitTransformStyle:
3697         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(transformStyle3D, TransformStyle3D)
3698         return;
3699     case CSSPropertyWebkitPrintColorAdjust:
3700         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(printColorAdjust, PrintColorAdjust);
3701         return;
3702     case CSSPropertyWebkitPerspective: {
3703         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3704         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3705             m_style->setPerspective(0);
3706             return;
3707         }
3708
3709         float perspectiveValue;
3710         int type = primitiveValue->primitiveType();
3711         if (CSSPrimitiveValue::isUnitTypeLength(type))
3712             perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3713         else if (type == CSSPrimitiveValue::CSS_NUMBER) {
3714             // For backward compatibility, treat valueless numbers as px.
3715             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3716         } else
3717             return;
3718
3719         if (perspectiveValue >= 0.0f)
3720             m_style->setPerspective(perspectiveValue);
3721         return;
3722     }
3723     case CSSPropertyWebkitAnimation:
3724         if (isInitial)
3725             m_style->clearAnimations();
3726         else if (isInherit)
3727             m_style->inheritAnimations(m_parentStyle->animations());
3728         return;
3729     case CSSPropertyWebkitTransition:
3730         if (isInitial)
3731             m_style->clearTransitions();
3732         else if (isInherit)
3733             m_style->inheritTransitions(m_parentStyle->transitions());
3734         return;
3735     case CSSPropertyPointerEvents:
3736     {
3737 #if ENABLE(DASHBOARD_SUPPORT)
3738         // <rdar://problem/6561077> Work around the Stocks widget's misuse of the
3739         // pointer-events property by not applying it in Dashboard.
3740         Settings* settings = m_checker.document()->settings();
3741         if (settings && settings->usesDashboardBackwardCompatibilityMode())
3742             return;
3743 #endif
3744         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(pointerEvents, PointerEvents)
3745         return;
3746     }
3747 #if ENABLE(TOUCH_EVENTS)
3748     case CSSPropertyWebkitTapHighlightColor: {
3749         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
3750         if (!primitiveValue)
3751             break;
3752
3753         Color col = getColorFromPrimitiveValue(primitiveValue);
3754         m_style->setTapHighlightColor(col);
3755         return;
3756     }
3757 #endif
3758     case CSSPropertyWebkitColorCorrection:
3759         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(colorSpace, ColorSpace);
3760         return;
3761     case CSSPropertySize:
3762         applyPageSizeProperty(value);
3763         return;
3764     case CSSPropertySpeak:
3765         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(speak, Speak);
3766         return;
3767     case CSSPropertyInvalid:
3768         return;
3769     // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
3770     case CSSPropertyWebkitBorderEnd:
3771     case CSSPropertyWebkitBorderEndColor:
3772     case CSSPropertyWebkitBorderEndStyle:
3773     case CSSPropertyWebkitBorderEndWidth:
3774     case CSSPropertyWebkitBorderStart:
3775     case CSSPropertyWebkitBorderStartColor:
3776     case CSSPropertyWebkitBorderStartStyle:
3777     case CSSPropertyWebkitBorderStartWidth:
3778     case CSSPropertyWebkitBorderBefore:
3779     case CSSPropertyWebkitBorderBeforeColor:
3780     case CSSPropertyWebkitBorderBeforeStyle:
3781     case CSSPropertyWebkitBorderBeforeWidth:
3782     case CSSPropertyWebkitBorderAfter:
3783     case CSSPropertyWebkitBorderAfterColor:
3784     case CSSPropertyWebkitBorderAfterStyle:
3785     case CSSPropertyWebkitBorderAfterWidth:
3786     case CSSPropertyWebkitMarginEnd:
3787     case CSSPropertyWebkitMarginStart:
3788     case CSSPropertyWebkitMarginBefore:
3789     case CSSPropertyWebkitMarginAfter:
3790     case CSSPropertyWebkitMarginCollapse:
3791     case CSSPropertyWebkitMarginBeforeCollapse:
3792     case CSSPropertyWebkitMarginTopCollapse:
3793     case CSSPropertyWebkitMarginAfterCollapse:
3794     case CSSPropertyWebkitMarginBottomCollapse:
3795     case CSSPropertyWebkitPaddingEnd:
3796     case CSSPropertyWebkitPaddingStart:
3797     case CSSPropertyWebkitPaddingBefore:
3798     case CSSPropertyWebkitPaddingAfter:
3799     case CSSPropertyWebkitLogicalWidth:
3800     case CSSPropertyWebkitLogicalHeight:
3801     case CSSPropertyWebkitMinLogicalWidth:
3802     case CSSPropertyWebkitMinLogicalHeight:
3803     case CSSPropertyWebkitMaxLogicalWidth:
3804     case CSSPropertyWebkitMaxLogicalHeight:
3805     {
3806         int newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3807         ASSERT(newId != id);
3808         return applyProperty(newId, value);
3809     }
3810     case CSSPropertyFontStretch:
3811     case CSSPropertyPage:
3812     case CSSPropertyTextLineThrough:
3813     case CSSPropertyTextLineThroughColor:
3814     case CSSPropertyTextLineThroughMode:
3815     case CSSPropertyTextLineThroughStyle:
3816     case CSSPropertyTextLineThroughWidth:
3817     case CSSPropertyTextOverline:
3818     case CSSPropertyTextOverlineColor:
3819     case CSSPropertyTextOverlineMode:
3820     case CSSPropertyTextOverlineStyle:
3821     case CSSPropertyTextOverlineWidth:
3822     case CSSPropertyTextUnderline:
3823     case CSSPropertyTextUnderlineColor:
3824     case CSSPropertyTextUnderlineMode:
3825     case CSSPropertyTextUnderlineStyle:
3826     case CSSPropertyTextUnderlineWidth:
3827     case CSSPropertyWebkitFontSizeDelta:
3828     case CSSPropertyWebkitTextDecorationsInEffect:
3829     case CSSPropertyWebkitTextStroke:
3830     case CSSPropertyWebkitTextEmphasis:
3831         return;
3832
3833     // CSS Text Layout Module Level 3: Vertical writing support
3834     case CSSPropertyWebkitWritingMode: {
3835         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(writingMode, WritingMode)
3836         if (!isInherit && !isInitial && m_element && m_element == m_element->document()->documentElement())
3837             m_element->document()->setWritingModeSetOnDocumentElement(true);
3838         FontDescription fontDescription = m_style->fontDescription();
3839         fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
3840         setFontDescription(fontDescription);
3841         return;
3842     }
3843
3844     case CSSPropertyWebkitLineBoxContain: {
3845         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)