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