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