Optimize stylesheet insertions
[WebKit-https.git] / Source / WebCore / css / StyleResolver.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  * Copyright (C) 2012 Google Inc. All rights reserved.
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Library General Public
15  * License as published by the Free Software Foundation; either
16  * version 2 of the License, or (at your option) any later version.
17  *
18  * This library is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  * Library General Public License for more details.
22  *
23  * You should have received a copy of the GNU Library General Public License
24  * along with this library; see the file COPYING.LIB.  If not, write to
25  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26  * Boston, MA 02110-1301, USA.
27  */
28
29 #include "config.h"
30 #include "StyleResolver.h"
31
32 #include "Attribute.h"
33 #include "CSSBorderImage.h"
34 #include "CSSCalculationValue.h"
35 #include "CSSCursorImageValue.h"
36 #include "CSSFontFaceRule.h"
37 #include "CSSFontSelector.h"
38 #include "CSSImportRule.h"
39 #include "CSSLineBoxContainValue.h"
40 #include "CSSMediaRule.h"
41 #include "CSSPageRule.h"
42 #include "CSSParser.h"
43 #include "CSSPrimitiveValueMappings.h"
44 #include "CSSPropertyNames.h"
45 #include "CSSReflectValue.h"
46 #include "CSSRuleList.h"
47 #include "CSSSelector.h"
48 #include "CSSSelectorList.h"
49 #include "CSSStyleRule.h"
50 #include "CSSStyleSheet.h"
51 #include "CSSTimingFunctionValue.h"
52 #include "CSSValueList.h"
53 #if ENABLE(CSS_VARIABLES)
54 #include "CSSVariableValue.h"
55 #endif
56 #include "CachedImage.h"
57 #include "CalculationValue.h"
58 #include "ContentData.h"
59 #include "ContextFeatures.h"
60 #include "Counter.h"
61 #include "CounterContent.h"
62 #include "CursorList.h"
63 #include "DocumentStyleSheetCollection.h"
64 #include "FontFeatureValue.h"
65 #include "FontValue.h"
66 #include "Frame.h"
67 #include "FrameSelection.h"
68 #include "FrameView.h"
69 #include "HTMLDocument.h"
70 #include "HTMLIFrameElement.h"
71 #include "HTMLInputElement.h"
72 #include "HTMLNames.h"
73 #include "HTMLOptionElement.h"
74 #include "HTMLProgressElement.h"
75 #include "HTMLStyleElement.h"
76 #include "HTMLTextAreaElement.h"
77 #include "InspectorInstrumentation.h"
78 #include "KeyframeList.h"
79 #include "LinkHash.h"
80 #include "LocaleToScriptMapping.h"
81 #include "MathMLNames.h"
82 #include "Matrix3DTransformOperation.h"
83 #include "MatrixTransformOperation.h"
84 #include "MediaList.h"
85 #include "MediaQueryEvaluator.h"
86 #include "NodeRenderStyle.h"
87 #include "NodeRenderingContext.h"
88 #include "Page.h"
89 #include "PageGroup.h"
90 #include "Pair.h"
91 #include "PerspectiveTransformOperation.h"
92 #include "QuotesData.h"
93 #include "Rect.h"
94 #include "RenderRegion.h"
95 #include "RenderScrollbar.h"
96 #include "RenderScrollbarTheme.h"
97 #include "RenderStyleConstants.h"
98 #include "RenderTheme.h"
99 #include "RenderView.h"
100 #include "RotateTransformOperation.h"
101 #include "SVGDocumentExtensions.h"
102 #include "SVGFontFaceElement.h"
103 #include "ScaleTransformOperation.h"
104 #include "SecurityOrigin.h"
105 #include "Settings.h"
106 #include "ShadowData.h"
107 #include "ShadowRoot.h"
108 #include "ShadowValue.h"
109 #include "SkewTransformOperation.h"
110 #include "StyleBuilder.h"
111 #include "StyleCachedImage.h"
112 #include "StyleGeneratedImage.h"
113 #include "StylePendingImage.h"
114 #include "StyleRule.h"
115 #include "StyleRuleImport.h"
116 #include "StyleSheetContents.h"
117 #include "StyleSheetList.h"
118 #include "Text.h"
119 #include "TransformationMatrix.h"
120 #include "TranslateTransformOperation.h"
121 #include "UserAgentStyleSheets.h"
122 #include "WebCoreMemoryInstrumentation.h"
123 #include "WebKitCSSKeyframeRule.h"
124 #include "WebKitCSSKeyframesRule.h"
125 #include "WebKitCSSRegionRule.h"
126 #include "WebKitCSSTransformValue.h"
127 #include "WebKitFontFamilyNames.h"
128 #include "XMLNames.h"
129 #include <wtf/MemoryInstrumentationHashSet.h>
130 #include <wtf/MemoryInstrumentationVector.h>
131 #include <wtf/StdLibExtras.h>
132 #include <wtf/Vector.h>
133
134 #if ENABLE(CSS_FILTERS)
135 #include "FilterOperation.h"
136 #include "WebKitCSSFilterValue.h"
137 #endif
138
139 #if ENABLE(DASHBOARD_SUPPORT) || ENABLE(WIDGET_REGION)
140 #include "DashboardRegion.h"
141 #endif
142
143 #if ENABLE(SVG)
144 #include "CachedSVGDocument.h"
145 #include "SVGDocument.h"
146 #include "SVGElement.h"
147 #include "SVGNames.h"
148 #include "SVGURIReference.h"
149 #include "WebKitCSSSVGDocumentValue.h"
150 #endif
151
152 #if ENABLE(CSS_SHADERS)
153 #include "CustomFilterArrayParameter.h"
154 #include "CustomFilterNumberParameter.h"
155 #include "CustomFilterOperation.h"
156 #include "CustomFilterParameter.h"
157 #include "CustomFilterTransformParameter.h"
158 #include "StyleCachedShader.h"
159 #include "StyleCustomFilterProgram.h"
160 #include "StylePendingShader.h"
161 #include "StyleShader.h"
162 #include "WebKitCSSMixFunctionValue.h"
163 #include "WebKitCSSShaderValue.h"
164 #endif
165
166 #if ENABLE(CSS_IMAGE_SET)
167 #include "CSSImageSetValue.h"
168 #include "StyleCachedImageSet.h"
169 #endif
170
171 #if PLATFORM(BLACKBERRY)
172 #define FIXED_POSITION_CREATES_STACKING_CONTEXT 1
173 #endif
174
175
176 using namespace std;
177
178 namespace WebCore {
179
180 using namespace HTMLNames;
181
182 #define HANDLE_INHERIT(prop, Prop) \
183 if (isInherit) { \
184     m_style->set##Prop(m_parentStyle->prop()); \
185     return; \
186 }
187
188 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
189 HANDLE_INHERIT(prop, Prop) \
190 if (isInitial) { \
191     m_style->set##Prop(RenderStyle::initial##Prop()); \
192     return; \
193 }
194
195 #define HANDLE_INHERIT_AND_INITIAL_WITH_VALUE(prop, Prop, Value) \
196 HANDLE_INHERIT(prop, Prop) \
197 if (isInitial) { \
198     m_style->set##Prop(RenderStyle::initial##Value());\
199     return;\
200 }
201
202 #define HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(prop, Prop) \
203 HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
204 if (primitiveValue) \
205     m_style->set##Prop(*primitiveValue);
206
207 class RuleData {
208 public:
209     RuleData(StyleRule*, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule);
210
211     unsigned position() const { return m_position; }
212     StyleRule* rule() const { return m_rule; }
213     CSSSelector* selector() const { return m_rule->selectorList().selectorAt(m_selectorIndex); }
214     unsigned selectorIndex() const { return m_selectorIndex; }
215
216     bool hasFastCheckableSelector() const { return m_hasFastCheckableSelector; }
217     bool hasMultipartSelector() const { return m_hasMultipartSelector; }
218     bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; }
219     bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; }
220     unsigned specificity() const { return m_specificity; }
221     unsigned linkMatchType() const { return m_linkMatchType; }
222     bool hasDocumentSecurityOrigin() const { return m_hasDocumentSecurityOrigin; }
223     bool isInRegionRule() const { return m_isInRegionRule; }
224
225     // Try to balance between memory usage (there can be lots of RuleData objects) and good filtering performance.
226     static const unsigned maximumIdentifierCount = 4;
227     const unsigned* descendantSelectorIdentifierHashes() const { return m_descendantSelectorIdentifierHashes; }
228
229     void reportMemoryUsage(MemoryObjectInfo*) const;
230
231 private:
232     StyleRule* m_rule;
233     unsigned m_selectorIndex : 12;
234     // This number was picked fairly arbitrarily. We can probably lower it if we need to.
235     // Some simple testing showed <100,000 RuleData's on large sites.
236     unsigned m_position : 20;
237     unsigned m_specificity : 24;
238     unsigned m_hasFastCheckableSelector : 1;
239     unsigned m_hasMultipartSelector : 1;
240     unsigned m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1;
241     unsigned m_containsUncommonAttributeSelector : 1;
242     unsigned m_linkMatchType : 2; //  SelectorChecker::LinkMatchMask
243     unsigned m_hasDocumentSecurityOrigin : 1;
244     unsigned m_isInRegionRule : 1;
245     // Use plain array instead of a Vector to minimize memory overhead.
246     unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount];
247 };
248     
249 struct SameSizeAsRuleData {
250     void* a;
251     unsigned b;
252     unsigned c;
253     unsigned d[4];
254 };
255
256 COMPILE_ASSERT(sizeof(RuleData) == sizeof(SameSizeAsRuleData), RuleData_should_stay_small);
257
258 class RuleSet {
259     WTF_MAKE_NONCOPYABLE(RuleSet); WTF_MAKE_FAST_ALLOCATED;
260 public:
261     static PassOwnPtr<RuleSet> create() { return adoptPtr(new RuleSet); }
262
263     typedef HashMap<AtomicStringImpl*, OwnPtr<Vector<RuleData> > > AtomRuleMap;
264
265     void addRulesFromSheet(StyleSheetContents*, const MediaQueryEvaluator&, StyleResolver* = 0, const ContainerNode* = 0);
266
267     void addStyleRule(StyleRule*, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
268     void addRule(StyleRule*, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule = false);
269     void addPageRule(StyleRulePage*);
270     void addToRuleSet(AtomicStringImpl* key, AtomRuleMap&, const RuleData&);
271     void addRegionRule(StyleRuleRegion*, bool hasDocumentSecurityOrigin);
272     void shrinkToFit();
273     void disableAutoShrinkToFit() { m_autoShrinkToFitEnabled = false; }
274
275     const StyleResolver::Features& features() const { return m_features; }
276
277     const Vector<RuleData>* idRules(AtomicStringImpl* key) const { return m_idRules.get(key); }
278     const Vector<RuleData>* classRules(AtomicStringImpl* key) const { return m_classRules.get(key); }
279     const Vector<RuleData>* tagRules(AtomicStringImpl* key) const { return m_tagRules.get(key); }
280     const Vector<RuleData>* shadowPseudoElementRules(AtomicStringImpl* key) const { return m_shadowPseudoElementRules.get(key); }
281     const Vector<RuleData>* linkPseudoClassRules() const { return &m_linkPseudoClassRules; }
282     const Vector<RuleData>* focusPseudoClassRules() const { return &m_focusPseudoClassRules; }
283     const Vector<RuleData>* universalRules() const { return &m_universalRules; }
284     const Vector<StyleRulePage*>& pageRules() const { return m_pageRules; }
285
286     void reportMemoryUsage(MemoryObjectInfo*) const;
287
288 public:
289     RuleSet();
290
291     AtomRuleMap m_idRules;
292     AtomRuleMap m_classRules;
293     AtomRuleMap m_tagRules;
294     AtomRuleMap m_shadowPseudoElementRules;
295     Vector<RuleData> m_linkPseudoClassRules;
296     Vector<RuleData> m_focusPseudoClassRules;
297     Vector<RuleData> m_universalRules;
298     Vector<StyleRulePage*> m_pageRules;
299     unsigned m_ruleCount;
300     bool m_autoShrinkToFitEnabled;
301     StyleResolver::Features m_features;
302
303     struct RuleSetSelectorPair {
304         RuleSetSelectorPair(CSSSelector* selector, PassOwnPtr<RuleSet> ruleSet) : selector(selector), ruleSet(ruleSet) { }
305         RuleSetSelectorPair(const RuleSetSelectorPair& rs) : selector(rs.selector), ruleSet(const_cast<RuleSetSelectorPair*>(&rs)->ruleSet.release()) { }
306         void reportMemoryUsage(MemoryObjectInfo*) const;
307
308         CSSSelector* selector;
309         OwnPtr<RuleSet> ruleSet;
310     };
311
312     Vector<RuleSetSelectorPair> m_regionSelectorsAndRuleSets;
313 };
314
315 static RuleSet* defaultStyle;
316 static RuleSet* defaultQuirksStyle;
317 static RuleSet* defaultPrintStyle;
318 static RuleSet* defaultViewSourceStyle;
319 static StyleSheetContents* simpleDefaultStyleSheet;
320 static StyleSheetContents* defaultStyleSheet;
321 static StyleSheetContents* quirksStyleSheet;
322 static StyleSheetContents* svgStyleSheet;
323 static StyleSheetContents* mathMLStyleSheet;
324 static StyleSheetContents* mediaControlsStyleSheet;
325 static StyleSheetContents* fullscreenStyleSheet;
326
327 RenderStyle* StyleResolver::s_styleNotYetAvailable;
328
329 static void loadFullDefaultStyle();
330 static void loadSimpleDefaultStyle();
331 template <class ListType>
332 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >&, ListType*);
333
334 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
335 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}";
336
337 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
338 {
339     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
340 }
341
342 static const MediaQueryEvaluator& screenEval()
343 {
344     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
345     return staticScreenEval;
346 }
347
348 static const MediaQueryEvaluator& printEval()
349 {
350     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
351     return staticPrintEval;
352 }
353
354 static StylePropertySet* leftToRightDeclaration()
355 {
356     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
357     if (leftToRightDecl->isEmpty())
358         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
359     return leftToRightDecl.get();
360 }
361
362 static StylePropertySet* rightToLeftDeclaration()
363 {
364     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
365     if (rightToLeftDecl->isEmpty())
366         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
367     return rightToLeftDecl.get();
368 }
369
370 StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
371     : m_hasUAAppearance(false)
372     , m_backgroundData(BackgroundFillLayer)
373     , m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
374     , m_checker(document, !document->inQuirksMode())
375     , m_parentStyle(0)
376     , m_rootElementStyle(0)
377     , m_element(0)
378     , m_styledElement(0)
379     , m_regionForStyling(0)
380     , m_elementLinkState(NotInsideLink)
381     , m_parentNode(0)
382     , m_lineHeightValue(0)
383     , m_fontDirty(false)
384     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
385     , m_sameOriginOnly(false)
386     , m_distributedToInsertionPoint(false)
387     , m_hasUnknownPseudoElements(false)
388     , m_fontSelector(CSSFontSelector::create(document))
389     , m_applyPropertyToRegularStyle(true)
390     , m_applyPropertyToVisitedLinkStyle(false)
391     , m_styleBuilder(StyleBuilder::sharedStyleBuilder())
392 #if ENABLE(CSS_SHADERS)
393     , m_hasPendingShaders(false)
394 #endif
395 #if ENABLE(STYLE_SCOPED)
396     , m_scopeStackParent(0)
397     , m_scopeStackParentBoundsIndex(0)
398 #endif
399     , m_styleMap(this)
400 {
401     Element* root = document->documentElement();
402
403     if (!defaultStyle) {
404         if (!root || elementCanUseSimpleDefaultStyle(root))
405             loadSimpleDefaultStyle();
406         else
407             loadFullDefaultStyle();
408     }
409
410     // construct document root element default style. this is needed
411     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
412     // This is here instead of constructor, because when constructor is run,
413     // document doesn't have documentElement
414     // NOTE: this assumes that element that gets passed to styleForElement -call
415     // is always from the document that owns the style selector
416     FrameView* view = document->view();
417     if (view)
418         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
419     else
420         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
421
422     if (root)
423         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
424
425     if (m_rootDefaultStyle && view)
426         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
427
428     resetAuthorStyle();
429
430     DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
431     // FIXME: This sucks! The user sheet is reparsed every time!
432     OwnPtr<RuleSet> tempUserStyle = RuleSet::create();
433     if (CSSStyleSheet* pageUserSheet = styleSheetCollection->pageUserSheet())
434         tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), *m_medium, this);
435     addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->pageGroupUserSheets(), *tempUserStyle);
436     addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->documentUserSheets(), *tempUserStyle);
437     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
438         m_userStyle = tempUserStyle.release();
439
440 #if ENABLE(SVG_FONTS)
441     if (document->svgExtensions()) {
442         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
443         HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
444         for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
445             fontSelector()->addFontFaceRule((*it)->fontFaceRule());
446     }
447 #endif
448
449     addStylesheetsFromSeamlessParents();
450     appendAuthorStylesheets(0, styleSheetCollection->authorStyleSheets());
451 }
452
453 void StyleResolver::addStylesheetsFromSeamlessParents()
454 {
455     // Build a list of stylesheet lists from our ancestors, and walk that
456     // list in reverse order so that the root-most sheets are appended first.
457     Document* childDocument = document();
458     Vector<const Vector<RefPtr<StyleSheet> >* > ancestorSheets;
459     while (HTMLIFrameElement* parentIFrame = childDocument->seamlessParentIFrame()) {
460         Document* parentDocument = parentIFrame->document();
461         ancestorSheets.append(&parentDocument->styleSheetCollection()->authorStyleSheets());
462         childDocument = parentDocument;
463     }
464     for (int i = ancestorSheets.size() - 1; i >= 0; i--)
465         appendAuthorStylesheets(0, *ancestorSheets[i]);
466 }
467
468 void StyleResolver::addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >* userSheets, RuleSet& userStyle)
469 {
470     if (!userSheets)
471         return;
472
473     unsigned length = userSheets->size();
474     for (unsigned i = 0; i < length; i++) {
475         StyleSheetContents* sheet = userSheets->at(i)->contents();
476         if (sheet->isUserStyleSheet())
477             userStyle.addRulesFromSheet(sheet, *m_medium, this);
478         else
479             m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
480     }
481 }
482
483 static PassOwnPtr<RuleSet> makeRuleSet(const Vector<StyleResolver::RuleFeature>& rules)
484 {
485     size_t size = rules.size();
486     if (!size)
487         return nullptr;
488     OwnPtr<RuleSet> ruleSet = RuleSet::create();
489     for (size_t i = 0; i < size; ++i)
490         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin, false);
491     ruleSet->shrinkToFit();
492     return ruleSet.release();
493 }
494
495 void StyleResolver::collectFeatures()
496 {
497     m_features.clear();
498     // Collect all ids and rules using sibling selectors (:first-child and similar)
499     // in the current set of stylesheets. Style sharing code uses this information to reject
500     // sharing candidates.
501     m_features.add(defaultStyle->features());
502     m_features.add(m_authorStyle->features());
503 #if ENABLE(STYLE_SCOPED)
504     for (ScopedRuleSetMap::iterator it = m_scopedAuthorStyles.begin(); it != m_scopedAuthorStyles.end(); ++it)
505         m_features.add(it->second->features());
506 #endif
507     if (m_userStyle)
508         m_features.add(m_userStyle->features());
509
510     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
511     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
512 }
513
514 #if ENABLE(STYLE_SCOPED)
515 const ContainerNode* StyleResolver::determineScope(const CSSStyleSheet* sheet)
516 {
517     ASSERT(sheet);
518
519     if (!ContextFeatures::styleScopedEnabled(document()))
520         return 0;
521
522     Node* ownerNode = sheet->ownerNode();
523     if (!ownerNode || !ownerNode->isHTMLElement() || !ownerNode->hasTagName(HTMLNames::styleTag))
524         return 0;
525
526     HTMLStyleElement* styleElement = static_cast<HTMLStyleElement*>(ownerNode);
527     if (!styleElement->scoped())
528         return styleElement->isInShadowTree()? styleElement->shadowRoot() : 0;
529
530     ContainerNode* parent = styleElement->parentNode();
531     if (!parent)
532         return 0;
533
534     return (parent->isElementNode() || parent->isShadowRoot()) ? parent : 0;
535 }
536
537 inline RuleSet* StyleResolver::ruleSetForScope(const ContainerNode* scope) const
538 {
539     if (!scope->hasScopedHTMLStyleChild())
540         return 0;
541     ScopedRuleSetMap::const_iterator it = m_scopedAuthorStyles.find(scope);
542     return it != m_scopedAuthorStyles.end() ? it->second.get() : 0; 
543 }
544 #endif
545
546 void StyleResolver::resetAuthorStyle()
547 {
548     m_authorStyle = RuleSet::create();
549     m_authorStyle->disableAutoShrinkToFit();
550 }
551
552 void StyleResolver::appendAuthorStylesheets(unsigned firstNew, const Vector<RefPtr<StyleSheet> >& stylesheets)
553 {
554     // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
555     // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
556     unsigned size = stylesheets.size();
557     for (unsigned i = firstNew; i < size; ++i) {
558         if (!stylesheets[i]->isCSSStyleSheet())
559             continue;
560         CSSStyleSheet* cssSheet = static_cast<CSSStyleSheet*>(stylesheets[i].get());
561         if (cssSheet->disabled())
562             continue;
563         if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), this))
564             continue;
565         StyleSheetContents* sheet = cssSheet->contents();
566 #if ENABLE(STYLE_SCOPED)
567         const ContainerNode* scope = determineScope(cssSheet);
568         if (scope) {
569             ScopedRuleSetMap::AddResult addResult = m_scopedAuthorStyles.add(scope, nullptr);
570             if (addResult.isNewEntry)
571                 addResult.iterator->second = RuleSet::create();
572             addResult.iterator->second->addRulesFromSheet(sheet, *m_medium, this, scope);
573             continue;
574         }
575 #endif
576         m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
577         if (!m_styleRuleToCSSOMWrapperMap.isEmpty())
578             collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, cssSheet);
579     }
580     m_authorStyle->shrinkToFit();
581     collectFeatures();
582     
583     if (document()->renderer() && document()->renderer()->style())
584         document()->renderer()->style()->font().update(fontSelector());
585 }
586
587 #if ENABLE(STYLE_SCOPED)
588 void StyleResolver::setupScopeStack(const ContainerNode* parent)
589 {
590     // The scoping element stack shouldn't be used if <style scoped> isn't used anywhere.
591     ASSERT(!m_scopedAuthorStyles.isEmpty());
592
593     m_scopeStack.shrink(0);
594     int authorStyleBoundsIndex = 0;
595     for (const ContainerNode* scope = parent; scope; scope = scope->parentOrHostNode()) {
596         RuleSet* ruleSet = ruleSetForScope(scope);
597         if (ruleSet)
598             m_scopeStack.append(ScopeStackFrame(scope, authorStyleBoundsIndex, ruleSet));
599         if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
600             --authorStyleBoundsIndex;
601     }
602     m_scopeStack.reverse();
603     m_scopeStackParent = parent;
604     m_scopeStackParentBoundsIndex = 0;
605 }
606
607 void StyleResolver::pushScope(const ContainerNode* scope, const ContainerNode* scopeParent)
608 {
609     // Shortcut: Don't bother with the scoping element stack if <style scoped> isn't used anywhere.
610     if (m_scopedAuthorStyles.isEmpty()) {
611         ASSERT(!m_scopeStackParent);
612         ASSERT(m_scopeStack.isEmpty());
613         return;
614     }
615     // In some wacky cases during style resolve we may get invoked for random elements.
616     // Recreate the whole scoping element stack in such cases.
617     if (!scopeStackIsConsistent(scopeParent)) {
618         setupScopeStack(scope);
619         return;
620     }
621     if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
622         ++m_scopeStackParentBoundsIndex;
623     // Otherwise just push the parent onto the stack.
624     RuleSet* ruleSet = ruleSetForScope(scope);
625     if (ruleSet)
626         m_scopeStack.append(ScopeStackFrame(scope, m_scopeStackParentBoundsIndex, ruleSet));
627     m_scopeStackParent = scope;
628 }
629
630 void StyleResolver::popScope(const ContainerNode* scope)
631 {
632     // Only bother to update the scoping element stack if it is consistent.
633     if (scopeStackIsConsistent(scope)) {
634         if (!m_scopeStack.isEmpty() && m_scopeStack.last().m_scope == scope)
635             m_scopeStack.removeLast();
636         if (scope->isShadowRoot() && !toShadowRoot(scope)->applyAuthorStyles())
637             --m_scopeStackParentBoundsIndex;
638         m_scopeStackParent = scope->parentOrHostNode();
639     }
640 }
641 #endif
642
643 void StyleResolver::pushParentElement(Element* parent)
644 {
645     const ContainerNode* parentsParent = parent->parentOrHostElement();
646
647     // We are not always invoked consistently. For example, script execution can cause us to enter
648     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
649     // Reset the stack in this case, or if we see a new root element.
650     // Otherwise just push the new parent.
651     if (!parentsParent || m_checker.parentStackIsEmpty())
652         m_checker.setupParentStack(parent);
653     else
654         m_checker.pushParent(parent);
655
656     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
657     pushScope(parent, parent->parentOrHostNode());
658 }
659
660 void StyleResolver::popParentElement(Element* parent)
661 {
662     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
663     // Pause maintaining the stack in this case.
664     if (m_checker.parentStackIsConsistent(parent))
665         m_checker.popParent();
666     popScope(parent);
667 }
668
669 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
670 {
671     ASSERT(shadowRoot->host());
672     pushScope(shadowRoot, shadowRoot->host());
673 }
674
675 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
676 {
677     ASSERT(shadowRoot->host());
678     popScope(shadowRoot);
679 }
680
681 // This is a simplified style setting function for keyframe styles
682 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
683 {
684     AtomicString s(rule->name());
685     m_keyframesRuleMap.set(s.impl(), rule);
686 }
687
688 StyleResolver::~StyleResolver()
689 {
690     m_fontSelector->clearDocument();
691 }
692
693 void StyleResolver::sweepMatchedPropertiesCache()
694 {
695     // Look for cache entries containing a style declaration with a single ref and remove them.
696     // This may happen when an element attribute mutation causes it to swap out its Attribute::decl()
697     // for another CSSMappedAttributeDeclaration, potentially leaving this cache with the last ref.
698     Vector<unsigned, 16> toRemove;
699     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
700     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
701     for (; it != end; ++it) {
702         Vector<MatchedProperties>& matchedProperties = it->second.matchedProperties;
703         for (size_t i = 0; i < matchedProperties.size(); ++i) {
704             if (matchedProperties[i].properties->hasOneRef()) {
705                 toRemove.append(it->first);
706                 break;
707             }
708         }
709     }
710     for (size_t i = 0; i < toRemove.size(); ++i)
711         m_matchedPropertiesCache.remove(toRemove[i]);
712 }
713
714 StyleResolver::Features::Features()
715     : usesFirstLineRules(false)
716     , usesBeforeAfterRules(false)
717 {
718 }
719
720 StyleResolver::Features::~Features()
721 {
722 }
723     
724 void StyleResolver::Features::add(const StyleResolver::Features& other)
725 {
726     HashSet<AtomicStringImpl*>::iterator end = other.idsInRules.end();
727     for (HashSet<AtomicStringImpl*>::iterator it = other.idsInRules.begin(); it != end; ++it)
728         idsInRules.add(*it);
729     end = other.attrsInRules.end();
730     for (HashSet<AtomicStringImpl*>::iterator it = other.attrsInRules.begin(); it != end; ++it)
731         attrsInRules.add(*it);
732     siblingRules.append(other.siblingRules);
733     uncommonAttributeRules.append(other.uncommonAttributeRules);
734     usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
735     usesBeforeAfterRules = usesBeforeAfterRules || other.usesBeforeAfterRules;
736 }
737
738 void StyleResolver::Features::clear()
739 {
740     idsInRules.clear();
741     attrsInRules.clear();
742     siblingRules.clear();
743     uncommonAttributeRules.clear();
744     usesFirstLineRules = false;
745     usesBeforeAfterRules = false;
746 }
747
748 void StyleResolver::Features::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
749 {
750     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
751     info.addMember(idsInRules);
752     info.addMember(attrsInRules);
753     info.addMember(siblingRules);
754     info.addMember(uncommonAttributeRules);
755 }
756
757 static StyleSheetContents* parseUASheet(const String& str)
758 {
759     StyleSheetContents* sheet = StyleSheetContents::create().leakRef(); // leak the sheet on purpose
760     sheet->parseString(str);
761     return sheet;
762 }
763
764 static StyleSheetContents* parseUASheet(const char* characters, unsigned size)
765 {
766     return parseUASheet(String(characters, size));
767 }
768
769 static void loadFullDefaultStyle()
770 {
771     if (simpleDefaultStyleSheet) {
772         ASSERT(defaultStyle);
773         ASSERT(defaultPrintStyle == defaultStyle);
774         delete defaultStyle;
775         simpleDefaultStyleSheet->deref();
776         defaultStyle = RuleSet::create().leakPtr();
777         defaultPrintStyle = RuleSet::create().leakPtr();
778         simpleDefaultStyleSheet = 0;
779     } else {
780         ASSERT(!defaultStyle);
781         defaultStyle = RuleSet::create().leakPtr();
782         defaultPrintStyle = RuleSet::create().leakPtr();
783         defaultQuirksStyle = RuleSet::create().leakPtr();
784     }
785
786     // Strict-mode rules.
787     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
788     defaultStyleSheet = parseUASheet(defaultRules);
789     defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval());
790     defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval());
791
792     // Quirks-mode rules.
793     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
794     quirksStyleSheet = parseUASheet(quirksRules);
795     defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval());
796 }
797
798 static void loadSimpleDefaultStyle()
799 {
800     ASSERT(!defaultStyle);
801     ASSERT(!simpleDefaultStyleSheet);
802
803     defaultStyle = RuleSet::create().leakPtr();
804     // There are no media-specific rules in the simple default style.
805     defaultPrintStyle = defaultStyle;
806     defaultQuirksStyle = RuleSet::create().leakPtr();
807
808     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
809     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
810
811     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
812 }
813
814 static void loadViewSourceStyle()
815 {
816     ASSERT(!defaultViewSourceStyle);
817     defaultViewSourceStyle = RuleSet::create().leakPtr();
818     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
819 }
820
821 static void ensureDefaultStyleSheetsForElement(Element* element)
822 {
823     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element))
824         loadFullDefaultStyle();
825
826 #if ENABLE(SVG)
827     if (element->isSVGElement() && !svgStyleSheet) {
828         // SVG rules.
829         svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
830         defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval());
831         defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval());
832     }
833 #endif
834
835 #if ENABLE(MATHML)
836     if (element->isMathMLElement() && !mathMLStyleSheet) {
837         // MathML rules.
838         mathMLStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
839         defaultStyle->addRulesFromSheet(mathMLStyleSheet, screenEval());
840         defaultPrintStyle->addRulesFromSheet(mathMLStyleSheet, printEval());
841     }
842 #endif
843
844 #if ENABLE(VIDEO)
845     if (!mediaControlsStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
846         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
847         mediaControlsStyleSheet = parseUASheet(mediaRules);
848         defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval());
849         defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval());
850     }
851 #endif
852
853 #if ENABLE(FULLSCREEN_API)
854     if (!fullscreenStyleSheet && element->document()->webkitIsFullScreen()) {
855         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
856         fullscreenStyleSheet = parseUASheet(fullscreenRules);
857         defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
858         defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
859     }
860 #endif
861
862     ASSERT(defaultStyle->features().idsInRules.isEmpty());
863     ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty());
864 }
865
866 void StyleResolver::addMatchedProperties(MatchResult& matchResult, const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, bool inRegionRule)
867 {
868     matchResult.matchedProperties.grow(matchResult.matchedProperties.size() + 1);
869     MatchedProperties& newProperties = matchResult.matchedProperties.last();
870     newProperties.properties = const_cast<StylePropertySet*>(properties);
871     newProperties.linkMatchType = linkMatchType;
872     newProperties.isInRegionRule = inRegionRule;
873     matchResult.matchedRules.append(rule);
874 }
875
876 inline void StyleResolver::addElementStyleProperties(MatchResult& result, const StylePropertySet* propertySet, bool isCacheable)
877 {
878     if (!propertySet)
879         return;
880     result.ranges.lastAuthorRule = result.matchedProperties.size();
881     if (result.ranges.firstAuthorRule == -1)
882         result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
883     addMatchedProperties(result, propertySet);
884     if (!isCacheable)
885         result.isCacheable = false;
886 }
887
888 void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
889 {
890     ASSERT(rules);
891     ASSERT(m_element);
892
893     // We need to collect the rules for id, class, tag, and everything else into a buffer and
894     // then sort the buffer.
895     if (m_element->hasID())
896         collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, options);
897     if (m_styledElement && m_styledElement->hasClass()) {
898         for (size_t i = 0; i < m_styledElement->classNames().size(); ++i)
899             collectMatchingRulesForList(rules->classRules(m_styledElement->classNames()[i].impl()), firstRuleIndex, lastRuleIndex, options);
900     }
901     const AtomicString& pseudoId = m_element->shadowPseudoId();
902     if (!pseudoId.isEmpty()) {
903         ASSERT(m_styledElement);
904         collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
905     }
906     if (m_element->isLink())
907         collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
908     if (m_checker.matchesFocusPseudoClass(m_element))
909         collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
910     collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, options);
911     collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, options);
912 }
913
914 void StyleResolver::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
915 {
916     if (!m_regionForStyling)
917         return;
918
919     unsigned size = rules->m_regionSelectorsAndRuleSets.size();
920     for (unsigned i = 0; i < size; ++i) {
921         CSSSelector* regionSelector = rules->m_regionSelectorsAndRuleSets.at(i).selector;
922         if (checkRegionSelector(regionSelector, static_cast<Element*>(m_regionForStyling->node()))) {
923             RuleSet* regionRules = rules->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
924             ASSERT(regionRules);
925             collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, options);
926         }
927     }
928 }
929
930 void StyleResolver::sortAndTransferMatchedRules(MatchResult& result)
931 {
932     if (m_matchedRules.isEmpty())
933         return;
934
935     sortMatchedRules();
936
937     if (m_checker.mode() == SelectorChecker::CollectingRules) {
938         if (!m_ruleList)
939             m_ruleList = StaticCSSRuleList::create();
940         for (unsigned i = 0; i < m_matchedRules.size(); ++i)
941             m_ruleList->rules().append(m_matchedRules[i]->rule()->createCSSOMWrapper());
942         return;
943     }
944
945     // Now transfer the set of matched rules over to our list of declarations.
946     // FIXME: This sucks, the inspector should get the style from the visited style itself.
947     bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
948     for (unsigned i = 0; i < m_matchedRules.size(); i++) {
949         if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
950             m_style->setAffectedByUncommonAttributeSelectors();
951         unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
952         if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
953             linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
954         addMatchedProperties(result, m_matchedRules[i]->rule()->properties(), m_matchedRules[i]->rule(), linkMatchType, m_matchedRules[i]->isInRegionRule());
955     }
956 }
957
958 void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
959 {
960 #if ENABLE(STYLE_SCOPED)
961     if (m_scopedAuthorStyles.isEmpty())
962         return;
963
964     MatchOptions options(includeEmptyRules);
965
966     // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
967     if (!scopeStackIsConsistent(m_element))
968         setupScopeStack(m_element);
969
970     unsigned int firstShadowScopeIndex = 0;
971     if (m_element->treeScope()->applyAuthorStyles()) {
972         unsigned i;
973         for (i = 0; i < m_scopeStack.size() && !m_scopeStack[i].m_scope->isInShadowTree(); ++i) {
974             const ScopeStackFrame& frame = m_scopeStack[i];
975             options.scope = frame.m_scope;
976             collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
977             collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
978         }
979         firstShadowScopeIndex = i;
980     }
981
982     if (!m_element->isInShadowTree() || m_scopeStack.isEmpty())
983         return;
984
985     unsigned scopedIndex = m_scopeStack.size();
986     int authorStyleBoundsIndex = m_scopeStackParentBoundsIndex;
987     for ( ; scopedIndex > firstShadowScopeIndex; --scopedIndex) {
988         if (authorStyleBoundsIndex != m_scopeStack[scopedIndex - 1].m_authorStyleBoundsIndex)
989             break;
990     }
991
992     // Ruleset for ancestor nodes should be applied first.
993     for (unsigned i = scopedIndex; i < m_scopeStack.size(); ++i) {
994         const ScopeStackFrame& frame = m_scopeStack[i];
995         options.scope = frame.m_scope;
996         collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
997         collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
998     }
999 #else
1000     UNUSED_PARAM(result);
1001     UNUSED_PARAM(includeEmptyRules);
1002 #endif
1003 }
1004
1005 void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules)
1006 {
1007     m_matchedRules.clear();
1008     result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
1009
1010     if (!m_element)
1011         return;
1012
1013     // Match global author rules.
1014     MatchOptions options(includeEmptyRules);
1015     collectMatchingRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
1016     collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
1017
1018     matchScopedAuthorRules(result, includeEmptyRules);
1019
1020     sortAndTransferMatchedRules(result);
1021 }
1022
1023 void StyleResolver::matchUserRules(MatchResult& result, bool includeEmptyRules)
1024 {
1025     if (!m_userStyle)
1026         return;
1027     
1028     m_matchedRules.clear();
1029
1030     result.ranges.lastUserRule = result.matchedProperties.size() - 1;
1031     collectMatchingRules(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
1032     collectMatchingRulesForRegion(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
1033
1034     sortAndTransferMatchedRules(result);
1035 }
1036
1037 void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules)
1038 {
1039     m_matchedRules.clear();
1040     
1041     result.ranges.lastUARule = result.matchedProperties.size() - 1;
1042     collectMatchingRules(rules, result.ranges.firstUARule, result.ranges.lastUARule, false);
1043
1044     sortAndTransferMatchedRules(result);
1045 }
1046
1047 class MatchingUARulesScope {
1048 public:
1049     MatchingUARulesScope();
1050     ~MatchingUARulesScope();
1051
1052     static bool isMatchingUARules();
1053
1054 private:
1055     static bool m_matchingUARules;
1056 };
1057
1058 MatchingUARulesScope::MatchingUARulesScope()
1059 {
1060     ASSERT(!m_matchingUARules);
1061     m_matchingUARules = true;
1062 }
1063
1064 MatchingUARulesScope::~MatchingUARulesScope()
1065 {
1066     m_matchingUARules = false;
1067 }
1068
1069 inline bool MatchingUARulesScope::isMatchingUARules()
1070 {
1071     return m_matchingUARules;
1072 }
1073
1074 bool MatchingUARulesScope::m_matchingUARules = false;
1075
1076 void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
1077 {
1078     if (!rules)
1079         return;
1080
1081     TreeScope* treeScope = m_element->treeScope();
1082
1083     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
1084     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
1085     bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
1086
1087     unsigned size = rules->size();
1088     for (unsigned i = 0; i < size; ++i) {
1089         const RuleData& ruleData = rules->at(i);
1090         if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
1091             continue;
1092
1093         StyleRule* rule = ruleData.rule();
1094         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
1095 #if ENABLE(STYLE_SCOPED)
1096         if (checkSelector(ruleData, options.scope)) {
1097 #else
1098         if (checkSelector(ruleData)) {
1099 #endif
1100             // Check whether the rule is applicable in the current tree scope. Criteria for this:
1101             // a) it's a UA rule
1102             // b) the tree scope allows author rules
1103             // c) the rules comes from a scoped style sheet within the same tree scope
1104             // d) the rule contains shadow-ID pseudo elements
1105             if (!MatchingUARulesScope::isMatchingUARules()
1106                 && !treeScope->applyAuthorStyles()
1107 #if ENABLE(STYLE_SCOPED)
1108                 && (!options.scope || options.scope->treeScope() != treeScope)
1109 #endif
1110                 && !m_hasUnknownPseudoElements) {
1111
1112                 InspectorInstrumentation::didMatchRule(cookie, false);
1113                 continue;
1114             }
1115             // If the rule has no properties to apply, then ignore it in the non-debug mode.
1116             const StylePropertySet* properties = rule->properties();
1117             if (!properties || (properties->isEmpty() && !options.includeEmptyRules)) {
1118                 InspectorInstrumentation::didMatchRule(cookie, false);
1119                 continue;
1120             }
1121             // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
1122             if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) {
1123                 InspectorInstrumentation::didMatchRule(cookie, false);
1124                 continue;
1125             }
1126             // If we're matching normal rules, set a pseudo bit if
1127             // we really just matched a pseudo-element.
1128             if (m_dynamicPseudo != NOPSEUDO && m_pseudoStyle == NOPSEUDO) {
1129                 if (m_checker.mode() == SelectorChecker::CollectingRules) {
1130                     InspectorInstrumentation::didMatchRule(cookie, false);
1131                     continue;
1132                 }
1133                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
1134                     m_style->setHasPseudoStyle(m_dynamicPseudo);
1135             } else {
1136                 // Update our first/last rule indices in the matched rules array.
1137                 ++lastRuleIndex;
1138                 if (firstRuleIndex == -1)
1139                     firstRuleIndex = lastRuleIndex;
1140
1141                 // Add this rule to our list of matched rules.
1142                 addMatchedRule(&ruleData);
1143                 InspectorInstrumentation::didMatchRule(cookie, true);
1144                 continue;
1145             }
1146         }
1147         InspectorInstrumentation::didMatchRule(cookie, false);
1148     }
1149 }
1150
1151 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
1152 {
1153     unsigned specificity1 = r1->specificity();
1154     unsigned specificity2 = r2->specificity();
1155     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
1156 }
1157
1158 void StyleResolver::sortMatchedRules()
1159 {
1160     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
1161 }
1162
1163 void StyleResolver::matchAllRules(MatchResult& result, bool includeSMILProperties)
1164 {
1165     matchUARules(result);
1166
1167     // Now we check user sheet rules.
1168     if (m_matchAuthorAndUserStyles)
1169         matchUserRules(result, false);
1170         
1171     // Now check author rules, beginning first with presentational attributes mapped from HTML.
1172     if (m_styledElement) {
1173         addElementStyleProperties(result, m_styledElement->attributeStyle());
1174
1175         // Now we check additional mapped declarations.
1176         // Tables and table cells share an additional mapped rule that must be applied
1177         // after all attributes, since their mapped style depends on the values of multiple attributes.
1178         addElementStyleProperties(result, m_styledElement->additionalAttributeStyle());
1179
1180         if (m_styledElement->isHTMLElement()) {
1181             bool isAuto;
1182             TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
1183             if (isAuto)
1184                 addMatchedProperties(result, textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
1185         }
1186     }
1187     
1188     // Check the rules in author sheets next.
1189     if (m_matchAuthorAndUserStyles)
1190         matchAuthorRules(result, false);
1191
1192     // Now check our inline style attribute.
1193     if (m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->inlineStyle()) {
1194         // Inline style is immutable as long as there is no CSSOM wrapper.
1195         // FIXME: Media control shadow trees seem to have problems with caching.
1196         bool isInlineStyleCacheable = !m_styledElement->inlineStyle()->isMutable() && !m_styledElement->isInShadowTree();
1197         // FIXME: Constify.
1198         addElementStyleProperties(result, m_styledElement->inlineStyle(), isInlineStyleCacheable);
1199     }
1200
1201 #if ENABLE(SVG)
1202     // Now check SMIL animation override style.
1203     if (includeSMILProperties && m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->isSVGElement())
1204         addElementStyleProperties(result, static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties(), false /* isCacheable */);
1205 #else
1206     UNUSED_PARAM(includeSMILProperties);
1207 #endif
1208 }
1209
1210 inline void StyleResolver::initElement(Element* e)
1211 {
1212     if (m_element != e) {
1213         m_element = e;
1214         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
1215         m_elementLinkState = m_checker.determineLinkState(m_element);
1216         if (e && e == e->document()->documentElement()) {
1217             e->document()->setDirectionSetOnDocumentElement(false);
1218             e->document()->setWritingModeSetOnDocumentElement(false);
1219         }
1220     }
1221 }
1222
1223 inline void StyleResolver::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
1224 {
1225     m_pseudoStyle = pseudoID;
1226
1227     if (e) {
1228         NodeRenderingContext context(e);
1229         m_parentNode = context.parentNodeForRenderingAndStyle();
1230         m_parentStyle = context.resetStyleInheritance()? 0 :
1231             parentStyle ? parentStyle :
1232             m_parentNode ? m_parentNode->renderStyle() : 0;
1233         m_distributedToInsertionPoint = context.insertionPoint();
1234     } else {
1235         m_parentNode = 0;
1236         m_parentStyle = parentStyle;
1237         m_distributedToInsertionPoint = false;
1238     }
1239
1240     Node* docElement = e ? e->document()->documentElement() : 0;
1241     RenderStyle* docStyle = m_checker.document()->renderStyle();
1242     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
1243
1244     m_style = 0;
1245
1246     m_pendingImageProperties.clear();
1247
1248     m_ruleList = 0;
1249
1250     m_fontDirty = false;
1251 }
1252
1253 static const unsigned cStyleSearchThreshold = 10;
1254 static const unsigned cStyleSearchLevelThreshold = 10;
1255
1256 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
1257 {
1258     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
1259         return 0;
1260     if (!parent || !parent->isStyledElement())
1261         return 0;
1262 #if ENABLE(STYLE_SCOPED)
1263     if (parent->hasScopedHTMLStyleChild())
1264         return 0;
1265 #endif
1266     StyledElement* p = static_cast<StyledElement*>(parent);
1267     if (p->inlineStyle())
1268         return 0;
1269 #if ENABLE(SVG)
1270     if (p->isSVGElement() && static_cast<SVGElement*>(p)->animatedSMILStyleProperties())
1271         return 0;
1272 #endif
1273     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
1274         return 0;
1275
1276     RenderStyle* parentStyle = p->renderStyle();
1277     unsigned subcount = 0;
1278     Node* thisCousin = p;
1279     Node* currentNode = p->previousSibling();
1280
1281     // Reserve the tries for this level. This effectively makes sure that the algorithm
1282     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
1283     visitedNodeCount += cStyleSearchThreshold;
1284     while (thisCousin) {
1285         while (currentNode) {
1286             ++subcount;
1287             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
1288                 // Adjust for unused reserved tries.
1289                 visitedNodeCount -= cStyleSearchThreshold - subcount;
1290                 return currentNode->lastChild();
1291             }
1292             if (subcount >= cStyleSearchThreshold)
1293                 return 0;
1294             currentNode = currentNode->previousSibling();
1295         }
1296         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
1297         thisCousin = currentNode;
1298     }
1299
1300     return 0;
1301 }
1302
1303 bool StyleResolver::matchesRuleSet(RuleSet* ruleSet)
1304 {
1305     if (!ruleSet)
1306         return false;
1307     m_matchedRules.clear();
1308
1309     int firstRuleIndex = -1, lastRuleIndex = -1;
1310     collectMatchingRules(ruleSet, firstRuleIndex, lastRuleIndex, false);
1311
1312     if (m_matchedRules.isEmpty())
1313         return false;
1314     m_matchedRules.clear();
1315     return true;
1316 }
1317
1318 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
1319 {
1320     HTMLInputElement* thisInputElement = element->toInputElement();
1321     HTMLInputElement* otherInputElement = m_element->toInputElement();
1322
1323     if (!thisInputElement || !otherInputElement)
1324         return false;
1325
1326     if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
1327         return false;
1328
1329     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1330         return false;
1331     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
1332         return false;
1333     if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1334         return false;
1335     if (thisInputElement->required() != otherInputElement->required())
1336         return false;
1337
1338     if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1339         return false;
1340
1341     if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1342         return false;
1343
1344     if (m_element->document()->containsValidityStyleRules()) {
1345         bool willValidate = element->willValidate();
1346
1347         if (willValidate != m_element->willValidate())
1348             return false;
1349
1350         if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1351             return false;
1352
1353         if (element->isInRange() != m_element->isInRange())
1354             return false;
1355
1356         if (element->isOutOfRange() != m_element->isOutOfRange())
1357             return false;
1358     }
1359
1360     return true;
1361 }
1362
1363 // This function makes some assumptions that only make sense for attribute styles (we only compare CSSProperty::id() and CSSProperty::value().)
1364 static inline bool attributeStylesEqual(const StylePropertySet* a, const StylePropertySet* b)
1365 {
1366     if (a == b)
1367         return true;
1368     if (a->propertyCount() != b->propertyCount())
1369         return false;
1370     unsigned propertyCount = a->propertyCount();
1371     for (unsigned i = 0; i < propertyCount; ++i) {
1372         const CSSProperty& aProperty = a->propertyAt(i);
1373         unsigned j;
1374         for (j = 0; j < propertyCount; ++j) {
1375             const CSSProperty& bProperty = b->propertyAt(j);
1376             if (aProperty.id() != bProperty.id())
1377                 continue;
1378             // We could get a few more hits by comparing cssText() here, but that gets expensive quickly.
1379             if (aProperty.value() != bProperty.value())
1380                 return false;
1381             break;
1382         }
1383         if (j == propertyCount)
1384             return false;
1385     }
1386     return true;
1387 }
1388
1389 static inline bool elementHasDirectionAuto(Element* element)
1390 {
1391     // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
1392     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
1393 }
1394
1395 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
1396 {
1397     RenderStyle* style = element->renderStyle();
1398
1399     if (!style)
1400         return false;
1401     if (style->unique())
1402         return false;
1403     if (element->tagQName() != m_element->tagQName())
1404         return false;
1405     if (element->hasClass() != m_element->hasClass())
1406         return false;
1407     if (element->inlineStyle())
1408         return false;
1409     if (element->needsStyleRecalc())
1410         return false;
1411 #if ENABLE(SVG)
1412     if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
1413         return false;
1414 #endif
1415     if (!!element->attributeStyle() != !!m_styledElement->attributeStyle())
1416         return false;
1417     const StylePropertySet* additionalAttributeStyleA = element->additionalAttributeStyle();
1418     const StylePropertySet* additionalAttributeStyleB = m_styledElement->additionalAttributeStyle();
1419     if (!additionalAttributeStyleA != !additionalAttributeStyleB)
1420         return false;
1421     if (element->isLink() != m_element->isLink())
1422         return false;
1423     if (style->affectedByUncommonAttributeSelectors())
1424         return false;
1425     if (element->hovered() != m_element->hovered())
1426         return false;
1427     if (element->active() != m_element->active())
1428         return false;
1429     if (element->focused() != m_element->focused())
1430         return false;
1431     if (element->shadowPseudoId() != m_element->shadowPseudoId())
1432         return false;
1433     if (element == element->document()->cssTarget())
1434         return false;
1435     if (m_element == m_element->document()->cssTarget())
1436         return false;
1437     if (element->fastGetAttribute(XMLNames::langAttr) != m_element->fastGetAttribute(XMLNames::langAttr))
1438         return false;
1439     if (element->fastGetAttribute(langAttr) != m_element->fastGetAttribute(langAttr))
1440         return false;
1441     if (element->fastGetAttribute(readonlyAttr) != m_element->fastGetAttribute(readonlyAttr))
1442         return false;
1443     if (element->fastGetAttribute(cellpaddingAttr) != m_element->fastGetAttribute(cellpaddingAttr))
1444         return false;
1445
1446     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1447         return false;
1448
1449 #if ENABLE(STYLE_SCOPED)
1450     if (element->hasScopedHTMLStyleChild())
1451         return false;
1452 #endif
1453
1454 #if ENABLE(PROGRESS_ELEMENT)
1455     if (element->hasTagName(progressTag)) {
1456         if (!m_element->hasTagName(progressTag))
1457             return false;
1458
1459         HTMLProgressElement* thisProgressElement = static_cast<HTMLProgressElement*>(element);
1460         HTMLProgressElement* otherProgressElement = static_cast<HTMLProgressElement*>(m_element);
1461         if (thisProgressElement->isDeterminate() != otherProgressElement->isDeterminate())
1462             return false;
1463     }
1464 #endif
1465
1466     // FIXME: We should share style for option and optgroup whenever possible.
1467     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
1468     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
1469     if (element->hasTagName(optionTag) || element->hasTagName(optgroupTag))
1470         return false;
1471
1472     bool isControl = element->isFormControlElement();
1473
1474     if (isControl != m_element->isFormControlElement())
1475         return false;
1476
1477     if (isControl && !canShareStyleWithControl(element))
1478         return false;
1479
1480     if (style->transitions() || style->animations())
1481         return false;
1482
1483 #if USE(ACCELERATED_COMPOSITING)
1484     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1485     // See comments in RenderObject::setStyle().
1486     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag)
1487 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1488         // With proxying, the media elements are backed by a RenderEmbeddedObject.
1489         || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1490 #endif
1491         )
1492         return false;
1493 #endif
1494
1495     if (elementHasDirectionAuto(element) || elementHasDirectionAuto(m_element))
1496         return false;
1497
1498     if (element->hasClass()) {
1499 #if ENABLE(SVG)
1500         // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
1501         if (element->isSVGElement()) {
1502             if (element->getAttribute(classAttr) != m_element->getAttribute(classAttr))
1503                 return false;
1504         } else
1505 #endif
1506         if (element->fastGetAttribute(classAttr) != m_element->fastGetAttribute(classAttr))
1507             return false;
1508     }
1509
1510     if (element->attributeStyle() && !attributeStylesEqual(element->attributeStyle(), m_styledElement->attributeStyle()))
1511         return false;
1512
1513     if (additionalAttributeStyleA && !attributeStylesEqual(additionalAttributeStyleA, additionalAttributeStyleB))
1514         return false;
1515
1516     if (element->isLink() && m_elementLinkState != style->insideLink())
1517         return false;
1518
1519     return true;
1520 }
1521
1522 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
1523 {
1524     for (; node; node = node->previousSibling()) {
1525         if (!node->isStyledElement())
1526             continue;
1527         if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
1528             break;
1529         if (count++ == cStyleSearchThreshold)
1530             return 0;
1531     }
1532     return static_cast<StyledElement*>(node);
1533 }
1534
1535 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1536 {
1537     return parentStyle->childrenAffectedByPositionalRules()
1538         || parentStyle->childrenAffectedByFirstChildRules()
1539         || parentStyle->childrenAffectedByLastChildRules() 
1540         || parentStyle->childrenAffectedByDirectAdjacentRules();
1541 }
1542
1543 RenderStyle* StyleResolver::locateSharedStyle()
1544 {
1545     if (!m_styledElement || !m_parentStyle)
1546         return 0;
1547     // If the element has inline style it is probably unique.
1548     if (m_styledElement->inlineStyle())
1549         return 0;
1550 #if ENABLE(SVG)
1551     if (m_styledElement->isSVGElement() && static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties())
1552         return 0;
1553 #endif
1554     // Ids stop style sharing if they show up in the stylesheets.
1555     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1556         return 0;
1557     if (parentStylePreventsSharing(m_parentStyle))
1558         return 0;
1559 #if ENABLE(STYLE_SCOPED)
1560     if (m_styledElement->hasScopedHTMLStyleChild())
1561         return 0;
1562 #endif
1563
1564     // Check previous siblings and their cousins.
1565     unsigned count = 0;
1566     unsigned visitedNodeCount = 0;
1567     StyledElement* shareElement = 0;
1568     Node* cousinList = m_styledElement->previousSibling();
1569     while (cousinList) {
1570         shareElement = findSiblingForStyleSharing(cousinList, count);
1571         if (shareElement)
1572             break;
1573         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1574     }
1575
1576     // If we have exhausted all our budget or our cousins.
1577     if (!shareElement)
1578         return 0;
1579
1580     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1581     if (matchesRuleSet(m_siblingRuleSet.get()))
1582         return 0;
1583     // Can't share if attribute rules apply.
1584     if (matchesRuleSet(m_uncommonAttributeRuleSet.get()))
1585         return 0;
1586     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1587     if (parentStylePreventsSharing(m_parentStyle))
1588         return 0;
1589     return shareElement->renderStyle();
1590 }
1591
1592 void StyleResolver::matchUARules(MatchResult& result)
1593 {
1594     MatchingUARulesScope scope;
1595
1596     // First we match rules from the user agent sheet.
1597     if (simpleDefaultStyleSheet)
1598         result.isCacheable = false;
1599     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1600         ? defaultPrintStyle : defaultStyle;
1601     matchUARules(result, userAgentStyleSheet);
1602
1603     // In quirks mode, we match rules from the quirks user agent sheet.
1604     if (!m_checker.strictParsing())
1605         matchUARules(result, defaultQuirksStyle);
1606
1607     // 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.
1608     if (m_checker.document()->isViewSource()) {
1609         if (!defaultViewSourceStyle)
1610             loadViewSourceStyle();
1611         matchUARules(result, defaultViewSourceStyle);
1612     }
1613 }
1614
1615 static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderStyle* style)
1616 {
1617     if (paginationMode == Pagination::Unpaginated)
1618         return;
1619         
1620     switch (paginationMode) {
1621     case Pagination::LeftToRightPaginated:
1622         style->setColumnAxis(HorizontalColumnAxis);
1623         if (style->isHorizontalWritingMode())
1624             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1625         else
1626             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1627         break;
1628     case Pagination::RightToLeftPaginated:
1629         style->setColumnAxis(HorizontalColumnAxis);
1630         if (style->isHorizontalWritingMode())
1631             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1632         else
1633             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1634         break;
1635     case Pagination::TopToBottomPaginated:
1636         style->setColumnAxis(VerticalColumnAxis);
1637         if (style->isHorizontalWritingMode())
1638             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1639         else
1640             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1641         break;
1642     case Pagination::BottomToTopPaginated:
1643         style->setColumnAxis(VerticalColumnAxis);
1644         if (style->isHorizontalWritingMode())
1645             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1646         else
1647             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1648         break;
1649     case Pagination::Unpaginated:
1650         ASSERT_NOT_REACHED();
1651         break;
1652     }
1653 }
1654
1655 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document* document, CSSFontSelector* fontSelector)
1656 {
1657     Frame* frame = document->frame();
1658
1659     // HTML5 states that seamless iframes should replace default CSS values
1660     // with values inherited from the containing iframe element. However,
1661     // some values (such as the case of designMode = "on") still need to
1662     // be set by this "document style".
1663     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1664     bool seamlessWithParent = document->shouldDisplaySeamlesslyWithParent();
1665     if (seamlessWithParent) {
1666         RenderStyle* iframeStyle = document->seamlessParentIFrame()->renderStyle();
1667         if (iframeStyle)
1668             documentStyle->inheritFrom(iframeStyle);
1669     }
1670
1671     // FIXME: It's not clear which values below we want to override in the seamless case!
1672     documentStyle->setDisplay(BLOCK);
1673     if (!seamlessWithParent) {
1674         documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1675         documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomFactor() : 1);
1676         documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1677         documentStyle->setLocale(document->contentLanguage());
1678     }
1679     // FIXME: This overrides any -webkit-user-modify inherited from the parent iframe.
1680     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1681
1682     Element* docElement = document->documentElement();
1683     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1684     if (docElementRenderer) {
1685         // Use the direction and writing-mode of the body to set the
1686         // viewport's direction and writing-mode unless the property is set on the document element.
1687         // If there is no body, then use the document element.
1688         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1689         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1690             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1691         else
1692             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1693         if (bodyRenderer && !document->directionSetOnDocumentElement())
1694             documentStyle->setDirection(bodyRenderer->style()->direction());
1695         else
1696             documentStyle->setDirection(docElementRenderer->style()->direction());
1697     }
1698
1699     if (frame) {
1700         if (FrameView* frameView = frame->view()) {
1701             const Pagination& pagination = frameView->pagination();
1702             if (pagination.mode != Pagination::Unpaginated) {
1703                 setStylesForPaginationMode(pagination.mode, documentStyle.get());
1704                 documentStyle->setColumnGap(pagination.gap);
1705                 if (RenderView* view = document->renderView()) {
1706                     if (view->hasColumns())
1707                         view->updateColumnInfoFromStyle(documentStyle.get());
1708                 }
1709             }
1710         }
1711     }
1712
1713     // Seamless iframes want to inherit their font from their parent iframe, so early return before setting the font.
1714     if (seamlessWithParent)
1715         return documentStyle.release();
1716
1717     FontDescription fontDescription;
1718     fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
1719     if (Settings* settings = document->settings()) {
1720         fontDescription.setUsePrinterFont(document->printing() || !settings->screenFontSubstitutionEnabled());
1721         fontDescription.setRenderingMode(settings->fontRenderingMode());
1722         const AtomicString& standardFont = settings->standardFontFamily(fontDescription.script());
1723         if (!standardFont.isEmpty()) {
1724             fontDescription.setGenericFamily(FontDescription::StandardFamily);
1725             fontDescription.firstFamily().setFamily(standardFont);
1726             fontDescription.firstFamily().appendFamily(0);
1727         }
1728         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1729         int size = StyleResolver::fontSizeForKeyword(document, CSSValueMedium, false);
1730         fontDescription.setSpecifiedSize(size);
1731         bool useSVGZoomRules = document->isSVGDocument();
1732         fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1733     } else
1734         fontDescription.setUsePrinterFont(document->printing());
1735
1736     documentStyle->setFontDescription(fontDescription);
1737     documentStyle->font().update(fontSelector);
1738
1739     return documentStyle.release();
1740 }
1741
1742 static inline bool isAtShadowBoundary(const Element* element)
1743 {
1744     if (!element)
1745         return false;
1746     ContainerNode* parentNode = element->parentNode();
1747     return parentNode && parentNode->isShadowRoot();
1748 }
1749
1750 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
1751     StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
1752 {
1753     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1754     // will vanish if a style recalc happens during loading.
1755     if (sharingBehavior == AllowStyleSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1756         if (!s_styleNotYetAvailable) {
1757             s_styleNotYetAvailable = RenderStyle::create().leakRef();
1758             s_styleNotYetAvailable->setDisplay(NONE);
1759             s_styleNotYetAvailable->font().update(m_fontSelector);
1760         }
1761         element->document()->setHasNodesWithPlaceholderStyle();
1762         return s_styleNotYetAvailable;
1763     }
1764
1765     initElement(element);
1766     initForStyleResolve(element, defaultParent);
1767     m_regionForStyling = regionForStyling;
1768     if (sharingBehavior == AllowStyleSharing && !m_distributedToInsertionPoint) {
1769         RenderStyle* sharedStyle = locateSharedStyle();
1770         if (sharedStyle)
1771             return sharedStyle;
1772     }
1773
1774     m_style = RenderStyle::create();
1775
1776     RefPtr<RenderStyle> cloneForParent;
1777
1778     if (m_parentStyle)
1779         m_style->inheritFrom(m_parentStyle, isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
1780     else {
1781         // Make sure our fonts are initialized if we don't inherit them from our parent style.
1782         if (Settings* settings = documentSettings()) {
1783             initializeFontStyle(settings);
1784             m_style->font().update(fontSelector());
1785         } else
1786             m_style->font().update(0);
1787         cloneForParent = RenderStyle::clone(style());
1788         m_parentStyle = cloneForParent.get();
1789     }
1790
1791     if (element->isLink()) {
1792         m_style->setIsLink(true);
1793         m_style->setInsideLink(m_elementLinkState);
1794     }
1795
1796     ensureDefaultStyleSheetsForElement(element);
1797
1798     MatchResult matchResult;
1799     if (matchingBehavior == MatchOnlyUserAgentRules)
1800         matchUARules(matchResult);
1801     else
1802         matchAllRules(matchResult, matchingBehavior != MatchAllRulesExcludingSMIL);
1803
1804     applyMatchedProperties(matchResult, element);
1805
1806     // Clean up our style object's display and text decorations (among other fixups).
1807     adjustRenderStyle(style(), m_parentStyle, element);
1808
1809     initElement(0); // Clear out for the next resolve.
1810
1811     if (cloneForParent)
1812         m_parentStyle = 0;
1813
1814     // Now return the style.
1815     return m_style.release();
1816 }
1817
1818 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
1819 {
1820     MatchResult result;
1821     if (keyframe->properties())
1822         addMatchedProperties(result, keyframe->properties());
1823
1824     ASSERT(!m_style);
1825
1826     // Create the style
1827     m_style = RenderStyle::clone(elementStyle);
1828
1829     m_lineHeightValue = 0;
1830
1831     // We don't need to bother with !important. Since there is only ever one
1832     // decl, there's nothing to override. So just add the first properties.
1833     bool inheritedOnly = false;
1834     if (keyframe->properties())
1835         applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1836
1837     // If our font got dirtied, go ahead and update it now.
1838     updateFont();
1839
1840     // Line-height is set when we are sure we decided on the font-size
1841     if (m_lineHeightValue)
1842         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1843
1844     // Now do rest of the properties.
1845     if (keyframe->properties())
1846         applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1847
1848     // If our font got dirtied by one of the non-essential font props,
1849     // go ahead and update it a second time.
1850     updateFont();
1851
1852     // Start loading resources referenced by this style.
1853     loadPendingResources();
1854     
1855     // Add all the animating properties to the keyframe.
1856     if (const StylePropertySet* styleDeclaration = keyframe->properties()) {
1857         unsigned propertyCount = styleDeclaration->propertyCount();
1858         for (unsigned i = 0; i < propertyCount; ++i) {
1859             CSSPropertyID property = styleDeclaration->propertyAt(i).id();
1860             // Timing-function within keyframes is special, because it is not animated; it just
1861             // describes the timing function between this keyframe and the next.
1862             if (property != CSSPropertyWebkitAnimationTimingFunction)
1863                 keyframeValue.addProperty(property);
1864         }
1865     }
1866
1867     return m_style.release();
1868 }
1869
1870 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1871 {
1872     list.clear();
1873
1874     // Get the keyframesRule for this name
1875     if (!e || list.animationName().isEmpty())
1876         return;
1877
1878     m_keyframesRuleMap.checkConsistency();
1879
1880     KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
1881     if (it == m_keyframesRuleMap.end())
1882         return;
1883
1884     const StyleRuleKeyframes* keyframesRule = it->second.get();
1885
1886     // Construct and populate the style for each keyframe
1887     const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
1888     for (unsigned i = 0; i < keyframes.size(); ++i) {
1889         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1890         initElement(e);
1891         initForStyleResolve(e);
1892
1893         const StyleKeyframe* keyframe = keyframes[i].get();
1894
1895         KeyframeValue keyframeValue(0, 0);
1896         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
1897
1898         // Add this keyframe style to all the indicated key times
1899         Vector<float> keys;
1900         keyframe->getKeys(keys);
1901         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1902             keyframeValue.setKey(keys[keyIndex]);
1903             list.insert(keyframeValue);
1904         }
1905     }
1906
1907     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1908     int initialListSize = list.size();
1909     if (initialListSize > 0 && list[0].key()) {
1910         static StyleKeyframe* zeroPercentKeyframe;
1911         if (!zeroPercentKeyframe) {
1912             zeroPercentKeyframe = StyleKeyframe::create().leakRef();
1913             zeroPercentKeyframe->setKeyText("0%");
1914         }
1915         KeyframeValue keyframeValue(0, 0);
1916         keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
1917         list.insert(keyframeValue);
1918     }
1919
1920     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1921     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1922         static StyleKeyframe* hundredPercentKeyframe;
1923         if (!hundredPercentKeyframe) {
1924             hundredPercentKeyframe = StyleKeyframe::create().leakRef();
1925             hundredPercentKeyframe->setKeyText("100%");
1926         }
1927         KeyframeValue keyframeValue(1, 0);
1928         keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
1929         list.insert(keyframeValue);
1930     }
1931 }
1932
1933 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1934 {
1935     ASSERT(m_parentStyle);
1936     if (!e)
1937         return 0;
1938
1939     initElement(e);
1940
1941     initForStyleResolve(e, parentStyle, pseudo);
1942     m_style = RenderStyle::create();
1943     m_style->inheritFrom(m_parentStyle);
1944
1945     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1946     // those rules.
1947
1948     // Check UA, user and author rules.
1949     MatchResult matchResult;
1950     matchUARules(matchResult);
1951
1952     if (m_matchAuthorAndUserStyles) {
1953         matchUserRules(matchResult, false);
1954         matchAuthorRules(matchResult, false);
1955     }
1956
1957     if (matchResult.matchedProperties.isEmpty())
1958         return 0;
1959
1960     m_style->setStyleType(pseudo);
1961
1962     applyMatchedProperties(matchResult, e);
1963
1964     // Clean up our style object's display and text decorations (among other fixups).
1965     adjustRenderStyle(style(), parentStyle, 0);
1966
1967     // Start loading resources referenced by this style.
1968     loadPendingResources();
1969
1970     // Now return the style.
1971     return m_style.release();
1972 }
1973
1974 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
1975 {
1976     initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1977
1978     m_style = RenderStyle::create();
1979     m_style->inheritFrom(m_rootElementStyle);
1980
1981     const bool isLeft = isLeftPage(pageIndex);
1982     const bool isFirst = isFirstPage(pageIndex);
1983     const String page = pageName(pageIndex);
1984     
1985     MatchResult result;
1986     matchPageRules(result, defaultPrintStyle, isLeft, isFirst, page);
1987     matchPageRules(result, m_userStyle.get(), isLeft, isFirst, page);
1988     // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
1989     matchPageRules(result, m_authorStyle.get(), isLeft, isFirst, page);
1990     m_lineHeightValue = 0;
1991     bool inheritedOnly = false;
1992 #if ENABLE(CSS_VARIABLES)
1993     applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1994 #endif
1995     applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1996
1997     // If our font got dirtied, go ahead and update it now.
1998     updateFont();
1999
2000     // Line-height is set when we are sure we decided on the font-size.
2001     if (m_lineHeightValue)
2002         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2003
2004     applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
2005
2006     // Start loading resources referenced by this style.
2007     loadPendingResources();
2008
2009     // Now return the style.
2010     return m_style.release();
2011 }
2012
2013 static void addIntrinsicMargins(RenderStyle* style)
2014 {
2015     // Intrinsic margin value.
2016     const int intrinsicMargin = 2 * style->effectiveZoom();
2017
2018     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
2019     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
2020     if (style->width().isIntrinsicOrAuto()) {
2021         if (style->marginLeft().quirk())
2022             style->setMarginLeft(Length(intrinsicMargin, Fixed));
2023         if (style->marginRight().quirk())
2024             style->setMarginRight(Length(intrinsicMargin, Fixed));
2025     }
2026
2027     if (style->height().isAuto()) {
2028         if (style->marginTop().quirk())
2029             style->setMarginTop(Length(intrinsicMargin, Fixed));
2030         if (style->marginBottom().quirk())
2031             style->setMarginBottom(Length(intrinsicMargin, Fixed));
2032     }
2033 }
2034
2035 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
2036 {
2037     switch (display) {
2038     case BLOCK:
2039     case TABLE:
2040     case BOX:
2041     case FLEX:
2042     case GRID:
2043         return display;
2044
2045     case LIST_ITEM:
2046         // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
2047         if (!strictParsing && isFloating)
2048             return BLOCK;
2049         return display;
2050     case INLINE_TABLE:
2051         return TABLE;
2052     case INLINE_BOX:
2053         return BOX;
2054     case INLINE_FLEX:
2055         return FLEX;
2056     case INLINE_GRID:
2057         return GRID;
2058
2059     case INLINE:
2060     case RUN_IN:
2061     case COMPACT:
2062     case INLINE_BLOCK:
2063     case TABLE_ROW_GROUP:
2064     case TABLE_HEADER_GROUP:
2065     case TABLE_FOOTER_GROUP:
2066     case TABLE_ROW:
2067     case TABLE_COLUMN_GROUP:
2068     case TABLE_COLUMN:
2069     case TABLE_CELL:
2070     case TABLE_CAPTION:
2071         return BLOCK;
2072     case NONE:
2073         ASSERT_NOT_REACHED();
2074         return NONE;
2075     }
2076     ASSERT_NOT_REACHED();
2077     return BLOCK;
2078 }
2079
2080 // CSS requires text-decoration to be reset at each DOM element for tables, 
2081 // inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
2082 // and absolute or relatively positioned elements.
2083 static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e)
2084 {
2085     return style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
2086         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
2087         || style->isFloating() || style->hasOutOfFlowPosition();
2088 }
2089
2090 static bool isDisplayFlexibleBox(EDisplay display)
2091 {
2092     return display == FLEX || display == INLINE_FLEX;
2093 }
2094
2095 void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
2096 {
2097     ASSERT(parentStyle);
2098
2099     // Cache our original display.
2100     style->setOriginalDisplay(style->display());
2101
2102     if (style->display() != NONE) {
2103         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
2104         // property.
2105         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
2106         // these tags to retain their display types.
2107         if (!m_checker.strictParsing() && e) {
2108             if (e->hasTagName(tdTag)) {
2109                 style->setDisplay(TABLE_CELL);
2110                 style->setFloating(NoFloat);
2111             } else if (e->hasTagName(tableTag))
2112                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
2113         }
2114
2115         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
2116             if (style->whiteSpace() == KHTML_NOWRAP) {
2117                 // Figure out if we are really nowrapping or if we should just
2118                 // use normal instead. If the width of the cell is fixed, then
2119                 // we don't actually use NOWRAP.
2120                 if (style->width().isFixed())
2121                     style->setWhiteSpace(NORMAL);
2122                 else
2123                     style->setWhiteSpace(NOWRAP);
2124             }
2125         }
2126
2127         // Tables never support the -webkit-* values for text-align and will reset back to the default.
2128         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
2129             style->setTextAlign(TASTART);
2130
2131         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
2132         // fix a crash where a site tries to position these objects. They also never honor display.
2133         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
2134             style->setPosition(StaticPosition);
2135             style->setDisplay(BLOCK);
2136         }
2137
2138         // Ruby text does not support float or position. This might change with evolution of the specification.
2139         if (e && e->hasTagName(rtTag)) {
2140             style->setPosition(StaticPosition);
2141             style->setFloating(NoFloat);
2142         }
2143
2144         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
2145         // Table headers with a text-align of -webkit-auto will change the text-align to center.
2146         if (e && e->hasTagName(thTag) && style->textAlign() == TASTART)
2147             style->setTextAlign(CENTER);
2148
2149         if (e && e->hasTagName(legendTag))
2150             style->setDisplay(BLOCK);
2151
2152         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
2153         if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document()->documentElement() == e))
2154             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), m_checker.strictParsing()));
2155
2156         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
2157         // clear how that should work.
2158         if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
2159             style->setDisplay(INLINE_BLOCK);
2160
2161         // After performing the display mutation, check table rows. We do not honor position:relative on
2162         // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
2163         // on some sites).
2164         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
2165              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
2166              && style->position() == RelativePosition)
2167             style->setPosition(StaticPosition);
2168
2169         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
2170         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
2171         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
2172             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
2173             || style->display() == TABLE_CELL)
2174             style->setWritingMode(parentStyle->writingMode());
2175
2176         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
2177         // of block-flow to anything other than TopToBottomWritingMode.
2178         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
2179         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
2180             style->setWritingMode(TopToBottomWritingMode);
2181
2182         if (isDisplayFlexibleBox(parentStyle->display())) {
2183             style->setFloating(NoFloat);
2184             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), m_checker.strictParsing()));
2185         }
2186     }
2187
2188     // Make sure our z-index value is only applied if the object is positioned.
2189     if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle->display()))
2190         style->setHasAutoZIndex();
2191
2192     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
2193     // cases where objects that should be blended as a single unit end up with a non-transparent
2194     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
2195     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e)
2196         || style->opacity() < 1.0f
2197         || style->hasTransformRelatedProperty()
2198         || style->hasMask()
2199         || style->clipPath()
2200         || style->boxReflect()
2201         || style->hasFilter()
2202         || style->hasBlendMode()
2203         || style->position() == StickyPosition
2204 #ifdef FIXED_POSITION_CREATES_STACKING_CONTEXT
2205         || style->position() == FixedPosition
2206 #else
2207         || (style->position() == FixedPosition && e && e->document()->page() && e->document()->page()->settings()->fixedPositionCreatesStackingContext())
2208 #endif
2209 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
2210         // Touch overflow scrolling creates a stacking context.
2211         || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
2212 #endif
2213         ))
2214         style->setZIndex(0);
2215
2216     // Textarea considers overflow visible as auto.
2217     if (e && e->hasTagName(textareaTag)) {
2218         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
2219         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
2220     }
2221
2222     if (doesNotInheritTextDecoration(style, e))
2223         style->setTextDecorationsInEffect(style->textDecoration());
2224     else
2225         style->addToTextDecorationsInEffect(style->textDecoration());
2226
2227     // If either overflow value is not visible, change to auto.
2228     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
2229         style->setOverflowY(OMARQUEE);
2230     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
2231         style->setOverflowX(OMARQUEE);
2232     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
2233         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
2234         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
2235         // default to auto so we can at least scroll through the pages.
2236         style->setOverflowX(OAUTO);
2237     } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
2238         style->setOverflowY(OAUTO);
2239
2240     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
2241     // styles are specified on a root element, then they will be incorporated in
2242     // StyleResolver::styleForDocument().
2243     if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e->hasTagName(htmlTag) || e->hasTagName(bodyTag)))
2244         setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style), style);
2245
2246     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
2247     // FIXME: Eventually table sections will support auto and scroll.
2248     if (style->display() == TABLE || style->display() == INLINE_TABLE
2249         || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
2250         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
2251             style->setOverflowX(OVISIBLE);
2252         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
2253             style->setOverflowY(OVISIBLE);
2254     }
2255
2256     // Menulists should have visible overflow
2257     if (style->appearance() == MenulistPart) {
2258         style->setOverflowX(OVISIBLE);
2259         style->setOverflowY(OVISIBLE);
2260     }
2261
2262     // Cull out any useless layers and also repeat patterns into additional layers.
2263     style->adjustBackgroundLayers();
2264     style->adjustMaskLayers();
2265
2266     // Do the same for animations and transitions.
2267     style->adjustAnimations();
2268     style->adjustTransitions();
2269
2270     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
2271     // alter fonts and heights/widths.
2272     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
2273         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
2274         // so we have to treat all image buttons as though they were explicitly sized.
2275         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
2276             addIntrinsicMargins(style);
2277     }
2278
2279     // Let the theme also have a crack at adjusting the style.
2280     if (style->hasAppearance())
2281         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
2282
2283     // If we have first-letter pseudo style, do not share this style.
2284     if (style->hasPseudoStyle(FIRST_LETTER))
2285         style->setUnique();
2286
2287     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
2288     if (style->preserves3D() && (style->overflowX() != OVISIBLE
2289         || style->overflowY() != OVISIBLE
2290         || style->hasFilter()))
2291         style->setTransformStyle3D(TransformStyle3DFlat);
2292
2293     // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
2294     if (e && e->hasTagName(iframeTag) && style->display() == INLINE && static_cast<HTMLIFrameElement*>(e)->shouldDisplaySeamlessly())
2295         style->setDisplay(INLINE_BLOCK);
2296
2297 #if ENABLE(SVG)
2298     if (e && e->isSVGElement()) {
2299         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
2300         if (style->overflowY() == OSCROLL)
2301             style->setOverflowY(OHIDDEN);
2302         else if (style->overflowY() == OAUTO)
2303             style->setOverflowY(OVISIBLE);
2304
2305         if (style->overflowX() == OSCROLL)
2306             style->setOverflowX(OHIDDEN);
2307         else if (style->overflowX() == OAUTO)
2308             style->setOverflowX(OVISIBLE);
2309
2310         // Only the root <svg> element in an SVG document fragment tree honors css position
2311         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
2312             style->setPosition(RenderStyle::initialPosition());
2313
2314         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
2315         // not be scaled again.
2316         if (e->hasTagName(SVGNames::foreignObjectTag))
2317             style->setEffectiveZoom(RenderStyle::initialZoom());
2318     }
2319 #endif
2320 }
2321
2322 bool StyleResolver::checkRegionStyle(Element* regionElement)
2323 {
2324     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
2325     // so all region rules are global by default. Verify whether that can stand or needs changing.
2326
2327     unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size();
2328     for (unsigned i = 0; i < rulesSize; ++i) {
2329         ASSERT(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2330         if (checkRegionSelector(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2331             return true;
2332     }
2333
2334     if (m_userStyle) {
2335         rulesSize = m_userStyle->m_regionSelectorsAndRuleSets.size();
2336         for (unsigned i = 0; i < rulesSize; ++i) {
2337             ASSERT(m_userStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2338             if (checkRegionSelector(m_userStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2339                 return true;
2340         }
2341     }
2342
2343     return false;
2344 }
2345
2346 void StyleResolver::updateFont()
2347 {
2348     if (!m_fontDirty)
2349         return;
2350
2351     checkForTextSizeAdjust();
2352     checkForGenericFamilyChange(style(), m_parentStyle);
2353     checkForZoomChange(style(), m_parentStyle);
2354     m_style->font().update(m_fontSelector);
2355     m_fontDirty = false;
2356 }
2357
2358 void StyleResolver::cacheBorderAndBackground()
2359 {
2360     m_hasUAAppearance = m_style->hasAppearance();
2361     if (m_hasUAAppearance) {
2362         m_borderData = m_style->border();
2363         m_backgroundData = *m_style->backgroundLayers();
2364         m_backgroundColor = m_style->backgroundColor();
2365     }
2366 }
2367
2368 PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
2369 {
2370     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
2371 }
2372
2373 PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
2374 {
2375     if (!e || !e->document()->haveStylesheetsLoaded())
2376         return 0;
2377
2378     m_checker.setMode(SelectorChecker::CollectingRules);
2379
2380     initElement(e);
2381     initForStyleResolve(e, 0, pseudoId);
2382
2383     MatchResult dummy;
2384     if (rulesToInclude & UAAndUserCSSRules) {
2385         // First we match rules from the user agent sheet.
2386         matchUARules(dummy);
2387
2388         // Now we check user sheet rules.
2389         if (m_matchAuthorAndUserStyles)
2390             matchUserRules(dummy, rulesToInclude & EmptyCSSRules);
2391     }
2392
2393     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
2394         m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
2395
2396         // Check the rules in author sheets.
2397         matchAuthorRules(dummy, rulesToInclude & EmptyCSSRules);
2398
2399         m_sameOriginOnly = false;
2400     }
2401
2402     m_checker.setMode(SelectorChecker::ResolvingStyle);
2403
2404     return m_ruleList.release();
2405 }
2406
2407 inline bool StyleResolver::checkSelector(const RuleData& ruleData, const ContainerNode* scope)
2408 {
2409     m_dynamicPseudo = NOPSEUDO;
2410     m_hasUnknownPseudoElements = false;
2411
2412     if (ruleData.hasFastCheckableSelector()) {
2413         // We know this selector does not include any pseudo elements.
2414         if (m_pseudoStyle != NOPSEUDO)
2415             return false;
2416         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
2417         // This is limited to HTML only so we don't need to check the namespace.
2418         if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
2419             if (!ruleData.hasMultipartSelector())
2420                 return true;
2421         } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
2422             return false;
2423         if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
2424             return false;
2425         return m_checker.fastCheckSelector(ruleData.selector(), m_element);
2426     }
2427
2428     // Slow path.
2429     SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled);
2430     context.elementStyle = style();
2431     context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
2432     context.scope = scope;
2433     context.pseudoStyle = m_pseudoStyle;
2434     SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo, m_hasUnknownPseudoElements);
2435     if (match != SelectorChecker::SelectorMatches)
2436         return false;
2437     if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != m_dynamicPseudo)
2438         return false;
2439     return true;
2440 }
2441
2442 bool StyleResolver::checkRegionSelector(CSSSelector* regionSelector, Element* regionElement)
2443 {
2444     if (!regionSelector || !regionElement)
2445         return false;
2446
2447     m_hasUnknownPseudoElements = false;
2448     m_pseudoStyle = NOPSEUDO;
2449
2450     for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s))
2451         if (m_checker.checkSelector(s, regionElement))
2452             return true;
2453
2454     return false;
2455 }
2456     
2457 bool StyleResolver::determineStylesheetSelectorScopes(StyleSheetContents* stylesheet, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes)
2458 {
2459     ASSERT(!stylesheet->isLoading());
2460
2461     const Vector<RefPtr<StyleRuleImport> >& importRules = stylesheet->importRules();
2462     for (unsigned i = 0; i < importRules.size(); ++i) {
2463         if (!importRules[i]->styleSheet())
2464             continue;
2465         if (!determineStylesheetSelectorScopes(importRules[i]->styleSheet(), idScopes, classScopes))
2466             return false;
2467     }
2468
2469     const Vector<RefPtr<StyleRuleBase> >& rules = stylesheet->childRules();
2470     for (unsigned i = 0; i < rules.size(); i++) {
2471         StyleRuleBase* rule = rules[i].get();
2472         if (rule->isStyleRule()) {
2473             StyleRule* styleRule = static_cast<StyleRule*>(rule);
2474             if (!SelectorChecker::determineSelectorScopes(styleRule->selectorList(), idScopes, classScopes))
2475                 return false;
2476             continue;
2477         } 
2478         // FIXME: Media rules and maybe some others could be allowed.
2479         return false;
2480     }
2481     return true;
2482 }
2483
2484 // -----------------------------------------------------------------
2485
2486 static inline bool isSelectorMatchingHTMLBasedOnRuleHash(const CSSSelector* selector)
2487 {
2488     const AtomicString& selectorNamespace = selector->tag().namespaceURI();
2489     if (selectorNamespace != starAtom && selectorNamespace != xhtmlNamespaceURI)
2490         return false;
2491     if (selector->m_match == CSSSelector::None)
2492         return true;
2493     if (selector->tag() != starAtom)
2494         return false;
2495     if (SelectorChecker::isCommonPseudoClassSelector(selector))
2496         return true;
2497     return selector->m_match == CSSSelector::Id || selector->m_match == CSSSelector::Class;
2498 }
2499
2500 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector)
2501 {
2502     CSSSelectorList* selectorList = selector->selectorList();
2503     if (!selectorList)
2504         return false;
2505     for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2506         if (subSelector->isAttributeSelector())
2507             return true;
2508     }
2509     return false;
2510 }
2511
2512 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute)
2513 {
2514     // These are explicitly tested for equality in canShareStyleWithElement.
2515     return attribute == typeAttr || attribute == readonlyAttr;
2516 }
2517
2518 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector)
2519 {
2520     for (; selector; selector = selector->tagHistory()) {
2521         // Allow certain common attributes (used in the default style) in the selectors that match the current element.
2522         if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute()))
2523             return true;
2524         if (selectorListContainsUncommonAttributeSelector(selector))
2525             return true;
2526         if (selector->relation() != CSSSelector::SubSelector) {
2527             selector = selector->tagHistory();
2528             break;
2529         }
2530     }
2531
2532     for (; selector; selector = selector->tagHistory()) {
2533         if (selector->isAttributeSelector())
2534             return true;
2535         if (selectorListContainsUncommonAttributeSelector(selector))
2536             return true;
2537     }
2538     return false;
2539 }
2540
2541 RuleData::RuleData(StyleRule* rule, unsigned selectorIndex, unsigned position, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
2542     : m_rule(rule)
2543     , m_selectorIndex(selectorIndex)
2544     , m_position(position)
2545     , m_specificity(selector()->specificity())
2546     , m_hasFastCheckableSelector(canUseFastCheckSelector && SelectorChecker::isFastCheckableSelector(selector()))
2547     , m_hasMultipartSelector(!!selector()->tagHistory())
2548     , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector()))
2549     , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector()))
2550     , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector()))
2551     , m_hasDocumentSecurityOrigin(hasDocumentSecurityOrigin)
2552     , m_isInRegionRule(inRegionRule)
2553 {
2554     ASSERT(m_position == position);
2555     ASSERT(m_selectorIndex == selectorIndex);
2556     SelectorChecker::collectIdentifierHashes(selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
2557 }
2558
2559 void RuleData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
2560 {
2561     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
2562 }
2563
2564 RuleSet::RuleSet()
2565     : m_ruleCount(0)
2566     , m_autoShrinkToFitEnabled(true)
2567 {
2568 }
2569
2570 static void reportAtomRuleMap(MemoryClassInfo* info, const RuleSet::AtomRuleMap& atomicRuleMap)
2571 {
2572     info->addHashMap(atomicRuleMap);
2573     for (RuleSet::AtomRuleMap::const_iterator it = atomicRuleMap.begin(); it != atomicRuleMap.end(); ++it)
2574         info->addMember(*it->second);
2575 }
2576
2577 void RuleSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
2578 {
2579     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
2580     reportAtomRuleMap(&info, m_idRules);
2581     reportAtomRuleMap(&info, m_classRules);
2582     reportAtomRuleMap(&info, m_tagRules);
2583     reportAtomRuleMap(&info, m_shadowPseudoElementRules);
2584     info.addMember(m_linkPseudoClassRules);
2585     info.addMember(m_focusPseudoClassRules);
2586     info.addMember(m_universalRules);
2587     info.addMember(m_pageRules);
2588     info.addMember(m_regionSelectorsAndRuleSets);
2589 }
2590
2591 void RuleSet::RuleSetSelectorPair::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
2592 {
2593     MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
2594     info.addMember(ruleSet);
2595 }
2596
2597 static inline void collectFeaturesFromSelector(StyleResolver::Features& features, const CSSSelector* selector)
2598 {
2599     if (selector->m_match == CSSSelector::Id)
2600         features.idsInRules.add(selector->value().impl());
2601     if (selector->isAttributeSelector())
2602         features.attrsInRules.add(selector->attribute().localName().impl());
2603     switch (selector->pseudoType()) {
2604     case CSSSelector::PseudoFirstLine:
2605         features.usesFirstLineRules = true;
2606         break;
2607     case CSSSelector::PseudoBefore:
2608     case CSSSelector::PseudoAfter:
2609         features.usesBeforeAfterRules = true;
2610         break;
2611     default:
2612         break;
2613     }
2614 }
2615
2616 static void collectFeaturesFromRuleData(StyleResolver::Features& features, const RuleData& ruleData)
2617 {
2618     bool foundSiblingSelector = false;
2619     for (CSSSelector* selector = ruleData.selector(); selector; selector = selector->tagHistory()) {
2620         collectFeaturesFromSelector(features, selector);
2621         
2622         if (CSSSelectorList* selectorList = selector->selectorList()) {
2623             for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) {
2624                 if (!foundSiblingSelector && selector->isSiblingSelector())
2625                     foundSiblingSelector = true;
2626                 collectFeaturesFromSelector(features, subSelector);
2627             }
2628         } else if (!foundSiblingSelector && selector->isSiblingSelector())
2629             foundSiblingSelector = true;
2630     }
2631     if (foundSiblingSelector)
2632         features.siblingRules.append(StyleResolver::RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
2633     if (ruleData.containsUncommonAttributeSelector())
2634         features.uncommonAttributeRules.append(StyleResolver::RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin()));
2635 }
2636     
2637 void RuleSet::addToRuleSet(AtomicStringImpl* key, AtomRuleMap& map, const RuleData& ruleData)
2638 {
2639     if (!key)
2640         return;
2641     OwnPtr<Vector<RuleData> >& rules = map.add(key, nullptr).iterator->second;
2642     if (!rules)
2643         rules = adoptPtr(new Vector<RuleData>);
2644     rules->append(ruleData);
2645 }
2646
2647 void RuleSet::addRule(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool inRegionRule)
2648 {
2649     RuleData ruleData(rule, selectorIndex, m_ruleCount++, hasDocumentSecurityOrigin, canUseFastCheckSelector, inRegionRule);
2650     collectFeaturesFromRuleData(m_features, ruleData);
2651
2652     CSSSelector* selector = ruleData.selector();
2653
2654     if (selector->m_match == CSSSelector::Id) {
2655         addToRuleSet(selector->value().impl(), m_idRules, ruleData);
2656         return;
2657     }
2658     if (selector->m_match == CSSSelector::Class) {
2659         addToRuleSet(selector->value().impl(), m_classRules, ruleData);
2660         return;
2661     }
2662     if (selector->isUnknownPseudoElement()) {
2663         addToRuleSet(selector->value().impl(), m_shadowPseudoElementRules, ruleData);
2664         return;
2665     }
2666     if (SelectorChecker::isCommonPseudoClassSelector(selector)) {
2667         switch (selector->pseudoType()) {
2668         case CSSSelector::PseudoLink:
2669         case CSSSelector::PseudoVisited:
2670         case CSSSelector::PseudoAnyLink:
2671             m_linkPseudoClassRules.append(ruleData);
2672             return;
2673         case CSSSelector::PseudoFocus:
2674             m_focusPseudoClassRules.append(ruleData);
2675             return;
2676         default:
2677             ASSERT_NOT_REACHED();
2678         }
2679         return;
2680     }
2681     const AtomicString& localName = selector->tag().localName();
2682     if (localName != starAtom) {
2683         addToRuleSet(localName.impl(), m_tagRules, ruleData);
2684         return;
2685     }
2686     m_universalRules.append(ruleData);
2687 }
2688
2689 void RuleSet::addPageRule(StyleRulePage* rule)
2690 {
2691     m_pageRules.append(rule);
2692 }
2693
2694 void RuleSet::addRegionRule(StyleRuleRegion* regionRule, bool hasDocumentSecurityOrigin)
2695 {
2696     OwnPtr<RuleSet> regionRuleSet = RuleSet::create();
2697     // The region rule set should take into account the position inside the parent rule set.
2698     // Otherwise, the rules inside region block might be incorrectly positioned before other similar rules from
2699     // the stylesheet that contains the region block.
2700     regionRuleSet->m_ruleCount = m_ruleCount;
2701
2702     // Collect the region rules into a rule set
2703     const Vector<RefPtr<StyleRuleBase> >& childRules = regionRule->childRules();
2704     for (unsigned i = 0; i < childRules.size(); ++i) {
2705         StyleRuleBase* regionStylingRule = childRules[i].get();
2706         if (regionStylingRule->isStyleRule())
2707             regionRuleSet->addStyleRule(static_cast<StyleRule*>(regionStylingRule), hasDocumentSecurityOrigin, true, true);
2708     }
2709     // Update the "global" rule count so that proper order is maintained
2710     m_ruleCount = regionRuleSet->m_ruleCount;
2711
2712     m_regionSelectorsAndRuleSets.append(RuleSetSelectorPair(regionRule->selectorList().first(), regionRuleSet.release()));
2713 }
2714
2715 void RuleSet::addRulesFromSheet(StyleSheetContents* sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver, const ContainerNode* scope)
2716 {
2717     ASSERT(sheet);
2718     
2719     const Vector<RefPtr<StyleRuleImport> >& importRules = sheet->importRules();
2720     for (unsigned i = 0; i < importRules.size(); ++i) {
2721         StyleRuleImport* importRule = importRules[i].get();
2722         if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), resolver)))
2723             addRulesFromSheet(importRule->styleSheet(), medium, resolver, scope);
2724     }
2725     bool hasDocumentSecurityOrigin = resolver && resolver->document()->securityOrigin()->canRequest(sheet->baseURL());
2726
2727     const Vector<RefPtr<StyleRuleBase> >& rules = sheet->childRules();
2728     for (unsigned i = 0; i < rules.size(); ++i) {
2729         StyleRuleBase* rule = rules[i].get();
2730
2731         ASSERT(!rule->isImportRule());
2732         if (rule->isStyleRule())
2733             addStyleRule(static_cast<StyleRule*>(rule), hasDocumentSecurityOrigin, !scope);
2734         else if (rule->isPageRule())
2735             addPageRule(static_cast<StyleRulePage*>(rule));
2736         else if (rule->isMediaRule()) {
2737             StyleRuleMedia* mediaRule = static_cast<StyleRuleMedia*>(rule);
2738
2739             if ((!mediaRule->mediaQueries() || medium.eval(mediaRule->mediaQueries(), resolver))) {
2740                 // Traverse child elements of the @media rule.
2741                 const Vector<RefPtr<StyleRuleBase> >& childRules = mediaRule->childRules();
2742                 for (unsigned j = 0; j < childRules.size(); ++j) {
2743                     StyleRuleBase* childRule = childRules[j].get();
2744                     if (childRule->isStyleRule())
2745                         addStyleRule(static_cast<StyleRule*>(childRule), hasDocumentSecurityOrigin, !scope);
2746                     else if (childRule->isPageRule())
2747                         addPageRule(static_cast<StyleRulePage*>(childRule));
2748                     else if (childRule->isFontFaceRule() && resolver) {
2749                         // Add this font face to our set.
2750                         // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
2751                         if (scope)
2752                             continue;
2753                         const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(childRule);
2754                         resolver->fontSelector()->addFontFaceRule(fontFaceRule);
2755                         resolver->invalidateMatchedPropertiesCache();
2756                     } else if (childRule->isKeyframesRule() && resolver) {
2757                         // Add this keyframe rule to our set.
2758                         // FIXME(BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
2759                         if (scope)
2760                             continue;
2761                         resolver->addKeyframeStyle(static_cast<StyleRuleKeyframes*>(childRule));
2762                     }
2763                 } // for rules
2764             } // if rules
2765         } else if (rule->isFontFaceRule() && resolver) {
2766             // Add this font face to our set.
2767             // FIXME(BUG 72461): We don't add @font-face rules of scoped style sheets for the moment.
2768             if (scope)
2769                 continue;
2770             const StyleRuleFontFace* fontFaceRule = static_cast<StyleRuleFontFace*>(rule);
2771             resolver->fontSelector()->addFontFaceRule(fontFaceRule);
2772             resolver->invalidateMatchedPropertiesCache();
2773         } else if (rule->isKeyframesRule() && resolver) {
2774             // FIXME (BUG 72462): We don't add @keyframe rules of scoped style sheets for the moment.
2775             if (scope)
2776                 continue;
2777             resolver->addKeyframeStyle(static_cast<StyleRuleKeyframes*>(rule));
2778         }
2779 #if ENABLE(CSS_REGIONS)
2780         else if (rule->isRegionRule() && resolver) {
2781             // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment.
2782             if (scope)
2783                 continue;
2784             addRegionRule(static_cast<StyleRuleRegion*>(rule), hasDocumentSecurityOrigin);
2785         }
2786 #endif
2787     }
2788     if (m_autoShrinkToFitEnabled)
2789         shrinkToFit();
2790 }
2791
2792 void RuleSet::addStyleRule(StyleRule* rule, bool hasDocumentSecurityOrigin, bool canUseFastCheckSelector, bool isInRegionRule)
2793 {
2794     for (size_t selectorIndex = 0; selectorIndex != notFound; selectorIndex = rule->selectorList().indexOfNextSelectorAfter(selectorIndex))
2795         addRule(rule, selectorIndex, hasDocumentSecurityOrigin, canUseFastCheckSelector, isInRegionRule);
2796 }
2797
2798 static inline void shrinkMapVectorsToFit(RuleSet::AtomRuleMap& map)
2799 {
2800     RuleSet::AtomRuleMap::iterator end = map.end();
2801     for (RuleSet::AtomRuleMap::iterator it = map.begin(); it != end; ++it)
2802         it->second->shrinkToFit();
2803 }
2804
2805 void RuleSet::shrinkToFit()
2806 {
2807     shrinkMapVectorsToFit(m_idRules);
2808     shrinkMapVectorsToFit(m_classRules);
2809     shrinkMapVectorsToFit(m_tagRules);
2810     shrinkMapVectorsToFit(m_shadowPseudoElementRules);
2811     m_linkPseudoClassRules.shrinkToFit();
2812     m_focusPseudoClassRules.shrinkToFit();
2813     m_universalRules.shrinkToFit();
2814     m_pageRules.shrinkToFit();
2815 }
2816
2817 // -------------------------------------------------------------------------------------
2818 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2819
2820 Length StyleResolver::convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2821 {
2822     return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2823 }
2824
2825 Length StyleResolver::convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2826 {
2827     return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2828 }
2829
2830 template <StyleResolver::StyleApplicationPass pass>
2831 void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, bool filterRegionProperties)
2832 {
2833     ASSERT(!filterRegionProperties || m_regionForStyling);
2834     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), rule);
2835
2836     unsigned propertyCount = properties->propertyCount();
2837     for (unsigned i = 0; i < propertyCount; ++i) {
2838         const CSSProperty& current = properties->propertyAt(i);
2839         if (isImportant != current.isImportant())
2840             continue;
2841         if (inheritedOnly && !current.isInherited()) {
2842             // If the property value is explicitly inherited, we need to apply further non-inherited properties
2843             // as they might override the value inherited here. For this reason we don't allow declarations with
2844             // explicitly inherited properties to be cached.
2845             ASSERT(!current.value()->isInheritedValue());
2846             continue;
2847         }
2848         CSSPropertyID property = current.id();
2849
2850         if (filterRegionProperties && !StyleResolver::isValidRegionStyleProperty(property))
2851             continue;
2852
2853         switch (pass) {
2854 #if ENABLE(CSS_VARIABLES)
2855         case VariableDefinitions:
2856             COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_is_before_first_property);
2857             if (property == CSSPropertyVariable)
2858                 applyProperty(current.id(), current.value());
2859             break;
2860 #endif
2861         case HighPriorityProperties:
2862             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2863             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range);
2864             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2865 #if ENABLE(CSS_VARIABLES)
2866             if (property == CSSPropertyVariable)
2867                 continue;
2868 #endif
2869             // give special priority to font-xxx, color properties, etc
2870             if (property < CSSPropertyLineHeight)
2871                 applyProperty(current.id(), current.value());
2872             // we apply line-height later
2873             else if (property == CSSPropertyLineHeight)
2874                 m_lineHeightValue = current.value();
2875             break;
2876         case LowPriorityProperties:
2877             if (property > CSSPropertyLineHeight)
2878                 applyProperty(current.id(), current.value());
2879         }
2880     }
2881     InspectorInstrumentation::didProcessRule(cookie);
2882 }
2883
2884 template <StyleResolver::StyleApplicationPass pass>
2885 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
2886 {
2887     if (startIndex == -1)
2888         return;
2889
2890     if (m_style->insideLink() != NotInsideLink) {
2891         for (int i = startIndex; i <= endIndex; ++i) {
2892             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2893             unsigned linkMatchType = matchedProperties.linkMatchType;
2894             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2895             m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2896             m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2897
2898             applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2899         }
2900         m_applyPropertyToRegularStyle = true;
2901         m_applyPropertyToVisitedLinkStyle = false;
2902         return;
2903     }
2904     for (int i = startIndex; i <= endIndex; ++i) {
2905         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2906         applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2907     }
2908 }
2909
2910 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
2911 {
2912     
2913     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
2914 }
2915
2916 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
2917 {
2918     return a.firstUARule == b.firstUARule
2919         && a.lastUARule == b.lastUARule
2920         && a.firstAuthorRule == b.firstAuthorRule
2921         && a.lastAuthorRule == b.lastAuthorRule
2922         && a.firstUserRule == b.firstUserRule
2923         && a.lastUserRule == b.lastUserRule;
2924 }
2925
2926 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
2927 {
2928     return !(a == b);
2929 }
2930
2931 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
2932 {
2933     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
2934 }
2935
2936 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
2937 {
2938     return !(a == b);
2939 }
2940
2941 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
2942 {
2943     ASSERT(hash);
2944
2945     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
2946     if (it == m_matchedPropertiesCache.end())
2947         return 0;
2948     MatchedPropertiesCacheItem& cacheItem = it->second;
2949
2950     size_t size = matchResult.matchedProperties.size();
2951     if (size != cacheItem.matchedProperties.size())
2952         return 0;
2953     for (size_t i = 0; i < size; ++i) {
2954         if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
2955             return 0;
2956     }
2957     if (cacheItem.ranges != matchResult.ranges)
2958         return 0;
2959     return &cacheItem;
2960 }
2961
2962 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
2963 {
2964     static unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
2965     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps) {
2966         sweepMatchedPropertiesCache();
2967         m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
2968     }
2969
2970     ASSERT(hash);
2971     MatchedPropertiesCacheItem cacheItem;
2972     cacheItem.matchedProperties.append(matchResult.matchedProperties);
2973     cacheItem.ranges = matchResult.ranges;
2974     // Note that we don't cache the original RenderStyle instance. It may be further modified.
2975     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
2976     cacheItem.renderStyle = RenderStyle::clone(style);
2977     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
2978     m_matchedPropertiesCache.add(hash, cacheItem);
2979 }
2980
2981 void StyleResolver::invalidateMatchedPropertiesCache()
2982 {
2983     m_matchedPropertiesCache.clear();
2984 }
2985
2986 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
2987 {
2988     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
2989     if (element == element->document()->documentElement() && element->document()->writingModeSetOnDocumentElement())
2990         return false;
2991     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2992         return false;
2993     if (style->hasAppearance())
2994         return false;
2995     if (style->zoom() != RenderStyle::initialZoom())
2996         return false;
2997     // The cache assumes static knowledge about which properties are inherited.
2998     if (parentStyle->hasExplicitlyInheritedProperties())
2999         return false;
3000     return true;
3001 }
3002
3003 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element)
3004 {
3005     ASSERT(element);
3006     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
3007     bool applyInheritedOnly = false;
3008     const MatchedPropertiesCacheItem* cacheItem = 0;
3009     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
3010         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
3011         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
3012         // element context. This is fast and saves memory by reusing the style data structures.
3013         m_style->copyNonInheritedFrom(cacheItem->renderStyle.get());
3014         if (m_parentStyle->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
3015             EInsideLink linkStatus = m_style->insideLink();
3016             // If the cache item parent style has identical inherited properties to the current parent style then the
3017             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
3018             m_style->inheritFrom(cacheItem->renderStyle.get());
3019
3020             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
3021             m_style->setInsideLink(linkStatus);
3022             return;
3023         }
3024         applyInheritedOnly = true; 
3025     }
3026
3027 #if ENABLE(CSS_VARIABLES)
3028     // First apply all variable definitions, as they may be used during application of later properties.
3029     applyMatchedProperties<VariableDefinitions>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
3030     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
3031     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
3032     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
3033 #endif
3034
3035     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
3036     // high-priority properties first, i.e., those properties that other properties depend on.
3037     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
3038     // and (4) normal important.
3039     m_lineHeightValue = 0;
3040     applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
3041     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
3042     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
3043     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
3044
3045     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) {
3046         m_fontDirty = true;
3047         applyInheritedOnly = false;
3048     }
3049
3050     // If our font got dirtied, go ahead and update it now.
3051     updateFont();
3052
3053     // Line-height is set when we are sure we decided on the font-size.
3054     if (m_lineHeightValue)
3055         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
3056
3057     // Many properties depend on the font. If it changes we just apply all properties.
3058     if (cacheItem && cacheItem->renderStyle->fontDescription() != m_style->fontDescription())
3059         applyInheritedOnly = false;
3060
3061     // Now do the normal priority UA properties.
3062     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
3063     
3064     // Cache our border and background so that we can examine them later.
3065     cacheBorderAndBackground();
3066     
3067     // Now do the author and user normal priority properties and all the !important properties.
3068     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
3069     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
3070     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
3071     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
3072    
3073     // Start loading resources referenced by this style.
3074     loadPendingResources();
3075     
3076     ASSERT(!m_fontDirty);
3077     
3078     if (cacheItem || !cacheHash)
3079         return;
3080     if (!isCacheableInMatchedPropertiesCache(m_element, m_style.get(), m_parentStyle))
3081         return;
3082     addToMatchedPropertiesCache(m_style.get(), m_parentStyle, cacheHash, matchResult);
3083 }
3084
3085 static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
3086 {
3087     return r1->selector()->specificity() < r2->selector()->specificity();
3088 }
3089
3090 void StyleResolver::matchPageRules(MatchResult& result, RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
3091 {
3092     if (!rules)
3093         return;
3094
3095     Vector<StyleRulePage*> matchedPageRules;
3096     matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
3097     if (matchedPageRules.isEmpty())
3098         return;
3099
3100     std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
3101
3102     for (unsigned i = 0; i < matchedPageRules.size(); i++)
3103         addMatchedProperties(result, matchedPageRules[i]->properties());
3104 }
3105
3106 void StyleResolver::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
3107 {
3108     unsigned size = rules.size();
3109     for (unsigned i = 0; i < size; ++i) {
3110         StyleRulePage* rule = rules[i];
3111         const AtomicString& selectorLocalName = rule->selector()->tag().localName();
3112         if (selectorLocalName != starAtom && selectorLocalName != pageName)
3113             continue;
3114         CSSSelector::PseudoType pseudoType = rule->selector()->pseudoType();
3115         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
3116             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
3117             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
3118             continue;
3119
3120         // If the rule has no properties to apply, then ignore it.
3121         const StylePropertySet* properties = rule->properties();
3122         if (!properties || properties->isEmpty())
3123             continue;
3124
3125         // Add this rule to our list of matched rules.
3126         matchedRules.append(rule);
3127     }
3128 }
3129
3130 bool StyleResolver::isLeftPage(int pageIndex) const
3131 {
3132     bool isFirstPageLeft = false;
3133     if (!m_rootElementStyle->isLeftToRightDirection())
3134         isFirstPageLeft = true;
3135
3136     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
3137 }
3138
3139 bool StyleResolver::isFirstPage(int pageIndex) const
3140 {
3141     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
3142     return (!pageIndex);
3143 }
3144
3145 String StyleResolver::pageName(int /* pageIndex */) const
3146 {
3147     // FIXME: Implement page index to page name mapping.
3148     return "";
3149 }
3150
3151 template <class ListType>
3152 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, ListType* listType)
3153 {
3154     if (!listType)
3155         return;
3156     unsigned size = listType->length();
3157     for (unsigned i = 0; i < size; ++i) {
3158         CSSRule* cssRule = listType->item(i);
3159         if (cssRule->isImportRule())
3160             collectCSSOMWrappers(wrapperMap, static_cast<CSSImportRule*>(cssRule)->styleSheet());
3161         else if (cssRule->isMediaRule())
3162             collectCSSOMWrappers(wrapperMap, static_cast<CSSMediaRule*>(cssRule));
3163 #if ENABLE(CSS_REGIONS)
3164         else if (cssRule->isRegionRule())
3165             collectCSSOMWrappers(wrapperMap, static_cast<WebKitCSSRegionRule*>(cssRule));
3166 #endif
3167         else if (cssRule->isStyleRule()) {
3168             CSSStyleRule* cssStyleRule = static_cast<CSSStyleRule*>(cssRule);
3169             wrapperMap.add(cssStyleRule->styleRule(), cssStyleRule);
3170         }
3171     }
3172 }
3173
3174 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, HashSet<RefPtr<CSSStyleSheet> >& sheetWrapperSet, StyleSheetContents* styleSheet)
3175 {
3176     if (!styleSheet)
3177         return;
3178     RefPtr<CSSStyleSheet> styleSheetWrapper = CSSStyleSheet::create(styleSheet);
3179     sheetWrapperSet.add(styleSheetWrapper);
3180     collectCSSOMWrappers(wrapperMap, styleSheetWrapper.get());
3181 }
3182
3183 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, DocumentStyleSheetCollection* styleSheetCollection)
3184 {
3185     const Vector<RefPtr<StyleSheet> >& styleSheets = styleSheetCollection->authorStyleSheets();
3186     for (unsigned i = 0; i < styleSheets.size(); ++i) {
3187         StyleSheet* styleSheet = styleSheets[i].get();
3188         if (!styleSheet->isCSSStyleSheet())
3189             continue;
3190         collectCSSOMWrappers(wrapperMap, static_cast<CSSStyleSheet*>(styleSheet));
3191     }
3192     collectCSSOMWrappers(wrapperMap, styleSheetCollection->pageUserSheet());
3193     {
3194         const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = styleSheetCollection->pageGroupUserSheets();
3195         if (pageGroupUserSheets) {
3196             for (size_t i = 0, size = pageGroupUserSheets->size(); i < size; ++i)
3197                 collectCSSOMWrappers(wrapperMap, pageGroupUserSheets->at(i).get());
3198         }
3199     }
3200     {
3201         const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = styleSheetCollection->documentUserSheets();
3202         if (documentUserSheets) {
3203             for (size_t i = 0, size = documentUserSheets->size(); i < size; ++i)
3204                 collectCSSOMWrappers(wrapperMap, documentUserSheets->at(i).get());
3205         }
3206     }
3207 }
3208
3209 CSSStyleRule* StyleResolver::ensureFullCSSOMWrapperForInspector(StyleRule* rule)
3210 {
3211     if (m_styleRuleToCSSOMWrapperMap.isEmpty()) {
3212         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, simpleDefaultStyleSheet);
3213         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, defaultStyleSheet);
3214         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, quirksStyleSheet);
3215         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, svgStyleSheet);
3216         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, mathMLStyleSheet);
3217         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, mediaControlsStyleSheet);
3218         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, fullscreenStyleSheet);
3219
3220         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, document()->styleSheetCollection());
3221     }
3222     return m_styleRuleToCSSOMWrapperMap.get(rule).get();
3223 }
3224
3225 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
3226 {
3227     initElement(0);
3228     initForStyleResolve(0, style);
3229     m_style = style;
3230     applyPropertyToCurrentStyle(id, value);
3231 }
3232
3233 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
3234 {
3235     if (value)
3236         applyProperty(id, value);
3237 }
3238
3239 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
3240 {
3241     switch (id) {
3242     case CSSPropertyBackgroundColor:
3243     case CSSPropertyBorderLeftColor:
3244     case CSSPropertyBorderRightColor:
3245     case CSSPropertyBorderTopColor:
3246     case CSSPropertyBorderBottomColor:
3247     case CSSPropertyColor:
3248     case CSSPropertyOutlineColor:
3249     case CSSPropertyWebkitColumnRuleColor:
3250     case CSSPropertyWebkitTextEmphasisColor:
3251     case CSSPropertyWebkitTextFillColor:
3252     case CSSPropertyWebkitTextStrokeColor:
3253     // Also allow shorthands so that inherit/initial still work.
3254     case CSSPropertyBackground:
3255     case CSSPropertyBorderLeft:
3256     case CSSPropertyBorderRight:
3257     case CSSPropertyBorderTop:
3258     case CSSPropertyBorderBottom:
3259     case CSSPropertyOutline:
3260     case CSSPropertyWebkitColumnRule:
3261 #if ENABLE(SVG)
3262     case CSSPropertyFill:
3263     case CSSPropertyStroke:
3264 #endif
3265         return true;
3266     default:
3267         break;
3268     }
3269
3270     return false;
3271 }
3272
3273 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
3274 // FIXME: add incremental support for other region styling properties.
3275 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
3276 {
3277     switch (id) {
3278     case CSSPropertyBackgroundColor:
3279     case CSSPropertyColor:
3280         return true;
3281     default:
3282         break;
3283     }
3284
3285     return false;
3286 }
3287
3288 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
3289 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
3290 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
3291 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
3292 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
3293 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
3294 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
3295 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
3296 bool StyleResolver::useSVGZoomRules()
3297 {
3298     return m_element && m_element->isSVGElement();
3299 }
3300
3301 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, StyleResolver* selector, Length& length)
3302 {
3303     Length workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
3304     if (workingLength.isUndefined())
3305         return false;
3306
3307     if (primitiveValue->isLength())
3308         workingLength.setQuirk(primitiveValue->isQuirkValue());
3309
3310     length = workingLength;
3311     return true;
3312 }
3313
3314 static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, StyleResolver* selector)
3315 {
3316     // Handle 'none'.
3317     if (value->isPrimitiveValue()) {
3318         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3319         if (primitiveValue->getIdent() == CSSValueNone) {
3320             lengths.append(Length(Undefined));
3321             return true;
3322         }
3323         return false;
3324     }
3325
3326     if (value->isValueList()) {
3327         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3328             CSSValue* currValue = i.value();
3329             if (!currValue->isPrimitiveValue())
3330                 return false;
3331
3332             Length length;
3333             if (!createGridTrackBreadth(static_cast<CSSPrimitiveValue*>(currValue), selector, length))
3334                 return false;
3335
3336             lengths.append(length);
3337         }
3338         return true;
3339     }
3340
3341     return false;
3342 }
3343
3344
3345 static bool createGridPosition(CSSValue* value, Length& position)
3346 {
3347     // For now, we only accept: <integer> | 'auto'
3348     if (!value->isPrimitiveValue())
3349         return false;
3350
3351     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3352     if (primitiveValue->getIdent() == CSSValueAuto)
3353         return true;
3354
3355     ASSERT(primitiveValue->isNumber());
3356     position.setValue(primitiveValue->getIntValue());
3357     return true;
3358 }
3359
3360 #if ENABLE(CSS_VARIABLES)
3361 static bool hasVariableReference(CSSValue* value)
3362 {
3363     if (value->isPrimitiveValue()) {
3364         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
3365         return primitiveValue->hasVariableReference();
3366     }
3367
3368     if (value->isCalculationValue())
3369         return static_cast<CSSCalcValue*>(value)->hasVariableReference();
3370
3371     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3372         if (hasVariableReference(i.value()))
3373             return true;
3374     }
3375
3376     return false;
3377 }
3378
3379 void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<std::pair<CSSPropertyID, String> >& knownExpressions)
3380 {
3381     std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVariables(*style()->variables()));
3382
3383     if (knownExpressions.contains(expression))
3384         return; // cycle detected.
3385
3386     knownExpressions.append(expression);
3387
3388     // FIXME: It would be faster not to re-parse from strings, but for now CSS property validation lives inside the parser so we do it there.
3389     RefPtr<StylePropertySet> resultSet = StylePropertySet::create();
3390     if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, document()))
3391         return; // expression failed to parse.
3392
3393     for (unsigned i = 0; i < resultSet->propertyCount(); i++) {
3394         const CSSProperty& property = resultSet->propertyAt(i);
3395         if (property.id() != CSSPropertyVariable && hasVariableReference(property.value()))
3396             resolveVariables(property.id(), property.value(), knownExpressions);
3397         else
3398             applyProperty(property.id(), property.value());
3399     }
3400 }
3401 #endif
3402
3403 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
3404 {
3405 #if ENABLE(CSS_VARIABLES)
3406     if (id != CSSPropertyVariable && hasVariableReference(value)) {
3407         Vector<std::pair<CSSPropertyID, String> > knownExpressions;
3408         resolveVariables(id, value, knownExpressions);
3409         return;
3410     }
3411 #endif
3412
3413     bool isInherit = m_parentNode && value->isInheritedValue();
3414     bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
3415
3416     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
3417
3418     if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
3419         // Limit the properties that can be applied to only the ones honored by :visited.
3420         return;
3421     }
3422
3423     if (isInherit && m_parentStyle && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))