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