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