[CSS Box Alignment] New CSS Value 'normal' for Content Alignment
[WebKit-https.git] / Source / WebCore / rendering / style / RenderStyle.cpp
1 /*
2  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
3  * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
4  * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  */
22
23 #include "config.h"
24 #include "RenderStyle.h"
25
26 #include "ContentData.h"
27 #include "CSSCustomPropertyValue.h"
28 #include "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         || rareInheritedData->m_imageRendering != other.rareInheritedData->m_imageRendering)
813         return true;
814
815 #if ENABLE(CSS_SHAPES)
816     if (rareNonInheritedData->m_shapeOutside != other.rareNonInheritedData->m_shapeOutside)
817         return true;
818 #endif
819
820     // FIXME: this should probably be moved to changeRequiresLayerRepaint().
821     if (rareNonInheritedData->m_clipPath != other.rareNonInheritedData->m_clipPath) {
822         changedContextSensitiveProperties |= ContextSensitivePropertyClipPath;
823         // Don't return; keep looking for another change.
824     }
825
826     return false;
827 }
828
829 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle& other, unsigned&) const
830 {
831     if (inherited->color != other.inherited->color
832         || inherited_flags._text_decorations != other.inherited_flags._text_decorations
833         || visual->textDecoration != other.visual->textDecoration
834         || rareNonInheritedData->m_textDecorationStyle != other.rareNonInheritedData->m_textDecorationStyle
835         || rareNonInheritedData->m_textDecorationColor != other.rareNonInheritedData->m_textDecorationColor
836         || rareInheritedData->m_textDecorationSkip != other.rareInheritedData->m_textDecorationSkip
837         || rareInheritedData->textFillColor != other.rareInheritedData->textFillColor
838         || rareInheritedData->textStrokeColor != other.rareInheritedData->textStrokeColor
839         || rareInheritedData->textEmphasisColor != other.rareInheritedData->textEmphasisColor
840         || rareInheritedData->textEmphasisFill != other.rareInheritedData->textEmphasisFill)
841         return true;
842
843     return false;
844 }
845
846 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle& other, unsigned&) const
847 {
848     if (rareNonInheritedData.get() != other.rareNonInheritedData.get()) {
849         if (rareNonInheritedData->m_transformStyle3D != other.rareNonInheritedData->m_transformStyle3D
850             || rareNonInheritedData->m_backfaceVisibility != other.rareNonInheritedData->m_backfaceVisibility
851             || rareNonInheritedData->m_perspective != other.rareNonInheritedData->m_perspective
852             || rareNonInheritedData->m_perspectiveOriginX != other.rareNonInheritedData->m_perspectiveOriginX
853             || rareNonInheritedData->m_perspectiveOriginY != other.rareNonInheritedData->m_perspectiveOriginY)
854             return true;
855     }
856
857     return false;
858 }
859
860 StyleDifference RenderStyle::diff(const RenderStyle& other, unsigned& changedContextSensitiveProperties) const
861 {
862     changedContextSensitiveProperties = ContextSensitivePropertyNone;
863
864     StyleDifference svgChange = StyleDifferenceEqual;
865     if (m_svgStyle != other.m_svgStyle) {
866         svgChange = m_svgStyle->diff(other.m_svgStyle.get());
867         if (svgChange == StyleDifferenceLayout)
868             return svgChange;
869     }
870
871     if (changeRequiresLayout(other, changedContextSensitiveProperties))
872         return StyleDifferenceLayout;
873
874     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
875     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
876     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
877     // that are relevant for SVG and might return StyleDifferenceLayout.
878     if (svgChange != StyleDifferenceEqual)
879         return svgChange;
880
881     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
882         return StyleDifferenceLayoutPositionedMovementOnly;
883
884     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
885         return StyleDifferenceRepaintLayer;
886
887     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
888         return StyleDifferenceRepaint;
889
890     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
891         return StyleDifferenceRecompositeLayer;
892
893     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
894         return StyleDifferenceRepaintIfTextOrBorderOrOutline;
895
896     // Cursors are not checked, since they will be set appropriately in response to mouse events,
897     // so they don't need to cause any repaint or layout.
898
899     // 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
900     // the resulting transition properly.
901     return StyleDifferenceEqual;
902 }
903
904 bool RenderStyle::diffRequiresLayerRepaint(const RenderStyle& style, bool isComposited) const
905 {
906     unsigned changedContextSensitiveProperties = 0;
907
908     if (changeRequiresRepaint(style, changedContextSensitiveProperties))
909         return true;
910
911     if (isComposited && changeRequiresLayerRepaint(style, changedContextSensitiveProperties))
912         return changedContextSensitiveProperties & ContextSensitivePropertyClipRect;
913
914     return false;
915 }
916
917 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
918 {
919     StyleVisualData* data = visual.access();
920     data->clip.top() = top;
921     data->clip.right() = right;
922     data->clip.bottom() = bottom;
923     data->clip.left() = left;
924 }
925
926 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
927 {
928     if (!rareInheritedData.access()->cursorData)
929         rareInheritedData.access()->cursorData = CursorList::create();
930     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
931 }
932
933 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
934 {
935     rareInheritedData.access()->cursorData = other;
936 }
937
938 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
939 {
940     if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q))
941         return;
942
943     rareInheritedData.access()->quotes = q;
944 }
945
946 void RenderStyle::setWillChange(PassRefPtr<WillChangeData> willChangeData)
947 {
948     if (arePointingToEqualData(rareNonInheritedData->m_willChange.get(), willChangeData.get()))
949         return;
950
951     rareNonInheritedData.access()->m_willChange = WTFMove(willChangeData);
952 }
953
954 void RenderStyle::clearCursorList()
955 {
956     if (rareInheritedData->cursorData)
957         rareInheritedData.access()->cursorData = nullptr;
958 }
959
960 void RenderStyle::clearContent()
961 {
962     if (rareNonInheritedData->m_content)
963         rareNonInheritedData.access()->m_content = nullptr;
964 }
965
966 void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData)
967 {
968     auto& content = rareNonInheritedData.access()->m_content;
969     ContentData* lastContent = content.get();
970     while (lastContent && lastContent->next())
971         lastContent = lastContent->next();
972
973     if (lastContent)
974         lastContent->setNext(WTFMove(contentData));
975     else
976         content = WTFMove(contentData);
977 }
978
979 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
980 {
981     if (!image)
982         return;
983         
984     if (add) {
985         appendContent(std::make_unique<ImageContentData>(image));
986         return;
987     }
988
989     rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image);
990     if (!rareNonInheritedData.access()->m_altText.isNull())
991         rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText);
992 }
993
994 void RenderStyle::setContent(const String& string, bool add)
995 {
996     auto& content = rareNonInheritedData.access()->m_content;
997     if (add) {
998         ContentData* lastContent = content.get();
999         while (lastContent && lastContent->next())
1000             lastContent = lastContent->next();
1001
1002         if (lastContent) {
1003             // We attempt to merge with the last ContentData if possible.
1004             if (is<TextContentData>(*lastContent)) {
1005                 TextContentData& textContent = downcast<TextContentData>(*lastContent);
1006                 textContent.setText(textContent.text() + string);
1007             } else
1008                 lastContent->setNext(std::make_unique<TextContentData>(string));
1009
1010             if (!rareNonInheritedData.access()->m_altText.isNull())
1011                 lastContent->setAltText(rareNonInheritedData.access()->m_altText);
1012             return;
1013         }
1014     }
1015
1016     content = std::make_unique<TextContentData>(string);
1017     if (!rareNonInheritedData.access()->m_altText.isNull())
1018         content->setAltText(rareNonInheritedData.access()->m_altText);
1019 }
1020
1021 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
1022 {
1023     if (!counter)
1024         return;
1025
1026     if (add) {
1027         appendContent(std::make_unique<CounterContentData>(WTFMove(counter)));
1028         return;
1029     }
1030
1031     rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(WTFMove(counter));
1032 }
1033
1034 void RenderStyle::setContent(QuoteType quote, bool add)
1035 {
1036     if (add) {
1037         appendContent(std::make_unique<QuoteContentData>(quote));
1038         return;
1039     }
1040
1041     rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote);
1042 }
1043
1044 void RenderStyle::setContentAltText(const String& string)
1045 {
1046     rareNonInheritedData.access()->m_altText = string;
1047     
1048     if (rareNonInheritedData.access()->m_content)
1049         rareNonInheritedData.access()->m_content->setAltText(string);
1050 }
1051
1052 const String& RenderStyle::contentAltText() const
1053 {
1054     return rareNonInheritedData->m_altText;
1055 }
1056
1057 // FIXME: use affectedByTransformOrigin().
1058 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
1059 {
1060     // transform-origin brackets the transform with translate operations.
1061     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
1062     // in that case.
1063     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
1064         return false;
1065
1066     for (auto& operation : transformOperations) {
1067         TransformOperation::OperationType type = operation->type();
1068         if (type != TransformOperation::TRANSLATE_X
1069             && type != TransformOperation::TRANSLATE_Y
1070             && type != TransformOperation::TRANSLATE 
1071             && type != TransformOperation::TRANSLATE_Z
1072             && type != TransformOperation::TRANSLATE_3D)
1073             return true;
1074     }
1075
1076     return false;
1077 }
1078
1079 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
1080 {
1081     auto& operations = rareNonInheritedData->m_transform->m_operations.operations();
1082     bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
1083
1084     float offsetX = transformOriginX().isPercent() ? boundingBox.x() : 0;
1085     float offsetY = transformOriginY().isPercent() ? boundingBox.y() : 0;
1086
1087     if (applyTransformOrigin) {
1088         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
1089                               floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
1090                               transformOriginZ());
1091     }
1092
1093     for (auto& operation : operations)
1094         operation->apply(transform, boundingBox.size());
1095
1096     if (applyTransformOrigin) {
1097         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
1098                               -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
1099                               -transformOriginZ());
1100     }
1101 }
1102
1103 void RenderStyle::setPageScaleTransform(float scale)
1104 {
1105     if (scale == 1)
1106         return;
1107     TransformOperations transform;
1108     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
1109     setTransform(transform);
1110     setTransformOriginX(Length(0, Fixed));
1111     setTransformOriginY(Length(0, Fixed));
1112 }
1113
1114 void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1115 {
1116     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
1117
1118     StyleRareInheritedData* rareData = rareInheritedData.access();
1119     if (!add) {
1120         rareData->textShadow = WTFMove(shadowData);
1121         return;
1122     }
1123
1124     shadowData->setNext(WTFMove(rareData->textShadow));
1125     rareData->textShadow = WTFMove(shadowData);
1126 }
1127
1128 void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1129 {
1130     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
1131     if (!add) {
1132         rareData->m_boxShadow = WTFMove(shadowData);
1133         return;
1134     }
1135
1136     shadowData->setNext(WTFMove(rareData->m_boxShadow));
1137     rareData->m_boxShadow = WTFMove(shadowData);
1138 }
1139
1140 static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size)
1141 {
1142     return RoundedRect::Radii(
1143         LayoutSize(valueForLength(border.topLeft().width(), size.width()),
1144             valueForLength(border.topLeft().height(), size.height())),
1145         LayoutSize(valueForLength(border.topRight().width(), size.width()),
1146             valueForLength(border.topRight().height(), size.height())),
1147         LayoutSize(valueForLength(border.bottomLeft().width(), size.width()),
1148             valueForLength(border.bottomLeft().height(), size.height())),
1149         LayoutSize(valueForLength(border.bottomRight().width(), size.width()),
1150             valueForLength(border.bottomRight().height(), size.height())));
1151 }
1152
1153 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
1154 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
1155 {
1156     if (rareInheritedData->listStyleImage != v)
1157         rareInheritedData.access()->listStyleImage = v;
1158 }
1159
1160 Color RenderStyle::color() const { return inherited->color; }
1161 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
1162 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
1163 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
1164
1165 float RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
1166 float RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
1167 void RenderStyle::setHorizontalBorderSpacing(float v) { SET_VAR(inherited, horizontal_border_spacing, v); }
1168 void RenderStyle::setVerticalBorderSpacing(float v) { SET_VAR(inherited, vertical_border_spacing, v); }
1169
1170 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1171 {
1172     RoundedRect roundedRect(borderRect);
1173     if (hasBorderRadius()) {
1174         RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size());
1175         radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
1176         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1177     }
1178     return roundedRect;
1179 }
1180
1181 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1182 {
1183     bool horizontal = isHorizontalWritingMode();
1184
1185     LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1186     LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1187     LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1188     LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1189
1190     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1191 }
1192
1193 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
1194     LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1195 {
1196     LayoutRect innerRect(borderRect.x() + leftWidth, 
1197                borderRect.y() + topWidth, 
1198                borderRect.width() - leftWidth - rightWidth, 
1199                borderRect.height() - topWidth - bottomWidth);
1200
1201     RoundedRect roundedRect(innerRect);
1202
1203     if (hasBorderRadius()) {
1204         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1205         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1206         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1207     }
1208     return roundedRect;
1209 }
1210
1211 static bool allLayersAreFixed(const FillLayer* layer)
1212 {
1213     bool allFixed = true;
1214     
1215     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1216         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1217
1218     return layer && allFixed;
1219 }
1220
1221 bool RenderStyle::hasEntirelyFixedBackground() const
1222 {
1223     return allLayersAreFixed(backgroundLayers());
1224 }
1225
1226 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1227 {
1228     return rareNonInheritedData->m_counterDirectives.get();
1229 }
1230
1231 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1232 {
1233     auto& map = rareNonInheritedData.access()->m_counterDirectives;
1234     if (!map)
1235         map = std::make_unique<CounterDirectiveMap>();
1236     return *map;
1237 }
1238
1239 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1240 {
1241     if (const CounterDirectiveMap* directives = counterDirectives())
1242         return directives->get(identifier);
1243     return CounterDirectives();
1244 }
1245
1246 const AtomicString& RenderStyle::hyphenString() const
1247 {
1248     ASSERT(hyphens() != HyphensNone);
1249
1250     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1251     if (!hyphenationString.isNull())
1252         return hyphenationString;
1253
1254     // FIXME: This should depend on locale.
1255     static NeverDestroyed<AtomicString> hyphenMinusString(&hyphenMinus, 1);
1256     static NeverDestroyed<AtomicString> hyphenString(&hyphen, 1);
1257     return fontCascade().primaryFont().glyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1258 }
1259
1260 const AtomicString& RenderStyle::textEmphasisMarkString() const
1261 {
1262     switch (textEmphasisMark()) {
1263     case TextEmphasisMarkNone:
1264         return nullAtom;
1265     case TextEmphasisMarkCustom:
1266         return textEmphasisCustomMark();
1267     case TextEmphasisMarkDot: {
1268         static NeverDestroyed<AtomicString> filledDotString(&bullet, 1);
1269         static NeverDestroyed<AtomicString> openDotString(&whiteBullet, 1);
1270         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1271     }
1272     case TextEmphasisMarkCircle: {
1273         static NeverDestroyed<AtomicString> filledCircleString(&blackCircle, 1);
1274         static NeverDestroyed<AtomicString> openCircleString(&whiteCircle, 1);
1275         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1276     }
1277     case TextEmphasisMarkDoubleCircle: {
1278         static NeverDestroyed<AtomicString> filledDoubleCircleString(&fisheye, 1);
1279         static NeverDestroyed<AtomicString> openDoubleCircleString(&bullseye, 1);
1280         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1281     }
1282     case TextEmphasisMarkTriangle: {
1283         static NeverDestroyed<AtomicString> filledTriangleString(&blackUpPointingTriangle, 1);
1284         static NeverDestroyed<AtomicString> openTriangleString(&whiteUpPointingTriangle, 1);
1285         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1286     }
1287     case TextEmphasisMarkSesame: {
1288         static NeverDestroyed<AtomicString> filledSesameString(&sesameDot, 1);
1289         static NeverDestroyed<AtomicString> openSesameString(&whiteSesameDot, 1);
1290         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1291     }
1292     case TextEmphasisMarkAuto:
1293         ASSERT_NOT_REACHED();
1294         return nullAtom;
1295     }
1296
1297     ASSERT_NOT_REACHED();
1298     return nullAtom;
1299 }
1300
1301 #if ENABLE(DASHBOARD_SUPPORT)
1302 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1303 {
1304     static NeverDestroyed<Vector<StyleDashboardRegion>> emptyList;
1305     return emptyList;
1306 }
1307
1308 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1309 {
1310     static NeverDestroyed<Vector<StyleDashboardRegion>> noneList;
1311     static bool noneListInitialized = false;
1312
1313     if (!noneListInitialized) {
1314         StyleDashboardRegion region;
1315         region.label = "";
1316         region.offset.top()  = Length();
1317         region.offset.right() = Length();
1318         region.offset.bottom() = Length();
1319         region.offset.left() = Length();
1320         region.type = StyleDashboardRegion::None;
1321         noneList.get().append(region);
1322         noneListInitialized = true;
1323     }
1324     return noneList;
1325 }
1326 #endif
1327
1328 void RenderStyle::adjustAnimations()
1329 {
1330     AnimationList* animationList = rareNonInheritedData->m_animations.get();
1331     if (!animationList)
1332         return;
1333
1334     // Get rid of empty animations and anything beyond them
1335     for (size_t i = 0; i < animationList->size(); ++i) {
1336         if (animationList->animation(i).isEmpty()) {
1337             animationList->resize(i);
1338             break;
1339         }
1340     }
1341
1342     if (animationList->isEmpty()) {
1343         clearAnimations();
1344         return;
1345     }
1346
1347     // Repeat patterns into layers that don't have some properties set.
1348     animationList->fillUnsetProperties();
1349 }
1350
1351 void RenderStyle::adjustTransitions()
1352 {
1353     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1354     if (!transitionList)
1355         return;
1356
1357     // Get rid of empty transitions and anything beyond them
1358     for (size_t i = 0; i < transitionList->size(); ++i) {
1359         if (transitionList->animation(i).isEmpty()) {
1360             transitionList->resize(i);
1361             break;
1362         }
1363     }
1364
1365     if (transitionList->isEmpty()) {
1366         clearTransitions();
1367         return;
1368     }
1369
1370     // Repeat patterns into layers that don't have some properties set.
1371     transitionList->fillUnsetProperties();
1372
1373     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1374     // but the lists tend to be very short, so it is probably ok
1375     for (size_t i = 0; i < transitionList->size(); ++i) {
1376         for (size_t j = i+1; j < transitionList->size(); ++j) {
1377             if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1378                 // toss i
1379                 transitionList->remove(i);
1380                 j = i;
1381             }
1382         }
1383     }
1384 }
1385
1386 AnimationList& RenderStyle::ensureAnimations()
1387 {
1388     if (!rareNonInheritedData.access()->m_animations)
1389         rareNonInheritedData.access()->m_animations = std::make_unique<AnimationList>();
1390     return *rareNonInheritedData->m_animations;
1391 }
1392
1393 AnimationList& RenderStyle::ensureTransitions()
1394 {
1395     if (!rareNonInheritedData.access()->m_transitions)
1396         rareNonInheritedData.access()->m_transitions = std::make_unique<AnimationList>();
1397     return *rareNonInheritedData->m_transitions;
1398 }
1399
1400 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1401 {
1402     if (transitions()) {
1403         for (size_t i = 0; i < transitions()->size(); ++i) {
1404             const Animation& p = transitions()->animation(i);
1405             if (p.animationMode() == Animation::AnimateAll || p.property() == property) {
1406                 return &p;
1407             }
1408         }
1409     }
1410     return 0;
1411 }
1412
1413 const FontCascade& RenderStyle::fontCascade() const { return inherited->fontCascade; }
1414 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->fontCascade.fontMetrics(); }
1415 const FontCascadeDescription& RenderStyle::fontDescription() const { return inherited->fontCascade.fontDescription(); }
1416 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
1417 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
1418 int RenderStyle::fontSize() const { return inherited->fontCascade.pixelSize(); }
1419
1420 const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; }
1421 float RenderStyle::letterSpacing() const { return inherited->fontCascade.letterSpacing(); }
1422
1423 bool RenderStyle::setFontDescription(const FontCascadeDescription& v)
1424 {
1425     if (inherited->fontCascade.fontDescription() != v) {
1426         inherited.access()->fontCascade = FontCascade(v, inherited->fontCascade.letterSpacing(), inherited->fontCascade.wordSpacing());
1427         return true;
1428     }
1429     return false;
1430 }
1431
1432 #if ENABLE(IOS_TEXT_AUTOSIZING)
1433 const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; }
1434 void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); }
1435 #else
1436 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1437 #endif
1438
1439 Length RenderStyle::lineHeight() const
1440 {
1441     const Length& lh = inherited->line_height;
1442 #if ENABLE(TEXT_AUTOSIZING)
1443     // Unlike fontDescription().computedSize() and hence fontSize(), this is
1444     // recalculated on demand as we only store the specified line height.
1445     // FIXME: Should consider scaling the fixed part of any calc expressions
1446     // too, though this involves messily poking into CalcExpressionLength.
1447     float multiplier = textAutosizingMultiplier();
1448     if (multiplier > 1 && lh.isFixed())
1449         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1450 #endif
1451     return lh;
1452 }
1453 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1454
1455 int RenderStyle::computedLineHeight() const
1456 {
1457     const Length& lh = lineHeight();
1458
1459     // Negative value means the line height is not set. Use the font's built-in spacing.
1460     if (lh.isNegative())
1461         return fontMetrics().lineSpacing();
1462
1463     if (lh.isPercentOrCalculated())
1464         return minimumValueForLength(lh, fontSize());
1465
1466     return clampTo<int>(lh.value());
1467 }
1468
1469 void RenderStyle::setWordSpacing(Length value)
1470 {
1471     float fontWordSpacing;
1472     switch (value.type()) {
1473     case Auto:
1474         fontWordSpacing = 0;
1475         break;
1476     case Percent:
1477         fontWordSpacing = value.percent() * fontCascade().spaceWidth() / 100;
1478         break;
1479     case Fixed:
1480         fontWordSpacing = value.value();
1481         break;
1482     case Calculated:
1483         fontWordSpacing = value.nonNanCalculatedValue(maxValueForCssLength);
1484         break;
1485     default:
1486         ASSERT_NOT_REACHED();
1487         fontWordSpacing = 0;
1488         break;
1489     }
1490     inherited.access()->fontCascade.setWordSpacing(fontWordSpacing);
1491     rareInheritedData.access()->wordSpacing = WTFMove(value);
1492 }
1493
1494 void RenderStyle::setLetterSpacing(float v) { inherited.access()->fontCascade.setLetterSpacing(v); }
1495
1496 void RenderStyle::setFontSize(float size)
1497 {
1498     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1499     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1500
1501     ASSERT(std::isfinite(size));
1502     if (!std::isfinite(size) || size < 0)
1503         size = 0;
1504     else
1505         size = std::min(maximumAllowedFontSize, size);
1506
1507     FontSelector* currentFontSelector = fontCascade().fontSelector();
1508     auto description = fontDescription();
1509     description.setSpecifiedSize(size);
1510     description.setComputedSize(size);
1511
1512 #if ENABLE(TEXT_AUTOSIZING)
1513     float multiplier = textAutosizingMultiplier();
1514     if (multiplier > 1) {
1515         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1516         description.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1517     }
1518 #endif
1519
1520     setFontDescription(description);
1521     fontCascade().update(currentFontSelector);
1522 }
1523
1524 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1525 {
1526     top = 0;
1527     right = 0;
1528     bottom = 0;
1529     left = 0;
1530
1531     for ( ; shadow; shadow = shadow->next()) {
1532         if (shadow->style() == Inset)
1533             continue;
1534
1535         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1536         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1537         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1538         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1539         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1540     }
1541 }
1542
1543 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1544 {
1545     LayoutUnit top = 0;
1546     LayoutUnit right = 0;
1547     LayoutUnit bottom = 0;
1548     LayoutUnit left = 0;
1549
1550     for ( ; shadow; shadow = shadow->next()) {
1551         if (shadow->style() == Normal)
1552             continue;
1553
1554         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1555         top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1556         right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1557         bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1558         left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1559     }
1560
1561     return LayoutBoxExtent(top, right, bottom, left);
1562 }
1563
1564 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1565 {
1566     left = 0;
1567     right = 0;
1568
1569     for ( ; shadow; shadow = shadow->next()) {
1570         if (shadow->style() == Inset)
1571             continue;
1572
1573         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1574         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1575         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1576     }
1577 }
1578
1579 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1580 {
1581     top = 0;
1582     bottom = 0;
1583
1584     for ( ; shadow; shadow = shadow->next()) {
1585         if (shadow->style() == Inset)
1586             continue;
1587
1588         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1589         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1590         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1591     }
1592 }
1593
1594 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1595 {
1596     Color result;
1597     EBorderStyle borderStyle = BNONE;
1598     switch (colorProperty) {
1599     case CSSPropertyBackgroundColor:
1600         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1601     case CSSPropertyBorderLeftColor:
1602         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1603         borderStyle = borderLeftStyle();
1604         break;
1605     case CSSPropertyBorderRightColor:
1606         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1607         borderStyle = borderRightStyle();
1608         break;
1609     case CSSPropertyBorderTopColor:
1610         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1611         borderStyle = borderTopStyle();
1612         break;
1613     case CSSPropertyBorderBottomColor:
1614         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1615         borderStyle = borderBottomStyle();
1616         break;
1617     case CSSPropertyColor:
1618         result = visitedLink ? visitedLinkColor() : color();
1619         break;
1620     case CSSPropertyOutlineColor:
1621         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1622         break;
1623     case CSSPropertyColumnRuleColor:
1624         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1625         break;
1626     case CSSPropertyWebkitTextDecorationColor:
1627         // Text decoration color fallback is handled in RenderObject::decorationColor.
1628         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1629     case CSSPropertyWebkitTextEmphasisColor:
1630         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1631         break;
1632     case CSSPropertyWebkitTextFillColor:
1633         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1634         break;
1635     case CSSPropertyWebkitTextStrokeColor:
1636         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1637         break;
1638     default:
1639         ASSERT_NOT_REACHED();
1640         break;
1641     }
1642
1643     if (!result.isValid()) {
1644         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1645             result.setRGB(238, 238, 238);
1646         else
1647             result = visitedLink ? visitedLinkColor() : color();
1648     }
1649     return result;
1650 }
1651
1652 Color RenderStyle::visitedDependentColor(int colorProperty) const
1653 {
1654     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1655     if (insideLink() != InsideVisitedLink)
1656         return unvisitedColor;
1657
1658     Color visitedColor = colorIncludingFallback(colorProperty, true);
1659
1660     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1661     if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1662         return visitedColor;
1663
1664     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1665     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1666     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1667     // have to match, it makes more sense to return the unvisited background color if specified than it
1668     // does to return black. This behavior matches what Firefox 4 does as well.
1669     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1670         return unvisitedColor;
1671
1672     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1673     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1674 }
1675
1676 const BorderValue& RenderStyle::borderBefore() const
1677 {
1678     switch (writingMode()) {
1679     case TopToBottomWritingMode:
1680         return borderTop();
1681     case BottomToTopWritingMode:
1682         return borderBottom();
1683     case LeftToRightWritingMode:
1684         return borderLeft();
1685     case RightToLeftWritingMode:
1686         return borderRight();
1687     }
1688     ASSERT_NOT_REACHED();
1689     return borderTop();
1690 }
1691
1692 const BorderValue& RenderStyle::borderAfter() const
1693 {
1694     switch (writingMode()) {
1695     case TopToBottomWritingMode:
1696         return borderBottom();
1697     case BottomToTopWritingMode:
1698         return borderTop();
1699     case LeftToRightWritingMode:
1700         return borderRight();
1701     case RightToLeftWritingMode:
1702         return borderLeft();
1703     }
1704     ASSERT_NOT_REACHED();
1705     return borderBottom();
1706 }
1707
1708 const BorderValue& RenderStyle::borderStart() const
1709 {
1710     if (isHorizontalWritingMode())
1711         return isLeftToRightDirection() ? borderLeft() : borderRight();
1712     return isLeftToRightDirection() ? borderTop() : borderBottom();
1713 }
1714
1715 const BorderValue& RenderStyle::borderEnd() const
1716 {
1717     if (isHorizontalWritingMode())
1718         return isLeftToRightDirection() ? borderRight() : borderLeft();
1719     return isLeftToRightDirection() ? borderBottom() : borderTop();
1720 }
1721
1722 float RenderStyle::borderBeforeWidth() const
1723 {
1724     switch (writingMode()) {
1725     case TopToBottomWritingMode:
1726         return borderTopWidth();
1727     case BottomToTopWritingMode:
1728         return borderBottomWidth();
1729     case LeftToRightWritingMode:
1730         return borderLeftWidth();
1731     case RightToLeftWritingMode:
1732         return borderRightWidth();
1733     }
1734     ASSERT_NOT_REACHED();
1735     return borderTopWidth();
1736 }
1737
1738 float RenderStyle::borderAfterWidth() const
1739 {
1740     switch (writingMode()) {
1741     case TopToBottomWritingMode:
1742         return borderBottomWidth();
1743     case BottomToTopWritingMode:
1744         return borderTopWidth();
1745     case LeftToRightWritingMode:
1746         return borderRightWidth();
1747     case RightToLeftWritingMode:
1748         return borderLeftWidth();
1749     }
1750     ASSERT_NOT_REACHED();
1751     return borderBottomWidth();
1752 }
1753
1754 float RenderStyle::borderStartWidth() const
1755 {
1756     if (isHorizontalWritingMode())
1757         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1758     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1759 }
1760
1761 float RenderStyle::borderEndWidth() const
1762 {
1763     if (isHorizontalWritingMode())
1764         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1765     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1766 }
1767
1768 void RenderStyle::setMarginStart(Length margin)
1769 {
1770     if (isHorizontalWritingMode()) {
1771         if (isLeftToRightDirection())
1772             setMarginLeft(margin);
1773         else
1774             setMarginRight(margin);
1775     } else {
1776         if (isLeftToRightDirection())
1777             setMarginTop(margin);
1778         else
1779             setMarginBottom(margin);
1780     }
1781 }
1782
1783 void RenderStyle::setMarginEnd(Length margin)
1784 {
1785     if (isHorizontalWritingMode()) {
1786         if (isLeftToRightDirection())
1787             setMarginRight(margin);
1788         else
1789             setMarginLeft(margin);
1790     } else {
1791         if (isLeftToRightDirection())
1792             setMarginBottom(margin);
1793         else
1794             setMarginTop(margin);
1795     }
1796 }
1797
1798 TextEmphasisMark RenderStyle::textEmphasisMark() const
1799 {
1800     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1801     if (mark != TextEmphasisMarkAuto)
1802         return mark;
1803
1804     if (isHorizontalWritingMode())
1805         return TextEmphasisMarkDot;
1806
1807     return TextEmphasisMarkSesame;
1808 }
1809
1810 #if ENABLE(TOUCH_EVENTS)
1811 Color RenderStyle::initialTapHighlightColor()
1812 {
1813     return RenderTheme::tapHighlightColor();
1814 }
1815 #endif
1816
1817 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1818 {
1819     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1820                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1821                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1822                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1823 }
1824
1825 std::pair<FontOrientation, NonCJKGlyphOrientation> RenderStyle::fontAndGlyphOrientation()
1826 {
1827     // FIXME: TextOrientationSideways should map to sideways-left in vertical-lr, which is not supported yet.
1828
1829     if (isHorizontalWritingMode())
1830         return { Horizontal, NonCJKGlyphOrientation::Mixed };
1831
1832     switch (textOrientation()) {
1833     case TextOrientation::Mixed:
1834         return { Vertical, NonCJKGlyphOrientation::Mixed };
1835     case TextOrientation::Upright:
1836         return { Vertical, NonCJKGlyphOrientation::Upright };
1837     case TextOrientation::Sideways:
1838         return { Horizontal, NonCJKGlyphOrientation::Mixed };
1839     default:
1840         ASSERT_NOT_REACHED();
1841         return { Horizontal, NonCJKGlyphOrientation::Mixed };
1842     }
1843 }
1844
1845 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1846 {
1847     if (surround->border.m_image.image() == image.get())
1848         return;
1849     surround.access()->border.m_image.setImage(image);
1850 }
1851
1852 void RenderStyle::setBorderImageSlices(LengthBox slices)
1853 {
1854     if (surround->border.m_image.imageSlices() == slices)
1855         return;
1856     surround.access()->border.m_image.setImageSlices(slices);
1857 }
1858
1859 void RenderStyle::setBorderImageWidth(LengthBox slices)
1860 {
1861     if (surround->border.m_image.borderSlices() == slices)
1862         return;
1863     surround.access()->border.m_image.setBorderSlices(slices);
1864 }
1865
1866 void RenderStyle::setBorderImageOutset(LengthBox outset)
1867 {
1868     if (surround->border.m_image.outset() == outset)
1869         return;
1870     surround.access()->border.m_image.setOutset(outset);
1871 }
1872
1873 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
1874 {
1875     if (paginationMode == Pagination::Unpaginated)
1876         return;
1877     
1878     setColumnFill(ColumnFillAuto);
1879     
1880     switch (paginationMode) {
1881     case Pagination::LeftToRightPaginated:
1882         setColumnAxis(HorizontalColumnAxis);
1883         if (isHorizontalWritingMode())
1884             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1885         else
1886             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1887         break;
1888     case Pagination::RightToLeftPaginated:
1889         setColumnAxis(HorizontalColumnAxis);
1890         if (isHorizontalWritingMode())
1891             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1892         else
1893             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1894         break;
1895     case Pagination::TopToBottomPaginated:
1896         setColumnAxis(VerticalColumnAxis);
1897         if (isHorizontalWritingMode())
1898             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1899         else
1900             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1901         break;
1902     case Pagination::BottomToTopPaginated:
1903         setColumnAxis(VerticalColumnAxis);
1904         if (isHorizontalWritingMode())
1905             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1906         else
1907             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1908         break;
1909     case Pagination::Unpaginated:
1910         ASSERT_NOT_REACHED();
1911         break;
1912     }
1913 }
1914
1915 #if ENABLE(CSS_SCROLL_SNAP)
1916 LengthSize RenderStyle::initialScrollSnapDestination()
1917 {
1918     return defaultScrollSnapDestination();
1919 }
1920
1921 Vector<LengthSize> RenderStyle::initialScrollSnapCoordinates()
1922 {
1923     return Vector<LengthSize>();
1924 }
1925
1926 const ScrollSnapPoints* RenderStyle::scrollSnapPointsX() const
1927 {
1928     return rareNonInheritedData->m_scrollSnapPoints->xPoints.get();
1929 }
1930
1931 const ScrollSnapPoints* RenderStyle::scrollSnapPointsY() const
1932 {
1933     return rareNonInheritedData->m_scrollSnapPoints->yPoints.get();
1934 }
1935
1936 const LengthSize& RenderStyle::scrollSnapDestination() const
1937 {
1938     return rareNonInheritedData->m_scrollSnapPoints->destination;
1939 }
1940
1941 const Vector<LengthSize>& RenderStyle::scrollSnapCoordinates() const
1942 {
1943     return rareNonInheritedData->m_scrollSnapPoints->coordinates;
1944 }
1945
1946 void RenderStyle::setScrollSnapPointsX(std::unique_ptr<ScrollSnapPoints> points)
1947 {
1948     if (rareNonInheritedData->m_scrollSnapPoints->xPoints.get() == points.get())
1949         return;
1950     rareNonInheritedData.access()->m_scrollSnapPoints.access()->xPoints = WTFMove(points);
1951 }
1952
1953 void RenderStyle::setScrollSnapPointsY(std::unique_ptr<ScrollSnapPoints> points)
1954 {
1955     if (rareNonInheritedData->m_scrollSnapPoints->yPoints.get() == points.get())
1956         return;
1957     rareNonInheritedData.access()->m_scrollSnapPoints.access()->yPoints = WTFMove(points);
1958 }
1959
1960 void RenderStyle::setScrollSnapDestination(LengthSize destination)
1961 {
1962     if (rareNonInheritedData->m_scrollSnapPoints->destination == destination)
1963         return;
1964     rareNonInheritedData.access()->m_scrollSnapPoints.access()->destination = WTFMove(destination);
1965 }
1966
1967 void RenderStyle::setScrollSnapCoordinates(Vector<LengthSize> coordinates)
1968 {
1969     if (rareNonInheritedData->m_scrollSnapPoints->coordinates == coordinates)
1970         return;
1971     rareNonInheritedData.access()->m_scrollSnapPoints.access()->coordinates = WTFMove(coordinates);
1972 }
1973
1974 #endif
1975
1976 void RenderStyle::checkVariablesInCustomProperties()
1977 {
1978     if (!rareInheritedData->m_customProperties->containsVariables())
1979         return;
1980     
1981     // Our first pass checks the variables for validity and replaces any properties that became
1982     // invalid with empty values.
1983     auto& customProperties = rareInheritedData.access()->m_customProperties.access()->values();
1984     HashSet<AtomicString> invalidProperties;
1985     for (auto entry : customProperties) {
1986         if (!entry.value->isVariableDependentValue())
1987             continue;
1988         HashSet<AtomicString> seenProperties;
1989         downcast<CSSVariableDependentValue>(*entry.value).checkVariablesForCycles(entry.key, customProperties, seenProperties, invalidProperties);
1990     }
1991     
1992     // Now insert invalid values.
1993     if (!invalidProperties.isEmpty()) {
1994         RefPtr<CSSValue> invalidValue = CSSCustomPropertyValue::createInvalid();
1995         for (auto& property : invalidProperties)
1996             customProperties.set(property, invalidValue);
1997     }
1998
1999     // Now that all of the properties have been tested for validity and replaced with
2000     // invalid values if they failed, we can perform variable substitution on the valid values.
2001     Vector<RefPtr<CSSCustomPropertyValue>> resolvedValues;
2002     for (auto entry : customProperties) {
2003         if (!entry.value->isVariableDependentValue())
2004             continue;
2005         
2006         CSSParserValueList parserList;
2007         RefPtr<CSSCustomPropertyValue> result;
2008         if (!downcast<CSSVariableDependentValue>(*entry.value).valueList()->buildParserValueListSubstitutingVariables(&parserList, customProperties)) {
2009             RefPtr<CSSValue> invalidResult = CSSCustomPropertyValue::createInvalid();
2010             result = CSSCustomPropertyValue::create(entry.key, invalidResult);
2011         } else {
2012             RefPtr<CSSValue> newValueList = CSSValueList::createFromParserValueList(parserList);
2013             result = CSSCustomPropertyValue::create(entry.key, newValueList);
2014         }
2015         resolvedValues.append(result);
2016     }
2017     
2018     // With all results computed, we can now mutate our table to eliminate the variables and
2019     // hold the final values. This way when we inherit, we don't end up resubstituting variables, etc.
2020     for (auto& resolvedValue : resolvedValues)
2021         customProperties.set(resolvedValue->name(), resolvedValue->value());
2022
2023     rareInheritedData.access()->m_customProperties.access()->setContainsVariables(false);
2024 }
2025
2026 float RenderStyle::outlineWidth() const
2027 {
2028     if (m_background->outline().style() == BNONE)
2029         return 0;
2030     if (outlineStyleIsAuto())
2031         return std::max(m_background->outline().width(), RenderTheme::platformFocusRingWidth());
2032     return m_background->outline().width();
2033 }
2034
2035 float RenderStyle::outlineOffset() const
2036 {
2037     if (m_background->outline().style() == BNONE)
2038         return 0;
2039     if (outlineStyleIsAuto())
2040         return (m_background->outline().offset() + RenderTheme::platformFocusRingOffset(outlineWidth()));
2041     return m_background->outline().offset();
2042 }
2043
2044 } // namespace WebCore