Unreviewed, rolling out r134986.
[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 "ElementShadow.h"
65 #include "FontFeatureValue.h"
66 #include "FontValue.h"
67 #include "Frame.h"
68 #include "FrameSelection.h"
69 #include "FrameView.h"
70 #include "HTMLDocument.h"
71 #include "HTMLIFrameElement.h"
72 #include "HTMLInputElement.h"
73 #include "HTMLNames.h"
74 #include "HTMLOptionElement.h"
75 #include "HTMLProgressElement.h"
76 #include "HTMLStyleElement.h"
77 #include "HTMLTextAreaElement.h"
78 #include "InsertionPoint.h"
79 #include "InspectorInstrumentation.h"
80 #include "KeyframeList.h"
81 #include "LinkHash.h"
82 #include "LocaleToScriptMapping.h"
83 #include "MathMLNames.h"
84 #include "Matrix3DTransformOperation.h"
85 #include "MatrixTransformOperation.h"
86 #include "MediaList.h"
87 #include "MediaQueryEvaluator.h"
88 #include "NodeRenderStyle.h"
89 #include "NodeRenderingContext.h"
90 #include "Page.h"
91 #include "PageGroup.h"
92 #include "Pair.h"
93 #include "PerspectiveTransformOperation.h"
94 #include "QuotesData.h"
95 #include "Rect.h"
96 #include "RenderRegion.h"
97 #include "RenderScrollbar.h"
98 #include "RenderScrollbarTheme.h"
99 #include "RenderStyleConstants.h"
100 #include "RenderTheme.h"
101 #include "RenderView.h"
102 #include "RotateTransformOperation.h"
103 #include "RuleSet.h"
104 #include "SVGDocumentExtensions.h"
105 #include "SVGFontFaceElement.h"
106 #include "ScaleTransformOperation.h"
107 #include "SecurityOrigin.h"
108 #include "Settings.h"
109 #include "ShadowData.h"
110 #include "ShadowRoot.h"
111 #include "ShadowValue.h"
112 #include "SiblingTraversalStrategies.h"
113 #include "SkewTransformOperation.h"
114 #include "StyleBuilder.h"
115 #include "StyleCachedImage.h"
116 #include "StyleGeneratedImage.h"
117 #include "StylePendingImage.h"
118 #include "StyleRule.h"
119 #include "StyleRuleImport.h"
120 #include "StyleSheetContents.h"
121 #include "StyleSheetList.h"
122 #include "Text.h"
123 #include "TransformationMatrix.h"
124 #include "TranslateTransformOperation.h"
125 #include "UserAgentStyleSheets.h"
126 #include "WebCoreMemoryInstrumentation.h"
127 #include "WebKitCSSKeyframeRule.h"
128 #include "WebKitCSSKeyframesRule.h"
129 #include "WebKitCSSRegionRule.h"
130 #include "WebKitCSSTransformValue.h"
131 #include "WebKitFontFamilyNames.h"
132 #include "XMLNames.h"
133 #include <wtf/MemoryInstrumentationHashMap.h>
134 #include <wtf/MemoryInstrumentationHashSet.h>
135 #include <wtf/MemoryInstrumentationVector.h>
136 #include <wtf/StdLibExtras.h>
137 #include <wtf/Vector.h>
138
139 #if ENABLE(CSS_FILTERS)
140 #include "FilterOperation.h"
141 #include "WebKitCSSFilterValue.h"
142 #endif
143
144 #if ENABLE(DASHBOARD_SUPPORT)
145 #include "DashboardRegion.h"
146 #endif
147
148 #if ENABLE(SVG)
149 #include "CachedSVGDocument.h"
150 #include "CachedSVGDocumentReference.h"
151 #include "SVGDocument.h"
152 #include "SVGElement.h"
153 #include "SVGNames.h"
154 #include "SVGURIReference.h"
155 #include "WebKitCSSSVGDocumentValue.h"
156 #endif
157
158 #if ENABLE(CSS_SHADERS)
159 #include "CustomFilterArrayParameter.h"
160 #include "CustomFilterConstants.h"
161 #include "CustomFilterNumberParameter.h"
162 #include "CustomFilterOperation.h"
163 #include "CustomFilterParameter.h"
164 #include "CustomFilterTransformParameter.h"
165 #include "StyleCachedShader.h"
166 #include "StyleCustomFilterProgram.h"
167 #include "StylePendingShader.h"
168 #include "StyleShader.h"
169 #include "WebKitCSSMixFunctionValue.h"
170 #include "WebKitCSSShaderValue.h"
171 #endif
172
173 #if ENABLE(CSS_IMAGE_SET)
174 #include "CSSImageSetValue.h"
175 #include "StyleCachedImageSet.h"
176 #endif
177
178 using namespace std;
179
180 namespace WTF {
181
182 template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*> {
183     template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
184 };
185
186 }
187
188 namespace WebCore {
189
190 using namespace HTMLNames;
191
192 #define HANDLE_INHERIT(prop, Prop) \
193 if (isInherit) { \
194     m_style->set##Prop(m_parentStyle->prop()); \
195     return; \
196 }
197
198 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
199 HANDLE_INHERIT(prop, Prop) \
200 if (isInitial) { \
201     m_style->set##Prop(RenderStyle::initial##Prop()); \
202     return; \
203 }
204
205 static RuleSet* defaultStyle;
206 static RuleSet* defaultQuirksStyle;
207 static RuleSet* defaultPrintStyle;
208 static RuleSet* defaultViewSourceStyle;
209 static StyleSheetContents* simpleDefaultStyleSheet;
210 static StyleSheetContents* defaultStyleSheet;
211 static StyleSheetContents* quirksStyleSheet;
212 static StyleSheetContents* svgStyleSheet;
213 static StyleSheetContents* mathMLStyleSheet;
214 static StyleSheetContents* mediaControlsStyleSheet;
215 static StyleSheetContents* fullscreenStyleSheet;
216
217 RenderStyle* StyleResolver::s_styleNotYetAvailable;
218
219 static void loadFullDefaultStyle();
220 static void loadSimpleDefaultStyle();
221 template <class ListType>
222 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >&, ListType*);
223
224 // FIXME: It would be nice to use some mechanism that guarantees this is in sync with the real UA stylesheet.
225 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}";
226
227 static inline bool elementCanUseSimpleDefaultStyle(Element* e)
228 {
229     return e->hasTagName(htmlTag) || e->hasTagName(headTag) || e->hasTagName(bodyTag) || e->hasTagName(divTag) || e->hasTagName(spanTag) || e->hasTagName(brTag) || e->hasTagName(aTag);
230 }
231
232 static const MediaQueryEvaluator& screenEval()
233 {
234     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticScreenEval, ("screen"));
235     return staticScreenEval;
236 }
237
238 static const MediaQueryEvaluator& printEval()
239 {
240     DEFINE_STATIC_LOCAL(const MediaQueryEvaluator, staticPrintEval, ("print"));
241     return staticPrintEval;
242 }
243
244 static StylePropertySet* leftToRightDeclaration()
245 {
246     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
247     if (leftToRightDecl->isEmpty())
248         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
249     return leftToRightDecl.get();
250 }
251
252 static StylePropertySet* rightToLeftDeclaration()
253 {
254     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
255     if (rightToLeftDecl->isEmpty())
256         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
257     return rightToLeftDecl.get();
258 }
259
260 StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
261     : m_hasUAAppearance(false)
262     , m_backgroundData(BackgroundFillLayer)
263     , m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
264     , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
265     , m_checker(document, !document->inQuirksMode())
266     , m_parentStyle(0)
267     , m_rootElementStyle(0)
268     , m_element(0)
269     , m_styledElement(0)
270     , m_regionForStyling(0)
271     , m_elementLinkState(NotInsideLink)
272     , m_parentNode(0)
273     , m_lineHeightValue(0)
274     , m_fontDirty(false)
275     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
276     , m_sameOriginOnly(false)
277     , m_distributedToInsertionPoint(false)
278     , m_fontSelector(CSSFontSelector::create(document))
279     , m_applyPropertyToRegularStyle(true)
280     , m_applyPropertyToVisitedLinkStyle(false)
281     , m_styleBuilder(StyleBuilder::sharedStyleBuilder())
282 #if ENABLE(CSS_SHADERS)
283     , m_hasPendingShaders(false)
284 #endif
285     , m_styleMap(this)
286 {
287     Element* root = document->documentElement();
288
289     if (!defaultStyle) {
290         if (!root || elementCanUseSimpleDefaultStyle(root))
291             loadSimpleDefaultStyle();
292         else
293             loadFullDefaultStyle();
294     }
295
296     // construct document root element default style. this is needed
297     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
298     // This is here instead of constructor, because when constructor is run,
299     // document doesn't have documentElement
300     // NOTE: this assumes that element that gets passed to styleForElement -call
301     // is always from the document that owns the style selector
302     FrameView* view = document->view();
303     if (view)
304         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
305     else
306         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
307
308     if (root)
309         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
310
311     if (m_rootDefaultStyle && view)
312         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
313
314     resetAuthorStyle();
315
316     DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
317     // FIXME: This sucks! The user sheet is reparsed every time!
318     OwnPtr<RuleSet> tempUserStyle = RuleSet::create();
319     if (CSSStyleSheet* pageUserSheet = styleSheetCollection->pageUserSheet())
320         tempUserStyle->addRulesFromSheet(pageUserSheet->contents(), *m_medium, this);
321     addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->pageGroupUserSheets(), *tempUserStyle);
322     addAuthorRulesAndCollectUserRulesFromSheets(styleSheetCollection->documentUserSheets(), *tempUserStyle);
323     if (tempUserStyle->m_ruleCount > 0 || tempUserStyle->m_pageRules.size() > 0)
324         m_userStyle = tempUserStyle.release();
325
326 #if ENABLE(SVG_FONTS)
327     if (document->svgExtensions()) {
328         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
329         HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
330         for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
331             fontSelector()->addFontFaceRule((*it)->fontFaceRule());
332     }
333 #endif
334
335     appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets());
336 }
337
338 void StyleResolver::addAuthorRulesAndCollectUserRulesFromSheets(const Vector<RefPtr<CSSStyleSheet> >* userSheets, RuleSet& userStyle)
339 {
340     if (!userSheets)
341         return;
342
343     unsigned length = userSheets->size();
344     for (unsigned i = 0; i < length; i++) {
345         StyleSheetContents* sheet = userSheets->at(i)->contents();
346         if (sheet->isUserStyleSheet())
347             userStyle.addRulesFromSheet(sheet, *m_medium, this);
348         else
349             m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
350     }
351 }
352
353 static PassOwnPtr<RuleSet> makeRuleSet(const Vector<RuleFeature>& rules)
354 {
355     size_t size = rules.size();
356     if (!size)
357         return nullptr;
358     OwnPtr<RuleSet> ruleSet = RuleSet::create();
359     for (size_t i = 0; i < size; ++i)
360         ruleSet->addRule(rules[i].rule, rules[i].selectorIndex, rules[i].hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState);
361     ruleSet->shrinkToFit();
362     return ruleSet.release();
363 }
364
365 void StyleResolver::collectFeatures()
366 {
367     m_features.clear();
368     // Collect all ids and rules using sibling selectors (:first-child and similar)
369     // in the current set of stylesheets. Style sharing code uses this information to reject
370     // sharing candidates.
371     m_features.add(defaultStyle->features());
372     m_features.add(m_authorStyle->features());
373     if (m_scopeResolver)
374         m_scopeResolver->collectFeaturesTo(m_features);
375     if (m_userStyle)
376         m_features.add(m_userStyle->features());
377
378     m_siblingRuleSet = makeRuleSet(m_features.siblingRules);
379     m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules);
380 }
381
382 void StyleResolver::resetAuthorStyle()
383 {
384     m_authorStyle = RuleSet::create();
385     m_authorStyle->disableAutoShrinkToFit();
386 }
387
388 void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
389 {
390     // This handles sheets added to the end of the stylesheet list only. In other cases the style resolver
391     // needs to be reconstructed. To handle insertions too the rule order numbers would need to be updated.
392     unsigned size = styleSheets.size();
393     for (unsigned i = firstNew; i < size; ++i) {
394         CSSStyleSheet* cssSheet = styleSheets[i].get();
395         ASSERT(!cssSheet->disabled());
396         if (cssSheet->mediaQueries() && !m_medium->eval(cssSheet->mediaQueries(), this))
397             continue;
398         StyleSheetContents* sheet = cssSheet->contents();
399 #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
400         if (const ContainerNode* scope = StyleScopeResolver::scopeFor(cssSheet)) {
401             ensureScopeResolver()->ensureRuleSetFor(scope)->addRulesFromSheet(sheet, *m_medium, this, scope);
402             continue;
403         }
404 #endif
405
406         m_authorStyle->addRulesFromSheet(sheet, *m_medium, this);
407         if (!m_styleRuleToCSSOMWrapperMap.isEmpty())
408             collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, cssSheet);
409     }
410     m_authorStyle->shrinkToFit();
411     collectFeatures();
412     
413     if (document()->renderer() && document()->renderer()->style())
414         document()->renderer()->style()->font().update(fontSelector());
415 }
416
417 void StyleResolver::pushParentElement(Element* parent)
418 {
419     const ContainerNode* parentsParent = parent->parentOrHostElement();
420
421     // We are not always invoked consistently. For example, script execution can cause us to enter
422     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
423     // Reset the stack in this case, or if we see a new root element.
424     // Otherwise just push the new parent.
425     if (!parentsParent || m_checker.parentStackIsEmpty())
426         m_checker.setupParentStack(parent);
427     else
428         m_checker.pushParent(parent);
429
430     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
431     if (m_scopeResolver)
432         m_scopeResolver->push(parent, parent->parentOrHostNode());
433 }
434
435 void StyleResolver::popParentElement(Element* parent)
436 {
437     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
438     // Pause maintaining the stack in this case.
439     if (m_checker.parentStackIsConsistent(parent))
440         m_checker.popParent();
441     if (m_scopeResolver)
442         m_scopeResolver->pop(parent);
443 }
444
445 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
446 {
447     ASSERT(shadowRoot->host());
448     if (m_scopeResolver)
449         m_scopeResolver->push(shadowRoot, shadowRoot->host());
450 }
451
452 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
453 {
454     ASSERT(shadowRoot->host());
455     if (m_scopeResolver)
456         m_scopeResolver->pop(shadowRoot);
457 }
458
459 // This is a simplified style setting function for keyframe styles
460 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
461 {
462     AtomicString s(rule->name());
463     m_keyframesRuleMap.set(s.impl(), rule);
464 }
465
466 StyleResolver::~StyleResolver()
467 {
468     m_fontSelector->clearDocument();
469 }
470
471 void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
472 {
473     // Look for cache entries containing a style declaration with a single ref and remove them.
474     // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
475     // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
476     Vector<unsigned, 16> toRemove;
477     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
478     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
479     for (; it != end; ++it) {
480         Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
481         for (size_t i = 0; i < matchedProperties.size(); ++i) {
482             if (matchedProperties[i].properties->hasOneRef()) {
483                 toRemove.append(it->key);
484                 break;
485             }
486         }
487     }
488     for (size_t i = 0; i < toRemove.size(); ++i)
489         m_matchedPropertiesCache.remove(toRemove[i]);
490
491     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
492 }
493
494 static StyleSheetContents* parseUASheet(const String& str)
495 {
496     StyleSheetContents* sheet = StyleSheetContents::create().leakRef(); // leak the sheet on purpose
497     sheet->parseString(str);
498     return sheet;
499 }
500
501 static StyleSheetContents* parseUASheet(const char* characters, unsigned size)
502 {
503     return parseUASheet(String(characters, size));
504 }
505
506 static void loadFullDefaultStyle()
507 {
508     if (simpleDefaultStyleSheet) {
509         ASSERT(defaultStyle);
510         ASSERT(defaultPrintStyle == defaultStyle);
511         delete defaultStyle;
512         simpleDefaultStyleSheet->deref();
513         defaultStyle = RuleSet::create().leakPtr();
514         defaultPrintStyle = RuleSet::create().leakPtr();
515         simpleDefaultStyleSheet = 0;
516     } else {
517         ASSERT(!defaultStyle);
518         defaultStyle = RuleSet::create().leakPtr();
519         defaultPrintStyle = RuleSet::create().leakPtr();
520         defaultQuirksStyle = RuleSet::create().leakPtr();
521     }
522
523     // Strict-mode rules.
524     String defaultRules = String(htmlUserAgentStyleSheet, sizeof(htmlUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraDefaultStyleSheet();
525     defaultStyleSheet = parseUASheet(defaultRules);
526     defaultStyle->addRulesFromSheet(defaultStyleSheet, screenEval());
527     defaultPrintStyle->addRulesFromSheet(defaultStyleSheet, printEval());
528
529     // Quirks-mode rules.
530     String quirksRules = String(quirksUserAgentStyleSheet, sizeof(quirksUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraQuirksStyleSheet();
531     quirksStyleSheet = parseUASheet(quirksRules);
532     defaultQuirksStyle->addRulesFromSheet(quirksStyleSheet, screenEval());
533 }
534
535 static void loadSimpleDefaultStyle()
536 {
537     ASSERT(!defaultStyle);
538     ASSERT(!simpleDefaultStyleSheet);
539
540     defaultStyle = RuleSet::create().leakPtr();
541     // There are no media-specific rules in the simple default style.
542     defaultPrintStyle = defaultStyle;
543     defaultQuirksStyle = RuleSet::create().leakPtr();
544
545     simpleDefaultStyleSheet = parseUASheet(simpleUserAgentStyleSheet, strlen(simpleUserAgentStyleSheet));
546     defaultStyle->addRulesFromSheet(simpleDefaultStyleSheet, screenEval());
547
548     // No need to initialize quirks sheet yet as there are no quirk rules for elements allowed in simple default style.
549 }
550
551 static void loadViewSourceStyle()
552 {
553     ASSERT(!defaultViewSourceStyle);
554     defaultViewSourceStyle = RuleSet::create().leakPtr();
555     defaultViewSourceStyle->addRulesFromSheet(parseUASheet(sourceUserAgentStyleSheet, sizeof(sourceUserAgentStyleSheet)), screenEval());
556 }
557
558 static void ensureDefaultStyleSheetsForElement(Element* element)
559 {
560     if (simpleDefaultStyleSheet && !elementCanUseSimpleDefaultStyle(element))
561         loadFullDefaultStyle();
562
563 #if ENABLE(SVG)
564     if (element->isSVGElement() && !svgStyleSheet) {
565         // SVG rules.
566         svgStyleSheet = parseUASheet(svgUserAgentStyleSheet, sizeof(svgUserAgentStyleSheet));
567         defaultStyle->addRulesFromSheet(svgStyleSheet, screenEval());
568         defaultPrintStyle->addRulesFromSheet(svgStyleSheet, printEval());
569     }
570 #endif
571
572 #if ENABLE(MATHML)
573     if (element->isMathMLElement() && !mathMLStyleSheet) {
574         // MathML rules.
575         mathMLStyleSheet = parseUASheet(mathmlUserAgentStyleSheet, sizeof(mathmlUserAgentStyleSheet));
576         defaultStyle->addRulesFromSheet(mathMLStyleSheet, screenEval());
577         defaultPrintStyle->addRulesFromSheet(mathMLStyleSheet, printEval());
578     }
579 #endif
580
581 #if ENABLE(VIDEO)
582     if (!mediaControlsStyleSheet && (element->hasTagName(videoTag) || element->hasTagName(audioTag))) {
583         String mediaRules = String(mediaControlsUserAgentStyleSheet, sizeof(mediaControlsUserAgentStyleSheet)) + RenderTheme::themeForPage(element->document()->page())->extraMediaControlsStyleSheet();
584         mediaControlsStyleSheet = parseUASheet(mediaRules);
585         defaultStyle->addRulesFromSheet(mediaControlsStyleSheet, screenEval());
586         defaultPrintStyle->addRulesFromSheet(mediaControlsStyleSheet, printEval());
587     }
588 #endif
589
590 #if ENABLE(FULLSCREEN_API)
591     if (!fullscreenStyleSheet && element->document()->webkitIsFullScreen()) {
592         String fullscreenRules = String(fullscreenUserAgentStyleSheet, sizeof(fullscreenUserAgentStyleSheet)) + RenderTheme::defaultTheme()->extraFullScreenStyleSheet();
593         fullscreenStyleSheet = parseUASheet(fullscreenRules);
594         defaultStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
595         defaultQuirksStyle->addRulesFromSheet(fullscreenStyleSheet, screenEval());
596     }
597 #endif
598
599     ASSERT(defaultStyle->features().idsInRules.isEmpty());
600     ASSERT(mathMLStyleSheet || defaultStyle->features().siblingRules.isEmpty());
601 }
602
603 void StyleResolver::addMatchedProperties(MatchResult& matchResult, const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, bool inRegionRule)
604 {
605     matchResult.matchedProperties.grow(matchResult.matchedProperties.size() + 1);
606     MatchedProperties& newProperties = matchResult.matchedProperties.last();
607     newProperties.properties = const_cast<StylePropertySet*>(properties);
608     newProperties.linkMatchType = linkMatchType;
609     newProperties.isInRegionRule = inRegionRule;
610     matchResult.matchedRules.append(rule);
611 }
612
613 inline void StyleResolver::addElementStyleProperties(MatchResult& result, const StylePropertySet* propertySet, bool isCacheable)
614 {
615     if (!propertySet)
616         return;
617     result.ranges.lastAuthorRule = result.matchedProperties.size();
618     if (result.ranges.firstAuthorRule == -1)
619         result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
620     addMatchedProperties(result, propertySet);
621     if (!isCacheable)
622         result.isCacheable = false;
623 }
624
625 class MatchingUARulesScope {
626 public:
627     MatchingUARulesScope();
628     ~MatchingUARulesScope();
629
630     static bool isMatchingUARules();
631
632 private:
633     static bool m_matchingUARules;
634 };
635
636 MatchingUARulesScope::MatchingUARulesScope()
637 {
638     ASSERT(!m_matchingUARules);
639     m_matchingUARules = true;
640 }
641
642 MatchingUARulesScope::~MatchingUARulesScope()
643 {
644     m_matchingUARules = false;
645 }
646
647 inline bool MatchingUARulesScope::isMatchingUARules()
648 {
649     return m_matchingUARules;
650 }
651
652 bool MatchingUARulesScope::m_matchingUARules = false;
653
654 void StyleResolver::collectMatchingRules(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
655 {
656     ASSERT(rules);
657     ASSERT(m_element);
658
659     const AtomicString& pseudoId = m_element->shadowPseudoId();
660     if (!pseudoId.isEmpty()) {
661         ASSERT(m_styledElement);
662         collectMatchingRulesForList(rules->shadowPseudoElementRules(pseudoId.impl()), firstRuleIndex, lastRuleIndex, options);
663     }
664
665     // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
666     // a) it's a UA rule
667     // b) the tree scope allows author rules
668     // c) the rules comes from a scoped style sheet within the same tree scope
669     TreeScope* treeScope = m_element->treeScope();
670     if (!MatchingUARulesScope::isMatchingUARules()
671         && !treeScope->applyAuthorStyles()
672         && (!options.scope || options.scope->treeScope() != treeScope))
673         return;
674
675     // We need to collect the rules for id, class, tag, and everything else into a buffer and
676     // then sort the buffer.
677     if (m_element->hasID())
678         collectMatchingRulesForList(rules->idRules(m_element->idForStyleResolution().impl()), firstRuleIndex, lastRuleIndex, options);
679     if (m_styledElement && m_styledElement->hasClass()) {
680         for (size_t i = 0; i < m_styledElement->classNames().size(); ++i)
681             collectMatchingRulesForList(rules->classRules(m_styledElement->classNames()[i].impl()), firstRuleIndex, lastRuleIndex, options);
682     }
683
684     if (m_element->isLink())
685         collectMatchingRulesForList(rules->linkPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
686     if (m_checker.matchesFocusPseudoClass(m_element))
687         collectMatchingRulesForList(rules->focusPseudoClassRules(), firstRuleIndex, lastRuleIndex, options);
688     collectMatchingRulesForList(rules->tagRules(m_element->localName().impl()), firstRuleIndex, lastRuleIndex, options);
689     collectMatchingRulesForList(rules->universalRules(), firstRuleIndex, lastRuleIndex, options);
690 }
691
692 void StyleResolver::collectMatchingRulesForRegion(RuleSet* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
693 {
694     if (!m_regionForStyling)
695         return;
696
697     unsigned size = rules->m_regionSelectorsAndRuleSets.size();
698     for (unsigned i = 0; i < size; ++i) {
699         CSSSelector* regionSelector = rules->m_regionSelectorsAndRuleSets.at(i).selector;
700         if (checkRegionSelector(regionSelector, static_cast<Element*>(m_regionForStyling->node()))) {
701             RuleSet* regionRules = rules->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
702             ASSERT(regionRules);
703             collectMatchingRules(regionRules, firstRuleIndex, lastRuleIndex, options);
704         }
705     }
706 }
707
708 void StyleResolver::sortAndTransferMatchedRules(MatchResult& result)
709 {
710     if (m_matchedRules.isEmpty())
711         return;
712
713     sortMatchedRules();
714
715     if (m_checker.mode() == SelectorChecker::CollectingRules) {
716         if (!m_ruleList)
717             m_ruleList = StaticCSSRuleList::create();
718         for (unsigned i = 0; i < m_matchedRules.size(); ++i)
719             m_ruleList->rules().append(m_matchedRules[i]->rule()->createCSSOMWrapper());
720         return;
721     }
722
723     // Now transfer the set of matched rules over to our list of declarations.
724     // FIXME: This sucks, the inspector should get the style from the visited style itself.
725     bool swapVisitedUnvisited = InspectorInstrumentation::forcePseudoState(m_element, CSSSelector::PseudoVisited);
726     for (unsigned i = 0; i < m_matchedRules.size(); i++) {
727         if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector())
728             m_style->setAffectedByUncommonAttributeSelectors();
729         unsigned linkMatchType = m_matchedRules[i]->linkMatchType();
730         if (swapVisitedUnvisited && linkMatchType && linkMatchType != SelectorChecker::MatchAll)
731             linkMatchType = (linkMatchType == SelectorChecker::MatchVisited) ? SelectorChecker::MatchLink : SelectorChecker::MatchVisited;
732         addMatchedProperties(result, m_matchedRules[i]->rule()->properties(), m_matchedRules[i]->rule(), linkMatchType, m_matchedRules[i]->isInRegionRule());
733     }
734 }
735
736 void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
737 {
738 #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
739     if (!m_scopeResolver)
740         return;
741
742     matchHostRules(result, includeEmptyRules);
743
744     if (!m_scopeResolver->hasScopedStyles())
745         return;
746
747     // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
748     if (!m_scopeResolver->ensureStackConsistency(m_element))
749         return;
750
751     bool applyAuthorStyles = m_element->treeScope()->applyAuthorStyles();
752     bool documentScope = true;
753     unsigned scopeSize = m_scopeResolver->stackSize();
754     for (unsigned i = 0; i < scopeSize; ++i) {
755         const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
756         documentScope = documentScope && !frame.m_scope->isInShadowTree();
757         if (documentScope) {
758             if (!applyAuthorStyles)
759                 continue;
760         } else {
761             if (!m_scopeResolver->matchesStyleBounds(frame))
762                 continue;
763         }
764            
765         MatchOptions options(includeEmptyRules, frame.m_scope);
766         collectMatchingRules(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
767         collectMatchingRulesForRegion(frame.m_ruleSet, result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
768     }
769
770 #else
771     UNUSED_PARAM(result);
772     UNUSED_PARAM(includeEmptyRules);
773 #endif
774 }
775
776 inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
777 {
778 #if ENABLE(SHADOW_DOM)
779     return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_element);
780 #else
781     return false;
782 #endif
783 }
784
785 void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules)
786 {
787 #if ENABLE(SHADOW_DOM)
788     ASSERT(m_scopeResolver);
789
790     Vector<RuleSet*> matchedRules;
791     m_scopeResolver->matchHostRules(m_element, matchedRules);
792     if (matchedRules.isEmpty())
793         return;
794
795     MatchOptions options(includeEmptyRules);
796     options.scope = m_element;
797     for (unsigned i = matchedRules.size(); i > 0; --i)
798         collectMatchingRules(matchedRules.at(i-1), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
799 #else
800     UNUSED_PARAM(result);
801     UNUSED_PARAM(includeEmptyRules);
802 #endif
803 }
804
805 void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules)
806 {
807     m_matchedRules.clear();
808     result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
809
810     if (!m_element)
811         return;
812
813     // Match global author rules.
814     MatchOptions options(includeEmptyRules);
815     collectMatchingRules(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
816     collectMatchingRulesForRegion(m_authorStyle.get(), result.ranges.firstAuthorRule, result.ranges.lastAuthorRule, options);
817
818     matchScopedAuthorRules(result, includeEmptyRules);
819
820     sortAndTransferMatchedRules(result);
821 }
822
823 void StyleResolver::matchUserRules(MatchResult& result, bool includeEmptyRules)
824 {
825     if (!m_userStyle)
826         return;
827     
828     m_matchedRules.clear();
829
830     result.ranges.lastUserRule = result.matchedProperties.size() - 1;
831     collectMatchingRules(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
832     collectMatchingRulesForRegion(m_userStyle.get(), result.ranges.firstUserRule, result.ranges.lastUserRule, includeEmptyRules);
833
834     sortAndTransferMatchedRules(result);
835 }
836
837 void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules)
838 {
839     m_matchedRules.clear();
840     
841     result.ranges.lastUARule = result.matchedProperties.size() - 1;
842     collectMatchingRules(rules, result.ranges.firstUARule, result.ranges.lastUARule, false);
843
844     sortAndTransferMatchedRules(result);
845 }
846
847 void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, int& firstRuleIndex, int& lastRuleIndex, const MatchOptions& options)
848 {
849     if (!rules)
850         return;
851
852     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
853     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
854     bool canUseFastReject = m_checker.parentStackIsConsistent(m_parentNode);
855
856     unsigned size = rules->size();
857     for (unsigned i = 0; i < size; ++i) {
858         const RuleData& ruleData = rules->at(i);
859         if (canUseFastReject && m_checker.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
860             continue;
861
862         StyleRule* rule = ruleData.rule();
863         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule);
864         if (checkSelector(ruleData, options.scope)) {
865             // If the rule has no properties to apply, then ignore it in the non-debug mode.
866             const StylePropertySet* properties = rule->properties();
867             if (!properties || (properties->isEmpty() && !options.includeEmptyRules)) {
868                 InspectorInstrumentation::didMatchRule(cookie, false);
869                 continue;
870             }
871             // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
872             if (m_sameOriginOnly && !ruleData.hasDocumentSecurityOrigin()) {
873                 InspectorInstrumentation::didMatchRule(cookie, false);
874                 continue;
875             }
876             // If we're matching normal rules, set a pseudo bit if
877             // we really just matched a pseudo-element.
878             if (m_dynamicPseudo != NOPSEUDO && m_pseudoStyle == NOPSEUDO) {
879                 if (m_checker.mode() == SelectorChecker::CollectingRules) {
880                     InspectorInstrumentation::didMatchRule(cookie, false);
881                     continue;
882                 }
883                 if (m_dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
884                     m_style->setHasPseudoStyle(m_dynamicPseudo);
885             } else {
886                 // Update our first/last rule indices in the matched rules array.
887                 ++lastRuleIndex;
888                 if (firstRuleIndex == -1)
889                     firstRuleIndex = lastRuleIndex;
890
891                 // Add this rule to our list of matched rules.
892                 addMatchedRule(&ruleData);
893                 InspectorInstrumentation::didMatchRule(cookie, true);
894                 continue;
895             }
896         }
897         InspectorInstrumentation::didMatchRule(cookie, false);
898     }
899 }
900
901 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
902 {
903     unsigned specificity1 = r1->specificity();
904     unsigned specificity2 = r2->specificity();
905     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
906 }
907
908 void StyleResolver::sortMatchedRules()
909 {
910     std::sort(m_matchedRules.begin(), m_matchedRules.end(), compareRules);
911 }
912
913 void StyleResolver::matchAllRules(MatchResult& result, bool includeSMILProperties)
914 {
915     matchUARules(result);
916
917     // Now we check user sheet rules.
918     if (m_matchAuthorAndUserStyles)
919         matchUserRules(result, false);
920         
921     // Now check author rules, beginning first with presentational attributes mapped from HTML.
922     if (m_styledElement) {
923         addElementStyleProperties(result, m_styledElement->presentationAttributeStyle());
924
925         // Now we check additional mapped declarations.
926         // Tables and table cells share an additional mapped rule that must be applied
927         // after all attributes, since their mapped style depends on the values of multiple attributes.
928         addElementStyleProperties(result, m_styledElement->additionalPresentationAttributeStyle());
929
930         if (m_styledElement->isHTMLElement()) {
931             bool isAuto;
932             TextDirection textDirection = toHTMLElement(m_styledElement)->directionalityIfhasDirAutoAttribute(isAuto);
933             if (isAuto)
934                 addMatchedProperties(result, textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
935         }
936     }
937     
938     // Check the rules in author sheets next.
939     if (m_matchAuthorAndUserStyles)
940         matchAuthorRules(result, false);
941
942     // Now check our inline style attribute.
943     if (m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->inlineStyle()) {
944         // Inline style is immutable as long as there is no CSSOM wrapper.
945         // FIXME: Media control shadow trees seem to have problems with caching.
946         bool isInlineStyleCacheable = !m_styledElement->inlineStyle()->isMutable() && !m_styledElement->isInShadowTree();
947         // FIXME: Constify.
948         addElementStyleProperties(result, m_styledElement->inlineStyle(), isInlineStyleCacheable);
949     }
950
951 #if ENABLE(SVG)
952     // Now check SMIL animation override style.
953     if (includeSMILProperties && m_matchAuthorAndUserStyles && m_styledElement && m_styledElement->isSVGElement())
954         addElementStyleProperties(result, static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties(), false /* isCacheable */);
955 #else
956     UNUSED_PARAM(includeSMILProperties);
957 #endif
958 }
959
960 inline void StyleResolver::initElement(Element* e)
961 {
962     if (m_element != e) {
963         m_element = e;
964         m_styledElement = m_element && m_element->isStyledElement() ? static_cast<StyledElement*>(m_element) : 0;
965         m_elementLinkState = m_checker.determineLinkState(m_element);
966         if (e && e == e->document()->documentElement()) {
967             e->document()->setDirectionSetOnDocumentElement(false);
968             e->document()->setWritingModeSetOnDocumentElement(false);
969         }
970     }
971 }
972
973 inline bool shouldResetStyleInheritance(NodeRenderingContext& context)
974 {
975     if (context.resetStyleInheritance())
976         return true;
977
978     if (InsertionPoint* insertionPoint = context.insertionPoint())
979         return insertionPoint->resetStyleInheritance();
980
981     return false;
982 }
983
984 inline void StyleResolver::initForStyleResolve(Element* e, RenderStyle* parentStyle, PseudoId pseudoID)
985 {
986     m_pseudoStyle = pseudoID;
987
988     if (e) {
989         NodeRenderingContext context(e);
990         m_parentNode = context.parentNodeForRenderingAndStyle();
991         m_parentStyle = shouldResetStyleInheritance(context) ? 0 :
992             parentStyle ? parentStyle :
993             m_parentNode ? m_parentNode->renderStyle() : 0;
994         m_distributedToInsertionPoint = context.insertionPoint();
995     } else {
996         m_parentNode = 0;
997         m_parentStyle = parentStyle;
998         m_distributedToInsertionPoint = false;
999     }
1000
1001     Node* docElement = e ? e->document()->documentElement() : 0;
1002     RenderStyle* docStyle = m_checker.document()->renderStyle();
1003     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
1004
1005     m_style = 0;
1006
1007     m_pendingImageProperties.clear();
1008
1009     m_ruleList = 0;
1010
1011     m_fontDirty = false;
1012 }
1013
1014 static const unsigned cStyleSearchThreshold = 10;
1015 static const unsigned cStyleSearchLevelThreshold = 10;
1016
1017 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
1018 {
1019     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
1020         return 0;
1021     if (!parent || !parent->isStyledElement())
1022         return 0;
1023     if (parent->hasScopedHTMLStyleChild())
1024         return 0;
1025     StyledElement* p = static_cast<StyledElement*>(parent);
1026     if (p->inlineStyle())
1027         return 0;
1028 #if ENABLE(SVG)
1029     if (p->isSVGElement() && static_cast<SVGElement*>(p)->animatedSMILStyleProperties())
1030         return 0;
1031 #endif
1032     if (p->hasID() && m_features.idsInRules.contains(p->idForStyleResolution().impl()))
1033         return 0;
1034
1035     RenderStyle* parentStyle = p->renderStyle();
1036     unsigned subcount = 0;
1037     Node* thisCousin = p;
1038     Node* currentNode = p->previousSibling();
1039
1040     // Reserve the tries for this level. This effectively makes sure that the algorithm
1041     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
1042     visitedNodeCount += cStyleSearchThreshold;
1043     while (thisCousin) {
1044         while (currentNode) {
1045             ++subcount;
1046             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()) {
1047                 // Adjust for unused reserved tries.
1048                 visitedNodeCount -= cStyleSearchThreshold - subcount;
1049                 return currentNode->lastChild();
1050             }
1051             if (subcount >= cStyleSearchThreshold)
1052                 return 0;
1053             currentNode = currentNode->previousSibling();
1054         }
1055         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
1056         thisCousin = currentNode;
1057     }
1058
1059     return 0;
1060 }
1061
1062 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
1063 {
1064     if (!ruleSet)
1065         return false;
1066     m_matchedRules.clear();
1067
1068     int firstRuleIndex = -1, lastRuleIndex = -1;
1069     m_checker.setMode(SelectorChecker::SharingRules);
1070     collectMatchingRules(ruleSet, firstRuleIndex, lastRuleIndex, false);
1071     m_checker.setMode(SelectorChecker::ResolvingStyle);
1072     if (m_matchedRules.isEmpty())
1073         return false;
1074     m_matchedRules.clear();
1075     return true;
1076 }
1077
1078 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
1079 {
1080     HTMLInputElement* thisInputElement = element->toInputElement();
1081     HTMLInputElement* otherInputElement = m_element->toInputElement();
1082
1083     if (!thisInputElement || !otherInputElement)
1084         return false;
1085
1086     if (thisInputElement->attributeData() != otherInputElement->attributeData()) {
1087         if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
1088             return false;
1089         if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
1090             return false;
1091     }
1092
1093     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
1094         return false;
1095     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
1096         return false;
1097     if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
1098         return false;
1099     if (thisInputElement->required() != otherInputElement->required())
1100         return false;
1101
1102     if (element->isEnabledFormControl() != m_element->isEnabledFormControl())
1103         return false;
1104
1105     if (element->isDefaultButtonForForm() != m_element->isDefaultButtonForForm())
1106         return false;
1107
1108     if (m_element->document()->containsValidityStyleRules()) {
1109         bool willValidate = element->willValidate();
1110
1111         if (willValidate != m_element->willValidate())
1112             return false;
1113
1114         if (willValidate && (element->isValidFormControlElement() != m_element->isValidFormControlElement()))
1115             return false;
1116
1117         if (element->isInRange() != m_element->isInRange())
1118             return false;
1119
1120         if (element->isOutOfRange() != m_element->isOutOfRange())
1121             return false;
1122     }
1123
1124     return true;
1125 }
1126
1127 // This function makes some assumptions that only make sense for attribute styles (we only compare CSSProperty::id() and CSSProperty::value().)
1128 static inline bool attributeStylesEqual(const StylePropertySet* a, const StylePropertySet* b)
1129 {
1130     if (a == b)
1131         return true;
1132     if (a->propertyCount() != b->propertyCount())
1133         return false;
1134     unsigned propertyCount = a->propertyCount();
1135     for (unsigned i = 0; i < propertyCount; ++i) {
1136         StylePropertySet::PropertyReference aProperty = a->propertyAt(i);
1137         unsigned j;
1138         for (j = 0; j < propertyCount; ++j) {
1139             StylePropertySet::PropertyReference bProperty = b->propertyAt(j);
1140             if (aProperty.id() != bProperty.id())
1141                 continue;
1142             // We could get a few more hits by comparing cssText() here, but that gets expensive quickly.
1143             if (aProperty.value() != bProperty.value())
1144                 return false;
1145             break;
1146         }
1147         if (j == propertyCount)
1148             return false;
1149     }
1150     return true;
1151 }
1152
1153 static inline bool elementHasDirectionAuto(Element* element)
1154 {
1155     // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
1156     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
1157 }
1158
1159 static inline bool haveIdenticalStyleAffectingAttributes(StyledElement* a, StyledElement* b)
1160 {
1161     if (a->attributeData() == b->attributeData())
1162         return true;
1163     if (a->fastGetAttribute(XMLNames::langAttr) != b->fastGetAttribute(XMLNames::langAttr))
1164         return false;
1165     if (a->fastGetAttribute(langAttr) != b->fastGetAttribute(langAttr))
1166         return false;
1167     // FIXME: This is probably not necessary.
1168     if (a->fastGetAttribute(cellpaddingAttr) != b->fastGetAttribute(cellpaddingAttr))
1169         return false;
1170     if (a->hasClass()) {
1171 #if ENABLE(SVG)
1172         // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
1173         if (a->isSVGElement()) {
1174             if (a->getAttribute(classAttr) != b->getAttribute(classAttr))
1175                 return false;
1176         } else
1177 #endif
1178         if (a->fastGetAttribute(classAttr) != b->fastGetAttribute(classAttr))
1179             return false;
1180     }
1181
1182     if (a->presentationAttributeStyle() && !attributeStylesEqual(a->presentationAttributeStyle(), b->presentationAttributeStyle()))
1183         return false;
1184
1185 #if ENABLE(PROGRESS_ELEMENT)
1186     if (a->hasTagName(progressTag)) {
1187         if (static_cast<HTMLProgressElement*>(a)->isDeterminate() != static_cast<HTMLProgressElement*>(b)->isDeterminate())
1188             return false;
1189     }
1190 #endif
1191
1192     return true;
1193 }
1194
1195 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
1196 {
1197     RenderStyle* style = element->renderStyle();
1198
1199     if (!style)
1200         return false;
1201     if (style->unique())
1202         return false;
1203     if (element->tagQName() != m_element->tagQName())
1204         return false;
1205     if (element->hasClass() != m_element->hasClass())
1206         return false;
1207     if (element->inlineStyle())
1208         return false;
1209     if (element->needsStyleRecalc())
1210         return false;
1211 #if ENABLE(SVG)
1212     if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
1213         return false;
1214 #endif
1215     if (!!element->presentationAttributeStyle() != !!m_styledElement->presentationAttributeStyle())
1216         return false;
1217     const StylePropertySet* additionalPresentationAttributeStyleA = element->additionalPresentationAttributeStyle();
1218     const StylePropertySet* additionalPresentationAttributeStyleB = m_styledElement->additionalPresentationAttributeStyle();
1219     if (!additionalPresentationAttributeStyleA != !additionalPresentationAttributeStyleB)
1220         return false;
1221     if (element->isLink() != m_element->isLink())
1222         return false;
1223     if (style->affectedByUncommonAttributeSelectors())
1224         return false;
1225     if (element->hovered() != m_element->hovered())
1226         return false;
1227     if (element->active() != m_element->active())
1228         return false;
1229     if (element->focused() != m_element->focused())
1230         return false;
1231     if (element->shadowPseudoId() != m_element->shadowPseudoId())
1232         return false;
1233     if (element == element->document()->cssTarget())
1234         return false;
1235
1236     if (!haveIdenticalStyleAffectingAttributes(element, m_styledElement))
1237         return false;
1238
1239     if (element->hasID() && m_features.idsInRules.contains(element->idForStyleResolution().impl()))
1240         return false;
1241     if (element->hasScopedHTMLStyleChild())
1242         return false;
1243
1244     // FIXME: We should share style for option and optgroup whenever possible.
1245     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
1246     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
1247     if (element->hasTagName(optionTag) || element->hasTagName(optgroupTag))
1248         return false;
1249
1250     bool isControl = element->isFormControlElement();
1251
1252     if (isControl != m_element->isFormControlElement())
1253         return false;
1254
1255     if (isControl && !canShareStyleWithControl(element))
1256         return false;
1257
1258     if (style->transitions() || style->animations())
1259         return false;
1260
1261 #if USE(ACCELERATED_COMPOSITING)
1262     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1263     // See comments in RenderObject::setStyle().
1264     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag)
1265 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1266         // With proxying, the media elements are backed by a RenderEmbeddedObject.
1267         || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1268 #endif
1269         )
1270         return false;
1271 #endif
1272
1273     if (elementHasDirectionAuto(element))
1274         return false;
1275
1276     if (additionalPresentationAttributeStyleA && !attributeStylesEqual(additionalPresentationAttributeStyleA, additionalPresentationAttributeStyleB))
1277         return false;
1278
1279     if (element->isLink() && m_elementLinkState != style->insideLink())
1280         return false;
1281
1282     return true;
1283 }
1284
1285 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
1286 {
1287     for (; node; node = node->previousSibling()) {
1288         if (!node->isStyledElement())
1289             continue;
1290         if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
1291             break;
1292         if (count++ == cStyleSearchThreshold)
1293             return 0;
1294     }
1295     return static_cast<StyledElement*>(node);
1296 }
1297
1298 static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
1299 {
1300     return parentStyle->childrenAffectedByPositionalRules()
1301         || parentStyle->childrenAffectedByFirstChildRules()
1302         || parentStyle->childrenAffectedByLastChildRules() 
1303         || parentStyle->childrenAffectedByDirectAdjacentRules();
1304 }
1305
1306 RenderStyle* StyleResolver::locateSharedStyle()
1307 {
1308     if (!m_styledElement || !m_parentStyle)
1309         return 0;
1310     // If the element has inline style it is probably unique.
1311     if (m_styledElement->inlineStyle())
1312         return 0;
1313 #if ENABLE(SVG)
1314     if (m_styledElement->isSVGElement() && static_cast<SVGElement*>(m_styledElement)->animatedSMILStyleProperties())
1315         return 0;
1316 #endif
1317     // Ids stop style sharing if they show up in the stylesheets.
1318     if (m_styledElement->hasID() && m_features.idsInRules.contains(m_styledElement->idForStyleResolution().impl()))
1319         return 0;
1320     if (parentStylePreventsSharing(m_parentStyle))
1321         return 0;
1322     if (m_styledElement->hasScopedHTMLStyleChild())
1323         return 0;
1324     if (m_element == m_element->document()->cssTarget())
1325         return 0;
1326     if (elementHasDirectionAuto(m_element))
1327         return 0;
1328
1329     // Check previous siblings and their cousins.
1330     unsigned count = 0;
1331     unsigned visitedNodeCount = 0;
1332     StyledElement* shareElement = 0;
1333     Node* cousinList = m_styledElement->previousSibling();
1334     while (cousinList) {
1335         shareElement = findSiblingForStyleSharing(cousinList, count);
1336         if (shareElement)
1337             break;
1338         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1339     }
1340
1341     // If we have exhausted all our budget or our cousins.
1342     if (!shareElement)
1343         return 0;
1344
1345     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1346     if (styleSharingCandidateMatchesRuleSet(m_siblingRuleSet.get()))
1347         return 0;
1348     // Can't share if attribute rules apply.
1349     if (styleSharingCandidateMatchesRuleSet(m_uncommonAttributeRuleSet.get()))
1350         return 0;
1351     // Can't share if @host @-rules apply.
1352     if (styleSharingCandidateMatchesHostRules())
1353         return 0;
1354     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1355     if (parentStylePreventsSharing(m_parentStyle))
1356         return 0;
1357     return shareElement->renderStyle();
1358 }
1359
1360 void StyleResolver::matchUARules(MatchResult& result)
1361 {
1362     MatchingUARulesScope scope;
1363
1364     // First we match rules from the user agent sheet.
1365     if (simpleDefaultStyleSheet)
1366         result.isCacheable = false;
1367     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1368         ? defaultPrintStyle : defaultStyle;
1369     matchUARules(result, userAgentStyleSheet);
1370
1371     // In quirks mode, we match rules from the quirks user agent sheet.
1372     if (!m_checker.strictParsing())
1373         matchUARules(result, defaultQuirksStyle);
1374
1375     // 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.
1376     if (m_checker.document()->isViewSource()) {
1377         if (!defaultViewSourceStyle)
1378             loadViewSourceStyle();
1379         matchUARules(result, defaultViewSourceStyle);
1380     }
1381 }
1382
1383 static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderStyle* style)
1384 {
1385     if (paginationMode == Pagination::Unpaginated)
1386         return;
1387         
1388     switch (paginationMode) {
1389     case Pagination::LeftToRightPaginated:
1390         style->setColumnAxis(HorizontalColumnAxis);
1391         if (style->isHorizontalWritingMode())
1392             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1393         else
1394             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1395         break;
1396     case Pagination::RightToLeftPaginated:
1397         style->setColumnAxis(HorizontalColumnAxis);
1398         if (style->isHorizontalWritingMode())
1399             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1400         else
1401             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1402         break;
1403     case Pagination::TopToBottomPaginated:
1404         style->setColumnAxis(VerticalColumnAxis);
1405         if (style->isHorizontalWritingMode())
1406             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1407         else
1408             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1409         break;
1410     case Pagination::BottomToTopPaginated:
1411         style->setColumnAxis(VerticalColumnAxis);
1412         if (style->isHorizontalWritingMode())
1413             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1414         else
1415             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1416         break;
1417     case Pagination::Unpaginated:
1418         ASSERT_NOT_REACHED();
1419         break;
1420     }
1421 }
1422
1423 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document* document, CSSFontSelector* fontSelector)
1424 {
1425     Frame* frame = document->frame();
1426
1427     // HTML5 states that seamless iframes should replace default CSS values
1428     // with values inherited from the containing iframe element. However,
1429     // some values (such as the case of designMode = "on") still need to
1430     // be set by this "document style".
1431     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1432     bool seamlessWithParent = document->shouldDisplaySeamlesslyWithParent();
1433     if (seamlessWithParent) {
1434         RenderStyle* iframeStyle = document->seamlessParentIFrame()->renderStyle();
1435         if (iframeStyle)
1436             documentStyle->inheritFrom(iframeStyle);
1437     }
1438
1439     // FIXME: It's not clear which values below we want to override in the seamless case!
1440     documentStyle->setDisplay(BLOCK);
1441     if (!seamlessWithParent) {
1442         documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1443         documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomFactor() : 1);
1444         documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1445         documentStyle->setLocale(document->contentLanguage());
1446     }
1447     // FIXME: This overrides any -webkit-user-modify inherited from the parent iframe.
1448     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1449
1450     Element* docElement = document->documentElement();
1451     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1452     if (docElementRenderer) {
1453         // Use the direction and writing-mode of the body to set the
1454         // viewport's direction and writing-mode unless the property is set on the document element.
1455         // If there is no body, then use the document element.
1456         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1457         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1458             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1459         else
1460             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1461         if (bodyRenderer && !document->directionSetOnDocumentElement())
1462             documentStyle->setDirection(bodyRenderer->style()->direction());
1463         else
1464             documentStyle->setDirection(docElementRenderer->style()->direction());
1465     }
1466
1467     if (frame) {
1468         if (FrameView* frameView = frame->view()) {
1469             const Pagination& pagination = frameView->pagination();
1470             if (pagination.mode != Pagination::Unpaginated) {
1471                 setStylesForPaginationMode(pagination.mode, documentStyle.get());
1472                 documentStyle->setColumnGap(pagination.gap);
1473                 if (RenderView* view = document->renderView()) {
1474                     if (view->hasColumns())
1475                         view->updateColumnInfoFromStyle(documentStyle.get());
1476                 }
1477             }
1478         }
1479     }
1480
1481     // Seamless iframes want to inherit their font from their parent iframe, so early return before setting the font.
1482     if (seamlessWithParent)
1483         return documentStyle.release();
1484
1485     FontDescription fontDescription;
1486     fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
1487     if (Settings* settings = document->settings()) {
1488         fontDescription.setUsePrinterFont(document->printing() || !settings->screenFontSubstitutionEnabled());
1489         fontDescription.setRenderingMode(settings->fontRenderingMode());
1490         const AtomicString& standardFont = settings->standardFontFamily(fontDescription.script());
1491         if (!standardFont.isEmpty()) {
1492             fontDescription.setGenericFamily(FontDescription::StandardFamily);
1493             fontDescription.firstFamily().setFamily(standardFont);
1494             fontDescription.firstFamily().appendFamily(0);
1495         }
1496         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1497         int size = StyleResolver::fontSizeForKeyword(document, CSSValueMedium, false);
1498         fontDescription.setSpecifiedSize(size);
1499         bool useSVGZoomRules = document->isSVGDocument();
1500         fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1501     } else
1502         fontDescription.setUsePrinterFont(document->printing());
1503
1504     documentStyle->setFontDescription(fontDescription);
1505     documentStyle->font().update(fontSelector);
1506
1507     return documentStyle.release();
1508 }
1509
1510 static inline bool isAtShadowBoundary(const Element* element)
1511 {
1512     if (!element)
1513         return false;
1514     ContainerNode* parentNode = element->parentNode();
1515     return parentNode && parentNode->isShadowRoot();
1516 }
1517
1518 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
1519     StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
1520 {
1521     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1522     // will vanish if a style recalc happens during loading.
1523     if (sharingBehavior == AllowStyleSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1524         if (!s_styleNotYetAvailable) {
1525             s_styleNotYetAvailable = RenderStyle::create().leakRef();
1526             s_styleNotYetAvailable->setDisplay(NONE);
1527             s_styleNotYetAvailable->font().update(m_fontSelector);
1528         }
1529         element->document()->setHasNodesWithPlaceholderStyle();
1530         return s_styleNotYetAvailable;
1531     }
1532
1533     initElement(element);
1534     initForStyleResolve(element, defaultParent);
1535     m_regionForStyling = regionForStyling;
1536     if (sharingBehavior == AllowStyleSharing && !m_distributedToInsertionPoint) {
1537         RenderStyle* sharedStyle = locateSharedStyle();
1538         if (sharedStyle)
1539             return sharedStyle;
1540     }
1541
1542     m_style = RenderStyle::create();
1543
1544     RefPtr<RenderStyle> cloneForParent;
1545
1546     if (m_parentStyle)
1547         m_style->inheritFrom(m_parentStyle, isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
1548     else {
1549         // Make sure our fonts are initialized if we don't inherit them from our parent style.
1550         if (Settings* settings = documentSettings()) {
1551             initializeFontStyle(settings);
1552             m_style->font().update(fontSelector());
1553         } else
1554             m_style->font().update(0);
1555         cloneForParent = RenderStyle::clone(style());
1556         m_parentStyle = cloneForParent.get();
1557     }
1558     // contenteditable attribute (implemented by -webkit-user-modify) should
1559     // be propagated from shadow host to distributed node.
1560     if (m_distributedToInsertionPoint) {
1561         if (Element* parent = element->parentElement()) {
1562             if (RenderStyle* styleOfShadowHost = parent->renderStyle())
1563                 m_style->setUserModify(styleOfShadowHost->userModify());
1564         }
1565     }
1566
1567     if (element->isLink()) {
1568         m_style->setIsLink(true);
1569         m_style->setInsideLink(m_elementLinkState);
1570     }
1571
1572     ensureDefaultStyleSheetsForElement(element);
1573
1574     MatchResult matchResult;
1575     if (matchingBehavior == MatchOnlyUserAgentRules)
1576         matchUARules(matchResult);
1577     else
1578         matchAllRules(matchResult, matchingBehavior != MatchAllRulesExcludingSMIL);
1579
1580     applyMatchedProperties(matchResult, element);
1581
1582     // Clean up our style object's display and text decorations (among other fixups).
1583     adjustRenderStyle(style(), m_parentStyle, element);
1584
1585     initElement(0); // Clear out for the next resolve.
1586
1587     if (cloneForParent)
1588         m_parentStyle = 0;
1589
1590     // Now return the style.
1591     return m_style.release();
1592 }
1593
1594 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
1595 {
1596     MatchResult result;
1597     if (keyframe->properties())
1598         addMatchedProperties(result, keyframe->properties());
1599
1600     ASSERT(!m_style);
1601
1602     // Create the style
1603     m_style = RenderStyle::clone(elementStyle);
1604
1605     m_lineHeightValue = 0;
1606
1607     // We don't need to bother with !important. Since there is only ever one
1608     // decl, there's nothing to override. So just add the first properties.
1609     bool inheritedOnly = false;
1610     if (keyframe->properties())
1611         applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1612
1613     // If our font got dirtied, go ahead and update it now.
1614     updateFont();
1615
1616     // Line-height is set when we are sure we decided on the font-size
1617     if (m_lineHeightValue)
1618         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1619
1620     // Now do rest of the properties.
1621     if (keyframe->properties())
1622         applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1623
1624     // If our font got dirtied by one of the non-essential font props,
1625     // go ahead and update it a second time.
1626     updateFont();
1627
1628     // Start loading resources referenced by this style.
1629     loadPendingResources();
1630     
1631     // Add all the animating properties to the keyframe.
1632     if (const StylePropertySet* styleDeclaration = keyframe->properties()) {
1633         unsigned propertyCount = styleDeclaration->propertyCount();
1634         for (unsigned i = 0; i < propertyCount; ++i) {
1635             CSSPropertyID property = styleDeclaration->propertyAt(i).id();
1636             // Timing-function within keyframes is special, because it is not animated; it just
1637             // describes the timing function between this keyframe and the next.
1638             if (property != CSSPropertyWebkitAnimationTimingFunction)
1639                 keyframeValue.addProperty(property);
1640         }
1641     }
1642
1643     return m_style.release();
1644 }
1645
1646 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1647 {
1648     list.clear();
1649
1650     // Get the keyframesRule for this name
1651     if (!e || list.animationName().isEmpty())
1652         return;
1653
1654     m_keyframesRuleMap.checkConsistency();
1655
1656     KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
1657     if (it == m_keyframesRuleMap.end())
1658         return;
1659
1660     const StyleRuleKeyframes* keyframesRule = it->value.get();
1661
1662     // Construct and populate the style for each keyframe
1663     const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
1664     for (unsigned i = 0; i < keyframes.size(); ++i) {
1665         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1666         initElement(e);
1667         initForStyleResolve(e);
1668
1669         const StyleKeyframe* keyframe = keyframes[i].get();
1670
1671         KeyframeValue keyframeValue(0, 0);
1672         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
1673
1674         // Add this keyframe style to all the indicated key times
1675         Vector<float> keys;
1676         keyframe->getKeys(keys);
1677         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1678             keyframeValue.setKey(keys[keyIndex]);
1679             list.insert(keyframeValue);
1680         }
1681     }
1682
1683     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1684     int initialListSize = list.size();
1685     if (initialListSize > 0 && list[0].key()) {
1686         static StyleKeyframe* zeroPercentKeyframe;
1687         if (!zeroPercentKeyframe) {
1688             zeroPercentKeyframe = StyleKeyframe::create().leakRef();
1689             zeroPercentKeyframe->setKeyText("0%");
1690         }
1691         KeyframeValue keyframeValue(0, 0);
1692         keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
1693         list.insert(keyframeValue);
1694     }
1695
1696     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1697     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1698         static StyleKeyframe* hundredPercentKeyframe;
1699         if (!hundredPercentKeyframe) {
1700             hundredPercentKeyframe = StyleKeyframe::create().leakRef();
1701             hundredPercentKeyframe->setKeyText("100%");
1702         }
1703         KeyframeValue keyframeValue(1, 0);
1704         keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
1705         list.insert(keyframeValue);
1706     }
1707 }
1708
1709 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(PseudoId pseudo, Element* e, RenderStyle* parentStyle)
1710 {
1711     ASSERT(m_parentStyle);
1712     if (!e)
1713         return 0;
1714
1715     initElement(e);
1716
1717     initForStyleResolve(e, parentStyle, pseudo);
1718     m_style = RenderStyle::create();
1719     m_style->inheritFrom(m_parentStyle);
1720
1721     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1722     // those rules.
1723
1724     // Check UA, user and author rules.
1725     MatchResult matchResult;
1726     matchUARules(matchResult);
1727
1728     if (m_matchAuthorAndUserStyles) {
1729         matchUserRules(matchResult, false);
1730         matchAuthorRules(matchResult, false);
1731     }
1732
1733     if (matchResult.matchedProperties.isEmpty())
1734         return 0;
1735
1736     m_style->setStyleType(pseudo);
1737
1738     applyMatchedProperties(matchResult, e);
1739
1740     // Clean up our style object's display and text decorations (among other fixups).
1741     adjustRenderStyle(style(), parentStyle, 0);
1742
1743     // Start loading resources referenced by this style.
1744     loadPendingResources();
1745
1746     // Now return the style.
1747     return m_style.release();
1748 }
1749
1750 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
1751 {
1752     initForStyleResolve(m_checker.document()->documentElement()); // m_rootElementStyle will be set to the document style.
1753
1754     m_style = RenderStyle::create();
1755     m_style->inheritFrom(m_rootElementStyle);
1756
1757     const bool isLeft = isLeftPage(pageIndex);
1758     const bool isFirst = isFirstPage(pageIndex);
1759     const String page = pageName(pageIndex);
1760     
1761     MatchResult result;
1762     matchPageRules(result, defaultPrintStyle, isLeft, isFirst, page);
1763     matchPageRules(result, m_userStyle.get(), isLeft, isFirst, page);
1764     // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
1765     matchPageRules(result, m_authorStyle.get(), isLeft, isFirst, page);
1766     m_lineHeightValue = 0;
1767     bool inheritedOnly = false;
1768 #if ENABLE(CSS_VARIABLES)
1769     applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1770 #endif
1771     applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1772
1773     // If our font got dirtied, go ahead and update it now.
1774     updateFont();
1775
1776     // Line-height is set when we are sure we decided on the font-size.
1777     if (m_lineHeightValue)
1778         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
1779
1780     applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1781
1782     // Start loading resources referenced by this style.
1783     loadPendingResources();
1784
1785     // Now return the style.
1786     return m_style.release();
1787 }
1788
1789 static void addIntrinsicMargins(RenderStyle* style)
1790 {
1791     // Intrinsic margin value.
1792     const int intrinsicMargin = 2 * style->effectiveZoom();
1793
1794     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1795     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1796     if (style->width().isIntrinsicOrAuto()) {
1797         if (style->marginLeft().quirk())
1798             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1799         if (style->marginRight().quirk())
1800             style->setMarginRight(Length(intrinsicMargin, Fixed));
1801     }
1802
1803     if (style->height().isAuto()) {
1804         if (style->marginTop().quirk())
1805             style->setMarginTop(Length(intrinsicMargin, Fixed));
1806         if (style->marginBottom().quirk())
1807             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1808     }
1809 }
1810
1811 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
1812 {
1813     switch (display) {
1814     case BLOCK:
1815     case TABLE:
1816     case BOX:
1817     case FLEX:
1818     case GRID:
1819         return display;
1820
1821     case LIST_ITEM:
1822         // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
1823         if (!strictParsing && isFloating)
1824             return BLOCK;
1825         return display;
1826     case INLINE_TABLE:
1827         return TABLE;
1828     case INLINE_BOX:
1829         return BOX;
1830     case INLINE_FLEX:
1831         return FLEX;
1832     case INLINE_GRID:
1833         return GRID;
1834
1835     case INLINE:
1836     case RUN_IN:
1837     case COMPACT:
1838     case INLINE_BLOCK:
1839     case TABLE_ROW_GROUP:
1840     case TABLE_HEADER_GROUP:
1841     case TABLE_FOOTER_GROUP:
1842     case TABLE_ROW:
1843     case TABLE_COLUMN_GROUP:
1844     case TABLE_COLUMN:
1845     case TABLE_CELL:
1846     case TABLE_CAPTION:
1847         return BLOCK;
1848     case NONE:
1849         ASSERT_NOT_REACHED();
1850         return NONE;
1851     }
1852     ASSERT_NOT_REACHED();
1853     return BLOCK;
1854 }
1855
1856 // CSS requires text-decoration to be reset at each DOM element for tables, 
1857 // inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
1858 // and absolute or relatively positioned elements.
1859 static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e)
1860 {
1861     return style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1862         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
1863         || style->isFloating() || style->hasOutOfFlowPosition();
1864 }
1865
1866 static bool isDisplayFlexibleBox(EDisplay display)
1867 {
1868     return display == FLEX || display == INLINE_FLEX;
1869 }
1870
1871 void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1872 {
1873     ASSERT(parentStyle);
1874
1875     // Cache our original display.
1876     style->setOriginalDisplay(style->display());
1877
1878     if (style->display() != NONE) {
1879         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1880         // property.
1881         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1882         // these tags to retain their display types.
1883         if (!m_checker.strictParsing() && e) {
1884             if (e->hasTagName(tdTag)) {
1885                 style->setDisplay(TABLE_CELL);
1886                 style->setFloating(NoFloat);
1887             } else if (e->hasTagName(tableTag))
1888                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1889         }
1890
1891         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1892             if (style->whiteSpace() == KHTML_NOWRAP) {
1893                 // Figure out if we are really nowrapping or if we should just
1894                 // use normal instead. If the width of the cell is fixed, then
1895                 // we don't actually use NOWRAP.
1896                 if (style->width().isFixed())
1897                     style->setWhiteSpace(NORMAL);
1898                 else
1899                     style->setWhiteSpace(NOWRAP);
1900             }
1901         }
1902
1903         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1904         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1905             style->setTextAlign(TASTART);
1906
1907         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1908         // fix a crash where a site tries to position these objects. They also never honor display.
1909         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1910             style->setPosition(StaticPosition);
1911             style->setDisplay(BLOCK);
1912         }
1913
1914         // Ruby text does not support float or position. This might change with evolution of the specification.
1915         if (e && e->hasTagName(rtTag)) {
1916             style->setPosition(StaticPosition);
1917             style->setFloating(NoFloat);
1918         }
1919
1920         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1921         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1922         if (e && e->hasTagName(thTag) && style->textAlign() == TASTART)
1923             style->setTextAlign(CENTER);
1924
1925         if (e && e->hasTagName(legendTag))
1926             style->setDisplay(BLOCK);
1927
1928         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1929         if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document()->documentElement() == e))
1930             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), m_checker.strictParsing()));
1931
1932         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1933         // clear how that should work.
1934         if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
1935             style->setDisplay(INLINE_BLOCK);
1936
1937         // After performing the display mutation, check table rows. We do not honor position:relative on
1938         // table rows or cells. This has been established in CSS2.1 (and caused a crash in containingBlock()
1939         // on some sites).
1940         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1941              || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
1942              && style->position() == RelativePosition)
1943             style->setPosition(StaticPosition);
1944
1945         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1946         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1947         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1948             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1949             || style->display() == TABLE_CELL)
1950             style->setWritingMode(parentStyle->writingMode());
1951
1952         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1953         // of block-flow to anything other than TopToBottomWritingMode.
1954         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1955         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1956             style->setWritingMode(TopToBottomWritingMode);
1957
1958         if (isDisplayFlexibleBox(parentStyle->display())) {
1959             style->setFloating(NoFloat);
1960             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), m_checker.strictParsing()));
1961         }
1962     }
1963
1964     // Make sure our z-index value is only applied if the object is positioned.
1965     if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle->display()))
1966         style->setHasAutoZIndex();
1967
1968     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1969     // cases where objects that should be blended as a single unit end up with a non-transparent
1970     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1971     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e)
1972         || style->opacity() < 1.0f
1973         || style->hasTransformRelatedProperty()
1974         || style->hasMask()
1975         || style->clipPath()
1976         || style->boxReflect()
1977         || style->hasFilter()
1978         || style->hasBlendMode()
1979         || style->position() == StickyPosition
1980         || (style->position() == FixedPosition && e && e->document()->page() && e->document()->page()->settings()->fixedPositionCreatesStackingContext())
1981 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1982         // Touch overflow scrolling creates a stacking context.
1983         || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
1984 #endif
1985         ))
1986         style->setZIndex(0);
1987
1988     // Textarea considers overflow visible as auto.
1989     if (e && e->hasTagName(textareaTag)) {
1990         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1991         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1992     }
1993
1994     if (doesNotInheritTextDecoration(style, e))
1995         style->setTextDecorationsInEffect(style->textDecoration());
1996     else
1997         style->addToTextDecorationsInEffect(style->textDecoration());
1998
1999     // If either overflow value is not visible, change to auto.
2000     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
2001         style->setOverflowY(OMARQUEE);
2002     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
2003         style->setOverflowX(OMARQUEE);
2004     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
2005         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
2006         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
2007         // default to auto so we can at least scroll through the pages.
2008         style->setOverflowX(OAUTO);
2009     } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
2010         style->setOverflowY(OAUTO);
2011
2012     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
2013     // styles are specified on a root element, then they will be incorporated in
2014     // StyleResolver::styleForDocument().
2015     if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e->hasTagName(htmlTag) || e->hasTagName(bodyTag)))
2016         setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style), style);
2017
2018     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
2019     // FIXME: Eventually table sections will support auto and scroll.
2020     if (style->display() == TABLE || style->display() == INLINE_TABLE
2021         || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
2022         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
2023             style->setOverflowX(OVISIBLE);
2024         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
2025             style->setOverflowY(OVISIBLE);
2026     }
2027
2028     // Menulists should have visible overflow
2029     if (style->appearance() == MenulistPart) {
2030         style->setOverflowX(OVISIBLE);
2031         style->setOverflowY(OVISIBLE);
2032     }
2033
2034     // Cull out any useless layers and also repeat patterns into additional layers.
2035     style->adjustBackgroundLayers();
2036     style->adjustMaskLayers();
2037
2038     // Do the same for animations and transitions.
2039     style->adjustAnimations();
2040     style->adjustTransitions();
2041
2042     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
2043     // alter fonts and heights/widths.
2044     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
2045         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
2046         // so we have to treat all image buttons as though they were explicitly sized.
2047         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
2048             addIntrinsicMargins(style);
2049     }
2050
2051     // Let the theme also have a crack at adjusting the style.
2052     if (style->hasAppearance())
2053         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_hasUAAppearance, m_borderData, m_backgroundData, m_backgroundColor);
2054
2055     // If we have first-letter pseudo style, do not share this style.
2056     if (style->hasPseudoStyle(FIRST_LETTER))
2057         style->setUnique();
2058
2059     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
2060     if (style->preserves3D() && (style->overflowX() != OVISIBLE
2061         || style->overflowY() != OVISIBLE
2062         || style->hasFilter()))
2063         style->setTransformStyle3D(TransformStyle3DFlat);
2064
2065     // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
2066     if (e && e->hasTagName(iframeTag) && style->display() == INLINE && static_cast<HTMLIFrameElement*>(e)->shouldDisplaySeamlessly())
2067         style->setDisplay(INLINE_BLOCK);
2068
2069 #if ENABLE(SVG)
2070     if (e && e->isSVGElement()) {
2071         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
2072         if (style->overflowY() == OSCROLL)
2073             style->setOverflowY(OHIDDEN);
2074         else if (style->overflowY() == OAUTO)
2075             style->setOverflowY(OVISIBLE);
2076
2077         if (style->overflowX() == OSCROLL)
2078             style->setOverflowX(OHIDDEN);
2079         else if (style->overflowX() == OAUTO)
2080             style->setOverflowX(OVISIBLE);
2081
2082         // Only the root <svg> element in an SVG document fragment tree honors css position
2083         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
2084             style->setPosition(RenderStyle::initialPosition());
2085
2086         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
2087         // not be scaled again.
2088         if (e->hasTagName(SVGNames::foreignObjectTag))
2089             style->setEffectiveZoom(RenderStyle::initialZoom());
2090     }
2091 #endif
2092 }
2093
2094 bool StyleResolver::checkRegionStyle(Element* regionElement)
2095 {
2096     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
2097     // so all region rules are global by default. Verify whether that can stand or needs changing.
2098
2099     unsigned rulesSize = m_authorStyle->m_regionSelectorsAndRuleSets.size();
2100     for (unsigned i = 0; i < rulesSize; ++i) {
2101         ASSERT(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2102         if (checkRegionSelector(m_authorStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2103             return true;
2104     }
2105
2106     if (m_userStyle) {
2107         rulesSize = m_userStyle->m_regionSelectorsAndRuleSets.size();
2108         for (unsigned i = 0; i < rulesSize; ++i) {
2109             ASSERT(m_userStyle->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2110             if (checkRegionSelector(m_userStyle->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2111                 return true;
2112         }
2113     }
2114
2115     return false;
2116 }
2117
2118 void StyleResolver::updateFont()
2119 {
2120     if (!m_fontDirty)
2121         return;
2122
2123     checkForTextSizeAdjust();
2124     checkForGenericFamilyChange(style(), m_parentStyle);
2125     checkForZoomChange(style(), m_parentStyle);
2126     m_style->font().update(m_fontSelector);
2127     m_fontDirty = false;
2128 }
2129
2130 void StyleResolver::cacheBorderAndBackground()
2131 {
2132     m_hasUAAppearance = m_style->hasAppearance();
2133     if (m_hasUAAppearance) {
2134         m_borderData = m_style->border();
2135         m_backgroundData = *m_style->backgroundLayers();
2136         m_backgroundColor = m_style->backgroundColor();
2137     }
2138 }
2139
2140 PassRefPtr<CSSRuleList> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
2141 {
2142     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
2143 }
2144
2145 PassRefPtr<CSSRuleList> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
2146 {
2147     if (!e || !e->document()->haveStylesheetsLoaded())
2148         return 0;
2149
2150     m_checker.setMode(SelectorChecker::CollectingRules);
2151
2152     initElement(e);
2153     initForStyleResolve(e, 0, pseudoId);
2154
2155     MatchResult dummy;
2156     if (rulesToInclude & UAAndUserCSSRules) {
2157         // First we match rules from the user agent sheet.
2158         matchUARules(dummy);
2159
2160         // Now we check user sheet rules.
2161         if (m_matchAuthorAndUserStyles)
2162             matchUserRules(dummy, rulesToInclude & EmptyCSSRules);
2163     }
2164
2165     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
2166         m_sameOriginOnly = !(rulesToInclude & CrossOriginCSSRules);
2167
2168         // Check the rules in author sheets.
2169         matchAuthorRules(dummy, rulesToInclude & EmptyCSSRules);
2170
2171         m_sameOriginOnly = false;
2172     }
2173
2174     m_checker.setMode(SelectorChecker::ResolvingStyle);
2175
2176     return m_ruleList.release();
2177 }
2178
2179 inline bool StyleResolver::checkSelector(const RuleData& ruleData, const ContainerNode* scope)
2180 {
2181     m_dynamicPseudo = NOPSEUDO;
2182
2183     if (ruleData.hasFastCheckableSelector()) {
2184         // We know this selector does not include any pseudo elements.
2185         if (m_pseudoStyle != NOPSEUDO)
2186             return false;
2187         // We know a sufficiently simple single part selector matches simply because we found it from the rule hash.
2188         // This is limited to HTML only so we don't need to check the namespace.
2189         if (ruleData.hasRightmostSelectorMatchingHTMLBasedOnRuleHash() && m_element->isHTMLElement()) {
2190             if (!ruleData.hasMultipartSelector())
2191                 return true;
2192         } else if (!SelectorChecker::tagMatches(m_element, ruleData.selector()))
2193             return false;
2194         if (!SelectorChecker::fastCheckRightmostAttributeSelector(m_element, ruleData.selector()))
2195             return false;
2196         return m_checker.fastCheckSelector(ruleData.selector(), m_element);
2197     }
2198
2199     // Slow path.
2200     SelectorChecker::SelectorCheckingContext context(ruleData.selector(), m_element, SelectorChecker::VisitedMatchEnabled);
2201     context.elementStyle = style();
2202     context.elementParentStyle = m_parentNode ? m_parentNode->renderStyle() : 0;
2203     context.scope = scope;
2204     context.pseudoStyle = m_pseudoStyle;
2205     SelectorChecker::SelectorMatch match = m_checker.checkSelector(context, m_dynamicPseudo);
2206     if (match != SelectorChecker::SelectorMatches)
2207         return false;
2208     if (m_pseudoStyle != NOPSEUDO && m_pseudoStyle != m_dynamicPseudo)
2209         return false;
2210     return true;
2211 }
2212
2213 bool StyleResolver::checkRegionSelector(CSSSelector* regionSelector, Element* regionElement)
2214 {
2215     if (!regionSelector || !regionElement)
2216         return false;
2217
2218     m_pseudoStyle = NOPSEUDO;
2219
2220     for (CSSSelector* s = regionSelector; s; s = CSSSelectorList::next(s))
2221         if (m_checker.checkSelector(s, regionElement))
2222             return true;
2223
2224     return false;
2225 }
2226
2227 // -------------------------------------------------------------------------------------
2228 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
2229
2230 Length StyleResolver::convertToIntLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2231 {
2232     return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2233 }
2234
2235 Length StyleResolver::convertToFloatLength(CSSPrimitiveValue* primitiveValue, RenderStyle* style, RenderStyle* rootStyle, double multiplier)
2236 {
2237     return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
2238 }
2239
2240 template <StyleResolver::StyleApplicationPass pass>
2241 void StyleResolver::applyProperties(const StylePropertySet* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, bool filterRegionProperties)
2242 {
2243     ASSERT(!filterRegionProperties || m_regionForStyling);
2244     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(document(), rule);
2245
2246     unsigned propertyCount = properties->propertyCount();
2247     for (unsigned i = 0; i < propertyCount; ++i) {
2248         StylePropertySet::PropertyReference current = properties->propertyAt(i);
2249         if (isImportant != current.isImportant())
2250             continue;
2251         if (inheritedOnly && !current.isInherited()) {
2252             // If the property value is explicitly inherited, we need to apply further non-inherited properties
2253             // as they might override the value inherited here. For this reason we don't allow declarations with
2254             // explicitly inherited properties to be cached.
2255             ASSERT(!current.value()->isInheritedValue());
2256             continue;
2257         }
2258         CSSPropertyID property = current.id();
2259
2260         if (filterRegionProperties && !StyleResolver::isValidRegionStyleProperty(property))
2261             continue;
2262
2263         switch (pass) {
2264 #if ENABLE(CSS_VARIABLES)
2265         case VariableDefinitions:
2266             COMPILE_ASSERT(CSSPropertyVariable < firstCSSProperty, CSS_variable_is_before_first_property);
2267             if (property == CSSPropertyVariable)
2268                 applyProperty(current.id(), current.value());
2269             break;
2270 #endif
2271         case HighPriorityProperties:
2272             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
2273             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range);
2274             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
2275 #if ENABLE(CSS_VARIABLES)
2276             if (property == CSSPropertyVariable)
2277                 continue;
2278 #endif
2279             // give special priority to font-xxx, color properties, etc
2280             if (property < CSSPropertyLineHeight)
2281                 applyProperty(current.id(), current.value());
2282             // we apply line-height later
2283             else if (property == CSSPropertyLineHeight)
2284                 m_lineHeightValue = current.value();
2285             break;
2286         case LowPriorityProperties:
2287             if (property > CSSPropertyLineHeight)
2288                 applyProperty(current.id(), current.value());
2289         }
2290     }
2291     InspectorInstrumentation::didProcessRule(cookie);
2292 }
2293
2294 template <StyleResolver::StyleApplicationPass pass>
2295 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
2296 {
2297     if (startIndex == -1)
2298         return;
2299
2300     if (m_style->insideLink() != NotInsideLink) {
2301         for (int i = startIndex; i <= endIndex; ++i) {
2302             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2303             unsigned linkMatchType = matchedProperties.linkMatchType;
2304             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
2305             m_applyPropertyToRegularStyle = linkMatchType & SelectorChecker::MatchLink;
2306             m_applyPropertyToVisitedLinkStyle = linkMatchType & SelectorChecker::MatchVisited;
2307
2308             applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2309         }
2310         m_applyPropertyToRegularStyle = true;
2311         m_applyPropertyToVisitedLinkStyle = false;
2312         return;
2313     }
2314     for (int i = startIndex; i <= endIndex; ++i) {
2315         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
2316         applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, matchedProperties.isInRegionRule);
2317     }
2318 }
2319
2320 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
2321 {
2322     
2323     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
2324 }
2325
2326 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
2327 {
2328     return a.firstUARule == b.firstUARule
2329         && a.lastUARule == b.lastUARule
2330         && a.firstAuthorRule == b.firstAuthorRule
2331         && a.lastAuthorRule == b.lastAuthorRule
2332         && a.firstUserRule == b.firstUserRule
2333         && a.lastUserRule == b.lastUserRule;
2334 }
2335
2336 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
2337 {
2338     return !(a == b);
2339 }
2340
2341 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
2342 {
2343     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
2344 }
2345
2346 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
2347 {
2348     return !(a == b);
2349 }
2350
2351 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
2352 {
2353     ASSERT(hash);
2354
2355     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
2356     if (it == m_matchedPropertiesCache.end())
2357         return 0;
2358     MatchedPropertiesCacheItem& cacheItem = it->value;
2359
2360     size_t size = matchResult.matchedProperties.size();
2361     if (size != cacheItem.matchedProperties.size())
2362         return 0;
2363     for (size_t i = 0; i < size; ++i) {
2364         if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
2365             return 0;
2366     }
2367     if (cacheItem.ranges != matchResult.ranges)
2368         return 0;
2369     return &cacheItem;
2370 }
2371
2372 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
2373 {
2374     static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
2375     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps) {
2376         static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
2377         m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
2378     }
2379
2380     ASSERT(hash);
2381     MatchedPropertiesCacheItem cacheItem;
2382     cacheItem.matchedProperties.append(matchResult.matchedProperties);
2383     cacheItem.ranges = matchResult.ranges;
2384     // Note that we don't cache the original RenderStyle instance. It may be further modified.
2385     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
2386     cacheItem.renderStyle = RenderStyle::clone(style);
2387     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
2388     m_matchedPropertiesCache.add(hash, cacheItem);
2389 }
2390
2391 void StyleResolver::invalidateMatchedPropertiesCache()
2392 {
2393     m_matchedPropertiesCache.clear();
2394 }
2395
2396 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
2397 {
2398     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
2399     if (element == element->document()->documentElement() && element->document()->writingModeSetOnDocumentElement())
2400         return false;
2401     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
2402         return false;
2403     if (style->hasAppearance())
2404         return false;
2405     if (style->zoom() != RenderStyle::initialZoom())
2406         return false;
2407     // The cache assumes static knowledge about which properties are inherited.
2408     if (parentStyle->hasExplicitlyInheritedProperties())
2409         return false;
2410     return true;
2411 }
2412
2413 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element)
2414 {
2415     ASSERT(element);
2416     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
2417     bool applyInheritedOnly = false;
2418     const MatchedPropertiesCacheItem* cacheItem = 0;
2419     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
2420         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
2421         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
2422         // element context. This is fast and saves memory by reusing the style data structures.
2423         m_style->copyNonInheritedFrom(cacheItem->renderStyle.get());
2424         if (m_parentStyle->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
2425             EInsideLink linkStatus = m_style->insideLink();
2426             // If the cache item parent style has identical inherited properties to the current parent style then the
2427             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
2428             m_style->inheritFrom(cacheItem->renderStyle.get());
2429
2430             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
2431             m_style->setInsideLink(linkStatus);
2432             return;
2433         }
2434         applyInheritedOnly = true; 
2435     }
2436
2437 #if ENABLE(CSS_VARIABLES)
2438     // First apply all variable definitions, as they may be used during application of later properties.
2439     applyMatchedProperties<VariableDefinitions>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
2440     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
2441     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
2442     applyMatchedProperties<VariableDefinitions>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2443 #endif
2444
2445     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
2446     // high-priority properties first, i.e., those properties that other properties depend on.
2447     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
2448     // and (4) normal important.
2449     m_lineHeightValue = 0;
2450     applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
2451     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
2452     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
2453     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2454
2455     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != m_style->effectiveZoom()) {
2456         m_fontDirty = true;
2457         applyInheritedOnly = false;
2458     }
2459
2460     // If our font got dirtied, go ahead and update it now.
2461     updateFont();
2462
2463     // Line-height is set when we are sure we decided on the font-size.
2464     if (m_lineHeightValue)
2465         applyProperty(CSSPropertyLineHeight, m_lineHeightValue);
2466
2467     // Many properties depend on the font. If it changes we just apply all properties.
2468     if (cacheItem && cacheItem->renderStyle->fontDescription() != m_style->fontDescription())
2469         applyInheritedOnly = false;
2470
2471     // Now do the normal priority UA properties.
2472     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2473     
2474     // Cache our border and background so that we can examine them later.
2475     cacheBorderAndBackground();
2476     
2477     // Now do the author and user normal priority properties and all the !important properties.
2478     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
2479     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
2480     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
2481     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
2482    
2483     // Start loading resources referenced by this style.
2484     loadPendingResources();
2485     
2486     ASSERT(!m_fontDirty);
2487     
2488     if (cacheItem || !cacheHash)
2489         return;
2490     if (!isCacheableInMatchedPropertiesCache(m_element, m_style.get(), m_parentStyle))
2491         return;
2492     addToMatchedPropertiesCache(m_style.get(), m_parentStyle, cacheHash, matchResult);
2493 }
2494
2495 static inline bool comparePageRules(const StyleRulePage* r1, const StyleRulePage* r2)
2496 {
2497     return r1->selector()->specificity() < r2->selector()->specificity();
2498 }
2499
2500 void StyleResolver::matchPageRules(MatchResult& result, RuleSet* rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2501 {
2502     if (!rules)
2503         return;
2504
2505     Vector<StyleRulePage*> matchedPageRules;
2506     matchPageRulesForList(matchedPageRules, rules->pageRules(), isLeftPage, isFirstPage, pageName);
2507     if (matchedPageRules.isEmpty())
2508         return;
2509
2510     std::stable_sort(matchedPageRules.begin(), matchedPageRules.end(), comparePageRules);
2511
2512     for (unsigned i = 0; i < matchedPageRules.size(); i++)
2513         addMatchedProperties(result, matchedPageRules[i]->properties());
2514 }
2515
2516 void StyleResolver::matchPageRulesForList(Vector<StyleRulePage*>& matchedRules, const Vector<StyleRulePage*>& rules, bool isLeftPage, bool isFirstPage, const String& pageName)
2517 {
2518     unsigned size = rules.size();
2519     for (unsigned i = 0; i < size; ++i) {
2520         StyleRulePage* rule = rules[i];
2521         const AtomicString& selectorLocalName = rule->selector()->tag().localName();
2522         if (selectorLocalName != starAtom && selectorLocalName != pageName)
2523             continue;
2524         CSSSelector::PseudoType pseudoType = rule->selector()->pseudoType();
2525         if ((pseudoType == CSSSelector::PseudoLeftPage && !isLeftPage)
2526             || (pseudoType == CSSSelector::PseudoRightPage && isLeftPage)
2527             || (pseudoType == CSSSelector::PseudoFirstPage && !isFirstPage))
2528             continue;
2529
2530         // If the rule has no properties to apply, then ignore it.
2531         const StylePropertySet* properties = rule->properties();
2532         if (!properties || properties->isEmpty())
2533             continue;
2534
2535         // Add this rule to our list of matched rules.
2536         matchedRules.append(rule);
2537     }
2538 }
2539
2540 bool StyleResolver::isLeftPage(int pageIndex) const
2541 {
2542     bool isFirstPageLeft = false;
2543     if (!m_rootElementStyle->isLeftToRightDirection())
2544         isFirstPageLeft = true;
2545
2546     return (pageIndex + (isFirstPageLeft ? 1 : 0)) % 2;
2547 }
2548
2549 bool StyleResolver::isFirstPage(int pageIndex) const
2550 {
2551     // FIXME: In case of forced left/right page, page at index 1 (not 0) can be the first page.
2552     return (!pageIndex);
2553 }
2554
2555 String StyleResolver::pageName(int /* pageIndex */) const
2556 {
2557     // FIXME: Implement page index to page name mapping.
2558     return "";
2559 }
2560
2561 template <class ListType>
2562 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, ListType* listType)
2563 {
2564     if (!listType)
2565         return;
2566     unsigned size = listType->length();
2567     for (unsigned i = 0; i < size; ++i) {
2568         CSSRule* cssRule = listType->item(i);
2569         if (cssRule->isImportRule())
2570             collectCSSOMWrappers(wrapperMap, static_cast<CSSImportRule*>(cssRule)->styleSheet());
2571         else if (cssRule->isMediaRule())
2572             collectCSSOMWrappers(wrapperMap, static_cast<CSSMediaRule*>(cssRule));
2573 #if ENABLE(CSS_REGIONS)
2574         else if (cssRule->isRegionRule())
2575             collectCSSOMWrappers(wrapperMap, static_cast<WebKitCSSRegionRule*>(cssRule));
2576 #endif
2577         else if (cssRule->isStyleRule()) {
2578             CSSStyleRule* cssStyleRule = static_cast<CSSStyleRule*>(cssRule);
2579             wrapperMap.add(cssStyleRule->styleRule(), cssStyleRule);
2580         }
2581     }
2582 }
2583
2584 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, HashSet<RefPtr<CSSStyleSheet> >& sheetWrapperSet, StyleSheetContents* styleSheet)
2585 {
2586     if (!styleSheet)
2587         return;
2588     RefPtr<CSSStyleSheet> styleSheetWrapper = CSSStyleSheet::create(styleSheet);
2589     sheetWrapperSet.add(styleSheetWrapper);
2590     collectCSSOMWrappers(wrapperMap, styleSheetWrapper.get());
2591 }
2592
2593 static void collectCSSOMWrappers(HashMap<StyleRule*, RefPtr<CSSStyleRule> >& wrapperMap, DocumentStyleSheetCollection* styleSheetCollection)
2594 {
2595     const Vector<RefPtr<CSSStyleSheet> >& styleSheets = styleSheetCollection->activeAuthorStyleSheets();
2596     for (unsigned i = 0; i < styleSheets.size(); ++i)
2597         collectCSSOMWrappers(wrapperMap, styleSheets[i].get());
2598
2599     collectCSSOMWrappers(wrapperMap, styleSheetCollection->pageUserSheet());
2600     {
2601         const Vector<RefPtr<CSSStyleSheet> >* pageGroupUserSheets = styleSheetCollection->pageGroupUserSheets();
2602         if (pageGroupUserSheets) {
2603             for (size_t i = 0, size = pageGroupUserSheets->size(); i < size; ++i)
2604                 collectCSSOMWrappers(wrapperMap, pageGroupUserSheets->at(i).get());
2605         }
2606     }
2607     {
2608         const Vector<RefPtr<CSSStyleSheet> >* documentUserSheets = styleSheetCollection->documentUserSheets();
2609         if (documentUserSheets) {
2610             for (size_t i = 0, size = documentUserSheets->size(); i < size; ++i)
2611                 collectCSSOMWrappers(wrapperMap, documentUserSheets->at(i).get());
2612         }
2613     }
2614 }
2615
2616 CSSStyleRule* StyleResolver::ensureFullCSSOMWrapperForInspector(StyleRule* rule)
2617 {
2618     if (m_styleRuleToCSSOMWrapperMap.isEmpty()) {
2619         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, simpleDefaultStyleSheet);
2620         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, defaultStyleSheet);
2621         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, quirksStyleSheet);
2622         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, svgStyleSheet);
2623         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, mathMLStyleSheet);
2624         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, mediaControlsStyleSheet);
2625         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, m_styleSheetCSSOMWrapperSet, fullscreenStyleSheet);
2626
2627         collectCSSOMWrappers(m_styleRuleToCSSOMWrapperMap, document()->styleSheetCollection());
2628     }
2629     return m_styleRuleToCSSOMWrapperMap.get(rule).get();
2630 }
2631
2632 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
2633 {
2634     initElement(0);
2635     initForStyleResolve(0, style);
2636     m_style = style;
2637     applyPropertyToCurrentStyle(id, value);
2638 }
2639
2640 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
2641 {
2642     if (value)
2643         applyProperty(id, value);
2644 }
2645
2646 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
2647 {
2648     switch (id) {
2649     case CSSPropertyBackgroundColor:
2650     case CSSPropertyBorderLeftColor:
2651     case CSSPropertyBorderRightColor:
2652     case CSSPropertyBorderTopColor:
2653     case CSSPropertyBorderBottomColor:
2654     case CSSPropertyColor:
2655     case CSSPropertyOutlineColor:
2656     case CSSPropertyWebkitColumnRuleColor:
2657     case CSSPropertyWebkitTextEmphasisColor:
2658     case CSSPropertyWebkitTextFillColor:
2659     case CSSPropertyWebkitTextStrokeColor:
2660     // Also allow shorthands so that inherit/initial still work.
2661     case CSSPropertyBackground:
2662     case CSSPropertyBorderLeft:
2663     case CSSPropertyBorderRight:
2664     case CSSPropertyBorderTop:
2665     case CSSPropertyBorderBottom:
2666     case CSSPropertyOutline:
2667     case CSSPropertyWebkitColumnRule:
2668 #if ENABLE(SVG)
2669     case CSSPropertyFill:
2670     case CSSPropertyStroke:
2671 #endif
2672         return true;
2673     default:
2674         break;
2675     }
2676
2677     return false;
2678 }
2679
2680 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
2681 // FIXME: add incremental support for other region styling properties.
2682 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
2683 {
2684     switch (id) {
2685     case CSSPropertyBackgroundColor:
2686     case CSSPropertyColor:
2687         return true;
2688     default:
2689         break;
2690     }
2691
2692     return false;
2693 }
2694
2695 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2696 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2697 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2698 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2699 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2700 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
2701 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
2702 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
2703 bool StyleResolver::useSVGZoomRules()
2704 {
2705     return m_element && m_element->isSVGElement();
2706 }
2707
2708 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, StyleResolver* selector, Length& length)
2709 {
2710     Length workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(selector->style(), selector->rootElementStyle(), selector->style()->effectiveZoom());
2711     if (workingLength.isUndefined())
2712         return false;
2713
2714     if (primitiveValue->isLength())
2715         workingLength.setQuirk(primitiveValue->isQuirkValue());
2716
2717     length = workingLength;
2718     return true;
2719 }
2720
2721 static bool createGridTrackList(CSSValue* value, Vector<Length>& lengths, StyleResolver* selector)
2722 {
2723     // Handle 'none'.
2724     if (value->isPrimitiveValue()) {
2725         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2726         if (primitiveValue->getIdent() == CSSValueNone) {
2727             lengths.append(Length(Undefined));
2728             return true;
2729         }
2730         return false;
2731     }
2732
2733     if (value->isValueList()) {
2734         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2735             CSSValue* currValue = i.value();
2736             if (!currValue->isPrimitiveValue())
2737                 return false;
2738
2739             Length length;
2740             if (!createGridTrackBreadth(static_cast<CSSPrimitiveValue*>(currValue), selector, length))
2741                 return false;
2742
2743             lengths.append(length);
2744         }
2745         return true;
2746     }
2747
2748     return false;
2749 }
2750
2751
2752 static bool createGridPosition(CSSValue* value, Length& position)
2753 {
2754     // For now, we only accept: <integer> | 'auto'
2755     if (!value->isPrimitiveValue())
2756         return false;
2757
2758     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2759     if (primitiveValue->getIdent() == CSSValueAuto)
2760         return true;
2761
2762     ASSERT(primitiveValue->isNumber());
2763     position.setValue(primitiveValue->getIntValue());
2764     return true;
2765 }
2766
2767 #if ENABLE(CSS_VARIABLES)
2768 static bool hasVariableReference(CSSValue* value)
2769 {
2770     if (value->isPrimitiveValue()) {
2771         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2772         return primitiveValue->hasVariableReference();
2773     }
2774
2775     if (value->isCalculationValue())
2776         return static_cast<CSSCalcValue*>(value)->hasVariableReference();
2777
2778     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2779         if (hasVariableReference(i.value()))
2780             return true;
2781     }
2782
2783     return false;
2784 }
2785
2786 void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<std::pair<CSSPropertyID, String> >& knownExpressions)
2787 {
2788     std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVariables(*style()->variables()));
2789
2790     if (knownExpressions.contains(expression))
2791         return; // cycle detected.
2792
2793     knownExpressions.append(expression);
2794
2795     // 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.
2796     RefPtr<StylePropertySet> resultSet = StylePropertySet::create();
2797     if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, document()))
2798         return; // expression failed to parse.
2799
2800     for (unsigned i = 0; i < resultSet->propertyCount(); i++) {
2801         StylePropertySet::PropertyReference property = resultSet->propertyAt(i);
2802         if (property.id() != CSSPropertyVariable && hasVariableReference(property.value()))
2803             resolveVariables(property.id(), property.value(), knownExpressions);
2804         else
2805             applyProperty(property.id(), property.value());
2806     }
2807 }
2808 #endif
2809
2810 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
2811 {
2812 #if ENABLE(CSS_VARIABLES)
2813     if (id != CSSPropertyVariable && hasVariableReference(value)) {
2814         Vector<std::pair<CSSPropertyID, String> > knownExpressions;
2815         resolveVariables(id, value, knownExpressions);
2816         return;
2817     }
2818 #endif
2819
2820     bool isInherit = m_parentNode && value->isInheritedValue();
2821     bool isInitial = value->isInitialValue() || (!m_parentNode && value->isInheritedValue());
2822
2823     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2824     ASSERT(!isInherit || (m_parentNode && m_parentStyle)); // isInherit -> (m_parentNode && m_parentStyle)
2825
2826     if (!applyPropertyToRegularStyle() && (!applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2827         // Limit the properties that can be applied to only the ones honored by :visited.
2828         return;
2829     }
2830
2831     if (isInherit && !m_parentStyle->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
2832         m_parentStyle->setHasExplicitlyInheritedProperties();
2833
2834 #if ENABLE(CSS_VARIABLES)
2835     if (id == CSSPropertyVariable) {
2836         ASSERT(value->isVariableValue());
2837         CSSVariableValue* variable = static_cast<CSSVariableValue*>(value);
2838         ASSERT(!variable->name().isEmpty());
2839         ASSERT(!variable->value().isEmpty());
2840         m_style->setVariable(variable->name(), variable->value());
2841         return;
2842     }
2843 #endif
2844
2845     // Check lookup table for implementations and use when available.
2846     const PropertyHandler& handler = m_styleBuilder.propertyHandler(id);
2847     if (handler.isValid()) {
2848         if (isInherit)
2849             handler.applyInheritValue(id, this);
2850         else if (isInitial)
2851             handler.applyInitialValue(id, this);
2852         else
2853             handler.applyValue(id, this, value);
2854         return;
2855     }
2856
2857     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
2858
2859     float zoomFactor = m_style->effectiveZoom();
2860
2861     // What follows is a list that maps the CSS properties into their corresponding front-end
2862     // RenderStyle values. Shorthands (e.g. border, background) occur in this list as well and
2863     // are only hit when mapping "inherit" or "initial" into front-end values.
2864     switch (id) {
2865     // lists
2866     case CSSPropertyContent:
2867         // list of string, uri, counter, attr, i
2868         {
2869             // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2870             // note is a reminder that eventually "inherit" needs to be supported.
2871
2872             if (isInitial) {
2873                 m_style->clearContent();
2874                 return;
2875             }
2876
2877             if (!value->isValueList())
2878                 return;
2879
2880             bool didSet = false;
2881             for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2882                 CSSValue* item = i.value();
2883                 if (item->isImageGeneratorValue()) {
2884                     if (item->isGradientValue())
2885                         m_style->setContent(StyleGeneratedImage::create(static_cast<CSSGradientValue*>(item)->gradientWithStylesResolved(this).get()), didSet);
2886                     else
2887                         m_style->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
2888                     didSet = true;
2889 #if ENABLE(CSS_IMAGE_SET)
2890                 } else if (item->isImageSetValue()) {
2891                     m_style->setContent(setOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageSetValue*>(item)), didSet);
2892                     didSet = true;
2893 #endif
2894                 }
2895
2896                 if (item->isImageValue()) {
2897                     m_style->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(item)), didSet);
2898                     didSet = true;
2899                     continue;
2900                 }
2901
2902                 if (!item->isPrimitiveValue())
2903                     continue;
2904
2905                 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2906
2907                 if (contentValue->isString()) {
2908                     m_style->setContent(contentValue->getStringValue().impl(), didSet);
2909                     didSet = true;
2910                 } else if (contentValue->isAttr()) {
2911                     // FIXME: Can a namespace be specified for an attr(foo)?
2912                     if (m_style->styleType() == NOPSEUDO)
2913                         m_style->setUnique();
2914                     else
2915                         m_parentStyle->setUnique();
2916                     QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2917                     const AtomicString& value = m_element->getAttribute(attr);
2918                     m_style->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2919                     didSet = true;
2920                     // register the fact that the attribute value affects the style
2921                     m_features.attrsInRules.add(attr.localName().impl());
2922                 } else if (contentValue->isCounter()) {
2923                     Counter* counterValue = contentValue->getCounterValue();
2924                     EListStyleType listStyleType = NoneListStyle;
2925                     int listStyleIdent = counterValue->listStyleIdent();
2926                     if (listStyleIdent != CSSValueNone)
2927                         listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2928                     OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
2929                     m_style->setContent(counter.release(), didSet);
2930                     didSet = true;
2931                 } else {
2932                     switch (contentValue->getIdent()) {
2933                     case CSSValueOpenQuote:
2934                         m_style->setContent(OPEN_QUOTE, didSet);
2935                         didSet = true;
2936                         break;
2937                     case CSSValueCloseQuote:
2938                         m_style->setContent(CLOSE_QUOTE, didSet);
2939                         didSet = true;
2940                         break;
2941                     case CSSValueNoOpenQuote:
2942                         m_style->setContent(NO_OPEN_QUOTE, didSet);
2943                         didSet = true;
2944                         break;
2945                     case CSSValueNoCloseQuote:
2946                         m_style->setContent(NO_CLOSE_QUOTE, didSet);
2947                         didSet = true;
2948                         break;
2949                     default:
2950                         // normal and none do not have any effect.
2951                         { }
2952                     }
2953                 }
2954             }
2955             if (!didSet)
2956                 m_style->clearContent();
2957             return;
2958         }
2959     case CSSPropertyQuotes:
2960         if (isInherit) {
2961             m_style->setQuotes(m_parentStyle->quotes());
2962             return;
2963         }
2964         if (isInitial) {
2965             m_style->setQuotes(0);
2966             return;
2967         }
2968         if (value->isValueList()) {
2969             CSSValueList* list = static_cast<CSSValueList*>(value);
2970             RefPtr<QuotesData> quotes = QuotesData::create();
2971             for (size_t i = 0; i < list->length(); i += 2) {
2972                 CSSValue* first = list->itemWithoutBoundsCheck(i);
2973                 // item() returns null if out of bounds so this is safe.
2974                 CSSValue* second = list->item(i + 1);
2975                 if (!second)
2976                     continue;
2977                 ASSERT(first->isPrimitiveValue());
2978                 ASSERT(second->isPrimitiveValue());
2979                 String startQuote = static_cast<CSSPrimitiveValue*>(first)->getStringValue();
2980                 String endQuote = static_cast<CSSPrimitiveValue*>(second)->getStringValue();
2981                 quotes->addPair(std::make_pair(startQuote, endQuote));
2982             }
2983             m_style->setQuotes(quotes);
2984             return;
2985         }
2986         if (primitiveValue) {
2987             if (primitiveValue->getIdent() == CSSValueNone)
2988                 m_style->setQuotes(QuotesData::create());
2989         }
2990         return;
2991     case CSSPropertyFontFamily: {
2992         // list of strings and ids
2993         if (isInherit) {
2994             FontDescription parentFontDescription = m_parentStyle->fontDescription();
2995             FontDescription fontDescription = m_style->fontDescription();
2996             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
2997             fontDescription.setFamily(parentFontDescription.firstFamily());
2998             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
2999             setFontDescription(fontDescription);
3000             return;
3001         }
3002
3003         if (isInitial) {
3004             FontDescription initialDesc = FontDescription();
3005             FontDescription fontDescription = m_style->fontDescription();
3006             // We need to adjust the size to account for the generic family change from monospace
3007             // to non-monospace.
3008             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
3009                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
3010             fontDescription.setGenericFamily(initialDesc.genericFamily());
3011             if (!initialDesc.firstFamily().familyIsEmpty())
3012                 fontDescription.setFamily(initialDesc.firstFamily());
3013             setFontDescription(fontDescription);
3014             return;
3015         }
3016
3017         if (!value->isValueList())
3018             return;
3019         FontDescription fontDescription = m_style->fontDescription();
3020         FontFamily& firstFamily = fontDescription.firstFamily();
3021         FontFamily* currFamily = 0;
3022
3023         // Before mapping in a new font-family property, we should reset the generic family.
3024         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
3025         fontDescription.setGenericFamily(FontDescription::NoFamily);
3026
3027         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3028             CSSValue* item = i.value();
3029             if (!item->isPrimitiveValue())
3030                 continue;
3031             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
3032             AtomicString face;
3033             Settings* settings = documentSettings();
3034             if (contentValue->isString())
3035                 face = contentValue->getStringValue();
3036             else if (settings) {
3037                 switch (contentValue->getIdent()) {
3038                 case CSSValueWebkitBody:
3039                     face = settings->standardFontFamily();
3040                     break;
3041                 case CSSValueSerif:
3042                     face = serifFamily;
3043                     fontDescription.setGenericFamily(FontDescription::SerifFamily);
3044                     break;
3045                 case CSSValueSansSerif:
3046                     face = sansSerifFamily;
3047                     fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
3048                     break;
3049                 case CSSValueCursive:
3050                     face = cursiveFamily;
3051                     fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3052                     break;
3053                 case CSSValueFantasy:
3054                     face = fantasyFamily;
3055                     fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3056                     break;
3057                 case CSSValueMonospace:
3058                     face = monospaceFamily;
3059                     fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3060                     break;
3061                 case CSSValueWebkitPictograph:
3062                     face = pictographFamily;
3063                     fontDescription.setGenericFamily(FontDescription::PictographFamily);
3064                     break;
3065                 }
3066             }
3067
3068             if (!face.isEmpty()) {
3069                 if (!currFamily) {
3070                     // Filling in the first family.
3071                     firstFamily.setFamily(face);
3072                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
3073                     currFamily = &firstFamily;
3074                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
3075                 } else {
3076                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
3077                     newFamily->setFamily(face);
3078                     currFamily->appendFamily(newFamily);
3079                     currFamily = newFamily.get();
3080                 }
3081             }
3082         }
3083
3084         // We can't call useFixedDefaultSize() until all new font families have been added
3085         // If currFamily is non-zero then we set at least one family on this description.
3086         if (currFamily) {
3087             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
3088                 setFontSize(fontDescription, fontSizeForKeyword(m_checker.document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
3089
3090             setFontDescription(fontDescription);
3091         }
3092         return;
3093     }
3094 // shorthand properties
3095     case CSSPropertyBackground:
3096         if (isInitial) {
3097             m_style->clearBackgroundLayers();
3098             m_style->setBackgroundColor(Color());
3099         } else if (isInherit) {
3100             m_style->inheritBackgroundLayers(*m_parentStyle->backgroundLayers());
3101             m_style->setBackgroundColor(m_parentStyle->backgroundColor());
3102         }
3103         return;
3104     case CSSPropertyWebkitMask:
3105         if (isInitial)
3106             m_style->clearMaskLayers();
3107         else if (isInherit)
3108             m_style->inheritMaskLayers(*m_parentStyle->maskLayers());
3109         return;
3110     case CSSPropertyFont:
3111         if (isInherit) {
3112             FontDescription fontDescription = m_parentStyle->fontDescription();
3113             m_style->setLineHeight(m_parentStyle->specifiedLineHeight());
3114             m_lineHeightValue = 0;
3115             setFontDescription(fontDescription);
3116         } else if (isInitial) {
3117             Settings* settings = documentSettings();
3118             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3119             if (!settings)
3120                 return;
3121             initializeFontStyle(settings);
3122         } else if (primitiveValue) {
3123             m_style->setLineHeight(RenderStyle::initialLineHeight());
3124             m_lineHeightValue = 0;
3125
3126             FontDescription fontDescription;
3127             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3128
3129             // Double-check and see if the theme did anything. If not, don't bother updating the font.
3130             if (fontDescription.isAbsoluteSize()) {
3131                 // Make sure the rendering mode and printer font settings are updated.
3132                 Settings* settings = documentSettings();
3133                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3134                 if (!settings)
3135                     return;
3136                 fontDescription.setRenderingMode(settings->fontRenderingMode());
3137                 fontDescription.setUsePrinterFont(m_checker.document()->printing() || !settings->screenFontSubstitutionEnabled());
3138
3139                 // Handle the zoom factor.
3140                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(m_checker.document(), m_style.get(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3141                 setFontDescription(fontDescription);
3142             }
3143         } else if (value->isFontValue()) {
3144             FontValue* font = static_cast<FontValue*>(value);
3145             if (!font->style || !font->variant || !font->weight
3146                 || !font->size || !font->lineHeight || !font->family)
3147                 return;
3148             applyProperty(CSSPropertyFontStyle, font->style.get());
3149             applyProperty(CSSPropertyFontVariant, font->variant.get());
3150             applyProperty(CSSPropertyFontWeight, font->weight.get());
3151             // The previous properties can dirty our font but they don't try to read the font's
3152             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3153             // need query the dirtied font's x-height to get the computed size. To be safe in this
3154             // case, let's just update the font now.
3155             updateFont();
3156             applyProperty(CSSPropertyFontSize, font->size.get());
3157
3158             m_lineHeightValue = font->lineHeight.get();
3159
3160             applyProperty(CSSPropertyFontFamily, font->family.get());
3161         }
3162         return;
3163
3164     // CSS3 Properties
3165     case CSSPropertyTextShadow:
3166     case CSSPropertyBoxShadow:
3167     case CSSPropertyWebkitBoxShadow: {
3168         if (isInherit) {
3169             if (id == CSSPropertyTextShadow)
3170                 return m_style->setTextShadow(m_parentStyle->textShadow() ? adoptPtr(new ShadowData(*m_parentStyle->textShadow())) : nullptr);
3171             return m_style->setBoxShadow(m_parentStyle->boxShadow() ? adoptPtr(new ShadowData(*m_parentStyle->boxShadow())) : nullptr);
3172         }
3173         if (isInitial || primitiveValue) // initial | none
3174             return id == CSSPropertyTextShadow ? m_style->setTextShadow(nullptr) : m_style->setBoxShadow(nullptr);
3175
3176         if (!value->isValueList())
3177             return;
3178
3179         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3180             CSSValue* currValue = i.value();
3181             if (!currValue->isShadowValue())
3182                 continue;
3183             ShadowValue* item = static_cast<ShadowValue*>(currValue);
3184             int x = item->x->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3185             int y = item->y->computeLength<int>(style(), m_rootElementStyle, zoomFactor);
3186             int blur = item->blur ? item->blur->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3187             int spread = item->spread ? item->spread->computeLength<int>(style(), m_rootElementStyle, zoomFactor) : 0;
3188             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3189             Color color;
3190             if (item->color)
3191                 color = colorFromPrimitiveValue(item->color.get());
3192             else if (m_style)
3193                 color = m_style->color();
3194
3195             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3196             if (id == CSSPropertyTextShadow)
3197                 m_style->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3198             else
3199                 m_style->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3200         }
3201         return;
3202     }
3203     case CSSPropertyWebkitBoxReflect: {
3204         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3205         if (primitiveValue) {
3206             m_style->setBoxReflect(RenderStyle::initialBoxReflect());
3207             return;
3208         }
3209
3210         if (!value->isReflectValue())
3211             return;
3212
3213         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3214         RefPtr<StyleReflection> reflection = StyleReflection::create();
3215         reflection->setDirection(reflectValue->direction());
3216         if (reflectValue->offset())
3217             reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(style(), m_rootElementStyle, zoomFactor));
3218         NinePieceImage mask;
3219         mask.setMaskDefaults();
3220         m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
3221         reflection->setMask(mask);
3222
3223         m_style->setBoxReflect(reflection.release());
3224         return;
3225     }
3226     case CSSPropertySrc: // Only used in @font-face rules.
3227         return;
3228     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3229         return;
3230     case CSSPropertyWebkitColumnRule:
3231         if (isInherit) {
3232             m_style->setColumnRuleColor(m_parentStyle->columnRuleColor().isValid() ? m_parentStyle->columnRuleColor() : m_parentStyle->color());
3233             m_style->setColumnRuleStyle(m_parentStyle->columnRuleStyle());
3234             m_style->setColumnRuleWidth(m_parentStyle->columnRuleWidth());
3235         } else if (isInitial)
3236             m_style->resetColumnRule();
3237         return;
3238     case CSSPropertyWebkitMarquee:
3239         if (!m_parentNode || !value->isInheritedValue())
3240             return;
3241         m_style->setMarqueeDirection(m_parentStyle->marqueeDirection());
3242         m_style->setMarqueeIncrement(m_parentStyle->marqueeIncrement());
3243         m_style->setMarqueeSpeed(m_parentStyle->marqueeSpeed());
3244         m_style->setMarqueeLoopCount(m_parentStyle->marqueeLoopCount());
3245         m_style->setMarqueeBehavior(m_parentStyle->marqueeBehavior());
3246         return;
3247     case CSSPropertyWebkitMarqueeRepetition: {
3248         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3249         if (!primitiveValue)
3250             return;
3251         if (primitiveValue->getIdent() == CSSValueInfinite)
3252             m_style->setMarqueeLoopCount(-1); // -1 means repeat forever.
3253         else if (primitiveValue->isNumber())
3254             m_style->setMarqueeLoopCount(primitiveValue->getIntValue());
3255         return;
3256     }
3257     case CSSPropertyWebkitMarqueeSpeed: {
3258         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3259         if (!primitiveValue)
3260             return;
3261         if (int ident = primitiveValue->getIdent()) {
3262             switch (ident) {
3263             case CSSValueSlow:
3264                 m_style->setMarqueeSpeed(500); // 500 msec.
3265                 break;
3266             case CSSValueNormal:
3267                 m_style->setMarqueeSpeed(85); // 85msec. The WinIE default.
3268                 break;
3269             case CSSValueFast:
3270                 m_style->setMarqueeSpeed(10); // 10msec. Super fast.
3271                 break;
3272             }
3273         } else if (primitiveValue->isTime())
3274             m_style->setMarqueeSpeed(primitiveValue->computeTime<int, CSSPrimitiveValue::Milliseconds>());
3275         else if (primitiveValue->isNumber()) // For scrollamount support.
3276             m_style->setMarqueeSpeed(primitiveValue->getIntValue());
3277         return;
3278     }
3279     case CSSPropertyWebkitMarqueeIncrement: {
3280         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3281         if (!primitiveValue)
3282             return;
3283         if (primitiveValue->getIdent()) {
3284             switch (primitiveValue->getIdent()) {
3285             case CSSValueSmall:
3286                 m_style->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3287                 break;
3288             case CSSValueNormal:
3289                 m_style->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3290                 break;
3291             case CSSValueLarge:
3292                 m_style->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3293                 break;
3294             }
3295         } else {
3296             Length marqueeLength = convertToIntLength(primitiveValue, style(), m_rootElementStyle);
3297             if (!marqueeLength.isUndefined())
3298                 m_style->setMarqueeIncrement(marqueeLength);
3299         }
3300         return;
3301     }
3302     case CSSPropertyWebkitLocale: {
3303         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3304         if (!primitiveValue)
3305             return;
3306         if (primitiveValue->getIdent() == CSSValueAuto)
3307             m_style->setLocale(nullAtom);
3308         else
3309             m_style->setLocale(primitiveValue->getStringValue());
3310         FontDescription fontDescription = m_style->fontDescription();
3311         fontDescription.setScript(localeToScriptCodeForFontSelection(m_style->locale()));
3312         setFontDescription(fontDescription);
3313         return;
3314     }
3315     case CSSPropertyWebkitTextSizeAdjust: {
3316         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
3317         if (!primitiveValue || !primitiveValue->getIdent())
3318             return;
3319         setTextSizeAdjust(primitiveValue->getIdent() == CSSValueAuto);
3320         return;
3321     }
3322 #if ENABLE(DASHBOARD_SUPPORT)
3323     case CSSPropertyWebkitDashboardRegion:
3324     {
3325         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3326         if (!primitiveValue)
3327             return;
3328
3329         if (primitiveValue->getIdent() == CSSValueNone) {
3330             m_style->setDashboardRegions(RenderStyle::noneDashboardRegions());
3331             return;
3332         }
3333
3334         DashboardRegion* region = primitiveValue->getDashboardRegionValue();
3335         if (!region)
3336             return;
3337
3338         DashboardRegion* first = region;
3339         while (region) {
3340             Length top = convertToIntLength(region->top(), style(), m_rootElementStyle);
3341             Length right = convertToIntLength(region->right(), style(), m_rootElementStyle);
3342             Length bottom = convertToIntLength(region->bottom(), style(), m_rootElementStyle);
3343             Length left = convertToIntLength(region->left(), style(), m_rootElementStyle);
3344
3345             if (top.isUndefined())
3346                 top = Length();
3347             if (right.isUndefined())
3348                 right = Length();
3349             if (bottom.isUndefined())
3350                 bottom = Length();
3351             if (left.isUndefined())
3352                 left = Length();
3353
3354             if (region->m_isCircle)
3355                 m_style->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3356             else if (region->m_isRectangle)
3357                 m_style->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3358             region = region->m_next.get();
3359         }
3360
3361         m_element->document()->setHasAnnotatedRegions(true);
3362
3363         return;
3364     }
3365 #endif
3366 #if ENABLE(DRAGGABLE_REGION)
3367     case CSSPropertyWebkitAppRegion: {
3368         if (!primitiveValue || !primitiveValue->getIdent())
3369             return;
3370         m_style->setDraggableRegionMode(primitiveValue->getIdent() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
3371         m_element->document()->setHasAnnotatedRegions(true);
3372         return;
3373     }
3374 #endif
3375     case CSSPropertyWebkitTextStrokeWidth: {
3376         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3377         float width = 0;
3378         switch (primitiveValue->getIdent()) {
3379         case CSSValueThin:
3380         case CSSValueMedium:
3381         case CSSValueThick: {
3382             double result = 1.0 / 48;
3383             if (primitiveValue->getIdent() == CSSValueMedium)
3384                 result *= 3;
3385             else if (primitiveValue->getIdent() == CSSValueThick)
3386                 result *= 5;
3387             width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3388             break;
3389         }
3390         default:
3391             width = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3392             break;
3393         }
3394         m_style->setTextStrokeWidth(width);
3395         return;
3396     }
3397     case CSSPropertyWebkitTransform: {
3398         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3399         TransformOperations operations;
3400         createTransformOperations(value, style(), m_rootElementStyle, operations);
3401         m_style->setTransform(operations);
3402         return;
3403     }
3404     case CSSPropertyWebkitPerspective: {
3405         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3406
3407         if (!primitiveValue)
3408             return;
3409
3410         if (primitiveValue->getIdent() == CSSValueNone) {
3411             m_style->setPerspective(0);
3412             return;
3413         }
3414
3415         float perspectiveValue;
3416         if (primitiveValue->isLength())
3417             perspectiveValue = primitiveValue->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3418         else if (primitiveValue->isNumber()) {
3419             // For backward compatibility, treat valueless numbers as px.
3420             perspectiveValue = CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX)->computeLength<float>(style(), m_rootElementStyle, zoomFactor);
3421         } else
3422             return;
3423
3424         if (perspectiveValue >= 0.0f)
3425             m_style->setPerspective(perspectiveValue);
3426         return;
3427     }
3428     case CSSPropertyWebkitAnimation:
3429         if (isInitial)
3430             m_style->clearAnimations();
3431         else if (isInherit)
3432             m_style->inheritAnimations(m_parentStyle->animations());
3433         return;
3434     case CSSPropertyWebkitTransition:
3435         if (isInitial)
3436             m_style->clearTransitions();
3437         else if (isInherit)
3438             m_style->inheritTransitions(m_parentStyle->transitions());
3439         return;
3440 #if ENABLE(TOUCH_EVENTS)
3441     case CSSPropertyWebkitTapHighlightColor: {
3442         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
3443         if (!primitiveValue)
3444             break;
3445
3446         Color col = colorFromPrimitiveValue(primitiveValue);
3447         m_style->setTapHighlightColor(col);
3448         return;
3449     }
3450 #endif
3451 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
3452     case CSSPropertyWebkitOverflowScrolling: {
3453         HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
3454         if (!primitiveValue)
3455             break;
3456         m_style->setUseTouchOverflowScrolling(primitiveValue->getIdent() == CSSValueTouch);
3457         return;
3458     }
3459 #endif
3460     case CSSPropertyInvalid:
3461         return;
3462     // Directional properties are resolved by resolveDirectionAwareProperty() before the switch.
3463     case CSSPropertyWebkitBorderEnd:
3464     case CSSPropertyWebkitBorderEndColor:
3465     case CSSPropertyWebkitBorderEndStyle:
3466     case CSSPropertyWebkitBorderEndWidth:
3467     case CSSPropertyWebkitBorderStart:
3468     case CSSPropertyWebkitBorderStartColor:
3469     case CSSPropertyWebkitBorderStartStyle:
3470     case CSSPropertyWebkitBorderStartWidth:
3471     case CSSPropertyWebkitBorderBefore:
3472     case CSSPropertyWebkitBorderBeforeColor:
3473     case CSSPropertyWebkitBorderBeforeStyle:
3474     case CSSPropertyWebkitBorderBeforeWidth:
3475     case CSSPropertyWebkitBorderAfter:
3476     case CSSPropertyWebkitBorderAfterColor:
3477     case CSSPropertyWebkitBorderAfterStyle:
3478     case CSSPropertyWebkitBorderAfterWidth:
3479     case CSSPropertyWebkitMarginEnd:
3480     case CSSPropertyWebkitMarginStart:
3481     case CSSPropertyWebkitMarginBefore:
3482     case CSSPropertyWebkitMarginAfter:
3483     case CSSPropertyWebkitMarginCollapse:
3484     case CSSPropertyWebkitMarginBeforeCollapse:
3485     case CSSPropertyWebkitMarginTopCollapse:
3486     case CSSPropertyWebkitMarginAfterCollapse:
3487     case CSSPropertyWebkitMarginBottomCollapse:
3488     case CSSPropertyWebkitPaddingEnd:
3489     case CSSPropertyWebkitPaddingStart:
3490     case CSSPropertyWebkitPaddingBefore:
3491     case CSSPropertyWebkitPaddingAfter:
3492     case CSSPropertyWebkitLogicalWidth:
3493     case CSSPropertyWebkitLogicalHeight:
3494     case CSSPropertyWebkitMinLogicalWidth:
3495     case CSSPropertyWebkitMinLogicalHeight:
3496     case CSSPropertyWebkitMaxLogicalWidth:
3497     case CSSPropertyWebkitMaxLogicalHeight:
3498     {
3499         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, m_style->direction(), m_style->writingMode());
3500         ASSERT(newId != id);
3501         return applyProperty(newId, value);
3502     }
3503     case CSSPropertyFontStretch:
3504     case CSSPropertyPage:
3505     case CSSPropertyTextLineThrough:
3506     case CSSPropertyTextLineThroughColor:
3507     case CSSPropertyTextLineThroughMode:
3508     case CSSPropertyTextLineThroughStyle:
3509     case CSSPropertyTextLineThroughWidth:
3510     case CSSPropertyTextOverline:
3511     case CSSPropertyTextOverlineColor:
3512     case CSSPropertyTextOverlineMode:
3513     case CSSPropertyTextOverlineStyle:
3514     case CSSPropertyTextOverlineWidth:
3515     case CSSPropertyTextUnderline:
3516     case CSSPropertyTextUnderlineColor:
3517     case CSSPropertyTextUnderlineMode:
3518     case CSSPropertyTextUnderlineStyle:
3519     case CSSPropertyTextUnderlineWidth:
3520     case CSSPropertyWebkitFontSizeDelta:
3521     case CSSPropertyWebkitTextDecorationsInEffect:
3522     case CSSPropertyWebkitTextStroke:
3523     case CSSPropertyWebkitTextEmphasis:
3524         return;
3525
3526     // CSS Text Layout Module Level 3: Vertical writing support
3527     case CSSPropertyWebkitWritingMode: {
3528         HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
3529         
3530         if (primitiveValue)
3531             m_style->setWritingMode(*primitiveValue);
3532         
3533         // FIXME: It is not ok to modify document state while applying style.
3534         if (m_element && m_element == m_element->document()->documentElement())
3535             m_element->document()->setWritingModeSetOnDocumentElement(true);
3536         FontDescription fontDescription = m_style->fontDescription();
3537         fontDescription.setOrientation(m_style->isHorizontalWritingMode() ? Horizontal : Vertical);
3538         setFontDescription(fontDescription);
3539         return;
3540     }
3541
3542     case CSSPropertyWebkitLineBoxContain: {
3543         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
3544         if (primitiveValue && primitiveValue->getIdent() == CSSValueNone) {
3545             m_style->setLineBoxContain(LineBoxContainNone);
3546             return;
3547         }
3548
3549         if (!value->isCSSLineBoxContainValue())
3550             return;
3551
3552         CSSLineBoxContainValue* lineBoxContainValue = static_cast<CSSLineBoxContainValue*>(value);
3553         m_style->setLineBoxContain(lineBoxContainValue->value());
3554         return;
3555     }
3556
3557     // CSS Fonts Module Level 3
3558     case CSSPropertyWebkitFontFeatureSettings: {
3559         if (primitiveValue && primitiveValue->getIdent() == CSSValueNormal) {
3560             setFontDescription(m_style->fontDescription().makeNormalFeatureSettings());
3561             return;
3562         }
3563
3564         if (!value->isValueList())
3565             return;
3566
3567         FontDescription fontDescription = m_style->fontDescription();
3568         CSSValueList* list = static_cast<CSSValueList*>(value);
3569         RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
3570         int len = list->length();
3571         for (int i = 0; i < len; ++i) {
3572             CSSValue* item = list->itemWithoutBoundsCheck(i);
3573             if (!item->isFontFeatureValue())
3574                 continue;
3575             FontFeatureValue* feature = static_cast<FontFeatureValue*>(item);
3576             settings->append(FontFeature(feature->tag(), feature->value()));
3577         }
3578         fontDescription.setFeatureSettings(settings.release());
3579         setFontDescription(fontDescription);
3580         return;
3581     }
3582
3583 #if ENABLE(CSS_FILTERS)
3584     case CSSPropertyWebkitFilter: {
3585         HANDLE_INHERIT_AND_INITIAL(filter, Filter);
3586         FilterOperations operations;
3587         if (createFilterOperations(value, style(), m_rootElementStyle, operations))
3588             m_style->setFilter(operations);
3589         return;
3590     }
3591 #endif
3592     case CSSPropertyWebkitGridColumns: {
3593         Vector<Length> lengths;
3594         if (!createGridTrackList(value, lengths, this))
3595             return;
3596         m_style->setGridColumns(lengths);
3597         return;
3598     }
3599     case CSSPropertyWebkitGridRows: {
3600         Vector<Length> lengths;
3601         if (!createGridTrackList(value, lengths, this))
3602             return;
3603         m_style->setGridRows(lengths);
3604         return;
3605     }
3606
3607     case CSSPropertyWebkitGridColumn: {
3608         Length column;
3609         if (!createGridPosition(value, column))
3610             return;
3611         m_style->setGridItemColumn(column);
3612         return;
3613     }
3614     case CSSPropertyWebkitGridRow: {
3615         Length row;
3616         if (!createGridPosition(value, row))
3617             return;
3618         m_style->setGridItemRow(row);
3619         return;
3620     }
3621     // These properties are implemented in the StyleBuilder lookup table.
3622     case CSSPropertyBackgroundAttachment:
3623     case CSSPropertyBackgroundClip:
3624     case CSSPropertyBackgroundColor:
3625     case CSSPropertyBackgroundImage:
3626     case CSSPropertyBackgroundOrigin:
3627     case CSSPropertyBackgroundPosition:
3628     case CSSPropertyBackgroundPositionX:
3629     case CSSPropertyBackgroundPositionY:
3630     case CSSPropertyBackgroundRepeat:
3631     case CSSPropertyBackgroundRepeatX:
3632     case CSSPropertyBackgroundRepeatY:
3633     case CSSPropertyBackgroundSize:
3634     case CSSPropertyBorder:
3635     case CSSPropertyBorderBottom:
3636     case CSSPropertyBorderBottomColor:
3637     case CSSPropertyBorderBottomLeftRadius:
3638     case CSSPropertyBorderBottomRightRadius:
3639     case CSSPropertyBorderBottomStyle:
3640     case CSSPropertyBorderBottomWidth:
3641     case CSSPropertyBorderCollapse:
3642     case CSSPropertyBorderColor:
3643     case CSSPropertyBorderImage:
3644     case CSSPropertyBorderImageOutset:
3645     case CSSPropertyBorderImageRepeat:
3646     case CSSPropertyBorderImageSlice:
3647     case CSSPropertyBorderImageSource:
3648     case CSSPropertyBorderImageWidth:
3649     case CSSPropertyBorderLeft:
3650     case CSSPropertyBorderLeftColor:
3651     case CSSPropertyBorderLeftStyle:
3652     case CSSPropertyBorderLeftWidth:
3653     case CSSPropertyBorderRadius:
3654     case CSSPropertyBorderRight:
3655     case CSSPropertyBorderRightColor:
3656     case CSSPropertyBorderRightStyle:
3657     case CSSPropertyBorderRightWidth:
3658     case CSSPropertyBorderSpacing:
3659     case CSSPropertyBorderStyle:
3660     case CSSPropertyBorderTop:
3661     case CSSPropertyBorderTopColor:
3662     case CSSPropertyBorderTopLeftRadius:
3663     case CSSPropertyBorderTopRightRadius:
3664     case CSSPropertyBorderTopStyle:
3665     case CSSPropertyBorderTopWidth:
3666     case CSSPropertyBorderWidth:
3667     case CSSPropertyBottom:
3668     case CSSPropertyBoxSizing:
3669     case CSSPropertyCaptionSide:
3670     case CSSPropertyClear:
3671     case CSSPropertyClip:
3672     case CSSPropertyColor:
3673     case CSSPropertyCounterIncrement:
3674     case CSSPropertyCounterReset:
3675     case CSSPropertyCursor:
3676     case CSSPropertyDirection:
3677     case CSSPropertyDisplay:
3678     case CSSPropertyEmptyCells:
3679     case CSSPropertyFloat:
3680     case CSSPropertyFontSize:
3681     case CSSPropertyFontStyle:
3682     case CSSPropertyFontVariant:
3683     case CSSPropertyFontWeight:
3684     case CSSPropertyHeight:
3685 #if ENABLE(CSS_IMAGE_ORIENTATION)
3686     case CSSPropertyImageOrientation:
3687 #endif
3688     case CSSPropertyImageRendering:
3689 #if ENABLE(CSS_IMAGE_RESOLUTION)
3690     case CSSPropertyImageResolution:
3691 #endif
3692     case CSSPropertyLeft:
3693     case CSSPropertyLetterSpacing:
3694     case CSSPropertyLineHeight:
3695     case CSSPropertyListStyle:
3696     case CSSPropertyListStyleImage:
3697     case CSSPropertyListStylePosition:
3698     case CSSPropertyListStyleType:
3699     case CSSPropertyMargin:
3700     case CSSPropertyMarginBottom:
3701     case CSSPropertyMarginLeft:
3702     case CSSPropertyMarginRight:
3703     case CSSPropertyMarginTop:
3704     case CSSPropertyMaxHeight:
3705     case CSSPropertyMaxWidth:
3706     case CSSPropertyMinHeight:
3707     case CSSPropertyMinWidth:
3708     case CSSPropertyOpacity:
3709     case CSSPropertyOrphans:
3710     case CSSPropertyOutline:
3711     case CSSPropertyOutlineColor:
3712     case CSSPropertyOutlineOffset:
3713     case CSSPropertyOutlineStyle:
3714     case CSSPropertyOutlineWidth:
3715     case CSSPropertyOverflow:
3716     case CSSPropertyOverflowWrap:
3717     case CSSPropertyOverflowX:
3718     case CSSPropertyOverflowY:
3719     case CSSPropertyPadding:
3720     case CSSPropertyPaddingBottom:
3721     case CSSPropertyPaddingLeft:
3722     case CSSPropertyPaddingRight:
3723     case CSSPropertyPaddingTop:
3724     case CSSPropertyPageBreakAfter:
3725     case CSSPropertyPageBreakBefore:
3726     case CSSPropertyPageBreakInside:
3727     case CSSPropertyPointerEvents:
3728     case CSSPropertyPosition:
3729     case CSSPropertyResize:
3730     case CSSPropertyRight:
3731     case CSSPropertySize:
3732     case CSSPropertySpeak:
3733     case CSSPropertyTabSize:
3734     case CSSPropertyTableLayout:
3735     case CSSPropertyTextAlign:
3736     case CSSPropertyTextDecoration:
3737     case CSSPropertyTextIndent:
3738     case CSSPropertyTextOverflow:
3739     case CSSPropertyTextRendering:
3740     case CSSPropertyTextTransform:
3741     case CSSPropertyTop:
3742     case CSSPropertyUnicodeBidi:
3743 #if ENABLE(CSS_VARIABLES)
3744     case CSSPropertyVariable:
3745 #endif
3746     case CSSPropertyVerticalAlign:
3747     case CSSPropertyVisibility:
3748     case CSSPropertyWebkitAnimationDelay:
3749     case CSSPropertyWebkitAnimationDirection:
3750     case CSSPropertyWebkitAnimationDuration:
3751     case CSSPropertyWebkitAnimationFillMode:
3752     case CSSPropertyWebkitAnimationIterationCount:
3753     case CSSPropertyWebkitAnimationName:
3754     case CSSPropertyWebkitAnimationPlayState:
3755     case CSSPropertyWebkitAnimationTimingFunction:
3756     case CSSPropertyWebkitAppearance:
3757     case CSSPropertyWebkitAspectRatio:
3758     case CSSPropertyWebkitBackfaceVisibility:
3759     case CSSPropertyWebkitBackgroundClip:
3760     case CSSPropertyWebkitBackgroundComposite:
3761     case CSSPropertyWebkitBackgroundOrigin:
3762     case CSSPropertyWebkitBackgroundSize:
3763     case CSSPropertyWebkitBorderFit:
3764     case CSSPropertyWebkitBorderHorizontalSpacing:
3765     case CSSPropertyWebkitBorderImage:
3766     case CSSPropertyWebkitBorderRadius:
3767     case CSSPropertyWebkitBorderVerticalSpacing:
3768     case CSSPropertyWebkitBoxAlign:
3769 #if ENABLE(CSS_BOX_DECORATION_BREAK)
3770     case CSSPropertyWebkitBoxDecorationBreak:
3771 #endif
3772     case CSSPropertyWebkitBoxDirection:
3773     case CSSPropertyWebkitBoxFlex:
3774     case CSSPropertyWebkitBoxFlexGroup:
3775     case CSSPropertyWebkitBoxLines:
3776     case CSSPropertyWebkitBoxOrdinalGroup:
3777     case CSSPropertyWebkitBoxOrient:
3778     case CSSPropertyWebkitBoxPack:
3779     case CSSPropertyWebkitColorCorrection:
3780     case CSSPropertyWebkitColumnAxis:
3781     case CSSPropertyWebkitColumnBreakAfter:
3782     case CSSPropertyWebkitColumnBreakBefore:
3783     case CSSPropertyWebkitColumnBreakInside:
3784     case CSSPropertyWebkitColumnCount:
3785     case CSSPropertyWebkitColumnGap:
3786     case CSSPropertyWebkitColumnProgression:
3787     case CSSPropertyWebkitColumnRuleColor:
3788     case CSSPropertyWebkitColumnRuleStyle:
3789     case CSSPropertyWebkitColumnRuleWidth:
3790     case CSSPropertyWebkitColumns:
3791     case CSSPropertyWebkitColumnSpan:
3792     case CSSPropertyWebkitColumnWidth:
3793     case CSSPropertyWebkitAlignContent:
3794     case CSSPropertyWebkitAlignItems:
3795     case CSSPropertyWebkitAlignSelf:
3796     case CSSPropertyWebkitFlex:
3797     case CSSPropertyWebkitFlexBasis:
3798     case CSSPropertyWebkitFlexDirection:
3799     case CSSPropertyWebkitFlexFlow:
3800     case CSSPropertyWebkitFlexGrow:
3801     case CSSPropertyWebkitFlexShrink:
3802     case CSSPropertyWebkitFlexWrap:
3803     case CSSPropertyWebkitJustifyContent:
3804     case CSSPropertyWebkitOrder:
3805 #if ENABLE(CSS_REGIONS)
3806     case CSSPropertyWebkitFlowFrom:
3807     case CSSPropertyWebkitFlowInto:
3808 #endif
3809     case CSSPropertyWebkitFontKerning:
3810     case CSSPropertyWebkitFontSmoothing:
3811     case CSSPropertyWebkitFontVariantLigatures:
3812     case CSSPropertyWebkitHighlight:
3813     case CSSPropertyWebkitHyphenateCharacter:
3814     case CSSPropertyWebkitHyphenateLimitAfter:
3815     case CSSPropertyWebkitHyphenateLimitBefore:
3816     case CSSPropertyWebkitHyphenateLimitLines:
3817     case CSSPropertyWebkitHyphens:
3818     case CSSPropertyWebkitLineAlign:
3819     case CSSPropertyWebkitLineBreak:
3820     case CSSPropertyWebkitLineClamp:
3821     case CSSPropertyWebkitLineGrid:
3822     case CSSPropertyWebkitLineSnap:
3823     case CSSPropertyWebkitMarqueeDirection:
3824     case CSSPropertyWebkitMarqueeStyle:
3825     case CSSPropertyWebkitMaskAttachment:
3826     case CSSPropertyWebkitMaskBoxImage:
3827     case CSSPropertyWebkitMaskBoxImageOutset:
3828     case CSSPropertyWebkitMaskBoxImageRepeat:
3829     case CSSPropertyWebkitMaskBoxImageSlice:
3830     case CSSPropertyWebkitMaskBoxImageSource:
3831     case CSSPropertyWebkitMaskBoxImageWidth:
3832     case CSSPropertyWebkitMaskClip:
3833     case CSSPropertyWebkitMaskComposite:
3834     case CSSPropertyWebkitMaskImage:
3835     case CSSPropertyWebkitMaskOrigin:
3836     case CSSPropertyWebkitMaskPosition:
3837     case CSSPropertyWebkitMaskPositionX:
3838     case CSSPropertyWebkitMaskPositionY:
3839     case CSSPropertyWebkitMaskRepeat:
3840     case CSSPropertyWebkitMaskRepeatX:
3841     case CSSPropertyWebkitMaskRepeatY:
3842     case CSSPropertyWebkitMaskSize:
3843     case CSSPropertyWebkitNbspMode:
3844     case CSSPropertyWebkitPerspectiveOrigin:
3845     case CSSPropertyWebkitPerspectiveOriginX:
3846     case CSSPropertyWebkitPerspectiveOriginY:
3847     case CSSPropertyWebkitPrintColorAdjust:
3848 #if ENABLE(CSS_REGIONS)
3849     case CSSPropertyWebkitRegionBreakAfter:
3850     case CSSPropertyWebkitRegionBreakBefore:
3851     case CSSPropertyWebkitRegionBreakInside:
3852     case CSSPropertyWebkitRegionOverflow:
3853 #endif
3854     case CSSPropertyWebkitRtlOrdering:
3855     case CSSPropertyWebkitTextCombine:
3856 #if ENABLE(CSS3_TEXT)
3857     case CSSPropertyWebkitTextDecorationLine:
3858     case CSSPropertyWebkitTextDecorationStyle:
3859     case CSSPropertyWebkitTextAlignLast:
3860 #endif // CSS3_TEXT
3861     case CSSPropertyWebkitTextEmphasisColor:
3862     case CSSPropertyWebkitTextEmphasisPosition:
3863     case CSSPropertyWebkitTextEmphasisStyle:
3864     case CSSPropertyWebkitTextFillColor:
3865     case CSSPropertyWebkitTextOrientation:
3866     case CSSPropertyWebkitTextSecurity:
3867     case CSSPropertyWebkitTextStrokeColor:
3868     case CSSPropertyWebkitTransformOrigin:
3869     case CSSPropertyWebkitTransformOriginX:
3870     case CSSPropertyWebkitTransformOriginY:
3871     case CSSPropertyWebkitTransformOriginZ:
3872     case CSSPropertyWebkitTransformStyle:
3873     case CSSPropertyWebkitTransitionDelay:
3874     case CSSPropertyWebkitTransitionDuration:
3875     case CSSPropertyWebkitTransitionProperty:
3876     case CSSPropertyWebkitTransitionTimingFunction:
3877     case CSSPropertyWebkitUserDrag:
3878     case CSSPropertyWebkitUserModify:
3879     case CSSPropertyWebkitUserSelect:
3880     case CSSPropertyWebkitClipPath:
3881 #if ENABLE(CSS_EXCLUSIONS)
3882     case CSSPropertyWebkitWrap:
3883     case CSSPropertyWebkitWrapFlow:
3884     case CSSPropertyWebkitShapeMargin:
3885     case CSSPropertyWebkitShapePadding:
3886     case CSSPropertyWebkitWrapThrough:
3887     case CSSPropertyWebkitShapeInside:
3888     case CSSPropertyWebkitShapeOutside:
3889 #endif
3890     case CSSPropertyWhiteSpace:
3891     case CSSPropertyWidows:
3892     case CSSPropertyWidth:
3893     case CSSPropertyWordBreak:
3894     case CSSPropertyWordSpacing:
3895     case CSSPropertyWordWrap:
3896     case CSSPropertyZIndex:
3897     case CSSPropertyZoom:
3898 #if ENABLE(CSS_DEVICE_ADAPTATION)
3899     case CSSPropertyMaxZoom:
3900     case CSSPropertyMinZoom:
3901     case CSSPropertyOrientation:
3902     case CSSPropertyUserZoom:
3903 #endif
3904         ASSERT_NOT_REACHED();
3905         return;
3906 #if ENABLE(SVG)
3907     default:
3908         // Try the SVG properties
3909         applySVGProperty(id, value);
3910         return;
3911 #endif
3912     }
3913 }
3914
3915 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value)
3916 {
3917     if (value->isImageValue())
3918         return cachedOrPendingFromValue(property, static_cast<CSSImageValue*>(value));
3919
3920     if (value->isImageGeneratorValue()) {
3921         if (value->isGradientValue())
3922             return generatedOrPendingFromValue(property, static_cast<CSSGradientValue*>(value)->gradientWithStylesResolved(this).get());
3923         return generatedOrPendingFromValue(property, static_cast<CSSImageGeneratorValue*>(value));
3924     }
3925
3926 #if ENABLE(CSS_IMAGE_SET)
3927     if (value->isImageSetValue())
3928         return setOrPendingFromValue(property, static_cast<CSSImageSetValue*>(value));
3929 #endif
3930
3931     return 0;
3932 }
3933
3934 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
3935 {
3936     RefPtr<StyleImage> image = value->cachedOrPendingImage();
3937     if (image && image->isPendingImage())
3938         m_pendingImageProperties.set(property, value);
3939     return image.release();