Unreviewed, rolling out r145349.
[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 "StylePropertyShorthand.h"
118 #include "StyleRule.h"
119 #include "StyleRuleImport.h"
120 #include "StyleSheetContents.h"
121 #include "StyleSheetList.h"
122 #include "Text.h"
123 #include "TransformationMatrix.h"
124 #include "TranslateTransformOperation.h"
125 #include "UserAgentStyleSheets.h"
126 #include "ViewportStyleResolver.h"
127 #include "VisitedLinkState.h"
128 #include "WebCoreMemoryInstrumentation.h"
129 #include "WebKitCSSKeyframeRule.h"
130 #include "WebKitCSSKeyframesRule.h"
131 #include "WebKitCSSRegionRule.h"
132 #include "WebKitCSSTransformValue.h"
133 #include "WebKitFontFamilyNames.h"
134 #include "XMLNames.h"
135 #include <wtf/MemoryInstrumentationHashMap.h>
136 #include <wtf/MemoryInstrumentationHashSet.h>
137 #include <wtf/MemoryInstrumentationVector.h>
138 #include <wtf/StdLibExtras.h>
139 #include <wtf/Vector.h>
140
141 #if ENABLE(CSS_FILTERS)
142 #include "FilterOperation.h"
143 #include "WebKitCSSFilterValue.h"
144 #endif
145
146 #if ENABLE(DASHBOARD_SUPPORT)
147 #include "DashboardRegion.h"
148 #endif
149
150 #if ENABLE(SVG)
151 #include "CachedSVGDocument.h"
152 #include "CachedSVGDocumentReference.h"
153 #include "SVGDocument.h"
154 #include "SVGElement.h"
155 #include "SVGNames.h"
156 #include "SVGURIReference.h"
157 #include "WebKitCSSSVGDocumentValue.h"
158 #endif
159
160 #if ENABLE(CSS_SHADERS)
161 #include "CustomFilterArrayParameter.h"
162 #include "CustomFilterConstants.h"
163 #include "CustomFilterNumberParameter.h"
164 #include "CustomFilterOperation.h"
165 #include "CustomFilterParameter.h"
166 #include "CustomFilterTransformParameter.h"
167 #include "StyleCachedShader.h"
168 #include "StyleCustomFilterProgram.h"
169 #include "StylePendingShader.h"
170 #include "StyleShader.h"
171 #include "WebKitCSSMixFunctionValue.h"
172 #include "WebKitCSSShaderValue.h"
173 #endif
174
175 #if ENABLE(CSS_IMAGE_SET)
176 #include "CSSImageSetValue.h"
177 #include "StyleCachedImageSet.h"
178 #endif
179
180 #if ENABLE(VIDEO_TRACK)
181 #include "WebVTTElement.h"
182 #endif
183
184 using namespace std;
185
186 namespace WTF {
187
188 template<> struct SequenceMemoryInstrumentationTraits<const WebCore::RuleData*> {
189     template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
190 };
191
192 }
193
194 namespace WebCore {
195
196 using namespace HTMLNames;
197
198 #define HANDLE_INHERIT(prop, Prop) \
199 if (isInherit) { \
200     m_state.style()->set##Prop(m_state.parentStyle()->prop()); \
201     return; \
202 }
203
204 #define HANDLE_INHERIT_AND_INITIAL(prop, Prop) \
205 HANDLE_INHERIT(prop, Prop) \
206 if (isInitial) { \
207     m_state.style()->set##Prop(RenderStyle::initial##Prop()); \
208     return; \
209 }
210
211 RenderStyle* StyleResolver::s_styleNotYetAvailable;
212
213 static StylePropertySet* leftToRightDeclaration()
214 {
215     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, leftToRightDecl, (StylePropertySet::create()));
216     if (leftToRightDecl->isEmpty())
217         leftToRightDecl->setProperty(CSSPropertyDirection, CSSValueLtr);
218     return leftToRightDecl.get();
219 }
220
221 static StylePropertySet* rightToLeftDeclaration()
222 {
223     DEFINE_STATIC_LOCAL(RefPtr<StylePropertySet>, rightToLeftDecl, (StylePropertySet::create()));
224     if (rightToLeftDecl->isEmpty())
225         rightToLeftDecl->setProperty(CSSPropertyDirection, CSSValueRtl);
226     return rightToLeftDecl.get();
227 }
228
229
230 inline StaticCSSRuleList* StyleResolver::State::ensureRuleList()
231 {
232     if (!m_ruleList)
233         m_ruleList = StaticCSSRuleList::create();
234     return m_ruleList.get();
235 }
236
237 inline void StyleResolver::State::cacheBorderAndBackground()
238 {
239     m_hasUAAppearance = m_style->hasAppearance();
240     if (m_hasUAAppearance) {
241         m_borderData = m_style->border();
242         m_backgroundData = *m_style->backgroundLayers();
243         m_backgroundColor = m_style->backgroundColor();
244     }
245 }
246
247 inline void StyleResolver::State::clear()
248 {
249     m_element = 0;
250     m_styledElement = 0;
251     m_parentStyle = 0;
252     m_parentNode = 0;
253     m_regionForStyling = 0;
254     m_ruleList = 0;
255     m_matchedRules.clear();
256     m_pendingImageProperties.clear();
257 #if ENABLE(CSS_SHADERS)
258     m_hasPendingShaders = false;
259 #endif
260 #if ENABLE(CSS_FILTERS) && ENABLE(SVG)
261     m_pendingSVGDocuments.clear();
262 #endif
263 }
264
265 StyleResolver::StyleResolver(Document* document, bool matchAuthorAndUserStyles)
266     : m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
267     , m_matchedPropertiesCacheSweepTimer(this, &StyleResolver::sweepMatchedPropertiesCache)
268     , m_document(document)
269     , m_matchAuthorAndUserStyles(matchAuthorAndUserStyles)
270     , m_fontSelector(CSSFontSelector::create(document))
271 #if ENABLE(CSS_DEVICE_ADAPTATION)
272     , m_viewportStyleResolver(ViewportStyleResolver::create(document))
273 #endif
274     , m_styleBuilder(StyleBuilder::sharedStyleBuilder())
275     , m_styleMap(this)
276 {
277     Element* root = document->documentElement();
278
279     CSSDefaultStyleSheets::initDefaultStyle(root);
280
281     // construct document root element default style. this is needed
282     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
283     // This is here instead of constructor, because when constructor is run,
284     // document doesn't have documentElement
285     // NOTE: this assumes that element that gets passed to styleForElement -call
286     // is always from the document that owns the style selector
287     FrameView* view = document->view();
288     if (view)
289         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType()));
290     else
291         m_medium = adoptPtr(new MediaQueryEvaluator("all"));
292
293     if (root)
294         m_rootDefaultStyle = styleForElement(root, 0, DisallowStyleSharing, MatchOnlyUserAgentRules);
295
296     if (m_rootDefaultStyle && view)
297         m_medium = adoptPtr(new MediaQueryEvaluator(view->mediaType(), view->frame(), m_rootDefaultStyle.get()));
298
299     m_ruleSets.resetAuthorStyle();
300
301     DocumentStyleSheetCollection* styleSheetCollection = document->styleSheetCollection();
302     m_ruleSets.initUserStyle(styleSheetCollection, *m_medium, *this);
303
304 #if ENABLE(SVG_FONTS)
305     if (document->svgExtensions()) {
306         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = document->svgExtensions()->svgFontFaceElements();
307         HashSet<SVGFontFaceElement*>::const_iterator end = svgFontFaceElements.end();
308         for (HashSet<SVGFontFaceElement*>::const_iterator it = svgFontFaceElements.begin(); it != end; ++it)
309             fontSelector()->addFontFaceRule((*it)->fontFaceRule());
310     }
311 #endif
312
313     appendAuthorStyleSheets(0, styleSheetCollection->activeAuthorStyleSheets());
314 }
315
316 void StyleResolver::appendAuthorStyleSheets(unsigned firstNew, const Vector<RefPtr<CSSStyleSheet> >& styleSheets)
317 {
318     m_ruleSets.appendAuthorStyleSheets(firstNew, styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, document()->isViewSource(), this);
319     if (document()->renderer() && document()->renderer()->style())
320         document()->renderer()->style()->font().update(fontSelector());
321
322 #if ENABLE(CSS_DEVICE_ADAPTATION)
323     viewportStyleResolver()->resolve();
324 #endif
325 }
326
327 void StyleResolver::pushParentElement(Element* parent)
328 {
329     const ContainerNode* parentsParent = parent->parentOrShadowHostElement();
330
331     // We are not always invoked consistently. For example, script execution can cause us to enter
332     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
333     // Reset the stack in this case, or if we see a new root element.
334     // Otherwise just push the new parent.
335     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
336         m_selectorFilter.setupParentStack(parent);
337     else
338         m_selectorFilter.pushParent(parent);
339
340     // Note: We mustn't skip ShadowRoot nodes for the scope stack.
341     if (m_scopeResolver)
342         m_scopeResolver->push(parent, parent->parentOrShadowHostNode());
343 }
344
345 void StyleResolver::popParentElement(Element* parent)
346 {
347     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
348     // Pause maintaining the stack in this case.
349     if (m_selectorFilter.parentStackIsConsistent(parent))
350         m_selectorFilter.popParent();
351     if (m_scopeResolver)
352         m_scopeResolver->pop(parent);
353 }
354
355 void StyleResolver::pushParentShadowRoot(const ShadowRoot* shadowRoot)
356 {
357     ASSERT(shadowRoot->host());
358     if (m_scopeResolver)
359         m_scopeResolver->push(shadowRoot, shadowRoot->host());
360 }
361
362 void StyleResolver::popParentShadowRoot(const ShadowRoot* shadowRoot)
363 {
364     ASSERT(shadowRoot->host());
365     if (m_scopeResolver)
366         m_scopeResolver->pop(shadowRoot);
367 }
368
369 // This is a simplified style setting function for keyframe styles
370 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
371 {
372     AtomicString s(rule->name());
373     m_keyframesRuleMap.set(s.impl(), rule);
374 }
375
376 StyleResolver::~StyleResolver()
377 {
378     m_fontSelector->clearDocument();
379
380 #if ENABLE(CSS_DEVICE_ADAPTATION)
381     m_viewportStyleResolver->clearDocument();
382 #endif
383 }
384
385 void StyleResolver::sweepMatchedPropertiesCache(Timer<StyleResolver>*)
386 {
387     // Look for cache entries containing a style declaration with a single ref and remove them.
388     // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
389     // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
390     Vector<unsigned, 16> toRemove;
391     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
392     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
393     for (; it != end; ++it) {
394         Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
395         for (size_t i = 0; i < matchedProperties.size(); ++i) {
396             if (matchedProperties[i].properties->hasOneRef()) {
397                 toRemove.append(it->key);
398                 break;
399             }
400         }
401     }
402     for (size_t i = 0; i < toRemove.size(); ++i)
403         m_matchedPropertiesCache.remove(toRemove[i]);
404
405     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
406 }
407
408 void StyleResolver::addMatchedProperties(MatchResult& matchResult, const StylePropertySet* properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
409 {
410     matchResult.matchedProperties.grow(matchResult.matchedProperties.size() + 1);
411     MatchedProperties& newProperties = matchResult.matchedProperties.last();
412     newProperties.properties = const_cast<StylePropertySet*>(properties);
413     newProperties.linkMatchType = linkMatchType;
414     newProperties.whitelistType = propertyWhitelistType;
415     matchResult.matchedRules.append(rule);
416 }
417
418 inline void StyleResolver::addElementStyleProperties(MatchResult& result, const StylePropertySet* propertySet, bool isCacheable)
419 {
420     if (!propertySet)
421         return;
422     result.ranges.lastAuthorRule = result.matchedProperties.size();
423     if (result.ranges.firstAuthorRule == -1)
424         result.ranges.firstAuthorRule = result.ranges.lastAuthorRule;
425     addMatchedProperties(result, propertySet);
426     if (!isCacheable)
427         result.isCacheable = false;
428 }
429
430 class MatchingUARulesScope {
431 public:
432     MatchingUARulesScope();
433     ~MatchingUARulesScope();
434
435     static bool isMatchingUARules();
436
437 private:
438     static bool m_matchingUARules;
439 };
440
441 MatchingUARulesScope::MatchingUARulesScope()
442 {
443     ASSERT(!m_matchingUARules);
444     m_matchingUARules = true;
445 }
446
447 MatchingUARulesScope::~MatchingUARulesScope()
448 {
449     m_matchingUARules = false;
450 }
451
452 inline bool MatchingUARulesScope::isMatchingUARules()
453 {
454     return m_matchingUARules;
455 }
456
457 bool MatchingUARulesScope::m_matchingUARules = false;
458
459 void StyleResolver::collectMatchingRules(const MatchRequest& matchRequest, RuleRange& ruleRange)
460 {
461     ASSERT(matchRequest.ruleSet);
462     ASSERT(m_state.element());
463
464     State& state = m_state;
465     Element* element = state.element();
466     const StyledElement* styledElement = state.styledElement();
467     const AtomicString& pseudoId = element->shadowPseudoId();
468     if (!pseudoId.isEmpty()) {
469         ASSERT(styledElement);
470         collectMatchingRulesForList(matchRequest.ruleSet->shadowPseudoElementRules(pseudoId.impl()), matchRequest, ruleRange);
471     }
472
473 #if ENABLE(VIDEO_TRACK)
474     if (element->isWebVTTElement())
475         collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange);
476 #endif
477     // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
478     // a) it's a UA rule
479     // b) the tree scope allows author rules
480     // c) the rules comes from a scoped style sheet within the same tree scope
481     TreeScope* treeScope = element->treeScope();
482     if (!MatchingUARulesScope::isMatchingUARules()
483         && !treeScope->applyAuthorStyles()
484         && (!matchRequest.scope || matchRequest.scope->treeScope() != treeScope)
485         && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary)
486         return;
487
488     // We need to collect the rules for id, class, tag, and everything else into a buffer and
489     // then sort the buffer.
490     if (element->hasID())
491         collectMatchingRulesForList(matchRequest.ruleSet->idRules(element->idForStyleResolution().impl()), matchRequest, ruleRange);
492     if (styledElement && styledElement->hasClass()) {
493         for (size_t i = 0; i < styledElement->classNames().size(); ++i)
494             collectMatchingRulesForList(matchRequest.ruleSet->classRules(styledElement->classNames()[i].impl()), matchRequest, ruleRange);
495     }
496
497     if (element->isLink())
498         collectMatchingRulesForList(matchRequest.ruleSet->linkPseudoClassRules(), matchRequest, ruleRange);
499     if (SelectorChecker::matchesFocusPseudoClass(element))
500         collectMatchingRulesForList(matchRequest.ruleSet->focusPseudoClassRules(), matchRequest, ruleRange);
501     collectMatchingRulesForList(matchRequest.ruleSet->tagRules(element->localName().impl()), matchRequest, ruleRange);
502     collectMatchingRulesForList(matchRequest.ruleSet->universalRules(), matchRequest, ruleRange);
503 }
504
505 void StyleResolver::collectMatchingRulesForRegion(const MatchRequest& matchRequest, RuleRange& ruleRange)
506 {
507     if (!m_state.regionForStyling())
508         return;
509
510     unsigned size = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.size();
511     for (unsigned i = 0; i < size; ++i) {
512         const CSSSelector* regionSelector = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).selector;
513         if (checkRegionSelector(regionSelector, static_cast<Element*>(m_state.regionForStyling()->node()))) {
514             RuleSet* regionRules = matchRequest.ruleSet->m_regionSelectorsAndRuleSets.at(i).ruleSet.get();
515             ASSERT(regionRules);
516             collectMatchingRules(MatchRequest(regionRules, matchRequest.includeEmptyRules, matchRequest.scope), ruleRange);
517         }
518     }
519 }
520
521 void StyleResolver::sortAndTransferMatchedRules(MatchResult& result)
522 {
523     State& state = m_state;
524     Vector<const RuleData*, 32>& matchedRules = state.matchedRules();
525     if (matchedRules.isEmpty())
526         return;
527
528     sortMatchedRules();
529
530     if (state.mode() == SelectorChecker::CollectingRules) {
531         for (unsigned i = 0; i < matchedRules.size(); ++i)
532             state.ensureRuleList()->rules().append(matchedRules[i]->rule()->createCSSOMWrapper());
533         return;
534     }
535
536     // Now transfer the set of matched rules over to our list of declarations.
537     for (unsigned i = 0; i < matchedRules.size(); i++) {
538         if (state.style() && matchedRules[i]->containsUncommonAttributeSelector())
539             state.style()->setUnique();
540         addMatchedProperties(result, matchedRules[i]->rule()->properties(), matchedRules[i]->rule(), matchedRules[i]->linkMatchType(), matchedRules[i]->propertyWhitelistType());
541     }
542 }
543
544 void StyleResolver::matchScopedAuthorRules(MatchResult& result, bool includeEmptyRules)
545 {
546 #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM)
547     if (!m_scopeResolver)
548         return;
549
550     // Match scoped author rules by traversing the scoped element stack (rebuild it if it got inconsistent).
551     if (m_scopeResolver->hasScopedStyles() && m_scopeResolver->ensureStackConsistency(m_state.element())) {
552         bool applyAuthorStyles = m_state.element()->treeScope()->applyAuthorStyles();
553         bool documentScope = true;
554         unsigned scopeSize = m_scopeResolver->stackSize();
555         for (unsigned i = 0; i < scopeSize; ++i) {
556             m_state.matchedRules().clear();
557             result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
558
559             const StyleScopeResolver::StackFrame& frame = m_scopeResolver->stackFrameAt(i);
560             documentScope = documentScope && !frame.m_scope->isInShadowTree();
561             if (documentScope) {
562                 if (!applyAuthorStyles)
563                     continue;
564             } else {
565                 if (!m_scopeResolver->matchesStyleBounds(frame))
566                     continue;
567             }
568
569             MatchRequest matchRequest(frame.m_ruleSet, includeEmptyRules, frame.m_scope);
570             RuleRange ruleRange = result.ranges.authorRuleRange();
571             collectMatchingRules(matchRequest, ruleRange);
572             collectMatchingRulesForRegion(matchRequest, ruleRange);
573             sortAndTransferMatchedRules(result);
574         }
575     }
576
577     matchHostRules(result, includeEmptyRules);
578 #else
579     UNUSED_PARAM(result);
580     UNUSED_PARAM(includeEmptyRules);
581 #endif
582 }
583
584 inline bool StyleResolver::styleSharingCandidateMatchesHostRules()
585 {
586 #if ENABLE(SHADOW_DOM)
587     return m_scopeResolver && m_scopeResolver->styleSharingCandidateMatchesHostRules(m_state.element());
588 #else
589     return false;
590 #endif
591 }
592
593 void StyleResolver::matchHostRules(MatchResult& result, bool includeEmptyRules)
594 {
595 #if ENABLE(SHADOW_DOM)
596     ASSERT(m_scopeResolver);
597
598     m_state.matchedRules().clear();
599     result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
600
601     Vector<RuleSet*> matchedRules;
602     m_scopeResolver->matchHostRules(m_state.element(), matchedRules);
603     if (matchedRules.isEmpty())
604         return;
605
606     for (unsigned i = matchedRules.size(); i > 0; --i) {
607         RuleRange ruleRange = result.ranges.authorRuleRange();
608         collectMatchingRules(MatchRequest(matchedRules.at(i-1), includeEmptyRules, m_state.element()), ruleRange);
609     }
610     sortAndTransferMatchedRules(result);
611 #else
612     UNUSED_PARAM(result);
613     UNUSED_PARAM(includeEmptyRules);
614 #endif
615 }
616
617 void StyleResolver::matchAuthorRules(MatchResult& result, bool includeEmptyRules)
618 {
619     m_state.matchedRules().clear();
620     result.ranges.lastAuthorRule = result.matchedProperties.size() - 1;
621
622     if (!m_state.element())
623         return;
624
625     // Match global author rules.
626     MatchRequest matchRequest(m_ruleSets.authorStyle(), includeEmptyRules);
627     RuleRange ruleRange = result.ranges.authorRuleRange();
628     collectMatchingRules(matchRequest, ruleRange);
629     collectMatchingRulesForRegion(matchRequest, ruleRange);
630 #if ENABLE(SHADOW_DOM)
631     Vector<MatchRequest> matchRequests;
632     m_ruleSets.shadowDistributedRules().collectMatchRequests(includeEmptyRules, matchRequests);
633     for (size_t i = 0; i < matchRequests.size(); ++i)
634         collectMatchingRules(matchRequests[i], ruleRange);
635 #endif
636
637     sortAndTransferMatchedRules(result);
638
639     matchScopedAuthorRules(result, includeEmptyRules);
640 }
641
642 void StyleResolver::matchUserRules(MatchResult& result, bool includeEmptyRules)
643 {
644     if (!m_ruleSets.userStyle())
645         return;
646     
647     m_state.matchedRules().clear();
648
649     result.ranges.lastUserRule = result.matchedProperties.size() - 1;
650     MatchRequest matchRequest(m_ruleSets.userStyle(), includeEmptyRules);
651     RuleRange ruleRange = result.ranges.userRuleRange();
652     collectMatchingRules(matchRequest, ruleRange);
653     collectMatchingRulesForRegion(matchRequest, ruleRange);
654
655     sortAndTransferMatchedRules(result);
656 }
657
658 void StyleResolver::matchUARules(MatchResult& result, RuleSet* rules)
659 {
660     m_state.matchedRules().clear();
661     
662     result.ranges.lastUARule = result.matchedProperties.size() - 1;
663     RuleRange ruleRange = result.ranges.UARuleRange();
664     collectMatchingRules(MatchRequest(rules), ruleRange);
665
666     sortAndTransferMatchedRules(result);
667 }
668
669 void StyleResolver::collectMatchingRulesForList(const Vector<RuleData>* rules, const MatchRequest& matchRequest, RuleRange& ruleRange)
670 {
671     if (!rules)
672         return;
673
674     State& state = m_state;
675     // In some cases we may end up looking up style for random elements in the middle of a recursive tree resolve.
676     // Ancestor identifier filter won't be up-to-date in that case and we can't use the fast path.
677     bool canUseFastReject = m_selectorFilter.parentStackIsConsistent(state.parentNode()) && matchRequest.behaviorAtBoundary == SelectorChecker::DoesNotCrossBoundary;
678
679     unsigned size = rules->size();
680     for (unsigned i = 0; i < size; ++i) {
681         const RuleData& ruleData = rules->at(i);
682         if (canUseFastReject && m_selectorFilter.fastRejectSelector<RuleData::maximumIdentifierCount>(ruleData.descendantSelectorIdentifierHashes()))
683             continue;
684
685         StyleRule* rule = ruleData.rule();
686         InspectorInstrumentationCookie cookie = InspectorInstrumentation::willMatchRule(document(), rule, this);
687         PseudoId dynamicPseudo = NOPSEUDO;
688         if (ruleMatches(ruleData, matchRequest.scope, dynamicPseudo, matchRequest.behaviorAtBoundary)) {
689             // If the rule has no properties to apply, then ignore it in the non-debug mode.
690             const StylePropertySet* properties = rule->properties();
691             if (!properties || (properties->isEmpty() && !matchRequest.includeEmptyRules)) {
692                 InspectorInstrumentation::didMatchRule(cookie, false);
693                 continue;
694             }
695             // FIXME: Exposing the non-standard getMatchedCSSRules API to web is the only reason this is needed.
696             if (state.isSameOriginOnly() && !ruleData.hasDocumentSecurityOrigin()) {
697                 InspectorInstrumentation::didMatchRule(cookie, false);
698                 continue;
699             }
700             // If we're matching normal rules, set a pseudo bit if
701             // we really just matched a pseudo-element.
702             if (dynamicPseudo != NOPSEUDO && state.pseudoStyleRequest().pseudoId == NOPSEUDO) {
703                 if (state.mode() == SelectorChecker::CollectingRules) {
704                     InspectorInstrumentation::didMatchRule(cookie, false);
705                     continue;
706                 }
707                 if (dynamicPseudo < FIRST_INTERNAL_PSEUDOID)
708                     state.style()->setHasPseudoStyle(dynamicPseudo);
709             } else {
710                 // Update our first/last rule indices in the matched rules array.
711                 ++ruleRange.lastRuleIndex;
712                 if (ruleRange.firstRuleIndex == -1)
713                     ruleRange.firstRuleIndex = ruleRange.lastRuleIndex;
714
715                 // Add this rule to our list of matched rules.
716                 m_state.addMatchedRule(&ruleData);
717                 InspectorInstrumentation::didMatchRule(cookie, true);
718                 continue;
719             }
720         }
721         InspectorInstrumentation::didMatchRule(cookie, false);
722     }
723 }
724
725 static inline bool compareRules(const RuleData* r1, const RuleData* r2)
726 {
727     unsigned specificity1 = r1->specificity();
728     unsigned specificity2 = r2->specificity();
729     return (specificity1 == specificity2) ? r1->position() < r2->position() : specificity1 < specificity2;
730 }
731
732 void StyleResolver::sortMatchedRules()
733 {
734     std::sort(m_state.matchedRules().begin(), m_state.matchedRules().end(), compareRules);
735 }
736
737 void StyleResolver::matchAllRules(MatchResult& result, bool includeSMILProperties)
738 {
739     matchUARules(result);
740
741     // Now we check user sheet rules.
742     if (m_matchAuthorAndUserStyles)
743         matchUserRules(result, false);
744
745     // Now check author rules, beginning first with presentational attributes mapped from HTML.
746     if (m_state.styledElement()) {
747         addElementStyleProperties(result, m_state.styledElement()->presentationAttributeStyle());
748
749         // Now we check additional mapped declarations.
750         // Tables and table cells share an additional mapped rule that must be applied
751         // after all attributes, since their mapped style depends on the values of multiple attributes.
752         addElementStyleProperties(result, m_state.styledElement()->additionalPresentationAttributeStyle());
753
754         if (m_state.styledElement()->isHTMLElement()) {
755             bool isAuto;
756             TextDirection textDirection = toHTMLElement(m_state.styledElement())->directionalityIfhasDirAutoAttribute(isAuto);
757             if (isAuto)
758                 addMatchedProperties(result, textDirection == LTR ? leftToRightDeclaration() : rightToLeftDeclaration());
759         }
760     }
761     
762     // Check the rules in author sheets next.
763     if (m_matchAuthorAndUserStyles)
764         matchAuthorRules(result, false);
765
766     // Now check our inline style attribute.
767     if (m_matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->inlineStyle()) {
768         // Inline style is immutable as long as there is no CSSOM wrapper.
769         // FIXME: Media control shadow trees seem to have problems with caching.
770         bool isInlineStyleCacheable = !m_state.styledElement()->inlineStyle()->isMutable() && !m_state.styledElement()->isInShadowTree();
771         // FIXME: Constify.
772         addElementStyleProperties(result, m_state.styledElement()->inlineStyle(), isInlineStyleCacheable);
773     }
774
775 #if ENABLE(SVG)
776     // Now check SMIL animation override style.
777     if (includeSMILProperties && m_matchAuthorAndUserStyles && m_state.styledElement() && m_state.styledElement()->isSVGElement())
778         addElementStyleProperties(result, static_cast<SVGElement*>(m_state.styledElement())->animatedSMILStyleProperties(), false /* isCacheable */);
779 #else
780     UNUSED_PARAM(includeSMILProperties);
781 #endif
782 }
783
784 bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
785 {
786     for (unsigned i = 0; i < classNames.size(); ++i) {
787         if (m_ruleSets.features().classesInRules.contains(classNames[i].impl()))
788             return true;
789     }
790     return false;
791 }
792
793 inline void StyleResolver::State::initElement(Element* e)
794 {
795     m_element = e;
796     m_styledElement = e && e->isStyledElement() ? static_cast<StyledElement*>(e) : 0;
797     m_elementLinkState = e ? e->document()->visitedLinkState()->determineLinkState(e) : NotInsideLink;
798 }
799
800 inline void StyleResolver::initElement(Element* e)
801 {
802     if (m_state.element() != e) {
803         m_state.initElement(e);
804         if (e && e == e->document()->documentElement()) {
805             e->document()->setDirectionSetOnDocumentElement(false);
806             e->document()->setWritingModeSetOnDocumentElement(false);
807         }
808     }
809 }
810
811 inline void StyleResolver::State::initForStyleResolve(Document* document, Element* e, RenderStyle* parentStyle, const PseudoStyleRequest& pseudoStyleRequest, RenderRegion* regionForStyling)
812 {
813     m_pseudoStyleRequest = pseudoStyleRequest;
814     m_regionForStyling = regionForStyling;
815
816     if (e) {
817         NodeRenderingContext context(e);
818         m_parentNode = context.parentNodeForRenderingAndStyle();
819         m_parentStyle = context.resetStyleInheritance() ? 0 :
820             parentStyle ? parentStyle :
821             m_parentNode ? m_parentNode->renderStyle() : 0;
822         m_distributedToInsertionPoint = context.insertionPoint();
823     } else {
824         m_parentNode = 0;
825         m_parentStyle = parentStyle;
826         m_distributedToInsertionPoint = false;
827     }
828
829     Node* docElement = e ? e->document()->documentElement() : 0;
830     RenderStyle* docStyle = document->renderStyle();
831     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
832
833     m_style = 0;
834     m_pendingImageProperties.clear();
835     m_ruleList = 0;
836     m_fontDirty = false;
837 }
838
839 static const unsigned cStyleSearchThreshold = 10;
840 static const unsigned cStyleSearchLevelThreshold = 10;
841
842 static inline bool parentElementPreventsSharing(const Element* parentElement)
843 {
844     if (!parentElement)
845         return false;
846     return parentElement->hasFlagsSetDuringStylingOfChildren();
847 }
848
849 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
850 {
851     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
852         return 0;
853     if (!parent || !parent->isStyledElement())
854         return 0;
855     if (parent->hasScopedHTMLStyleChild())
856         return 0;
857     StyledElement* p = static_cast<StyledElement*>(parent);
858     if (p->inlineStyle())
859         return 0;
860 #if ENABLE(SVG)
861     if (p->isSVGElement() && static_cast<SVGElement*>(p)->animatedSMILStyleProperties())
862         return 0;
863 #endif
864     if (p->hasID() && m_ruleSets.features().idsInRules.contains(p->idForStyleResolution().impl()))
865         return 0;
866
867     RenderStyle* parentStyle = p->renderStyle();
868     unsigned subcount = 0;
869     Node* thisCousin = p;
870     Node* currentNode = p->previousSibling();
871
872     // Reserve the tries for this level. This effectively makes sure that the algorithm
873     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
874     visitedNodeCount += cStyleSearchThreshold;
875     while (thisCousin) {
876         while (currentNode) {
877             ++subcount;
878             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()
879                 && currentNode->isElementNode() && !parentElementPreventsSharing(toElement(currentNode))
880 #if ENABLE(SHADOW_DOM)
881                 && !toElement(currentNode)->shadow()
882 #endif
883                 ) {
884                 // Adjust for unused reserved tries.
885                 visitedNodeCount -= cStyleSearchThreshold - subcount;
886                 return currentNode->lastChild();
887             }
888             if (subcount >= cStyleSearchThreshold)
889                 return 0;
890             currentNode = currentNode->previousSibling();
891         }
892         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
893         thisCousin = currentNode;
894     }
895
896     return 0;
897 }
898
899 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
900 {
901     if (!ruleSet)
902         return false;
903     m_state.matchedRules().clear();
904
905     m_state.setMode(SelectorChecker::SharingRules);
906     int firstRuleIndex = -1, lastRuleIndex = -1;
907     RuleRange ruleRange(firstRuleIndex, lastRuleIndex);
908     collectMatchingRules(MatchRequest(ruleSet), ruleRange);
909     m_state.setMode(SelectorChecker::ResolvingStyle);
910     if (m_state.matchedRules().isEmpty())
911         return false;
912     m_state.matchedRules().clear();
913     return true;
914 }
915
916 bool StyleResolver::canShareStyleWithControl(StyledElement* element) const
917 {
918     const State& state = m_state;
919     HTMLInputElement* thisInputElement = element->toInputElement();
920     HTMLInputElement* otherInputElement = state.element()->toInputElement();
921
922     if (!thisInputElement || !otherInputElement)
923         return false;
924
925     if (thisInputElement->elementData() != otherInputElement->elementData()) {
926         if (thisInputElement->fastGetAttribute(typeAttr) != otherInputElement->fastGetAttribute(typeAttr))
927             return false;
928         if (thisInputElement->fastGetAttribute(readonlyAttr) != otherInputElement->fastGetAttribute(readonlyAttr))
929             return false;
930     }
931
932     if (thisInputElement->isAutofilled() != otherInputElement->isAutofilled())
933         return false;
934     if (thisInputElement->shouldAppearChecked() != otherInputElement->shouldAppearChecked())
935         return false;
936     if (thisInputElement->isIndeterminate() != otherInputElement->isIndeterminate())
937         return false;
938     if (thisInputElement->isRequired() != otherInputElement->isRequired())
939         return false;
940
941     if (element->isEnabledFormControl() != state.element()->isEnabledFormControl())
942         return false;
943
944     if (element->isDefaultButtonForForm() != state.element()->isDefaultButtonForForm())
945         return false;
946
947     if (state.document()->containsValidityStyleRules()) {
948         bool willValidate = element->willValidate();
949
950         if (willValidate != state.element()->willValidate())
951             return false;
952
953         if (willValidate && (element->isValidFormControlElement() != state.element()->isValidFormControlElement()))
954             return false;
955
956         if (element->isInRange() != state.element()->isInRange())
957             return false;
958
959         if (element->isOutOfRange() != state.element()->isOutOfRange())
960             return false;
961     }
962
963     return true;
964 }
965
966 static inline bool elementHasDirectionAuto(Element* element)
967 {
968     // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
969     return element->isHTMLElement() && toHTMLElement(element)->hasDirectionAuto();
970 }
971
972 bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement* sharingCandidate) const
973 {
974     const State& state = m_state;
975     if (state.element()->elementData() == sharingCandidate->elementData())
976         return true;
977     if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate->fastGetAttribute(XMLNames::langAttr))
978         return false;
979     if (state.element()->fastGetAttribute(langAttr) != sharingCandidate->fastGetAttribute(langAttr))
980         return false;
981
982     if (!state.elementAffectedByClassRules()) {
983         if (sharingCandidate->hasClass() && classNamesAffectedByRules(sharingCandidate->classNames()))
984             return false;
985     } else if (sharingCandidate->hasClass()) {
986 #if ENABLE(SVG)
987         // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
988         if (state.element()->isSVGElement()) {
989             if (state.element()->getAttribute(classAttr) != sharingCandidate->getAttribute(classAttr))
990                 return false;
991         } else {
992 #endif
993             if (state.element()->classNames() != sharingCandidate->classNames())
994                 return false;
995 #if ENABLE(SVG)
996         }
997 #endif
998     } else
999         return false;
1000
1001     if (state.styledElement()->presentationAttributeStyle() != sharingCandidate->presentationAttributeStyle())
1002         return false;
1003
1004 #if ENABLE(PROGRESS_ELEMENT)
1005     if (state.element()->hasTagName(progressTag)) {
1006         if (static_cast<HTMLProgressElement*>(state.element())->isDeterminate() != static_cast<HTMLProgressElement*>(sharingCandidate)->isDeterminate())
1007             return false;
1008     }
1009 #endif
1010
1011     return true;
1012 }
1013
1014 bool StyleResolver::canShareStyleWithElement(StyledElement* element) const
1015 {
1016     RenderStyle* style = element->renderStyle();
1017     const State& state = m_state;
1018
1019     if (!style)
1020         return false;
1021     if (style->unique())
1022         return false;
1023     if (style->hasUniquePseudoStyle())
1024         return false;
1025     if (element->tagQName() != state.element()->tagQName())
1026         return false;
1027     if (element->inlineStyle())
1028         return false;
1029     if (element->needsStyleRecalc())
1030         return false;
1031 #if ENABLE(SVG)
1032     if (element->isSVGElement() && static_cast<SVGElement*>(element)->animatedSMILStyleProperties())
1033         return false;
1034 #endif
1035     if (element->isLink() != state.element()->isLink())
1036         return false;
1037     if (element->hovered() != state.element()->hovered())
1038         return false;
1039     if (element->active() != state.element()->active())
1040         return false;
1041     if (element->focused() != state.element()->focused())
1042         return false;
1043     if (element->shadowPseudoId() != state.element()->shadowPseudoId())
1044         return false;
1045     if (element == element->document()->cssTarget())
1046         return false;
1047     if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element))
1048         return false;
1049     if (element->additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle())
1050         return false;
1051
1052     if (element->hasID() && m_ruleSets.features().idsInRules.contains(element->idForStyleResolution().impl()))
1053         return false;
1054     if (element->hasScopedHTMLStyleChild())
1055         return false;
1056
1057     // FIXME: We should share style for option and optgroup whenever possible.
1058     // Before doing so, we need to resolve issues in HTMLSelectElement::recalcListItems
1059     // and RenderMenuList::setText. See also https://bugs.webkit.org/show_bug.cgi?id=88405
1060     if (element->hasTagName(optionTag) || element->hasTagName(optgroupTag))
1061         return false;
1062
1063     bool isControl = element->isFormControlElement();
1064
1065     if (isControl != state.element()->isFormControlElement())
1066         return false;
1067
1068     if (isControl && !canShareStyleWithControl(element))
1069         return false;
1070
1071     if (style->transitions() || style->animations())
1072         return false;
1073
1074 #if USE(ACCELERATED_COMPOSITING)
1075     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
1076     // See comments in RenderObject::setStyle().
1077     if (element->hasTagName(iframeTag) || element->hasTagName(frameTag) || element->hasTagName(embedTag) || element->hasTagName(objectTag) || element->hasTagName(appletTag) || element->hasTagName(canvasTag)
1078 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
1079         // With proxying, the media elements are backed by a RenderEmbeddedObject.
1080         || element->hasTagName(videoTag) || element->hasTagName(audioTag)
1081 #endif
1082         )
1083         return false;
1084 #endif
1085
1086     if (elementHasDirectionAuto(element))
1087         return false;
1088
1089     if (element->isLink() && state.elementLinkState() != style->insideLink())
1090         return false;
1091
1092 #if ENABLE(VIDEO_TRACK)
1093     // Deny sharing styles between WebVTT and non-WebVTT nodes.
1094     if (element->isWebVTTElement() != state.element()->isWebVTTElement())
1095         return false;
1096
1097     if (element->isWebVTTElement() && state.element()->isWebVTTElement() && toWebVTTElement(element)->isPastNode() != toWebVTTElement(state.element())->isPastNode())
1098         return false;
1099 #endif
1100
1101 #if ENABLE(FULLSCREEN_API)
1102     if (element == element->document()->webkitCurrentFullScreenElement() || state.element() == state.document()->webkitCurrentFullScreenElement())
1103         return false;
1104 #endif
1105     return true;
1106 }
1107
1108 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
1109 {
1110     for (; node; node = node->previousSibling()) {
1111         if (!node->isStyledElement())
1112             continue;
1113         if (canShareStyleWithElement(static_cast<StyledElement*>(node)))
1114             break;
1115         if (count++ == cStyleSearchThreshold)
1116             return 0;
1117     }
1118     return static_cast<StyledElement*>(node);
1119 }
1120
1121 RenderStyle* StyleResolver::locateSharedStyle()
1122 {
1123     State& state = m_state;
1124     if (!state.styledElement() || !state.parentStyle())
1125         return 0;
1126
1127     // If the element has inline style it is probably unique.
1128     if (state.styledElement()->inlineStyle())
1129         return 0;
1130 #if ENABLE(SVG)
1131     if (state.styledElement()->isSVGElement() && static_cast<SVGElement*>(state.styledElement())->animatedSMILStyleProperties())
1132         return 0;
1133 #endif
1134     // Ids stop style sharing if they show up in the stylesheets.
1135     if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl()))
1136         return 0;
1137     if (parentElementPreventsSharing(state.element()->parentElement()))
1138         return 0;
1139     if (state.styledElement()->hasScopedHTMLStyleChild())
1140         return 0;
1141     if (state.element() == state.document()->cssTarget())
1142         return 0;
1143     if (elementHasDirectionAuto(state.element()))
1144         return 0;
1145
1146     // Cache whether state.element is affected by any known class selectors.
1147     // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
1148     state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames()));
1149
1150     // Check previous siblings and their cousins.
1151     unsigned count = 0;
1152     unsigned visitedNodeCount = 0;
1153     StyledElement* shareElement = 0;
1154     Node* cousinList = state.styledElement()->previousSibling();
1155     while (cousinList) {
1156         shareElement = findSiblingForStyleSharing(cousinList, count);
1157         if (shareElement)
1158             break;
1159         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
1160     }
1161
1162     // If we have exhausted all our budget or our cousins.
1163     if (!shareElement)
1164         return 0;
1165
1166     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
1167     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling()))
1168         return 0;
1169     // Can't share if attribute rules apply.
1170     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute()))
1171         return 0;
1172     // Can't share if @host @-rules apply.
1173     if (styleSharingCandidateMatchesHostRules())
1174         return 0;
1175     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
1176     if (parentElementPreventsSharing(state.element()->parentElement()))
1177         return 0;
1178     return shareElement->renderStyle();
1179 }
1180
1181 void StyleResolver::matchUARules(MatchResult& result)
1182 {
1183     MatchingUARulesScope scope;
1184
1185     // First we match rules from the user agent sheet.
1186     if (CSSDefaultStyleSheets::simpleDefaultStyleSheet)
1187         result.isCacheable = false;
1188     RuleSet* userAgentStyleSheet = m_medium->mediaTypeMatchSpecific("print")
1189         ? CSSDefaultStyleSheets::defaultPrintStyle : CSSDefaultStyleSheets::defaultStyle;
1190     matchUARules(result, userAgentStyleSheet);
1191
1192     // In quirks mode, we match rules from the quirks user agent sheet.
1193     if (document()->inQuirksMode())
1194         matchUARules(result, CSSDefaultStyleSheets::defaultQuirksStyle);
1195
1196     // 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.
1197     if (document()->isViewSource())
1198         matchUARules(result, CSSDefaultStyleSheets::viewSourceStyle());
1199 }
1200
1201 static void setStylesForPaginationMode(Pagination::Mode paginationMode, RenderStyle* style)
1202 {
1203     if (paginationMode == Pagination::Unpaginated)
1204         return;
1205         
1206     switch (paginationMode) {
1207     case Pagination::LeftToRightPaginated:
1208         style->setColumnAxis(HorizontalColumnAxis);
1209         if (style->isHorizontalWritingMode())
1210             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1211         else
1212             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1213         break;
1214     case Pagination::RightToLeftPaginated:
1215         style->setColumnAxis(HorizontalColumnAxis);
1216         if (style->isHorizontalWritingMode())
1217             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1218         else
1219             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1220         break;
1221     case Pagination::TopToBottomPaginated:
1222         style->setColumnAxis(VerticalColumnAxis);
1223         if (style->isHorizontalWritingMode())
1224             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1225         else
1226             style->setColumnProgression(style->isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1227         break;
1228     case Pagination::BottomToTopPaginated:
1229         style->setColumnAxis(VerticalColumnAxis);
1230         if (style->isHorizontalWritingMode())
1231             style->setColumnProgression(style->isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1232         else
1233             style->setColumnProgression(style->isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1234         break;
1235     case Pagination::Unpaginated:
1236         ASSERT_NOT_REACHED();
1237         break;
1238     }
1239 }
1240
1241 static void getFontAndGlyphOrientation(const RenderStyle* style, FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
1242 {
1243     if (style->isHorizontalWritingMode()) {
1244         fontOrientation = Horizontal;
1245         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1246         return;
1247     }
1248
1249     switch (style->textOrientation()) {
1250     case TextOrientationVerticalRight:
1251         fontOrientation = Vertical;
1252         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1253         return;
1254     case TextOrientationUpright:
1255         fontOrientation = Vertical;
1256         glyphOrientation = NonCJKGlyphOrientationUpright;
1257         return;
1258     case TextOrientationSideways:
1259         if (style->writingMode() == LeftToRightWritingMode) {
1260             // FIXME: This should map to sideways-left, which is not supported yet.
1261             fontOrientation = Vertical;
1262             glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1263             return;
1264         }
1265         fontOrientation = Horizontal;
1266         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1267         return;
1268     case TextOrientationSidewaysRight:
1269         fontOrientation = Horizontal;
1270         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1271         return;
1272     default:
1273         ASSERT_NOT_REACHED();
1274         fontOrientation = Horizontal;
1275         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1276         return;
1277     }
1278 }
1279
1280 PassRefPtr<RenderStyle> StyleResolver::styleForDocument(Document* document, CSSFontSelector* fontSelector)
1281 {
1282     Frame* frame = document->frame();
1283
1284     // HTML5 states that seamless iframes should replace default CSS values
1285     // with values inherited from the containing iframe element. However,
1286     // some values (such as the case of designMode = "on") still need to
1287     // be set by this "document style".
1288     RefPtr<RenderStyle> documentStyle = RenderStyle::create();
1289     bool seamlessWithParent = document->shouldDisplaySeamlesslyWithParent();
1290     if (seamlessWithParent) {
1291         RenderStyle* iframeStyle = document->seamlessParentIFrame()->renderStyle();
1292         if (iframeStyle)
1293             documentStyle->inheritFrom(iframeStyle);
1294     }
1295
1296     // FIXME: It's not clear which values below we want to override in the seamless case!
1297     documentStyle->setDisplay(BLOCK);
1298     if (!seamlessWithParent) {
1299         documentStyle->setRTLOrdering(document->visuallyOrdered() ? VisualOrder : LogicalOrder);
1300         documentStyle->setZoom(frame && !document->printing() ? frame->pageZoomFactor() : 1);
1301         documentStyle->setPageScaleTransform(frame ? frame->frameScaleFactor() : 1);
1302         documentStyle->setLocale(document->contentLanguage());
1303     }
1304     // This overrides any -webkit-user-modify inherited from the parent iframe.
1305     documentStyle->setUserModify(document->inDesignMode() ? READ_WRITE : READ_ONLY);
1306
1307     Element* docElement = document->documentElement();
1308     RenderObject* docElementRenderer = docElement ? docElement->renderer() : 0;
1309     if (docElementRenderer) {
1310         // Use the direction and writing-mode of the body to set the
1311         // viewport's direction and writing-mode unless the property is set on the document element.
1312         // If there is no body, then use the document element.
1313         RenderObject* bodyRenderer = document->body() ? document->body()->renderer() : 0;
1314         if (bodyRenderer && !document->writingModeSetOnDocumentElement())
1315             documentStyle->setWritingMode(bodyRenderer->style()->writingMode());
1316         else
1317             documentStyle->setWritingMode(docElementRenderer->style()->writingMode());
1318         if (bodyRenderer && !document->directionSetOnDocumentElement())
1319             documentStyle->setDirection(bodyRenderer->style()->direction());
1320         else
1321             documentStyle->setDirection(docElementRenderer->style()->direction());
1322     }
1323
1324     if (frame) {
1325         if (FrameView* frameView = frame->view()) {
1326             const Pagination& pagination = frameView->pagination();
1327             if (pagination.mode != Pagination::Unpaginated) {
1328                 setStylesForPaginationMode(pagination.mode, documentStyle.get());
1329                 documentStyle->setColumnGap(pagination.gap);
1330                 if (RenderView* view = document->renderView()) {
1331                     if (view->hasColumns())
1332                         view->updateColumnInfoFromStyle(documentStyle.get());
1333                 }
1334             }
1335         }
1336     }
1337
1338     // Seamless iframes want to inherit their font from their parent iframe, so early return before setting the font.
1339     if (seamlessWithParent)
1340         return documentStyle.release();
1341
1342     FontDescription fontDescription;
1343     fontDescription.setScript(localeToScriptCodeForFontSelection(documentStyle->locale()));
1344     if (Settings* settings = document->settings()) {
1345         fontDescription.setUsePrinterFont(document->printing() || !settings->screenFontSubstitutionEnabled());
1346         fontDescription.setRenderingMode(settings->fontRenderingMode());
1347         const AtomicString& standardFont = settings->standardFontFamily(fontDescription.script());
1348         if (!standardFont.isEmpty()) {
1349             fontDescription.setGenericFamily(FontDescription::StandardFamily);
1350             fontDescription.firstFamily().setFamily(standardFont);
1351             fontDescription.firstFamily().appendFamily(0);
1352         }
1353         fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
1354         int size = StyleResolver::fontSizeForKeyword(document, CSSValueMedium, false);
1355         fontDescription.setSpecifiedSize(size);
1356         bool useSVGZoomRules = document->isSVGDocument();
1357         fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, documentStyle.get(), fontDescription.isAbsoluteSize(), size, useSVGZoomRules));
1358     } else
1359         fontDescription.setUsePrinterFont(document->printing());
1360
1361     FontOrientation fontOrientation;
1362     NonCJKGlyphOrientation glyphOrientation;
1363     getFontAndGlyphOrientation(documentStyle.get(), fontOrientation, glyphOrientation);
1364     fontDescription.setOrientation(fontOrientation);
1365     fontDescription.setNonCJKGlyphOrientation(glyphOrientation);
1366
1367     documentStyle->setFontDescription(fontDescription);
1368     documentStyle->font().update(fontSelector);
1369
1370     return documentStyle.release();
1371 }
1372
1373 static inline bool isAtShadowBoundary(const Element* element)
1374 {
1375     if (!element)
1376         return false;
1377     ContainerNode* parentNode = element->parentNode();
1378     return parentNode && parentNode->isShadowRoot();
1379 }
1380
1381 PassRefPtr<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
1382     StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, RenderRegion* regionForStyling)
1383 {
1384     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
1385     // will vanish if a style recalc happens during loading.
1386     if (sharingBehavior == AllowStyleSharing && !element->document()->haveStylesheetsLoaded() && !element->renderer()) {
1387         if (!s_styleNotYetAvailable) {
1388             s_styleNotYetAvailable = RenderStyle::create().leakRef();
1389             s_styleNotYetAvailable->setDisplay(NONE);
1390             s_styleNotYetAvailable->font().update(m_fontSelector);
1391         }
1392         element->document()->setHasNodesWithPlaceholderStyle();
1393         return s_styleNotYetAvailable;
1394     }
1395
1396     State& state = m_state;
1397     initElement(element);
1398     state.initForStyleResolve(document(), element, defaultParent, NOPSEUDO, regionForStyling);
1399     if (sharingBehavior == AllowStyleSharing && !state.distributedToInsertionPoint()) {
1400         RenderStyle* sharedStyle = locateSharedStyle();
1401         if (sharedStyle)
1402             return sharedStyle;
1403     }
1404
1405     RefPtr<RenderStyle> cloneForParent;
1406
1407     if (state.parentStyle()) {
1408         state.setStyle(RenderStyle::create());
1409         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
1410     } else {
1411         state.setStyle(defaultStyleForElement());
1412         cloneForParent = RenderStyle::clone(state.style());
1413         state.setParentStyle(cloneForParent.get());
1414     }
1415     // contenteditable attribute (implemented by -webkit-user-modify) should
1416     // be propagated from shadow host to distributed node.
1417     if (state.distributedToInsertionPoint()) {
1418         if (Element* parent = element->parentElement()) {
1419             if (RenderStyle* styleOfShadowHost = parent->renderStyle())
1420                 state.style()->setUserModify(styleOfShadowHost->userModify());
1421         }
1422     }
1423
1424     if (element->isLink()) {
1425         state.style()->setIsLink(true);
1426         EInsideLink linkState = state.elementLinkState();
1427         if (linkState != NotInsideLink) {
1428             bool forceVisited = InspectorInstrumentation::forcePseudoState(element, CSSSelector::PseudoVisited);
1429             if (forceVisited)
1430                 linkState = InsideVisitedLink;
1431         }
1432         state.style()->setInsideLink(linkState);
1433     }
1434
1435     bool needsCollection = false;
1436     CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(element, needsCollection);
1437     if (needsCollection)
1438         m_ruleSets.collectFeatures(document()->isViewSource(), m_scopeResolver.get());
1439
1440     MatchResult matchResult;
1441     if (matchingBehavior == MatchOnlyUserAgentRules)
1442         matchUARules(matchResult);
1443     else
1444         matchAllRules(matchResult, matchingBehavior != MatchAllRulesExcludingSMIL);
1445
1446     applyMatchedProperties(matchResult, element);
1447
1448     // Clean up our style object's display and text decorations (among other fixups).
1449     adjustRenderStyle(state.style(), state.parentStyle(), element);
1450
1451     state.clear(); // Clear out for the next resolve.
1452
1453     document()->didAccessStyleResolver();
1454
1455     // Now return the style.
1456     return state.takeStyle();
1457 }
1458
1459 PassRefPtr<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
1460 {
1461     MatchResult result;
1462     if (keyframe->properties())
1463         addMatchedProperties(result, keyframe->properties());
1464
1465     ASSERT(!m_state.style());
1466
1467     State& state = m_state;
1468
1469     // Create the style
1470     state.setStyle(RenderStyle::clone(elementStyle));
1471     state.setLineHeightValue(0);
1472
1473     // We don't need to bother with !important. Since there is only ever one
1474     // decl, there's nothing to override. So just add the first properties.
1475     bool inheritedOnly = false;
1476     if (keyframe->properties())
1477         applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1478
1479     // If our font got dirtied, go ahead and update it now.
1480     updateFont();
1481
1482     // Line-height is set when we are sure we decided on the font-size
1483     if (state.lineHeightValue())
1484         applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
1485
1486     // Now do rest of the properties.
1487     if (keyframe->properties())
1488         applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1489
1490     // If our font got dirtied by one of the non-essential font props,
1491     // go ahead and update it a second time.
1492     updateFont();
1493
1494     // Start loading resources referenced by this style.
1495     loadPendingResources();
1496     
1497     // Add all the animating properties to the keyframe.
1498     if (const StylePropertySet* styleDeclaration = keyframe->properties()) {
1499         unsigned propertyCount = styleDeclaration->propertyCount();
1500         for (unsigned i = 0; i < propertyCount; ++i) {
1501             CSSPropertyID property = styleDeclaration->propertyAt(i).id();
1502             // Timing-function within keyframes is special, because it is not animated; it just
1503             // describes the timing function between this keyframe and the next.
1504             if (property != CSSPropertyWebkitAnimationTimingFunction)
1505                 keyframeValue.addProperty(property);
1506         }
1507     }
1508
1509     document()->didAccessStyleResolver();
1510
1511     return state.takeStyle();
1512 }
1513
1514 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
1515 {
1516     list.clear();
1517
1518     // Get the keyframesRule for this name
1519     if (!e || list.animationName().isEmpty())
1520         return;
1521
1522     m_keyframesRuleMap.checkConsistency();
1523
1524     KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
1525     if (it == m_keyframesRuleMap.end())
1526         return;
1527
1528     const StyleRuleKeyframes* keyframesRule = it->value.get();
1529
1530     // Construct and populate the style for each keyframe
1531     const Vector<RefPtr<StyleKeyframe> >& keyframes = keyframesRule->keyframes();
1532     for (unsigned i = 0; i < keyframes.size(); ++i) {
1533         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
1534         initElement(e);
1535         m_state.initForStyleResolve(document(), e);
1536
1537         const StyleKeyframe* keyframe = keyframes[i].get();
1538
1539         KeyframeValue keyframeValue(0, 0);
1540         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
1541
1542         // Add this keyframe style to all the indicated key times
1543         Vector<float> keys;
1544         keyframe->getKeys(keys);
1545         for (size_t keyIndex = 0; keyIndex < keys.size(); ++keyIndex) {
1546             keyframeValue.setKey(keys[keyIndex]);
1547             list.insert(keyframeValue);
1548         }
1549     }
1550
1551     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
1552     int initialListSize = list.size();
1553     if (initialListSize > 0 && list[0].key()) {
1554         static StyleKeyframe* zeroPercentKeyframe;
1555         if (!zeroPercentKeyframe) {
1556             zeroPercentKeyframe = StyleKeyframe::create().leakRef();
1557             zeroPercentKeyframe->setKeyText("0%");
1558         }
1559         KeyframeValue keyframeValue(0, 0);
1560         keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
1561         list.insert(keyframeValue);
1562     }
1563
1564     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
1565     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
1566         static StyleKeyframe* hundredPercentKeyframe;
1567         if (!hundredPercentKeyframe) {
1568             hundredPercentKeyframe = StyleKeyframe::create().leakRef();
1569             hundredPercentKeyframe->setKeyText("100%");
1570         }
1571         KeyframeValue keyframeValue(1, 0);
1572         keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
1573         list.insert(keyframeValue);
1574     }
1575 }
1576
1577 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* e, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
1578 {
1579     ASSERT(parentStyle);
1580     if (!e)
1581         return 0;
1582
1583     State& state = m_state;
1584
1585     initElement(e);
1586
1587     state.initForStyleResolve(document(), e, parentStyle, pseudoStyleRequest);
1588     state.setStyle(RenderStyle::create());
1589     state.style()->inheritFrom(m_state.parentStyle());
1590
1591     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
1592     // those rules.
1593
1594     // Check UA, user and author rules.
1595     MatchResult matchResult;
1596     matchUARules(matchResult);
1597
1598     if (m_matchAuthorAndUserStyles) {
1599         matchUserRules(matchResult, false);
1600         matchAuthorRules(matchResult, false);
1601     }
1602
1603     if (matchResult.matchedProperties.isEmpty())
1604         return 0;
1605
1606     state.style()->setStyleType(pseudoStyleRequest.pseudoId);
1607
1608     applyMatchedProperties(matchResult, e);
1609
1610     // Clean up our style object's display and text decorations (among other fixups).
1611     adjustRenderStyle(state.style(), m_state.parentStyle(), 0);
1612
1613     // Start loading resources referenced by this style.
1614     loadPendingResources();
1615
1616     document()->didAccessStyleResolver();
1617
1618     // Now return the style.
1619     return state.takeStyle();
1620 }
1621
1622 PassRefPtr<RenderStyle> StyleResolver::styleForPage(int pageIndex)
1623 {
1624     m_state.initForStyleResolve(document(), document()->documentElement()); // m_rootElementStyle will be set to the document style.
1625
1626     m_state.setStyle(RenderStyle::create());
1627     m_state.style()->inheritFrom(m_state.rootElementStyle());
1628
1629     const bool isLeft = isLeftPage(pageIndex);
1630     const bool isFirst = isFirstPage(pageIndex);
1631     const String page = pageName(pageIndex);
1632     
1633     MatchResult result;
1634     matchPageRules(result, CSSDefaultStyleSheets::defaultPrintStyle, isLeft, isFirst, page);
1635     matchPageRules(result, m_ruleSets.userStyle(), isLeft, isFirst, page);
1636     // Only consider the global author RuleSet for @page rules, as per the HTML5 spec.
1637     matchPageRules(result, m_ruleSets.authorStyle(), isLeft, isFirst, page);
1638     m_state.setLineHeightValue(0);
1639     bool inheritedOnly = false;
1640 #if ENABLE(CSS_VARIABLES)
1641     applyMatchedProperties<VariableDefinitions>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1642 #endif
1643     applyMatchedProperties<HighPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1644
1645     // If our font got dirtied, go ahead and update it now.
1646     updateFont();
1647
1648     // Line-height is set when we are sure we decided on the font-size.
1649     if (m_state.lineHeightValue())
1650         applyProperty(CSSPropertyLineHeight, m_state.lineHeightValue());
1651
1652     applyMatchedProperties<LowPriorityProperties>(result, false, 0, result.matchedProperties.size() - 1, inheritedOnly);
1653
1654     // Start loading resources referenced by this style.
1655     loadPendingResources();
1656
1657     document()->didAccessStyleResolver();
1658
1659     // Now return the style.
1660     return m_state.takeStyle();
1661 }
1662
1663 PassRefPtr<RenderStyle> StyleResolver::defaultStyleForElement()
1664 {
1665     m_state.setStyle(RenderStyle::create());
1666     // Make sure our fonts are initialized if we don't inherit them from our parent style.
1667     if (Settings* settings = documentSettings()) {
1668         initializeFontStyle(settings);
1669         m_state.style()->font().update(fontSelector());
1670     } else
1671         m_state.style()->font().update(0);
1672
1673     return m_state.takeStyle();
1674 }
1675
1676 PassRefPtr<RenderStyle> StyleResolver::styleForText(Text* textNode)
1677 {
1678     ASSERT(textNode);
1679
1680     NodeRenderingContext context(textNode);
1681     Node* parentNode = context.parentNodeForRenderingAndStyle();
1682     return context.resetStyleInheritance() || !parentNode ?
1683         defaultStyleForElement() : parentNode->renderStyle();
1684 }
1685
1686 static void addIntrinsicMargins(RenderStyle* style)
1687 {
1688     // Intrinsic margin value.
1689     const int intrinsicMargin = 2 * style->effectiveZoom();
1690
1691     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1692     // FIXME: Using "quirk" to decide the margin wasn't set is kind of lame.
1693     if (style->width().isIntrinsicOrAuto()) {
1694         if (style->marginLeft().quirk())
1695             style->setMarginLeft(Length(intrinsicMargin, Fixed));
1696         if (style->marginRight().quirk())
1697             style->setMarginRight(Length(intrinsicMargin, Fixed));
1698     }
1699
1700     if (style->height().isAuto()) {
1701         if (style->marginTop().quirk())
1702             style->setMarginTop(Length(intrinsicMargin, Fixed));
1703         if (style->marginBottom().quirk())
1704             style->setMarginBottom(Length(intrinsicMargin, Fixed));
1705     }
1706 }
1707
1708 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
1709 {
1710     switch (display) {
1711     case BLOCK:
1712     case TABLE:
1713     case BOX:
1714     case FLEX:
1715     case GRID:
1716         return display;
1717
1718     case LIST_ITEM:
1719         // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
1720         if (!strictParsing && isFloating)
1721             return BLOCK;
1722         return display;
1723     case INLINE_TABLE:
1724         return TABLE;
1725     case INLINE_BOX:
1726         return BOX;
1727     case INLINE_FLEX:
1728         return FLEX;
1729     case INLINE_GRID:
1730         return GRID;
1731
1732     case INLINE:
1733     case RUN_IN:
1734     case COMPACT:
1735     case INLINE_BLOCK:
1736     case TABLE_ROW_GROUP:
1737     case TABLE_HEADER_GROUP:
1738     case TABLE_FOOTER_GROUP:
1739     case TABLE_ROW:
1740     case TABLE_COLUMN_GROUP:
1741     case TABLE_COLUMN:
1742     case TABLE_CELL:
1743     case TABLE_CAPTION:
1744         return BLOCK;
1745     case NONE:
1746         ASSERT_NOT_REACHED();
1747         return NONE;
1748     }
1749     ASSERT_NOT_REACHED();
1750     return BLOCK;
1751 }
1752
1753 // CSS requires text-decoration to be reset at each DOM element for tables, 
1754 // inline blocks, inline tables, run-ins, shadow DOM crossings, floating elements,
1755 // and absolute or relatively positioned elements.
1756 static bool doesNotInheritTextDecoration(RenderStyle* style, Element* e)
1757 {
1758     return style->display() == TABLE || style->display() == INLINE_TABLE || style->display() == RUN_IN
1759         || style->display() == INLINE_BLOCK || style->display() == INLINE_BOX || isAtShadowBoundary(e)
1760         || style->isFloating() || style->hasOutOfFlowPosition();
1761 }
1762
1763 static bool isDisplayFlexibleBox(EDisplay display)
1764 {
1765     return display == FLEX || display == INLINE_FLEX;
1766 }
1767
1768 void StyleResolver::adjustRenderStyle(RenderStyle* style, RenderStyle* parentStyle, Element *e)
1769 {
1770     ASSERT(parentStyle);
1771
1772     // Cache our original display.
1773     style->setOriginalDisplay(style->display());
1774
1775     if (style->display() != NONE) {
1776         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1777         // property.
1778         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1779         // these tags to retain their display types.
1780         if (document()->inQuirksMode() && e) {
1781             if (e->hasTagName(tdTag)) {
1782                 style->setDisplay(TABLE_CELL);
1783                 style->setFloating(NoFloat);
1784             } else if (e->hasTagName(tableTag))
1785                 style->setDisplay(style->isDisplayInlineType() ? INLINE_TABLE : TABLE);
1786         }
1787
1788         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1789             if (style->whiteSpace() == KHTML_NOWRAP) {
1790                 // Figure out if we are really nowrapping or if we should just
1791                 // use normal instead. If the width of the cell is fixed, then
1792                 // we don't actually use NOWRAP.
1793                 if (style->width().isFixed())
1794                     style->setWhiteSpace(NORMAL);
1795                 else
1796                     style->setWhiteSpace(NOWRAP);
1797             }
1798         }
1799
1800         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1801         if (e && e->hasTagName(tableTag) && (style->textAlign() == WEBKIT_LEFT || style->textAlign() == WEBKIT_CENTER || style->textAlign() == WEBKIT_RIGHT))
1802             style->setTextAlign(TASTART);
1803
1804         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1805         // fix a crash where a site tries to position these objects. They also never honor display.
1806         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1807             style->setPosition(StaticPosition);
1808             style->setDisplay(BLOCK);
1809         }
1810
1811         // Ruby text does not support float or position. This might change with evolution of the specification.
1812         if (e && e->hasTagName(rtTag)) {
1813             style->setPosition(StaticPosition);
1814             style->setFloating(NoFloat);
1815         }
1816
1817         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1818         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1819         if (e && e->hasTagName(thTag) && style->textAlign() == TASTART)
1820             style->setTextAlign(CENTER);
1821
1822         if (e && e->hasTagName(legendTag))
1823             style->setDisplay(BLOCK);
1824
1825         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1826         if (style->hasOutOfFlowPosition() || style->isFloating() || (e && e->document()->documentElement() == e))
1827             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document()->inQuirksMode()));
1828
1829         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1830         // clear how that should work.
1831         if (style->display() == INLINE && style->styleType() == NOPSEUDO && style->writingMode() != parentStyle->writingMode())
1832             style->setDisplay(INLINE_BLOCK);
1833
1834         // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
1835         // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
1836         // on some sites).
1837         if ((style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW_GROUP
1838             || style->display() == TABLE_FOOTER_GROUP || style->display() == TABLE_ROW)
1839             && style->hasInFlowPosition())
1840             style->setPosition(StaticPosition);
1841
1842         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1843         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1844         if (style->display() == TABLE_COLUMN || style->display() == TABLE_COLUMN_GROUP || style->display() == TABLE_FOOTER_GROUP
1845             || style->display() == TABLE_HEADER_GROUP || style->display() == TABLE_ROW || style->display() == TABLE_ROW_GROUP
1846             || style->display() == TABLE_CELL)
1847             style->setWritingMode(parentStyle->writingMode());
1848
1849         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1850         // of block-flow to anything other than TopToBottomWritingMode.
1851         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1852         if (style->writingMode() != TopToBottomWritingMode && (style->display() == BOX || style->display() == INLINE_BOX))
1853             style->setWritingMode(TopToBottomWritingMode);
1854
1855         if (isDisplayFlexibleBox(parentStyle->display())) {
1856             style->setFloating(NoFloat);
1857             style->setDisplay(equivalentBlockDisplay(style->display(), style->isFloating(), !document()->inQuirksMode()));
1858         }
1859
1860 #if ENABLE(DIALOG_ELEMENT)
1861         // Per the spec, position 'static' and 'relative' in the top layer compute to 'absolute'.
1862         if (e && e->isInTopLayer() && (style->position() == StaticPosition || style->position() == RelativePosition)) {
1863             style->setPosition(AbsolutePosition);
1864             style->setDisplay(BLOCK);
1865         }
1866 #endif
1867     }
1868
1869     // Make sure our z-index value is only applied if the object is positioned.
1870     if (style->position() == StaticPosition && !isDisplayFlexibleBox(parentStyle->display()))
1871         style->setHasAutoZIndex();
1872
1873     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1874     // cases where objects that should be blended as a single unit end up with a non-transparent
1875     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1876     if (style->hasAutoZIndex() && ((e && e->document()->documentElement() == e)
1877         || style->opacity() < 1.0f
1878         || style->hasTransformRelatedProperty()
1879         || style->hasMask()
1880         || style->clipPath()
1881         || style->boxReflect()
1882         || style->hasFilter()
1883         || style->hasBlendMode()
1884         || style->position() == StickyPosition
1885         || (style->position() == FixedPosition && e && e->document()->page() && e->document()->page()->settings()->fixedPositionCreatesStackingContext())
1886 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1887         // Touch overflow scrolling creates a stacking context.
1888         || ((style->overflowX() != OHIDDEN || style->overflowY() != OHIDDEN) && style->useTouchOverflowScrolling())
1889 #endif
1890 #if ENABLE(DIALOG_ELEMENT)
1891         || (e && e->isInTopLayer())
1892 #endif
1893         ))
1894         style->setZIndex(0);
1895
1896     // Textarea considers overflow visible as auto.
1897     if (e && e->hasTagName(textareaTag)) {
1898         style->setOverflowX(style->overflowX() == OVISIBLE ? OAUTO : style->overflowX());
1899         style->setOverflowY(style->overflowY() == OVISIBLE ? OAUTO : style->overflowY());
1900     }
1901
1902     if (doesNotInheritTextDecoration(style, e))
1903         style->setTextDecorationsInEffect(style->textDecoration());
1904     else
1905         style->addToTextDecorationsInEffect(style->textDecoration());
1906
1907     // If either overflow value is not visible, change to auto.
1908     if (style->overflowX() == OMARQUEE && style->overflowY() != OMARQUEE)
1909         style->setOverflowY(OMARQUEE);
1910     else if (style->overflowY() == OMARQUEE && style->overflowX() != OMARQUEE)
1911         style->setOverflowX(OMARQUEE);
1912     else if (style->overflowX() == OVISIBLE && style->overflowY() != OVISIBLE) {
1913         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
1914         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
1915         // default to auto so we can at least scroll through the pages.
1916         style->setOverflowX(OAUTO);
1917     } else if (style->overflowY() == OVISIBLE && style->overflowX() != OVISIBLE)
1918         style->setOverflowY(OAUTO);
1919
1920     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
1921     // styles are specified on a root element, then they will be incorporated in
1922     // StyleResolver::styleForDocument().
1923     if ((style->overflowY() == OPAGEDX || style->overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
1924         setStylesForPaginationMode(WebCore::paginationModeForRenderStyle(style), style);
1925
1926     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1927     // FIXME: Eventually table sections will support auto and scroll.
1928     if (style->display() == TABLE || style->display() == INLINE_TABLE
1929         || style->display() == TABLE_ROW_GROUP || style->display() == TABLE_ROW) {
1930         if (style->overflowX() != OVISIBLE && style->overflowX() != OHIDDEN)
1931             style->setOverflowX(OVISIBLE);
1932         if (style->overflowY() != OVISIBLE && style->overflowY() != OHIDDEN)
1933             style->setOverflowY(OVISIBLE);
1934     }
1935
1936     // Menulists should have visible overflow
1937     if (style->appearance() == MenulistPart) {
1938         style->setOverflowX(OVISIBLE);
1939         style->setOverflowY(OVISIBLE);
1940     }
1941
1942     // Cull out any useless layers and also repeat patterns into additional layers.
1943     style->adjustBackgroundLayers();
1944     style->adjustMaskLayers();
1945
1946     // Do the same for animations and transitions.
1947     style->adjustAnimations();
1948     style->adjustTransitions();
1949
1950     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1951     // alter fonts and heights/widths.
1952     if (e && e->isFormControlElement() && style->fontSize() >= 11) {
1953         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1954         // so we have to treat all image buttons as though they were explicitly sized.
1955         if (!e->hasTagName(inputTag) || !static_cast<HTMLInputElement*>(e)->isImageButton())
1956             addIntrinsicMargins(style);
1957     }
1958
1959     // Let the theme also have a crack at adjusting the style.
1960     if (style->hasAppearance())
1961         RenderTheme::defaultTheme()->adjustStyle(this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
1962
1963     // If we have first-letter pseudo style, do not share this style.
1964     if (style->hasPseudoStyle(FIRST_LETTER))
1965         style->setUnique();
1966
1967     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
1968     if (style->preserves3D() && (style->overflowX() != OVISIBLE
1969         || style->overflowY() != OVISIBLE
1970         || style->hasFilter()))
1971         style->setTransformStyle3D(TransformStyle3DFlat);
1972
1973     // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
1974     if (e && e->hasTagName(iframeTag) && style->display() == INLINE && static_cast<HTMLIFrameElement*>(e)->shouldDisplaySeamlessly())
1975         style->setDisplay(INLINE_BLOCK);
1976
1977 #if ENABLE(SVG)
1978     if (e && e->isSVGElement()) {
1979         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1980         if (style->overflowY() == OSCROLL)
1981             style->setOverflowY(OHIDDEN);
1982         else if (style->overflowY() == OAUTO)
1983             style->setOverflowY(OVISIBLE);
1984
1985         if (style->overflowX() == OSCROLL)
1986             style->setOverflowX(OHIDDEN);
1987         else if (style->overflowX() == OAUTO)
1988             style->setOverflowX(OVISIBLE);
1989
1990         // Only the root <svg> element in an SVG document fragment tree honors css position
1991         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1992             style->setPosition(RenderStyle::initialPosition());
1993
1994         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
1995         // not be scaled again.
1996         if (e->hasTagName(SVGNames::foreignObjectTag))
1997             style->setEffectiveZoom(RenderStyle::initialZoom());
1998     }
1999 #endif
2000 }
2001
2002 bool StyleResolver::checkRegionStyle(Element* regionElement)
2003 {
2004     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
2005     // so all region rules are global by default. Verify whether that can stand or needs changing.
2006
2007     unsigned rulesSize = m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.size();
2008     for (unsigned i = 0; i < rulesSize; ++i) {
2009         ASSERT(m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2010         if (checkRegionSelector(m_ruleSets.authorStyle()->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2011             return true;
2012     }
2013
2014     if (m_ruleSets.userStyle()) {
2015         rulesSize = m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.size();
2016         for (unsigned i = 0; i < rulesSize; ++i) {
2017             ASSERT(m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.at(i).ruleSet.get());
2018             if (checkRegionSelector(m_ruleSets.userStyle()->m_regionSelectorsAndRuleSets.at(i).selector, regionElement))
2019                 return true;
2020         }
2021     }
2022
2023     return false;
2024 }
2025
2026 static void checkForOrientationChange(RenderStyle* style)
2027 {
2028     FontOrientation fontOrientation;
2029     NonCJKGlyphOrientation glyphOrientation;
2030     getFontAndGlyphOrientation(style, fontOrientation, glyphOrientation);
2031
2032     const FontDescription& fontDescription = style->fontDescription();
2033     if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
2034         return;
2035
2036     FontDescription newFontDescription(fontDescription);
2037     newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
2038     newFontDescription.setOrientation(fontOrientation);
2039     style->setFontDescription(newFontDescription);
2040 }
2041
2042 void StyleResolver::updateFont()
2043 {
2044     if (!m_state.fontDirty())
2045         return;
2046
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 + 17, 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 #if ENABLE(SVG)
2535     case CSSPropertyFill:
2536     case CSSPropertyStroke:
2537 #endif
2538         return true;
2539     default:
2540         break;
2541     }
2542
2543     return false;
2544 }
2545
2546 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
2547 // FIXME: add incremental support for other region styling properties.
2548 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
2549 {
2550     switch (id) {
2551     case CSSPropertyBackgroundColor:
2552     case CSSPropertyColor:
2553         return true;
2554     default:
2555         break;
2556     }
2557
2558     return false;
2559 }
2560
2561 #if ENABLE(VIDEO_TRACK)
2562 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
2563 {
2564     switch (id) {
2565     case CSSPropertyBackground:
2566     case CSSPropertyBackgroundAttachment:
2567     case CSSPropertyBackgroundClip:
2568     case CSSPropertyBackgroundColor:
2569     case CSSPropertyBackgroundImage:
2570     case CSSPropertyBackgroundOrigin:
2571     case CSSPropertyBackgroundPosition:
2572     case CSSPropertyBackgroundPositionX:
2573     case CSSPropertyBackgroundPositionY:
2574     case CSSPropertyBackgroundRepeat:
2575     case CSSPropertyBackgroundRepeatX:
2576     case CSSPropertyBackgroundRepeatY:
2577     case CSSPropertyBackgroundSize:
2578     case CSSPropertyColor:
2579     case CSSPropertyFont:
2580     case CSSPropertyFontFamily:
2581     case CSSPropertyFontSize:
2582     case CSSPropertyFontStyle:
2583     case CSSPropertyFontVariant:
2584     case CSSPropertyFontWeight:
2585     case CSSPropertyLineHeight:
2586     case CSSPropertyOpacity:
2587     case CSSPropertyOutline:
2588     case CSSPropertyOutlineColor:
2589     case CSSPropertyOutlineOffset:
2590     case CSSPropertyOutlineStyle:
2591     case CSSPropertyOutlineWidth:
2592     case CSSPropertyVisibility:
2593     case CSSPropertyWhiteSpace:
2594     case CSSPropertyTextDecoration:
2595     case CSSPropertyTextShadow:
2596     case CSSPropertyBorderStyle:
2597         return true;
2598     default:
2599         break;
2600     }
2601     return false;
2602 }
2603 #endif
2604 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
2605 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
2606 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
2607 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
2608 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
2609 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
2610 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
2611 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
2612 bool StyleResolver::useSVGZoomRules()
2613 {
2614     return m_state.element() && m_state.element()->isSVGElement();
2615 }
2616
2617 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, Length& workingLength)
2618 {
2619     if (primitiveValue->getIdent() == CSSValueWebkitMinContent) {
2620         workingLength = Length(MinContent);
2621         return true;
2622     }
2623
2624     if (primitiveValue->getIdent() == CSSValueWebkitMaxContent) {
2625         workingLength = Length(MaxContent);
2626         return true;
2627     }
2628
2629     workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
2630     if (workingLength.isUndefined())
2631         return false;
2632
2633     if (primitiveValue->isLength())
2634         workingLength.setQuirk(primitiveValue->isQuirkValue());
2635
2636     return true;
2637 }
2638
2639 static bool createGridTrackMinMax(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, GridTrackSize& trackSize)
2640 {
2641     Pair* minMaxTrackBreadth = primitiveValue->getPairValue();
2642     if (!minMaxTrackBreadth) {
2643         Length workingLength;
2644         if (!createGridTrackBreadth(primitiveValue, state, workingLength))
2645             return false;
2646
2647         trackSize.setLength(workingLength);
2648         return true;
2649     }
2650
2651     Length minTrackBreadth;
2652     Length maxTrackBreadth;
2653     if (!createGridTrackBreadth(minMaxTrackBreadth->first(), state, minTrackBreadth) || !createGridTrackBreadth(minMaxTrackBreadth->second(), state, maxTrackBreadth))
2654         return false;
2655
2656     trackSize.setMinMax(minTrackBreadth, maxTrackBreadth);
2657     return true;
2658 }
2659
2660 static bool createGridTrackGroup(CSSValue* value, const StyleResolver::State& state, Vector<GridTrackSize>& trackSizes)
2661 {
2662     if (!value->isValueList())
2663         return false;
2664
2665     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2666         CSSValue* currValue = i.value();
2667         if (!currValue->isPrimitiveValue())
2668             return false;
2669
2670         GridTrackSize trackSize;
2671         if (!createGridTrackMinMax(static_cast<CSSPrimitiveValue*>(currValue), state, trackSize))
2672             return false;
2673
2674         trackSizes.append(trackSize);
2675     }
2676     return true;
2677 }
2678
2679 static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, const StyleResolver::State& state)
2680 {
2681     // Handle 'none'.
2682     if (value->isPrimitiveValue()) {
2683         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2684         return primitiveValue->getIdent() == CSSValueNone;
2685     }
2686
2687     return createGridTrackGroup(value, state, trackSizes);
2688 }
2689
2690
2691 static bool createGridPosition(CSSValue* value, GridPosition& position)
2692 {
2693     // For now, we only accept: <integer> | 'auto'
2694     if (!value->isPrimitiveValue())
2695         return false;
2696
2697     CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2698     if (primitiveValue->getIdent() == CSSValueAuto)
2699         return true;
2700
2701     ASSERT_WITH_SECURITY_IMPLICATION(primitiveValue->isNumber());
2702     position.setIntegerPosition(primitiveValue->getIntValue());
2703     return true;
2704 }
2705
2706 #if ENABLE(CSS_VARIABLES)
2707 static bool hasVariableReference(CSSValue* value)
2708 {
2709     if (value->isPrimitiveValue()) {
2710         CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
2711         return primitiveValue->hasVariableReference();
2712     }
2713
2714     if (value->isCalculationValue())
2715         return static_cast<CSSCalcValue*>(value)->hasVariableReference();
2716
2717     if (value->isReflectValue()) {
2718         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
2719         CSSPrimitiveValue* direction = reflectValue->direction();
2720         CSSPrimitiveValue* offset = reflectValue->offset();
2721         CSSValue* mask = reflectValue->mask();
2722         return (direction && hasVariableReference(direction)) || (offset && hasVariableReference(offset)) || (mask && hasVariableReference(mask));
2723     }
2724
2725     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2726         if (hasVariableReference(i.value()))
2727             return true;
2728     }
2729
2730     return false;
2731 }
2732
2733 void StyleResolver::resolveVariables(CSSPropertyID id, CSSValue* value, Vector<std::pair<CSSPropertyID, String> >& knownExpressions)
2734 {
2735     std::pair<CSSPropertyID, String> expression(id, value->serializeResolvingVariables(*m_state.style()->variables()));
2736
2737     if (knownExpressions.contains(expression))
2738         return; // cycle detected.
2739
2740     knownExpressions.append(expression);
2741
2742     // 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.
2743     RefPtr<StylePropertySet> resultSet = StylePropertySet::create();
2744     if (!CSSParser::parseValue(resultSet.get(), id, expression.second, false, document()))
2745         return; // expression failed to parse.
2746
2747     for (unsigned i = 0; i < resultSet->propertyCount(); i++) {
2748         StylePropertySet::PropertyReference property = resultSet->propertyAt(i);
2749         if (property.id() != CSSPropertyVariable && hasVariableReference(property.value()))
2750             resolveVariables(property.id(), property.value(), knownExpressions);
2751         else
2752             applyProperty(property.id(), property.value());
2753     }
2754 }
2755 #endif
2756
2757 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
2758 {
2759 #if ENABLE(CSS_VARIABLES)
2760     if (id != CSSPropertyVariable && hasVariableReference(value)) {
2761         Vector<std::pair<CSSPropertyID, String> > knownExpressions;
2762         resolveVariables(id, value, knownExpressions);
2763         return;
2764     }
2765 #endif
2766
2767     // CSS variables don't resolve shorthands at parsing time, so this should be *after* handling variables.
2768     ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
2769
2770     State& state = m_state;
2771     bool isInherit = state.parentNode() && value->isInheritedValue();
2772     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
2773
2774     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2775     ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
2776
2777     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2778         // Limit the properties that can be applied to only the ones honored by :visited.
2779         return;
2780     }
2781
2782     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
2783         state.parentStyle()->setHasExplicitlyInheritedProperties();
2784
2785 #if ENABLE(CSS_VARIABLES)
2786     if (id == CSSPropertyVariable) {
2787         ASSERT_WITH_SECURITY_IMPLICATION(value->isVariableValue());
2788         CSSVariableValue* variable = static_cast<CSSVariableValue*>(value);
2789         ASSERT(!variable->name().isEmpty());
2790         ASSERT(!variable->value().isEmpty());
2791         state.style()->setVariable(variable->name(), variable->value());
2792         return;
2793     }
2794 #endif
2795
2796     // Check lookup table for implementations and use when available.
2797     const PropertyHandler& handler = m_styleBuilder.propertyHandler(id);
2798     if (handler.isValid()) {
2799         if (isInherit)
2800             handler.applyInheritValue(id, this);
2801         else if (isInitial)
2802             handler.applyInitialValue(id, this);
2803         else
2804             handler.applyValue(id, this, value);
2805         return;
2806     }
2807
2808     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? static_cast<CSSPrimitiveValue*>(value) : 0;
2809
2810     float zoomFactor = state.style()->effectiveZoom();
2811
2812     // What follows is a list that maps the CSS properties into their corresponding front-end
2813     // RenderStyle values.
2814     switch (id) {
2815     // lists
2816     case CSSPropertyContent:
2817         // list of string, uri, counter, attr, i
2818         {
2819             // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2820             // note is a reminder that eventually "inherit" needs to be supported.
2821
2822             if (isInitial) {
2823                 state.style()->clearContent();
2824                 return;
2825             }
2826
2827             if (!value->isValueList())
2828                 return;
2829
2830             bool didSet = false;
2831             for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2832                 CSSValue* item = i.value();
2833                 if (item->isImageGeneratorValue()) {
2834                     if (item->isGradientValue())
2835                         state.style()->setContent(StyleGeneratedImage::create(static_cast<CSSGradientValue*>(item)->gradientWithStylesResolved(this).get()), didSet);
2836                     else
2837                         state.style()->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
2838                     didSet = true;
2839 #if ENABLE(CSS_IMAGE_SET)
2840                 } else if (item->isImageSetValue()) {
2841                     state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageSetValue*>(item)), didSet);
2842                     didSet = true;
2843 #endif
2844                 }
2845
2846                 if (item->isImageValue()) {
2847                     state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageValue*>(item)), didSet);
2848                     didSet = true;
2849                     continue;
2850                 }
2851
2852                 if (!item->isPrimitiveValue())
2853                     continue;
2854
2855                 CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2856
2857                 if (contentValue->isString()) {
2858                     state.style()->setContent(contentValue->getStringValue().impl(), didSet);
2859                     didSet = true;
2860                 } else if (contentValue->isAttr()) {
2861                     // FIXME: Can a namespace be specified for an attr(foo)?
2862                     if (state.style()->styleType() == NOPSEUDO)
2863                         state.style()->setUnique();
2864                     else
2865                         state.parentStyle()->setUnique();
2866                     QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2867                     const AtomicString& value = state.element()->getAttribute(attr);
2868                     state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2869                     didSet = true;
2870                     // register the fact that the attribute value affects the style
2871                     m_ruleSets.features().attrsInRules.add(attr.localName().impl());
2872                 } else if (contentValue->isCounter()) {
2873                     Counter* counterValue = contentValue->getCounterValue();
2874                     EListStyleType listStyleType = NoneListStyle;
2875                     int listStyleIdent = counterValue->listStyleIdent();
2876                     if (listStyleIdent != CSSValueNone)
2877                         listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2878                     OwnPtr<CounterContent> counter = adoptPtr(new CounterContent(counterValue->identifier(), listStyleType, counterValue->separator()));
2879                     state.style()->setContent(counter.release(), didSet);
2880                     didSet = true;
2881                 } else {
2882                     switch (contentValue->getIdent()) {
2883                     case CSSValueOpenQuote:
2884                         state.style()->setContent(OPEN_QUOTE, didSet);
2885                         didSet = true;
2886                         break;
2887                     case CSSValueCloseQuote:
2888                         state.style()->setContent(CLOSE_QUOTE, didSet);
2889                         didSet = true;
2890                         break;
2891                     case CSSValueNoOpenQuote:
2892                         state.style()->setContent(NO_OPEN_QUOTE, didSet);
2893                         didSet = true;
2894                         break;
2895                     case CSSValueNoCloseQuote:
2896                         state.style()->setContent(NO_CLOSE_QUOTE, didSet);
2897                         didSet = true;
2898                         break;
2899                     default:
2900                         // normal and none do not have any effect.
2901                         { }
2902                     }
2903                 }
2904             }
2905             if (!didSet)
2906                 state.style()->clearContent();
2907             return;
2908         }
2909     case CSSPropertyQuotes:
2910         if (isInherit) {
2911             state.style()->setQuotes(state.parentStyle()->quotes());
2912             return;
2913         }
2914         if (isInitial) {
2915             state.style()->setQuotes(0);
2916             return;
2917         }
2918         if (value->isValueList()) {
2919             CSSValueList* list = static_cast<CSSValueList*>(value);
2920             RefPtr<QuotesData> quotes = QuotesData::create();
2921             for (size_t i = 0; i < list->length(); i += 2) {
2922                 CSSValue* first = list->itemWithoutBoundsCheck(i);
2923                 // item() returns null if out of bounds so this is safe.
2924                 CSSValue* second = list->item(i + 1);
2925                 if (!second)
2926                     continue;
2927                 ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue());
2928                 ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue());
2929                 String startQuote = static_cast<CSSPrimitiveValue*>(first)->getStringValue();
2930                 String endQuote = static_cast<CSSPrimitiveValue*>(second)->getStringValue();
2931                 quotes->addPair(std::make_pair(startQuote, endQuote));
2932             }
2933             state.style()->setQuotes(quotes);
2934             return;
2935         }
2936         if (primitiveValue) {
2937             if (primitiveValue->getIdent() == CSSValueNone)
2938                 state.style()->setQuotes(QuotesData::create());
2939         }
2940         return;
2941     case CSSPropertyFontFamily: {
2942         // list of strings and ids
2943         if (isInherit) {
2944             FontDescription parentFontDescription = state.parentStyle()->fontDescription();
2945             FontDescription fontDescription = state.style()->fontDescription();
2946             fontDescription.setGenericFamily(parentFontDescription.genericFamily());
2947             fontDescription.setFamily(parentFontDescription.firstFamily());
2948             fontDescription.setIsSpecifiedFont(parentFontDescription.isSpecifiedFont());
2949             setFontDescription(fontDescription);
2950             return;
2951         }
2952
2953         if (isInitial) {
2954             FontDescription initialDesc = FontDescription();
2955             FontDescription fontDescription = state.style()->fontDescription();
2956             // We need to adjust the size to account for the generic family change from monospace
2957             // to non-monospace.
2958             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize())
2959                 setFontSize(fontDescription, fontSizeForKeyword(document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, false));
2960             fontDescription.setGenericFamily(initialDesc.genericFamily());
2961             if (!initialDesc.firstFamily().familyIsEmpty())
2962                 fontDescription.setFamily(initialDesc.firstFamily());
2963             setFontDescription(fontDescription);
2964             return;
2965         }
2966
2967         if (!value->isValueList())
2968             return;
2969         FontDescription fontDescription = state.style()->fontDescription();
2970         FontFamily& firstFamily = fontDescription.firstFamily();
2971         FontFamily* currFamily = 0;
2972
2973         // Before mapping in a new font-family property, we should reset the generic family.
2974         bool oldFamilyUsedFixedDefaultSize = fontDescription.useFixedDefaultSize();
2975         fontDescription.setGenericFamily(FontDescription::NoFamily);
2976
2977         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2978             CSSValue* item = i.value();
2979             if (!item->isPrimitiveValue())
2980                 continue;
2981             CSSPrimitiveValue* contentValue = static_cast<CSSPrimitiveValue*>(item);
2982             AtomicString face;
2983             Settings* settings = documentSettings();
2984             if (contentValue->isString())
2985                 face = contentValue->getStringValue();
2986             else if (settings) {
2987                 switch (contentValue->getIdent()) {
2988                 case CSSValueWebkitBody:
2989                     face = settings->standardFontFamily();
2990                     break;
2991                 case CSSValueSerif:
2992                     face = serifFamily;
2993                     fontDescription.setGenericFamily(FontDescription::SerifFamily);
2994                     break;
2995                 case CSSValueSansSerif:
2996                     face = sansSerifFamily;
2997                     fontDescription.setGenericFamily(FontDescription::SansSerifFamily);
2998                     break;
2999                 case CSSValueCursive:
3000                     face = cursiveFamily;
3001                     fontDescription.setGenericFamily(FontDescription::CursiveFamily);
3002                     break;
3003                 case CSSValueFantasy:
3004                     face = fantasyFamily;
3005                     fontDescription.setGenericFamily(FontDescription::FantasyFamily);
3006                     break;
3007                 case CSSValueMonospace:
3008                     face = monospaceFamily;
3009                     fontDescription.setGenericFamily(FontDescription::MonospaceFamily);
3010                     break;
3011                 case CSSValueWebkitPictograph:
3012                     face = pictographFamily;
3013                     fontDescription.setGenericFamily(FontDescription::PictographFamily);
3014                     break;
3015                 }
3016             }
3017
3018             if (!face.isEmpty()) {
3019                 if (!currFamily) {
3020                     // Filling in the first family.
3021                     firstFamily.setFamily(face);
3022                     firstFamily.appendFamily(0); // Remove any inherited family-fallback list.
3023                     currFamily = &firstFamily;
3024                     fontDescription.setIsSpecifiedFont(fontDescription.genericFamily() == FontDescription::NoFamily);
3025                 } else {
3026                     RefPtr<SharedFontFamily> newFamily = SharedFontFamily::create();
3027                     newFamily->setFamily(face);
3028                     currFamily->appendFamily(newFamily);
3029                     currFamily = newFamily.get();
3030                 }
3031             }
3032         }
3033
3034         // We can't call useFixedDefaultSize() until all new font families have been added
3035         // If currFamily is non-zero then we set at least one family on this description.
3036         if (currFamily) {
3037             if (fontDescription.keywordSize() && fontDescription.useFixedDefaultSize() != oldFamilyUsedFixedDefaultSize)
3038                 setFontSize(fontDescription, fontSizeForKeyword(document(), CSSValueXxSmall + fontDescription.keywordSize() - 1, !oldFamilyUsedFixedDefaultSize));
3039
3040             setFontDescription(fontDescription);
3041         }
3042         return;
3043     }
3044     // Shorthand properties.
3045     case CSSPropertyFont:
3046         if (isInherit) {
3047             FontDescription fontDescription = state.parentStyle()->fontDescription();
3048             state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight());
3049             state.setLineHeightValue(0);
3050             setFontDescription(fontDescription);
3051         } else if (isInitial) {
3052             Settings* settings = documentSettings();
3053             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3054             if (!settings)
3055                 return;
3056             initializeFontStyle(settings);
3057         } else if (primitiveValue) {
3058             state.style()->setLineHeight(RenderStyle::initialLineHeight());
3059             state.setLineHeightValue(0);
3060
3061             FontDescription fontDescription;
3062             RenderTheme::defaultTheme()->systemFont(primitiveValue->getIdent(), fontDescription);
3063
3064             // Double-check and see if the theme did anything. If not, don't bother updating the font.
3065             if (fontDescription.isAbsoluteSize()) {
3066                 // Make sure the rendering mode and printer font settings are updated.
3067                 Settings* settings = documentSettings();
3068                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
3069                 if (!settings)
3070                     return;
3071                 fontDescription.setRenderingMode(settings->fontRenderingMode());
3072                 fontDescription.setUsePrinterFont(document()->printing() || !settings->screenFontSubstitutionEnabled());
3073
3074                 // Handle the zoom factor.
3075                 fontDescription.setComputedSize(getComputedSizeFromSpecifiedSize(document(), state.style(), fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), useSVGZoomRules()));
3076                 setFontDescription(fontDescription);
3077             }
3078         } else if (value->isFontValue()) {
3079             FontValue* font = static_cast<FontValue*>(value);
3080             if (!font->style || !font->variant || !font->weight
3081                 || !font->size || !font->lineHeight || !font->family)
3082                 return;
3083             applyProperty(CSSPropertyFontStyle, font->style.get());
3084             applyProperty(CSSPropertyFontVariant, font->variant.get());
3085             applyProperty(CSSPropertyFontWeight, font->weight.get());
3086             // The previous properties can dirty our font but they don't try to read the font's
3087             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
3088             // need query the dirtied font's x-height to get the computed size. To be safe in this
3089             // case, let's just update the font now.
3090             updateFont();
3091             applyProperty(CSSPropertyFontSize, font->size.get());
3092
3093             state.setLineHeightValue(font->lineHeight.get());
3094
3095             applyProperty(CSSPropertyFontFamily, font->family.get());
3096         }
3097         return;
3098
3099     case CSSPropertyBackground:
3100     case CSSPropertyBackgroundPosition:
3101     case CSSPropertyBackgroundRepeat:
3102     case CSSPropertyBorder:
3103     case CSSPropertyBorderBottom:
3104     case CSSPropertyBorderColor:
3105     case CSSPropertyBorderImage:
3106     case CSSPropertyBorderLeft:
3107     case CSSPropertyBorderRadius:
3108     case CSSPropertyBorderRight:
3109     case CSSPropertyBorderSpacing:
3110     case CSSPropertyBorderStyle:
3111     case CSSPropertyBorderTop:
3112     case CSSPropertyBorderWidth:
3113     case CSSPropertyListStyle:
3114     case CSSPropertyMargin:
3115     case CSSPropertyOutline:
3116     case CSSPropertyOverflow:
3117     case CSSPropertyPadding:
3118     case CSSPropertyTransition:
3119     case CSSPropertyWebkitAnimation:
3120     case CSSPropertyWebkitBorderAfter:
3121     case CSSPropertyWebkitBorderBefore:
3122     case CSSPropertyWebkitBorderEnd:
3123     case CSSPropertyWebkitBorderStart:
3124     case CSSPropertyWebkitBorderRadius:
3125     case CSSPropertyWebkitColumns:
3126     case CSSPropertyWebkitColumnRule:
3127     case CSSPropertyWebkitFlex:
3128     case CSSPropertyWebkitFlexFlow:
3129     case CSSPropertyWebkitGridColumn:
3130     case CSSPropertyWebkitGridRow:
3131     case CSSPropertyWebkitMarginCollapse:
3132     case CSSPropertyWebkitMarquee:
3133     case CSSPropertyWebkitMask:
3134     case CSSPropertyWebkitMaskPosition:
3135     case CSSPropertyWebkitMaskRepeat:
3136     case CSSPropertyWebkitTextEmphasis:
3137     case CSSPropertyWebkitTextStroke:
3138     case CSSPropertyWebkitTransition:
3139     case CSSPropertyWebkitTransformOrigin:
3140 #if ENABLE(CSS_EXCLUSIONS)
3141     case CSSPropertyWebkitWrap:
3142 #endif
3143         ASSERT(isExpandedShorthand(id));
3144         ASSERT_NOT_REACHED();
3145         break;
3146
3147     // CSS3 Properties
3148     case CSSPropertyTextShadow:
3149     case CSSPropertyBoxShadow:
3150     case CSSPropertyWebkitBoxShadow: {
3151         if (isInherit) {
3152             if (id == CSSPropertyTextShadow)
3153                 return state.style()->setTextShadow(state.parentStyle()->textShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr);
3154             return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr);
3155         }
3156         if (isInitial || primitiveValue) // initial | none
3157             return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr);
3158
3159         if (!value->isValueList())
3160             return;
3161
3162         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
3163             CSSValue* currValue = i.value();
3164             if (!currValue->isShadowValue())
3165                 continue;
3166             ShadowValue* item = static_cast<ShadowValue*>(currValue);
3167             int x = item->x->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
3168             int y = item->y->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
3169             int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
3170             int spread = item->spread ? item->spread->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
3171             ShadowStyle shadowStyle = item->style && item->style->getIdent() == CSSValueInset ? Inset : Normal;
3172             Color color;
3173             if (item->color)
3174                 color = colorFromPrimitiveValue(item->color.get());
3175             else if (state.style())
3176                 color = state.style()->color();
3177
3178             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
3179             if (id == CSSPropertyTextShadow)
3180                 state.style()->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3181             else
3182                 state.style()->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
3183         }
3184         return;
3185     }
3186     case CSSPropertyWebkitBoxReflect: {
3187         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
3188         if (primitiveValue) {
3189             state.style()->setBoxReflect(RenderStyle::initialBoxReflect());
3190             return;
3191         }
3192
3193         if (!value->isReflectValue())
3194             return;
3195
3196         CSSReflectValue* reflectValue = static_cast<CSSReflectValue*>(value);
3197         RefPtr<StyleReflection> reflection = StyleReflection::create();
3198         reflection->setDirection(*reflectValue->direction());
3199         if (reflectValue->offset())
3200             reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.style(), state.rootElementStyle(), zoomFactor));
3201         NinePieceImage mask;
3202         mask.setMaskDefaults();
3203         m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
3204         reflection->setMask(mask);
3205
3206         state.style()->setBoxReflect(reflection.release());
3207         return;
3208     }
3209     case CSSPropertySrc: // Only used in @font-face rules.
3210         return;
3211     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
3212         return;
3213     case CSSPropertyWebkitMarqueeRepetition: {
3214         HANDLE_INHERIT_AND_INITIAL(marqueeLoopCount, MarqueeLoopCount)
3215         if (!primitiveValue)
3216             return;
3217         if (primitiveValue->getIdent() == CSSValueInfinite)
3218             state.style()->setMarqueeLoopCount(-1); // -1 means repeat forever.
3219         else if (primitiveValue->isNumber())
3220             state.style()->setMarqueeLoopCount(primitiveValue->getIntValue());
3221         return;
3222     }
3223     case CSSPropertyWebkitMarqueeSpeed: {
3224         HANDLE_INHERIT_AND_INITIAL(marqueeSpeed, MarqueeSpeed)
3225         if (!primitiveValue)
3226             return;
3227         if (int ident = primitiveValue->getIdent()) {
3228             switch (ident) {
3229             case CSSValueSlow:
3230                 state.style()->setMarqueeSpeed(500); // 500 msec.
3231                 break;
3232             case CSSValueNormal:
3233                 state.style()->setMarqueeSpeed(85); // 85msec. The WinIE default.
3234                 break;
3235             case CSSValueFast:
3236                 state.style()->setMarqueeSpeed(10); // 10msec. Super fast.
3237                 break;
3238             }
3239         } else if (primitiveValue->isTime())
3240             state.style()->setMarqueeSpeed(primitiveValue->computeTime<int, CSSPrimitiveValue::Milliseconds>());
3241         else if (primitiveValue->isNumber()) // For scrollamount support.
3242             state.style()->setMarqueeSpeed(primitiveValue->getIntValue());
3243         return;
3244     }
3245     case CSSPropertyWebkitMarqueeIncrement: {
3246         HANDLE_INHERIT_AND_INITIAL(marqueeIncrement, MarqueeIncrement)
3247         if (!primitiveValue)
3248             return;
3249         if (primitiveValue->getIdent()) {
3250             switch (primitiveValue->getIdent()) {
3251             case CSSValueSmall:
3252                 state.style()->setMarqueeIncrement(Length(1, Fixed)); // 1px.
3253                 break;
3254             case CSSValueNormal:
3255                 state.style()->setMarqueeIncrement(Length(6, Fixed)); // 6px. The WinIE default.
3256                 break;
3257             case CSSValueLarge:
3258                 state.style()->setMarqueeIncrement(Length(36, Fixed)); // 36px.
3259                 break;
3260             }
3261         } else {
3262             Length marqueeLength = convertToIntLength(primitiveValue, state.style(), state.rootElementStyle());
3263             if (!marqueeLength.isUndefined())
3264                 state.style()->setMarqueeIncrement(marqueeLength);
3265         }
3266         return;
3267     }
3268     case CSSPropertyWebkitLocale: {
3269         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
3270         if (!primitiveValue)
3271             return;
3272         if (primitiveValue->getIdent() == CSSValueAuto)
3273             state.style()->setLocale(nullAtom);
3274         else
3275             state.style()->setLocale(primitiveValue->getStringValue());
3276         FontDescription fontDescription = state.style()->fontDescription();
3277         fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale()));
3278         setFontDescription(fontDescription);
3279         return;
3280     }
3281 #if ENABLE(DASHBOARD_SUPPORT)
3282     case CSSPropertyWebkitDashboardRegion:
3283     {
3284         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
3285         if (!primitiveValue)
3286             return;
3287
3288         if (primitiveValue->getIdent() == CSSValueNone) {
3289             state.style()->setDashboardRegions(RenderStyle::noneDashboardRegions());
3290             return;
3291         }
3292
3293         DashboardRegion* region = primitiveValue->getDashboardRegionValue();
3294         if (!region)
3295             return;
3296
3297         DashboardRegion* first = region;
3298         while (region) {
3299             Length top = convertToIntLength(region->top(), state.style(), state.rootElementStyle());
3300             Length right = convertToIntLength(region->right(), state.style(), state.rootElementStyle());
3301             Length bottom = convertToIntLength(region->bottom(), state.style(), state.rootElementStyle());
3302             Length left = convertToIntLength(region->left(), state.style(), state.rootElementStyle());
3303
3304             if (top.isUndefined())
3305                 top = Length();
3306             if (right.isUndefined())
3307                 right = Length();
3308             if (bottom.isUndefined())
3309                 bottom = Length();
3310             if (left.isUndefined())
3311                 left = Length();
3312
3313             if (region->m_isCircle)
3314                 state.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
3315             else if (region->m_isRectangle)
3316                 state.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
3317             region = region->m_next.get();
3318         }
3319
3320         state.document()->setHasAnnotatedRegions(true);
3321
3322         return;
3323     }
3324 #endif
3325 #if ENABLE(DRAGGABLE_REGION)
3326     case CSSPropertyWebkitAppRegion: {
3327         if (!primitiveValue || !primitiveValue->getIdent())
3328             return;
3329         state.style()->setDraggableRegionMode(primitiveValue->getIdent() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
3330         state.document()->setHasAnnotatedRegions(true);
3331         return;
3332     }
3333 #endif
3334     case CSSPropertyWebkitTextStrokeWidth: {
3335         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
3336         float width = 0;
3337         switch (primitiveValue->getIdent()) {
3338         case CSSValueThin:
3339         case CSSValueMedium:
3340         case CSSValueThick: {
3341             double result = 1.0 / 48;
3342             if (primitiveValue->getIdent() == CSSValueMedium)
3343                 result *= 3;
3344             else if (primitiveValue->getIdent() == CSSValueThick)
3345                 result *= 5;
3346             width = CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS)->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
3347             break;
3348         }
3349         default:
3350             width = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
3351             break;
3352         }
3353         state.style()->setTextStrokeWidth(width);
3354         return;
3355     }
3356     case CSSPropertyWebkitTransform: {
3357         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
3358         TransformOperations operations;
3359         createTransformOperations(value, state.style(), state.rootElementStyle(), operations);
3360         state.style()->setTransform(operations);
3361         return;
3362     }
3363     case CSSPropertyWebkitPerspective: {
3364         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
3365
3366         if (!primitiveValue)
3367             return;
3368
3369         if (primitiveValue->getIdent() == CSSValueNone) {
3370             state.style()->setPerspective(0);
3371             return;