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