[Vertical Writing Mode] Rename "vertical-right" CSS value to match spec
[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 "CSSBorderImage.h"
34 #include "CSSCalculationValue.h"
35 #include "CSSCursorImageValue.h"
36 #include "CSSCustomPropertyValue.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 "CSSInheritedValue.h"
45 #include "CSSInitialValue.h"
46 #include "CSSKeyframeRule.h"
47 #include "CSSKeyframesRule.h"
48 #include "CSSLineBoxContainValue.h"
49 #include "CSSPageRule.h"
50 #include "CSSParser.h"
51 #include "CSSPrimitiveValueMappings.h"
52 #include "CSSPropertyNames.h"
53 #include "CSSReflectValue.h"
54 #include "CSSSelector.h"
55 #include "CSSSelectorList.h"
56 #include "CSSShadowValue.h"
57 #include "CSSStyleRule.h"
58 #include "CSSSupportsRule.h"
59 #include "CSSTimingFunctionValue.h"
60 #include "CSSValueList.h"
61 #include "CSSVariableDependentValue.h"
62 #include "CachedImage.h"
63 #include "CachedResourceLoader.h"
64 #include "CachedSVGDocument.h"
65 #include "CachedSVGDocumentReference.h"
66 #include "CalculationValue.h"
67 #include "ContentData.h"
68 #include "Counter.h"
69 #include "CounterContent.h"
70 #include "CursorList.h"
71 #include "ElementRuleCollector.h"
72 #include "FilterOperation.h"
73 #include "Frame.h"
74 #include "FrameSelection.h"
75 #include "FrameView.h"
76 #include "HTMLDocument.h"
77 #include "HTMLIFrameElement.h"
78 #include "HTMLInputElement.h"
79 #include "HTMLNames.h"
80 #include "HTMLOptGroupElement.h"
81 #include "HTMLOptionElement.h"
82 #include "HTMLProgressElement.h"
83 #include "HTMLStyleElement.h"
84 #include "HTMLTableElement.h"
85 #include "HTMLTextAreaElement.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/TemporaryChange.h>
144 #include <wtf/Vector.h>
145 #include <wtf/text/AtomicStringHash.h>
146
147 #if ENABLE(CSS_GRID_LAYOUT)
148 #include "CSSGridLineNamesValue.h"
149 #include "CSSGridTemplateAreasValue.h"
150 #endif
151
152 #if ENABLE(CSS_IMAGE_SET)
153 #include "CSSImageSetValue.h"
154 #include "StyleCachedImageSet.h"
155 #endif
156
157 #if ENABLE(DASHBOARD_SUPPORT)
158 #include "DashboardRegion.h"
159 #endif
160
161 #if ENABLE(VIDEO_TRACK)
162 #include "WebVTTElement.h"
163 #endif
164
165 #if ENABLE(CSS_SCROLL_SNAP)
166 #include "LengthRepeat.h"
167 #endif
168
169 namespace WebCore {
170
171 using namespace HTMLNames;
172
173 static const CSSPropertyID lastHighPriorityProperty = CSSPropertyFontSynthesis;
174 static const CSSPropertyID firstLowPriorityProperty = static_cast<CSSPropertyID>(lastHighPriorityProperty + 1);
175
176 static void extractDirectionAndWritingMode(const RenderStyle&, const StyleResolver::MatchResult&, TextDirection&, WritingMode&);
177
178 RenderStyle* StyleResolver::s_styleNotYetAvailable;
179
180 inline void StyleResolver::State::cacheBorderAndBackground()
181 {
182     m_hasUAAppearance = m_style->hasAppearance();
183     if (m_hasUAAppearance) {
184         m_borderData = m_style->border();
185         m_backgroundData = *m_style->backgroundLayers();
186         m_backgroundColor = m_style->backgroundColor();
187     }
188 }
189
190 inline void StyleResolver::State::clear()
191 {
192     m_element = nullptr;
193     m_styledElement = nullptr;
194     m_parentStyle = nullptr;
195     m_regionForStyling = nullptr;
196     m_pendingImageProperties.clear();
197     m_filtersWithPendingSVGDocuments.clear();
198     m_cssToLengthConversionData = CSSToLengthConversionData();
199 }
200
201 void StyleResolver::MatchResult::addMatchedProperties(const StyleProperties& properties, StyleRule* rule, unsigned linkMatchType, PropertyWhitelistType propertyWhitelistType)
202 {
203     m_matchedProperties.grow(m_matchedProperties.size() + 1);
204     StyleResolver::MatchedProperties& newProperties = m_matchedProperties.last();
205     newProperties.properties = const_cast<StyleProperties*>(&properties);
206     newProperties.linkMatchType = linkMatchType;
207     newProperties.whitelistType = propertyWhitelistType;
208     matchedRules.append(rule);
209
210     if (isCacheable) {
211         for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
212             // Currently the property cache only copy the non-inherited values and resolve
213             // the inherited ones.
214             // Here we define some exception were we have to resolve some properties that are not inherited
215             // by default. If those exceptions become too common on the web, it should be possible
216             // to build a list of exception to resolve instead of completely disabling the cache.
217
218             StyleProperties::PropertyReference current = properties.propertyAt(i);
219             if (!current.isInherited()) {
220                 // If the property value is explicitly inherited, we need to apply further non-inherited properties
221                 // as they might override the value inherited here. For this reason we don't allow declarations with
222                 // explicitly inherited properties to be cached.
223                 const CSSValue& value = *current.value();
224                 if (value.isInheritedValue()) {
225                     isCacheable = false;
226                     break;
227                 }
228
229                 // The value currentColor has implicitely the same side effect. It depends on the value of color,
230                 // which is an inherited value, making the non-inherited property implicitely inherited.
231                 if (is<CSSPrimitiveValue>(value) && downcast<CSSPrimitiveValue>(value).getValueID() == CSSValueCurrentcolor) {
232                     isCacheable = false;
233                     break;
234                 }
235             }
236         }
237     }
238 }
239
240 StyleResolver::StyleResolver(Document& document)
241     : m_matchedPropertiesCacheAdditionsSinceLastSweep(0)
242     , m_matchedPropertiesCacheSweepTimer(*this, &StyleResolver::sweepMatchedPropertiesCache)
243     , m_document(document)
244     , m_matchAuthorAndUserStyles(m_document.settings() ? m_document.settings()->authorAndUserStylesEnabled() : true)
245 #if ENABLE(CSS_DEVICE_ADAPTATION)
246     , m_viewportStyleResolver(ViewportStyleResolver::create(&document))
247 #endif
248     , m_styleMap(this)
249 {
250     Element* root = m_document.documentElement();
251
252     CSSDefaultStyleSheets::initDefaultStyle(root);
253
254     // construct document root element default style. this is needed
255     // to evaluate media queries that contain relative constraints, like "screen and (max-width: 10em)"
256     // This is here instead of constructor, because when constructor is run,
257     // document doesn't have documentElement
258     // NOTE: this assumes that element that gets passed to styleForElement -call
259     // is always from the document that owns the style selector
260     FrameView* view = m_document.view();
261     if (view)
262         m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType());
263     else
264         m_medium = std::make_unique<MediaQueryEvaluator>("all");
265
266     if (root)
267         m_rootDefaultStyle = styleForElement(root, m_document.renderStyle(), DisallowStyleSharing, MatchOnlyUserAgentRules);
268
269     if (m_rootDefaultStyle && view)
270         m_medium = std::make_unique<MediaQueryEvaluator>(view->mediaType(), &view->frame(), m_rootDefaultStyle.get());
271
272     m_ruleSets.resetAuthorStyle();
273
274     m_ruleSets.initUserStyle(m_document.extensionStyleSheets(), *m_medium, *this);
275
276 #if ENABLE(SVG_FONTS)
277     if (m_document.svgExtensions()) {
278         const HashSet<SVGFontFaceElement*>& svgFontFaceElements = m_document.svgExtensions()->svgFontFaceElements();
279         for (auto* svgFontFaceElement : svgFontFaceElements)
280             m_document.fontSelector().addFontFaceRule(svgFontFaceElement->fontFaceRule(), svgFontFaceElement->isInUserAgentShadowTree());
281     }
282 #endif
283 }
284
285 void StyleResolver::appendAuthorStyleSheets(const Vector<RefPtr<CSSStyleSheet>>& styleSheets)
286 {
287     m_ruleSets.appendAuthorStyleSheets(styleSheets, m_medium.get(), m_inspectorCSSOMWrappers, this);
288     if (auto renderView = document().renderView())
289         renderView->style().fontCascade().update(&document().fontSelector());
290
291 #if ENABLE(CSS_DEVICE_ADAPTATION)
292     viewportStyleResolver()->resolve();
293 #endif
294 }
295
296 void StyleResolver::pushParentElement(Element* parent)
297 {
298     const ContainerNode* parentsParent = parent->parentOrShadowHostElement();
299
300     // We are not always invoked consistently. For example, script execution can cause us to enter
301     // style recalc in the middle of tree building. We may also be invoked from somewhere within the tree.
302     // Reset the stack in this case, or if we see a new root element.
303     // Otherwise just push the new parent.
304     if (!parentsParent || m_selectorFilter.parentStackIsEmpty())
305         m_selectorFilter.setupParentStack(parent);
306     else
307         m_selectorFilter.pushParent(parent);
308 }
309
310 void StyleResolver::popParentElement(Element* parent)
311 {
312     // Note that we may get invoked for some random elements in some wacky cases during style resolve.
313     // Pause maintaining the stack in this case.
314     if (m_selectorFilter.parentStackIsConsistent(parent))
315         m_selectorFilter.popParent();
316 }
317
318 // This is a simplified style setting function for keyframe styles
319 void StyleResolver::addKeyframeStyle(PassRefPtr<StyleRuleKeyframes> rule)
320 {
321     AtomicString s(rule->name());
322     m_keyframesRuleMap.set(s.impl(), rule);
323 }
324
325 StyleResolver::~StyleResolver()
326 {
327     RELEASE_ASSERT(!m_inLoadPendingImages);
328
329 #if ENABLE(CSS_DEVICE_ADAPTATION)
330     m_viewportStyleResolver->clearDocument();
331 #endif
332 }
333
334 void StyleResolver::sweepMatchedPropertiesCache()
335 {
336     // Look for cache entries containing a style declaration with a single ref and remove them.
337     // This may happen when an element attribute mutation causes it to generate a new inlineStyle()
338     // or presentationAttributeStyle(), potentially leaving this cache with the last ref on the old one.
339     Vector<unsigned, 16> toRemove;
340     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.begin();
341     MatchedPropertiesCache::iterator end = m_matchedPropertiesCache.end();
342     for (; it != end; ++it) {
343         Vector<MatchedProperties>& matchedProperties = it->value.matchedProperties;
344         for (size_t i = 0; i < matchedProperties.size(); ++i) {
345             if (matchedProperties[i].properties->hasOneRef()) {
346                 toRemove.append(it->key);
347                 break;
348             }
349         }
350     }
351     for (size_t i = 0; i < toRemove.size(); ++i)
352         m_matchedPropertiesCache.remove(toRemove[i]);
353
354     m_matchedPropertiesCacheAdditionsSinceLastSweep = 0;
355 }
356
357 bool StyleResolver::classNamesAffectedByRules(const SpaceSplitString& classNames) const
358 {
359     for (unsigned i = 0; i < classNames.size(); ++i) {
360         if (m_ruleSets.features().classesInRules.contains(classNames[i].impl()))
361             return true;
362     }
363     return false;
364 }
365
366 inline void StyleResolver::State::updateConversionData()
367 {
368     m_cssToLengthConversionData = CSSToLengthConversionData(m_style.get(), m_rootElementStyle, m_element ? document().renderView() : nullptr);
369 }
370
371 inline void StyleResolver::State::initElement(Element* element)
372 {
373     m_element = element;
374     m_styledElement = element && is<StyledElement>(*element) ? downcast<StyledElement>(element) : nullptr;
375     m_elementLinkState = element ? element->document().visitedLinkState().determineLinkState(*element) : NotInsideLink;
376     updateConversionData();
377 }
378
379 inline void StyleResolver::initElement(Element* e)
380 {
381     if (m_state.element() != e) {
382         m_state.initElement(e);
383         if (e && e == e->document().documentElement()) {
384             e->document().setDirectionSetOnDocumentElement(false);
385             e->document().setWritingModeSetOnDocumentElement(false);
386         }
387     }
388 }
389
390 inline void StyleResolver::State::initForStyleResolve(Document& document, Element* e, RenderStyle* parentStyle, const RenderRegion* regionForStyling)
391 {
392     m_regionForStyling = regionForStyling;
393
394     if (e) {
395         bool resetStyleInheritance = hasShadowRootParent(*e) && downcast<ShadowRoot>(*e->parentNode()).resetStyleInheritance();
396         m_parentStyle = resetStyleInheritance ? nullptr : parentStyle;
397     } else
398         m_parentStyle = parentStyle;
399
400     Node* docElement = e ? e->document().documentElement() : nullptr;
401     RenderStyle* docStyle = document.renderStyle();
402     m_rootElementStyle = docElement && e != docElement ? docElement->renderStyle() : docStyle;
403
404     m_style = nullptr;
405     m_pendingImageProperties.clear();
406     m_fontDirty = false;
407     
408     m_authorRollback = nullptr;
409     m_userRollback = nullptr;
410
411     updateConversionData();
412 }
413
414 inline void StyleResolver::State::setStyle(Ref<RenderStyle>&& style)
415 {
416     m_style = WTF::move(style);
417     updateConversionData();
418 }
419
420 static const unsigned cStyleSearchThreshold = 10;
421 static const unsigned cStyleSearchLevelThreshold = 10;
422
423 static inline bool parentElementPreventsSharing(const Element* parentElement)
424 {
425     if (!parentElement)
426         return false;
427     return parentElement->hasFlagsSetDuringStylingOfChildren();
428 }
429
430 Node* StyleResolver::locateCousinList(Element* parent, unsigned& visitedNodeCount) const
431 {
432     if (visitedNodeCount >= cStyleSearchThreshold * cStyleSearchLevelThreshold)
433         return nullptr;
434     if (!is<StyledElement>(parent))
435         return nullptr;
436     StyledElement* styledParent = downcast<StyledElement>(parent);
437     if (styledParent->inlineStyle())
438         return nullptr;
439     if (is<SVGElement>(*styledParent) && downcast<SVGElement>(*styledParent).animatedSMILStyleProperties())
440         return nullptr;
441     if (styledParent->hasID() && m_ruleSets.features().idsInRules.contains(styledParent->idForStyleResolution().impl()))
442         return nullptr;
443
444     RenderStyle* parentStyle = styledParent->renderStyle();
445     unsigned subcount = 0;
446     Node* thisCousin = styledParent;
447     Node* currentNode = styledParent->previousSibling();
448
449     // Reserve the tries for this level. This effectively makes sure that the algorithm
450     // will never go deeper than cStyleSearchLevelThreshold levels into recursion.
451     visitedNodeCount += cStyleSearchThreshold;
452     while (thisCousin) {
453         while (currentNode) {
454             ++subcount;
455             if (currentNode->renderStyle() == parentStyle && currentNode->lastChild()
456                 && is<Element>(*currentNode) && !parentElementPreventsSharing(downcast<Element>(currentNode))
457                 ) {
458                 // Adjust for unused reserved tries.
459                 visitedNodeCount -= cStyleSearchThreshold - subcount;
460                 return currentNode->lastChild();
461             }
462             if (subcount >= cStyleSearchThreshold)
463                 return nullptr;
464             currentNode = currentNode->previousSibling();
465         }
466         currentNode = locateCousinList(thisCousin->parentElement(), visitedNodeCount);
467         thisCousin = currentNode;
468     }
469
470     return nullptr;
471 }
472
473 bool StyleResolver::styleSharingCandidateMatchesRuleSet(RuleSet* ruleSet)
474 {
475     if (!ruleSet)
476         return false;
477
478     ElementRuleCollector collector(*m_state.element(), m_state.style(), m_ruleSets, m_selectorFilter);
479     return collector.hasAnyMatchingRules(ruleSet);
480 }
481
482 bool StyleResolver::canShareStyleWithControl(StyledElement& element) const
483 {
484     const State& state = m_state;
485     if (!is<HTMLInputElement>(element) || !is<HTMLInputElement>(*state.element()))
486         return false;
487
488     auto& thisInputElement = downcast<HTMLInputElement>(element);
489     auto& otherInputElement = downcast<HTMLInputElement>(*state.element());
490
491     if (thisInputElement.isAutoFilled() != otherInputElement.isAutoFilled())
492         return false;
493     if (thisInputElement.shouldAppearChecked() != otherInputElement.shouldAppearChecked())
494         return false;
495     if (thisInputElement.shouldAppearIndeterminate() != otherInputElement.shouldAppearIndeterminate())
496         return false;
497     if (thisInputElement.isRequired() != otherInputElement.isRequired())
498         return false;
499
500     if (element.isDisabledFormControl() != state.element()->isDisabledFormControl())
501         return false;
502
503     if (element.isDefaultButtonForForm() != state.element()->isDefaultButtonForForm())
504         return false;
505
506     if (element.isInRange() != state.element()->isInRange())
507         return false;
508
509     if (element.isOutOfRange() != state.element()->isOutOfRange())
510         return false;
511
512     return true;
513 }
514
515 static inline bool elementHasDirectionAuto(Element& element)
516 {
517     // FIXME: This line is surprisingly hot, we may wish to inline hasDirectionAuto into StyleResolver.
518     return is<HTMLElement>(element) && downcast<HTMLElement>(element).hasDirectionAuto();
519 }
520
521 bool StyleResolver::sharingCandidateHasIdenticalStyleAffectingAttributes(StyledElement& sharingCandidate) const
522 {
523     const State& state = m_state;
524     if (state.element()->elementData() == sharingCandidate.elementData())
525         return true;
526     if (state.element()->fastGetAttribute(XMLNames::langAttr) != sharingCandidate.fastGetAttribute(XMLNames::langAttr))
527         return false;
528     if (state.element()->fastGetAttribute(langAttr) != sharingCandidate.fastGetAttribute(langAttr))
529         return false;
530
531     if (!state.elementAffectedByClassRules()) {
532         if (sharingCandidate.hasClass() && classNamesAffectedByRules(sharingCandidate.classNames()))
533             return false;
534     } else if (sharingCandidate.hasClass()) {
535         // SVG elements require a (slow!) getAttribute comparision because "class" is an animatable attribute for SVG.
536         if (state.element()->isSVGElement()) {
537             if (state.element()->getAttribute(classAttr) != sharingCandidate.getAttribute(classAttr))
538                 return false;
539         } else {
540             if (state.element()->classNames() != sharingCandidate.classNames())
541                 return false;
542         }
543     } else
544         return false;
545
546     if (state.styledElement()->presentationAttributeStyle() != sharingCandidate.presentationAttributeStyle())
547         return false;
548
549     if (state.element()->hasTagName(progressTag)) {
550         if (state.element()->shouldAppearIndeterminate() != sharingCandidate.shouldAppearIndeterminate())
551             return false;
552     }
553
554     return true;
555 }
556
557 bool StyleResolver::canShareStyleWithElement(StyledElement& element) const
558 {
559     auto* style = element.renderStyle();
560     const State& state = m_state;
561
562     if (!style)
563         return false;
564     if (style->unique())
565         return false;
566     if (style->hasUniquePseudoStyle())
567         return false;
568     if (element.tagQName() != state.element()->tagQName())
569         return false;
570     if (element.inlineStyle())
571         return false;
572     if (element.needsStyleRecalc())
573         return false;
574     if (element.isSVGElement() && downcast<SVGElement>(element).animatedSMILStyleProperties())
575         return false;
576     if (element.isLink() != state.element()->isLink())
577         return false;
578     if (element.hovered() != state.element()->hovered())
579         return false;
580     if (element.active() != state.element()->active())
581         return false;
582     if (element.focused() != state.element()->focused())
583         return false;
584     if (element.shadowPseudoId() != state.element()->shadowPseudoId())
585         return false;
586     if (&element == element.document().cssTarget())
587         return false;
588     if (!sharingCandidateHasIdenticalStyleAffectingAttributes(element))
589         return false;
590     if (element.additionalPresentationAttributeStyle() != state.styledElement()->additionalPresentationAttributeStyle())
591         return false;
592     if (element.affectsNextSiblingElementStyle() || element.styleIsAffectedByPreviousSibling())
593         return false;
594
595     if (element.hasID() && m_ruleSets.features().idsInRules.contains(element.idForStyleResolution().impl()))
596         return false;
597
598     bool isControl = is<HTMLFormControlElement>(element);
599
600     if (isControl != is<HTMLFormControlElement>(*state.element()))
601         return false;
602
603     if (isControl && !canShareStyleWithControl(element))
604         return false;
605
606     if (style->transitions() || style->animations())
607         return false;
608
609     // Turn off style sharing for elements that can gain layers for reasons outside of the style system.
610     // See comments in RenderObject::setStyle().
611     if (element.hasTagName(iframeTag) || element.hasTagName(frameTag) || element.hasTagName(embedTag) || element.hasTagName(objectTag) || element.hasTagName(appletTag) || element.hasTagName(canvasTag))
612         return false;
613
614     if (elementHasDirectionAuto(element))
615         return false;
616
617     if (element.isLink() && state.elementLinkState() != style->insideLink())
618         return false;
619
620     if (element.elementData() != state.element()->elementData()) {
621         if (element.fastGetAttribute(readonlyAttr) != state.element()->fastGetAttribute(readonlyAttr))
622             return false;
623         if (element.isSVGElement()) {
624             if (element.getAttribute(typeAttr) != state.element()->getAttribute(typeAttr))
625                 return false;
626         } else {
627             if (element.fastGetAttribute(typeAttr) != state.element()->fastGetAttribute(typeAttr))
628                 return false;
629         }
630     }
631
632     if (element.matchesValidPseudoClass() != state.element()->matchesValidPseudoClass())
633         return false;
634
635     if (element.matchesInvalidPseudoClass() != state.element()->matchesValidPseudoClass())
636         return false;
637
638 #if ENABLE(VIDEO_TRACK)
639     // Deny sharing styles between WebVTT and non-WebVTT nodes.
640     if (is<WebVTTElement>(*state.element()))
641         return false;
642 #endif
643
644 #if ENABLE(FULLSCREEN_API)
645     if (&element == element.document().webkitCurrentFullScreenElement() || state.element() == state.document().webkitCurrentFullScreenElement())
646         return false;
647 #endif
648     return true;
649 }
650
651 inline StyledElement* StyleResolver::findSiblingForStyleSharing(Node* node, unsigned& count) const
652 {
653     for (; node; node = node->previousSibling()) {
654         if (!is<StyledElement>(*node))
655             continue;
656         if (canShareStyleWithElement(downcast<StyledElement>(*node)))
657             break;
658         if (count++ == cStyleSearchThreshold)
659             return nullptr;
660     }
661     return downcast<StyledElement>(node);
662 }
663
664 RenderStyle* StyleResolver::locateSharedStyle()
665 {
666     State& state = m_state;
667     if (!state.styledElement() || !state.parentStyle())
668         return nullptr;
669
670     // If the element has inline style it is probably unique.
671     if (state.styledElement()->inlineStyle())
672         return nullptr;
673     if (state.styledElement()->isSVGElement() && downcast<SVGElement>(*state.styledElement()).animatedSMILStyleProperties())
674         return nullptr;
675     // Ids stop style sharing if they show up in the stylesheets.
676     if (state.styledElement()->hasID() && m_ruleSets.features().idsInRules.contains(state.styledElement()->idForStyleResolution().impl()))
677         return nullptr;
678     if (parentElementPreventsSharing(state.element()->parentElement()))
679         return nullptr;
680     if (state.element() == state.document().cssTarget())
681         return nullptr;
682     if (elementHasDirectionAuto(*state.element()))
683         return nullptr;
684
685     // Cache whether state.element is affected by any known class selectors.
686     // FIXME: This shouldn't be a member variable. The style sharing code could be factored out of StyleResolver.
687     state.setElementAffectedByClassRules(state.element() && state.element()->hasClass() && classNamesAffectedByRules(state.element()->classNames()));
688
689     // Check previous siblings and their cousins.
690     unsigned count = 0;
691     unsigned visitedNodeCount = 0;
692     StyledElement* shareElement = nullptr;
693     Node* cousinList = state.styledElement()->previousSibling();
694     while (cousinList) {
695         shareElement = findSiblingForStyleSharing(cousinList, count);
696         if (shareElement)
697             break;
698         cousinList = locateCousinList(cousinList->parentElement(), visitedNodeCount);
699     }
700
701     // If we have exhausted all our budget or our cousins.
702     if (!shareElement)
703         return nullptr;
704
705     // Can't share if sibling rules apply. This is checked at the end as it should rarely fail.
706     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.sibling()))
707         return nullptr;
708     // Can't share if attribute rules apply.
709     if (styleSharingCandidateMatchesRuleSet(m_ruleSets.uncommonAttribute()))
710         return nullptr;
711     // Tracking child index requires unique style for each node. This may get set by the sibling rule match above.
712     if (parentElementPreventsSharing(state.element()->parentElement()))
713         return nullptr;
714     return shareElement->renderStyle();
715 }
716
717 static inline bool isAtShadowBoundary(const Element* element)
718 {
719     if (!element)
720         return false;
721     ContainerNode* parentNode = element->parentNode();
722     return parentNode && parentNode->isShadowRoot();
723 }
724
725 Ref<RenderStyle> StyleResolver::styleForElement(Element* element, RenderStyle* defaultParent,
726     StyleSharingBehavior sharingBehavior, RuleMatchingBehavior matchingBehavior, const RenderRegion* regionForStyling)
727 {
728     RELEASE_ASSERT(!m_inLoadPendingImages);
729
730     // Once an element has a renderer, we don't try to destroy it, since otherwise the renderer
731     // will vanish if a style recalc happens during loading.
732     if (sharingBehavior == AllowStyleSharing && !element->document().haveStylesheetsLoaded() && !element->renderer()) {
733         if (!s_styleNotYetAvailable) {
734             s_styleNotYetAvailable = &RenderStyle::create().leakRef();
735             s_styleNotYetAvailable->setDisplay(NONE);
736             s_styleNotYetAvailable->fontCascade().update(&document().fontSelector());
737         }
738         element->document().setHasNodesWithPlaceholderStyle();
739         return *s_styleNotYetAvailable;
740     }
741
742     State& state = m_state;
743     initElement(element);
744     state.initForStyleResolve(document(), element, defaultParent, regionForStyling);
745     if (sharingBehavior == AllowStyleSharing) {
746         if (RenderStyle* sharedStyle = locateSharedStyle()) {
747             state.clear();
748             return *sharedStyle;
749         }
750     }
751
752     if (state.parentStyle()) {
753         state.setStyle(RenderStyle::create());
754         state.style()->inheritFrom(state.parentStyle(), isAtShadowBoundary(element) ? RenderStyle::AtShadowBoundary : RenderStyle::NotAtShadowBoundary);
755     } else {
756         state.setStyle(defaultStyleForElement());
757         state.setParentStyle(RenderStyle::clone(state.style()));
758     }
759
760     if (element->isLink()) {
761         state.style()->setIsLink(true);
762         EInsideLink linkState = state.elementLinkState();
763         if (linkState != NotInsideLink) {
764             bool forceVisited = InspectorInstrumentation::forcePseudoState(*element, CSSSelector::PseudoClassVisited);
765             if (forceVisited)
766                 linkState = InsideVisitedLink;
767         }
768         state.style()->setInsideLink(linkState);
769     }
770
771     bool needsCollection = false;
772     CSSDefaultStyleSheets::ensureDefaultStyleSheetsForElement(*element, needsCollection);
773     if (needsCollection)
774         m_ruleSets.collectFeatures();
775
776     ElementRuleCollector collector(*element, state.style(), m_ruleSets, m_selectorFilter);
777     collector.setRegionForStyling(regionForStyling);
778     collector.setMedium(m_medium.get());
779
780     if (matchingBehavior == MatchOnlyUserAgentRules)
781         collector.matchUARules();
782     else
783         collector.matchAllRules(m_matchAuthorAndUserStyles, matchingBehavior != MatchAllRulesExcludingSMIL);
784
785     applyMatchedProperties(collector.matchedResult(), element);
786
787     // Clean up our style object's display and text decorations (among other fixups).
788     adjustRenderStyle(*state.style(), *state.parentStyle(), element);
789
790     if (state.style()->hasViewportUnits())
791         document().setHasStyleWithViewportUnits();
792
793     state.clear(); // Clear out for the next resolve.
794
795     // Now return the style.
796     return state.takeStyle();
797 }
798
799 Ref<RenderStyle> StyleResolver::styleForKeyframe(const RenderStyle* elementStyle, const StyleKeyframe* keyframe, KeyframeValue& keyframeValue)
800 {
801     RELEASE_ASSERT(!m_inLoadPendingImages);
802
803     MatchResult result;
804     result.addMatchedProperties(keyframe->properties());
805
806     ASSERT(!m_state.style());
807
808     State& state = m_state;
809
810     // Create the style
811     state.setStyle(RenderStyle::clone(elementStyle));
812     state.setParentStyle(RenderStyle::clone(elementStyle));
813
814     TextDirection direction;
815     WritingMode writingMode;
816     extractDirectionAndWritingMode(*state.style(), result, direction, writingMode);
817
818     // We don't need to bother with !important. Since there is only ever one
819     // decl, there's nothing to override. So just add the first properties.
820     CascadedProperties cascade(direction, writingMode);
821     cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
822     
823     // Resolve custom properties first.
824     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
825
826     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
827
828     // If our font got dirtied, update it now.
829     updateFont();
830
831     // Now do rest of the properties.
832     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
833
834     // If our font got dirtied by one of the non-essential font props, update it a second time.
835     updateFont();
836
837     cascade.applyDeferredProperties(*this, &result);
838
839     adjustRenderStyle(*state.style(), *state.parentStyle(), nullptr);
840
841     // Start loading resources referenced by this style.
842     loadPendingResources();
843     
844     // Add all the animating properties to the keyframe.
845     unsigned propertyCount = keyframe->properties().propertyCount();
846     for (unsigned i = 0; i < propertyCount; ++i) {
847         CSSPropertyID property = keyframe->properties().propertyAt(i).id();
848         // Timing-function within keyframes is special, because it is not animated; it just
849         // describes the timing function between this keyframe and the next.
850         if (property != CSSPropertyWebkitAnimationTimingFunction && property != CSSPropertyAnimationTimingFunction)
851             keyframeValue.addProperty(property);
852     }
853
854     return state.takeStyle();
855 }
856
857 void StyleResolver::keyframeStylesForAnimation(Element* e, const RenderStyle* elementStyle, KeyframeList& list)
858 {
859     list.clear();
860
861     // Get the keyframesRule for this name
862     if (!e || list.animationName().isEmpty())
863         return;
864
865     m_keyframesRuleMap.checkConsistency();
866
867     KeyframesRuleMap::iterator it = m_keyframesRuleMap.find(list.animationName().impl());
868     if (it == m_keyframesRuleMap.end())
869         return;
870
871     const StyleRuleKeyframes* keyframesRule = it->value.get();
872
873     // Construct and populate the style for each keyframe
874     const Vector<RefPtr<StyleKeyframe>>& keyframes = keyframesRule->keyframes();
875     for (unsigned i = 0; i < keyframes.size(); ++i) {
876         // Apply the declaration to the style. This is a simplified version of the logic in styleForElement
877         initElement(e);
878         m_state.initForStyleResolve(document(), e, nullptr);
879
880         const StyleKeyframe* keyframe = keyframes[i].get();
881
882         KeyframeValue keyframeValue(0, nullptr);
883         keyframeValue.setStyle(styleForKeyframe(elementStyle, keyframe, keyframeValue));
884
885         // Add this keyframe style to all the indicated key times
886         for (auto& key: keyframe->keys()) {
887             keyframeValue.setKey(key);
888             list.insert(keyframeValue);
889         }
890     }
891
892     // If the 0% keyframe is missing, create it (but only if there is at least one other keyframe)
893     int initialListSize = list.size();
894     if (initialListSize > 0 && list[0].key()) {
895         static StyleKeyframe* zeroPercentKeyframe;
896         if (!zeroPercentKeyframe) {
897             zeroPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
898             zeroPercentKeyframe->setKeyText("0%");
899         }
900         KeyframeValue keyframeValue(0, nullptr);
901         keyframeValue.setStyle(styleForKeyframe(elementStyle, zeroPercentKeyframe, keyframeValue));
902         list.insert(keyframeValue);
903     }
904
905     // If the 100% keyframe is missing, create it (but only if there is at least one other keyframe)
906     if (initialListSize > 0 && (list[list.size() - 1].key() != 1)) {
907         static StyleKeyframe* hundredPercentKeyframe;
908         if (!hundredPercentKeyframe) {
909             hundredPercentKeyframe = &StyleKeyframe::create(MutableStyleProperties::create()).leakRef();
910             hundredPercentKeyframe->setKeyText("100%");
911         }
912         KeyframeValue keyframeValue(1, nullptr);
913         keyframeValue.setStyle(styleForKeyframe(elementStyle, hundredPercentKeyframe, keyframeValue));
914         list.insert(keyframeValue);
915     }
916 }
917
918 PassRefPtr<RenderStyle> StyleResolver::pseudoStyleForElement(Element* element, const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle)
919 {
920     ASSERT(parentStyle);
921     if (!element)
922         return nullptr;
923
924     State& state = m_state;
925
926     initElement(element);
927
928     state.initForStyleResolve(document(), element, parentStyle);
929
930     if (m_state.parentStyle()) {
931         state.setStyle(RenderStyle::create());
932         state.style()->inheritFrom(m_state.parentStyle());
933     } else {
934         state.setStyle(defaultStyleForElement());
935         state.setParentStyle(RenderStyle::clone(state.style()));
936     }
937
938     // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
939     // those rules.
940
941     // Check UA, user and author rules.
942     ElementRuleCollector collector(*element, m_state.style(), m_ruleSets, m_selectorFilter);
943     collector.setPseudoStyleRequest(pseudoStyleRequest);
944     collector.setMedium(m_medium.get());
945     collector.matchUARules();
946
947     if (m_matchAuthorAndUserStyles) {
948         collector.matchUserRules(false);
949         collector.matchAuthorRules(false);
950     }
951
952     if (collector.matchedResult().matchedProperties().isEmpty())
953         return nullptr;
954
955     state.style()->setStyleType(pseudoStyleRequest.pseudoId);
956
957     applyMatchedProperties(collector.matchedResult(), element);
958
959     // Clean up our style object's display and text decorations (among other fixups).
960     adjustRenderStyle(*state.style(), *m_state.parentStyle(), nullptr);
961
962     if (state.style()->hasViewportUnits())
963         document().setHasStyleWithViewportUnits();
964
965     // Start loading resources referenced by this style.
966     loadPendingResources();
967
968     // Now return the style.
969     return state.takeStyle();
970 }
971
972 Ref<RenderStyle> StyleResolver::styleForPage(int pageIndex)
973 {
974     RELEASE_ASSERT(!m_inLoadPendingImages);
975
976     m_state.initForStyleResolve(m_document, m_document.documentElement(), m_document.renderStyle());
977
978     m_state.setStyle(RenderStyle::create());
979     m_state.style()->inheritFrom(m_state.rootElementStyle());
980
981     PageRuleCollector collector(m_state, m_ruleSets);
982     collector.matchAllPageRules(pageIndex);
983
984     MatchResult& result = collector.matchedResult();
985
986     TextDirection direction;
987     WritingMode writingMode;
988     extractDirectionAndWritingMode(*m_state.style(), result, direction, writingMode);
989
990     CascadedProperties cascade(direction, writingMode);
991     cascade.addMatches(result, false, 0, result.matchedProperties().size() - 1);
992
993     // Resolve custom properties first.
994     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &result);
995
996     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &result);
997
998     // If our font got dirtied, update it now.
999     updateFont();
1000
1001     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &result);
1002
1003     cascade.applyDeferredProperties(*this, &result);
1004
1005     // Start loading resources referenced by this style.
1006     loadPendingResources();
1007
1008     // Now return the style.
1009     return m_state.takeStyle();
1010 }
1011
1012 Ref<RenderStyle> StyleResolver::defaultStyleForElement()
1013 {
1014     m_state.setStyle(RenderStyle::create());
1015     // Make sure our fonts are initialized if we don't inherit them from our parent style.
1016     initializeFontStyle(documentSettings());
1017     if (documentSettings())
1018         m_state.style()->fontCascade().update(&document().fontSelector());
1019     else
1020         m_state.style()->fontCascade().update(nullptr);
1021
1022     return m_state.takeStyle();
1023 }
1024
1025 static void addIntrinsicMargins(RenderStyle& style)
1026 {
1027     // Intrinsic margin value.
1028     const int intrinsicMargin = 2 * style.effectiveZoom();
1029
1030     // FIXME: Using width/height alone and not also dealing with min-width/max-width is flawed.
1031     // FIXME: Using "hasQuirk" to decide the margin wasn't set is kind of lame.
1032     if (style.width().isIntrinsicOrAuto()) {
1033         if (style.marginLeft().hasQuirk())
1034             style.setMarginLeft(Length(intrinsicMargin, Fixed));
1035         if (style.marginRight().hasQuirk())
1036             style.setMarginRight(Length(intrinsicMargin, Fixed));
1037     }
1038
1039     if (style.height().isAuto()) {
1040         if (style.marginTop().hasQuirk())
1041             style.setMarginTop(Length(intrinsicMargin, Fixed));
1042         if (style.marginBottom().hasQuirk())
1043             style.setMarginBottom(Length(intrinsicMargin, Fixed));
1044     }
1045 }
1046
1047 static EDisplay equivalentBlockDisplay(EDisplay display, bool isFloating, bool strictParsing)
1048 {
1049     switch (display) {
1050     case BLOCK:
1051     case TABLE:
1052     case BOX:
1053     case FLEX:
1054     case WEBKIT_FLEX:
1055 #if ENABLE(CSS_GRID_LAYOUT)
1056     case GRID:
1057 #endif
1058         return display;
1059
1060     case LIST_ITEM:
1061         // It is a WinIE bug that floated list items lose their bullets, so we'll emulate the quirk, but only in quirks mode.
1062         if (!strictParsing && isFloating)
1063             return BLOCK;
1064         return display;
1065     case INLINE_TABLE:
1066         return TABLE;
1067     case INLINE_BOX:
1068         return BOX;
1069     case INLINE_FLEX:
1070     case WEBKIT_INLINE_FLEX:
1071         return FLEX;
1072 #if ENABLE(CSS_GRID_LAYOUT)
1073     case INLINE_GRID:
1074         return GRID;
1075 #endif
1076
1077     case INLINE:
1078     case COMPACT:
1079     case INLINE_BLOCK:
1080     case TABLE_ROW_GROUP:
1081     case TABLE_HEADER_GROUP:
1082     case TABLE_FOOTER_GROUP:
1083     case TABLE_ROW:
1084     case TABLE_COLUMN_GROUP:
1085     case TABLE_COLUMN:
1086     case TABLE_CELL:
1087     case TABLE_CAPTION:
1088         return BLOCK;
1089     case NONE:
1090         ASSERT_NOT_REACHED();
1091         return NONE;
1092     }
1093     ASSERT_NOT_REACHED();
1094     return BLOCK;
1095 }
1096
1097 // CSS requires text-decoration to be reset at each DOM element for tables, 
1098 // inline blocks, inline tables, shadow DOM crossings, floating elements,
1099 // and absolute or relatively positioned elements.
1100 static bool doesNotInheritTextDecoration(const RenderStyle& style, Element* e)
1101 {
1102     return style.display() == TABLE || style.display() == INLINE_TABLE
1103         || style.display() == INLINE_BLOCK || style.display() == INLINE_BOX || isAtShadowBoundary(e)
1104         || style.isFloating() || style.hasOutOfFlowPosition();
1105 }
1106
1107 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1108 static bool isScrollableOverflow(EOverflow overflow)
1109 {
1110     return overflow == OSCROLL || overflow == OAUTO || overflow == OOVERLAY;
1111 }
1112 #endif
1113
1114 void StyleResolver::adjustStyleForInterCharacterRuby()
1115 {
1116     RenderStyle* style = m_state.style();
1117     if (style->rubyPosition() != RubyPositionInterCharacter || !m_state.element() || !m_state.element()->hasTagName(rtTag))
1118         return;
1119     style->setTextAlign(CENTER);
1120     if (style->isHorizontalWritingMode())
1121         style->setWritingMode(LeftToRightWritingMode);
1122 }
1123
1124 void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& parentStyle, Element *e)
1125 {
1126     // Cache our original display.
1127     style.setOriginalDisplay(style.display());
1128
1129     if (style.display() != NONE) {
1130         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1131         // property.
1132         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1133         // these tags to retain their display types.
1134         if (document().inQuirksMode() && e) {
1135             if (e->hasTagName(tdTag)) {
1136                 style.setDisplay(TABLE_CELL);
1137                 style.setFloating(NoFloat);
1138             } else if (is<HTMLTableElement>(*e))
1139                 style.setDisplay(style.isDisplayInlineType() ? INLINE_TABLE : TABLE);
1140         }
1141
1142         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1143             if (style.whiteSpace() == KHTML_NOWRAP) {
1144                 // Figure out if we are really nowrapping or if we should just
1145                 // use normal instead. If the width of the cell is fixed, then
1146                 // we don't actually use NOWRAP.
1147                 if (style.width().isFixed())
1148                     style.setWhiteSpace(NORMAL);
1149                 else
1150                     style.setWhiteSpace(NOWRAP);
1151             }
1152         }
1153
1154         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1155         if (is<HTMLTableElement>(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT))
1156             style.setTextAlign(TASTART);
1157
1158         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1159         // fix a crash where a site tries to position these objects. They also never honor display.
1160         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1161             style.setPosition(StaticPosition);
1162             style.setDisplay(BLOCK);
1163         }
1164
1165         // Ruby text does not support float or position. This might change with evolution of the specification.
1166         if (e && e->hasTagName(rtTag)) {
1167             style.setPosition(StaticPosition);
1168             style.setFloating(NoFloat);
1169         }
1170
1171         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1172         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1173         if (e && e->hasTagName(thTag) && style.textAlign() == TASTART)
1174             style.setTextAlign(CENTER);
1175
1176         if (e && e->hasTagName(legendTag))
1177             style.setDisplay(BLOCK);
1178
1179         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1180         if (style.hasOutOfFlowPosition() || style.isFloating() || (e && e->document().documentElement() == e))
1181             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1182
1183         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1184         // clear how that should work.
1185         if (style.display() == INLINE && style.styleType() == NOPSEUDO && style.writingMode() != parentStyle.writingMode())
1186             style.setDisplay(INLINE_BLOCK);
1187
1188         // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
1189         // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
1190         // on some sites).
1191         if ((style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW_GROUP
1192             || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW)
1193             && style.position() == RelativePosition)
1194             style.setPosition(StaticPosition);
1195
1196         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1197         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1198         if (style.display() == TABLE_COLUMN || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_FOOTER_GROUP
1199             || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW || style.display() == TABLE_ROW_GROUP
1200             || style.display() == TABLE_CELL)
1201             style.setWritingMode(parentStyle.writingMode());
1202
1203         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1204         // of block-flow to anything other than TopToBottomWritingMode.
1205         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1206         if (style.writingMode() != TopToBottomWritingMode && (style.display() == BOX || style.display() == INLINE_BOX))
1207             style.setWritingMode(TopToBottomWritingMode);
1208
1209         if (parentStyle.isDisplayFlexibleOrGridBox()) {
1210             style.setFloating(NoFloat);
1211             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1212         }
1213     }
1214
1215     // Make sure our z-index value is only applied if the object is positioned.
1216     if (style.position() == StaticPosition && !parentStyle.isDisplayFlexibleOrGridBox())
1217         style.setHasAutoZIndex();
1218
1219     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1220     // cases where objects that should be blended as a single unit end up with a non-transparent
1221     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1222     if (style.hasAutoZIndex() && ((e && e->document().documentElement() == e)
1223         || style.opacity() < 1.0f
1224         || style.hasTransformRelatedProperty()
1225         || style.hasMask()
1226         || style.clipPath()
1227         || style.boxReflect()
1228         || style.hasFilter()
1229 #if ENABLE(FILTERS_LEVEL_2)
1230         || style.hasBackdropFilter()
1231 #endif
1232         || style.hasBlendMode()
1233         || style.hasIsolation()
1234         || style.position() == StickyPosition
1235         || (style.position() == FixedPosition && documentSettings() && documentSettings()->fixedPositionCreatesStackingContext())
1236         || style.hasFlowFrom()
1237         || style.willChangeCreatesStackingContext()
1238         ))
1239         style.setZIndex(0);
1240
1241     // Textarea considers overflow visible as auto.
1242     if (is<HTMLTextAreaElement>(e)) {
1243         style.setOverflowX(style.overflowX() == OVISIBLE ? OAUTO : style.overflowX());
1244         style.setOverflowY(style.overflowY() == OVISIBLE ? OAUTO : style.overflowY());
1245     }
1246
1247     // Disallow -webkit-user-modify on :pseudo and ::pseudo elements.
1248     if (e && !e->shadowPseudoId().isNull())
1249         style.setUserModify(READ_ONLY);
1250
1251     if (doesNotInheritTextDecoration(style, e))
1252         style.setTextDecorationsInEffect(style.textDecoration());
1253     else
1254         style.addToTextDecorationsInEffect(style.textDecoration());
1255
1256     // If either overflow value is not visible, change to auto.
1257     if (style.overflowX() == OMARQUEE && style.overflowY() != OMARQUEE)
1258         style.setOverflowY(OMARQUEE);
1259     else if (style.overflowY() == OMARQUEE && style.overflowX() != OMARQUEE)
1260         style.setOverflowX(OMARQUEE);
1261     else if (style.overflowX() == OVISIBLE && style.overflowY() != OVISIBLE) {
1262         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
1263         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
1264         // default to auto so we can at least scroll through the pages.
1265         style.setOverflowX(OAUTO);
1266     } else if (style.overflowY() == OVISIBLE && style.overflowX() != OVISIBLE)
1267         style.setOverflowY(OAUTO);
1268
1269     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
1270     // styles are specified on a root element, then they will be incorporated in
1271     // Style::createForDocument().
1272     if ((style.overflowY() == OPAGEDX || style.overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
1273         style.setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style));
1274
1275     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1276     // FIXME: Eventually table sections will support auto and scroll.
1277     if (style.display() == TABLE || style.display() == INLINE_TABLE
1278         || style.display() == TABLE_ROW_GROUP || style.display() == TABLE_ROW) {
1279         if (style.overflowX() != OVISIBLE && style.overflowX() != OHIDDEN)
1280             style.setOverflowX(OVISIBLE);
1281         if (style.overflowY() != OVISIBLE && style.overflowY() != OHIDDEN)
1282             style.setOverflowY(OVISIBLE);
1283     }
1284
1285     // Menulists should have visible overflow
1286     if (style.appearance() == MenulistPart) {
1287         style.setOverflowX(OVISIBLE);
1288         style.setOverflowY(OVISIBLE);
1289     }
1290
1291 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1292     // Touch overflow scrolling creates a stacking context.
1293     if (style.hasAutoZIndex() && style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY())))
1294         style.setZIndex(0);
1295 #endif
1296
1297     // Cull out any useless layers and also repeat patterns into additional layers.
1298     style.adjustBackgroundLayers();
1299     style.adjustMaskLayers();
1300
1301     // Do the same for animations and transitions.
1302     style.adjustAnimations();
1303     style.adjustTransitions();
1304
1305     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1306     // alter fonts and heights/widths.
1307     if (is<HTMLFormControlElement>(e) && style.fontSize() >= 11) {
1308         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1309         // so we have to treat all image buttons as though they were explicitly sized.
1310         if (!is<HTMLInputElement>(*e) || !downcast<HTMLInputElement>(*e).isImageButton())
1311             addIntrinsicMargins(style);
1312     }
1313
1314     // Let the theme also have a crack at adjusting the style.
1315     if (style.hasAppearance())
1316         RenderTheme::defaultTheme()->adjustStyle(*this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
1317
1318     // If we have first-letter pseudo style, do not share this style.
1319     if (style.hasPseudoStyle(FIRST_LETTER))
1320         style.setUnique();
1321
1322     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
1323     if (style.preserves3D() && (style.overflowX() != OVISIBLE
1324         || style.overflowY() != OVISIBLE
1325         || style.hasFilter()
1326 #if ENABLE(FILTERS_LEVEL_2)
1327         || style.hasBackdropFilter()
1328 #endif
1329         || style.hasBlendMode()))
1330         style.setTransformStyle3D(TransformStyle3DFlat);
1331
1332     if (e && e->isSVGElement()) {
1333         // Only the root <svg> element in an SVG document fragment tree honors css position
1334         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1335             style.setPosition(RenderStyle::initialPosition());
1336
1337         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
1338         // not be scaled again.
1339         if (e->hasTagName(SVGNames::foreignObjectTag))
1340             style.setEffectiveZoom(RenderStyle::initialZoom());
1341
1342         // SVG text layout code expects us to be a block-level style element.
1343         if ((e->hasTagName(SVGNames::foreignObjectTag) || e->hasTagName(SVGNames::textTag)) && style.isDisplayInlineType())
1344             style.setDisplay(BLOCK);
1345     }
1346
1347     // If the inherited value of justify-items includes the legacy keyword, 'auto'
1348     // computes to the the inherited value.
1349     if (parentStyle.justifyItemsPositionType() == LegacyPosition && style.justifyItemsPosition() == ItemPositionAuto)
1350         style.setJustifyItems(parentStyle.justifyItems());
1351 }
1352
1353 bool StyleResolver::checkRegionStyle(Element* regionElement)
1354 {
1355     unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size();
1356     for (unsigned i = 0; i < rulesSize; ++i) {
1357         ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1358         if (checkRegionSelector(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1359             return true;
1360     }
1361
1362     if (m_ruleSets.userStyle()) {
1363         rulesSize = m_ruleSets.userStyle()->regionSelectorsAndRuleSets().size();
1364         for (unsigned i = 0; i < rulesSize; ++i) {
1365             ASSERT(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1366             if (checkRegionSelector(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1367                 return true;
1368         }
1369     }
1370
1371     return false;
1372 }
1373
1374 static void checkForOrientationChange(RenderStyle* style)
1375 {
1376     FontOrientation fontOrientation;
1377     NonCJKGlyphOrientation glyphOrientation;
1378     std::tie(fontOrientation, glyphOrientation) = style->fontAndGlyphOrientation();
1379
1380     const auto& fontDescription = style->fontDescription();
1381     if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
1382         return;
1383
1384     auto newFontDescription = fontDescription;
1385     newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
1386     newFontDescription.setOrientation(fontOrientation);
1387     style->setFontDescription(newFontDescription);
1388 }
1389
1390 void StyleResolver::updateFont()
1391 {
1392     if (!m_state.fontDirty())
1393         return;
1394
1395     RenderStyle* style = m_state.style();
1396 #if ENABLE(IOS_TEXT_AUTOSIZING)
1397     checkForTextSizeAdjust(style);
1398 #endif
1399     checkForGenericFamilyChange(style, m_state.parentStyle());
1400     checkForZoomChange(style, m_state.parentStyle());
1401     checkForOrientationChange(style);
1402     style->fontCascade().update(&document().fontSelector());
1403     if (m_state.fontSizeHasViewportUnits())
1404         style->setHasViewportUnits(true);
1405     m_state.setFontDirty(false);
1406 }
1407
1408 Vector<RefPtr<StyleRule>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
1409 {
1410     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1411 }
1412
1413 Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
1414 {
1415     if (!element || !element->document().haveStylesheetsLoaded())
1416         return Vector<RefPtr<StyleRule>>();
1417
1418     initElement(element);
1419     m_state.initForStyleResolve(document(), element, nullptr);
1420
1421     ElementRuleCollector collector(*element, m_state.style(), m_ruleSets, m_selectorFilter);
1422     collector.setMode(SelectorChecker::Mode::CollectingRules);
1423     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1424     collector.setMedium(m_medium.get());
1425
1426     if (rulesToInclude & UAAndUserCSSRules) {
1427         // First we match rules from the user agent sheet.
1428         collector.matchUARules();
1429         
1430         // Now we check user sheet rules.
1431         if (m_matchAuthorAndUserStyles)
1432             collector.matchUserRules(rulesToInclude & EmptyCSSRules);
1433     }
1434
1435     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1436         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
1437
1438         // Check the rules in author sheets.
1439         collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
1440     }
1441
1442     return collector.matchedRuleList();
1443 }
1444
1445 static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
1446 {
1447     switch (propertyID) {
1448     case CSSPropertyWebkitBackgroundClip:
1449     case CSSPropertyBackgroundClip:
1450     case CSSPropertyWebkitBackgroundOrigin:
1451     case CSSPropertyBackgroundOrigin:
1452     case CSSPropertyWebkitBackgroundSize:
1453     case CSSPropertyBackgroundSize:
1454     case CSSPropertyWebkitBorderImage:
1455     case CSSPropertyBorderImage:
1456     case CSSPropertyBorderImageSlice:
1457     case CSSPropertyBorderImageSource:
1458     case CSSPropertyBorderImageOutset:
1459     case CSSPropertyBorderImageRepeat:
1460     case CSSPropertyBorderImageWidth:
1461     case CSSPropertyWebkitBoxShadow:
1462     case CSSPropertyBoxShadow:
1463     case CSSPropertyWebkitTextDecoration:
1464     case CSSPropertyWebkitTextDecorationLine:
1465     case CSSPropertyWebkitTextDecorationStyle:
1466     case CSSPropertyWebkitTextDecorationColor:
1467     case CSSPropertyWebkitTextDecorationSkip:
1468     case CSSPropertyWebkitTextUnderlinePosition:
1469     case CSSPropertyTextDecoration:
1470         return true;
1471     default:
1472         return false;
1473     }
1474 }
1475
1476 static bool elementTypeHasAppearanceFromUAStyle(const Element& element)
1477 {
1478     // NOTE: This is just a hard-coded list of elements that have some -webkit-appearance value in html.css
1479     const auto& localName = element.localName();
1480     return localName == HTMLNames::inputTag
1481         || localName == HTMLNames::textareaTag
1482         || localName == HTMLNames::buttonTag
1483         || localName == HTMLNames::progressTag
1484         || localName == HTMLNames::selectTag
1485         || localName == HTMLNames::meterTag
1486         || localName == HTMLNames::isindexTag;
1487 }
1488
1489 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1490 {
1491     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1492 }
1493
1494 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1495 {
1496     return a.firstUARule == b.firstUARule
1497         && a.lastUARule == b.lastUARule
1498         && a.firstAuthorRule == b.firstAuthorRule
1499         && a.lastAuthorRule == b.lastAuthorRule
1500         && a.firstUserRule == b.firstUserRule
1501         && a.lastUserRule == b.lastUserRule;
1502 }
1503
1504 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1505 {
1506     return !(a == b);
1507 }
1508
1509 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1510 {
1511     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
1512 }
1513
1514 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1515 {
1516     return !(a == b);
1517 }
1518
1519 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
1520 {
1521     ASSERT(hash);
1522
1523     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
1524     if (it == m_matchedPropertiesCache.end())
1525         return nullptr;
1526     MatchedPropertiesCacheItem& cacheItem = it->value;
1527
1528     size_t size = matchResult.matchedProperties().size();
1529     if (size != cacheItem.matchedProperties.size())
1530         return nullptr;
1531     for (size_t i = 0; i < size; ++i) {
1532         if (matchResult.matchedProperties()[i] != cacheItem.matchedProperties[i])
1533             return nullptr;
1534     }
1535     if (cacheItem.ranges != matchResult.ranges)
1536         return nullptr;
1537     return &cacheItem;
1538 }
1539
1540 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
1541 {
1542     static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
1543     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps
1544         && !m_matchedPropertiesCacheSweepTimer.isActive()) {
1545         static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
1546         m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
1547     }
1548
1549     ASSERT(hash);
1550     MatchedPropertiesCacheItem cacheItem;
1551     cacheItem.matchedProperties.appendVector(matchResult.matchedProperties());
1552     cacheItem.ranges = matchResult.ranges;
1553     // Note that we don't cache the original RenderStyle instance. It may be further modified.
1554     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
1555     cacheItem.renderStyle = RenderStyle::clone(style);
1556     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
1557     m_matchedPropertiesCache.add(hash, WTF::move(cacheItem));
1558 }
1559
1560 void StyleResolver::invalidateMatchedPropertiesCache()
1561 {
1562     m_matchedPropertiesCache.clear();
1563 }
1564
1565 void StyleResolver::clearCachedPropertiesAffectedByViewportUnits()
1566 {
1567     Vector<unsigned, 16> toRemove;
1568     for (auto& cacheKeyValue : m_matchedPropertiesCache) {
1569         if (cacheKeyValue.value.renderStyle->hasViewportUnits())
1570             toRemove.append(cacheKeyValue.key);
1571     }
1572     for (auto key : toRemove)
1573         m_matchedPropertiesCache.remove(key);
1574 }
1575
1576 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
1577 {
1578     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
1579     if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement())
1580         return false;
1581     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
1582         return false;
1583     if (style->hasAppearance())
1584         return false;
1585     if (style->zoom() != RenderStyle::initialZoom())
1586         return false;
1587     if (style->writingMode() != RenderStyle::initialWritingMode() || style->direction() != RenderStyle::initialDirection())
1588         return false;
1589     // The cache assumes static knowledge about which properties are inherited.
1590     if (parentStyle->hasExplicitlyInheritedProperties())
1591         return false;
1592     return true;
1593 }
1594
1595 void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolver::MatchResult& matchResult, TextDirection& direction, WritingMode& writingMode)
1596 {
1597     direction = style.direction();
1598     writingMode = style.writingMode();
1599
1600     bool hadImportantWebkitWritingMode = false;
1601     bool hadImportantDirection = false;
1602
1603     for (const auto& matchedProperties : matchResult.matchedProperties()) {
1604         for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) {
1605             auto property = matchedProperties.properties->propertyAt(i);
1606             if (!property.value()->isPrimitiveValue())
1607                 continue;
1608             switch (property.id()) {
1609             case CSSPropertyWebkitWritingMode:
1610                 if (!hadImportantWebkitWritingMode || property.isImportant()) {
1611                     writingMode = downcast<CSSPrimitiveValue>(*property.value());
1612                     hadImportantWebkitWritingMode = property.isImportant();
1613                 }
1614                 break;
1615             case CSSPropertyDirection:
1616                 if (!hadImportantDirection || property.isImportant()) {
1617                     direction = downcast<CSSPrimitiveValue>(*property.value());
1618                     hadImportantDirection = property.isImportant();
1619                 }
1620                 break;
1621             default:
1622                 break;
1623             }
1624         }
1625     }
1626 }
1627
1628 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache)
1629 {
1630     ASSERT(element);
1631     State& state = m_state;
1632     unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties().data(), matchResult.matchedProperties().size()) : 0;
1633     bool applyInheritedOnly = false;
1634     const MatchedPropertiesCacheItem* cacheItem = nullptr;
1635     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))
1636         && isCacheableInMatchedPropertiesCache(element, state.style(), state.parentStyle())) {
1637         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1638         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
1639         // element context. This is fast and saves memory by reusing the style data structures.
1640         state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
1641         if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
1642             EInsideLink linkStatus = state.style()->insideLink();
1643             // If the cache item parent style has identical inherited properties to the current parent style then the
1644             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1645             state.style()->inheritFrom(cacheItem->renderStyle.get());
1646
1647             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1648             state.style()->setInsideLink(linkStatus);
1649             return;
1650         }
1651         applyInheritedOnly = true; 
1652     }
1653
1654     // Directional properties (*-before/after) are aliases that depend on the TextDirection and WritingMode.
1655     // These must be resolved before we can begin the property cascade.
1656     TextDirection direction;
1657     WritingMode writingMode;
1658     extractDirectionAndWritingMode(*state.style(), matchResult, direction, writingMode);
1659
1660     if (elementTypeHasAppearanceFromUAStyle(*state.element())) {
1661         // FIXME: This is such a hack.
1662         // Find out if there's a -webkit-appearance property in effect from the UA sheet.
1663         // If so, we cache the border and background styles so that RenderTheme::adjustStyle()
1664         // can look at them later to figure out if this is a styled form control or not.
1665         CascadedProperties cascade(direction, writingMode);
1666         cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1667         cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1668
1669         applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
1670         adjustStyleForInterCharacterRuby();
1671     
1672         // Resolve custom variables first.
1673         applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
1674
1675         // Start by applying properties that other properties may depend on.
1676         applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
1677     
1678         updateFont();
1679         applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
1680
1681         state.cacheBorderAndBackground();
1682     }
1683
1684     CascadedProperties cascade(direction, writingMode);
1685     cascade.addMatches(matchResult, false, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly);
1686     cascade.addMatches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1687     cascade.addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1688     cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1689     
1690     // Resolve custom properties first.
1691     applyCascadedProperties(cascade, CSSPropertyCustom, CSSPropertyCustom, &matchResult);
1692
1693     applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition, &matchResult);
1694     
1695     // Adjust the font size to be smaller if ruby-position is inter-character.
1696     adjustStyleForInterCharacterRuby();
1697
1698     // Start by applying properties that other properties may depend on.
1699     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty, &matchResult);
1700
1701     // If the effective zoom value changes, we can't use the matched properties cache. Start over.
1702     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom())
1703         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
1704
1705     // If our font got dirtied, update it now.
1706     updateFont();
1707
1708     // If the font changed, we can't use the matched properties cache. Start over.
1709     if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
1710         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
1711
1712     // Apply properties that no other properties depend on.
1713     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty, &matchResult);
1714
1715     // Finally, some properties must be applied in the order they were parsed.
1716     // There are some CSS properties that affect the same RenderStyle values,
1717     // so to preserve behavior, we queue them up during cascade and flush here.
1718     cascade.applyDeferredProperties(*this, &matchResult);
1719
1720     // Start loading resources referenced by this style.
1721     loadPendingResources();
1722     
1723     ASSERT(!state.fontDirty());
1724     
1725     if (cacheItem || !cacheHash)
1726         return;
1727     if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
1728         return;
1729     addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
1730 }
1731
1732 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
1733 {
1734     initElement(nullptr);
1735     m_state.initForStyleResolve(document(), nullptr, style);
1736     m_state.setStyle(*style);
1737     applyPropertyToCurrentStyle(id, value);
1738 }
1739
1740 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
1741 {
1742     if (value)
1743         applyProperty(id, value);
1744 }
1745
1746 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
1747 {
1748     switch (id) {
1749     case CSSPropertyBackgroundColor:
1750     case CSSPropertyBorderLeftColor:
1751     case CSSPropertyBorderRightColor:
1752     case CSSPropertyBorderTopColor:
1753     case CSSPropertyBorderBottomColor:
1754     case CSSPropertyColor:
1755     case CSSPropertyOutlineColor:
1756     case CSSPropertyColumnRuleColor:
1757     case CSSPropertyWebkitTextDecorationColor:
1758     case CSSPropertyWebkitTextEmphasisColor:
1759     case CSSPropertyWebkitTextFillColor:
1760     case CSSPropertyWebkitTextStrokeColor:
1761     case CSSPropertyFill:
1762     case CSSPropertyStroke:
1763         return true;
1764     default:
1765         break;
1766     }
1767
1768     return false;
1769 }
1770
1771 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
1772 // FIXME: add incremental support for other region styling properties.
1773 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
1774 {
1775     switch (id) {
1776     case CSSPropertyBackgroundColor:
1777     case CSSPropertyColor:
1778         return true;
1779     default:
1780         break;
1781     }
1782
1783     return false;
1784 }
1785
1786 #if ENABLE(VIDEO_TRACK)
1787 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
1788 {
1789     switch (id) {
1790     case CSSPropertyBackground:
1791     case CSSPropertyBackgroundAttachment:
1792     case CSSPropertyBackgroundClip:
1793     case CSSPropertyBackgroundColor:
1794     case CSSPropertyBackgroundImage:
1795     case CSSPropertyBackgroundOrigin:
1796     case CSSPropertyBackgroundPosition:
1797     case CSSPropertyBackgroundPositionX:
1798     case CSSPropertyBackgroundPositionY:
1799     case CSSPropertyBackgroundRepeat:
1800     case CSSPropertyBackgroundRepeatX:
1801     case CSSPropertyBackgroundRepeatY:
1802     case CSSPropertyBackgroundSize:
1803     case CSSPropertyColor:
1804     case CSSPropertyFont:
1805     case CSSPropertyFontFamily:
1806     case CSSPropertyFontSize:
1807     case CSSPropertyFontStyle:
1808     case CSSPropertyFontVariant:
1809     case CSSPropertyFontWeight:
1810     case CSSPropertyLineHeight:
1811     case CSSPropertyOpacity:
1812     case CSSPropertyOutline:
1813     case CSSPropertyOutlineColor:
1814     case CSSPropertyOutlineOffset:
1815     case CSSPropertyOutlineStyle:
1816     case CSSPropertyOutlineWidth:
1817     case CSSPropertyVisibility:
1818     case CSSPropertyWhiteSpace:
1819     case CSSPropertyTextDecoration:
1820     case CSSPropertyTextShadow:
1821     case CSSPropertyBorderStyle:
1822         return true;
1823     default:
1824         break;
1825     }
1826     return false;
1827 }
1828 #endif
1829 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
1830 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
1831 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
1832 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
1833 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
1834 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
1835 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
1836 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
1837 bool StyleResolver::useSVGZoomRules()
1838 {
1839     return m_state.element() && m_state.element()->isSVGElement();
1840 }
1841
1842 // Scale with/height properties on inline SVG root.
1843 bool StyleResolver::useSVGZoomRulesForLength()
1844 {
1845     return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
1846 }
1847
1848 StyleResolver::CascadedProperties* StyleResolver::cascadedPropertiesForRollback(const MatchResult& matchResult)
1849 {
1850     ASSERT(cascadeLevel() != UserAgentLevel);
1851     
1852     TextDirection direction;
1853     WritingMode writingMode;
1854     extractDirectionAndWritingMode(*state().style(), matchResult, direction, writingMode);
1855
1856     if (cascadeLevel() == AuthorLevel) {
1857         CascadedProperties* authorRollback = state().authorRollback();
1858         if (authorRollback)
1859             return authorRollback;
1860         
1861         auto newAuthorRollback(std::make_unique<CascadedProperties>(direction, writingMode));
1862         
1863         // This special rollback cascade contains UA rules and user rules but no author rules.
1864         newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
1865         newAuthorRollback->addMatches(matchResult, false, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
1866         newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, false);
1867         newAuthorRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
1868     
1869         state().setAuthorRollback(newAuthorRollback);
1870         return state().authorRollback();
1871     }
1872     
1873     if (cascadeLevel() == UserLevel) {
1874         CascadedProperties* userRollback = state().userRollback();
1875         if (userRollback)
1876             return userRollback;
1877         
1878         auto newUserRollback(std::make_unique<CascadedProperties>(direction, writingMode));
1879         
1880         // This special rollback cascade contains only UA rules.
1881         newUserRollback->addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
1882         newUserRollback->addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, false);
1883     
1884         state().setUserRollback(newUserRollback);
1885         return state().userRollback();
1886     }
1887     
1888     return nullptr;
1889 }
1890
1891 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value, SelectorChecker::LinkMatchMask linkMatchMask, const MatchResult* matchResult)
1892 {
1893     ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
1894
1895     State& state = m_state;
1896     
1897     RefPtr<CSSValue> valueToApply = value;
1898     if (value->isVariableDependentValue()) {
1899         valueToApply = resolvedVariableValue(id, *downcast<CSSVariableDependentValue>(value));
1900         if (!valueToApply) {
1901             if (CSSProperty::isInheritedProperty(id))
1902                 valueToApply = CSSInheritedValue::create();
1903             else
1904                 valueToApply = CSSInitialValue::createExplicit();
1905         }
1906     }
1907
1908     if (CSSProperty::isDirectionAwareProperty(id)) {
1909         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
1910         ASSERT(newId != id);
1911         return applyProperty(newId, valueToApply.get(), linkMatchMask, matchResult);
1912     }
1913     
1914     CSSValue* valueToCheckForInheritInitial = valueToApply.get();
1915     CSSCustomPropertyValue* customPropertyValue = nullptr;
1916     
1917     if (id == CSSPropertyCustom) {
1918         customPropertyValue = &downcast<CSSCustomPropertyValue>(*valueToApply);
1919         valueToCheckForInheritInitial = customPropertyValue->value().get();
1920     }
1921
1922     bool isInherit = state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue();
1923     bool isInitial = valueToCheckForInheritInitial->isInitialValue() || (!state.parentStyle() && valueToCheckForInheritInitial->isInheritedValue());
1924     
1925     bool isUnset = valueToCheckForInheritInitial->isUnsetValue();
1926     bool isRevert = valueToCheckForInheritInitial->isRevertValue();
1927
1928     if (isRevert) {
1929         if (cascadeLevel() == UserAgentLevel || !matchResult)
1930             isUnset = true;
1931         else {
1932             // Fetch the correct rollback object from the state, building it if necessary.
1933             // This requires having the original MatchResult available.
1934             auto* rollback = cascadedPropertiesForRollback(*matchResult);
1935             ASSERT(rollback);
1936
1937             // With the cascade built, we need to obtain the property and apply it. If the property is
1938             // not present, then we behave like "unset." Otherwise we apply the property instead of
1939             // our own.
1940             if (customPropertyValue) {
1941                 if (rollback->hasCustomProperty(customPropertyValue->name())) {
1942                     auto property = rollback->customProperty(customPropertyValue->name());
1943                     if (property.cssValue[linkMatchMask])
1944                         applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
1945                     return;
1946                 }
1947             } else if (rollback->hasProperty(id)) {
1948                 auto& property = rollback->property(id);
1949                 if (property.cssValue[linkMatchMask])
1950                     applyProperty(property.id, property.cssValue[linkMatchMask], linkMatchMask, matchResult);
1951                 return;
1952             }
1953         
1954             isUnset = true;
1955         }
1956     }
1957     
1958     if (isUnset) {
1959         if (CSSProperty::isInheritedProperty(id))
1960             isInherit = true;
1961         else
1962             isInitial = true;
1963     }
1964
1965     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
1966
1967     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
1968         // Limit the properties that can be applied to only the ones honored by :visited.
1969         return;
1970     }
1971
1972     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
1973         state.parentStyle()->setHasExplicitlyInheritedProperties();
1974     
1975     if (id == CSSPropertyCustom) {
1976         CSSCustomPropertyValue* customProperty = &downcast<CSSCustomPropertyValue>(*valueToApply);
1977         if (isInherit) {
1978             RefPtr<CSSValue> customVal = state.parentStyle()->getCustomPropertyValue(customProperty->name());
1979             if (!customVal)
1980                 customVal = CSSCustomPropertyValue::createInvalid();
1981             state.style()->setCustomPropertyValue(customProperty->name(), customVal);
1982         } else if (isInitial)
1983             state.style()->setCustomPropertyValue(customProperty->name(), CSSCustomPropertyValue::createInvalid());
1984         else
1985             state.style()->setCustomPropertyValue(customProperty->name(), customProperty->value());
1986         return;
1987     }
1988
1989     // Use the generated StyleBuilder.
1990     StyleBuilder::applyProperty(id, *this, *valueToApply, isInitial, isInherit);
1991 }
1992
1993 RefPtr<CSSValue> StyleResolver::resolvedVariableValue(CSSPropertyID propID, const CSSVariableDependentValue& value)
1994 {
1995     CSSParser parser(m_state.document());
1996     return parser.parseVariableDependentValue(propID, value, m_state.style()->customProperties());
1997 }
1998
1999 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue& value)
2000 {
2001     if (is<CSSImageValue>(value))
2002         return cachedOrPendingFromValue(property, downcast<CSSImageValue>(value));
2003
2004     if (is<CSSImageGeneratorValue>(value)) {
2005         if (is<CSSGradientValue>(value))
2006             return generatedOrPendingFromValue(property, *downcast<CSSGradientValue>(value).gradientWithStylesResolved(this));
2007         return generatedOrPendingFromValue(property, downcast<CSSImageGeneratorValue>(value));
2008     }
2009
2010 #if ENABLE(CSS_IMAGE_SET)
2011     if (is<CSSImageSetValue>(value))
2012         return setOrPendingFromValue(property, downcast<CSSImageSetValue>(value));
2013 #endif
2014
2015     if (is<CSSCursorImageValue>(value))
2016         return cursorOrPendingFromValue(property, downcast<CSSCursorImageValue>(value));
2017
2018     return nullptr;
2019 }
2020
2021 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue& value)
2022 {
2023     RefPtr<StyleImage> image = value.cachedOrPendingImage();
2024     if (image && image->isPendingImage())
2025         m_state.pendingImageProperties().set(property, &value);
2026     return image.release();
2027 }
2028
2029 PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
2030 {
2031     if (is<CSSFilterImageValue>(value)) {
2032         // FilterImage needs to calculate FilterOperations.
2033         downcast<CSSFilterImageValue>(value).createFilterOperations(this);
2034     }
2035
2036     if (value.isPending()) {
2037         m_state.pendingImageProperties().set(property, &value);
2038         return StylePendingImage::create(&value);
2039     }
2040     return StyleGeneratedImage::create(value);
2041 }
2042
2043 #if ENABLE(CSS_IMAGE_SET)
2044 PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue& value)
2045 {
2046     RefPtr<StyleImage> image = value.cachedOrPendingImageSet(document());
2047     if (image && image->isPendingImage())
2048         m_state.pendingImageProperties().set(property, &value);
2049     return image.release();
2050 }
2051 #endif
2052
2053 PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue& value)
2054 {
2055     RefPtr<StyleImage> image = value.cachedOrPendingImage(document());
2056     if (image && image->isPendingImage())
2057         m_state.pendingImageProperties().set(property, &value);
2058     return image.release();
2059 }
2060
2061 #if ENABLE(IOS_TEXT_AUTOSIZING)
2062 void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
2063 {
2064     if (style->textSizeAdjust().isAuto())
2065         return;
2066
2067     auto newFontDescription = style->fontDescription();
2068     if (!style->textSizeAdjust().isNone())
2069         newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier());
2070     else
2071         newFontDescription.setComputedSize(newFontDescription.specifiedSize());
2072     style->setFontDescription(newFontDescription);
2073 }
2074 #endif
2075
2076 void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
2077 {
2078     if (!parentStyle)
2079         return;
2080     
2081     if (style->effectiveZoom() == parentStyle->effectiveZoom() && style->textZoom() == parentStyle->textZoom())
2082         return;
2083
2084     const auto& childFont = style->fontDescription();
2085     auto newFontDescription = childFont;
2086     setFontSize(newFontDescription, childFont.specifiedSize());
2087     style->setFontDescription(newFontDescription);
2088 }
2089
2090 void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
2091 {
2092     const auto& childFont = style->fontDescription();
2093
2094     if (childFont.isAbsoluteSize() || !parentStyle)
2095         return;
2096
2097     const auto& parentFont = parentStyle->fontDescription();
2098     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
2099         return;
2100     // We know the parent is monospace or the child is monospace, and that font
2101     // size was unspecified. We want to scale our font size as appropriate.
2102     // If the font uses a keyword size, then we refetch from the table rather than
2103     // multiplying by our scale factor.
2104     float size;
2105     if (CSSValueID sizeIdentifier = childFont.keywordSizeAsIdentifier())
2106         size = Style::fontSizeForKeyword(sizeIdentifier, childFont.useFixedDefaultSize(), document());
2107     else {
2108         Settings* settings = documentSettings();
2109         float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
2110             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
2111             : 1;
2112         size = parentFont.useFixedDefaultSize() ?
2113                 childFont.specifiedSize() / fixedScaleFactor :
2114                 childFont.specifiedSize() * fixedScaleFactor;
2115     }
2116
2117     auto newFontDescription = childFont;
2118     setFontSize(newFontDescription, size);
2119     style->setFontDescription(newFontDescription);
2120 }
2121
2122 void StyleResolver::initializeFontStyle(Settings* settings)
2123 {
2124     FontCascadeDescription fontDescription;
2125     if (settings)
2126         fontDescription.setRenderingMode(settings->fontRenderingMode());
2127     fontDescription.setOneFamily(standardFamily);
2128     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
2129     setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
2130     setFontDescription(fontDescription);
2131 }
2132
2133 void StyleResolver::setFontSize(FontCascadeDescription& fontDescription, float size)
2134 {
2135     fontDescription.setSpecifiedSize(size);
2136     fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
2137 }
2138
2139 static Color colorForCSSValue(CSSValueID cssValueId)
2140 {
2141     struct ColorValue {
2142         CSSValueID cssValueId;
2143         RGBA32 color;
2144     };
2145
2146     static const ColorValue colorValues[] = {
2147         { CSSValueAqua, 0xFF00FFFF },
2148         { CSSValueBlack, 0xFF000000 },
2149         { CSSValueBlue, 0xFF0000FF },
2150         { CSSValueFuchsia, 0xFFFF00FF },
2151         { CSSValueGray, 0xFF808080 },
2152         { CSSValueGreen, 0xFF008000  },
2153         { CSSValueGrey, 0xFF808080 },
2154         { CSSValueLime, 0xFF00FF00 },
2155         { CSSValueMaroon, 0xFF800000 },
2156         { CSSValueNavy, 0xFF000080 },
2157         { CSSValueOlive, 0xFF808000  },
2158         { CSSValueOrange, 0xFFFFA500 },
2159         { CSSValuePurple, 0xFF800080 },
2160         { CSSValueRed, 0xFFFF0000 },
2161         { CSSValueSilver, 0xFFC0C0C0 },
2162         { CSSValueTeal, 0xFF008080  },
2163         { CSSValueTransparent, 0x00000000 },
2164         { CSSValueWhite, 0xFFFFFFFF },
2165         { CSSValueYellow, 0xFFFFFF00 },
2166         { CSSValueInvalid, CSSValueInvalid }
2167     };
2168
2169     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
2170         if (col->cssValueId == cssValueId)
2171             return col->color;
2172     }
2173     return RenderTheme::defaultTheme()->systemColor(cssValueId);
2174 }
2175
2176 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue& value)
2177 {
2178     int ident = value.getValueID();
2179     switch (ident) {
2180     case CSSValueWebkitText:
2181     case CSSValueWebkitLink:
2182     case CSSValueWebkitActivelink:
2183     case CSSValueCurrentcolor:
2184         return true;
2185     default:
2186         return false;
2187     }
2188 }
2189
2190 Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue& value, bool forVisitedLink) const
2191 {
2192     if (value.isRGBColor())
2193         return Color(value.getRGBA32Value());
2194
2195     const State& state = m_state;
2196     CSSValueID ident = value.getValueID();
2197     switch (ident) {
2198     case 0:
2199         return Color();
2200     case CSSValueWebkitText:
2201         return state.document().textColor();
2202     case CSSValueWebkitLink:
2203         return (state.element()->isLink() && forVisitedLink) ? state.document().visitedLinkColor() : state.document().linkColor();
2204     case CSSValueWebkitActivelink:
2205         return state.document().activeLinkColor();
2206     case CSSValueWebkitFocusRingColor:
2207         return RenderTheme::focusRingColor();
2208     case CSSValueCurrentcolor:
2209         return state.style()->color();
2210     default:
2211         return colorForCSSValue(ident);
2212     }
2213 }
2214
2215 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
2216 {
2217     m_viewportDependentMediaQueryResults.append(std::make_unique<MediaQueryResult>(*expr, result));
2218 }
2219
2220 bool StyleResolver::hasMediaQueriesAffectedByViewportChange() const
2221 {
2222     unsigned s = m_viewportDependentMediaQueryResults.size();
2223     for (unsigned i = 0; i < s; i++) {
2224         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
2225             return true;
2226     }
2227     return false;
2228 }
2229
2230 static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
2231 {
2232     switch (type) {
2233     case WebKitCSSFilterValue::ReferenceFilterOperation:
2234         return FilterOperation::REFERENCE;
2235     case WebKitCSSFilterValue::GrayscaleFilterOperation:
2236         return FilterOperation::GRAYSCALE;
2237     case WebKitCSSFilterValue::SepiaFilterOperation:
2238         return FilterOperation::SEPIA;
2239     case WebKitCSSFilterValue::SaturateFilterOperation:
2240         return FilterOperation::SATURATE;
2241     case WebKitCSSFilterValue::HueRotateFilterOperation:
2242         return FilterOperation::HUE_ROTATE;
2243     case WebKitCSSFilterValue::InvertFilterOperation:
2244         return FilterOperation::INVERT;
2245     case WebKitCSSFilterValue::OpacityFilterOperation:
2246         return FilterOperation::OPACITY;
2247     case WebKitCSSFilterValue::BrightnessFilterOperation:
2248         return FilterOperation::BRIGHTNESS;
2249     case WebKitCSSFilterValue::ContrastFilterOperation:
2250         return FilterOperation::CONTRAST;
2251     case WebKitCSSFilterValue::BlurFilterOperation:
2252         return FilterOperation::BLUR;
2253     case WebKitCSSFilterValue::DropShadowFilterOperation:
2254         return FilterOperation::DROP_SHADOW;
2255     case WebKitCSSFilterValue::UnknownFilterOperation:
2256         return FilterOperation::NONE;
2257     }
2258     return FilterOperation::NONE;
2259 }
2260
2261 void StyleResolver::loadPendingSVGDocuments()
2262 {
2263     State& state = m_state;
2264
2265     // Crash reports indicate that we've seen calls to this function when our
2266     // style is NULL. We don't know exactly why this happens. Our guess is
2267     // reentering styleForElement().
2268     ASSERT(state.style());
2269     if (!state.style() || !state.style()->hasFilter() || state.filtersWithPendingSVGDocuments().isEmpty())
2270         return;
2271
2272     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
2273     options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
2274
2275     CachedResourceLoader& cachedResourceLoader = state.document().cachedResourceLoader();
2276     
2277     for (auto& filterOperation : state.filtersWithPendingSVGDocuments())
2278         filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader, options);
2279
2280     state.filtersWithPendingSVGDocuments().clear();
2281 }
2282
2283 bool StyleResolver::createFilterOperations(CSSValue& inValue, FilterOperations& outOperations)
2284 {
2285     State& state = m_state;
2286     ASSERT(outOperations.isEmpty());
2287     
2288     if (is<CSSPrimitiveValue>(inValue)) {
2289         CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
2290         if (primitiveValue.getValueID() == CSSValueNone)
2291             return true;
2292     }
2293     
2294     if (!is<CSSValueList>(inValue))
2295         return false;
2296
2297     FilterOperations operations;
2298     for (auto& currentValue : downcast<CSSValueList>(inValue)) {
2299         if (!is<WebKitCSSFilterValue>(currentValue.get()))
2300             continue;
2301
2302         auto& filterValue = downcast<WebKitCSSFilterValue>(currentValue.get());
2303         FilterOperation::OperationType operationType = filterOperationForType(filterValue.operationType());
2304
2305         if (operationType == FilterOperation::REFERENCE) {
2306             if (filterValue.length() != 1)
2307                 continue;
2308             CSSValue& argument = *filterValue.itemWithoutBoundsCheck(0);
2309
2310             if (!is<CSSPrimitiveValue>(argument))
2311                 continue;
2312
2313             CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(argument);
2314             String cssUrl = primitiveValue.getStringValue();
2315             URL url = m_state.document().completeURL(cssUrl);
2316
2317             RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
2318             if (SVGURIReference::isExternalURIReference(cssUrl, m_state.document()))
2319                 state.filtersWithPendingSVGDocuments().append(operation);
2320
2321             operations.operations().append(operation);
2322             continue;
2323         }
2324
2325         // Check that all parameters are primitive values, with the
2326         // exception of drop shadow which has a CSSShadowValue parameter.
2327         CSSPrimitiveValue* firstValue = nullptr;
2328         if (operationType != FilterOperation::DROP_SHADOW) {
2329             bool haveNonPrimitiveValue = false;
2330             for (unsigned j = 0; j < filterValue.length(); ++j) {
2331                 if (!is<CSSPrimitiveValue>(*filterValue.itemWithoutBoundsCheck(j))) {
2332                     haveNonPrimitiveValue = true;
2333                     break;
2334                 }
2335             }
2336             if (haveNonPrimitiveValue)
2337                 continue;
2338             if (filterValue.length())
2339                 firstValue = downcast<CSSPrimitiveValue>(filterValue.itemWithoutBoundsCheck(0));
2340         }
2341
2342         switch (filterValue.operationType()) {
2343         case WebKitCSSFilterValue::GrayscaleFilterOperation:
2344         case WebKitCSSFilterValue::SepiaFilterOperation:
2345         case WebKitCSSFilterValue::SaturateFilterOperation: {
2346             double amount = 1;
2347             if (filterValue.length() == 1) {
2348                 amount = firstValue->getDoubleValue();
2349                 if (firstValue->isPercentage())
2350                     amount /= 100;
2351             }
2352
2353             operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
2354             break;
2355         }
2356         case WebKitCSSFilterValue::HueRotateFilterOperation: {
2357             double angle = 0;
2358             if (filterValue.length() == 1)
2359                 angle = firstValue->computeDegrees();
2360
2361             operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
2362             break;
2363         }
2364         case WebKitCSSFilterValue::InvertFilterOperation:
2365         case WebKitCSSFilterValue::BrightnessFilterOperation:
2366         case WebKitCSSFilterValue::ContrastFilterOperation:
2367         case WebKitCSSFilterValue::OpacityFilterOperation: {
2368             double amount = (filterValue.operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
2369             if (filterValue.length() == 1) {
2370                 amount = firstValue->getDoubleValue();
2371                 if (firstValue->isPercentage())
2372                     amount /= 100;
2373             }
2374
2375             operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
2376             break;
2377         }
2378         case WebKitCSSFilterValue::BlurFilterOperation: {
2379             Length stdDeviation = Length(0, Fixed);
2380             if (filterValue.length() >= 1)
2381                 stdDeviation = convertToFloatLength(firstValue, state.cssToLengthConversionData());
2382             if (stdDeviation.isUndefined())
2383                 return false;
2384
2385             operations.operations().append(BlurFilterOperation::create(stdDeviation));
2386             break;
2387         }
2388         case WebKitCSSFilterValue::DropShadowFilterOperation: {
2389             if (filterValue.length() != 1)
2390                 return false;
2391
2392             CSSValue& cssValue = *filterValue.itemWithoutBoundsCheck(0);
2393             if (!is<CSSShadowValue>(cssValue))
2394                 continue;
2395
2396             CSSShadowValue& item = downcast<CSSShadowValue>(cssValue);
2397             int x = item.x->computeLength<int>(state.cssToLengthConversionData());
2398             int y = item.y->computeLength<int>(state.cssToLengthConversionData());
2399             IntPoint location(x, y);
2400             int blur = item.blur ? item.blur->computeLength<int>(state.cssToLengthConversionData()) : 0;
2401             Color color;
2402             if (item.color)
2403                 color = colorFromPrimitiveValue(*item.color);
2404
2405             operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent));
2406             break;
2407         }
2408         case WebKitCSSFilterValue::UnknownFilterOperation:
2409         default:
2410             ASSERT_NOT_REACHED();
2411             break;
2412         }
2413     }
2414
2415     outOperations = operations;
2416     return true;
2417 }
2418
2419 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options)
2420 {
2421     if (auto imageValue = pendingImage.cssImageValue())
2422         return imageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
2423
2424     if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
2425         imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader(), options);
2426         return StyleGeneratedImage::create(*imageGeneratorValue);
2427     }
2428
2429     if (auto cursorImageValue = pendingImage.cssCursorImageValue())
2430         return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
2431
2432 #if ENABLE(CSS_IMAGE_SET)
2433     if (auto imageSetValue = pendingImage.cssImageSetValue())
2434         return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader(), options);
2435 #endif
2436
2437     return nullptr;
2438 }
2439
2440 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage)
2441 {
2442     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
2443     options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
2444     return loadPendingImage(pendingImage, options);
2445 }
2446
2447 #if ENABLE(CSS_SHAPES)
2448 void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
2449 {
2450     if (!shapeValue)
2451         return;
2452
2453     StyleImage* image = shapeValue->image();
2454     if (!is<StylePendingImage>(image))
2455         return;
2456
2457     auto& pendingImage = downcast<StylePendingImage>(*image);
2458
2459     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
2460     options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled);
2461     options.setAllowCredentials(DoNotAllowStoredCredentials);
2462     options.setContentSecurityPolicyImposition(m_state.element() && m_state.element()->isInUserAgentShadowTree() ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck);
2463
2464     shapeValue->setImage(loadPendingImage(pendingImage, options));
2465 }
2466 #endif
2467
2468 void StyleResolver::loadPendingImages()
2469 {
2470     RELEASE_ASSERT(!m_inLoadPendingImages);
2471     TemporaryChange<bool> changeInLoadPendingImages(m_inLoadPendingImages, true);
2472
2473     if (m_state.pendingImageProperties().isEmpty())
2474         return;
2475
2476     auto end = m_state.pendingImageProperties().end().keys();
2477     for (auto it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) {
2478         CSSPropertyID currentProperty = *it;
2479
2480         switch (currentProperty) {
2481         case CSSPropertyBackgroundImage: {
2482             for (FillLayer* backgroundLayer = &m_state.style()->ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
2483                 auto* styleImage = backgroundLayer->image();
2484                 if (is<StylePendingImage>(styleImage))
2485                     backgroundLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2486             }
2487             break;
2488         }
2489         case CSSPropertyContent: {
2490             for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
2491                 if (is<ImageContentData>(*contentData)) {
2492                     auto& styleImage = downcast<ImageContentData>(*contentData).image();
2493                     if (is<StylePendingImage>(styleImage)) {
2494                         if (RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(styleImage)))
2495                             downcast<ImageContentData>(*contentData).setImage(loadedImage.release());
2496                     }
2497                 }
2498             }
2499             break;
2500         }
2501         case CSSPropertyCursor: {
2502             if (CursorList* cursorList = m_state.style()->cursors()) {
2503                 for (size_t i = 0; i < cursorList->size(); ++i) {
2504                     CursorData& currentCursor = cursorList->at(i);
2505                     auto* styleImage = currentCursor.image();
2506                     if (is<StylePendingImage>(styleImage))
2507                         currentCursor.setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2508                 }
2509             }
2510             break;
2511         }
2512         case CSSPropertyListStyleImage: {
2513             auto* styleImage = m_state.style()->listStyleImage();
2514             if (is<StylePendingImage>(styleImage))
2515                 m_state.style()->setListStyleImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2516             break;
2517         }
2518         case CSSPropertyBorderImageSource: {
2519             auto* styleImage = m_state.style()->borderImageSource();
2520             if (is<StylePendingImage>(styleImage))
2521                 m_state.style()->setBorderImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2522             break;
2523         }
2524         case CSSPropertyWebkitBoxReflect: {
2525             if (StyleReflection* reflection = m_state.style()->boxReflect()) {
2526                 const NinePieceImage& maskImage = reflection->mask();
2527                 auto* styleImage = maskImage.image();
2528                 if (is<StylePendingImage>(styleImage)) {
2529                     RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(*styleImage));
2530                     reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
2531                 }
2532             }
2533             break;
2534         }
2535         case CSSPropertyWebkitMaskBoxImageSource: {
2536             auto* styleImage = m_state.style()->maskBoxImageSource();
2537             if (is<StylePendingImage>(styleImage))
2538                 m_state.style()->setMaskBoxImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2539             break;
2540         }
2541         case CSSPropertyWebkitMaskImage: {
2542             for (FillLayer* maskLayer = &m_state.style()->ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
2543                 auto* styleImage = maskLayer->image();
2544                 if (is<StylePendingImage>(styleImage))
2545                     maskLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2546             }
2547             break;
2548         }
2549 #if ENABLE(CSS_SHAPES)
2550         case CSSPropertyWebkitShapeOutside:
2551             loadPendingShapeImage(m_state.style()->shapeOutside());
2552             break;
2553 #endif
2554         default:
2555             ASSERT_NOT_REACHED();
2556         }
2557     }
2558
2559     m_state.pendingImageProperties().clear();
2560 }
2561
2562 #ifndef NDEBUG
2563 static bool inLoadPendingResources = false;
2564 #endif
2565
2566 void StyleResolver::loadPendingResources()
2567 {
2568     // We've seen crashes in all three of the functions below. Some of them
2569     // indicate that style() is NULL. This NULL check will cut down on total
2570     // crashes, while the ASSERT will help us find the cause in debug builds.
2571     ASSERT(style());
2572     if (!style())
2573         return;
2574
2575 #ifndef NDEBUG
2576     // Re-entering this function will probably mean trouble. Catch it in debug builds.
2577     ASSERT(!inLoadPendingResources);
2578     inLoadPendingResources = true;
2579 #endif
2580
2581     // Start loading images referenced by this style.
2582     loadPendingImages();
2583
2584     // Start loading the SVG Documents referenced by this style.
2585     loadPendingSVGDocuments();
2586
2587 #ifndef NDEBUG
2588     inLoadPendingResources = false;
2589 #endif
2590 }
2591
2592 inline StyleResolver::MatchedProperties::MatchedProperties()
2593     : possiblyPaddedMember(nullptr)
2594 {
2595 }
2596
2597 StyleResolver::MatchedProperties::~MatchedProperties()
2598 {
2599 }
2600
2601 StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
2602     : m_direction(direction)
2603     , m_writingMode(writingMode)
2604 {
2605 }
2606
2607 inline bool StyleResolver::CascadedProperties::hasProperty(CSSPropertyID id) const
2608 {
2609     ASSERT(id < m_propertyIsPresent.size());
2610     return m_propertyIsPresent[id];
2611 }
2612
2613 inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id)
2614 {
2615     return m_properties[id];
2616 }
2617
2618 inline bool StyleResolver::CascadedProperties::hasCustomProperty(const String& name) const
2619 {
2620     return m_customProperties.contains(name);
2621 }
2622
2623 inline StyleResolver::CascadedProperties::Property StyleResolver::CascadedProperties::customProperty(const String& name) const
2624 {
2625     return m_customProperties.get(name);
2626 }
2627
2628 void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
2629 {
2630     ASSERT(linkMatchType <= SelectorChecker::MatchAll);
2631     property.id = id;
2632     property.level = cascadeLevel;
2633     if (linkMatchType == SelectorChecker::MatchAll) {
2634         property.cssValue[0] = &cssValue;
2635         property.cssValue[SelectorChecker::MatchLink] = &cssValue;
2636         property.cssValue[SelectorChecker::MatchVisited] = &cssValue;
2637     } else
2638         property.cssValue[linkMatchType] = &cssValue;
2639 }
2640
2641 void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
2642 {
2643     if (CSSProperty::isDirectionAwareProperty(id))
2644         id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
2645
2646     ASSERT(!shouldApplyPropertyInParseOrder(id));
2647
2648     auto& property = m_properties[id];
2649     ASSERT(id < m_propertyIsPresent.size());
2650     if (id == CSSPropertyCustom) {
2651         m_propertyIsPresent.set(id);
2652         const auto& customValue = downcast<CSSCustomPropertyValue>(cssValue);
2653         bool hasValue = customProperties().contains(customValue.name());
2654         if (!hasValue) {
2655             Property property;
2656             property.id = id;
2657             memset(property.cssValue, 0, sizeof(property.cssValue));
2658             setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
2659             customProperties().set(customValue.name(), property);
2660         } else {
2661             Property property = customProperties().get(customValue.name());
2662             setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
2663             customProperties().set(customValue.name(), property);
2664         }
2665         return;
2666     }
2667     
2668     if (!m_propertyIsPresent[id])
2669         memset(property.cssValue, 0, sizeof(property.cssValue));
2670     m_propertyIsPresent.set(id);
2671     setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
2672 }
2673
2674 void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType, CascadeLevel cascadeLevel)
2675 {
2676     ASSERT(!CSSProperty::isDirectionAwareProperty(id));
2677     ASSERT(shouldApplyPropertyInParseOrder(id));
2678
2679     Property property;
2680     memset(property.cssValue, 0, sizeof(property.cssValue));
2681     setPropertyInternal(property, id, cssValue, linkMatchType, cascadeLevel);
2682     m_deferredProperties.append(property);
2683 }
2684
2685 void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType, CascadeLevel cascadeLevel)
2686 {
2687     for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
2688         auto current = properties.propertyAt(i);
2689         if (isImportant != current.isImportant())
2690             continue;
2691         if (inheritedOnly && !current.isInherited()) {
2692             // We apply the inherited properties only when using the property cache.
2693             // A match with a value that is explicitely inherited should never have been cached.
2694             ASSERT(!current.value()->isInheritedValue());
2695             continue;
2696         }
2697         CSSPropertyID propertyID = current.id();
2698
2699         if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(propertyID))
2700             continue;
2701 #if ENABLE(VIDEO_TRACK)
2702         if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(propertyID))
2703             continue;
2704 #endif
2705
2706         if (shouldApplyPropertyInParseOrder(propertyID))
2707             setDeferred(propertyID, *current.value(), linkMatchType, cascadeLevel);
2708         else
2709             set(propertyID, *current.value(), linkMatchType, cascadeLevel);
2710     }
2711 }
2712
2713 static CascadeLevel cascadeLevelForIndex(const StyleResolver::MatchResult& matchResult, int index)
2714 {
2715     if (index >= matchResult.ranges.firstUARule && index <= matchResult.ranges.lastUARule)
2716         return UserAgentLevel;
2717     if (index >= matchResult.ranges.firstUserRule && index <= matchResult.ranges.lastUserRule)
2718         return UserLevel;
2719     return AuthorLevel;
2720 }
2721
2722 void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly)
2723 {
2724     if (startIndex == -1)
2725         return;
2726
2727     for (int i = startIndex; i <= endIndex; ++i) {
2728         const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i];
2729         addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType,
2730             cascadeLevelForIndex(matchResult, i));
2731     }
2732 }
2733
2734 void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver, const MatchResult* matchResult)
2735 {
2736     for (auto& property : m_deferredProperties)
2737         property.apply(resolver, matchResult);
2738 }
2739
2740 void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver, const MatchResult* matchResult)
2741 {
2742     State& state = resolver.state();
2743     state.setCascadeLevel(level);
2744
2745     if (cssValue[SelectorChecker::MatchDefault]) {
2746         state.setApplyPropertyToRegularStyle(true);
2747         state.setApplyPropertyToVisitedLinkStyle(false);
2748         resolver.applyProperty(id, cssValue[SelectorChecker::MatchDefault], SelectorChecker::MatchDefault, matchResult);
2749     }
2750
2751     if (state.style()->insideLink() == NotInsideLink)
2752         return;
2753
2754     if (cssValue[SelectorChecker::MatchLink]) {
2755         state.setApplyPropertyToRegularStyle(true);
2756         state.setApplyPropertyToVisitedLinkStyle(false);
2757         resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink], SelectorChecker::MatchLink, matchResult);
2758     }
2759
2760     if (cssValue[SelectorChecker::MatchVisited]) {
2761         state.setApplyPropertyToRegularStyle(false);
2762         state.setApplyPropertyToVisitedLinkStyle(true);
2763         resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited], SelectorChecker::MatchVisited, matchResult);
2764     }
2765
2766     state.setApplyPropertyToRegularStyle(true);
2767     state.setApplyPropertyToVisitedLinkStyle(false);
2768 }
2769
2770 void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty, const MatchResult* matchResult)
2771 {
2772     for (int id = firstProperty; id <= lastProperty; ++id) {
2773         CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
2774         if (!cascade.hasProperty(propertyID))
2775             continue;
2776         if (propertyID == CSSPropertyCustom) {
2777             HashMap<AtomicString, CascadedProperties::Property>::iterator end = cascade.customProperties().end();
2778             for (HashMap<AtomicString, CascadedProperties::Property>::iterator it = cascade.customProperties().begin(); it != end; ++it)
2779                 it->value.apply(*this, matchResult);
2780             continue;
2781         }
2782         auto& property = cascade.property(propertyID);
2783         ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
2784         property.apply(*this, matchResult);
2785     }
2786     
2787     if (firstProperty == CSSPropertyCustom)
2788         m_state.style()->checkVariablesInCustomProperties();
2789 }
2790
2791 } // namespace WebCore