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