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