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