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