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