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