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