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