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