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