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