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