Create inline wrappers for before/after pseudo elements that have display:contents
[WebKit-https.git] / Source / WebCore / rendering / style / RenderStyle.cpp
1 /*
2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3  * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
4  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "RenderStyle.h"
25
26 #include "ContentData.h"
27 #include "CSSCustomPropertyValue.h"
28 #include "CSSParser.h"
29 #include "CSSPropertyNames.h"
30 #include "CursorList.h"
31 #include "FloatRoundedRect.h"
32 #include "FontCascade.h"
33 #include "FontSelector.h"
34 #include "InlineTextBoxStyle.h"
35 #include "Pagination.h"
36 #include "QuotesData.h"
37 #include "RenderObject.h"
38 #include "RenderTheme.h"
39 #include "RuntimeEnabledFeatures.h"
40 #include "ScaleTransformOperation.h"
41 #include "ShadowData.h"
42 #include "StyleImage.h"
43 #include "StyleInheritedData.h"
44 #include "StyleResolver.h"
45 #include "StyleScrollSnapPoints.h"
46 #include "StyleSelfAlignmentData.h"
47 #include "StyleTreeResolver.h"
48 #include "WillChangeData.h"
49 #include <wtf/MathExtras.h>
50 #include <wtf/PointerComparison.h>
51 #include <wtf/StdLibExtras.h>
52 #include <algorithm>
53
54 #if ENABLE(TEXT_AUTOSIZING)
55 #include <wtf/text/StringHash.h>
56 #endif
57
58 namespace WebCore {
59
60 struct SameSizeAsBorderValue {
61     float m_width;
62     Color m_color;
63     int m_restBits;
64 };
65
66 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
67
68 struct SameSizeAsRenderStyle {
69     void* dataRefs[7];
70     void* ownPtrs[1];
71     void* dataRefSvgStyle;
72     struct InheritedFlags {
73         unsigned m_bitfields[2];
74     } m_inheritedFlags;
75
76     struct NonInheritedFlags {
77         unsigned m_bitfields[2];
78     } m_nonInheritedFlags;
79 #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
80     bool deletionCheck;
81 #endif
82 };
83
84 static_assert(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), "RenderStyle should stay small");
85
86 RenderStyle& RenderStyle::defaultStyle()
87 {
88     static NeverDestroyed<RenderStyle> style { CreateDefaultStyle };
89     return style;
90 }
91
92 RenderStyle RenderStyle::create()
93 {
94     return clone(defaultStyle());
95 }
96
97 std::unique_ptr<RenderStyle> RenderStyle::createPtr()
98 {
99     return clonePtr(defaultStyle());
100 }
101
102 RenderStyle RenderStyle::clone(const RenderStyle& style)
103 {
104     return RenderStyle(style, Clone);
105 }
106
107 std::unique_ptr<RenderStyle> RenderStyle::clonePtr(const RenderStyle& style)
108 {
109     return std::make_unique<RenderStyle>(style, Clone);
110 }
111
112 RenderStyle RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle& parentStyle, EDisplay display)
113 {
114     auto newStyle = create();
115     newStyle.inheritFrom(parentStyle);
116     newStyle.inheritUnicodeBidiFrom(&parentStyle);
117     newStyle.setDisplay(display);
118     return newStyle;
119 }
120
121 RenderStyle RenderStyle::createStyleInheritingFromPseudoStyle(const RenderStyle& pseudoStyle)
122 {
123     ASSERT(pseudoStyle.styleType() == BEFORE || pseudoStyle.styleType() == AFTER);
124
125     auto style = create();
126     style.inheritFrom(pseudoStyle);
127     return style;
128 }
129
130 RenderStyle::RenderStyle(RenderStyle&&) = default;
131 RenderStyle& RenderStyle::operator=(RenderStyle&&) = default;
132
133 RenderStyle::RenderStyle(CreateDefaultStyleTag)
134     : m_boxData(StyleBoxData::create())
135     , m_visualData(StyleVisualData::create())
136     , m_backgroundData(StyleBackgroundData::create())
137     , m_surroundData(StyleSurroundData::create())
138     , m_rareNonInheritedData(StyleRareNonInheritedData::create())
139     , m_rareInheritedData(StyleRareInheritedData::create())
140     , m_inheritedData(StyleInheritedData::create())
141     , m_svgStyle(SVGRenderStyle::create())
142 {
143     m_inheritedFlags.emptyCells = initialEmptyCells();
144     m_inheritedFlags.captionSide = initialCaptionSide();
145     m_inheritedFlags.listStyleType = initialListStyleType();
146     m_inheritedFlags.listStylePosition = initialListStylePosition();
147     m_inheritedFlags.visibility = initialVisibility();
148     m_inheritedFlags.textAlign = initialTextAlign();
149     m_inheritedFlags.textTransform = initialTextTransform();
150     m_inheritedFlags.textDecorations = initialTextDecoration();
151     m_inheritedFlags.cursor = initialCursor();
152 #if ENABLE(CURSOR_VISIBILITY)
153     m_inheritedFlags.cursorVisibility = initialCursorVisibility();
154 #endif
155     m_inheritedFlags.direction = initialDirection();
156     m_inheritedFlags.whiteSpace = initialWhiteSpace();
157     m_inheritedFlags.borderCollapse = initialBorderCollapse();
158     m_inheritedFlags.rtlOrdering = initialRTLOrdering();
159     m_inheritedFlags.boxDirection = initialBoxDirection();
160     m_inheritedFlags.printColorAdjust = initialPrintColorAdjust();
161     m_inheritedFlags.pointerEvents = initialPointerEvents();
162     m_inheritedFlags.insideLink = NotInsideLink;
163     m_inheritedFlags.insideDefaultButton = false;
164     m_inheritedFlags.writingMode = initialWritingMode();
165
166     m_nonInheritedFlags.effectiveDisplay = initialDisplay();
167     m_nonInheritedFlags.originalDisplay = initialDisplay();
168     m_nonInheritedFlags.overflowX = initialOverflowX();
169     m_nonInheritedFlags.overflowY = initialOverflowY();
170     m_nonInheritedFlags.verticalAlign = initialVerticalAlign();
171     m_nonInheritedFlags.clear = initialClear();
172     m_nonInheritedFlags.position = initialPosition();
173     m_nonInheritedFlags.unicodeBidi = initialUnicodeBidi();
174     m_nonInheritedFlags.floating = initialFloating();
175     m_nonInheritedFlags.tableLayout = initialTableLayout();
176     m_nonInheritedFlags.hasExplicitlySetDirection = false;
177     m_nonInheritedFlags.hasExplicitlySetWritingMode = false;
178     m_nonInheritedFlags.hasExplicitlySetTextAlign = false;
179     m_nonInheritedFlags.hasViewportUnits = false;
180     m_nonInheritedFlags.hasExplicitlyInheritedProperties = false;
181     m_nonInheritedFlags.isUnique = false;
182     m_nonInheritedFlags.emptyState = false;
183     m_nonInheritedFlags.firstChildState = false;
184     m_nonInheritedFlags.lastChildState = false;
185     m_nonInheritedFlags.affectedByHover = false;
186     m_nonInheritedFlags.affectedByActive = false;
187     m_nonInheritedFlags.affectedByDrag = false;
188     m_nonInheritedFlags.isLink = false;
189     m_nonInheritedFlags.styleType = NOPSEUDO;
190     m_nonInheritedFlags.pseudoBits = NOPSEUDO;
191
192     static_assert((sizeof(InheritedFlags) <= 8), "InheritedFlags does not grow");
193     static_assert((sizeof(NonInheritedFlags) <= 8), "NonInheritedFlags does not grow");
194 }
195
196 inline RenderStyle::RenderStyle(const RenderStyle& other, CloneTag)
197     : m_boxData(other.m_boxData)
198     , m_visualData(other.m_visualData)
199     , m_backgroundData(other.m_backgroundData)
200     , m_surroundData(other.m_surroundData)
201     , m_rareNonInheritedData(other.m_rareNonInheritedData)
202     , m_nonInheritedFlags(other.m_nonInheritedFlags)
203     , m_rareInheritedData(other.m_rareInheritedData)
204     , m_inheritedData(other.m_inheritedData)
205     , m_inheritedFlags(other.m_inheritedFlags)
206     , m_svgStyle(other.m_svgStyle)
207 {
208 }
209
210 inline RenderStyle::RenderStyle(RenderStyle& a, RenderStyle&& b)
211     : m_boxData(a.m_boxData.replace(WTFMove(b.m_boxData)))
212     , m_visualData(a.m_visualData.replace(WTFMove(b.m_visualData)))
213     , m_backgroundData(a.m_backgroundData.replace(WTFMove(b.m_backgroundData)))
214     , m_surroundData(a.m_surroundData.replace(WTFMove(b.m_surroundData)))
215     , m_rareNonInheritedData(a.m_rareNonInheritedData.replace(WTFMove(b.m_rareNonInheritedData)))
216     , m_nonInheritedFlags(std::exchange(a.m_nonInheritedFlags, b.m_nonInheritedFlags))
217     , m_rareInheritedData(a.m_rareInheritedData.replace(WTFMove(b.m_rareInheritedData)))
218     , m_inheritedData(a.m_inheritedData.replace(WTFMove(b.m_inheritedData)))
219     , m_inheritedFlags(std::exchange(a.m_inheritedFlags, b.m_inheritedFlags))
220     , m_cachedPseudoStyles(std::exchange(a.m_cachedPseudoStyles, WTFMove(b.m_cachedPseudoStyles)))
221     , m_svgStyle(a.m_svgStyle.replace(WTFMove(b.m_svgStyle)))
222 {
223 }
224
225 RenderStyle::~RenderStyle()
226 {
227 #if !ASSERT_DISABLED || ENABLE(SECURITY_ASSERTIONS)
228     ASSERT_WITH_SECURITY_IMPLICATION(!m_deletionHasBegun);
229     m_deletionHasBegun = true;
230 #endif
231 }
232
233 RenderStyle RenderStyle::replace(RenderStyle&& newStyle)
234 {
235     return RenderStyle { *this, WTFMove(newStyle) };
236 }
237
238 bool RenderStyle::isCSSGridLayoutEnabled()
239 {
240     return RuntimeEnabledFeatures::sharedFeatures().isCSSGridLayoutEnabled();
241 }
242
243 static StyleSelfAlignmentData resolvedSelfAlignment(const StyleSelfAlignmentData& value, ItemPosition normalValueBehavior)
244 {
245     if (value.position() == ItemPositionNormal || value.position() == ItemPositionAuto)
246         return { normalValueBehavior, OverflowAlignmentDefault };
247     return value;
248 }
249
250 StyleSelfAlignmentData RenderStyle::resolvedAlignItems(ItemPosition normalValueBehaviour) const
251 {
252     return resolvedSelfAlignment(alignItems(), normalValueBehaviour);
253 }
254
255 StyleSelfAlignmentData RenderStyle::resolvedAlignSelf(const RenderStyle* parentStyle, ItemPosition normalValueBehaviour) const
256 {
257     // The auto keyword computes to the parent's align-items computed value.
258     // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
259     if (!parentStyle || alignSelf().position() != ItemPositionAuto)
260         return resolvedSelfAlignment(alignSelf(), normalValueBehaviour);
261     return parentStyle->resolvedAlignItems(normalValueBehaviour);
262 }
263
264 StyleSelfAlignmentData RenderStyle::resolvedJustifyItems(ItemPosition normalValueBehaviour) const
265 {
266     // FIXME: justify-items 'auto' value is allowed only to provide the 'legacy' keyword's behavior, which it's still not implemented for layout.
267     // "If the inherited value of justify-items includes the legacy keyword, auto computes to the inherited value."
268     // https://drafts.csswg.org/css-align/#justify-items-property
269     if (justifyItems().position() == ItemPositionAuto)
270         return { normalValueBehaviour, OverflowAlignmentDefault };
271     return resolvedSelfAlignment(justifyItems(), normalValueBehaviour);
272 }
273
274 StyleSelfAlignmentData RenderStyle::resolvedJustifySelf(const RenderStyle* parentStyle, ItemPosition normalValueBehaviour) const
275 {
276     // The auto keyword computes to the parent's justify-items computed value.
277     // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
278     if (!parentStyle || justifySelf().position() != ItemPositionAuto)
279         return resolvedSelfAlignment(justifySelf(), normalValueBehaviour);
280     return parentStyle->resolvedJustifyItems(normalValueBehaviour);
281 }
282
283 static inline StyleContentAlignmentData resolvedContentAlignment(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
284 {
285     return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior : value;
286 }
287
288 StyleContentAlignmentData RenderStyle::resolvedAlignContent(const StyleContentAlignmentData& normalValueBehavior) const
289 {
290     // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
291     return resolvedContentAlignment(alignContent(), normalValueBehavior);
292 }
293
294 StyleContentAlignmentData RenderStyle::resolvedJustifyContent(const StyleContentAlignmentData& normalValueBehavior) const
295 {
296     // We will return the behaviour of 'normal' value if needed, which is specific of each layout model.
297     return resolvedContentAlignment(justifyContent(), normalValueBehavior);
298 }
299
300 static inline ContentPosition resolvedContentAlignmentPosition(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
301 {
302     return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.position() : value.position();
303 }
304
305 static inline ContentDistributionType resolvedContentAlignmentDistribution(const StyleContentAlignmentData& value, const StyleContentAlignmentData& normalValueBehavior)
306 {
307     return (value.position() == ContentPositionNormal && value.distribution() == ContentDistributionDefault) ? normalValueBehavior.distribution() : value.distribution();
308 }
309
310 ContentPosition RenderStyle::resolvedJustifyContentPosition(const StyleContentAlignmentData& normalValueBehavior) const
311 {
312     return resolvedContentAlignmentPosition(justifyContent(), normalValueBehavior);
313 }
314
315 ContentDistributionType RenderStyle::resolvedJustifyContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
316 {
317     return resolvedContentAlignmentDistribution(justifyContent(), normalValueBehavior);
318 }
319
320 ContentPosition RenderStyle::resolvedAlignContentPosition(const StyleContentAlignmentData& normalValueBehavior) const
321 {
322     return resolvedContentAlignmentPosition(alignContent(), normalValueBehavior);
323 }
324
325 ContentDistributionType RenderStyle::resolvedAlignContentDistribution(const StyleContentAlignmentData& normalValueBehavior) const
326 {
327     return resolvedContentAlignmentDistribution(alignContent(), normalValueBehavior);
328 }
329
330 void RenderStyle::inheritFrom(const RenderStyle& inheritParent)
331 {
332     m_rareInheritedData = inheritParent.m_rareInheritedData;
333     m_inheritedData = inheritParent.m_inheritedData;
334     m_inheritedFlags = inheritParent.m_inheritedFlags;
335
336     if (m_svgStyle != inheritParent.m_svgStyle)
337         m_svgStyle.access().inheritFrom(inheritParent.m_svgStyle.get());
338 }
339
340 void RenderStyle::copyNonInheritedFrom(const RenderStyle& other)
341 {
342     m_boxData = other.m_boxData;
343     m_visualData = other.m_visualData;
344     m_backgroundData = other.m_backgroundData;
345     m_surroundData = other.m_surroundData;
346     m_rareNonInheritedData = other.m_rareNonInheritedData;
347     m_nonInheritedFlags.copyNonInheritedFrom(other.m_nonInheritedFlags);
348
349     if (m_svgStyle != other.m_svgStyle)
350         m_svgStyle.access().copyNonInheritedFrom(other.m_svgStyle.get());
351
352     ASSERT(zoom() == initialZoom());
353 }
354
355 void RenderStyle::copyContentFrom(const RenderStyle& other)
356 {
357     if (!other.m_rareNonInheritedData->content)
358         return;
359     m_rareNonInheritedData.access().content = other.m_rareNonInheritedData->content->clone();
360 }
361
362 bool RenderStyle::operator==(const RenderStyle& other) const
363 {
364     // compare everything except the pseudoStyle pointer
365     return m_inheritedFlags == other.m_inheritedFlags
366         && m_nonInheritedFlags == other.m_nonInheritedFlags
367         && m_boxData == other.m_boxData
368         && m_visualData == other.m_visualData
369         && m_backgroundData == other.m_backgroundData
370         && m_surroundData == other.m_surroundData
371         && m_rareNonInheritedData == other.m_rareNonInheritedData
372         && m_rareInheritedData == other.m_rareInheritedData
373         && m_inheritedData == other.m_inheritedData
374         && m_svgStyle == other.m_svgStyle;
375 }
376
377 bool RenderStyle::hasUniquePseudoStyle() const
378 {
379     if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
380         return false;
381
382     for (auto& pseudoStyle : *m_cachedPseudoStyles) {
383         if (pseudoStyle->unique())
384             return true;
385     }
386
387     return false;
388 }
389
390 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
391 {
392     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
393         return nullptr;
394
395     if (styleType() != NOPSEUDO) 
396         return nullptr;
397
398     for (auto& pseudoStyle : *m_cachedPseudoStyles) {
399         if (pseudoStyle->styleType() == pid)
400             return pseudoStyle.get();
401     }
402
403     return nullptr;
404 }
405
406 RenderStyle* RenderStyle::addCachedPseudoStyle(std::unique_ptr<RenderStyle> pseudo)
407 {
408     if (!pseudo)
409         return nullptr;
410
411     ASSERT(pseudo->styleType() > NOPSEUDO);
412
413     RenderStyle* result = pseudo.get();
414
415     if (!m_cachedPseudoStyles)
416         m_cachedPseudoStyles = std::make_unique<PseudoStyleCache>();
417
418     m_cachedPseudoStyles->append(WTFMove(pseudo));
419
420     return result;
421 }
422
423 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
424 {
425     if (!m_cachedPseudoStyles)
426         return;
427     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
428         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
429         if (pseudoStyle->styleType() == pid) {
430             m_cachedPseudoStyles->remove(i);
431             return;
432         }
433     }
434 }
435
436 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
437 {
438     return m_inheritedFlags != other->m_inheritedFlags
439         || m_inheritedData != other->m_inheritedData
440         || m_svgStyle->inheritedNotEqual(other->m_svgStyle)
441         || m_rareInheritedData != other->m_rareInheritedData;
442 }
443
444 #if ENABLE(TEXT_AUTOSIZING)
445
446 static inline unsigned computeFontHash(const FontCascade& font)
447 {
448     IntegerHasher hasher;
449     hasher.add(ASCIICaseInsensitiveHash::hash(font.fontDescription().firstFamily()));
450     hasher.add(font.fontDescription().specifiedSize());
451     return hasher.hash();
452 }
453
454 unsigned RenderStyle::hashForTextAutosizing() const
455 {
456     // FIXME: Not a very smart hash. Could be improved upon. See <https://bugs.webkit.org/show_bug.cgi?id=121131>.
457     unsigned hash = m_rareNonInheritedData->appearance;
458     hash ^= m_rareNonInheritedData->marginBeforeCollapse;
459     hash ^= m_rareNonInheritedData->marginAfterCollapse;
460     hash ^= m_rareNonInheritedData->lineClamp.value();
461     hash ^= m_rareInheritedData->overflowWrap;
462     hash ^= m_rareInheritedData->nbspMode;
463     hash ^= m_rareInheritedData->lineBreak;
464     hash ^= WTF::FloatHash<float>::hash(m_inheritedData->specifiedLineHeight.value());
465     hash ^= computeFontHash(m_inheritedData->fontCascade);
466     hash ^= WTF::FloatHash<float>::hash(m_inheritedData->horizontalBorderSpacing);
467     hash ^= WTF::FloatHash<float>::hash(m_inheritedData->verticalBorderSpacing);
468     hash ^= m_inheritedFlags.boxDirection;
469     hash ^= m_inheritedFlags.rtlOrdering;
470     hash ^= m_nonInheritedFlags.position;
471     hash ^= m_nonInheritedFlags.floating;
472     hash ^= m_rareNonInheritedData->textOverflow;
473     hash ^= m_rareInheritedData->textSecurity;
474     return hash;
475 }
476
477 bool RenderStyle::equalForTextAutosizing(const RenderStyle& other) const
478 {
479     return m_rareNonInheritedData->appearance == other.m_rareNonInheritedData->appearance
480         && m_rareNonInheritedData->marginBeforeCollapse == other.m_rareNonInheritedData->marginBeforeCollapse
481         && m_rareNonInheritedData->marginAfterCollapse == other.m_rareNonInheritedData->marginAfterCollapse
482         && m_rareNonInheritedData->lineClamp == other.m_rareNonInheritedData->lineClamp
483         && m_rareInheritedData->textSizeAdjust == other.m_rareInheritedData->textSizeAdjust
484         && m_rareInheritedData->overflowWrap == other.m_rareInheritedData->overflowWrap
485         && m_rareInheritedData->nbspMode == other.m_rareInheritedData->nbspMode
486         && m_rareInheritedData->lineBreak == other.m_rareInheritedData->lineBreak
487         && m_rareInheritedData->textSecurity == other.m_rareInheritedData->textSecurity
488         && m_inheritedData->specifiedLineHeight == other.m_inheritedData->specifiedLineHeight
489         && m_inheritedData->fontCascade.equalForTextAutoSizing(other.m_inheritedData->fontCascade)
490         && m_inheritedData->horizontalBorderSpacing == other.m_inheritedData->horizontalBorderSpacing
491         && m_inheritedData->verticalBorderSpacing == other.m_inheritedData->verticalBorderSpacing
492         && m_inheritedFlags.boxDirection == other.m_inheritedFlags.boxDirection
493         && m_inheritedFlags.rtlOrdering == other.m_inheritedFlags.rtlOrdering
494         && m_nonInheritedFlags.position == other.m_nonInheritedFlags.position
495         && m_nonInheritedFlags.floating == other.m_nonInheritedFlags.floating
496         && m_rareNonInheritedData->textOverflow == other.m_rareNonInheritedData->textOverflow;
497 }
498
499 #endif // ENABLE(TEXT_AUTOSIZING)
500
501 bool RenderStyle::inheritedDataShared(const RenderStyle* other) const
502 {
503     // This is a fast check that only looks if the data structures are shared.
504     return m_inheritedFlags == other->m_inheritedFlags
505         && m_inheritedData.ptr() == other->m_inheritedData.ptr()
506         && m_svgStyle.ptr() == other->m_svgStyle.ptr()
507         && m_rareInheritedData.ptr() == other->m_rareInheritedData.ptr();
508 }
509
510 static bool positionChangeIsMovementOnly(const LengthBox& a, const LengthBox& b, const Length& width)
511 {
512     // If any unit types are different, then we can't guarantee
513     // that this was just a movement.
514     if (a.left().type() != b.left().type()
515         || a.right().type() != b.right().type()
516         || a.top().type() != b.top().type()
517         || a.bottom().type() != b.bottom().type())
518         return false;
519
520     // Only one unit can be non-auto in the horizontal direction and
521     // in the vertical direction.  Otherwise the adjustment of values
522     // is changing the size of the box.
523     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
524         return false;
525     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
526         return false;
527     // If our width is auto and left or right is specified then this 
528     // is not just a movement - we need to resize to our container.
529     if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.isIntrinsicOrAuto())
530         return false;
531
532     // One of the units is fixed or percent in both directions and stayed
533     // that way in the new style.  Therefore all we are doing is moving.
534     return true;
535 }
536
537 inline bool RenderStyle::changeAffectsVisualOverflow(const RenderStyle& other) const
538 {
539     if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()
540         && !arePointingToEqualData(m_rareNonInheritedData->boxShadow, other.m_rareNonInheritedData->boxShadow))
541         return true;
542
543     if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()
544         && !arePointingToEqualData(m_rareInheritedData->textShadow, other.m_rareInheritedData->textShadow))
545         return true;
546
547     if (m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
548         || m_visualData->textDecoration != other.m_visualData->textDecoration
549         || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle) {
550         // Underlines are always drawn outside of their textbox bounds when text-underline-position: under;
551         // is specified. We can take an early out here.
552         if (textUnderlinePosition() == TextUnderlinePositionUnder
553             || other.textUnderlinePosition() == TextUnderlinePositionUnder)
554             return true;
555         return visualOverflowForDecorations(*this, nullptr) != visualOverflowForDecorations(other, nullptr);
556     }
557
558     if (hasOutlineInVisualOverflow() != other.hasOutlineInVisualOverflow())
559         return true;
560     return false;
561 }
562
563 bool RenderStyle::changeRequiresLayout(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
564 {
565     if (m_boxData->width() != other.m_boxData->width()
566         || m_boxData->minWidth() != other.m_boxData->minWidth()
567         || m_boxData->maxWidth() != other.m_boxData->maxWidth()
568         || m_boxData->height() != other.m_boxData->height()
569         || m_boxData->minHeight() != other.m_boxData->minHeight()
570         || m_boxData->maxHeight() != other.m_boxData->maxHeight())
571         return true;
572
573     if (m_boxData->verticalAlign() != other.m_boxData->verticalAlign() || m_nonInheritedFlags.verticalAlign != other.m_nonInheritedFlags.verticalAlign)
574         return true;
575
576     if (m_boxData->boxSizing() != other.m_boxData->boxSizing())
577         return true;
578
579     if (m_surroundData->margin != other.m_surroundData->margin)
580         return true;
581
582     if (m_surroundData->padding != other.m_surroundData->padding)
583         return true;
584
585     // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
586     if (changeAffectsVisualOverflow(other))
587         return true;
588
589     if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()) {
590         if (m_rareNonInheritedData->appearance != other.m_rareNonInheritedData->appearance
591             || m_rareNonInheritedData->marginBeforeCollapse != other.m_rareNonInheritedData->marginBeforeCollapse
592             || m_rareNonInheritedData->marginAfterCollapse != other.m_rareNonInheritedData->marginAfterCollapse
593             || m_rareNonInheritedData->lineClamp != other.m_rareNonInheritedData->lineClamp
594             || m_rareNonInheritedData->initialLetter != other.m_rareNonInheritedData->initialLetter
595             || m_rareNonInheritedData->textOverflow != other.m_rareNonInheritedData->textOverflow)
596             return true;
597
598         if (m_rareNonInheritedData->shapeMargin != other.m_rareNonInheritedData->shapeMargin)
599             return true;
600
601         if (m_rareNonInheritedData->deprecatedFlexibleBox != other.m_rareNonInheritedData->deprecatedFlexibleBox)
602             return true;
603
604         if (m_rareNonInheritedData->flexibleBox != other.m_rareNonInheritedData->flexibleBox)
605             return true;
606
607         if (m_rareNonInheritedData->order != other.m_rareNonInheritedData->order
608             || m_rareNonInheritedData->alignContent != other.m_rareNonInheritedData->alignContent
609             || m_rareNonInheritedData->alignItems != other.m_rareNonInheritedData->alignItems
610             || m_rareNonInheritedData->alignSelf != other.m_rareNonInheritedData->alignSelf
611             || m_rareNonInheritedData->justifyContent != other.m_rareNonInheritedData->justifyContent
612             || m_rareNonInheritedData->justifyItems != other.m_rareNonInheritedData->justifyItems
613             || m_rareNonInheritedData->justifySelf != other.m_rareNonInheritedData->justifySelf)
614             return true;
615
616         if (!arePointingToEqualData(m_rareNonInheritedData->boxReflect, other.m_rareNonInheritedData->boxReflect))
617             return true;
618
619         if (m_rareNonInheritedData->multiCol != other.m_rareNonInheritedData->multiCol)
620             return true;
621
622         if (m_rareNonInheritedData->transform != other.m_rareNonInheritedData->transform) {
623             if (m_rareNonInheritedData->transform->hasTransform() != other.m_rareNonInheritedData->transform->hasTransform())
624                 return true;
625             if (*m_rareNonInheritedData->transform != *other.m_rareNonInheritedData->transform) {
626                 changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
627                 // Don't return; keep looking for another change
628             }
629         }
630
631         if (m_rareNonInheritedData->grid != other.m_rareNonInheritedData->grid
632             || m_rareNonInheritedData->gridItem != other.m_rareNonInheritedData->gridItem)
633             return true;
634
635 #if ENABLE(DASHBOARD_SUPPORT)
636         // If regions change, trigger a relayout to re-calc regions.
637         if (m_rareNonInheritedData->dashboardRegions != other.m_rareNonInheritedData->dashboardRegions)
638             return true;
639 #endif
640
641         if (!arePointingToEqualData(m_rareNonInheritedData->willChange, other.m_rareNonInheritedData->willChange)) {
642             changedContextSensitiveProperties |= ContextSensitivePropertyWillChange;
643             // Don't return; keep looking for another change
644         }
645     }
646
647     if (m_rareInheritedData.ptr() != other.m_rareInheritedData.ptr()) {
648         if (m_rareInheritedData->indent != other.m_rareInheritedData->indent
649 #if ENABLE(CSS3_TEXT)
650             || m_rareInheritedData->textAlignLast != other.m_rareInheritedData->textAlignLast
651             || m_rareInheritedData->textJustify != other.m_rareInheritedData->textJustify
652             || m_rareInheritedData->textIndentLine != other.m_rareInheritedData->textIndentLine
653 #endif
654             || m_rareInheritedData->effectiveZoom != other.m_rareInheritedData->effectiveZoom
655             || m_rareInheritedData->textZoom != other.m_rareInheritedData->textZoom
656 #if ENABLE(TEXT_AUTOSIZING)
657             || m_rareInheritedData->textSizeAdjust != other.m_rareInheritedData->textSizeAdjust
658 #endif
659             || m_rareInheritedData->wordBreak != other.m_rareInheritedData->wordBreak
660             || m_rareInheritedData->overflowWrap != other.m_rareInheritedData->overflowWrap
661             || m_rareInheritedData->nbspMode != other.m_rareInheritedData->nbspMode
662             || m_rareInheritedData->lineBreak != other.m_rareInheritedData->lineBreak
663             || m_rareInheritedData->textSecurity != other.m_rareInheritedData->textSecurity
664             || m_rareInheritedData->hyphens != other.m_rareInheritedData->hyphens
665             || m_rareInheritedData->hyphenationLimitBefore != other.m_rareInheritedData->hyphenationLimitBefore
666             || m_rareInheritedData->hyphenationLimitAfter != other.m_rareInheritedData->hyphenationLimitAfter
667             || m_rareInheritedData->hyphenationString != other.m_rareInheritedData->hyphenationString
668             || m_rareInheritedData->rubyPosition != other.m_rareInheritedData->rubyPosition
669             || m_rareInheritedData->textEmphasisMark != other.m_rareInheritedData->textEmphasisMark
670             || m_rareInheritedData->textEmphasisPosition != other.m_rareInheritedData->textEmphasisPosition
671             || m_rareInheritedData->textEmphasisCustomMark != other.m_rareInheritedData->textEmphasisCustomMark
672             || m_rareInheritedData->textOrientation != other.m_rareInheritedData->textOrientation
673             || m_rareInheritedData->tabSize != other.m_rareInheritedData->tabSize
674             || m_rareInheritedData->lineBoxContain != other.m_rareInheritedData->lineBoxContain
675             || m_rareInheritedData->lineGrid != other.m_rareInheritedData->lineGrid
676 #if ENABLE(CSS_IMAGE_ORIENTATION)
677             || m_rareInheritedData->imageOrientation != other.m_rareInheritedData->imageOrientation
678 #endif
679 #if ENABLE(CSS_IMAGE_RESOLUTION)
680             || m_rareInheritedData->imageResolutionSource != other.m_rareInheritedData->imageResolutionSource
681             || m_rareInheritedData->imageResolutionSnap != other.m_rareInheritedData->imageResolutionSnap
682             || m_rareInheritedData->imageResolution != other.m_rareInheritedData->imageResolution
683 #endif
684             || m_rareInheritedData->lineSnap != other.m_rareInheritedData->lineSnap
685             || m_rareInheritedData->lineAlign != other.m_rareInheritedData->lineAlign
686             || m_rareInheritedData->hangingPunctuation != other.m_rareInheritedData->hangingPunctuation
687 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
688             || m_rareInheritedData->useTouchOverflowScrolling != other.m_rareInheritedData->useTouchOverflowScrolling
689 #endif
690             || m_rareInheritedData->listStyleImage != other.m_rareInheritedData->listStyleImage) // FIXME: needs arePointingToEqualData()?
691             return true;
692
693         if (textStrokeWidth() != other.textStrokeWidth())
694             return true;
695         
696         // These properties affect the cached stroke bounding box rects.
697         if (m_rareInheritedData->capStyle != other.m_rareInheritedData->capStyle
698             || m_rareInheritedData->joinStyle != other.m_rareInheritedData->joinStyle
699             || m_rareInheritedData->strokeWidth != other.m_rareInheritedData->strokeWidth
700             || m_rareInheritedData->miterLimit != other.m_rareInheritedData->miterLimit)
701             return true;
702     }
703
704     if (m_inheritedData->lineHeight != other.m_inheritedData->lineHeight
705 #if ENABLE(TEXT_AUTOSIZING)
706         || m_inheritedData->specifiedLineHeight != other.m_inheritedData->specifiedLineHeight
707 #endif
708         || m_inheritedData->fontCascade != other.m_inheritedData->fontCascade
709         || m_inheritedData->horizontalBorderSpacing != other.m_inheritedData->horizontalBorderSpacing
710         || m_inheritedData->verticalBorderSpacing != other.m_inheritedData->verticalBorderSpacing
711         || m_inheritedFlags.boxDirection != other.m_inheritedFlags.boxDirection
712         || m_inheritedFlags.rtlOrdering != other.m_inheritedFlags.rtlOrdering
713         || m_nonInheritedFlags.position != other.m_nonInheritedFlags.position
714         || m_nonInheritedFlags.floating != other.m_nonInheritedFlags.floating
715         || m_nonInheritedFlags.originalDisplay != other.m_nonInheritedFlags.originalDisplay)
716         return true;
717
718
719     if (m_nonInheritedFlags.effectiveDisplay >= TABLE) {
720         if (m_inheritedFlags.borderCollapse != other.m_inheritedFlags.borderCollapse
721             || m_inheritedFlags.emptyCells != other.m_inheritedFlags.emptyCells
722             || m_inheritedFlags.captionSide != other.m_inheritedFlags.captionSide
723             || m_nonInheritedFlags.tableLayout != other.m_nonInheritedFlags.tableLayout)
724             return true;
725
726         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
727         // does not, so these style differences can be width differences.
728         if (m_inheritedFlags.borderCollapse
729             && ((borderTopStyle() == BHIDDEN && other.borderTopStyle() == BNONE)
730                 || (borderTopStyle() == BNONE && other.borderTopStyle() == BHIDDEN)
731                 || (borderBottomStyle() == BHIDDEN && other.borderBottomStyle() == BNONE)
732                 || (borderBottomStyle() == BNONE && other.borderBottomStyle() == BHIDDEN)
733                 || (borderLeftStyle() == BHIDDEN && other.borderLeftStyle() == BNONE)
734                 || (borderLeftStyle() == BNONE && other.borderLeftStyle() == BHIDDEN)
735                 || (borderRightStyle() == BHIDDEN && other.borderRightStyle() == BNONE)
736                 || (borderRightStyle() == BNONE && other.borderRightStyle() == BHIDDEN)))
737             return true;
738     }
739
740     if (m_nonInheritedFlags.effectiveDisplay == LIST_ITEM) {
741         if (m_inheritedFlags.listStyleType != other.m_inheritedFlags.listStyleType
742             || m_inheritedFlags.listStylePosition != other.m_inheritedFlags.listStylePosition)
743             return true;
744     }
745
746     if (m_inheritedFlags.textAlign != other.m_inheritedFlags.textAlign
747         || m_inheritedFlags.textTransform != other.m_inheritedFlags.textTransform
748         || m_inheritedFlags.direction != other.m_inheritedFlags.direction
749         || m_inheritedFlags.whiteSpace != other.m_inheritedFlags.whiteSpace
750         || m_nonInheritedFlags.clear != other.m_nonInheritedFlags.clear
751         || m_nonInheritedFlags.unicodeBidi != other.m_nonInheritedFlags.unicodeBidi)
752         return true;
753
754     // Check block flow direction.
755     if (m_inheritedFlags.writingMode != other.m_inheritedFlags.writingMode)
756         return true;
757
758     // Check text combine mode.
759     if (m_rareNonInheritedData->textCombine != other.m_rareNonInheritedData->textCombine)
760         return true;
761
762     // Check breaks.
763     if (m_rareNonInheritedData->breakBefore != other.m_rareNonInheritedData->breakBefore
764         || m_rareNonInheritedData->breakAfter != other.m_rareNonInheritedData->breakAfter
765         || m_rareNonInheritedData->breakInside != other.m_rareNonInheritedData->breakInside)
766         return true;
767
768     // Overflow returns a layout hint.
769     if (m_nonInheritedFlags.overflowX != other.m_nonInheritedFlags.overflowX
770         || m_nonInheritedFlags.overflowY != other.m_nonInheritedFlags.overflowY)
771         return true;
772
773     // If our border widths change, then we need to layout.  Other changes to borders
774     // only necessitate a repaint.
775     if (borderLeftWidth() != other.borderLeftWidth()
776         || borderTopWidth() != other.borderTopWidth()
777         || borderBottomWidth() != other.borderBottomWidth()
778         || borderRightWidth() != other.borderRightWidth())
779         return true;
780
781     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
782     if (!arePointingToEqualData(m_rareNonInheritedData->counterDirectives, other.m_rareNonInheritedData->counterDirectives))
783         return true;
784
785     if ((visibility() == COLLAPSE) != (other.visibility() == COLLAPSE))
786         return true;
787
788     if (m_rareNonInheritedData->hasOpacity() != other.m_rareNonInheritedData->hasOpacity()) {
789         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
790         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
791         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
792         // In addition we need to solve the floating object issue when layers come and go. Right now
793         // a full layout is necessary to keep floating object lists sane.
794         return true;
795     }
796
797     if (m_rareNonInheritedData->hasFilters() != other.m_rareNonInheritedData->hasFilters())
798         return true;
799
800 #if ENABLE(FILTERS_LEVEL_2)
801     if (m_rareNonInheritedData->hasBackdropFilters() != other.m_rareNonInheritedData->hasBackdropFilters())
802         return true;
803 #endif
804
805     if (!arePointingToEqualData(m_rareInheritedData->quotes, other.m_rareInheritedData->quotes))
806         return true;
807
808     if (position() != StaticPosition) {
809         if (m_surroundData->offset != other.m_surroundData->offset) {
810             // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
811             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
812             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
813             if (position() != AbsolutePosition)
814                 return true;
815
816             // Optimize for the case where a positioned layer is moving but not changing size.
817             if (!positionChangeIsMovementOnly(m_surroundData->offset, other.m_surroundData->offset, m_boxData->width()))
818                 return true;
819         }
820     }
821
822     bool hasFirstLineStyle = hasPseudoStyle(FIRST_LINE);
823     if (hasFirstLineStyle != other.hasPseudoStyle(FIRST_LINE))
824         return true;
825     if (hasFirstLineStyle) {
826         auto* firstLineStyle = getCachedPseudoStyle(FIRST_LINE);
827         if (!firstLineStyle)
828             return true;
829         auto* otherFirstLineStyle = other.getCachedPseudoStyle(FIRST_LINE);
830         if (!otherFirstLineStyle)
831             return true;
832         // FIXME: Not all first line style changes actually need layout.
833         if (*firstLineStyle != *otherFirstLineStyle)
834             return true;
835     }
836
837     return false;
838 }
839
840 bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle& other, unsigned&) const
841 {
842     if (position() == StaticPosition)
843         return false;
844
845     if (m_surroundData->offset != other.m_surroundData->offset) {
846         // Optimize for the case where a positioned layer is moving but not changing size.
847         if (position() == AbsolutePosition && positionChangeIsMovementOnly(m_surroundData->offset, other.m_surroundData->offset, m_boxData->width()))
848             return true;
849     }
850     
851     return false;
852 }
853
854 bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
855 {
856     // StyleResolver has ensured that zIndex is non-auto only if it's applicable.
857     if (m_boxData->zIndex() != other.m_boxData->zIndex() || m_boxData->hasAutoZIndex() != other.m_boxData->hasAutoZIndex())
858         return true;
859
860     if (position() != StaticPosition) {
861         if (m_visualData->clip != other.m_visualData->clip || m_visualData->hasClip != other.m_visualData->hasClip) {
862             changedContextSensitiveProperties |= ContextSensitivePropertyClipRect;
863             return true;
864         }
865     }
866
867 #if ENABLE(CSS_COMPOSITING)
868     if (m_rareNonInheritedData->effectiveBlendMode != other.m_rareNonInheritedData->effectiveBlendMode)
869         return true;
870 #endif
871
872     if (m_rareNonInheritedData->opacity != other.m_rareNonInheritedData->opacity) {
873         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
874         // Don't return; keep looking for another change.
875     }
876
877     if (m_rareNonInheritedData->filter != other.m_rareNonInheritedData->filter) {
878         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
879         // Don't return; keep looking for another change.
880     }
881
882 #if ENABLE(FILTERS_LEVEL_2)
883     if (m_rareNonInheritedData->backdropFilter != other.m_rareNonInheritedData->backdropFilter) {
884         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
885         // Don't return; keep looking for another change.
886     }
887 #endif
888
889     if (m_rareNonInheritedData->mask != other.m_rareNonInheritedData->mask
890         || m_rareNonInheritedData->maskBoxImage != other.m_rareNonInheritedData->maskBoxImage)
891         return true;
892
893     return false;
894 }
895
896 static bool requiresPainting(const RenderStyle& style)
897 {
898     if (style.visibility() == HIDDEN)
899         return false;
900     if (!style.opacity())
901         return false;
902     return true;
903 }
904
905 bool RenderStyle::changeRequiresRepaint(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
906 {
907     if (!requiresPainting(*this) && !requiresPainting(other))
908         return false;
909
910     if (m_inheritedFlags.visibility != other.m_inheritedFlags.visibility
911         || m_inheritedFlags.printColorAdjust != other.m_inheritedFlags.printColorAdjust
912         || m_inheritedFlags.insideLink != other.m_inheritedFlags.insideLink
913         || m_inheritedFlags.insideDefaultButton != other.m_inheritedFlags.insideDefaultButton
914         || m_surroundData->border != other.m_surroundData->border
915         || !m_backgroundData->isEquivalentForPainting(*other.m_backgroundData)
916         || m_rareInheritedData->userModify != other.m_rareInheritedData->userModify
917         || m_rareInheritedData->userSelect != other.m_rareInheritedData->userSelect
918         || m_rareNonInheritedData->userDrag != other.m_rareNonInheritedData->userDrag
919         || m_rareNonInheritedData->borderFit != other.m_rareNonInheritedData->borderFit
920         || m_rareNonInheritedData->objectFit != other.m_rareNonInheritedData->objectFit
921         || m_rareNonInheritedData->objectPosition != other.m_rareNonInheritedData->objectPosition
922         || m_rareInheritedData->imageRendering != other.m_rareInheritedData->imageRendering)
923         return true;
924
925     if (m_rareNonInheritedData->isNotFinal != other.m_rareNonInheritedData->isNotFinal)
926         return true;
927
928     if (m_rareNonInheritedData->shapeOutside != other.m_rareNonInheritedData->shapeOutside)
929         return true;
930
931     // FIXME: this should probably be moved to changeRequiresLayerRepaint().
932     if (m_rareNonInheritedData->clipPath != other.m_rareNonInheritedData->clipPath) {
933         changedContextSensitiveProperties |= ContextSensitivePropertyClipPath;
934         // Don't return; keep looking for another change.
935     }
936
937     return false;
938 }
939
940 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, unsigned&) const
941 {
942     if (m_inheritedData->color != other.m_inheritedData->color
943         || m_inheritedFlags.textDecorations != other.m_inheritedFlags.textDecorations
944         || m_visualData->textDecoration != other.m_visualData->textDecoration
945         || m_rareNonInheritedData->textDecorationStyle != other.m_rareNonInheritedData->textDecorationStyle
946         || m_rareNonInheritedData->textDecorationColor != other.m_rareNonInheritedData->textDecorationColor
947         || m_rareInheritedData->textDecorationSkip != other.m_rareInheritedData->textDecorationSkip
948         || m_rareInheritedData->textFillColor != other.m_rareInheritedData->textFillColor
949         || m_rareInheritedData->textStrokeColor != other.m_rareInheritedData->textStrokeColor
950         || m_rareInheritedData->textEmphasisColor != other.m_rareInheritedData->textEmphasisColor
951         || m_rareInheritedData->textEmphasisFill != other.m_rareInheritedData->textEmphasisFill
952         || m_rareInheritedData->strokeColor != other.m_rareInheritedData->strokeColor
953         || m_rareInheritedData->caretColor != other.m_rareInheritedData->caretColor)
954         return true;
955
956     return false;
957 }
958
959 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, unsigned&) const
960 {
961     if (m_rareNonInheritedData.ptr() != other.m_rareNonInheritedData.ptr()) {
962         if (m_rareNonInheritedData->transformStyle3D != other.m_rareNonInheritedData->transformStyle3D
963             || m_rareNonInheritedData->backfaceVisibility != other.m_rareNonInheritedData->backfaceVisibility
964             || m_rareNonInheritedData->perspective != other.m_rareNonInheritedData->perspective
965             || m_rareNonInheritedData->perspectiveOriginX != other.m_rareNonInheritedData->perspectiveOriginX
966             || m_rareNonInheritedData->perspectiveOriginY != other.m_rareNonInheritedData->perspectiveOriginY)
967             return true;
968     }
969
970     return false;
971 }
972
973 StyleDifference RenderStyle::diff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
974 {
975     changedContextSensitiveProperties = ContextSensitivePropertyNone;
976
977     StyleDifference svgChange = StyleDifferenceEqual;
978     if (m_svgStyle != other.m_svgStyle) {
979         svgChange = m_svgStyle->diff(other.m_svgStyle.get());
980         if (svgChange == StyleDifferenceLayout)
981             return svgChange;
982     }
983
984     if (changeRequiresLayout(other, changedContextSensitiveProperties))
985         return StyleDifferenceLayout;
986
987     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
988     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
989     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
990     // that are relevant for SVG and might return StyleDifferenceLayout.
991     if (svgChange != StyleDifferenceEqual)
992         return svgChange;
993
994     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
995         return StyleDifferenceLayoutPositionedMovementOnly;
996
997     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
998         return StyleDifferenceRepaintLayer;
999
1000     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
1001         return StyleDifferenceRepaint;
1002
1003     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
1004         return StyleDifferenceRecompositeLayer;
1005
1006     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
1007         return StyleDifferenceRepaintIfTextOrBorderOrOutline;
1008
1009     // Cursors are not checked, since they will be set appropriately in response to mouse events,
1010     // so they don't need to cause any repaint or layout.
1011
1012     // Animations don't need to be checked either.  We always set the new style on the RenderObject, so we will get a chance to fire off
1013     // the resulting transition properly.
1014     return StyleDifferenceEqual;
1015 }
1016
1017 bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const
1018 {
1019     unsigned changedContextSensitiveProperties = 0;
1020
1021     if (changeRequiresRepaint(style, changedContextSensitiveProperties))
1022         return true;
1023
1024     if (isComposited && changeRequiresLayerRepaint(style, changedContextSensitiveProperties))
1025         return changedContextSensitiveProperties & ContextSensitivePropertyClipRect;
1026
1027     return false;
1028 }
1029
1030 void RenderStyle::setClip(Length&& top, Length&& right, Length&& bottom, Length&& left)
1031 {
1032     auto& data = m_visualData.access();
1033     data.clip.top() = WTFMove(top);
1034     data.clip.right() = WTFMove(right);
1035     data.clip.bottom() = WTFMove(bottom);
1036     data.clip.left() = WTFMove(left);
1037 }
1038
1039 void RenderStyle::addCursor(RefPtr<StyleImage>&& image, const IntPoint& hotSpot)
1040 {
1041     auto& cursorData = m_rareInheritedData.access().cursorData;
1042     if (!cursorData)
1043         cursorData = CursorList::create();
1044     cursorData->append(CursorData(WTFMove(image), hotSpot));
1045 }
1046
1047 void RenderStyle::setCursorList(RefPtr<CursorList>&& list)
1048 {
1049     m_rareInheritedData.access().cursorData = WTFMove(list);
1050 }
1051
1052 void RenderStyle::setQuotes(RefPtr<QuotesData>&& q)
1053 {
1054     if (m_rareInheritedData->quotes == q || (m_rareInheritedData->quotes && q && *m_rareInheritedData->quotes == *q))
1055         return;
1056
1057     m_rareInheritedData.access().quotes = WTFMove(q);
1058 }
1059
1060 void RenderStyle::setWillChange(RefPtr<WillChangeData>&& willChangeData)
1061 {
1062     if (arePointingToEqualData(m_rareNonInheritedData->willChange.get(), willChangeData.get()))
1063         return;
1064
1065     m_rareNonInheritedData.access().willChange = WTFMove(willChangeData);
1066 }
1067
1068 void RenderStyle::clearCursorList()
1069 {
1070     if (m_rareInheritedData->cursorData)
1071         m_rareInheritedData.access().cursorData = nullptr;
1072 }
1073
1074 void RenderStyle::clearContent()
1075 {
1076     if (m_rareNonInheritedData->content)
1077         m_rareNonInheritedData.access().content = nullptr;
1078 }
1079
1080 static inline ContentData& lastContent(ContentData& firstContent)
1081 {
1082     auto* lastContent = &firstContent;
1083     for (auto* content = &firstContent; content; content = content->next())
1084         lastContent = content;
1085     return *lastContent;
1086 }
1087
1088 void RenderStyle::setContent(std::unique_ptr<ContentData> contentData, bool add)
1089 {
1090     auto& data = m_rareNonInheritedData.access();
1091     if (add && data.content)
1092         lastContent(*data.content).setNext(WTFMove(contentData));
1093     else {
1094         data.content = WTFMove(contentData);
1095         auto& altText = data.altText;
1096         if (!altText.isNull())
1097             data.content->setAltText(altText);
1098     }
1099 }
1100
1101 void RenderStyle::setContent(RefPtr<StyleImage>&& image, bool add)
1102 {
1103     if (!image)
1104         return;
1105     setContent(std::make_unique<ImageContentData>(image.releaseNonNull()), add);
1106 }
1107
1108 void RenderStyle::setContent(const String& string, bool add)
1109 {
1110     auto& data = m_rareNonInheritedData.access();
1111     if (add && data.content) {
1112         auto& last = lastContent(*data.content);
1113         if (!is<TextContentData>(last))
1114             last.setNext(std::make_unique<TextContentData>(string));
1115         else {
1116             auto& textContent = downcast<TextContentData>(last);
1117             textContent.setText(textContent.text() + string);
1118         }
1119     } else {
1120         data.content = std::make_unique<TextContentData>(string);
1121         auto& altText = data.altText;
1122         if (!altText.isNull())
1123             data.content->setAltText(altText);
1124     }
1125 }
1126
1127 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
1128 {
1129     if (!counter)
1130         return;
1131     setContent(std::make_unique<CounterContentData>(WTFMove(counter)), add);
1132 }
1133
1134 void RenderStyle::setContent(QuoteType quote, bool add)
1135 {
1136     setContent(std::make_unique<QuoteContentData>(quote), add);
1137 }
1138
1139 void RenderStyle::setContentAltText(const String& string)
1140 {
1141     auto& data = m_rareNonInheritedData.access();
1142     data.altText = string;
1143     if (data.content)
1144         data.content->setAltText(string);
1145 }
1146
1147 const String& RenderStyle::contentAltText() const
1148 {
1149     return m_rareNonInheritedData->altText;
1150 }
1151
1152 void RenderStyle::setHasAttrContent()
1153 {
1154     setUnique();
1155     SET_VAR(m_rareNonInheritedData, hasAttrContent, true);
1156 }
1157
1158 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
1159 {
1160     // The transform-origin property brackets the transform with translate operations.
1161     // When the only transform is a translation, the transform-origin is irrelevant.
1162
1163     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
1164         return false;
1165
1166     for (auto& operation : transformOperations) {
1167         // FIXME: Use affectedByTransformOrigin().
1168         auto type = operation->type();
1169         if (type != TransformOperation::TRANSLATE
1170             && type != TransformOperation::TRANSLATE_3D
1171             && type != TransformOperation::TRANSLATE_X
1172             && type != TransformOperation::TRANSLATE_Y
1173             && type != TransformOperation::TRANSLATE_Z)
1174             return true;
1175     }
1176
1177     return false;
1178 }
1179
1180 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
1181 {
1182     auto& operations = m_rareNonInheritedData->transform->operations.operations();
1183     bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
1184     
1185     FloatPoint3D originTranslate;
1186     if (applyTransformOrigin) {
1187         originTranslate.setX(boundingBox.x() + floatValueForLength(transformOriginX(), boundingBox.width()));
1188         originTranslate.setY(boundingBox.y() + floatValueForLength(transformOriginY(), boundingBox.height()));
1189         originTranslate.setZ(transformOriginZ());
1190         transform.translate3d(originTranslate.x(), originTranslate.y(), originTranslate.z());
1191     }
1192
1193     for (auto& operation : operations)
1194         operation->apply(transform, boundingBox.size());
1195
1196     if (applyTransformOrigin)
1197         transform.translate3d(-originTranslate.x(), -originTranslate.y(), -originTranslate.z());
1198 }
1199
1200 void RenderStyle::setPageScaleTransform(float scale)
1201 {
1202     if (scale == 1)
1203         return;
1204     TransformOperations transform;
1205     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
1206     setTransform(transform);
1207     setTransformOriginX(Length(0, Fixed));
1208     setTransformOriginY(Length(0, Fixed));
1209 }
1210
1211 void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1212 {
1213     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
1214
1215     auto& rareData = m_rareInheritedData.access();
1216     if (!add) {
1217         rareData.textShadow = WTFMove(shadowData);
1218         return;
1219     }
1220
1221     shadowData->setNext(WTFMove(rareData.textShadow));
1222     rareData.textShadow = WTFMove(shadowData);
1223 }
1224
1225 void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1226 {
1227     auto& rareData = m_rareNonInheritedData.access();
1228     if (!add) {
1229         rareData.boxShadow = WTFMove(shadowData);
1230         return;
1231     }
1232
1233     shadowData->setNext(WTFMove(rareData.boxShadow));
1234     rareData.boxShadow = WTFMove(shadowData);
1235 }
1236
1237 static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size)
1238 {
1239     return {
1240         sizeForLengthSize(border.topLeft(), size),
1241         sizeForLengthSize(border.topRight(), size),
1242         sizeForLengthSize(border.bottomLeft(), size),
1243         sizeForLengthSize(border.bottomRight(), size)
1244     };
1245 }
1246
1247 StyleImage* RenderStyle::listStyleImage() const
1248 {
1249     return m_rareInheritedData->listStyleImage.get();
1250 }
1251
1252 void RenderStyle::setListStyleImage(RefPtr<StyleImage>&& v)
1253 {
1254     if (m_rareInheritedData->listStyleImage != v)
1255         m_rareInheritedData.access().listStyleImage = WTFMove(v);
1256 }
1257
1258 const Color& RenderStyle::color() const
1259 {
1260     return m_inheritedData->color;
1261 }
1262
1263 const Color& RenderStyle::visitedLinkColor() const
1264 {
1265     return m_inheritedData->visitedLinkColor;
1266 }
1267
1268 void RenderStyle::setColor(const Color& v)
1269 {
1270     SET_VAR(m_inheritedData, color, v);
1271 }
1272
1273 void RenderStyle::setVisitedLinkColor(const Color& v)
1274 {
1275     SET_VAR(m_inheritedData, visitedLinkColor, v);
1276 }
1277
1278 float RenderStyle::horizontalBorderSpacing() const
1279 {
1280     return m_inheritedData->horizontalBorderSpacing;
1281 }
1282
1283 float RenderStyle::verticalBorderSpacing() const
1284 {
1285     return m_inheritedData->verticalBorderSpacing;
1286 }
1287
1288 void RenderStyle::setHorizontalBorderSpacing(float v)
1289 {
1290     SET_VAR(m_inheritedData, horizontalBorderSpacing, v);
1291 }
1292
1293 void RenderStyle::setVerticalBorderSpacing(float v)
1294 {
1295     SET_VAR(m_inheritedData, verticalBorderSpacing, v);
1296 }
1297
1298 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1299 {
1300     RoundedRect roundedRect(borderRect);
1301     if (hasBorderRadius()) {
1302         RoundedRect::Radii radii = calcRadiiFor(m_surroundData->border, borderRect.size());
1303         radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
1304         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1305     }
1306     return roundedRect;
1307 }
1308
1309 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1310 {
1311     bool horizontal = isHorizontalWritingMode();
1312     auto leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1313     auto rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1314     auto topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1315     auto bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1316     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1317 }
1318
1319 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
1320     LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1321 {
1322     RoundedRect roundedRect { { borderRect.x() + leftWidth, borderRect.y() + topWidth,
1323         borderRect.width() - leftWidth - rightWidth, borderRect.height() - topWidth - bottomWidth } };
1324     if (hasBorderRadius()) {
1325         auto radii = getRoundedBorderFor(borderRect).radii();
1326         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1327         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1328     }
1329     return roundedRect;
1330 }
1331
1332 static bool allLayersAreFixed(const FillLayer& layers)
1333 {
1334     for (auto* layer = &layers; layer; layer = layer->next()) {
1335         if (!(layer->image() && layer->attachment() == FixedBackgroundAttachment))
1336             return false;
1337     }
1338     return true;
1339 }
1340
1341 bool RenderStyle::hasEntirelyFixedBackground() const
1342 {
1343     return allLayersAreFixed(backgroundLayers());
1344 }
1345
1346 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1347 {
1348     return m_rareNonInheritedData->counterDirectives.get();
1349 }
1350
1351 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1352 {
1353     auto& map = m_rareNonInheritedData.access().counterDirectives;
1354     if (!map)
1355         map = std::make_unique<CounterDirectiveMap>();
1356     return *map;
1357 }
1358
1359 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1360 {
1361     if (const CounterDirectiveMap* directives = counterDirectives())
1362         return directives->get(identifier);
1363     return CounterDirectives();
1364 }
1365
1366 const AtomicString& RenderStyle::hyphenString() const
1367 {
1368     ASSERT(hyphens() != HyphensNone);
1369
1370     auto& hyphenationString = m_rareInheritedData->hyphenationString;
1371     if (!hyphenationString.isNull())
1372         return hyphenationString;
1373
1374     // FIXME: This should depend on locale.
1375     static NeverDestroyed<AtomicString> hyphenMinusString(&hyphenMinus, 1);
1376     static NeverDestroyed<AtomicString> hyphenString(&hyphen, 1);
1377     return fontCascade().primaryFont().glyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1378 }
1379
1380 const AtomicString& RenderStyle::textEmphasisMarkString() const
1381 {
1382     switch (textEmphasisMark()) {
1383     case TextEmphasisMarkNone:
1384         return nullAtom();
1385     case TextEmphasisMarkCustom:
1386         return textEmphasisCustomMark();
1387     case TextEmphasisMarkDot: {
1388         static NeverDestroyed<AtomicString> filledDotString(&bullet, 1);
1389         static NeverDestroyed<AtomicString> openDotString(&whiteBullet, 1);
1390         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1391     }
1392     case TextEmphasisMarkCircle: {
1393         static NeverDestroyed<AtomicString> filledCircleString(&blackCircle, 1);
1394         static NeverDestroyed<AtomicString> openCircleString(&whiteCircle, 1);
1395         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1396     }
1397     case TextEmphasisMarkDoubleCircle: {
1398         static NeverDestroyed<AtomicString> filledDoubleCircleString(&fisheye, 1);
1399         static NeverDestroyed<AtomicString> openDoubleCircleString(&bullseye, 1);
1400         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1401     }
1402     case TextEmphasisMarkTriangle: {
1403         static NeverDestroyed<AtomicString> filledTriangleString(&blackUpPointingTriangle, 1);
1404         static NeverDestroyed<AtomicString> openTriangleString(&whiteUpPointingTriangle, 1);
1405         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1406     }
1407     case TextEmphasisMarkSesame: {
1408         static NeverDestroyed<AtomicString> filledSesameString(&sesameDot, 1);
1409         static NeverDestroyed<AtomicString> openSesameString(&whiteSesameDot, 1);
1410         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1411     }
1412     case TextEmphasisMarkAuto:
1413         ASSERT_NOT_REACHED();
1414         return nullAtom();
1415     }
1416
1417     ASSERT_NOT_REACHED();
1418     return nullAtom();
1419 }
1420
1421 #if ENABLE(DASHBOARD_SUPPORT)
1422
1423 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1424 {
1425     static NeverDestroyed<Vector<StyleDashboardRegion>> emptyList;
1426     return emptyList;
1427 }
1428
1429 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1430 {
1431     static NeverDestroyed<Vector<StyleDashboardRegion>> noneList;
1432     static bool noneListInitialized = false;
1433     if (!noneListInitialized) {
1434         noneList.get().append(StyleDashboardRegion { emptyString(), { }, StyleDashboardRegion::None });
1435         noneListInitialized = true;
1436     }
1437     return noneList;
1438 }
1439
1440 #endif
1441
1442 void RenderStyle::adjustAnimations()
1443 {
1444     auto* animationList = m_rareNonInheritedData->animations.get();
1445     if (!animationList)
1446         return;
1447
1448     // Get rid of empty animations and anything beyond them
1449     for (size_t i = 0, size = animationList->size(); i < size; ++i) {
1450         if (animationList->animation(i).isEmpty()) {
1451             animationList->resize(i);
1452             break;
1453         }
1454     }
1455
1456     if (animationList->isEmpty()) {
1457         clearAnimations();
1458         return;
1459     }
1460
1461     // Repeat patterns into layers that don't have some properties set.
1462     animationList->fillUnsetProperties();
1463 }
1464
1465 void RenderStyle::adjustTransitions()
1466 {
1467     auto* transitionList = m_rareNonInheritedData->transitions.get();
1468     if (!transitionList)
1469         return;
1470
1471     // Get rid of empty transitions and anything beyond them
1472     for (size_t i = 0, size = transitionList->size(); i < size; ++i) {
1473         if (transitionList->animation(i).isEmpty()) {
1474             transitionList->resize(i);
1475             break;
1476         }
1477     }
1478
1479     if (transitionList->isEmpty()) {
1480         clearTransitions();
1481         return;
1482     }
1483
1484     // Repeat patterns into layers that don't have some properties set.
1485     transitionList->fillUnsetProperties();
1486
1487     // Make sure there are no duplicate properties.
1488     // This is an O(n^2) algorithm but the lists tend to be short, so it is probably OK.
1489     for (size_t i = 0; i < transitionList->size(); ++i) {
1490         for (size_t j = i + 1; j < transitionList->size(); ++j) {
1491             if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1492                 // toss i
1493                 transitionList->remove(i);
1494                 j = i;
1495             }
1496         }
1497     }
1498 }
1499
1500 AnimationList& RenderStyle::ensureAnimations()
1501 {
1502     if (!m_rareNonInheritedData.access().animations)
1503         m_rareNonInheritedData.access().animations = std::make_unique<AnimationList>();
1504     return *m_rareNonInheritedData->animations;
1505 }
1506
1507 AnimationList& RenderStyle::ensureTransitions()
1508 {
1509     if (!m_rareNonInheritedData.access().transitions)
1510         m_rareNonInheritedData.access().transitions = std::make_unique<AnimationList>();
1511     return *m_rareNonInheritedData->transitions;
1512 }
1513
1514 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1515 {
1516     auto* transitions = this->transitions();
1517     if (!transitions)
1518         return nullptr;
1519     for (size_t i = 0, size = transitions->size(); i < size; ++i) {
1520         auto& animation = transitions->animation(i);
1521         if (animation.animationMode() == Animation::AnimateAll || animation.property() == property)
1522             return &animation;
1523     }
1524     return nullptr;
1525 }
1526
1527 const FontCascade& RenderStyle::fontCascade() const
1528 {
1529     return m_inheritedData->fontCascade;
1530 }
1531
1532 const FontMetrics& RenderStyle::fontMetrics() const
1533 {
1534     return m_inheritedData->fontCascade.fontMetrics();
1535 }
1536
1537 const FontCascadeDescription& RenderStyle::fontDescription() const
1538 {
1539     return m_inheritedData->fontCascade.fontDescription();
1540 }
1541
1542 float RenderStyle::specifiedFontSize() const
1543 {
1544     return fontDescription().specifiedSize();
1545 }
1546
1547 float RenderStyle::computedFontSize() const
1548 {
1549     return fontDescription().computedSize();
1550 }
1551
1552 unsigned RenderStyle::computedFontPixelSize() const
1553 {
1554     return fontDescription().computedPixelSize();
1555 }
1556
1557 const Length& RenderStyle::wordSpacing() const
1558 {
1559     return m_rareInheritedData->wordSpacing;
1560 }
1561
1562 float RenderStyle::letterSpacing() const
1563 {
1564     return m_inheritedData->fontCascade.letterSpacing();
1565 }
1566
1567 bool RenderStyle::setFontDescription(const FontCascadeDescription& description)
1568 {
1569     if (m_inheritedData->fontCascade.fontDescription() == description)
1570         return false;
1571     auto& cascade = m_inheritedData.access().fontCascade;
1572     cascade = { description, cascade.letterSpacing(), cascade.wordSpacing() };
1573     return true;
1574 }
1575
1576 const Length& RenderStyle::specifiedLineHeight() const
1577 {
1578 #if ENABLE(TEXT_AUTOSIZING)
1579     return m_inheritedData->specifiedLineHeight;
1580 #else
1581     return m_inheritedData->lineHeight;
1582 #endif
1583 }
1584
1585 #if ENABLE(TEXT_AUTOSIZING)
1586
1587 void RenderStyle::setSpecifiedLineHeight(Length&& height)
1588 {
1589     SET_VAR(m_inheritedData, specifiedLineHeight, WTFMove(height));
1590 }
1591
1592 #endif
1593
1594 const Length& RenderStyle::lineHeight() const
1595 {
1596     return m_inheritedData->lineHeight;
1597 }
1598
1599 void RenderStyle::setLineHeight(Length&& height)
1600 {
1601     SET_VAR(m_inheritedData, lineHeight, WTFMove(height));
1602 }
1603
1604 int RenderStyle::computedLineHeight() const
1605 {
1606     const Length& lh = lineHeight();
1607
1608     // Negative value means the line height is not set. Use the font's built-in spacing.
1609     if (lh.isNegative())
1610         return fontMetrics().lineSpacing();
1611
1612     if (lh.isPercentOrCalculated())
1613         return minimumValueForLength(lh, computedFontPixelSize());
1614
1615     return clampTo<int>(lh.value());
1616 }
1617
1618 void RenderStyle::setWordSpacing(Length&& value)
1619 {
1620     float fontWordSpacing;
1621     switch (value.type()) {
1622     case Auto:
1623         fontWordSpacing = 0;
1624         break;
1625     case Percent:
1626         fontWordSpacing = value.percent() * fontCascade().spaceWidth() / 100;
1627         break;
1628     case Fixed:
1629         fontWordSpacing = value.value();
1630         break;
1631     case Calculated:
1632         fontWordSpacing = value.nonNanCalculatedValue(maxValueForCssLength);
1633         break;
1634     default:
1635         ASSERT_NOT_REACHED();
1636         fontWordSpacing = 0;
1637         break;
1638     }
1639     m_inheritedData.access().fontCascade.setWordSpacing(fontWordSpacing);
1640     m_rareInheritedData.access().wordSpacing = WTFMove(value);
1641 }
1642
1643 void RenderStyle::setLetterSpacing(float v) { m_inheritedData.access().fontCascade.setLetterSpacing(v); }
1644
1645 void RenderStyle::setFontSize(float size)
1646 {
1647     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1648     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1649
1650     ASSERT(std::isfinite(size));
1651     if (!std::isfinite(size) || size < 0)
1652         size = 0;
1653     else
1654         size = std::min(maximumAllowedFontSize, size);
1655
1656     FontSelector* currentFontSelector = fontCascade().fontSelector();
1657     auto description = fontDescription();
1658     description.setSpecifiedSize(size);
1659     description.setComputedSize(size);
1660
1661     setFontDescription(description);
1662     fontCascade().update(currentFontSelector);
1663 }
1664
1665 #if ENABLE(VARIATION_FONTS)
1666 void RenderStyle::setFontVariationSettings(FontVariationSettings settings)
1667 {
1668     FontSelector* currentFontSelector = fontCascade().fontSelector();
1669     auto description = fontDescription();
1670     description.setVariationSettings(WTFMove(settings));
1671
1672     setFontDescription(description);
1673     fontCascade().update(currentFontSelector);
1674 }
1675 #endif
1676
1677 void RenderStyle::setFontWeight(FontSelectionValue value)
1678 {
1679     FontSelector* currentFontSelector = fontCascade().fontSelector();
1680     auto description = fontDescription();
1681     description.setWeight(value);
1682
1683     setFontDescription(description);
1684     fontCascade().update(currentFontSelector);
1685 }
1686
1687 void RenderStyle::setFontStretch(FontSelectionValue value)
1688 {
1689     FontSelector* currentFontSelector = fontCascade().fontSelector();
1690     auto description = fontDescription();
1691     description.setStretch(value);
1692
1693     setFontDescription(description);
1694     fontCascade().update(currentFontSelector);
1695 }
1696
1697 void RenderStyle::setFontItalic(FontSelectionValue value)
1698 {
1699     FontSelector* currentFontSelector = fontCascade().fontSelector();
1700     auto description = fontDescription();
1701     description.setItalic(value);
1702
1703     setFontDescription(description);
1704     fontCascade().update(currentFontSelector);
1705 }
1706
1707 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
1708 {
1709     top = 0;
1710     right = 0;
1711     bottom = 0;
1712     left = 0;
1713
1714     for ( ; shadow; shadow = shadow->next()) {
1715         if (shadow->style() == Inset)
1716             continue;
1717
1718         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1719         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1720         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1721         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1722         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1723     }
1724 }
1725
1726 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1727 {
1728     LayoutUnit top = 0;
1729     LayoutUnit right = 0;
1730     LayoutUnit bottom = 0;
1731     LayoutUnit left = 0;
1732
1733     for ( ; shadow; shadow = shadow->next()) {
1734         if (shadow->style() == Normal)
1735             continue;
1736
1737         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1738         top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1739         right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1740         bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1741         left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1742     }
1743
1744     return LayoutBoxExtent(WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left));
1745 }
1746
1747 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1748 {
1749     left = 0;
1750     right = 0;
1751
1752     for ( ; shadow; shadow = shadow->next()) {
1753         if (shadow->style() == Inset)
1754             continue;
1755
1756         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1757         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1758         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1759     }
1760 }
1761
1762 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1763 {
1764     top = 0;
1765     bottom = 0;
1766
1767     for ( ; shadow; shadow = shadow->next()) {
1768         if (shadow->style() == Inset)
1769             continue;
1770
1771         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1772         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1773         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1774     }
1775 }
1776
1777 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1778 {
1779     Color result;
1780     EBorderStyle borderStyle = BNONE;
1781     switch (colorProperty) {
1782     case CSSPropertyBackgroundColor:
1783         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1784     case CSSPropertyBorderLeftColor:
1785         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1786         borderStyle = borderLeftStyle();
1787         break;
1788     case CSSPropertyBorderRightColor:
1789         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1790         borderStyle = borderRightStyle();
1791         break;
1792     case CSSPropertyBorderTopColor:
1793         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1794         borderStyle = borderTopStyle();
1795         break;
1796     case CSSPropertyBorderBottomColor:
1797         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1798         borderStyle = borderBottomStyle();
1799         break;
1800     case CSSPropertyCaretColor:
1801         result = visitedLink ? visitedLinkCaretColor() : caretColor();
1802         break;
1803     case CSSPropertyColor:
1804         result = visitedLink ? visitedLinkColor() : color();
1805         break;
1806     case CSSPropertyOutlineColor:
1807         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1808         break;
1809     case CSSPropertyColumnRuleColor:
1810         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1811         break;
1812     case CSSPropertyWebkitTextDecorationColor:
1813         // Text decoration color fallback is handled in RenderObject::decorationColor.
1814         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1815     case CSSPropertyWebkitTextEmphasisColor:
1816         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1817         break;
1818     case CSSPropertyWebkitTextFillColor:
1819         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1820         break;
1821     case CSSPropertyWebkitTextStrokeColor:
1822         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1823         break;
1824     case CSSPropertyStrokeColor:
1825         result = visitedLink ? visitedLinkStrokeColor() : strokeColor();
1826         break;
1827     default:
1828         ASSERT_NOT_REACHED();
1829         break;
1830     }
1831
1832     if (!result.isValid()) {
1833         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1834             result = Color(238, 238, 238);
1835         else
1836             result = visitedLink ? visitedLinkColor() : color();
1837     }
1838     return result;
1839 }
1840
1841 Color RenderStyle::visitedDependentColor(int colorProperty) const
1842 {
1843     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1844     if (insideLink() != InsideVisitedLink)
1845         return unvisitedColor;
1846
1847     Color visitedColor = colorIncludingFallback(colorProperty, true);
1848
1849     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1850     if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1851         return visitedColor;
1852
1853     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1854     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1855     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1856     // have to match, it makes more sense to return the unvisited background color if specified than it
1857     // does to return black. This behavior matches what Firefox 4 does as well.
1858     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1859         return unvisitedColor;
1860
1861     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1862     return visitedColor.colorWithAlpha(unvisitedColor.alphaAsFloat());
1863 }
1864
1865 const BorderValue& RenderStyle::borderBefore() const
1866 {
1867     switch (writingMode()) {
1868     case TopToBottomWritingMode:
1869         return borderTop();
1870     case BottomToTopWritingMode:
1871         return borderBottom();
1872     case LeftToRightWritingMode:
1873         return borderLeft();
1874     case RightToLeftWritingMode:
1875         return borderRight();
1876     }
1877     ASSERT_NOT_REACHED();
1878     return borderTop();
1879 }
1880
1881 const BorderValue& RenderStyle::borderAfter() const
1882 {
1883     switch (writingMode()) {
1884     case TopToBottomWritingMode:
1885         return borderBottom();
1886     case BottomToTopWritingMode:
1887         return borderTop();
1888     case LeftToRightWritingMode:
1889         return borderRight();
1890     case RightToLeftWritingMode:
1891         return borderLeft();
1892     }
1893     ASSERT_NOT_REACHED();
1894     return borderBottom();
1895 }
1896
1897 const BorderValue& RenderStyle::borderStart() const
1898 {
1899     if (isHorizontalWritingMode())
1900         return isLeftToRightDirection() ? borderLeft() : borderRight();
1901     return isLeftToRightDirection() ? borderTop() : borderBottom();
1902 }
1903
1904 const BorderValue& RenderStyle::borderEnd() const
1905 {
1906     if (isHorizontalWritingMode())
1907         return isLeftToRightDirection() ? borderRight() : borderLeft();
1908     return isLeftToRightDirection() ? borderBottom() : borderTop();
1909 }
1910
1911 float RenderStyle::borderBeforeWidth() const
1912 {
1913     switch (writingMode()) {
1914     case TopToBottomWritingMode:
1915         return borderTopWidth();
1916     case BottomToTopWritingMode:
1917         return borderBottomWidth();
1918     case LeftToRightWritingMode:
1919         return borderLeftWidth();
1920     case RightToLeftWritingMode:
1921         return borderRightWidth();
1922     }
1923     ASSERT_NOT_REACHED();
1924     return borderTopWidth();
1925 }
1926
1927 float RenderStyle::borderAfterWidth() const
1928 {
1929     switch (writingMode()) {
1930     case TopToBottomWritingMode:
1931         return borderBottomWidth();
1932     case BottomToTopWritingMode:
1933         return borderTopWidth();
1934     case LeftToRightWritingMode:
1935         return borderRightWidth();
1936     case RightToLeftWritingMode:
1937         return borderLeftWidth();
1938     }
1939     ASSERT_NOT_REACHED();
1940     return borderBottomWidth();
1941 }
1942
1943 float RenderStyle::borderStartWidth() const
1944 {
1945     if (isHorizontalWritingMode())
1946         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1947     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1948 }
1949
1950 float RenderStyle::borderEndWidth() const
1951 {
1952     if (isHorizontalWritingMode())
1953         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1954     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1955 }
1956
1957 void RenderStyle::setMarginStart(Length&& margin)
1958 {
1959     if (isHorizontalWritingMode()) {
1960         if (isLeftToRightDirection())
1961             setMarginLeft(WTFMove(margin));
1962         else
1963             setMarginRight(WTFMove(margin));
1964     } else {
1965         if (isLeftToRightDirection())
1966             setMarginTop(WTFMove(margin));
1967         else
1968             setMarginBottom(WTFMove(margin));
1969     }
1970 }
1971
1972 void RenderStyle::setMarginEnd(Length&& margin)
1973 {
1974     if (isHorizontalWritingMode()) {
1975         if (isLeftToRightDirection())
1976             setMarginRight(WTFMove(margin));
1977         else
1978             setMarginLeft(WTFMove(margin));
1979     } else {
1980         if (isLeftToRightDirection())
1981             setMarginBottom(WTFMove(margin));
1982         else
1983             setMarginTop(WTFMove(margin));
1984     }
1985 }
1986
1987 TextEmphasisMark RenderStyle::textEmphasisMark() const
1988 {
1989     auto mark = static_cast<TextEmphasisMark>(m_rareInheritedData->textEmphasisMark);
1990     if (mark != TextEmphasisMarkAuto)
1991         return mark;
1992     if (isHorizontalWritingMode())
1993         return TextEmphasisMarkDot;
1994     return TextEmphasisMarkSesame;
1995 }
1996
1997 #if ENABLE(TOUCH_EVENTS)
1998
1999 Color RenderStyle::initialTapHighlightColor()
2000 {
2001     return RenderTheme::tapHighlightColor();
2002 }
2003
2004 #endif
2005
2006 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
2007 {
2008     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
2009                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
2010                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
2011                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
2012 }
2013
2014 std::pair<FontOrientation, NonCJKGlyphOrientation> RenderStyle::fontAndGlyphOrientation()
2015 {
2016     // FIXME: TextOrientationSideways should map to sideways-left in vertical-lr, which is not supported yet.
2017
2018     if (isHorizontalWritingMode())
2019         return { Horizontal, NonCJKGlyphOrientation::Mixed };
2020
2021     switch (textOrientation()) {
2022     case TextOrientation::Mixed:
2023         return { Vertical, NonCJKGlyphOrientation::Mixed };
2024     case TextOrientation::Upright:
2025         return { Vertical, NonCJKGlyphOrientation::Upright };
2026     case TextOrientation::Sideways:
2027         return { Horizontal, NonCJKGlyphOrientation::Mixed };
2028     default:
2029         ASSERT_NOT_REACHED();
2030         return { Horizontal, NonCJKGlyphOrientation::Mixed };
2031     }
2032 }
2033
2034 void RenderStyle::setBorderImageSource(RefPtr<StyleImage>&& image)
2035 {
2036     if (m_surroundData->border.m_image.image() == image.get())
2037         return;
2038     m_surroundData.access().border.m_image.setImage(WTFMove(image));
2039 }
2040
2041 void RenderStyle::setBorderImageSlices(LengthBox&& slices)
2042 {
2043     if (m_surroundData->border.m_image.imageSlices() == slices)
2044         return;
2045     m_surroundData.access().border.m_image.setImageSlices(WTFMove(slices));
2046 }
2047
2048 void RenderStyle::setBorderImageWidth(LengthBox&& slices)
2049 {
2050     if (m_surroundData->border.m_image.borderSlices() == slices)
2051         return;
2052     m_surroundData.access().border.m_image.setBorderSlices(WTFMove(slices));
2053 }
2054
2055 void RenderStyle::setBorderImageOutset(LengthBox&& outset)
2056 {
2057     if (m_surroundData->border.m_image.outset() == outset)
2058         return;
2059     m_surroundData.access().border.m_image.setOutset(WTFMove(outset));
2060 }
2061
2062 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
2063 {
2064     if (paginationMode == Pagination::Unpaginated)
2065         return;
2066     
2067     setColumnFill(ColumnFillAuto);
2068     
2069     switch (paginationMode) {
2070     case Pagination::LeftToRightPaginated:
2071         setColumnAxis(HorizontalColumnAxis);
2072         if (isHorizontalWritingMode())
2073             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
2074         else
2075             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
2076         break;
2077     case Pagination::RightToLeftPaginated:
2078         setColumnAxis(HorizontalColumnAxis);
2079         if (isHorizontalWritingMode())
2080             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
2081         else
2082             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
2083         break;
2084     case Pagination::TopToBottomPaginated:
2085         setColumnAxis(VerticalColumnAxis);
2086         if (isHorizontalWritingMode())
2087             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
2088         else
2089             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
2090         break;
2091     case Pagination::BottomToTopPaginated:
2092         setColumnAxis(VerticalColumnAxis);
2093         if (isHorizontalWritingMode())
2094             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
2095         else
2096             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
2097         break;
2098     case Pagination::Unpaginated:
2099         ASSERT_NOT_REACHED();
2100         break;
2101     }
2102 }
2103
2104 #if ENABLE(CSS_SCROLL_SNAP)
2105
2106 ScrollSnapType RenderStyle::initialScrollSnapType()
2107 {
2108     return { };
2109 }
2110
2111 ScrollSnapAlign RenderStyle::initialScrollSnapAlign()
2112 {
2113     return { };
2114 }
2115
2116 const StyleScrollSnapArea& RenderStyle::scrollSnapArea() const
2117 {
2118     return *m_rareNonInheritedData->scrollSnapArea;
2119 }
2120
2121 const StyleScrollSnapPort& RenderStyle::scrollSnapPort() const
2122 {
2123     return *m_rareNonInheritedData->scrollSnapPort;
2124 }
2125
2126 const ScrollSnapType& RenderStyle::scrollSnapType() const
2127 {
2128     return m_rareNonInheritedData->scrollSnapPort->type;
2129 }
2130
2131 const LengthBox& RenderStyle::scrollPadding() const
2132 {
2133     return m_rareNonInheritedData->scrollSnapPort->scrollPadding;
2134 }
2135
2136 const Length& RenderStyle::scrollPaddingTop() const
2137 {
2138     return scrollPadding().top();
2139 }
2140
2141 const Length& RenderStyle::scrollPaddingBottom() const
2142 {
2143     return scrollPadding().bottom();
2144 }
2145
2146 const Length& RenderStyle::scrollPaddingLeft() const
2147 {
2148     return scrollPadding().left();
2149 }
2150
2151 const Length& RenderStyle::scrollPaddingRight() const
2152 {
2153     return scrollPadding().right();
2154 }
2155
2156 const ScrollSnapAlign& RenderStyle::scrollSnapAlign() const
2157 {
2158     return m_rareNonInheritedData->scrollSnapArea->alignment;
2159 }
2160
2161 const LengthBox& RenderStyle::scrollSnapMargin() const
2162 {
2163     return m_rareNonInheritedData->scrollSnapArea->scrollSnapMargin;
2164 }
2165
2166 const Length& RenderStyle::scrollSnapMarginTop() const
2167 {
2168     return scrollSnapMargin().top();
2169 }
2170
2171 const Length& RenderStyle::scrollSnapMarginBottom() const
2172 {
2173     return scrollSnapMargin().bottom();
2174 }
2175
2176 const Length& RenderStyle::scrollSnapMarginLeft() const
2177 {
2178     return scrollSnapMargin().left();
2179 }
2180
2181 const Length& RenderStyle::scrollSnapMarginRight() const
2182 {
2183     return scrollSnapMargin().right();
2184 }
2185
2186 void RenderStyle::setScrollSnapType(const ScrollSnapType& type)
2187 {
2188     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, type, type);
2189 }
2190
2191 void RenderStyle::setScrollPaddingTop(Length&& length)
2192 {
2193     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.top(), WTFMove(length));
2194 }
2195
2196 void RenderStyle::setScrollPaddingBottom(Length&& length)
2197 {
2198     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.bottom(), WTFMove(length));
2199 }
2200
2201 void RenderStyle::setScrollPaddingLeft(Length&& length)
2202 {
2203     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.left(), WTFMove(length));
2204 }
2205
2206 void RenderStyle::setScrollPaddingRight(Length&& length)
2207 {
2208     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapPort, scrollPadding.right(), WTFMove(length));
2209 }
2210
2211 void RenderStyle::setScrollSnapAlign(const ScrollSnapAlign& alignment)
2212 {
2213     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, alignment, alignment);
2214 }
2215
2216 void RenderStyle::setScrollSnapMarginTop(Length&& length)
2217 {
2218     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.top(), WTFMove(length));
2219 }
2220
2221 void RenderStyle::setScrollSnapMarginBottom(Length&& length)
2222 {
2223     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.bottom(), WTFMove(length));
2224 }
2225
2226 void RenderStyle::setScrollSnapMarginLeft(Length&& length)
2227 {
2228     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.left(), WTFMove(length));
2229 }
2230
2231 void RenderStyle::setScrollSnapMarginRight(Length&& length)
2232 {
2233     SET_NESTED_VAR(m_rareNonInheritedData, scrollSnapArea, scrollSnapMargin.right(), WTFMove(length));
2234 }
2235
2236 #endif
2237
2238 bool RenderStyle::hasReferenceFilterOnly() const
2239 {
2240     if (!hasFilter())
2241         return false;
2242     auto& filterOperations = m_rareNonInheritedData->filter->operations;
2243     return filterOperations.size() == 1 && filterOperations.at(0)->type() == FilterOperation::REFERENCE;
2244 }
2245
2246 void RenderStyle::checkVariablesInCustomProperties()
2247 {
2248     if (!m_rareInheritedData->customProperties->containsVariables)
2249         return;
2250
2251     auto& customPropertyData = m_rareInheritedData.access().customProperties.access();
2252
2253     // Our first pass checks the variables for validity and replaces any properties that became
2254     // invalid with empty values.
2255     auto& customProperties = customPropertyData.values;
2256     HashSet<AtomicString> invalidProperties;
2257     for (auto entry : customProperties) {
2258         if (!entry.value->containsVariables())
2259             continue;
2260         HashSet<AtomicString> seenProperties;
2261         entry.value->checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
2262     }
2263     
2264     // Now insert invalid values.
2265     if (!invalidProperties.isEmpty()) {
2266         auto invalidValue = CSSCustomPropertyValue::createInvalid();
2267         for (auto& property : invalidProperties)
2268             customProperties.set(property, invalidValue.copyRef());
2269     }
2270
2271     // Now that all of the properties have been tested for validity and replaced with
2272     // invalid values if they failed, we can perform variable substitution on the valid values.
2273     Vector<Ref<CSSCustomPropertyValue>> resolvedValues;
2274     for (auto entry : customProperties) {
2275         if (!entry.value->containsVariables())
2276             continue;
2277         entry.value->resolveVariableReferences(customProperties, resolvedValues);
2278     }
2279     
2280     // With all results computed, we can now mutate our table to eliminate the variables and
2281     // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
2282     for (auto& resolvedValue : resolvedValues)
2283         customProperties.set(resolvedValue->name(), resolvedValue.copyRef());
2284
2285     customPropertyData.containsVariables = false;
2286 }
2287
2288 float RenderStyle::outlineWidth() const
2289 {
2290     if (m_backgroundData->outline.style() == BNONE)
2291         return 0;
2292     if (outlineStyleIsAuto())
2293         return std::max(m_backgroundData->outline.width(), RenderTheme::platformFocusRingWidth());
2294     return m_backgroundData->outline.width();
2295 }
2296
2297 float RenderStyle::outlineOffset() const
2298 {
2299     if (m_backgroundData->outline.style() == BNONE)
2300         return 0;
2301     if (outlineStyleIsAuto())
2302         return (m_backgroundData->outline.offset() + RenderTheme::platformFocusRingOffset(outlineWidth()));
2303     return m_backgroundData->outline.offset();
2304 }
2305
2306 bool RenderStyle::shouldPlaceBlockDirectionScrollbarOnLeft() const
2307 {
2308     return !isLeftToRightDirection() && isHorizontalWritingMode();
2309 }
2310
2311 #if ENABLE(DASHBOARD_SUPPORT)
2312
2313 void RenderStyle::setDashboardRegion(int type, const String& label, Length&& top, Length&& right, Length&& bottom, Length&& left, bool append)
2314 {
2315     if (!append)
2316         m_rareNonInheritedData.access().dashboardRegions.clear();
2317     m_rareNonInheritedData.access().dashboardRegions.append({ label, { WTFMove(top), WTFMove(right), WTFMove(bottom), WTFMove(left) }, type });
2318 }
2319
2320 #endif
2321
2322 Vector<PaintType, 3> RenderStyle::paintTypesForPaintOrder(PaintOrder order)
2323 {
2324     Vector<PaintType, 3> paintOrder;
2325     switch (order) {
2326     case PaintOrder::Normal:
2327         FALLTHROUGH;
2328     case PaintOrder::Fill:
2329         paintOrder.append(PaintType::Fill);
2330         paintOrder.append(PaintType::Stroke);
2331         paintOrder.append(PaintType::Markers);
2332         break;
2333     case PaintOrder::FillMarkers:
2334         paintOrder.append(PaintType::Fill);
2335         paintOrder.append(PaintType::Markers);
2336         paintOrder.append(PaintType::Stroke);
2337         break;
2338     case PaintOrder::Stroke:
2339         paintOrder.append(PaintType::Stroke);
2340         paintOrder.append(PaintType::Fill);
2341         paintOrder.append(PaintType::Markers);
2342         break;
2343     case PaintOrder::StrokeMarkers:
2344         paintOrder.append(PaintType::Stroke);
2345         paintOrder.append(PaintType::Markers);
2346         paintOrder.append(PaintType::Fill);
2347         break;
2348     case PaintOrder::Markers:
2349         paintOrder.append(PaintType::Markers);
2350         paintOrder.append(PaintType::Fill);
2351         paintOrder.append(PaintType::Stroke);
2352         break;
2353     case PaintOrder::MarkersStroke:
2354         paintOrder.append(PaintType::Markers);
2355         paintOrder.append(PaintType::Stroke);
2356         paintOrder.append(PaintType::Fill);
2357         break;
2358     };
2359     return paintOrder;
2360 }
2361
2362 float RenderStyle::computedStrokeWidth(const IntSize& viewportSize) const
2363 {
2364     if (!hasExplicitlySetStrokeWidth())
2365         return textStrokeWidth();
2366     
2367     const Length& length = strokeWidth();
2368
2369     if (length.isPercent()) {
2370         // According to the spec, https://drafts.fxtf.org/paint/#stroke-width, the percentage is relative to the scaled viewport size.
2371         // The scaled viewport size is the geometric mean of the viewport width and height.
2372         ExceptionOr<float> result = length.value() * (viewportSize.width() + viewportSize.height()) / 200.0f;
2373         if (result.hasException())
2374             return 0;
2375         return result.releaseReturnValue();
2376     }
2377     
2378     if (length.isAuto() || !length.isSpecified())
2379         return 0;
2380     
2381     return floatValueForLength(length, viewportSize.width());
2382 }
2383
2384 bool RenderStyle::hasPositiveStrokeWidth() const
2385 {
2386     if (!hasExplicitlySetStrokeWidth())
2387         return textStrokeWidth() > 0;
2388
2389     return strokeWidth().isPositive();
2390 }
2391
2392 } // namespace WebCore