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