d65acaf49d86b10cbb619ea05fa29c4588cd22a0
[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 static bool isDisplayFlexibleBox(EDisplay display)
1147 {
1148     return display == FLEX || display == INLINE_FLEX;
1149 }
1150
1151 static inline bool isDisplayGridBox(EDisplay display)
1152 {
1153 #if ENABLE(CSS_GRID_LAYOUT)
1154     return display == GRID || display == INLINE_GRID;
1155 #else
1156     UNUSED_PARAM(display);
1157     return false;
1158 #endif
1159 }
1160
1161 static bool isDisplayFlexibleOrGridBox(EDisplay display)
1162 {
1163     return isDisplayFlexibleBox(display) || isDisplayGridBox(display);
1164 }
1165
1166 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1167 static bool isScrollableOverflow(EOverflow overflow)
1168 {
1169     return overflow == OSCROLL || overflow == OAUTO || overflow == OOVERLAY;
1170 }
1171 #endif
1172
1173 void StyleResolver::adjustStyleForInterCharacterRuby()
1174 {
1175     RenderStyle* style = m_state.style();
1176     if (style->rubyPosition() != RubyPositionInterCharacter || !m_state.element() || !m_state.element()->hasTagName(rtTag))
1177         return;
1178     style->setTextAlign(CENTER);
1179     if (style->isHorizontalWritingMode())
1180         style->setWritingMode(LeftToRightWritingMode);
1181 }
1182
1183 void StyleResolver::adjustStyleForMaskImages()
1184 {
1185     // If we already have the same mask image objects loaded on the old style,
1186     // use the old ones instead of loading new ones.
1187     RenderStyle* newStyle = m_state.style();
1188     RenderStyle* oldStyle = (m_state.element() ? m_state.element()->renderStyle() : nullptr);
1189
1190     if (newStyle && oldStyle) {
1191         Vector<RefPtr<MaskImageOperation>> removedExternalResources;
1192         
1193         // Get all mask objects from the old style in a vector
1194         // so we can remove them as we match them, making the following steps faster.
1195         Vector<RefPtr<MaskImageOperation>> oldStyleMaskImages;
1196         const FillLayer* oldMaskLayer = oldStyle->maskLayers();
1197         while (oldMaskLayer) {
1198             RefPtr<MaskImageOperation> oldMaskImage = oldMaskLayer->maskImage();
1199             if (oldMaskImage.get())
1200                 oldStyleMaskImages.append(oldMaskImage);
1201
1202             oldMaskLayer = oldMaskLayer->next();
1203         }
1204         
1205         // Try to match the new mask objects through the list from the old style.
1206         // This should work perfectly and optimal when the list of masks remained
1207         // the same and also work correctly (but slower) when they were reordered.
1208         FillLayer* newMaskLayer = &newStyle->ensureMaskLayers();
1209         int countOldStyleMaskImages = oldStyleMaskImages.size();
1210         while (newMaskLayer && countOldStyleMaskImages) {
1211             RefPtr<MaskImageOperation> newMaskImage = newMaskLayer->maskImage();
1212             if (newMaskImage.get()) {
1213                 for (int i = 0; i < countOldStyleMaskImages; i++) {
1214                     RefPtr<MaskImageOperation> oldMaskImage = oldStyleMaskImages[i];
1215                     if (*oldMaskImage == *newMaskImage) {
1216                         newMaskLayer->setMaskImage(oldMaskImage);
1217                         if (newMaskImage->isExternalDocument())
1218                             removedExternalResources.append(newMaskImage);
1219
1220                         oldStyleMaskImages.remove(i);
1221                         countOldStyleMaskImages--;
1222                         break;
1223                     }
1224                 }
1225             }
1226
1227             newMaskLayer = newMaskLayer->next();
1228         }
1229
1230         Vector<RefPtr<MaskImageOperation>>& pendingResources = m_state.maskImagesWithPendingSVGDocuments();
1231         pendingResources.removeAllMatching([&removedExternalResources] (const RefPtr<MaskImageOperation>& resource) {
1232             return removedExternalResources.contains(resource);
1233         });
1234     }
1235 }
1236
1237 void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& parentStyle, Element *e)
1238 {
1239     // Cache our original display.
1240     style.setOriginalDisplay(style.display());
1241
1242     if (style.display() != NONE) {
1243         // If we have a <td> that specifies a float property, in quirks mode we just drop the float
1244         // property.
1245         // Sites also commonly use display:inline/block on <td>s and <table>s. In quirks mode we force
1246         // these tags to retain their display types.
1247         if (document().inQuirksMode() && e) {
1248             if (e->hasTagName(tdTag)) {
1249                 style.setDisplay(TABLE_CELL);
1250                 style.setFloating(NoFloat);
1251             } else if (is<HTMLTableElement>(*e))
1252                 style.setDisplay(style.isDisplayInlineType() ? INLINE_TABLE : TABLE);
1253         }
1254
1255         if (e && (e->hasTagName(tdTag) || e->hasTagName(thTag))) {
1256             if (style.whiteSpace() == KHTML_NOWRAP) {
1257                 // Figure out if we are really nowrapping or if we should just
1258                 // use normal instead. If the width of the cell is fixed, then
1259                 // we don't actually use NOWRAP.
1260                 if (style.width().isFixed())
1261                     style.setWhiteSpace(NORMAL);
1262                 else
1263                     style.setWhiteSpace(NOWRAP);
1264             }
1265         }
1266
1267         // Tables never support the -webkit-* values for text-align and will reset back to the default.
1268         if (is<HTMLTableElement>(e) && (style.textAlign() == WEBKIT_LEFT || style.textAlign() == WEBKIT_CENTER || style.textAlign() == WEBKIT_RIGHT))
1269             style.setTextAlign(TASTART);
1270
1271         // Frames and framesets never honor position:relative or position:absolute. This is necessary to
1272         // fix a crash where a site tries to position these objects. They also never honor display.
1273         if (e && (e->hasTagName(frameTag) || e->hasTagName(framesetTag))) {
1274             style.setPosition(StaticPosition);
1275             style.setDisplay(BLOCK);
1276         }
1277
1278         // Ruby text does not support float or position. This might change with evolution of the specification.
1279         if (e && e->hasTagName(rtTag)) {
1280             style.setPosition(StaticPosition);
1281             style.setFloating(NoFloat);
1282         }
1283
1284         // FIXME: We shouldn't be overriding start/-webkit-auto like this. Do it in html.css instead.
1285         // Table headers with a text-align of -webkit-auto will change the text-align to center.
1286         if (e && e->hasTagName(thTag) && style.textAlign() == TASTART)
1287             style.setTextAlign(CENTER);
1288
1289         if (e && e->hasTagName(legendTag))
1290             style.setDisplay(BLOCK);
1291
1292         // Absolute/fixed positioned elements, floating elements and the document element need block-like outside display.
1293         if (style.hasOutOfFlowPosition() || style.isFloating() || (e && e->document().documentElement() == e))
1294             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1295
1296         // FIXME: Don't support this mutation for pseudo styles like first-letter or first-line, since it's not completely
1297         // clear how that should work.
1298         if (style.display() == INLINE && style.styleType() == NOPSEUDO && style.writingMode() != parentStyle.writingMode())
1299             style.setDisplay(INLINE_BLOCK);
1300
1301         // After performing the display mutation, check table rows. We do not honor position:relative or position:sticky on
1302         // table rows or cells. This has been established for position:relative in CSS2.1 (and caused a crash in containingBlock()
1303         // on some sites).
1304         if ((style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW_GROUP
1305             || style.display() == TABLE_FOOTER_GROUP || style.display() == TABLE_ROW)
1306             && style.position() == RelativePosition)
1307             style.setPosition(StaticPosition);
1308
1309         // writing-mode does not apply to table row groups, table column groups, table rows, and table columns.
1310         // FIXME: Table cells should be allowed to be perpendicular or flipped with respect to the table, though.
1311         if (style.display() == TABLE_COLUMN || style.display() == TABLE_COLUMN_GROUP || style.display() == TABLE_FOOTER_GROUP
1312             || style.display() == TABLE_HEADER_GROUP || style.display() == TABLE_ROW || style.display() == TABLE_ROW_GROUP
1313             || style.display() == TABLE_CELL)
1314             style.setWritingMode(parentStyle.writingMode());
1315
1316         // FIXME: Since we don't support block-flow on flexible boxes yet, disallow setting
1317         // of block-flow to anything other than TopToBottomWritingMode.
1318         // https://bugs.webkit.org/show_bug.cgi?id=46418 - Flexible box support.
1319         if (style.writingMode() != TopToBottomWritingMode && (style.display() == BOX || style.display() == INLINE_BOX))
1320             style.setWritingMode(TopToBottomWritingMode);
1321
1322         if (isDisplayFlexibleOrGridBox(parentStyle.display())) {
1323             style.setFloating(NoFloat);
1324             style.setDisplay(equivalentBlockDisplay(style.display(), style.isFloating(), !document().inQuirksMode()));
1325         }
1326     }
1327
1328     // Make sure our z-index value is only applied if the object is positioned.
1329     if (style.position() == StaticPosition && !isDisplayFlexibleOrGridBox(parentStyle.display()))
1330         style.setHasAutoZIndex();
1331
1332     // Auto z-index becomes 0 for the root element and transparent objects. This prevents
1333     // cases where objects that should be blended as a single unit end up with a non-transparent
1334     // object wedged in between them. Auto z-index also becomes 0 for objects that specify transforms/masks/reflections.
1335     if (style.hasAutoZIndex() && ((e && e->document().documentElement() == e)
1336         || style.opacity() < 1.0f
1337         || style.hasTransformRelatedProperty()
1338         || style.hasMask()
1339         || style.clipPath()
1340         || style.boxReflect()
1341         || style.hasFilter()
1342 #if ENABLE(FILTERS_LEVEL_2)
1343         || style.hasBackdropFilter()
1344 #endif
1345         || style.hasBlendMode()
1346         || style.hasIsolation()
1347         || style.position() == StickyPosition
1348         || (style.position() == FixedPosition && documentSettings() && documentSettings()->fixedPositionCreatesStackingContext())
1349         || style.hasFlowFrom()
1350         ))
1351         style.setZIndex(0);
1352
1353     // Textarea considers overflow visible as auto.
1354     if (is<HTMLTextAreaElement>(e)) {
1355         style.setOverflowX(style.overflowX() == OVISIBLE ? OAUTO : style.overflowX());
1356         style.setOverflowY(style.overflowY() == OVISIBLE ? OAUTO : style.overflowY());
1357     }
1358
1359     // Disallow -webkit-user-modify on :pseudo and ::pseudo elements.
1360     if (e && !e->shadowPseudoId().isNull())
1361         style.setUserModify(READ_ONLY);
1362
1363     if (doesNotInheritTextDecoration(style, e))
1364         style.setTextDecorationsInEffect(style.textDecoration());
1365     else
1366         style.addToTextDecorationsInEffect(style.textDecoration());
1367
1368     // If either overflow value is not visible, change to auto.
1369     if (style.overflowX() == OMARQUEE && style.overflowY() != OMARQUEE)
1370         style.setOverflowY(OMARQUEE);
1371     else if (style.overflowY() == OMARQUEE && style.overflowX() != OMARQUEE)
1372         style.setOverflowX(OMARQUEE);
1373     else if (style.overflowX() == OVISIBLE && style.overflowY() != OVISIBLE) {
1374         // FIXME: Once we implement pagination controls, overflow-x should default to hidden
1375         // if overflow-y is set to -webkit-paged-x or -webkit-page-y. For now, we'll let it
1376         // default to auto so we can at least scroll through the pages.
1377         style.setOverflowX(OAUTO);
1378     } else if (style.overflowY() == OVISIBLE && style.overflowX() != OVISIBLE)
1379         style.setOverflowY(OAUTO);
1380
1381     // Call setStylesForPaginationMode() if a pagination mode is set for any non-root elements. If these
1382     // styles are specified on a root element, then they will be incorporated in
1383     // Style::createForDocument().
1384     if ((style.overflowY() == OPAGEDX || style.overflowY() == OPAGEDY) && !(e && (e->hasTagName(htmlTag) || e->hasTagName(bodyTag))))
1385         style.setColumnStylesFromPaginationMode(WebCore::paginationModeForRenderStyle(style));
1386
1387     // Table rows, sections and the table itself will support overflow:hidden and will ignore scroll/auto.
1388     // FIXME: Eventually table sections will support auto and scroll.
1389     if (style.display() == TABLE || style.display() == INLINE_TABLE
1390         || style.display() == TABLE_ROW_GROUP || style.display() == TABLE_ROW) {
1391         if (style.overflowX() != OVISIBLE && style.overflowX() != OHIDDEN)
1392             style.setOverflowX(OVISIBLE);
1393         if (style.overflowY() != OVISIBLE && style.overflowY() != OHIDDEN)
1394             style.setOverflowY(OVISIBLE);
1395     }
1396
1397     // Menulists should have visible overflow
1398     if (style.appearance() == MenulistPart) {
1399         style.setOverflowX(OVISIBLE);
1400         style.setOverflowY(OVISIBLE);
1401     }
1402
1403 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
1404     // Touch overflow scrolling creates a stacking context.
1405     if (style.hasAutoZIndex() && style.useTouchOverflowScrolling() && (isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY())))
1406         style.setZIndex(0);
1407 #endif
1408
1409     // Cull out any useless layers and also repeat patterns into additional layers.
1410     style.adjustBackgroundLayers();
1411     style.adjustMaskLayers();
1412
1413     // Do the same for animations and transitions.
1414     style.adjustAnimations();
1415     style.adjustTransitions();
1416
1417     // Important: Intrinsic margins get added to controls before the theme has adjusted the style, since the theme will
1418     // alter fonts and heights/widths.
1419     if (is<HTMLFormControlElement>(e) && style.fontSize() >= 11) {
1420         // Don't apply intrinsic margins to image buttons. The designer knows how big the images are,
1421         // so we have to treat all image buttons as though they were explicitly sized.
1422         if (!is<HTMLInputElement>(*e) || !downcast<HTMLInputElement>(*e).isImageButton())
1423             addIntrinsicMargins(style);
1424     }
1425
1426     // Let the theme also have a crack at adjusting the style.
1427     if (style.hasAppearance())
1428         RenderTheme::defaultTheme()->adjustStyle(*this, style, e, m_state.hasUAAppearance(), m_state.borderData(), m_state.backgroundData(), m_state.backgroundColor());
1429
1430     // If we have first-letter pseudo style, do not share this style.
1431     if (style.hasPseudoStyle(FIRST_LETTER))
1432         style.setUnique();
1433
1434     // FIXME: when dropping the -webkit prefix on transform-style, we should also have opacity < 1 cause flattening.
1435     if (style.preserves3D() && (style.overflowX() != OVISIBLE
1436         || style.overflowY() != OVISIBLE
1437         || style.hasFilter()
1438 #if ENABLE(FILTERS_LEVEL_2)
1439         || style.hasBackdropFilter()
1440 #endif
1441         || style.hasBlendMode()))
1442         style.setTransformStyle3D(TransformStyle3DFlat);
1443
1444     if (e && e->isSVGElement()) {
1445         // Only the root <svg> element in an SVG document fragment tree honors css position
1446         if (!(e->hasTagName(SVGNames::svgTag) && e->parentNode() && !e->parentNode()->isSVGElement()))
1447             style.setPosition(RenderStyle::initialPosition());
1448
1449         // RenderSVGRoot handles zooming for the whole SVG subtree, so foreignObject content should
1450         // not be scaled again.
1451         if (e->hasTagName(SVGNames::foreignObjectTag))
1452             style.setEffectiveZoom(RenderStyle::initialZoom());
1453
1454         // SVG text layout code expects us to be a block-level style element.
1455         if ((e->hasTagName(SVGNames::foreignObjectTag) || e->hasTagName(SVGNames::textTag)) && style.isDisplayInlineType())
1456             style.setDisplay(BLOCK);
1457     }
1458 }
1459
1460 bool StyleResolver::checkRegionStyle(Element* regionElement)
1461 {
1462     unsigned rulesSize = m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().size();
1463     for (unsigned i = 0; i < rulesSize; ++i) {
1464         ASSERT(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1465         if (checkRegionSelector(m_ruleSets.authorStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1466             return true;
1467     }
1468
1469     if (m_ruleSets.userStyle()) {
1470         rulesSize = m_ruleSets.userStyle()->regionSelectorsAndRuleSets().size();
1471         for (unsigned i = 0; i < rulesSize; ++i) {
1472             ASSERT(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).ruleSet.get());
1473             if (checkRegionSelector(m_ruleSets.userStyle()->regionSelectorsAndRuleSets().at(i).selector, regionElement))
1474                 return true;
1475         }
1476     }
1477
1478     return false;
1479 }
1480
1481 static void checkForOrientationChange(RenderStyle* style)
1482 {
1483     FontOrientation fontOrientation;
1484     NonCJKGlyphOrientation glyphOrientation;
1485     style->getFontAndGlyphOrientation(fontOrientation, glyphOrientation);
1486
1487     const FontDescription& fontDescription = style->fontDescription();
1488     if (fontDescription.orientation() == fontOrientation && fontDescription.nonCJKGlyphOrientation() == glyphOrientation)
1489         return;
1490
1491     FontDescription newFontDescription(fontDescription);
1492     newFontDescription.setNonCJKGlyphOrientation(glyphOrientation);
1493     newFontDescription.setOrientation(fontOrientation);
1494     style->setFontDescription(newFontDescription);
1495 }
1496
1497 void StyleResolver::updateFont()
1498 {
1499     if (!m_state.fontDirty())
1500         return;
1501
1502     RenderStyle* style = m_state.style();
1503 #if ENABLE(IOS_TEXT_AUTOSIZING)
1504     checkForTextSizeAdjust(style);
1505 #endif
1506     checkForGenericFamilyChange(style, m_state.parentStyle());
1507     checkForZoomChange(style, m_state.parentStyle());
1508     checkForOrientationChange(style);
1509     style->fontCascade().update(&document().fontSelector());
1510     if (m_state.fontSizeHasViewportUnits())
1511         style->setHasViewportUnits(true);
1512     m_state.setFontDirty(false);
1513 }
1514
1515 Vector<RefPtr<StyleRule>> StyleResolver::styleRulesForElement(Element* e, unsigned rulesToInclude)
1516 {
1517     return pseudoStyleRulesForElement(e, NOPSEUDO, rulesToInclude);
1518 }
1519
1520 Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(Element* element, PseudoId pseudoId, unsigned rulesToInclude)
1521 {
1522     if (!element || !element->document().haveStylesheetsLoaded())
1523         return Vector<RefPtr<StyleRule>>();
1524
1525     initElement(element);
1526     m_state.initForStyleResolve(document(), element, 0);
1527
1528     ElementRuleCollector collector(*element, m_state.style(), m_ruleSets, m_selectorFilter);
1529     collector.setMode(SelectorChecker::Mode::CollectingRules);
1530     collector.setPseudoStyleRequest(PseudoStyleRequest(pseudoId));
1531     collector.setMedium(m_medium.get());
1532
1533     if (rulesToInclude & UAAndUserCSSRules) {
1534         // First we match rules from the user agent sheet.
1535         collector.matchUARules();
1536         
1537         // Now we check user sheet rules.
1538         if (m_matchAuthorAndUserStyles)
1539             collector.matchUserRules(rulesToInclude & EmptyCSSRules);
1540     }
1541
1542     if (m_matchAuthorAndUserStyles && (rulesToInclude & AuthorCSSRules)) {
1543         collector.setSameOriginOnly(!(rulesToInclude & CrossOriginCSSRules));
1544
1545         // Check the rules in author sheets.
1546         collector.matchAuthorRules(rulesToInclude & EmptyCSSRules);
1547     }
1548
1549     return collector.matchedRuleList();
1550 }
1551
1552 // -------------------------------------------------------------------------------------
1553
1554 static Length convertToFloatLength(const CSSPrimitiveValue* primitiveValue, const CSSToLengthConversionData& conversionData)
1555 {
1556     return primitiveValue ? primitiveValue->convertToLength<FixedFloatConversion | PercentConversion | CalculatedConversion>(conversionData) : Length(Undefined);
1557 }
1558
1559 static bool shouldApplyPropertyInParseOrder(CSSPropertyID propertyID)
1560 {
1561     switch (propertyID) {
1562     case CSSPropertyWebkitBackgroundClip:
1563     case CSSPropertyBackgroundClip:
1564     case CSSPropertyWebkitBackgroundOrigin:
1565     case CSSPropertyBackgroundOrigin:
1566     case CSSPropertyWebkitBackgroundSize:
1567     case CSSPropertyBackgroundSize:
1568     case CSSPropertyWebkitBorderImage:
1569     case CSSPropertyBorderImage:
1570     case CSSPropertyBorderImageSlice:
1571     case CSSPropertyBorderImageSource:
1572     case CSSPropertyBorderImageOutset:
1573     case CSSPropertyBorderImageRepeat:
1574     case CSSPropertyBorderImageWidth:
1575     case CSSPropertyWebkitBoxShadow:
1576     case CSSPropertyBoxShadow:
1577     case CSSPropertyWebkitTextDecoration:
1578     case CSSPropertyWebkitTextDecorationLine:
1579     case CSSPropertyWebkitTextDecorationStyle:
1580     case CSSPropertyWebkitTextDecorationColor:
1581     case CSSPropertyWebkitTextDecorationSkip:
1582     case CSSPropertyWebkitTextUnderlinePosition:
1583     case CSSPropertyTextDecoration:
1584         return true;
1585     default:
1586         return false;
1587     }
1588 }
1589
1590 static bool elementTypeHasAppearanceFromUAStyle(const Element& element)
1591 {
1592     // NOTE: This is just a hard-coded list of elements that have some -webkit-appearance value in html.css
1593     const auto& localName = element.localName();
1594     return localName == HTMLNames::inputTag
1595         || localName == HTMLNames::textareaTag
1596         || localName == HTMLNames::buttonTag
1597         || localName == HTMLNames::progressTag
1598         || localName == HTMLNames::selectTag
1599         || localName == HTMLNames::meterTag
1600         || localName == HTMLNames::isindexTag;
1601 }
1602
1603 unsigned StyleResolver::computeMatchedPropertiesHash(const MatchedProperties* properties, unsigned size)
1604 {
1605     return StringHasher::hashMemory(properties, sizeof(MatchedProperties) * size);
1606 }
1607
1608 bool operator==(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1609 {
1610     return a.firstUARule == b.firstUARule
1611         && a.lastUARule == b.lastUARule
1612         && a.firstAuthorRule == b.firstAuthorRule
1613         && a.lastAuthorRule == b.lastAuthorRule
1614         && a.firstUserRule == b.firstUserRule
1615         && a.lastUserRule == b.lastUserRule;
1616 }
1617
1618 bool operator!=(const StyleResolver::MatchRanges& a, const StyleResolver::MatchRanges& b)
1619 {
1620     return !(a == b);
1621 }
1622
1623 bool operator==(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1624 {
1625     return a.properties == b.properties && a.linkMatchType == b.linkMatchType;
1626 }
1627
1628 bool operator!=(const StyleResolver::MatchedProperties& a, const StyleResolver::MatchedProperties& b)
1629 {
1630     return !(a == b);
1631 }
1632
1633 const StyleResolver::MatchedPropertiesCacheItem* StyleResolver::findFromMatchedPropertiesCache(unsigned hash, const MatchResult& matchResult)
1634 {
1635     ASSERT(hash);
1636
1637     MatchedPropertiesCache::iterator it = m_matchedPropertiesCache.find(hash);
1638     if (it == m_matchedPropertiesCache.end())
1639         return 0;
1640     MatchedPropertiesCacheItem& cacheItem = it->value;
1641
1642     size_t size = matchResult.matchedProperties().size();
1643     if (size != cacheItem.matchedProperties.size())
1644         return 0;
1645     for (size_t i = 0; i < size; ++i) {
1646         if (matchResult.matchedProperties()[i] != cacheItem.matchedProperties[i])
1647             return 0;
1648     }
1649     if (cacheItem.ranges != matchResult.ranges)
1650         return 0;
1651     return &cacheItem;
1652 }
1653
1654 void StyleResolver::addToMatchedPropertiesCache(const RenderStyle* style, const RenderStyle* parentStyle, unsigned hash, const MatchResult& matchResult)
1655 {
1656     static const unsigned matchedDeclarationCacheAdditionsBetweenSweeps = 100;
1657     if (++m_matchedPropertiesCacheAdditionsSinceLastSweep >= matchedDeclarationCacheAdditionsBetweenSweeps
1658         && !m_matchedPropertiesCacheSweepTimer.isActive()) {
1659         static const unsigned matchedDeclarationCacheSweepTimeInSeconds = 60;
1660         m_matchedPropertiesCacheSweepTimer.startOneShot(matchedDeclarationCacheSweepTimeInSeconds);
1661     }
1662
1663     ASSERT(hash);
1664     MatchedPropertiesCacheItem cacheItem;
1665     cacheItem.matchedProperties.appendVector(matchResult.matchedProperties());
1666     cacheItem.ranges = matchResult.ranges;
1667     // Note that we don't cache the original RenderStyle instance. It may be further modified.
1668     // The RenderStyle in the cache is really just a holder for the substructures and never used as-is.
1669     cacheItem.renderStyle = RenderStyle::clone(style);
1670     cacheItem.parentRenderStyle = RenderStyle::clone(parentStyle);
1671     m_matchedPropertiesCache.add(hash, WTF::move(cacheItem));
1672 }
1673
1674 void StyleResolver::invalidateMatchedPropertiesCache()
1675 {
1676     m_matchedPropertiesCache.clear();
1677 }
1678
1679 void StyleResolver::clearCachedPropertiesAffectedByViewportUnits()
1680 {
1681     Vector<unsigned, 16> toRemove;
1682     for (auto& cacheKeyValue : m_matchedPropertiesCache) {
1683         if (cacheKeyValue.value.renderStyle->hasViewportUnits())
1684             toRemove.append(cacheKeyValue.key);
1685     }
1686     for (auto key : toRemove)
1687         m_matchedPropertiesCache.remove(key);
1688 }
1689
1690 static bool isCacheableInMatchedPropertiesCache(const Element* element, const RenderStyle* style, const RenderStyle* parentStyle)
1691 {
1692     // FIXME: CSSPropertyWebkitWritingMode modifies state when applying to document element. We can't skip the applying by caching.
1693     if (element == element->document().documentElement() && element->document().writingModeSetOnDocumentElement())
1694         return false;
1695     if (style->unique() || (style->styleType() != NOPSEUDO && parentStyle->unique()))
1696         return false;
1697     if (style->hasAppearance())
1698         return false;
1699     if (style->zoom() != RenderStyle::initialZoom())
1700         return false;
1701     if (style->writingMode() != RenderStyle::initialWritingMode() || style->direction() != RenderStyle::initialDirection())
1702         return false;
1703     // The cache assumes static knowledge about which properties are inherited.
1704     if (parentStyle->hasExplicitlyInheritedProperties())
1705         return false;
1706     return true;
1707 }
1708
1709 void extractDirectionAndWritingMode(const RenderStyle& style, const StyleResolver::MatchResult& matchResult, TextDirection& direction, WritingMode& writingMode)
1710 {
1711     direction = style.direction();
1712     writingMode = style.writingMode();
1713
1714     bool hadImportantWebkitWritingMode = false;
1715     bool hadImportantDirection = false;
1716
1717     for (const auto& matchedProperties : matchResult.matchedProperties()) {
1718         for (unsigned i = 0, count = matchedProperties.properties->propertyCount(); i < count; ++i) {
1719             auto property = matchedProperties.properties->propertyAt(i);
1720             if (!property.value()->isPrimitiveValue())
1721                 continue;
1722             switch (property.id()) {
1723             case CSSPropertyWebkitWritingMode:
1724                 if (!hadImportantWebkitWritingMode || property.isImportant()) {
1725                     writingMode = downcast<CSSPrimitiveValue>(*property.value());
1726                     hadImportantWebkitWritingMode = property.isImportant();
1727                 }
1728                 break;
1729             case CSSPropertyDirection:
1730                 if (!hadImportantDirection || property.isImportant()) {
1731                     direction = downcast<CSSPrimitiveValue>(*property.value());
1732                     hadImportantDirection = property.isImportant();
1733                 }
1734                 break;
1735             default:
1736                 break;
1737             }
1738         }
1739     }
1740 }
1741
1742 void StyleResolver::applyMatchedProperties(const MatchResult& matchResult, const Element* element, ShouldUseMatchedPropertiesCache shouldUseMatchedPropertiesCache)
1743 {
1744     ASSERT(element);
1745     State& state = m_state;
1746     unsigned cacheHash = shouldUseMatchedPropertiesCache && matchResult.isCacheable ? computeMatchedPropertiesHash(matchResult.matchedProperties().data(), matchResult.matchedProperties().size()) : 0;
1747     bool applyInheritedOnly = false;
1748     const MatchedPropertiesCacheItem* cacheItem = 0;
1749     if (cacheHash && (cacheItem = findFromMatchedPropertiesCache(cacheHash, matchResult))
1750         && isCacheableInMatchedPropertiesCache(element, state.style(), state.parentStyle())) {
1751         // We can build up the style by copying non-inherited properties from an earlier style object built using the same exact
1752         // style declarations. We then only need to apply the inherited properties, if any, as their values can depend on the 
1753         // element context. This is fast and saves memory by reusing the style data structures.
1754         state.style()->copyNonInheritedFrom(cacheItem->renderStyle.get());
1755         if (state.parentStyle()->inheritedDataShared(cacheItem->parentRenderStyle.get()) && !isAtShadowBoundary(element)) {
1756             EInsideLink linkStatus = state.style()->insideLink();
1757             // If the cache item parent style has identical inherited properties to the current parent style then the
1758             // resulting style will be identical too. We copy the inherited properties over from the cache and are done.
1759             state.style()->inheritFrom(cacheItem->renderStyle.get());
1760
1761             // Unfortunately the link status is treated like an inherited property. We need to explicitly restore it.
1762             state.style()->setInsideLink(linkStatus);
1763             return;
1764         }
1765         applyInheritedOnly = true; 
1766     }
1767
1768     // Directional properties (*-before/after) are aliases that depend on the TextDirection and WritingMode.
1769     // These must be resolved before we can begin the property cascade.
1770     TextDirection direction;
1771     WritingMode writingMode;
1772     extractDirectionAndWritingMode(*state.style(), matchResult, direction, writingMode);
1773
1774     if (elementTypeHasAppearanceFromUAStyle(*state.element())) {
1775         // FIXME: This is such a hack.
1776         // Find out if there's a -webkit-appearance property in effect from the UA sheet.
1777         // If so, we cache the border and background styles so that RenderTheme::adjustStyle()
1778         // can look at them later to figure out if this is a styled form control or not.
1779         CascadedProperties cascade(direction, writingMode);
1780         cascade.addMatches(matchResult, false, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1781         cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1782
1783         applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
1784         adjustStyleForInterCharacterRuby();
1785
1786         // Start by applying properties that other properties may depend on.
1787         applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
1788     
1789         updateFont();
1790         applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
1791
1792         state.cacheBorderAndBackground();
1793     }
1794
1795     CascadedProperties cascade(direction, writingMode);
1796     cascade.addMatches(matchResult, false, 0, matchResult.matchedProperties().size() - 1, applyInheritedOnly);
1797     cascade.addMatches(matchResult, true, matchResult.ranges.firstAuthorRule, matchResult.ranges.lastAuthorRule, applyInheritedOnly);
1798     cascade.addMatches(matchResult, true, matchResult.ranges.firstUserRule, matchResult.ranges.lastUserRule, applyInheritedOnly);
1799     cascade.addMatches(matchResult, true, matchResult.ranges.firstUARule, matchResult.ranges.lastUARule, applyInheritedOnly);
1800
1801     applyCascadedProperties(cascade, CSSPropertyWebkitRubyPosition, CSSPropertyWebkitRubyPosition);
1802     
1803     // Adjust the font size to be smaller if ruby-position is inter-character.
1804     adjustStyleForInterCharacterRuby();
1805
1806     // Start by applying properties that other properties may depend on.
1807     applyCascadedProperties(cascade, firstCSSProperty, lastHighPriorityProperty);
1808
1809     // If the effective zoom value changes, we can't use the matched properties cache. Start over.
1810     if (cacheItem && cacheItem->renderStyle->effectiveZoom() != state.style()->effectiveZoom())
1811         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
1812
1813     // If our font got dirtied, go ahead and update it now.
1814     updateFont();
1815
1816     // If the font changed, we can't use the matched properties cache. Start over.
1817     if (cacheItem && cacheItem->renderStyle->fontDescription() != state.style()->fontDescription())
1818         return applyMatchedProperties(matchResult, element, DoNotUseMatchedPropertiesCache);
1819
1820     // Apply properties that no other properties depend on.
1821     applyCascadedProperties(cascade, firstLowPriorityProperty, lastCSSProperty);
1822
1823     // Finally, some properties must be applied in the order they were parsed.
1824     // There are some CSS properties that affect the same RenderStyle values,
1825     // so to preserve behavior, we queue them up during cascade and flush here.
1826     cascade.applyDeferredProperties(*this);
1827     
1828     adjustStyleForMaskImages();
1829
1830     // Start loading resources referenced by this style.
1831     loadPendingResources();
1832     
1833     ASSERT(!state.fontDirty());
1834     
1835     if (cacheItem || !cacheHash)
1836         return;
1837     if (!isCacheableInMatchedPropertiesCache(state.element(), state.style(), state.parentStyle()))
1838         return;
1839     addToMatchedPropertiesCache(state.style(), state.parentStyle(), cacheHash, matchResult);
1840 }
1841
1842 void StyleResolver::applyPropertyToStyle(CSSPropertyID id, CSSValue* value, RenderStyle* style)
1843 {
1844     initElement(0);
1845     m_state.initForStyleResolve(document(), nullptr, style);
1846     m_state.setStyle(*style);
1847     applyPropertyToCurrentStyle(id, value);
1848 }
1849
1850 void StyleResolver::applyPropertyToCurrentStyle(CSSPropertyID id, CSSValue* value)
1851 {
1852     if (value)
1853         applyProperty(id, value);
1854 }
1855
1856 inline bool isValidVisitedLinkProperty(CSSPropertyID id)
1857 {
1858     switch (id) {
1859     case CSSPropertyBackgroundColor:
1860     case CSSPropertyBorderLeftColor:
1861     case CSSPropertyBorderRightColor:
1862     case CSSPropertyBorderTopColor:
1863     case CSSPropertyBorderBottomColor:
1864     case CSSPropertyColor:
1865     case CSSPropertyOutlineColor:
1866     case CSSPropertyColumnRuleColor:
1867     case CSSPropertyWebkitTextDecorationColor:
1868     case CSSPropertyWebkitTextEmphasisColor:
1869     case CSSPropertyWebkitTextFillColor:
1870     case CSSPropertyWebkitTextStrokeColor:
1871     case CSSPropertyFill:
1872     case CSSPropertyStroke:
1873         return true;
1874     default:
1875         break;
1876     }
1877
1878     return false;
1879 }
1880
1881 // http://dev.w3.org/csswg/css3-regions/#the-at-region-style-rule
1882 // FIXME: add incremental support for other region styling properties.
1883 inline bool StyleResolver::isValidRegionStyleProperty(CSSPropertyID id)
1884 {
1885     switch (id) {
1886     case CSSPropertyBackgroundColor:
1887     case CSSPropertyColor:
1888         return true;
1889     default:
1890         break;
1891     }
1892
1893     return false;
1894 }
1895
1896 #if ENABLE(VIDEO_TRACK)
1897 inline bool StyleResolver::isValidCueStyleProperty(CSSPropertyID id)
1898 {
1899     switch (id) {
1900     case CSSPropertyBackground:
1901     case CSSPropertyBackgroundAttachment:
1902     case CSSPropertyBackgroundClip:
1903     case CSSPropertyBackgroundColor:
1904     case CSSPropertyBackgroundImage:
1905     case CSSPropertyBackgroundOrigin:
1906     case CSSPropertyBackgroundPosition:
1907     case CSSPropertyBackgroundPositionX:
1908     case CSSPropertyBackgroundPositionY:
1909     case CSSPropertyBackgroundRepeat:
1910     case CSSPropertyBackgroundRepeatX:
1911     case CSSPropertyBackgroundRepeatY:
1912     case CSSPropertyBackgroundSize:
1913     case CSSPropertyColor:
1914     case CSSPropertyFont:
1915     case CSSPropertyFontFamily:
1916     case CSSPropertyFontSize:
1917     case CSSPropertyFontStyle:
1918     case CSSPropertyFontVariant:
1919     case CSSPropertyFontWeight:
1920     case CSSPropertyLineHeight:
1921     case CSSPropertyOpacity:
1922     case CSSPropertyOutline:
1923     case CSSPropertyOutlineColor:
1924     case CSSPropertyOutlineOffset:
1925     case CSSPropertyOutlineStyle:
1926     case CSSPropertyOutlineWidth:
1927     case CSSPropertyVisibility:
1928     case CSSPropertyWhiteSpace:
1929     case CSSPropertyTextDecoration:
1930     case CSSPropertyTextShadow:
1931     case CSSPropertyBorderStyle:
1932         return true;
1933     default:
1934         break;
1935     }
1936     return false;
1937 }
1938 #endif
1939 // SVG handles zooming in a different way compared to CSS. The whole document is scaled instead
1940 // of each individual length value in the render style / tree. CSSPrimitiveValue::computeLength*()
1941 // multiplies each resolved length with the zoom multiplier - so for SVG we need to disable that.
1942 // Though all CSS values that can be applied to outermost <svg> elements (width/height/border/padding...)
1943 // need to respect the scaling. RenderBox (the parent class of RenderSVGRoot) grabs values like
1944 // width/height/border/padding/... from the RenderStyle -> for SVG these values would never scale,
1945 // if we'd pass a 1.0 zoom factor everyhwere. So we only pass a zoom factor of 1.0 for specific
1946 // properties that are NOT allowed to scale within a zoomed SVG document (letter/word-spacing/font-size).
1947 bool StyleResolver::useSVGZoomRules()
1948 {
1949     return m_state.element() && m_state.element()->isSVGElement();
1950 }
1951
1952 // Scale with/height properties on inline SVG root.
1953 bool StyleResolver::useSVGZoomRulesForLength()
1954 {
1955     return is<SVGElement>(m_state.element()) && !(is<SVGSVGElement>(*m_state.element()) && m_state.element()->parentNode());
1956 }
1957
1958 void StyleResolver::applyProperty(CSSPropertyID id, CSSValue* value)
1959 {
1960     ASSERT_WITH_MESSAGE(!isShorthandCSSProperty(id), "Shorthand property id = %d wasn't expanded at parsing time", id);
1961
1962     State& state = m_state;
1963
1964     if (CSSProperty::isDirectionAwareProperty(id)) {
1965         CSSPropertyID newId = CSSProperty::resolveDirectionAwareProperty(id, state.style()->direction(), state.style()->writingMode());
1966         ASSERT(newId != id);
1967         return applyProperty(newId, value);
1968     }
1969
1970     bool isInherit = state.parentStyle() && value->isInheritedValue();
1971     bool isInitial = value->isInitialValue() || (!state.parentStyle() && value->isInheritedValue());
1972
1973     ASSERT(!isInherit || !isInitial); // isInherit -> !isInitial && isInitial -> !isInherit
1974
1975     if (!state.applyPropertyToRegularStyle() && (!state.applyPropertyToVisitedLinkStyle() || !isValidVisitedLinkProperty(id))) {
1976         // Limit the properties that can be applied to only the ones honored by :visited.
1977         return;
1978     }
1979
1980     if (isInherit && !state.parentStyle()->hasExplicitlyInheritedProperties() && !CSSProperty::isInheritedProperty(id))
1981         state.parentStyle()->setHasExplicitlyInheritedProperties();
1982
1983     // Use the generated StyleBuilder.
1984     StyleBuilder::applyProperty(id, *this, *value, isInitial, isInherit);
1985 }
1986
1987 PassRefPtr<StyleImage> StyleResolver::styleImage(CSSPropertyID property, CSSValue& value)
1988 {
1989     if (is<CSSImageValue>(value))
1990         return cachedOrPendingFromValue(property, downcast<CSSImageValue>(value));
1991
1992     if (is<CSSImageGeneratorValue>(value)) {
1993         if (is<CSSGradientValue>(value))
1994             return generatedOrPendingFromValue(property, *downcast<CSSGradientValue>(value).gradientWithStylesResolved(this));
1995         return generatedOrPendingFromValue(property, downcast<CSSImageGeneratorValue>(value));
1996     }
1997
1998 #if ENABLE(CSS_IMAGE_SET)
1999     if (is<CSSImageSetValue>(value))
2000         return setOrPendingFromValue(property, downcast<CSSImageSetValue>(value));
2001 #endif
2002
2003     if (is<CSSCursorImageValue>(value))
2004         return cursorOrPendingFromValue(property, downcast<CSSCursorImageValue>(value));
2005
2006     return nullptr;
2007 }
2008
2009 PassRefPtr<StyleImage> StyleResolver::cachedOrPendingFromValue(CSSPropertyID property, CSSImageValue& value)
2010 {
2011     RefPtr<StyleImage> image = value.cachedOrPendingImage();
2012     if (image && image->isPendingImage())
2013         m_state.pendingImageProperties().set(property, &value);
2014     return image.release();
2015 }
2016
2017 PassRefPtr<StyleImage> StyleResolver::generatedOrPendingFromValue(CSSPropertyID property, CSSImageGeneratorValue& value)
2018 {
2019     if (is<CSSFilterImageValue>(value)) {
2020         // FilterImage needs to calculate FilterOperations.
2021         downcast<CSSFilterImageValue>(value).createFilterOperations(this);
2022     }
2023
2024     if (value.isPending()) {
2025         m_state.pendingImageProperties().set(property, &value);
2026         return StylePendingImage::create(&value);
2027     }
2028     return StyleGeneratedImage::create(value);
2029 }
2030
2031 #if ENABLE(CSS_IMAGE_SET)
2032 PassRefPtr<StyleImage> StyleResolver::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue& value)
2033 {
2034     RefPtr<StyleImage> image = value.cachedOrPendingImageSet(document());
2035     if (image && image->isPendingImage())
2036         m_state.pendingImageProperties().set(property, &value);
2037     return image.release();
2038 }
2039 #endif
2040
2041 PassRefPtr<StyleImage> StyleResolver::cursorOrPendingFromValue(CSSPropertyID property, CSSCursorImageValue& value)
2042 {
2043     RefPtr<StyleImage> image = value.cachedOrPendingImage(document());
2044     if (image && image->isPendingImage())
2045         m_state.pendingImageProperties().set(property, &value);
2046     return image.release();
2047 }
2048
2049 #if ENABLE(IOS_TEXT_AUTOSIZING)
2050 void StyleResolver::checkForTextSizeAdjust(RenderStyle* style)
2051 {
2052     if (style->textSizeAdjust().isAuto())
2053         return;
2054
2055     FontDescription newFontDescription(style->fontDescription());
2056     if (!style->textSizeAdjust().isNone())
2057         newFontDescription.setComputedSize(newFontDescription.specifiedSize() * style->textSizeAdjust().multiplier());
2058     else
2059         newFontDescription.setComputedSize(newFontDescription.specifiedSize());
2060     style->setFontDescription(newFontDescription);
2061 }
2062 #endif
2063
2064 void StyleResolver::checkForZoomChange(RenderStyle* style, RenderStyle* parentStyle)
2065 {
2066     if (!parentStyle)
2067         return;
2068     
2069     if (style->effectiveZoom() == parentStyle->effectiveZoom())
2070         return;
2071
2072     const FontDescription& childFont = style->fontDescription();
2073     FontDescription newFontDescription(childFont);
2074     setFontSize(newFontDescription, childFont.specifiedSize());
2075     style->setFontDescription(newFontDescription);
2076 }
2077
2078 void StyleResolver::checkForGenericFamilyChange(RenderStyle* style, RenderStyle* parentStyle)
2079 {
2080     const FontDescription& childFont = style->fontDescription();
2081
2082     if (childFont.isAbsoluteSize() || !parentStyle)
2083         return;
2084
2085     const FontDescription& parentFont = parentStyle->fontDescription();
2086     if (childFont.useFixedDefaultSize() == parentFont.useFixedDefaultSize())
2087         return;
2088     // We know the parent is monospace or the child is monospace, and that font
2089     // size was unspecified. We want to scale our font size as appropriate.
2090     // If the font uses a keyword size, then we refetch from the table rather than
2091     // multiplying by our scale factor.
2092     float size;
2093     if (CSSValueID sizeIdentifier = childFont.keywordSizeAsIdentifier())
2094         size = Style::fontSizeForKeyword(sizeIdentifier, childFont.useFixedDefaultSize(), document());
2095     else {
2096         Settings* settings = documentSettings();
2097         float fixedScaleFactor = (settings && settings->defaultFixedFontSize() && settings->defaultFontSize())
2098             ? static_cast<float>(settings->defaultFixedFontSize()) / settings->defaultFontSize()
2099             : 1;
2100         size = parentFont.useFixedDefaultSize() ?
2101                 childFont.specifiedSize() / fixedScaleFactor :
2102                 childFont.specifiedSize() * fixedScaleFactor;
2103     }
2104
2105     FontDescription newFontDescription(childFont);
2106     setFontSize(newFontDescription, size);
2107     style->setFontDescription(newFontDescription);
2108 }
2109
2110 void StyleResolver::initializeFontStyle(Settings* settings)
2111 {
2112     FontDescription fontDescription;
2113     fontDescription.setRenderingMode(settings->fontRenderingMode());
2114     fontDescription.setOneFamily(standardFamily);
2115     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
2116     setFontSize(fontDescription, Style::fontSizeForKeyword(CSSValueMedium, false, document()));
2117     setFontDescription(fontDescription);
2118 }
2119
2120 void StyleResolver::setFontSize(FontDescription& fontDescription, float size)
2121 {
2122     fontDescription.setSpecifiedSize(size);
2123     fontDescription.setComputedSize(Style::computedFontSizeFromSpecifiedSize(size, fontDescription.isAbsoluteSize(), useSVGZoomRules(), m_state.style(), document()));
2124 }
2125
2126 static Color colorForCSSValue(CSSValueID cssValueId)
2127 {
2128     struct ColorValue {
2129         CSSValueID cssValueId;
2130         RGBA32 color;
2131     };
2132
2133     static const ColorValue colorValues[] = {
2134         { CSSValueAqua, 0xFF00FFFF },
2135         { CSSValueBlack, 0xFF000000 },
2136         { CSSValueBlue, 0xFF0000FF },
2137         { CSSValueFuchsia, 0xFFFF00FF },
2138         { CSSValueGray, 0xFF808080 },
2139         { CSSValueGreen, 0xFF008000  },
2140         { CSSValueGrey, 0xFF808080 },
2141         { CSSValueLime, 0xFF00FF00 },
2142         { CSSValueMaroon, 0xFF800000 },
2143         { CSSValueNavy, 0xFF000080 },
2144         { CSSValueOlive, 0xFF808000  },
2145         { CSSValueOrange, 0xFFFFA500 },
2146         { CSSValuePurple, 0xFF800080 },
2147         { CSSValueRed, 0xFFFF0000 },
2148         { CSSValueSilver, 0xFFC0C0C0 },
2149         { CSSValueTeal, 0xFF008080  },
2150         { CSSValueTransparent, 0x00000000 },
2151         { CSSValueWhite, 0xFFFFFFFF },
2152         { CSSValueYellow, 0xFFFFFF00 },
2153         { CSSValueInvalid, CSSValueInvalid }
2154     };
2155
2156     for (const ColorValue* col = colorValues; col->cssValueId; ++col) {
2157         if (col->cssValueId == cssValueId)
2158             return col->color;
2159     }
2160     return RenderTheme::defaultTheme()->systemColor(cssValueId);
2161 }
2162
2163 bool StyleResolver::colorFromPrimitiveValueIsDerivedFromElement(CSSPrimitiveValue& value)
2164 {
2165     int ident = value.getValueID();
2166     switch (ident) {
2167     case CSSValueWebkitText:
2168     case CSSValueWebkitLink:
2169     case CSSValueWebkitActivelink:
2170     case CSSValueCurrentcolor:
2171         return true;
2172     default:
2173         return false;
2174     }
2175 }
2176
2177 Color StyleResolver::colorFromPrimitiveValue(CSSPrimitiveValue& value, bool forVisitedLink) const
2178 {
2179     if (value.isRGBColor())
2180         return Color(value.getRGBA32Value());
2181
2182     const State& state = m_state;
2183     CSSValueID ident = value.getValueID();
2184     switch (ident) {
2185     case 0:
2186         return Color();
2187     case CSSValueWebkitText:
2188         return state.document().textColor();
2189     case CSSValueWebkitLink:
2190         return (state.element()->isLink() && forVisitedLink) ? state.document().visitedLinkColor() : state.document().linkColor();
2191     case CSSValueWebkitActivelink:
2192         return state.document().activeLinkColor();
2193     case CSSValueWebkitFocusRingColor:
2194         return RenderTheme::focusRingColor();
2195     case CSSValueCurrentcolor:
2196         return state.style()->color();
2197     default:
2198         return colorForCSSValue(ident);
2199     }
2200 }
2201
2202 void StyleResolver::addViewportDependentMediaQueryResult(const MediaQueryExp* expr, bool result)
2203 {
2204     m_viewportDependentMediaQueryResults.append(std::make_unique<MediaQueryResult>(*expr, result));
2205 }
2206
2207 bool StyleResolver::hasMediaQueriesAffectedByViewportChange() const
2208 {
2209     unsigned s = m_viewportDependentMediaQueryResults.size();
2210     for (unsigned i = 0; i < s; i++) {
2211         if (m_medium->eval(&m_viewportDependentMediaQueryResults[i]->m_expression) != m_viewportDependentMediaQueryResults[i]->m_result)
2212             return true;
2213     }
2214     return false;
2215 }
2216
2217 static FilterOperation::OperationType filterOperationForType(WebKitCSSFilterValue::FilterOperationType type)
2218 {
2219     switch (type) {
2220     case WebKitCSSFilterValue::ReferenceFilterOperation:
2221         return FilterOperation::REFERENCE;
2222     case WebKitCSSFilterValue::GrayscaleFilterOperation:
2223         return FilterOperation::GRAYSCALE;
2224     case WebKitCSSFilterValue::SepiaFilterOperation:
2225         return FilterOperation::SEPIA;
2226     case WebKitCSSFilterValue::SaturateFilterOperation:
2227         return FilterOperation::SATURATE;
2228     case WebKitCSSFilterValue::HueRotateFilterOperation:
2229         return FilterOperation::HUE_ROTATE;
2230     case WebKitCSSFilterValue::InvertFilterOperation:
2231         return FilterOperation::INVERT;
2232     case WebKitCSSFilterValue::OpacityFilterOperation:
2233         return FilterOperation::OPACITY;
2234     case WebKitCSSFilterValue::BrightnessFilterOperation:
2235         return FilterOperation::BRIGHTNESS;
2236     case WebKitCSSFilterValue::ContrastFilterOperation:
2237         return FilterOperation::CONTRAST;
2238     case WebKitCSSFilterValue::BlurFilterOperation:
2239         return FilterOperation::BLUR;
2240     case WebKitCSSFilterValue::DropShadowFilterOperation:
2241         return FilterOperation::DROP_SHADOW;
2242     case WebKitCSSFilterValue::UnknownFilterOperation:
2243         return FilterOperation::NONE;
2244     }
2245     return FilterOperation::NONE;
2246 }
2247
2248 void StyleResolver::loadPendingSVGDocuments()
2249 {
2250     State& state = m_state;
2251
2252     // Crash reports indicate that we've seen calls to this function when our
2253     // style is NULL. We don't know exactly why this happens. Our guess is
2254     // reentering styleForElement().
2255     ASSERT(state.style());
2256     if (!state.style())
2257         return;
2258     
2259     bool hasFilters = (state.style()->hasFilter() && !state.filtersWithPendingSVGDocuments().isEmpty());
2260     bool hasMasks = (state.style()->hasMask() && !state.maskImagesWithPendingSVGDocuments().isEmpty());
2261     
2262     if (!hasFilters && !hasMasks)
2263         return;
2264
2265     CachedResourceLoader& cachedResourceLoader = state.document().cachedResourceLoader();
2266     
2267     if (hasFilters) {
2268         for (auto& filterOperation : state.filtersWithPendingSVGDocuments())
2269             filterOperation->getOrCreateCachedSVGDocumentReference()->load(cachedResourceLoader);
2270
2271         state.filtersWithPendingSVGDocuments().clear();
2272     }
2273     
2274     if (hasMasks) {
2275         for (auto& maskImageOperation : state.maskImagesWithPendingSVGDocuments())
2276             maskImageOperation->ensureCachedSVGDocumentReference()->load(cachedResourceLoader);
2277
2278         state.maskImagesWithPendingSVGDocuments().clear();
2279     }
2280 }
2281
2282 bool StyleResolver::createFilterOperations(CSSValue& inValue, FilterOperations& outOperations)
2283 {
2284     State& state = m_state;
2285     ASSERT(outOperations.isEmpty());
2286     
2287     if (is<CSSPrimitiveValue>(inValue)) {
2288         CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(inValue);
2289         if (primitiveValue.getValueID() == CSSValueNone)
2290             return true;
2291     }
2292     
2293     if (!is<CSSValueList>(inValue))
2294         return false;
2295
2296     FilterOperations operations;
2297     for (auto& currentValue : downcast<CSSValueList>(inValue)) {
2298         if (!is<WebKitCSSFilterValue>(currentValue.get()))
2299             continue;
2300
2301         auto& filterValue = downcast<WebKitCSSFilterValue>(currentValue.get());
2302         FilterOperation::OperationType operationType = filterOperationForType(filterValue.operationType());
2303
2304         if (operationType == FilterOperation::REFERENCE) {
2305             if (filterValue.length() != 1)
2306                 continue;
2307             CSSValue& argument = *filterValue.itemWithoutBoundsCheck(0);
2308
2309             if (!is<CSSPrimitiveValue>(argument))
2310                 continue;
2311
2312             CSSPrimitiveValue& primitiveValue = downcast<CSSPrimitiveValue>(argument);
2313             String cssUrl = primitiveValue.getStringValue();
2314             URL url = m_state.document().completeURL(cssUrl);
2315
2316             RefPtr<ReferenceFilterOperation> operation = ReferenceFilterOperation::create(cssUrl, url.fragmentIdentifier());
2317             if (SVGURIReference::isExternalURIReference(cssUrl, m_state.document()))
2318                 state.filtersWithPendingSVGDocuments().append(operation);
2319
2320             operations.operations().append(operation);
2321             continue;
2322         }
2323
2324         // Check that all parameters are primitive values, with the
2325         // exception of drop shadow which has a CSSShadowValue parameter.
2326         CSSPrimitiveValue* firstValue = nullptr;
2327         if (operationType != FilterOperation::DROP_SHADOW) {
2328             bool haveNonPrimitiveValue = false;
2329             for (unsigned j = 0; j < filterValue.length(); ++j) {
2330                 if (!is<CSSPrimitiveValue>(*filterValue.itemWithoutBoundsCheck(j))) {
2331                     haveNonPrimitiveValue = true;
2332                     break;
2333                 }
2334             }
2335             if (haveNonPrimitiveValue)
2336                 continue;
2337             if (filterValue.length())
2338                 firstValue = downcast<CSSPrimitiveValue>(filterValue.itemWithoutBoundsCheck(0));
2339         }
2340
2341         switch (filterValue.operationType()) {
2342         case WebKitCSSFilterValue::GrayscaleFilterOperation:
2343         case WebKitCSSFilterValue::SepiaFilterOperation:
2344         case WebKitCSSFilterValue::SaturateFilterOperation: {
2345             double amount = 1;
2346             if (filterValue.length() == 1) {
2347                 amount = firstValue->getDoubleValue();
2348                 if (firstValue->isPercentage())
2349                     amount /= 100;
2350             }
2351
2352             operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
2353             break;
2354         }
2355         case WebKitCSSFilterValue::HueRotateFilterOperation: {
2356             double angle = 0;
2357             if (filterValue.length() == 1)
2358                 angle = firstValue->computeDegrees();
2359
2360             operations.operations().append(BasicColorMatrixFilterOperation::create(angle, operationType));
2361             break;
2362         }
2363         case WebKitCSSFilterValue::InvertFilterOperation:
2364         case WebKitCSSFilterValue::BrightnessFilterOperation:
2365         case WebKitCSSFilterValue::ContrastFilterOperation:
2366         case WebKitCSSFilterValue::OpacityFilterOperation: {
2367             double amount = (filterValue.operationType() == WebKitCSSFilterValue::BrightnessFilterOperation) ? 0 : 1;
2368             if (filterValue.length() == 1) {
2369                 amount = firstValue->getDoubleValue();
2370                 if (firstValue->isPercentage())
2371                     amount /= 100;
2372             }
2373
2374             operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
2375             break;
2376         }
2377         case WebKitCSSFilterValue::BlurFilterOperation: {
2378             Length stdDeviation = Length(0, Fixed);
2379             if (filterValue.length() >= 1)
2380                 stdDeviation = convertToFloatLength(firstValue, state.cssToLengthConversionData());
2381             if (stdDeviation.isUndefined())
2382                 return false;
2383
2384             operations.operations().append(BlurFilterOperation::create(stdDeviation));
2385             break;
2386         }
2387         case WebKitCSSFilterValue::DropShadowFilterOperation: {
2388             if (filterValue.length() != 1)
2389                 return false;
2390
2391             CSSValue& cssValue = *filterValue.itemWithoutBoundsCheck(0);
2392             if (!is<CSSShadowValue>(cssValue))
2393                 continue;
2394
2395             CSSShadowValue& item = downcast<CSSShadowValue>(cssValue);
2396             int x = item.x->computeLength<int>(state.cssToLengthConversionData());
2397             int y = item.y->computeLength<int>(state.cssToLengthConversionData());
2398             IntPoint location(x, y);
2399             int blur = item.blur ? item.blur->computeLength<int>(state.cssToLengthConversionData()) : 0;
2400             Color color;
2401             if (item.color)
2402                 color = colorFromPrimitiveValue(*item.color);
2403
2404             operations.operations().append(DropShadowFilterOperation::create(location, blur, color.isValid() ? color : Color::transparent));
2405             break;
2406         }
2407         case WebKitCSSFilterValue::UnknownFilterOperation:
2408         default:
2409             ASSERT_NOT_REACHED();
2410             break;
2411         }
2412     }
2413
2414     outOperations = operations;
2415     return true;
2416 }
2417
2418 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage, const ResourceLoaderOptions& options)
2419 {
2420     if (auto imageValue = pendingImage.cssImageValue())
2421         return imageValue->cachedImage(m_state.document().cachedResourceLoader(), options);
2422
2423     if (auto imageGeneratorValue = pendingImage.cssImageGeneratorValue()) {
2424         imageGeneratorValue->loadSubimages(m_state.document().cachedResourceLoader());
2425         return StyleGeneratedImage::create(*imageGeneratorValue);
2426     }
2427
2428     if (auto cursorImageValue = pendingImage.cssCursorImageValue())
2429         return cursorImageValue->cachedImage(m_state.document().cachedResourceLoader());
2430
2431 #if ENABLE(CSS_IMAGE_SET)
2432     if (auto imageSetValue = pendingImage.cssImageSetValue())
2433         return imageSetValue->cachedImageSet(m_state.document().cachedResourceLoader(), options);
2434 #endif
2435
2436     return nullptr;
2437 }
2438
2439 PassRefPtr<StyleImage> StyleResolver::loadPendingImage(const StylePendingImage& pendingImage)
2440 {
2441     return loadPendingImage(pendingImage, CachedResourceLoader::defaultCachedResourceOptions());
2442 }
2443
2444 #if ENABLE(CSS_SHAPES)
2445 void StyleResolver::loadPendingShapeImage(ShapeValue* shapeValue)
2446 {
2447     if (!shapeValue)
2448         return;
2449
2450     StyleImage* image = shapeValue->image();
2451     if (!is<StylePendingImage>(image))
2452         return;
2453
2454     auto& pendingImage = downcast<StylePendingImage>(*image);
2455
2456     ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
2457     options.setRequestOriginPolicy(PotentiallyCrossOriginEnabled);
2458     options.setAllowCredentials(DoNotAllowStoredCredentials);
2459
2460     shapeValue->setImage(loadPendingImage(pendingImage, options));
2461 }
2462 #endif
2463
2464 void StyleResolver::loadPendingImages()
2465 {
2466     RELEASE_ASSERT(!m_inLoadPendingImages);
2467     TemporaryChange<bool> changeInLoadPendingImages(m_inLoadPendingImages, true);
2468
2469     if (m_state.pendingImageProperties().isEmpty())
2470         return;
2471
2472     auto end = m_state.pendingImageProperties().end().keys();
2473     for (auto it = m_state.pendingImageProperties().begin().keys(); it != end; ++it) {
2474         CSSPropertyID currentProperty = *it;
2475
2476         switch (currentProperty) {
2477         case CSSPropertyBackgroundImage: {
2478             for (FillLayer* backgroundLayer = &m_state.style()->ensureBackgroundLayers(); backgroundLayer; backgroundLayer = backgroundLayer->next()) {
2479                 auto* styleImage = backgroundLayer->image();
2480                 if (is<StylePendingImage>(styleImage))
2481                     backgroundLayer->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2482             }
2483             break;
2484         }
2485         case CSSPropertyContent: {
2486             for (ContentData* contentData = const_cast<ContentData*>(m_state.style()->contentData()); contentData; contentData = contentData->next()) {
2487                 if (is<ImageContentData>(*contentData)) {
2488                     auto& styleImage = downcast<ImageContentData>(*contentData).image();
2489                     if (is<StylePendingImage>(styleImage)) {
2490                         if (RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(styleImage)))
2491                             downcast<ImageContentData>(*contentData).setImage(loadedImage.release());
2492                     }
2493                 }
2494             }
2495             break;
2496         }
2497         case CSSPropertyCursor: {
2498             if (CursorList* cursorList = m_state.style()->cursors()) {
2499                 for (size_t i = 0; i < cursorList->size(); ++i) {
2500                     CursorData& currentCursor = cursorList->at(i);
2501                     auto* styleImage = currentCursor.image();
2502                     if (is<StylePendingImage>(styleImage))
2503                         currentCursor.setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2504                 }
2505             }
2506             break;
2507         }
2508         case CSSPropertyListStyleImage: {
2509             auto* styleImage = m_state.style()->listStyleImage();
2510             if (is<StylePendingImage>(styleImage))
2511                 m_state.style()->setListStyleImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2512             break;
2513         }
2514         case CSSPropertyBorderImageSource: {
2515             auto* styleImage = m_state.style()->borderImageSource();
2516             if (is<StylePendingImage>(styleImage))
2517                 m_state.style()->setBorderImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2518             break;
2519         }
2520         case CSSPropertyWebkitBoxReflect: {
2521             if (StyleReflection* reflection = m_state.style()->boxReflect()) {
2522                 const NinePieceImage& maskImage = reflection->mask();
2523                 auto* styleImage = maskImage.image();
2524                 if (is<StylePendingImage>(styleImage)) {
2525                     RefPtr<StyleImage> loadedImage = loadPendingImage(downcast<StylePendingImage>(*styleImage));
2526                     reflection->setMask(NinePieceImage(loadedImage.release(), maskImage.imageSlices(), maskImage.fill(), maskImage.borderSlices(), maskImage.outset(), maskImage.horizontalRule(), maskImage.verticalRule()));
2527                 }
2528             }
2529             break;
2530         }
2531         case CSSPropertyWebkitMaskBoxImageSource: {
2532             auto* styleImage = m_state.style()->maskBoxImageSource();
2533             if (is<StylePendingImage>(styleImage))
2534                 m_state.style()->setMaskBoxImageSource(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2535             break;
2536         }
2537         case CSSPropertyWebkitMaskImage: {
2538             for (FillLayer* maskLayer = &m_state.style()->ensureMaskLayers(); maskLayer; maskLayer = maskLayer->next()) {
2539                 RefPtr<MaskImageOperation> maskImage = maskLayer->maskImage();
2540                 auto* styleImage = maskImage.get() ? maskImage->image() : nullptr;
2541                 if (is<StylePendingImage>(styleImage))
2542                     maskImage->setImage(loadPendingImage(downcast<StylePendingImage>(*styleImage)));
2543             }
2544             break;
2545         }
2546 #if ENABLE(CSS_SHAPES)
2547         case CSSPropertyWebkitShapeOutside:
2548             loadPendingShapeImage(m_state.style()->shapeOutside());
2549             break;
2550 #endif
2551         default:
2552             ASSERT_NOT_REACHED();
2553         }
2554     }
2555
2556     m_state.pendingImageProperties().clear();
2557 }
2558
2559 #ifndef NDEBUG
2560 static bool inLoadPendingResources = false;
2561 #endif
2562
2563 void StyleResolver::loadPendingResources()
2564 {
2565     // We've seen crashes in all three of the functions below. Some of them
2566     // indicate that style() is NULL. This NULL check will cut down on total
2567     // crashes, while the ASSERT will help us find the cause in debug builds.
2568     ASSERT(style());
2569     if (!style())
2570         return;
2571
2572 #ifndef NDEBUG
2573     // Re-entering this function will probably mean trouble. Catch it in debug builds.
2574     ASSERT(!inLoadPendingResources);
2575     inLoadPendingResources = true;
2576 #endif
2577
2578     // Start loading images referenced by this style.
2579     loadPendingImages();
2580
2581     // Start loading the SVG Documents referenced by this style.
2582     loadPendingSVGDocuments();
2583
2584 #ifndef NDEBUG
2585     inLoadPendingResources = false;
2586 #endif
2587 }
2588
2589 inline StyleResolver::MatchedProperties::MatchedProperties()
2590     : possiblyPaddedMember(0)
2591 {
2592 }
2593
2594 StyleResolver::MatchedProperties::~MatchedProperties()
2595 {
2596 }
2597
2598 StyleResolver::CascadedProperties::CascadedProperties(TextDirection direction, WritingMode writingMode)
2599     : m_direction(direction)
2600     , m_writingMode(writingMode)
2601 {
2602 }
2603
2604 inline bool StyleResolver::CascadedProperties::hasProperty(CSSPropertyID id) const
2605 {
2606     ASSERT(id < m_propertyIsPresent.size());
2607     return m_propertyIsPresent[id];
2608 }
2609
2610 inline StyleResolver::CascadedProperties::Property& StyleResolver::CascadedProperties::property(CSSPropertyID id)
2611 {
2612     return m_properties[id];
2613 }
2614
2615 void StyleResolver::CascadedProperties::setPropertyInternal(Property& property, CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
2616 {
2617     ASSERT(linkMatchType <= SelectorChecker::MatchAll);
2618     property.id = id;
2619     if (linkMatchType == SelectorChecker::MatchAll) {
2620         property.cssValue[0] = &cssValue;
2621         property.cssValue[SelectorChecker::MatchLink] = &cssValue;
2622         property.cssValue[SelectorChecker::MatchVisited] = &cssValue;
2623     } else
2624         property.cssValue[linkMatchType] = &cssValue;
2625 }
2626
2627 void StyleResolver::CascadedProperties::set(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
2628 {
2629     if (CSSProperty::isDirectionAwareProperty(id))
2630         id = CSSProperty::resolveDirectionAwareProperty(id, m_direction, m_writingMode);
2631
2632     ASSERT(!shouldApplyPropertyInParseOrder(id));
2633
2634     auto& property = m_properties[id];
2635     ASSERT(id < m_propertyIsPresent.size());
2636     if (!m_propertyIsPresent[id])
2637         memset(property.cssValue, 0, sizeof(property.cssValue));
2638     m_propertyIsPresent.set(id);
2639     setPropertyInternal(property, id, cssValue, linkMatchType);
2640 }
2641
2642 void StyleResolver::CascadedProperties::setDeferred(CSSPropertyID id, CSSValue& cssValue, unsigned linkMatchType)
2643 {
2644     ASSERT(!CSSProperty::isDirectionAwareProperty(id));
2645     ASSERT(shouldApplyPropertyInParseOrder(id));
2646
2647     Property property;
2648     memset(property.cssValue, 0, sizeof(property.cssValue));
2649     setPropertyInternal(property, id, cssValue, linkMatchType);
2650     m_deferredProperties.append(property);
2651 }
2652
2653 void StyleResolver::CascadedProperties::addStyleProperties(const StyleProperties& properties, StyleRule&, bool isImportant, bool inheritedOnly, PropertyWhitelistType propertyWhitelistType, unsigned linkMatchType)
2654 {
2655     for (unsigned i = 0, count = properties.propertyCount(); i < count; ++i) {
2656         auto current = properties.propertyAt(i);
2657         if (isImportant != current.isImportant())
2658             continue;
2659         if (inheritedOnly && !current.isInherited()) {
2660             // We apply the inherited properties only when using the property cache.
2661             // A match with a value that is explicitely inherited should never have been cached.
2662             ASSERT(!current.value()->isInheritedValue());
2663             continue;
2664         }
2665         CSSPropertyID propertyID = current.id();
2666
2667         if (propertyWhitelistType == PropertyWhitelistRegion && !StyleResolver::isValidRegionStyleProperty(propertyID))
2668             continue;
2669 #if ENABLE(VIDEO_TRACK)
2670         if (propertyWhitelistType == PropertyWhitelistCue && !StyleResolver::isValidCueStyleProperty(propertyID))
2671             continue;
2672 #endif
2673
2674         if (shouldApplyPropertyInParseOrder(propertyID))
2675             setDeferred(propertyID, *current.value(), linkMatchType);
2676         else
2677             set(propertyID, *current.value(), linkMatchType);
2678     }
2679 }
2680
2681 void StyleResolver::CascadedProperties::addMatches(const MatchResult& matchResult, bool important, int startIndex, int endIndex, bool inheritedOnly)
2682 {
2683     if (startIndex == -1)
2684         return;
2685
2686     for (int i = startIndex; i <= endIndex; ++i) {
2687         const MatchedProperties& matchedProperties = matchResult.matchedProperties()[i];
2688         addStyleProperties(*matchedProperties.properties, *matchResult.matchedRules[i], important, inheritedOnly, static_cast<PropertyWhitelistType>(matchedProperties.whitelistType), matchedProperties.linkMatchType);
2689     }
2690 }
2691
2692 void StyleResolver::CascadedProperties::applyDeferredProperties(StyleResolver& resolver)
2693 {
2694     for (auto& property : m_deferredProperties)
2695         property.apply(resolver);
2696 }
2697
2698 void StyleResolver::CascadedProperties::Property::apply(StyleResolver& resolver)
2699 {
2700     State& state = resolver.state();
2701
2702     if (cssValue[0]) {
2703         state.setApplyPropertyToRegularStyle(true);
2704         state.setApplyPropertyToVisitedLinkStyle(false);
2705         resolver.applyProperty(id, cssValue[0]);
2706     }
2707
2708     if (state.style()->insideLink() == NotInsideLink)
2709         return;
2710
2711     if (cssValue[SelectorChecker::MatchLink]) {
2712         state.setApplyPropertyToRegularStyle(true);
2713         state.setApplyPropertyToVisitedLinkStyle(false);
2714         resolver.applyProperty(id, cssValue[SelectorChecker::MatchLink]);
2715     }
2716
2717     if (cssValue[SelectorChecker::MatchVisited]) {
2718         state.setApplyPropertyToRegularStyle(false);
2719         state.setApplyPropertyToVisitedLinkStyle(true);
2720         resolver.applyProperty(id, cssValue[SelectorChecker::MatchVisited]);
2721     }
2722
2723     state.setApplyPropertyToRegularStyle(true);
2724     state.setApplyPropertyToVisitedLinkStyle(false);
2725 }
2726
2727 void StyleResolver::applyCascadedProperties(CascadedProperties& cascade, int firstProperty, int lastProperty)
2728 {
2729     for (int id = firstProperty; id <= lastProperty; ++id) {
2730         CSSPropertyID propertyID = static_cast<CSSPropertyID>(id);
2731         if (!cascade.hasProperty(propertyID))
2732             continue;
2733         auto& property = cascade.property(propertyID);
2734         ASSERT(!shouldApplyPropertyInParseOrder(propertyID));
2735         property.apply(*this);
2736     }
2737 }
2738
2739 } // namespace WebCore