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