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