81a5e71368115b89473f0ac1c7ab331ba0776db2
[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 = nullptr;
222     m_styledElement = nullptr;
223     m_parentStyle = nullptr;
224     m_parentNode = nullptr;
225     m_regionForStyling = nullptr;
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(const 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, const RenderStyle& parentStyle, Element *e)
1159 {
1160     // Cache our original display.
1161     style.setOriginalDisplay(style.display());
1162
1163     if (style.display() != NONE) {
1164         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1165         // property.
1166         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1167         // these tags to retain their display types.
1168         if (document().inQuirksMode() && e) {
1169             if (e->hasTagName(tdTag)) {
1170                 style.setDisplay(TABLE_CELL);
1171                 style.setFloating(NoFloat);
1172             } else if (isHTMLTableElement(e))
1173                 style.setDisplay(style.isDisplayInlineType() ? INLINE_TABLE : TABLE);
1174         }
1175
1176         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1177             if (style.whiteSpace() == KHTML_NOWRAP) {
1178                 // Figure out if we are really nowrapping or if we should just
1179                 // use normal instead. If the width of the cell is fixed, then
1180                 // we don't actually use NOWRAP.
1181                 if (style.width().isFixed())
1182                     style.setWhiteSpace(NORMAL);
1183                 else
1184                     style.setWhiteSpace(NOWRAP);
1185             }
1186         }
1187
1188         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1189         if (e && isHTMLTableElement(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT))
1190             style.setTextAlign(TASTART);
1191
1192         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1193         // fix a crash where a site tries to position these objects. They also never honor display.
1194         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1195             style.setPosition(StaticPosition);
1196             style.setDisplay(BLOCK);
1197         }
1198
1199         // Ruby text does not support float or position. This might change with evolution of the specification.
1200         if (e && e->hasTagName(rtTag)) {
1201             style.setPosition(StaticPosition);
1202             style.setFloating(NoFloat);
1203         }
1204
1205         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1206         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1207         if (e && e->hasTagName(thTag) && style.textAlign() == TASTART)
1208             style.setTextAlign(CENTER);
1209
1210         if (e && e->hasTagName(legendTag))
1211             style.setDisplay(BLOCK);
1212
1213         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1214         if (style.hasOutOfFlowPosition() || style.isFloating() || (e && e->document().documentElement() == e))
1215             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1216
1217         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1218         // clear how that should work.
1219         if (style.display() == INLINE && style.styleType() == NOPSEUDO && style.writingMode() != parentStyle.writingMode())
1220             style.setDisplay(INLINE_BLOCK);
1221
1222         // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
1223         // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
1224         // on some sites).
1225         if ((style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW_GROUP
1226             || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW)
1227             && style.hasInFlowPosition())
1228             style.setPosition(StaticPosition);
1229
1230         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1231         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1232         if (style.display() == TABLE_COLUMN || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_FOOTER_GROUP
1233             || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW || style.display() == TABLE_ROW_GROUP
1234             || style.display() == TABLE_CELL)
1235             style.setWritingMode(parentStyle.writingMode());
1236
1237         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1238         // of block-flow to anything other than TopToBottomWritingMode.
1239         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1240         if (style.writingMode() != TopToBottomWritingMode && (style.display() == BOX || style.display() == INLINE_BOX))
1241             style.setWritingMode(TopToBottomWritingMode);
1242
1243         if (isDisplayFlexibleBox(parentStyle.display())) {
1244             style.setFloating(NoFloat);
1245             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1246         }
1247     }
1248
1249     // Make sure our z-index value is only applied if the object is positioned.
1250     if (style.position() == StaticPosition && !isDisplayFlexibleBox(parentStyle.display()))
1251         style.setHasAutoZIndex();
1252
1253     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1254     // cases where objects that should be blended as a single unit end up with a non-transparent
1255     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1256     if (style.hasAutoZIndex() && ((e && e->document().documentElement() == e)
1257         || style.opacity() < 1.0f
1258         || style.hasTransformRelatedProperty()
1259         || style.hasMask()
1260         || style.clipPath()
1261         || style.boxReflect()
1262         || style.hasFilter()
1263         || style.hasBlendMode()
1264         || style.position() == StickyPosition
1265         || (style.position() == FixedPosition && e && e->document().page() && e->document().page()->settings().fixedPositionCreatesStackingContext())
1266         || style.hasFlowFrom()
1267         ))
1268         style.setZIndex(0);
1269
1270     // Textarea considers overflow visible as auto.
1271     if (e && isHTMLTextAreaElement(e)) {
1272         style.setOverflowX(style.overflowX() == OVISIBLE ? OAUTO : style.overflowX());
1273         style.setOverflowY(style.overflowY() == OVISIBLE ? OAUTO : style.overflowY());
1274     }
1275
1276     if (doesNotInheritTextDecoration(style, e))
1277         style.setTextDecorationsInEffect(style.textDecoration());
1278     else
1279         style.addToTextDecorationsInEffect(style.textDecoration());
1280
1281     // If either overflow value is not visible, change to auto.
1282     if (style.overflowX() == OMARQUEE && style.overflowY() != OMARQUEE)
1283         style.setOverflowY(OMARQUEE);
1284     else if (style.overflowY() == OMARQUEE && style.overflowX() != OMARQUEE)
1285         style.setOverflowX(OMARQUEE);
1286     else if (style.overflowX() == OVISIBLE && style.overflowY() != OVISIBLE) {
1287         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
1288         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
1289         // default to auto so we can at least scroll through the pages.
1290         style.setOverflowX(OAUTO);
1291     } else if (style.overflowY() == OVISIBLE && style.overflowX() != OVISIBLE)
1292         style.setOverflowY(OAUTO);
1293
1294     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
1295     // styles are specified on a root element, then they will be incorporated in
1296     // Style::createForDocument().
1297     if ((style.overflowY() == OPAGEDX || style.overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
1298         style.setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style));
1299
1300     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1301     // FIXME: Eventually table sections will support auto and scroll.
1302     if (style.display() == TABLE || style.display() == INLINE_TABLE
1303         || style.display() == TABLE_ROW_GROUP || style.display() == TABLE_ROW) {
1304         if (style.overflowX() != OVISIBLE && style.overflowX() != OHIDDEN)
1305             style.setOverflowX(OVISIBLE);
1306         if (style.overflowY() != OVISIBLE && style.overflowY() != OHIDDEN)
1307             style.setOverflowY(OVISIBLE);
1308     }
1309
1310     // Menulists should have visible overflow
1311     if (style.appearance() == MenulistPart) {
1312         style.setOverflowX(OVISIBLE);
1313         style.setOverflowY(OVISIBLE);
1314     }
1315
1316 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1317     // Touch overflow scrolling creates a stacking context.
1318     if (style.hasAutoZIndex() && style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY())))
1319         style.setZIndex(0);
1320 #endif
1321
1322     // Cull out any useless layers and also repeat patterns into additional layers.
1323     style.adjustBackgroundLayers();
1324     style.adjustMaskLayers();
1325
1326     // Do the same for animations and transitions.
1327     style.adjustAnimations();
1328     style.adjustTransitions();
1329
1330     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1331     // alter fonts and heights/widths.
1332     if (e && e->isFormControlElement() && style.fontSize() >= 11) {
1333         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1334         // so we have to treat all image buttons as though they were explicitly sized.
1335         if (!isHTMLInputElement(e) || !toHTMLInputElement(e)->isImageButton())
1336             addIntrinsicMargins(style);
1337     }
1338
1339     // Let the theme also have a crack at adjusting the style.
1340     if (style.hasAppearance())
1341         RenderTheme::defaultTheme()->adjustStyle(*this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
1342
1343     // If we have first-letter pseudo style, do not share this style.
1344     if (style.hasPseudoStyle(FIRST_LETTER))
1345         style.setUnique();
1346
1347     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
1348     if (style.preserves3D() && (style.overflowX() != OVISIBLE
1349         || style.overflowY() != OVISIBLE
1350         || style.hasFilter()))
1351         style.setTransformStyle3D(TransformStyle3DFlat);
1352
1353     // Seamless iframes behave like blocks. Map their display to inline-block when marked inline.
1354     if (e && e->hasTagName(iframeTag) && style.display() == INLINE && toHTMLIFrameElement(e)->shouldDisplaySeamlessly())
1355         style.setDisplay(INLINE_BLOCK);
1356
1357     adjustGridItemPosition(style, parentStyle);
1358
1359 #if ENABLE(SVG)
1360     if (e && e->isSVGElement()) {
1361         // Spec: http://www.w3.org/TR/SVG/masking.html#OverflowProperty
1362         if (style.overflowY() == OSCROLL)
1363             style.setOverflowY(OHIDDEN);
1364         else if (style.overflowY() == OAUTO)
1365             style.setOverflowY(OVISIBLE);
1366
1367         if (style.overflowX() == OSCROLL)
1368             style.setOverflowX(OHIDDEN);
1369         else if (style.overflowX() == OAUTO)
1370             style.setOverflowX(OVISIBLE);
1371
1372         // Only the root <svg> element in an SVG document fragment tree honors css position
1373         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1374             style.setPosition(RenderStyle::initialPosition());
1375
1376         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
1377         // not be scaled again.
1378         if (e->hasTagName(SVGNames::foreignObjectTag))
1379             style.setEffectiveZoom(RenderStyle::initialZoom());
1380     }
1381 #endif
1382 }
1383
1384 void StyleResolver::adjustGridItemPosition(RenderStyle& style, const RenderStyle& parentStyle) const
1385 {
1386     const GridPosition& columnStartPosition = style.gridItemColumnStart();
1387     const GridPosition& columnEndPosition = style.gridItemColumnEnd();
1388     const GridPosition& rowStartPosition = style.gridItemRowStart();
1389     const GridPosition& rowEndPosition = style.gridItemRowEnd();
1390
1391     // If opposing grid-placement properties both specify a grid span, they both compute to ‘auto’.
1392     if (columnStartPosition.isSpan() && columnEndPosition.isSpan()) {
1393         style.setGridItemColumnStart(GridPosition());
1394         style.setGridItemColumnEnd(GridPosition());
1395     }
1396
1397     if (rowStartPosition.isSpan() && rowEndPosition.isSpan()) {
1398         style.setGridItemRowStart(GridPosition());
1399         style.setGridItemRowEnd(GridPosition());
1400     }
1401
1402     // Unknown named grid area compute to 'auto'.
1403     const NamedGridAreaMap& map = parentStyle.namedGridArea();
1404
1405 #define CLEAR_UNKNOWN_NAMED_AREA(prop, Prop) \
1406     if (prop.isNamedGridArea() && !map.contains(prop.namedGridLine())) \
1407         style.setGridItem##Prop(GridPosition());
1408
1409     CLEAR_UNKNOWN_NAMED_AREA(columnStartPosition, ColumnStart);
1410     CLEAR_UNKNOWN_NAMED_AREA(columnEndPosition, ColumnEnd);
1411     CLEAR_UNKNOWN_NAMED_AREA(rowStartPosition, RowStart);
1412     CLEAR_UNKNOWN_NAMED_AREA(rowEndPosition, RowEnd);
1413 }
1414
1415 bool StyleResolver::checkRegionStyle(Element* regionElement)
1416 {
1417     // FIXME (BUG 72472): We don't add @-webkit-region rules of scoped style sheets for the moment,
1418     // so all region rules are global by default. Verify whether that can stand or needs changing.
1419
1420     unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size();
1421     for (unsigned i = 0; i < rulesSize; ++i) {
1422         ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1423         if (checkRegionSelector(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1424             return true;
1425     }
1426
1427     if (m_ruleSets.userStyle()) {
1428         rulesSize = m_ruleSets.userStyle()->regionSelectorsAndRuleSets().size();
1429         for (unsigned i = 0; i < rulesSize; ++i) {
1430             ASSERT(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1431             if (checkRegionSelector(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1432                 return true;
1433         }
1434     }
1435
1436     return false;
1437 }
1438
1439 static void checkForOrientationChange(RenderStyle* style)
1440 {
1441     FontOrientation fontOrientation;
1442     NonCJKGlyphOrientation glyphOrientation;
1443     style->getFontAndGlyphOrientation(fontOrientation, glyphOrientation);
1444
1445     const FontDescription& fontDescription = style->fontDescription();
1446     if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
1447         return;
1448
1449     FontDescription newFontDescription(fontDescription);
1450     newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
1451     newFontDescription.setOrientation(fontOrientation);
1452     style->setFontDescription(newFontDescription);
1453 }
1454
1455 void StyleResolver::updateFont()
1456 {
1457     if (!m_state.fontDirty())
1458         return;
1459
1460     RenderStyle* style = m_state.style();
1461 #if ENABLE(IOS_TEXT_AUTOSIZING)
1462     checkForTextSizeAdjust(style);
1463 #endif
1464     checkForGenericFamilyChange(style, m_state.parentStyle());
1465     checkForZoomChange(style, m_state.parentStyle());
1466     checkForOrientationChange(style);
1467     style->font().update(m_fontSelector);
1468     m_state.setFontDirty(false);
1469 }
1470
1471 Vector<RefPtr<StyleRuleBase>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
1472 {
1473     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1474 }
1475
1476 Vector<RefPtr<StyleRuleBase>> StyleResolver::pseudoStyleRulesForElement(Element* e, PseudoId pseudoId, unsigned rulesToInclude)
1477 {
1478     if (!e || !e->document().haveStylesheetsLoaded())
1479         return Vector<RefPtr<StyleRuleBase>>();
1480
1481     initElement(e);
1482     m_state.initForStyleResolve(document(), e, 0);
1483
1484     ElementRuleCollector collector(this, m_state);
1485     collector.setMode(SelectorChecker::CollectingRules);
1486     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1487     collector.setMedium(m_medium.get());
1488
1489     if (rulesToInclude & UAAndUserCSSRules) {
1490         // First we match rules from the user agent sheet.
1491         collector.matchUARules();
1492         
1493         // Now we check user sheet rules.
1494         if (m_matchAuthorAndUserStyles)
1495             collector.matchUserRules(rulesToInclude & EmptyCSSRules);
1496     }
1497
1498     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1499         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
1500
1501         // Check the rules in author sheets.
1502         collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
1503     }
1504
1505     return collector.matchedRuleList();
1506 }
1507
1508 // -------------------------------------------------------------------------------------
1509 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
1510
1511 Length StyleResolver::convertToIntLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
1512 {
1513     return primitiveValue ? primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
1514 }
1515
1516 Length StyleResolver::convertToFloatLength(const CSSPrimitiveValue* primitiveValue, const RenderStyle* style, const RenderStyle* rootStyle, double multiplier)
1517 {
1518     return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion | FractionConversion | ViewportPercentageConversion>(style, rootStyle, multiplier) : Length(Undefined);
1519 }
1520
1521 template <StyleResolver::StyleApplicationPass pass>
1522 void StyleResolver::applyProperties(const StyleProperties* properties, StyleRule* rule, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType)
1523 {
1524     ASSERT((propertyWhitelistType != PropertyWhitelistRegion) || m_state.regionForStyling());
1525     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willProcessRule(&document(), rule, *this);
1526
1527     unsigned propertyCount = properties->propertyCount();
1528     for (unsigned i = 0; i < propertyCount; ++i) {
1529         StyleProperties::PropertyReference current = properties->propertyAt(i);
1530         if (isImportant != current.isImportant())
1531             continue;
1532         if (inheritedOnly && !current.isInherited()) {
1533             // If the property value is explicitly inherited, we need to apply further non-inherited properties
1534             // as they might override the value inherited here. For this reason we don't allow declarations with
1535             // explicitly inherited properties to be cached.
1536             ASSERT(!current.value()->isInheritedValue());
1537             continue;
1538         }
1539         CSSPropertyID property = current.id();
1540
1541         if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(property))
1542             continue;
1543 #if ENABLE(VIDEO_TRACK)
1544         if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(property))
1545             continue;
1546 #endif
1547         switch (pass) {
1548         case HighPriorityProperties:
1549             COMPILE_ASSERT(firstCSSProperty == CSSPropertyColor, CSS_color_is_first_property);
1550 #if ENABLE(IOS_TEXT_AUTOSIZING)
1551             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 18, CSS_zoom_is_end_of_first_prop_range);
1552 #else
1553             COMPILE_ASSERT(CSSPropertyZoom == CSSPropertyColor + 17, CSS_zoom_is_end_of_first_prop_range);
1554 #endif
1555             COMPILE_ASSERT(CSSPropertyLineHeight == CSSPropertyZoom + 1, CSS_line_height_is_after_zoom);
1556             // give special priority to font-xxx, color properties, etc
1557             if (property < CSSPropertyLineHeight)
1558                 applyProperty(current.id(), current.value());
1559             // we apply line-height later
1560             else if (property == CSSPropertyLineHeight)
1561                 m_state.setLineHeightValue(current.value());
1562             break;
1563         case LowPriorityProperties:
1564             if (property > CSSPropertyLineHeight)
1565                 applyProperty(current.id(), current.value());
1566         }
1567     }
1568     InspectorInstrumentation::didProcessRule(cookie);
1569 }
1570
1571 template <StyleResolver::StyleApplicationPass pass>
1572 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, bool isImportant, int startIndex, int endIndex, bool inheritedOnly)
1573 {
1574     if (startIndex == -1)
1575         return;
1576
1577     State& state = m_state;
1578     if (state.style()->insideLink() != NotInsideLink) {
1579         for (int i = startIndex; i <= endIndex; ++i) {
1580             const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1581             unsigned linkMatchType = matchedProperties.linkMatchType;
1582             // FIXME: It would be nicer to pass these as arguments but that requires changes in many places.
1583             state.setApplyPropertyToRegularStyle(linkMatchType & SelectorChecker::MatchLink);
1584             state.setApplyPropertyToVisitedLinkStyle(linkMatchType & SelectorChecker::MatchVisited);
1585
1586             applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1587         }
1588         state.setApplyPropertyToRegularStyle(true);
1589         state.setApplyPropertyToVisitedLinkStyle(false);
1590         return;
1591     }
1592     for (int i = startIndex; i <= endIndex; ++i) {
1593         const MatchedProperties& matchedProperties = matchResult.matchedProperties[i];
1594         applyProperties<pass>(matchedProperties.properties.get(), matchResult.matchedRules[i], isImportant, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType));
1595     }
1596 }
1597
1598 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1599 {
1600     
1601     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1602 }
1603
1604 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1605 {
1606     return a.firstUARule == b.firstUARule
1607         && a.lastUARule == b.lastUARule
1608         && a.firstAuthorRule == b.firstAuthorRule
1609         && a.lastAuthorRule == b.lastAuthorRule
1610         && a.firstUserRule == b.firstUserRule
1611         && a.lastUserRule == b.lastUserRule;
1612 }
1613
1614 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1615 {
1616     return !(a == b);
1617 }
1618
1619 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1620 {
1621     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
1622 }
1623
1624 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1625 {
1626     return !(a == b);
1627 }
1628
1629 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
1630 {
1631     ASSERT(hash);
1632
1633     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
1634     if (it == m_matchedPropertiesCache.end())
1635         return 0;
1636     MatchedPropertiesCacheItem& cacheItem = it->value;
1637
1638     size_t size = matchResult.matchedProperties.size();
1639     if (size != cacheItem.matchedProperties.size())
1640         return 0;
1641     for (size_t i = 0; i < size; ++i) {
1642         if (matchResult.matchedProperties[i] != cacheItem.matchedProperties[i])
1643             return 0;
1644     }
1645     if (cacheItem.ranges != matchResult.ranges)
1646         return 0;
1647     return &cacheItem;
1648 }
1649
1650 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
1651 {
1652     static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
1653     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps
1654         && !m_matchedPropertiesCacheSweepTimer.isActive()) {
1655         static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
1656         m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
1657     }
1658
1659     ASSERT(hash);
1660     MatchedPropertiesCacheItem cacheItem;
1661     cacheItem.matchedProperties.appendVector(matchResult.matchedProperties);
1662     cacheItem.ranges = matchResult.ranges;
1663     // Note that we don't cache the original RenderStyle instance. It may be further modified.
1664     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
1665     cacheItem.renderStyle = RenderStyle::clone(style);
1666     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
1667     m_matchedPropertiesCache.add(hash, cacheItem);
1668 }
1669
1670 void StyleResolver::invalidateMatchedPropertiesCache()
1671 {
1672     m_matchedPropertiesCache.clear();
1673 }
1674
1675 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
1676 {
1677     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
1678     if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement())
1679         return false;
1680     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
1681         return false;
1682     if (style->hasAppearance())
1683         return false;
1684     if (style->zoom() != RenderStyle::initialZoom())
1685         return false;
1686     if (style->writingMode() != RenderStyle::initialWritingMode())
1687         return false;
1688     // The cache assumes static knowledge about which properties are inherited.
1689     if (parentStyle->hasExplicitlyInheritedProperties())
1690         return false;
1691     return true;
1692 }
1693
1694 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element)
1695 {
1696     ASSERT(element);
1697     State& state = m_state;
1698     unsigned cacheHash = matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties.data(), matchResult.matchedProperties.size()) : 0;
1699     bool applyInheritedOnly = false;
1700     const MatchedPropertiesCacheItem* cacheItem = 0;
1701     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))) {
1702         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1703         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
1704         // element context. This is fast and saves memory by reusing the style data structures.
1705         state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
1706         if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
1707             EInsideLink linkStatus = state.style()->insideLink();
1708             // If the cache item parent style has identical inherited properties to the current parent style then the
1709             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1710             state.style()->inheritFrom(cacheItem->renderStyle.get());
1711
1712             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1713             state.style()->setInsideLink(linkStatus);
1714             return;
1715         }
1716         applyInheritedOnly = true; 
1717     }
1718
1719     // Now we have all of the matched rules in the appropriate order. Walk the rules and apply
1720     // high-priority properties first, i.e., those properties that other properties depend on.
1721     // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
1722     // and (4) normal important.
1723     state.setLineHeightValue(0);
1724     applyMatchedProperties<HighPriorityProperties>(matchResult, false, 0, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1725     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1726     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1727     applyMatchedProperties<HighPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1728
1729     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom()) {
1730         state.setFontDirty(true);
1731         applyInheritedOnly = false;
1732     }
1733
1734     // If our font got dirtied, go ahead and update it now.
1735     updateFont();
1736
1737     // Line-height is set when we are sure we decided on the font-size.
1738     if (state.lineHeightValue())
1739         applyProperty(CSSPropertyLineHeight, state.lineHeightValue());
1740
1741     // Many properties depend on the font. If it changes we just apply all properties.
1742     if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
1743         applyInheritedOnly = false;
1744
1745     // Now do the normal priority UA properties.
1746     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1747     
1748     // Cache our border and background so that we can examine them later.
1749     state.cacheBorderAndBackground();
1750     
1751     // Now do the author and user normal priority properties and all the !important properties.
1752     applyMatchedProperties<LowPriorityProperties>(matchResult, false, matchResult.ranges.lastUARule + 1, matchResult.matchedProperties.size() - 1, applyInheritedOnly);
1753     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1754     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1755     applyMatchedProperties<LowPriorityProperties>(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1756    
1757     // Start loading resources referenced by this style.
1758     loadPendingResources();
1759     
1760     ASSERT(!state.fontDirty());
1761     
1762     if (cacheItem || !cacheHash)
1763         return;
1764     if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
1765         return;
1766     addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
1767 }
1768
1769 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
1770 {
1771     initElement(0);
1772     m_state.initForStyleResolve(document(), 0, style);
1773     m_state.setStyle(*style);
1774     applyPropertyToCurrentStyle(id, value);
1775 }
1776
1777 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
1778 {
1779     if (value)
1780         applyProperty(id, value);
1781 }
1782
1783 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
1784 {
1785     switch (id) {
1786     case CSSPropertyBackgroundColor:
1787     case CSSPropertyBorderLeftColor:
1788     case CSSPropertyBorderRightColor:
1789     case CSSPropertyBorderTopColor:
1790     case CSSPropertyBorderBottomColor:
1791     case CSSPropertyColor:
1792     case CSSPropertyOutlineColor:
1793     case CSSPropertyWebkitColumnRuleColor:
1794 #if ENABLE(CSS3_TEXT_DECORATION)
1795     case CSSPropertyWebkitTextDecorationColor:
1796 #endif
1797     case CSSPropertyWebkitTextEmphasisColor:
1798     case CSSPropertyWebkitTextFillColor:
1799     case CSSPropertyWebkitTextStrokeColor:
1800 #if ENABLE(SVG)
1801     case CSSPropertyFill:
1802     case CSSPropertyStroke:
1803 #endif
1804         return true;
1805     default:
1806         break;
1807     }
1808
1809     return false;
1810 }
1811
1812 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
1813 // FIXME: add incremental support for other region styling properties.
1814 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
1815 {
1816     switch (id) {
1817     case CSSPropertyBackgroundColor:
1818     case CSSPropertyColor:
1819         return true;
1820     default:
1821         break;
1822     }
1823
1824     return false;
1825 }
1826
1827 #if ENABLE(VIDEO_TRACK)
1828 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
1829 {
1830     switch (id) {
1831     case CSSPropertyBackground:
1832     case CSSPropertyBackgroundAttachment:
1833     case CSSPropertyBackgroundClip:
1834     case CSSPropertyBackgroundColor:
1835     case CSSPropertyBackgroundImage:
1836     case CSSPropertyBackgroundOrigin:
1837     case CSSPropertyBackgroundPosition:
1838     case CSSPropertyBackgroundPositionX:
1839     case CSSPropertyBackgroundPositionY:
1840     case CSSPropertyBackgroundRepeat:
1841     case CSSPropertyBackgroundRepeatX:
1842     case CSSPropertyBackgroundRepeatY:
1843     case CSSPropertyBackgroundSize:
1844     case CSSPropertyColor:
1845     case CSSPropertyFont:
1846     case CSSPropertyFontFamily:
1847     case CSSPropertyFontSize:
1848     case CSSPropertyFontStyle:
1849     case CSSPropertyFontVariant:
1850     case CSSPropertyFontWeight:
1851     case CSSPropertyLineHeight:
1852     case CSSPropertyOpacity:
1853     case CSSPropertyOutline:
1854     case CSSPropertyOutlineColor:
1855     case CSSPropertyOutlineOffset:
1856     case CSSPropertyOutlineStyle:
1857     case CSSPropertyOutlineWidth:
1858     case CSSPropertyVisibility:
1859     case CSSPropertyWhiteSpace:
1860     case CSSPropertyTextDecoration:
1861     case CSSPropertyTextShadow:
1862     case CSSPropertyBorderStyle:
1863         return true;
1864     default:
1865         break;
1866     }
1867     return false;
1868 }
1869 #endif
1870 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
1871 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
1872 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
1873 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
1874 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
1875 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
1876 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
1877 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
1878 bool StyleResolver::useSVGZoomRules()
1879 {
1880     return m_state.element() && m_state.element()->isSVGElement();
1881 }
1882
1883 static bool createGridTrackBreadth(CSSPrimitiveValue* primitiveValue, const StyleResolver::State& state, GridLength& workingLength)
1884 {
1885     if (primitiveValue->getValueID() == CSSValueWebkitMinContent) {
1886         workingLength = Length(MinContent);
1887         return true;
1888     }
1889
1890     if (primitiveValue->getValueID() == CSSValueWebkitMaxContent) {
1891         workingLength = Length(MaxContent);
1892         return true;
1893     }
1894
1895     if (primitiveValue->isFlex()) {
1896         // Fractional unit.
1897         workingLength.setFlex(primitiveValue->getDoubleValue());
1898         return true;
1899     }
1900
1901     workingLength = primitiveValue->convertToLength<FixedIntegerConversion | PercentConversion | ViewportPercentageConversion | AutoConversion>(state.style(), state.rootElementStyle(), state.style()->effectiveZoom());
1902     if (workingLength.length().isUndefined())
1903         return false;
1904
1905     if (primitiveValue->isLength())
1906         workingLength.length().setQuirk(primitiveValue->isQuirkValue());
1907
1908     return true;
1909 }
1910
1911 static bool createGridTrackSize(CSSValue* value, GridTrackSize& trackSize, const StyleResolver::State& state)
1912 {
1913     if (!value->isPrimitiveValue())
1914         return false;
1915
1916     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1917     Pair* minMaxTrackBreadth = primitiveValue->getPairValue();
1918     if (!minMaxTrackBreadth) {
1919         GridLength workingLength;
1920         if (!createGridTrackBreadth(primitiveValue, state, workingLength))
1921             return false;
1922
1923         trackSize.setLength(workingLength);
1924         return true;
1925     }
1926
1927     GridLength minTrackBreadth;
1928     GridLength maxTrackBreadth;
1929     if (!createGridTrackBreadth(minMaxTrackBreadth->first(), state, minTrackBreadth) || !createGridTrackBreadth(minMaxTrackBreadth->second(), state, maxTrackBreadth))
1930         return false;
1931
1932     trackSize.setMinMax(minTrackBreadth, maxTrackBreadth);
1933     return true;
1934 }
1935
1936 static bool createGridTrackList(CSSValue* value, Vector<GridTrackSize>& trackSizes, NamedGridLinesMap& namedGridLines, const StyleResolver::State& state)
1937 {
1938     // Handle 'none'.
1939     if (value->isPrimitiveValue()) {
1940         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1941         return primitiveValue->getValueID() == CSSValueNone;
1942     }
1943
1944     if (!value->isValueList())
1945         return false;
1946
1947     size_t currentNamedGridLine = 0;
1948     for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
1949         CSSValue* currValue = i.value();
1950         if (currValue->isPrimitiveValue()) {
1951             CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(currValue);
1952             if (primitiveValue->isString()) {
1953                 NamedGridLinesMap::AddResult result = namedGridLines.add(primitiveValue->getStringValue(), Vector<size_t>());
1954                 result.iterator->value.append(currentNamedGridLine);
1955                 continue;
1956             }
1957         }
1958
1959         ++currentNamedGridLine;
1960         GridTrackSize trackSize;
1961         if (!createGridTrackSize(currValue, trackSize, state))
1962             return false;
1963
1964         trackSizes.append(trackSize);
1965     }
1966
1967     // The parser should have rejected any <track-list> without any <track-size> as
1968     // this is not conformant to the syntax.
1969     ASSERT(!trackSizes.isEmpty());
1970     return true;
1971 }
1972
1973
1974 static bool createGridPosition(CSSValue* value, GridPosition& position)
1975 {
1976     // We accept the specification's grammar:
1977     // 'auto' | [ <integer> || <string> ] | [ span && [ <integer> || string ] ] | <ident>
1978     if (value->isPrimitiveValue()) {
1979         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
1980         // We translate <ident> to <string> during parsing as it makes handling it simpler.
1981         if (primitiveValue->isString()) {
1982             position.setNamedGridArea(primitiveValue->getStringValue());
1983             return true;
1984         }
1985
1986         ASSERT(primitiveValue->getValueID() == CSSValueAuto);
1987         return true;
1988     }
1989
1990     CSSValueList* values = toCSSValueList(value);
1991     ASSERT(values->length());
1992
1993     bool isSpanPosition = false;
1994     // The specification makes the <integer> optional, in which case it default to '1'.
1995     int gridLineNumber = 1;
1996     String gridLineName;
1997
1998     CSSValueListIterator it = values;
1999     CSSPrimitiveValue* currentValue = toCSSPrimitiveValue(it.value());
2000     if (currentValue->getValueID() == CSSValueSpan) {
2001         isSpanPosition = true;
2002         it.advance();
2003         currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
2004     }
2005
2006     if (currentValue && currentValue->isNumber()) {
2007         gridLineNumber = currentValue->getIntValue();
2008         it.advance();
2009         currentValue = it.hasMore() ? toCSSPrimitiveValue(it.value()) : 0;
2010     }
2011
2012     if (currentValue && currentValue->isString()) {
2013         gridLineName = currentValue->getStringValue();
2014         it.advance();
2015     }
2016
2017     ASSERT(!it.hasMore());
2018     if (isSpanPosition)
2019         position.setSpanPosition(gridLineNumber, gridLineName);
2020     else
2021         position.setExplicitPosition(gridLineNumber, gridLineName);
2022
2023     return true;
2024 }
2025
2026 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
2027 {
2028     ASSERT_WITH_MESSAGE(!isExpandedShorthand(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
2029
2030     State& state = m_state;
2031
2032     if (CSSProperty::isDirectionAwareProperty(id)) {
2033         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
2034         ASSERT(newId != id);
2035         return applyProperty(newId, value);
2036     }
2037
2038     bool isInherit = state.parentNode() && value->isInheritedValue();
2039     bool isInitial = value->isInitialValue() || (!state.parentNode() && value->isInheritedValue());
2040
2041     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
2042     ASSERT(!isInherit || (state.parentNode() && state.parentStyle())); // isInherit -> (state.parentNode() && state.parentStyle())
2043
2044     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
2045         // Limit the properties that can be applied to only the ones honored by :visited.
2046         return;
2047     }
2048
2049     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
2050         state.parentStyle()->setHasExplicitlyInheritedProperties();
2051
2052     // Check lookup table for implementations and use when available.
2053     const PropertyHandler& handler = m_deprecatedStyleBuilder.propertyHandler(id);
2054     if (handler.isValid()) {
2055         if (isInherit)
2056             handler.applyInheritValue(id, this);
2057         else if (isInitial)
2058             handler.applyInitialValue(id, this);
2059         else
2060             handler.applyValue(id, this, value);
2061         return;
2062     }
2063
2064     CSSPrimitiveValue* primitiveValue = value->isPrimitiveValue() ? toCSSPrimitiveValue(value) : 0;
2065
2066     float zoomFactor = state.style()->effectiveZoom();
2067
2068     // What follows is a list that maps the CSS properties into their corresponding front-end
2069     // RenderStyle values.
2070     switch (id) {
2071     // lists
2072     case CSSPropertyContent:
2073         // list of string, uri, counter, attr, i
2074         {
2075             // FIXME: In CSS3, it will be possible to inherit content. In CSS2 it is not. This
2076             // note is a reminder that eventually "inherit" needs to be supported.
2077
2078             if (isInitial) {
2079                 state.style()->clearContent();
2080                 return;
2081             }
2082
2083             if (!value->isValueList())
2084                 return;
2085
2086             bool didSet = false;
2087             for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2088                 CSSValue* item = i.value();
2089                 if (item->isImageGeneratorValue()) {
2090                     if (item->isGradientValue())
2091                         state.style()->setContent(StyleGeneratedImage::create(*toCSSGradientValue(item)->gradientWithStylesResolved(this)), didSet);
2092                     else
2093                         state.style()->setContent(StyleGeneratedImage::create(*toCSSImageGeneratorValue(item)), didSet);
2094                     didSet = true;
2095 #if ENABLE(CSS_IMAGE_SET)
2096                 } else if (item->isImageSetValue()) {
2097                     state.style()->setContent(setOrPendingFromValue(CSSPropertyContent, toCSSImageSetValue(item)), didSet);
2098                     didSet = true;
2099 #endif
2100                 }
2101
2102                 if (item->isImageValue()) {
2103                     state.style()->setContent(cachedOrPendingFromValue(CSSPropertyContent, toCSSImageValue(item)), didSet);
2104                     didSet = true;
2105                     continue;
2106                 }
2107
2108                 if (!item->isPrimitiveValue())
2109                     continue;
2110
2111                 CSSPrimitiveValue* contentValue = toCSSPrimitiveValue(item);
2112
2113                 if (contentValue->isString()) {
2114                     state.style()->setContent(contentValue->getStringValue().impl(), didSet);
2115                     didSet = true;
2116                 } else if (contentValue->isAttr()) {
2117                     // FIXME: Can a namespace be specified for an attr(foo)?
2118                     if (state.style()->styleType() == NOPSEUDO)
2119                         state.style()->setUnique();
2120                     else
2121                         state.parentStyle()->setUnique();
2122                     QualifiedName attr(nullAtom, contentValue->getStringValue().impl(), nullAtom);
2123                     const AtomicString& value = state.element()->getAttribute(attr);
2124                     state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
2125                     didSet = true;
2126                     // Register the fact that the attribute value affects the style.
2127                     m_ruleSets.features().attrsInRules.add(attr.localName().impl());
2128                 } else if (contentValue->isCounter()) {
2129                     Counter* counterValue = contentValue->getCounterValue();
2130                     EListStyleType listStyleType = NoneListStyle;
2131                     CSSValueID listStyleIdent = counterValue->listStyleIdent();
2132                     if (listStyleIdent != CSSValueNone)
2133                         listStyleType = static_cast<EListStyleType>(listStyleIdent - CSSValueDisc);
2134                     auto counter = std::make_unique<CounterContent>(counterValue->identifier(), listStyleType, counterValue->separator());
2135                     state.style()->setContent(std::move(counter), didSet);
2136                     didSet = true;
2137                 } else {
2138                     switch (contentValue->getValueID()) {
2139                     case CSSValueOpenQuote:
2140                         state.style()->setContent(OPEN_QUOTE, didSet);
2141                         didSet = true;
2142                         break;
2143                     case CSSValueCloseQuote:
2144                         state.style()->setContent(CLOSE_QUOTE, didSet);
2145                         didSet = true;
2146                         break;
2147                     case CSSValueNoOpenQuote:
2148                         state.style()->setContent(NO_OPEN_QUOTE, didSet);
2149                         didSet = true;
2150                         break;
2151                     case CSSValueNoCloseQuote:
2152                         state.style()->setContent(NO_CLOSE_QUOTE, didSet);
2153                         didSet = true;
2154                         break;
2155                     default:
2156                         // normal and none do not have any effect.
2157                         { }
2158                     }
2159                 }
2160             }
2161             if (!didSet)
2162                 state.style()->clearContent();
2163             return;
2164         }
2165     case CSSPropertyWebkitAlt:
2166         {
2167             bool didSet = false;
2168             if (primitiveValue->isString()) {
2169                 state.style()->setContentAltText(primitiveValue->getStringValue().impl());
2170                 didSet = true;
2171             } else if (primitiveValue->isAttr()) {
2172                 // FIXME: Can a namespace be specified for an attr(foo)?
2173                 if (state.style()->styleType() == NOPSEUDO)
2174                     state.style()->setUnique();
2175                 else
2176                     state.parentStyle()->setUnique();
2177                 QualifiedName attr(nullAtom, primitiveValue->getStringValue().impl(), nullAtom);
2178                 const AtomicString& value = state.element()->getAttribute(attr);
2179                 state.style()->setContentAltText(value.isNull() ? emptyAtom : value.impl());
2180                 didSet = true;
2181                 // Register the fact that the attribute value affects the style.
2182                 m_ruleSets.features().attrsInRules.add(attr.localName().impl());
2183             }
2184             if (!didSet)
2185                 state.style()->setContentAltText(emptyAtom);
2186         }
2187     case CSSPropertyQuotes:
2188         if (isInherit) {
2189             state.style()->setQuotes(state.parentStyle()->quotes());
2190             return;
2191         }
2192         if (isInitial) {
2193             state.style()->setQuotes(0);
2194             return;
2195         }
2196         if (value->isValueList()) {
2197             CSSValueList* list = toCSSValueList(value);
2198             Vector<std::pair<String, String>> quotes;
2199             for (size_t i = 0; i < list->length(); i += 2) {
2200                 CSSValue* first = list->itemWithoutBoundsCheck(i);
2201                 // item() returns null if out of bounds so this is safe.
2202                 CSSValue* second = list->item(i + 1);
2203                 if (!second)
2204                     continue;
2205                 ASSERT_WITH_SECURITY_IMPLICATION(first->isPrimitiveValue());
2206                 ASSERT_WITH_SECURITY_IMPLICATION(second->isPrimitiveValue());
2207                 String startQuote = toCSSPrimitiveValue(first)->getStringValue();
2208                 String endQuote = toCSSPrimitiveValue(second)->getStringValue();
2209                 quotes.append(std::make_pair(startQuote, endQuote));
2210             }
2211             state.style()->setQuotes(QuotesData::create(quotes));
2212             return;
2213         }
2214         if (primitiveValue) {
2215             if (primitiveValue->getValueID() == CSSValueNone)
2216                 state.style()->setQuotes(QuotesData::create(Vector<std::pair<String, String>>()));
2217         }
2218         return;
2219     // Shorthand properties.
2220     case CSSPropertyFont:
2221         if (isInherit) {
2222             FontDescription fontDescription = state.parentStyle()->fontDescription();
2223             state.style()->setLineHeight(state.parentStyle()->specifiedLineHeight());
2224             state.setLineHeightValue(0);
2225             setFontDescription(fontDescription);
2226         } else if (isInitial) {
2227             Settings* settings = documentSettings();
2228             ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
2229             if (!settings)
2230                 return;
2231             initializeFontStyle(settings);
2232         } else if (primitiveValue) {
2233             state.style()->setLineHeight(RenderStyle::initialLineHeight());
2234             state.setLineHeightValue(0);
2235
2236             FontDescription fontDescription;
2237             RenderTheme::defaultTheme()->systemFont(primitiveValue->getValueID(), fontDescription);
2238
2239             // Double-check and see if the theme did anything. If not, don't bother updating the font.
2240             if (fontDescription.isAbsoluteSize()) {
2241                 // Make sure the rendering mode and printer font settings are updated.
2242                 Settings* settings = documentSettings();
2243                 ASSERT(settings); // If we're doing style resolution, this document should always be in a frame and thus have settings
2244                 if (!settings)
2245                     return;
2246                 fontDescription.setRenderingMode(settings->fontRenderingMode());
2247                 fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
2248
2249                 // Handle the zoom factor.
2250                 fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(fontDescription.specifiedSize(), fontDescription.isAbsoluteSize(), useSVGZoomRules(), state.style(), document()));
2251                 setFontDescription(fontDescription);
2252             }
2253         } else if (value->isFontValue()) {
2254             CSSFontValue* font = toCSSFontValue(value);
2255             if (!font->style || !font->variant || !font->weight
2256                 || !font->size || !font->lineHeight || !font->family)
2257                 return;
2258             applyProperty(CSSPropertyFontStyle, font->style.get());
2259             applyProperty(CSSPropertyFontVariant, font->variant.get());
2260             applyProperty(CSSPropertyFontWeight, font->weight.get());
2261             // The previous properties can dirty our font but they don't try to read the font's
2262             // properties back, which is safe. However if font-size is using the 'ex' unit, it will
2263             // need query the dirtied font's x-height to get the computed size. To be safe in this
2264             // case, let's just update the font now.
2265             updateFont();
2266             applyProperty(CSSPropertyFontSize, font->size.get());
2267
2268             state.setLineHeightValue(font->lineHeight.get());
2269
2270             applyProperty(CSSPropertyFontFamily, font->family.get());
2271         }
2272         return;
2273
2274     case CSSPropertyBackground:
2275     case CSSPropertyBackgroundPosition:
2276     case CSSPropertyBackgroundRepeat:
2277     case CSSPropertyBorder:
2278     case CSSPropertyBorderBottom:
2279     case CSSPropertyBorderColor:
2280     case CSSPropertyBorderImage:
2281     case CSSPropertyBorderLeft:
2282     case CSSPropertyBorderRadius:
2283     case CSSPropertyBorderRight:
2284     case CSSPropertyBorderSpacing:
2285     case CSSPropertyBorderStyle:
2286     case CSSPropertyBorderTop:
2287     case CSSPropertyBorderWidth:
2288     case CSSPropertyListStyle:
2289     case CSSPropertyMargin:
2290     case CSSPropertyOutline:
2291     case CSSPropertyOverflow:
2292     case CSSPropertyPadding:
2293     case CSSPropertyTransition:
2294     case CSSPropertyWebkitAnimation:
2295     case CSSPropertyWebkitBorderAfter:
2296     case CSSPropertyWebkitBorderBefore:
2297     case CSSPropertyWebkitBorderEnd:
2298     case CSSPropertyWebkitBorderStart:
2299     case CSSPropertyWebkitBorderRadius:
2300     case CSSPropertyWebkitColumns:
2301     case CSSPropertyWebkitColumnRule:
2302     case CSSPropertyWebkitFlex:
2303     case CSSPropertyWebkitFlexFlow:
2304     case CSSPropertyWebkitGridArea:
2305     case CSSPropertyWebkitGridColumn:
2306     case CSSPropertyWebkitGridRow:
2307     case CSSPropertyWebkitMarginCollapse:
2308     case CSSPropertyWebkitMarquee:
2309     case CSSPropertyWebkitMask:
2310     case CSSPropertyWebkitMaskPosition:
2311     case CSSPropertyWebkitMaskRepeat:
2312     case CSSPropertyWebkitTextEmphasis:
2313     case CSSPropertyWebkitTextStroke:
2314     case CSSPropertyWebkitTransition:
2315     case CSSPropertyWebkitTransformOrigin:
2316         ASSERT(isExpandedShorthand(id));
2317         ASSERT_NOT_REACHED();
2318         break;
2319
2320     // CSS3 Properties
2321     case CSSPropertyTextShadow:
2322     case CSSPropertyBoxShadow:
2323     case CSSPropertyWebkitBoxShadow: {
2324         if (isInherit) {
2325             if (id == CSSPropertyTextShadow)
2326                 return state.style()->setTextShadow(state.parentStyle()->textShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->textShadow())) : nullptr);
2327             return state.style()->setBoxShadow(state.parentStyle()->boxShadow() ? adoptPtr(new ShadowData(*state.parentStyle()->boxShadow())) : nullptr);
2328         }
2329         if (isInitial || primitiveValue) // initial | none
2330             return id == CSSPropertyTextShadow ? state.style()->setTextShadow(nullptr) : state.style()->setBoxShadow(nullptr);
2331
2332         if (!value->isValueList())
2333             return;
2334
2335         for (CSSValueListIterator i = value; i.hasMore(); i.advance()) {
2336             CSSValue* currValue = i.value();
2337             if (!currValue->isShadowValue())
2338                 continue;
2339             CSSShadowValue* item = toCSSShadowValue(currValue);
2340             int x = item->x->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
2341             if (item->x->isViewportPercentageLength())
2342                 x = viewportPercentageValue(*item->x, x);
2343             int y = item->y->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor);
2344             if (item->y->isViewportPercentageLength())
2345                 y = viewportPercentageValue(*item->y, y);
2346             int blur = item->blur ? item->blur->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
2347             if (item->blur && item->blur->isViewportPercentageLength())
2348                 blur = viewportPercentageValue(*item->blur, blur);
2349             int spread = item->spread ? item->spread->computeLength<int>(state.style(), state.rootElementStyle(), zoomFactor) : 0;
2350             if (item->spread && item->spread->isViewportPercentageLength())
2351                 spread = viewportPercentageValue(*item->spread, spread);
2352             ShadowStyle shadowStyle = item->style && item->style->getValueID() == CSSValueInset ? Inset : Normal;
2353             Color color;
2354             if (item->color)
2355                 color = colorFromPrimitiveValue(item->color.get());
2356             else if (state.style())
2357                 color = state.style()->color();
2358
2359             OwnPtr<ShadowData> shadowData = adoptPtr(new ShadowData(IntPoint(x, y), blur, spread, shadowStyle, id == CSSPropertyWebkitBoxShadow, color.isValid() ? color : Color::transparent));
2360             if (id == CSSPropertyTextShadow)
2361                 state.style()->setTextShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
2362             else
2363                 state.style()->setBoxShadow(shadowData.release(), i.index()); // add to the list if this is not the first entry
2364         }
2365         return;
2366     }
2367     case CSSPropertyWebkitBoxReflect: {
2368         HANDLE_INHERIT_AND_INITIAL(boxReflect, BoxReflect)
2369         if (primitiveValue) {
2370             state.style()->setBoxReflect(RenderStyle::initialBoxReflect());
2371             return;
2372         }
2373
2374         if (!value->isReflectValue())
2375             return;
2376
2377         CSSReflectValue* reflectValue = toCSSReflectValue(value);
2378         RefPtr<StyleReflection> reflection = StyleReflection::create();
2379         reflection->setDirection(*reflectValue->direction());
2380         if (reflectValue->offset())
2381             reflection->setOffset(reflectValue->offset()->convertToLength<FixedIntegerConversion | PercentConversion | CalculatedConversion>(state.style(), state.rootElementStyle(), zoomFactor));
2382         NinePieceImage mask;
2383         mask.setMaskDefaults();
2384         m_styleMap.mapNinePieceImage(id, reflectValue->mask(), mask);
2385         reflection->setMask(mask);
2386
2387         state.style()->setBoxReflect(reflection.release());
2388         return;
2389     }
2390     case CSSPropertySrc: // Only used in @font-face rules.
2391         return;
2392     case CSSPropertyUnicodeRange: // Only used in @font-face rules.
2393         return;
2394     case CSSPropertyWebkitLocale: {
2395         HANDLE_INHERIT_AND_INITIAL(locale, Locale);
2396         if (!primitiveValue)
2397             return;
2398         if (primitiveValue->getValueID() == CSSValueAuto)
2399             state.style()->setLocale(nullAtom);
2400         else
2401             state.style()->setLocale(primitiveValue->getStringValue());
2402         FontDescription fontDescription = state.style()->fontDescription();
2403         fontDescription.setScript(localeToScriptCodeForFontSelection(state.style()->locale()));
2404         setFontDescription(fontDescription);
2405         return;
2406     }
2407 #if ENABLE(IOS_TEXT_AUTOSIZING)
2408     case CSSPropertyWebkitTextSizeAdjust: {
2409         HANDLE_INHERIT_AND_INITIAL(textSizeAdjust, TextSizeAdjust)
2410         if (!primitiveValue)
2411             return;
2412
2413         if (primitiveValue->getValueID() == CSSValueAuto)
2414             state.style()->setTextSizeAdjust(TextSizeAdjustment(AutoTextSizeAdjustment));
2415         else if (primitiveValue->getValueID() == CSSValueNone)
2416             state.style()->setTextSizeAdjust(TextSizeAdjustment(NoTextSizeAdjustment));
2417         else
2418             state.style()->setTextSizeAdjust(TextSizeAdjustment(primitiveValue->getFloatValue()));
2419
2420         state.setFontDirty(true);
2421         return;
2422     }
2423 #endif
2424 #if ENABLE(DASHBOARD_SUPPORT)
2425     case CSSPropertyWebkitDashboardRegion:
2426     {
2427         HANDLE_INHERIT_AND_INITIAL(dashboardRegions, DashboardRegions)
2428         if (!primitiveValue)
2429             return;
2430
2431         if (primitiveValue->getValueID() == CSSValueNone) {
2432             state.style()->setDashboardRegions(RenderStyle::noneDashboardRegions());
2433             return;
2434         }
2435
2436         DashboardRegion* region = primitiveValue->getDashboardRegionValue();
2437         if (!region)
2438             return;
2439
2440         DashboardRegion* first = region;
2441         while (region) {
2442             Length top = convertToIntLength(region->top(), state.style(), state.rootElementStyle());
2443             Length right = convertToIntLength(region->right(), state.style(), state.rootElementStyle());
2444             Length bottom = convertToIntLength(region->bottom(), state.style(), state.rootElementStyle());
2445             Length left = convertToIntLength(region->left(), state.style(), state.rootElementStyle());
2446
2447             if (top.isUndefined())
2448                 top = Length();
2449             if (right.isUndefined())
2450                 right = Length();
2451             if (bottom.isUndefined())
2452                 bottom = Length();
2453             if (left.isUndefined())
2454                 left = Length();
2455
2456             if (region->m_isCircle)
2457                 state.style()->setDashboardRegion(StyleDashboardRegion::Circle, region->m_label, top, right, bottom, left, region == first ? false : true);
2458             else if (region->m_isRectangle)
2459                 state.style()->setDashboardRegion(StyleDashboardRegion::Rectangle, region->m_label, top, right, bottom, left, region == first ? false : true);
2460             region = region->m_next.get();
2461         }
2462
2463         state.document().setHasAnnotatedRegions(true);
2464
2465         return;
2466     }
2467 #endif
2468 #if ENABLE(DRAGGABLE_REGION)
2469     case CSSPropertyWebkitAppRegion: {
2470         if (!primitiveValue || !primitiveValue->getValueID())
2471             return;
2472         state.style()->setDraggableRegionMode(primitiveValue->getValueID() == CSSValueDrag ? DraggableRegionDrag : DraggableRegionNoDrag);
2473         state.document().setHasAnnotatedRegions(true);
2474         return;
2475     }
2476 #endif
2477     case CSSPropertyWebkitTextStrokeWidth: {
2478         HANDLE_INHERIT_AND_INITIAL(textStrokeWidth, TextStrokeWidth)
2479         float width = 0;
2480         switch (primitiveValue->getValueID()) {
2481         case CSSValueThin:
2482         case CSSValueMedium:
2483         case CSSValueThick: {
2484             double result = 1.0 / 48;
2485             if (primitiveValue->getValueID() == CSSValueMedium)
2486                 result *= 3;
2487             else if (primitiveValue->getValueID() == CSSValueThick)
2488                 result *= 5;
2489             Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(result, CSSPrimitiveValue::CSS_EMS));
2490             width = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2491             break;
2492         }
2493         default:
2494             width = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2495             break;
2496         }
2497         state.style()->setTextStrokeWidth(width);
2498         return;
2499     }
2500     case CSSPropertyWebkitTransform: {
2501         HANDLE_INHERIT_AND_INITIAL(transform, Transform);
2502         TransformOperations operations;
2503         transformsForValue(state.style(), state.rootElementStyle(), value, operations);
2504         state.style()->setTransform(operations);
2505         return;
2506     }
2507     case CSSPropertyWebkitPerspective: {
2508         HANDLE_INHERIT_AND_INITIAL(perspective, Perspective)
2509
2510         if (!primitiveValue)
2511             return;
2512
2513         if (primitiveValue->getValueID() == CSSValueNone) {
2514             state.style()->setPerspective(0);
2515             return;
2516         }
2517
2518         float perspectiveValue;
2519         if (primitiveValue->isLength())
2520             perspectiveValue = primitiveValue->computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2521         else if (primitiveValue->isNumber()) {
2522             // For backward compatibility, treat valueless numbers as px.
2523             Ref<CSSPrimitiveValue> value(CSSPrimitiveValue::create(primitiveValue->getDoubleValue(), CSSPrimitiveValue::CSS_PX));
2524             perspectiveValue = value.get().computeLength<float>(state.style(), state.rootElementStyle(), zoomFactor);
2525         } else
2526             return;
2527
2528         if (perspectiveValue >= 0.0f)
2529             state.style()->setPerspective(perspectiveValue);
2530         return;
2531     }
2532 #if PLATFORM(IOS)
2533     case CSSPropertyWebkitTouchCallout: {
2534         HANDLE_INHERIT_AND_INITIAL(touchCalloutEnabled, TouchCalloutEnabled);
2535         if (!primitiveValue)
2536             break;
2537
2538         state.style()->setTouchCalloutEnabled(primitiveValue->getStringValue().lower() != "none");
2539         return;
2540     }
2541 #endif
2542 #if ENABLE(TOUCH_EVENTS)
2543     case CSSPropertyWebkitTapHighlightColor: {
2544         HANDLE_INHERIT_AND_INITIAL(tapHighlightColor, TapHighlightColor);
2545         if (!primitiveValue)
2546             break;
2547
2548         Color col = colorFromPrimitiveValue(primitiveValue);
2549         state.style()->setTapHighlightColor(col);
2550         return;
2551     }
2552 #endif
2553 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
2554     case CSSPropertyWebkitOverflowScrolling: {
2555         HANDLE_INHERIT_AND_INITIAL(useTouchOverflowScrolling, UseTouchOverflowScrolling);
2556         if (!primitiveValue)
2557             break;
2558         state.style()->setUseTouchOverflowScrolling(primitiveValue->getValueID() == CSSValueTouch);
2559         return;
2560     }
2561 #endif
2562     case CSSPropertyInvalid:
2563         return;
2564     case CSSPropertyFontStretch:
2565     case CSSPropertyPage:
2566     case CSSPropertyTextLineThrough:
2567     case CSSPropertyTextLineThroughColor:
2568     case CSSPropertyTextLineThroughMode:
2569     case CSSPropertyTextLineThroughStyle:
2570     case CSSPropertyTextLineThroughWidth:
2571     case CSSPropertyTextOverline:
2572     case CSSPropertyTextOverlineColor:
2573     case CSSPropertyTextOverlineMode:
2574     case CSSPropertyTextOverlineStyle:
2575     case CSSPropertyTextOverlineWidth:
2576     case CSSPropertyTextUnderline:
2577     case CSSPropertyTextUnderlineColor:
2578     case CSSPropertyTextUnderlineMode:
2579     case CSSPropertyTextUnderlineStyle:
2580     case CSSPropertyTextUnderlineWidth:
2581     case CSSPropertyWebkitFontSizeDelta:
2582     case CSSPropertyWebkitTextDecorationsInEffect:
2583         return;
2584
2585     // CSS Text Layout Module Level 3: Vertical writing support
2586     case CSSPropertyWebkitWritingMode: {
2587         HANDLE_INHERIT_AND_INITIAL(writingMode, WritingMode);
2588         
2589         if (primitiveValue)
2590             setWritingMode(*primitiveValue);
2591
2592         // FIXME: It is not ok to modify document state while applying style.
2593         if (state.element() && state.element() == state.document().documentElement())
2594             state.document().setWritingModeSetOnDocumentElement(true);
2595         return;
2596     }
2597
2598     case CSSPropertyWebkitTextOrientation: {
2599         HANDLE_INHERIT_AND_INITIAL(textOrientation, TextOrientation);
2600
2601         if (primitiveValue)
2602             setTextOrientation(*primitiveValue);
2603
2604         return;
2605     }
2606
2607     case CSSPropertyWebkitLineBoxContain: {
2608         HANDLE_INHERIT_AND_INITIAL(lineBoxContain, LineBoxContain)
2609         if (primitiveValue && primitiveValue->getValueID() == CSSValueNone) {
2610             state.style()->setLineBoxContain(LineBoxContainNone);
2611             return;
2612         }
2613
2614         if (!value->isLineBoxContainValue())
2615             return;
2616
2617         state.style()->setLineBoxContain(toCSSLineBoxContainValue(value)->value());
2618         return;
2619     }
2620
2621     // CSS Fonts Module Level 3
2622     case CSSPropertyWebkitFontFeatureSettings: {
2623         if (primitiveValue && primitiveValue->getValueID() == CSSValueNormal) {
2624             setFontDescription(state.style()->fontDescription().makeNormalFeatureSettings());
2625             return;
2626         }
2627
2628         if (!value->isValueList())
2629             return;
2630
2631         FontDescription fontDescription = state.style()->fontDescription();
2632         CSSValueList* list = toCSSValueList(value);
2633         RefPtr<FontFeatureSettings> settings = FontFeatureSettings::create();
2634         int len = list->length();
2635         for (int i = 0; i < len; ++i) {
2636             CSSValue* item = list->itemWithoutBoundsCheck(i);
2637             if (!item->isFontFeatureValue())
2638                 continue;
2639             CSSFontFeatureValue* feature = toCSSFontFeatureValue(item);
2640             settings->append(FontFeature(feature->tag(), feature->value()));
2641         }
2642         fontDescription.setFeatureSettings(settings.release());
2643         setFontDescription(fontDescription);
2644         return;
2645     }
2646
2647 #if ENABLE(CSS_FILTERS)
2648     case CSSPropertyWebkitFilter: {
2649         HANDLE_INHERIT_AND_INITIAL(filter, Filter);
2650         FilterOperations operations;
2651         if (createFilterOperations(value, operations))
2652             state.style()->setFilter(operations);
2653         return;
2654     }
2655 #endif
2656     case CSSPropertyWebkitGridAutoColumns: {
2657         HANDLE_INHERIT_AND_INITIAL(gridAutoColumns, GridAutoColumns);
2658         GridTrackSize trackSize;
2659         if (!createGridTrackSize(value, trackSize, state))
2660             return;
2661         state.style()->setGridAutoColumns(trackSize);
2662         return;
2663     }
2664     case CSSPropertyWebkitGridAutoRows: {
2665         HANDLE_INHERIT_AND_INITIAL(gridAutoRows, GridAutoRows);
2666         GridTrackSize trackSize;
2667         if (!createGridTrackSize(value, trackSize, state))
2668             return;
2669         state.style()->setGridAutoRows(trackSize);
2670         return;
2671     }
2672     case CSSPropertyWebkitGridDefinitionColumns: {
2673         if (isInherit) {
2674             m_state.style()->setGridColumns(m_state.parentStyle()->gridColumns());
2675             m_state.style()->setNamedGridColumnLines(m_state.parentStyle()->namedGridColumnLines());
2676             return;
2677         }
2678         if (isInitial) {
2679             m_state.style()->setGridColumns(RenderStyle::initialGridColumns());
2680             m_state.style()->setNamedGridColumnLines(RenderStyle::initialNamedGridColumnLines());
2681             return;
2682         }
2683         Vector<GridTrackSize> trackSizes;
2684         NamedGridLinesMap namedGridLines;
2685         if (!createGridTrackList(value, trackSizes, namedGridLines, state))
2686             return;
2687         state.style()->setGridColumns(trackSizes);
2688         state.style()->setNamedGridColumnLines(namedGridLines);
2689         return;
2690     }
2691     case CSSPropertyWebkitGridDefinitionRows: {
2692         if (isInherit) {
2693             m_state.style()->setGridRows(m_state.parentStyle()->gridRows());
2694             m_state.style()->setNamedGridRowLines(m_state.parentStyle()->namedGridRowLines());
2695             return;
2696         }
2697         if (isInitial) {
2698             m_state.style()->setGridRows(RenderStyle::initialGridRows());
2699             m_state.style()->setNamedGridRowLines(RenderStyle::initialNamedGridRowLines());
2700             return;
2701         }
2702         Vector<GridTrackSize> trackSizes;
2703         NamedGridLinesMap namedGridLines;
2704         if (!createGridTrackList(value, trackSizes, namedGridLines, state))
2705             return;
2706         state.style()->setGridRows(trackSizes);
2707         state.style()->setNamedGridRowLines(namedGridLines);
2708         return;
2709     }
2710
2711     case CSSPropertyWebkitGridColumnStart: {
2712         HANDLE_INHERIT_AND_INITIAL(gridItemColumnStart, GridItemColumnStart);
2713         GridPosition columnStartPosition;
2714         if (!createGridPosition(value, columnStartPosition))
2715             return;
2716         state.style()->setGridItemColumnStart(columnStartPosition);
2717         return;
2718     }
2719     case CSSPropertyWebkitGridColumnEnd: {
2720         HANDLE_INHERIT_AND_INITIAL(gridItemColumnEnd, GridItemColumnEnd);
2721         GridPosition columnEndPosition;
2722         if (!createGridPosition(value, columnEndPosition))
2723             return;
2724         state.style()->setGridItemColumnEnd(columnEndPosition);
2725         return;
2726     }
2727
2728     case CSSPropertyWebkitGridRowStart: {
2729         HANDLE_INHERIT_AND_INITIAL(gridItemRowStart, GridItemRowStart);
2730         GridPosition rowStartPosition;
2731         if (!createGridPosition(value, rowStartPosition))
2732             return;
2733         state.style()->setGridItemRowStart(rowStartPosition);
2734         return;
2735     }
2736     case CSSPropertyWebkitGridRowEnd: {
2737         HANDLE_INHERIT_AND_INITIAL(gridItemRowEnd, GridItemRowEnd);
2738         GridPosition rowEndPosition;
2739         if (!createGridPosition(value, rowEndPosition))
2740             return;
2741         state.style()->setGridItemRowEnd(rowEndPosition);
2742         return;
2743     }
2744     case CSSPropertyWebkitGridTemplate: {
2745         if (isInherit) {
2746             state.style()->setNamedGridArea(state.parentStyle()->namedGridArea());
2747             state.style()->setNamedGridAreaRowCount(state.parentStyle()->namedGridAreaRowCount());
2748             state.style()->setNamedGridAreaColumnCount(state.parentStyle()->namedGridAreaColumnCount());
2749             return;
2750         }
2751         if (isInitial) {
2752             state.style()->setNamedGridArea(RenderStyle::initialNamedGridArea());
2753             state.style()->setNamedGridAreaRowCount(RenderStyle::initialNamedGridAreaCount());
2754             state.style()->setNamedGridAreaColumnCount(RenderStyle::initialNamedGridAreaCount());
2755             return;
2756         }
2757
2758         if (value->isPrimitiveValue()) {
2759             ASSERT(toCSSPrimitiveValue(value)->getValueID() == CSSValueNone);
2760             return;
2761         }
2762
2763         CSSGridTemplateValue* gridTemplateValue = toCSSGridTemplateValue(value);
2764         state.style()->setNamedGridArea(gridTemplateValue->gridAreaMap());
2765         state.style()->setNamedGridAreaRowCount(gridTemplateValue->rowCount());
2766         state.style()->setNamedGridAreaColumnCount(gridTemplateValue->columnCount());
2767         return;
2768     }
2769
2770     // These properties are aliased and DeprecatedStyleBuilder already applied the property on the prefixed version.
2771     case CSSPropertyTransitionDelay:
2772     case CSSPropertyTransitionDuration:
2773     case CSSPropertyTransitionProperty:
2774     case CSSPropertyTransitionTimingFunction:
2775         return;
2776     // These properties are implemented in the DeprecatedStyleBuilder lookup table.
2777     case CSSPropertyBackgroundAttachment:
2778     case CSSPropertyBackgroundClip:
2779     case CSSPropertyBackgroundColor:
2780     case CSSPropertyBackgroundImage:
2781     case CSSPropertyBackgroundOrigin:
2782     case CSSPropertyBackgroundPositionX:
2783     case CSSPropertyBackgroundPositionY:
2784     case CSSPropertyBackgroundRepeatX:
2785     case CSSPropertyBackgroundRepeatY:
2786     case CSSPropertyBackgroundSize:
2787     case CSSPropertyBorderBottomColor:
2788     case CSSPropertyBorderBottomLeftRadius:
2789     case CSSPropertyBorderBottomRightRadius:
2790     case CSSPropertyBorderBottomStyle:
2791     case CSSPropertyBorderBottomWidth:
2792     case CSSPropertyBorderCollapse:
2793     case CSSPropertyBorderImageOutset:
2794     case CSSPropertyBorderImageRepeat:
2795     case CSSPropertyBorderImageSlice:
2796     case CSSPropertyBorderImageSource:
2797     case CSSPropertyBorderImageWidth:
2798     case CSSPropertyBorderLeftColor:
2799     case CSSPropertyBorderLeftStyle:
2800     case CSSPropertyBorderLeftWidth:
2801     case CSSPropertyBorderRightColor:
2802     case CSSPropertyBorderRightStyle:
2803     case CSSPropertyBorderRightWidth:
2804     case CSSPropertyBorderTopColor:
2805     case CSSPropertyBorderTopLeftRadius:
2806     case CSSPropertyBorderTopRightRadius:
2807     case CSSPropertyBorderTopStyle:
2808     case CSSPropertyBorderTopWidth:
2809     case CSSPropertyBottom:
2810     case CSSPropertyBoxSizing:
2811     case CSSPropertyCaptionSide:
2812     case CSSPropertyClear:
2813     case CSSPropertyClip:
2814     case CSSPropertyColor:
2815     case CSSPropertyCounterIncrement:
2816     case CSSPropertyCounterReset:
2817     case CSSPropertyCursor:
2818     case CSSPropertyDirection:
2819     case CSSPropertyDisplay:
2820     case CSSPropertyEmptyCells:
2821     case CSSPropertyFloat:
2822     case CSSPropertyFontSize:
2823     case CSSPropertyFontStyle:
2824     case CSSPropertyFontVariant:
2825     case CSSPropertyFontWeight:
2826     case CSSPropertyHeight:
2827 #if ENABLE(CSS_IMAGE_ORIENTATION)
2828     case CSSPropertyImageOrientation:
2829 #endif
2830     case CSSPropertyImageRendering:
2831 #if ENABLE(CSS_IMAGE_RESOLUTION)
2832     case CSSPropertyImageResolution:
2833 #endif
2834     case CSSPropertyLeft:
2835     case CSSPropertyLetterSpacing:
2836     case CSSPropertyLineHeight:
2837     case CSSPropertyListStyleImage:
2838     case CSSPropertyListStylePosition:
2839     case CSSPropertyListStyleType:
2840     case CSSPropertyMarginBottom:
2841     case CSSPropertyMarginLeft:
2842     case CSSPropertyMarginRight:
2843     case CSSPropertyMarginTop:
2844     case CSSPropertyMaxHeight:
2845     case CSSPropertyMaxWidth:
2846     case CSSPropertyMinHeight:
2847     case CSSPropertyMinWidth:
2848     case CSSPropertyObjectFit:
2849     case CSSPropertyOpacity:
2850     case CSSPropertyOrphans:
2851     case CSSPropertyOutlineColor:
2852     case CSSPropertyOutlineOffset:
2853     case CSSPropertyOutlineStyle:
2854     case CSSPropertyOutlineWidth:
2855     case CSSPropertyOverflowWrap:
2856     case CSSPropertyOverflowX:
2857     case CSSPropertyOverflowY:
2858     case CSSPropertyPaddingBottom:
2859     case CSSPropertyPaddingLeft:
2860     case CSSPropertyPaddingRight:
2861     case CSSPropertyPaddingTop:
2862     case CSSPropertyPageBreakAfter:
2863     case CSSPropertyPageBreakBefore:
2864     case CSSPropertyPageBreakInside:
2865     case CSSPropertyPointerEvents:
2866     case CSSPropertyPosition:
2867     case CSSPropertyResize:
2868     case CSSPropertyRight:
2869     case CSSPropertySize:
2870     case CSSPropertySpeak:
2871     case CSSPropertyTabSize:
2872     case CSSPropertyTableLayout:
2873     case CSSPropertyTextAlign:
2874     case CSSPropertyTextDecoration:
2875     case CSSPropertyTextIndent:
2876     case CSSPropertyTextOverflow:
2877     case CSSPropertyTextRendering:
2878     case CSSPropertyTextTransform:
2879     case CSSPropertyTop:
2880     case CSSPropertyUnicodeBidi:
2881     case CSSPropertyVerticalAlign:
2882     case CSSPropertyVisibility:
2883     case CSSPropertyWebkitAnimationDelay:
2884     case CSSPropertyWebkitAnimationDirection:
2885     case CSSPropertyWebkitAnimationDuration:
2886     case CSSPropertyWebkitAnimationFillMode:
2887     case CSSPropertyWebkitAnimationIterationCount:
2888     case CSSPropertyWebkitAnimationName:
2889     case CSSPropertyWebkitAnimationPlayState:
2890     case CSSPropertyWebkitAnimationTimingFunction:
2891     case CSSPropertyWebkitAppearance:
2892     case CSSPropertyWebkitAspectRatio:
2893     case CSSPropertyWebkitBackfaceVisibility:
2894     case CSSPropertyWebkitBackgroundClip:
2895     case CSSPropertyWebkitBackgroundComposite:
2896     case CSSPropertyWebkitBackgroundOrigin:
2897     case CSSPropertyWebkitBackgroundSize:
2898     case CSSPropertyWebkitBorderFit:
2899     case CSSPropertyWebkitBorderHorizontalSpacing:
2900     case CSSPropertyWebkitBorderImage:
2901     case CSSPropertyWebkitBorderVerticalSpacing:
2902     case CSSPropertyWebkitBoxAlign:
2903 #if ENABLE(CSS_BOX_DECORATION_BREAK)
2904     case CSSPropertyWebkitBoxDecorationBreak:
2905 #endif
2906     case CSSPropertyWebkitBoxDirection:
2907     case CSSPropertyWebkitBoxFlex:
2908     case CSSPropertyWebkitBoxFlexGroup:
2909     case CSSPropertyWebkitBoxLines:
2910     case CSSPropertyWebkitBoxOrdinalGroup:
2911     case CSSPropertyWebkitBoxOrient:
2912     case CSSPropertyWebkitBoxPack:
2913     case CSSPropertyWebkitColorCorrection:
2914     case CSSPropertyWebkitColumnAxis:
2915     case CSSPropertyWebkitColumnBreakAfter:
2916     case CSSPropertyWebkitColumnBreakBefore:
2917     case CSSPropertyWebkitColumnBreakInside:
2918     case CSSPropertyWebkitColumnCount:
2919     case CSSPropertyWebkitColumnGap:
2920     case CSSPropertyWebkitColumnProgression:
2921     case CSSPropertyWebkitColumnRuleColor:
2922     case CSSPropertyWebkitColumnRuleStyle:
2923     case CSSPropertyWebkitColumnRuleWidth:
2924     case CSSPropertyWebkitColumnSpan:
2925     case CSSPropertyWebkitColumnWidth:
2926 #if ENABLE(CURSOR_VISIBILITY)
2927     case CSSPropertyWebkitCursorVisibility:
2928 #endif
2929     case CSSPropertyWebkitAlignContent:
2930     case CSSPropertyWebkitAlignItems:
2931     case CSSPropertyWebkitAlignSelf:
2932     case CSSPropertyWebkitFlexBasis:
2933     case CSSPropertyWebkitFlexDirection:
2934     case CSSPropertyWebkitFlexGrow:
2935     case CSSPropertyWebkitFlexShrink:
2936     case CSSPropertyWebkitFlexWrap:
2937     case CSSPropertyWebkitJustifyContent:
2938     case CSSPropertyWebkitOrder:
2939 #if ENABLE(CSS_REGIONS)
2940     case CSSPropertyWebkitFlowFrom:
2941     case CSSPropertyWebkitFlowInto:
2942 #endif
2943     case CSSPropertyWebkitFontKerning:
2944     case CSSPropertyWebkitFontSmoothing:
2945     case CSSPropertyWebkitFontVariantLigatures:
2946     case CSSPropertyWebkitHighlight:
2947     case CSSPropertyWebkitHyphenateCharacter:
2948     case CSSPropertyWebkitHyphenateLimitAfter:
2949     case CSSPropertyWebkitHyphenateLimitBefore:
2950     case CSSPropertyWebkitHyphenateLimitLines:
2951     case CSSPropertyWebkitHyphens:
2952     case CSSPropertyWebkitLineAlign:
2953     case CSSPropertyWebkitLineBreak:
2954     case CSSPropertyWebkitLineClamp:
2955     case CSSPropertyWebkitLineGrid:
2956     case CSSPropertyWebkitLineSnap:
2957     case CSSPropertyWebkitMarqueeDirection:
2958     case CSSPropertyWebkitMarqueeIncrement:
2959     case CSSPropertyWebkitMarqueeRepetition:
2960     case CSSPropertyWebkitMarqueeSpeed:
2961     case CSSPropertyWebkitMarqueeStyle:
2962     case CSSPropertyWebkitMaskBoxImage:
2963     case CSSPropertyWebkitMaskBoxImageOutset:
2964     case CSSPropertyWebkitMaskBoxImageRepeat:
2965     case CSSPropertyWebkitMaskBoxImageSlice:
2966     case CSSPropertyWebkitMaskBoxImageSource:
2967     case CSSPropertyWebkitMaskBoxImageWidth:
2968     case CSSPropertyWebkitMaskClip:
2969     case CSSPropertyWebkitMaskComposite:
2970     case CSSPropertyWebkitMaskImage:
2971     case CSSPropertyWebkitMaskOrigin:
2972     case CSSPropertyWebkitMaskPositionX:
2973     case CSSPropertyWebkitMaskPositionY:
2974     case CSSPropertyWebkitMaskRepeatX:
2975     case CSSPropertyWebkitMaskRepeatY:
2976     case CSSPropertyWebkitMaskSize:
2977     case CSSPropertyWebkitMaskSourceType:
2978     case CSSPropertyWebkitNbspMode:
2979     case CSSPropertyWebkitPerspectiveOrigin:
2980     case CSSPropertyWebkitPerspectiveOriginX:
2981     case CSSPropertyWebkitPerspectiveOriginY:
2982     case CSSPropertyWebkitPrintColorAdjust:
2983 #if ENABLE(CSS_REGIONS)
2984     case CSSPropertyWebkitRegionBreakAfter:
2985     case CSSPropertyWebkitRegionBreakBefore:
2986     case CSSPropertyWebkitRegionBreakInside:
2987     case CSSPropertyWebkitRegionFragment:
2988 #endif
2989     case CSSPropertyWebkitRtlOrdering:
2990     case CSSPropertyWebkitRubyPosition:
2991     case CSSPropertyWebkitTextCombine:
2992 #if ENABLE(CSS3_TEXT)
2993     case CSSPropertyWebkitTextAlignLast:
2994     case CSSPropertyWebkitTextJustify:
2995 #endif // CSS3_TEXT
2996 #if ENABLE(CSS3_TEXT_DECORATION)
2997     case CSSPropertyWebkitTextDecorationLine:
2998     case CSSPropertyWebkitTextDecorationStyle:
2999     case CSSPropertyWebkitTextDecorationColor:
3000     case CSSPropertyWebkitTextDecorationSkip:
3001     case CSSPropertyWebkitTextUnderlinePosition:
3002 #endif
3003     case CSSPropertyWebkitTextEmphasisColor:
3004     case CSSPropertyWebkitTextEmphasisPosition:
3005     case CSSPropertyWebkitTextEmphasisStyle:
3006     case CSSPropertyWebkitTextFillColor:
3007     case CSSPropertyWebkitTextSecurity:
3008     case CSSPropertyWebkitTextStrokeColor:
3009     case CSSPropertyWebkitTransformOriginX:
3010     case CSSPropertyWebkitTransformOriginY:
3011     case CSSPropertyWebkitTransformOriginZ:
3012     case CSSPropertyWebkitTransformStyle:
3013     case CSSPropertyWebkitTransitionDelay:
3014     case CSSPropertyWebkitTransitionDuration:
3015     case CSSPropertyWebkitTransitionProperty:
3016     case CSSPropertyWebkitTransitionTimingFunction:
3017     case CSSPropertyWebkitUserDrag:
3018     case CSSPropertyWebkitUserModify:
3019     case CSSPropertyWebkitUserSelect:
3020     case CSSPropertyWebkitClipPath:
3021 #if ENABLE(CSS_SHAPES)
3022     case CSSPropertyWebkitShapeMargin:
3023     case CSSPropertyWebkitShapePadding:
3024     case CSSPropertyWebkitShapeImageThreshold:
3025     case CSSPropertyWebkitShapeInside:
3026     case CSSPropertyWebkitShapeOutside:
3027 #endif
3028 #if ENABLE(CSS_EXCLUSIONS)
3029     case CSSPropertyWebkitWrapFlow:
3030     case CSSPropertyWebkitWrapThrough:
3031 #endif
3032 #if ENABLE(CSS_SHADERS)
3033     case CSSPropertyMix:
3034     case CSSPropertyParameters:
3035 #endif
3036     case CSSPropertyWhiteSpace:
3037     case CSSPropertyWidows:
3038     case CSSPropertyWidth:
3039     case CSSPropertyWordBreak:
3040     case CSSPropertyWordSpacing:
3041     case CSSPropertyWordWrap:
3042     case CSSPropertyZIndex:
3043     case CSSPropertyZoom:
3044 #if ENABLE(CSS_DEVICE_ADAPTATION)
3045     case CSSPropertyMaxZoom:
3046     case CSSPropertyMinZoom:
3047     case CSSPropertyOrientation:
3048     case CSSPropertyUserZoom:
3049 #endif
3050         ASSERT_NOT_REACHED();
3051         return;
3052     default:
3053 #if ENABLE(SVG)
3054         // Try the SVG properties
3055         applySVGProperty(id, value);
3056 #endif
3057         return;
3058     }
3059 }
3060
3061 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue* value)
3062 {
3063     if (value->isImageValue())
3064         return cachedOrPendingFromValue(property, toCSSImageValue(value));
3065
3066     if (value->isImageGeneratorValue()) {
3067         if (value->isGradientValue())
3068             return generatedOrPendingFromValue(property, *toCSSGradientValue(value)->gradientWithStylesResolved(this));
3069         return generatedOrPendingFromValue(property, toCSSImageGeneratorValue(*value));
3070     }
3071
3072 #if ENABLE(CSS_IMAGE_SET)
3073     if (value->isImageSetValue())
3074         return setOrPendingFromValue(property, toCSSImageSetValue(value));
3075 #endif
3076
3077     if (value->isCursorImageValue())
3078         return cursorOrPendingFromValue(property, toCSSCursorImageValue(value));
3079
3080     return 0;
3081 }
3082
3083 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue* value)
3084 {
3085     RefPtr<StyleImage> image = value->cachedOrPendingImage();
3086     if (image && image->isPendingImage())
3087         m_state.pendingImageProperties().set(property, value);
3088     return image.release();
3089 }
3090
3091 PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
3092 {
3093 #if ENABLE(CSS_FILTERS)
3094     if (value.isFilterImageValue()) {
3095         // FilterImage needs to calculate FilterOperations.
3096         toCSSFilterImageValue(value).createFilterOperations(this);
3097     }
3098 #endif
3099     if (value.isPending()) {
3100         m_state.pendingImageProperties().set(property, &value);
3101         return StylePendingImage::create(&value);
3102     }
3103     return StyleGeneratedImage::create(value);
3104 }
3105
3106 #if ENABLE(CSS_IMAGE_SET)
3107 PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value)
3108 {
3109     RefPtr<StyleImage> image = value->cachedOrPendingImageSet(document());
3110     if (image && image->isPendingImage())
3111         m_state.pendingImageProperties().set(property, value);
3112     return image.release();
3113 }
3114 #endif
3115
3116 PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue* value)
3117 {
3118     RefPtr<StyleImage> image = value->cachedOrPendingImage(document());
3119     if (image && image->isPendingImage())
3120         m_state.pendingImageProperties().set(property, value);
3121     return image.release();
3122 }
3123
3124 #if ENABLE(IOS_TEXT_AUTOSIZING)
3125 void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
3126 {
3127     if (style->textSizeAdjust().isAuto())
3128         return;
3129
3130     FontDescription newFontDescription(style->fontDescription());
3131     if (!style->textSizeAdjust().isNone())
3132         newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier());
3133     else
3134         newFontDescription.setComputedSize(newFontDescription.specifiedSize());
3135     style->setFontDescription(newFontDescription);
3136 }
3137 #endif
3138
3139 void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
3140 {
3141     if (style->effectiveZoom() == parentStyle->effectiveZoom())
3142         return;
3143
3144     const FontDescription& childFont = style->fontDescription();
3145     FontDescription newFontDescription(childFont);
3146     setFontSize(newFontDescription, childFont.specifiedSize());
3147     style->setFontDescription(newFontDescription);
3148 }
3149
3150 void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
3151 {
3152     const FontDescription& childFont = style->fontDescription();
3153
3154     if (childFont.isAbsoluteSize() || !parentStyle)
3155         return;
3156
3157     const FontDescription& parentFont = parentStyle->fontDescription();
3158     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
3159         return;
3160
3161     // For now, lump all families but monospace together.
3162     if (childFont.genericFamily() != FontDescription::MonospaceFamily
3163         && parentFont.genericFamily() != FontDescription::MonospaceFamily)
3164         return;
3165
3166     // We know the parent is monospace or the child is monospace, and that font
3167     // size was unspecified. We want to scale our font size as appropriate.
3168     // If the font uses a keyword size, then we refetch from the table rather than
3169     // multiplying by our scale factor.
3170     float size;
3171     if (childFont.keywordSize())
3172         size = Style::fontSizeForKeyword(CSSValueXxSmall + childFont.keywordSize() - 1, childFont.useFixedDefaultSize(), document());
3173     else {
3174         Settings* settings = documentSettings();
3175         float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
3176             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
3177             : 1;
3178         size = parentFont.useFixedDefaultSize() ?
3179                 childFont.specifiedSize() / fixedScaleFactor :
3180                 childFont.specifiedSize() * fixedScaleFactor;
3181     }
3182
3183     FontDescription newFontDescription(childFont);
3184     setFontSize(newFontDescription, size);
3185     style->setFontDescription(newFontDescription);
3186 }
3187
3188 void StyleResolver::initializeFontStyle(Settings* settings)
3189 {
3190     FontDescription fontDescription;
3191     fontDescription.setGenericFamily(FontDescription::StandardFamily);
3192     fontDescription.setRenderingMode(settings->fontRenderingMode());
3193     fontDescription.setUsePrinterFont(document().printing() || !settings->screenFontSubstitutionEnabled());
3194     const AtomicString& standardFontFamily = documentSettings()->standardFontFamily();
3195     if (!standardFontFamily.isEmpty())
3196         fontDescription.setOneFamily(standardFontFamily);
3197     fontDescription.setKeywordSize(CSSValueMedium - CSSValueXxSmall + 1);
3198     setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
3199     m_state.style()->setLineHeight(RenderStyle::initialLineHeight());
3200     m_state.setLineHeightValue(0);
3201     setFontDescription(fontDescription);
3202 }
3203
3204 void StyleResolver::setFontSize(FontDescription& fontDescription, float size)
3205 {
3206     fontDescription.setSpecifiedSize(size);
3207     fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
3208 }
3209
3210 static Color colorForCSSValue(CSSValueID cssValueId)
3211 {
3212     struct ColorValue {
3213         CSSValueID cssValueId;
3214         RGBA32 color;
3215     };
3216
3217     static const ColorValue colorValues[] = {
3218         { CSSValueAqua, 0xFF00FFFF },
3219         { CSSValueBlack, 0xFF000000 },
3220         { CSSValueBlue, 0xFF0000FF },
3221         { CSSValueFuchsia, 0xFFFF00FF },
3222         { CSSValueGray, 0xFF808080 },
3223         { CSSValueGreen, 0xFF008000  },
3224         { CSSValueGrey, 0xFF808080 },
3225         { CSSValueLime, 0xFF00FF00 },
3226         { CSSValueMaroon, 0xFF800000 },
3227         { CSSValueNavy, 0xFF000080 },
3228         { CSSValueOlive, 0xFF808000  },
3229         { CSSValueOrange, 0xFFFFA500 },
3230         { CSSValuePurple, 0xFF800080 },
3231         { CSSValueRed, 0xFFFF0000 },
3232         { CSSValueSilver, 0xFFC0C0C0 },
3233         { CSSValueTeal, 0xFF008080  },
3234         { CSSValueTransparent, 0x00000000 },
3235         { CSSValueWhite, 0xFFFFFFFF },
3236         { CSSValueYellow, 0xFFFFFF00 },
3237         { CSSValueInvalid, CSSValueInvalid }
3238     };
3239
3240     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
3241         if (col->cssValueId == cssValueId)
3242             return col->color;
3243     }
3244     return RenderTheme::defaultTheme()->systemColor(cssValueId);
3245 }
3246
3247 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue* value)
3248 {
3249     int ident = value->getValueID();
3250     switch (ident) {
3251     case CSSValueWebkitText:
3252     case CSSValueWebkitLink:
3253     case CSSValueWebkitActivelink:
3254     case CSSValueCurrentcolor:
3255         return true;
3256     default:
3257         return false;
3258     }
3259 }
3260
3261 Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue* value, bool forVisitedLink) const
3262 {
3263     if (value->isRGBColor())
3264         return Color(value->getRGBA32Value());
3265
3266     const State& state = m_state;
3267     CSSValueID ident = value->getValueID();
3268     switch (ident) {
3269     case 0:
3270         return Color();
3271     case CSSValueWebkitText:
3272         return state.document().textColor();
3273     case CSSValueWebkitLink:
3274         return (state.element()->isLink() && forVisitedLink) ? state.document().visitedLinkColor() : state.document().linkColor();
3275     case CSSValueWebkitActivelink:
3276         return state.document().activeLinkColor();
3277     case CSSValueWebkitFocusRingColor:
3278         return RenderTheme::focusRingColor();
3279     case CSSValueCurrentcolor:
3280         return state.style()->color();
3281     default:
3282         return colorForCSSValue(ident);
3283     }
3284 }
3285
3286 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
3287 {
3288     m_viewportDependentMediaQueryResults.append(adoptPtr(new MediaQueryResult(*expr, result)));
3289 }
3290
3291 bool StyleResolver::affectedByViewportChange() const
3292 {
3293     unsigned s = m_viewportDependentMediaQueryResults.size();
3294     for (unsigned i = 0; i < s; i++) {
3295         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
3296             return true;
3297     }
3298     return false;
3299 }
3300
3301 #if ENABLE(CSS_FILTERS)
3302 static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
3303 {
3304     switch (type) {
3305     case WebKitCSSFilterValue::ReferenceFilterOperation:
3306         return FilterOperation::REFERENCE;
3307     case WebKitCSSFilterValue::GrayscaleFilterOperation:
3308         return FilterOperation::GRAYSCALE;
3309     case WebKitCSSFilterValue::SepiaFilterOperation:
3310         return FilterOperation::SEPIA;
3311     case WebKitCSSFilterValue::SaturateFilterOperation:
3312         return FilterOperation::SATURATE;
3313     case WebKitCSSFilterValue::HueRotateFilterOperation:
3314         return FilterOperation::HUE_ROTATE;
3315     case WebKitCSSFilterValue::InvertFilterOperation:
3316         return FilterOperation::INVERT;
3317     case WebKitCSSFilterValue::OpacityFilterOperation:
3318         return FilterOperation::OPACITY;
3319     case WebKitCSSFilterValue::BrightnessFilterOperation:
3320         return FilterOperation::BRIGHTNESS;
3321     case WebKitCSSFilterValue::ContrastFilterOperation:
3322         return FilterOperation::CONTRAST;
3323     case WebKitCSSFilterValue::BlurFilterOperation:
3324         return FilterOperation::BLUR;
3325     case WebKitCSSFilterValue::DropShadowFilterOperation:
3326         return FilterOperation::DROP_SHADOW;
3327 #if ENABLE(CSS_SHADERS)
3328     case WebKitCSSFilterValue::CustomFilterOperation:
3329         return FilterOperation::CUSTOM;
3330 #endif
3331     case WebKitCSSFilterValue::UnknownFilterOperation:
3332         return FilterOperation::NONE;
3333     }
3334     return FilterOperation::NONE;
3335 }
3336
3337 #if ENABLE(CSS_FILTERS) && ENABLE(SVG)
3338 void StyleResolver::loadPendingSVGDocuments()
3339 {
3340     State& state = m_state;
3341
3342     // Crash reports indicate that we've seen calls to this function when our
3343     // style is NULL. We don't know exactly why this happens. Our guess is
3344     // reentering styleForElement().
3345     ASSERT(state.style());
3346     if (!state.style() || !state.style()->hasFilter() || state.pendingSVGDocuments().isEmpty())
3347         return;
3348
3349     CachedResourceLoader* cachedResourceLoader = state.document().cachedResourceLoader();
3350     Vector<RefPtr<FilterOperation>>& filterOperations = state.style()->mutableFilter().operations();
3351     for (unsigned i = 0; i < filterOperations.size(); ++i) {
3352         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
3353         if (filterOperation->type() == FilterOperation::REFERENCE) {
3354             ReferenceFilterOperation* referenceFilter = static_cast<ReferenceFilterOperation*>(filterOperation.get());
3355
3356             WebKitCSSSVGDocumentValue* value = state.pendingSVGDocuments().get(referenceFilter);
3357             if (!value)
3358                 continue;
3359             CachedSVGDocument* cachedDocument = value->load(cachedResourceLoader);
3360             if (!cachedDocument)
3361                 continue;
3362
3363             // Stash the CachedSVGDocument on the reference filter.
3364             referenceFilter->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(cachedDocument)));
3365         }
3366     }
3367     state.pendingSVGDocuments().clear();
3368 }
3369 #endif
3370
3371 #if ENABLE(CSS_SHADERS)
3372 StyleShader* StyleResolver::styleShader(CSSValue* value)
3373 {
3374     if (value->isWebKitCSSShaderValue())
3375         return cachedOrPendingStyleShaderFromValue(toWebKitCSSShaderValue(value));
3376     return 0;
3377 }
3378
3379 StyleShader* StyleResolver::cachedOrPendingStyleShaderFromValue(WebKitCSSShaderValue* value)
3380 {
3381     StyleShader* shader = value->cachedOrPendingShader();
3382     if (shader && shader->isPendingShader())
3383         m_state.setHasPendingShaders(true);
3384     return shader;
3385 }
3386
3387 PassRefPtr<CustomFilterProgram> StyleResolver::lookupCustomFilterProgram(WebKitCSSShaderValue* vertexShader, WebKitCSSShaderValue* fragmentShader, 
3388     CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
3389 {
3390     CachedResourceLoader* cachedResourceLoader = m_state.document().cachedResourceLoader();
3391     URL vertexShaderURL = vertexShader ? vertexShader->completeURL(cachedResourceLoader) : URL();
3392     URL fragmentShaderURL = fragmentShader ? fragmentShader->completeURL(cachedResourceLoader) : URL();
3393     RefPtr<StyleCustomFilterProgram> program;
3394     if (m_customFilterProgramCache)
3395         program = m_customFilterProgramCache->lookup(CustomFilterProgramInfo(vertexShaderURL, fragmentShaderURL, programType, mixSettings, meshType));
3396     if (!program) {
3397         // Create a new StyleCustomFilterProgram that will be resolved during the loadPendingShaders and added to the cache.
3398         program = StyleCustomFilterProgram::create(vertexShaderURL, vertexShader ? styleShader(vertexShader) : 0, 
3399             fragmentShaderURL, fragmentShader ? styleShader(fragmentShader) : 0, programType, mixSettings, meshType);
3400     }
3401     return program.release();
3402 }
3403
3404 void StyleResolver::loadPendingShaders()
3405 {
3406     // FIXME: We shouldn't have to check that style is non-null. This is a speculative fix for:
3407     // https://bugs.webkit.org/show_bug.cgi?id=117665
3408     if (!m_state.hasPendingShaders() || !m_state.style() || !m_state.style()->hasFilter())
3409         return;
3410
3411     CachedResourceLoader* cachedResourceLoader = m_state.document().cachedResourceLoader();
3412
3413     Vector<RefPtr<FilterOperation>>& filterOperations = m_state.style()->mutableFilter().operations();
3414     for (unsigned i = 0; i < filterOperations.size(); ++i) {
3415         RefPtr<FilterOperation> filterOperation = filterOperations.at(i);
3416         if (filterOperation->type() == FilterOperation::CUSTOM) {
3417             CustomFilterOperation* customFilter = static_cast<CustomFilterOperation*>(filterOperation.get());
3418             ASSERT(customFilter->program());
3419             StyleCustomFilterProgram* program = static_cast<StyleCustomFilterProgram*>(customFilter->program());
3420             // Note that the StylePendingShaders could be already resolved to StyleCachedShaders. That's because the rule was matched before.
3421             // However, the StyleCustomFilterProgram that was initially created could have been removed from the cache in the meanwhile,
3422             // meaning that we get a new StyleCustomFilterProgram here that is not yet in the cache, but already has loaded StyleShaders.
3423             if (!program->hasPendingShaders() && program->inCache())
3424                 continue;
3425             if (!m_customFilterProgramCache)
3426                 m_customFilterProgramCache = adoptPtr(new StyleCustomFilterProgramCache());
3427             RefPtr<StyleCustomFilterProgram> styleProgram = m_customFilterProgramCache->lookup(program);
3428             if (styleProgram.get())
3429                 customFilter->setProgram(styleProgram.release());
3430             else {
3431                 if (program->vertexShader() && program->vertexShader()->isPendingShader()) {
3432                     WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->vertexShader())->cssShaderValue();
3433                     program->setVertexShader(shaderValue->cachedShader(cachedResourceLoader));
3434                 }
3435                 if (program->fragmentShader() && program->fragmentShader()->isPendingShader()) {
3436                     WebKitCSSShaderValue* shaderValue = static_cast<StylePendingShader*>(program->fragmentShader())->cssShaderValue();
3437                     program->setFragmentShader(shaderValue->cachedShader(cachedResourceLoader));
3438                 }
3439                 m_customFilterProgramCache->add(program);
3440             }
3441         }
3442     }
3443     m_state.setHasPendingShaders(false);
3444 }
3445
3446 static bool sortParametersByNameComparator(const RefPtr<CustomFilterParameter>& a, const RefPtr<CustomFilterParameter>& b)
3447 {
3448     return codePointCompareLessThan(a->name(), b->name());
3449 }
3450
3451 PassRefPtr<CustomFilterParameter> StyleResolver::parseCustomFilterArrayParameter(const String& name, CSSValueList* values, bool isArray)
3452 {
3453     RefPtr<CustomFilterArrayParameter> arrayParameter = CustomFilterArrayParameter::create(name, isArray ? CustomFilterArrayParameter::ARRAY : CustomFilterArrayParameter::MATRIX);
3454     for (unsigned i = 0, length = values->length(); i < length; ++i) {
3455         CSSValue* value = values->itemWithoutBoundsCheck(i);
3456         if (!value->isPrimitiveValue())
3457             return 0;
3458         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(value);
3459         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_NUMBER)
3460             return 0;
3461         arrayParameter->addValue(primitiveValue->getDoubleValue());
3462     }
3463     return arrayParameter.release();
3464 }
3465
3466 PassRefPtr<CustomFilterParameter> StyleResolver::parseCustomFilterColorParameter(const String& name, CSSValueList* values)
3467 {
3468     ASSERT(values->length());
3469     CSSPrimitiveValue* firstPrimitiveValue = toCSSPrimitiveValue(values->itemWithoutBoundsCheck(0));
3470     RefPtr<CustomFilterColorParameter> colorParameter = CustomFilterColorParameter::create(name);
3471     colorParameter->setColor(Color(firstPrimitiveValue->getRGBA32Value()));
3472     return colorParameter.release();
3473 }
3474
3475 PassRefPtr<CustomFilterParameter> StyleResolver::parseCustomFilterNumberParameter(const String& name, CSSValueList* values)
3476 {
3477     RefPtr<CustomFilterNumberParameter> numberParameter = CustomFilterNumberParameter::create(name);
3478     for (unsigned i = 0; i < values->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         numberParameter->addValue(primitiveValue->getDoubleValue());
3486     }
3487     return numberParameter.release();
3488 }
3489
3490 PassRefPtr<CustomFilterParameter> StyleResolver::parseCustomFilterTransformParameter(const String& name, CSSValueList* values)
3491 {
3492     RefPtr<CustomFilterTransformParameter> transformParameter = CustomFilterTransformParameter::create(name);
3493     TransformOperations operations;
3494     transformsForValue(m_state.style(), m_state.rootElementStyle(), values, operations);
3495     transformParameter->setOperations(operations);
3496     return transformParameter.release();
3497 }
3498
3499 PassRefPtr<CustomFilterParameter> StyleResolver::parseCustomFilterParameter(const String& name, CSSValue* parameterValue)
3500 {
3501     // FIXME: Implement other parameters types parsing.
3502     // textures: https://bugs.webkit.org/show_bug.cgi?id=71442
3503     // mat2, mat3, mat4: https://bugs.webkit.org/show_bug.cgi?id=71444
3504     // Number parameters are wrapped inside a CSSValueList and all
3505     // the other functions values inherit from CSSValueList.
3506     if (!parameterValue->isValueList())
3507         return 0;
3508
3509     CSSValueList* values = toCSSValueList(parameterValue);
3510     if (!values->length())
3511         return 0;
3512
3513     if (parameterValue->isWebKitCSSArrayFunctionValue())
3514         return parseCustomFilterArrayParameter(name, values, true);
3515
3516     if (parameterValue->isWebKitCSSMatFunctionValue())
3517         return parseCustomFilterArrayParameter(name, values, false);
3518
3519     // If the first value of the list is a transform function,
3520     // then we could safely assume that all the remaining items
3521     // are transforms. parseCustomFilterTransformParameter will
3522     // return 0 if that assumption is incorrect.
3523     if (values->itemWithoutBoundsCheck(0)->isWebKitCSSTransformValue())
3524         return parseCustomFilterTransformParameter(name, values);
3525
3526     // We can only have arrays of colors or numbers, so use the first value to choose between those two.
3527     // We need up to 4 values (all booleans or all numbers).
3528     if (!values->itemWithoutBoundsCheck(0)->isPrimitiveValue() || values->length() > 4)
3529         return 0;
3530     
3531     CSSPrimitiveValue* firstPrimitiveValue = toCSSPrimitiveValue(values->itemWithoutBoundsCheck(0));
3532     if (firstPrimitiveValue->primitiveType() == CSSPrimitiveValue::CSS_NUMBER)
3533         return parseCustomFilterNumberParameter(name, values);
3534
3535     if (firstPrimitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR)
3536         return parseCustomFilterColorParameter(name, values);
3537
3538     return 0;
3539 }
3540
3541 bool StyleResolver::parseCustomFilterParameterList(CSSValue* parametersValue, CustomFilterParameterList& parameterList)
3542 {
3543     HashSet<String> knownParameterNames;
3544     CSSValueListIterator parameterIterator(parametersValue);
3545     for (; parameterIterator.hasMore(); parameterIterator.advance()) {
3546         if (!parameterIterator.value()->isValueList())
3547             return false;
3548         CSSValueListIterator iterator(parameterIterator.value());
3549         if (!iterator.isPrimitiveValue())
3550             return false;
3551         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
3552         if (primitiveValue->primitiveType() != CSSPrimitiveValue::CSS_STRING)
3553             return false;
3554         
3555         String name = primitiveValue->getStringValue();
3556         // Do not allow duplicate parameter names.
3557         if (knownParameterNames.contains(name))
3558             return false;
3559         knownParameterNames.add(name);
3560         
3561         iterator.advance();
3562         
3563         if (!iterator.hasMore())
3564             return false;
3565         
3566         RefPtr<CustomFilterParameter> parameter = parseCustomFilterParameter(name, iterator.value());
3567         if (!parameter)
3568             return false;
3569         parameterList.append(parameter.release());
3570     }
3571     
3572     // Make sure we sort the parameters before passing them down to the CustomFilterOperation.
3573     std::sort(parameterList.begin(), parameterList.end(), sortParametersByNameComparator);
3574     
3575     return true;
3576 }
3577
3578 PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperationWithAtRuleReferenceSyntax(WebKitCSSFilterValue* filterValue)
3579 {
3580     // FIXME: Implement style resolution for the custom filter at-rule reference syntax.
3581     UNUSED_PARAM(filterValue);
3582     return 0;
3583 }
3584
3585 PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperationWithInlineSyntax(WebKitCSSFilterValue* filterValue)
3586 {
3587     CSSValue* shadersValue = filterValue->itemWithoutBoundsCheck(0);
3588     ASSERT_WITH_SECURITY_IMPLICATION(shadersValue->isValueList());
3589     CSSValueList* shadersList = toCSSValueList(shadersValue);
3590
3591     unsigned shadersListLength = shadersList->length();
3592     ASSERT(shadersListLength);
3593
3594
3595     WebKitCSSShaderValue* vertexShader = 0;
3596     WebKitCSSShaderValue* fragmentShader = 0;
3597
3598     if (shadersList->itemWithoutBoundsCheck(0)->isWebKitCSSShaderValue())
3599         vertexShader = toWebKitCSSShaderValue(shadersList->itemWithoutBoundsCheck(0));
3600
3601     CustomFilterProgramType programType = PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE;
3602     CustomFilterProgramMixSettings mixSettings;
3603
3604     if (shadersListLength > 1) {
3605         CSSValue* fragmentShaderOrMixFunction = shadersList->itemWithoutBoundsCheck(1);
3606         if (fragmentShaderOrMixFunction->isWebKitCSSMixFunctionValue()) {
3607             WebKitCSSMixFunctionValue* mixFunction = toWebKitCSSMixFunctionValue(fragmentShaderOrMixFunction);
3608             CSSValueListIterator iterator(mixFunction);
3609
3610             ASSERT(mixFunction->length());
3611             if (iterator.value()->isWebKitCSSShaderValue())
3612                 fragmentShader = toWebKitCSSShaderValue(iterator.value());
3613
3614             iterator.advance();
3615
3616             ASSERT(mixFunction->length() <= 3);
3617             while (iterator.hasMore()) {
3618                 CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
3619                 if (CSSParser::isBlendMode(primitiveValue->getValueID()))
3620                     mixSettings.blendMode = *primitiveValue;
3621                 else if (CSSParser::isCompositeOperator(primitiveValue->getValueID()))
3622                     mixSettings.compositeOperator = *primitiveValue;
3623                 else
3624                     ASSERT_NOT_REACHED();
3625                 iterator.advance();
3626             }
3627         } else {
3628             programType = PROGRAM_TYPE_NO_ELEMENT_TEXTURE;
3629             if (fragmentShaderOrMixFunction->isWebKitCSSShaderValue())
3630                 fragmentShader = toWebKitCSSShaderValue(fragmentShaderOrMixFunction);
3631         }
3632     }
3633
3634     if (!vertexShader && !fragmentShader)
3635         return 0;
3636
3637     unsigned meshRows = 1;
3638     unsigned meshColumns = 1;
3639     CustomFilterMeshType meshType = MeshTypeAttached;
3640     
3641     CSSValue* parametersValue = 0;
3642     
3643     if (filterValue->length() > 1) {
3644         CSSValueListIterator iterator(filterValue->itemWithoutBoundsCheck(1));
3645         
3646         // The second value might be the mesh box or the list of parameters:
3647         // If it starts with a number or any of the mesh-box identifiers it is 
3648         // the mesh-box list, if not it means it is the parameters list.
3649
3650         if (iterator.hasMore() && iterator.isPrimitiveValue()) {
3651             CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
3652             if (primitiveValue->isNumber()) {
3653                 // If only one integer value is specified, it will set both
3654                 // the rows and the columns.
3655                 meshColumns = meshRows = primitiveValue->getIntValue();
3656                 iterator.advance();
3657                 
3658                 // Try to match another number for the rows.
3659                 if (iterator.hasMore() && iterator.isPrimitiveValue()) {
3660                     CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
3661                     if (primitiveValue->isNumber()) {
3662                         meshRows = primitiveValue->getIntValue();
3663                         iterator.advance();
3664                     }
3665                 }
3666             }
3667         }
3668         
3669         if (iterator.hasMore() && iterator.isPrimitiveValue()) {
3670             CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(iterator.value());
3671             if (primitiveValue->getValueID() == CSSValueDetached) {
3672                 meshType = MeshTypeDetached;
3673                 iterator.advance();
3674             }
3675         }
3676         
3677         if (!iterator.index()) {
3678             // If no value was consumed from the mesh value, then it is just a parameter list, meaning that we end up
3679             // having just two CSSListValues: list of shaders and list of parameters.
3680             ASSERT(filterValue->length() == 2);
3681             parametersValue = filterValue->itemWithoutBoundsCheck(1);
3682         }
3683     }
3684     
3685     if (filterValue->length() > 2 && !parametersValue)
3686         parametersValue = filterValue->itemWithoutBoundsCheck(2);
3687     
3688     CustomFilterParameterList parameterList;
3689     if (parametersValue && !parseCustomFilterParameterList(parametersValue, parameterList))
3690         return 0;
3691
3692     RefPtr<CustomFilterProgram> program = lookupCustomFilterProgram(vertexShader, fragmentShader, programType, mixSettings, meshType);
3693     return CustomFilterOperation::create(program.release(), parameterList, meshRows, meshColumns);
3694 }
3695
3696 PassRefPtr<CustomFilterOperation> StyleResolver::createCustomFilterOperation(WebKitCSSFilterValue* filterValue)
3697 {
3698     ASSERT(filterValue->length());
3699     bool isAtRuleReferenceSyntax = filterValue->itemWithoutBoundsCheck(0)->isPrimitiveValue();
3700     return isAtRuleReferenceSyntax ? createCustomFilterOperationWithAtRuleReferenceSyntax(filterValue) : createCustomFilterOperationWithInlineSyntax(filterValue);
3701 }
3702
3703 #endif
3704
3705 bool StyleResolver::createFilterOperations(CSSValue* inValue, FilterOperations& outOperations)
3706 {
3707     State& state = m_state;
3708     RenderStyle* style = state.style();
3709     RenderStyle* rootStyle = state.rootElementStyle();
3710     ASSERT(outOperations.isEmpty());
3711     
3712     if (!inValue)
3713         return false;
3714     
3715     if (inValue->isPrimitiveValue()) {
3716         CSSPrimitiveValue* primitiveValue = toCSSPrimitiveValue(inValue);
3717         if (primitiveValue->getValueID() == CSSValueNone)
3718             return true;
3719     }
3720     
3721     if (!inValue->isValueList())
3722         return false;
3723
3724     float zoomFactor = style ? style->effectiveZoom() : 1;
3725     FilterOperations operations;
3726     for (CSSValueListIterator i = inValue; i.hasMore(); i.advance()) {
3727         CSSValue* currValue = i.value();
3728         if (!currValue->isWebKitCSSFilterValue())
3729             continue;
3730
3731         WebKitCSSFilterValue* filterValue = toWebKitCSSFilterValue(i.value());
3732         FilterOperation::OperationType operationType = filterOperationForType(filterValue->operationType());
3733
3734 #if ENABLE(CSS_SHADERS)
3735         if (operationType == FilterOperation::VALIDATED_CUSTOM) {
3736             // ValidatedCustomFilterOperation is not supposed to end up in the RenderStyle.
3737             ASSERT_NOT_REACHED();
3738             continue;
3739         }
3740         if (operationType == FilterOperation::CUSTOM) {
3741             RefPtr<CustomFilterOperation> operation = createCustomFilterOperation(filterValue);
3742             if (!operation)
3743                 return false;
3744             
3745             operations.operations().append(operation);
3746             continue;
3747         }
3748 #endif
3749         if (operationType == FilterOperation::REFERENCE) {
3750 #if ENABLE(SVG)
3751             if (filterValue->length() != 1)
3752                 continue;
3753             CSSValue* argument = filterValue->itemWithoutBoundsCheck(0);
3754
3755             if (!argument->isWebKitCSSSVGDocumentValue())
3756                 continue;
3757
3758             WebKitCSSSVGDocumentValue* svgDocumentValue = toWebKitCSSSVGDocumentValue(argument);
3759             URL url = m_state.document().completeURL(svgDocumentValue->url());
3760
3761             RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(svgDocumentValue->url(), url.fragmentIdentifier(), operationType);
3762             if (SVGURIReference::isExternalURIReference(svgDocumentValue->url(), m_state.document())) {
3763                 if (!svgDocumentValue->loadRequested())
3764                     m_state.pendingSVGDocuments().set(operation.get(), svgDocumentValue);
3765                 else if (svgDocumentValue->cachedSVGDocument())
3766                     operation->setCachedSVGDocumentReference(adoptPtr(new CachedSVGDocumentReference(svgDocumentValue->cachedSVGDocument())));
3767             }
3768             operations.operations().append(operation);
3769 #endif
3770             continue;
3771         }
3772
3773         // Check that all parameters are primitive values, with the
3774         // exception of drop shadow which has a CSSShadowValue parameter.
3775         CSSPrimitiveValue* firstValue = nullptr;
3776         if (operationType != FilterOperation::DROP_SHADOW) {
3777             bool haveNonPrimitiveValue = false;
3778             for (unsigned j = 0; j < filterValue->length(); ++j) {
3779                 if (!filterValue->itemWithoutBoundsCheck(j)->isPrimitiveValue()) {
3780                     haveNonPrimitiveValue = true;
3781                     break;
3782                 }
3783             }
3784             if (haveNonPrimitiveValue)
3785                 continue;
3786             if (filterValue->length())
3787                 firstValue = toCSSPrimitiveValue(filterValue->itemWithoutBoundsCheck(0));
3788         }
3789
3790         switch (filterValue->operationType()) {
3791         case WebKitCSSFilterValue::GrayscaleFilterOperation:
3792         case WebKitCSSFilterValue::SepiaFilterOperation:
3793         case WebKitCSSFilterValue::SaturateFilterOperation: {
3794             double amount = 1;
3795             if (filterValue->length() == 1) {
3796                 amount = firstValue->getDoubleValue();
3797                 if (firstValue->isPercentage())
3798                     amount /= 100;
3799             }
3800
3801             operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
3802             break;
3803         }
3804         case WebKitCSSFilterValue::HueRotateFilterOperation: {
3805             double angle = 0;
3806             if (filterValue->length() == 1)
3807                 angle = firstValue->computeDegrees();
3808
3809             operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
3810             break;
3811         }
3812         case WebKitCSSFilterValue::InvertFilterOperation:
3813         case WebKitCSSFilterValue::BrightnessFilterOperation:
3814         case WebKitCSSFilterValue::ContrastFilterOperation:
3815         case WebKitCSSFilterValue::OpacityFilterOperation: {
3816             double amount = (filterValue->operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
3817             if (filterValue->length() == 1) {
3818                 amount = firstValue->getDoubleValue();
3819                 if (firstValue->isPercentage())
3820                     amount /= 100;
3821             }
3822
3823             operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
3824             break;
3825         }
3826         case WebKitCSSFilterValue::BlurFilterOperation: {
3827             Length stdDeviation = Length(0, Fixed);
3828             if (filterValue->length() >= 1)
3829                 stdDeviation = convertToFloatLength(firstValue, style, rootStyle, zoomFactor);
3830             if (stdDeviation.isUndefined())
3831                 return false;
3832
3833             operations.operations().append(BlurFilterOperation::create(stdDeviation, operationType));
3834             break;
3835         }
3836         case WebKitCSSFilterValue::DropShadowFilterOperation: {
3837             if (filterValue->length() != 1)
3838                 return false;
3839
3840             CSSValue* cssValue = filterValue->itemWithoutBoundsCheck(0);
3841             if (!cssValue->isShadowValue())
3842                 continue;
3843
3844             CSSShadowValue* item = toCSSShadowValue(cssValue);
3845             int x = item->x->computeLength<int>(style, rootStyle, zoomFactor);
3846             if (item->x->isViewportPercentageLength())
3847                 x = viewportPercentageValue(*item->x, x);
3848             int y = item->y->computeLength<int>(style, rootStyle, zoomFactor);
3849             if (item->y->isViewportPercentageLength())
3850                 y = viewportPercentageValue(*item->y, y);
3851             IntPoint location(x, y);
3852             int blur = item->blur ? item->blur->computeLength<int>(style, rootStyle, zoomFactor) : 0;
3853             if (item->blur && item->blur->isViewportPercentageLength())
3854                 blur = viewportPercentageValue(*item->blur, blur);
3855             Color color;
3856             if (item->color)
3857                 color = colorFromPrimitiveValue(item->color.get());
3858
3859             operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent, operationType));
3860             break;
3861         }
3862         case WebKitCSSFilterValue::UnknownFilterOperation:
3863         default:
3864             ASSERT_NOT_REACHED();
3865             break;
3866         }
3867     }
3868
3869     outOperations = operations;
3870     return true;
3871 }
3872
3873 #endif
3874
3875 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(StylePendingImage* pendingImage)
3876 {
3877     if (auto imageValue = pendingImage->cssImageValue())
3878         return imageValue->cachedImage(m_state.document().cachedResourceLoader());
3879
3880     if (auto imageGeneratorValue = pendingImage->cssImageGeneratorValue()) {
3881         imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader());
3882         return StyleGeneratedImage::create(*imageGeneratorValue);
3883     }
3884
3885     if (auto cursorImageValue = pendingImage->cssCursorImageValue())
3886         return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader());
3887
3888 #if ENABLE(CSS_IMAGE_SET)
3889     if (CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue())
3890         return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader());
3891 #endif
3892
3893     return nullptr;
3894 }
3895
3896
3897 #if ENABLE(CSS_SHAPES)
3898 void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
3899 {
3900     if (!shapeValue)
3901         return;
3902
3903     StyleImage* image = shapeValue->image();
3904     if (!image || !image->isPendingImage())
3905         return;
3906
3907     StylePendingImage* pendingImage = static_cast<StylePendingImage*>(image);
3908     CSSImageValue* cssImageValue =  pendingImage->cssImageValue();
3909     CachedResourceLoader* cachedResourceLoader = m_state.document().cachedResourceLoader();
3910
3911     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
3912     options.requestOriginPolicy = PotentiallyCrossOriginEnabled;
3913     options.allowCredentials = DoNotAllowStoredCredentials;
3914
3915     shapeValue->setImage(cssImageValue->cachedImage(cachedResourceLoader, options));
3916 }
3917 #endif
3918
3919 void StyleResolver::loadPendingImages()
3920 {
3921     if (m_state.pendingImageProperties().isEmpty())
3922         return;
3923
3924     auto end = m_state.pendingImageProperties().end().keys();
3925     for (auto it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) {
3926         CSSPropertyID currentProperty = *it;
3927
3928         switch (currentProperty) {
3929         case CSSPropertyBackgroundImage: {
3930             for (FillLayer* backgroundLayer = m_state.style()->accessBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
3931                 if (backgroundLayer->image() && backgroundLayer->image()->isPendingImage())
3932                     backgroundLayer->setImage(loadPendingImage(static_cast<StylePendingImage*>(backgroundLayer->image())));
3933             }
3934             break;
3935         }
3936         case CSSPropertyContent: {
3937             for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
3938                 if (contentData->isImage()) {
3939                     StyleImage* image = static_cast<ImageContentData*>(contentData)->image();
3940                     if (image->isPendingImage()) {
3941                         RefPtr<StyleImage> loadedImage = loadPendingImage(static_cast<StylePendingImage*>(image));
3942                         if (loadedImage)
3943                             static_cast<ImageContentData*>(contentData)->setImage(loadedImage.release());
3944                     }
3945                 }
3946             }
3947             break;
3948         }
3949         case CSSPropertyCursor: {
3950             if (CursorList* cursorList = m_state.style()->cursors()) {
3951                 for (size_t i = 0; i < cursorList->size(); ++i) {
3952                     CursorData& currentCursor = cursorList->at(i);
3953                     if (StyleImage* image = currentCursor.image()) {
3954                         if (image->isPendingImage())
3955                             currentCursor.setImage(loadPendingImage(static_cast<StylePendingImage*>(image)));
3956                     }
3957                 }
3958             }
3959             break;
3960         }
3961         case CSSPropertyListStyleImage: {
3962             if (m_state.style()->listStyleImage() && m_state.style()->listStyleImage()->isPendingImage())
3963                 m_state.style()->setListStyleImage(loadPendingImage(static_cast<StylePendingImage*>(m_state.style()->listStyleImage())));
3964             break;
3965         }
3966         case CSSPropertyBorderImageSource: {
3967             if (m_state.style()->borderImageSource() && m_state.style()->borderImageSource()->isPendingImage())
3968         &nb