f4b38ddae994258f7d1a82377285d71078e5935e
[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         uint64_t m_flags;
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 ENABLE(CSS_SHAPES)
419         if (rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin)
420             return true;
421 #endif
422
423         if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
424             && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
425             return true;
426
427         if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
428             && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
429             return true;
430         if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
431             || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
432             || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
433             || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
434             || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
435             return true;
436
437         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
438         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
439             return true;
440
441         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
442             return true;
443
444         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
445             && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
446             return true;
447
448         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
449             && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
450             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
451             // Don't return; keep looking for another change
452         }
453
454 #if ENABLE(CSS_GRID_LAYOUT)
455         if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
456             || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
457             return true;
458 #endif
459
460 #if ENABLE(DASHBOARD_SUPPORT)
461         // If regions change, trigger a relayout to re-calc regions.
462         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
463             return true;
464 #endif
465     }
466
467     if (rareInheritedData.get() != other->rareInheritedData.get()) {
468         if (rareInheritedData->indent != other->rareInheritedData->indent
469 #if ENABLE(CSS3_TEXT)
470             || rareInheritedData->m_textAlignLast != other->rareInheritedData->m_textAlignLast
471             || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
472 #endif
473             || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
474 #if ENABLE(IOS_TEXT_AUTOSIZING)
475             || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
476 #endif
477             || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
478             || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
479             || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
480             || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
481             || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
482             || rareInheritedData->hyphens != other->rareInheritedData->hyphens
483             || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
484             || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
485             || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
486             || rareInheritedData->locale != other->rareInheritedData->locale
487             || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
488             || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
489             || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
490             || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
491             || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
492             || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
493             || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
494             || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
495 #if ENABLE(CSS_IMAGE_ORIENTATION)
496             || rareInheritedData->m_imageOrientation != other->rareInheritedData->m_imageOrientation
497 #endif
498 #if ENABLE(CSS_IMAGE_RESOLUTION)
499             || rareInheritedData->m_imageResolutionSource != other->rareInheritedData->m_imageResolutionSource
500             || rareInheritedData->m_imageResolutionSnap != other->rareInheritedData->m_imageResolutionSnap
501             || rareInheritedData->m_imageResolution != other->rareInheritedData->m_imageResolution
502 #endif
503             || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
504             || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
505 #if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
506             || rareInheritedData->useTouchOverflowScrolling != other->rareInheritedData->useTouchOverflowScrolling
507 #endif
508             || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
509             return true;
510
511         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
512             return true;
513
514         if (textStrokeWidth() != other->textStrokeWidth())
515             return true;
516     }
517
518 #if ENABLE(TEXT_AUTOSIZING)
519     if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
520         return true;
521 #endif
522
523     if (inherited->line_height != other->inherited->line_height
524 #if ENABLE(IOS_TEXT_AUTOSIZING)
525         || inherited->specifiedLineHeight != other->inherited->specifiedLineHeight
526 #endif
527         || inherited->font != other->inherited->font
528         || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
529         || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
530         || inherited_flags._box_direction != other->inherited_flags._box_direction
531         || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
532         || noninherited_flags.position() != other->noninherited_flags.position()
533         || noninherited_flags.floating() != other->noninherited_flags.floating()
534         || noninherited_flags.originalDisplay() != other->noninherited_flags.originalDisplay())
535         return true;
536
537
538     if ((noninherited_flags.effectiveDisplay()) >= TABLE) {
539         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
540             || inherited_flags._empty_cells != other->inherited_flags._empty_cells
541             || inherited_flags._caption_side != other->inherited_flags._caption_side
542             || noninherited_flags.tableLayout() != other->noninherited_flags.tableLayout())
543             return true;
544
545         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
546         // does not, so these style differences can be width differences.
547         if (inherited_flags._border_collapse
548             && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
549                 || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
550                 || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
551                 || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
552                 || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
553                 || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
554                 || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
555                 || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
556             return true;
557     }
558
559     if (noninherited_flags.effectiveDisplay() == LIST_ITEM) {
560         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
561             || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
562             return true;
563     }
564
565     if (inherited_flags._text_align != other->inherited_flags._text_align
566         || inherited_flags._text_transform != other->inherited_flags._text_transform
567         || inherited_flags._direction != other->inherited_flags._direction
568         || inherited_flags._white_space != other->inherited_flags._white_space
569         || noninherited_flags.clear() != other->noninherited_flags.clear()
570         || noninherited_flags.unicodeBidi() != other->noninherited_flags.unicodeBidi())
571         return true;
572
573     // Check block flow direction.
574     if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
575         return true;
576
577     // Check text combine mode.
578     if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
579         return true;
580
581     // Overflow returns a layout hint.
582     if (noninherited_flags.overflowX() != other->noninherited_flags.overflowX()
583         || noninherited_flags.overflowY() != other->noninherited_flags.overflowY())
584         return true;
585
586     // If our border widths change, then we need to layout.  Other changes to borders
587     // only necessitate a repaint.
588     if (borderLeftWidth() != other->borderLeftWidth()
589         || borderTopWidth() != other->borderTopWidth()
590         || borderBottomWidth() != other->borderBottomWidth()
591         || borderRightWidth() != other->borderRightWidth())
592         return true;
593
594     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
595     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
596     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
597     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
598         return true;
599
600     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
601         return true;
602
603     if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
604         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
605         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
606         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
607         // In addition we need to solve the floating object issue when layers come and go. Right now
608         // a full layout is necessary to keep floating object lists sane.
609         return true;
610     }
611
612 #if ENABLE(CSS_FILTERS)
613     if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
614         return true;
615 #endif
616
617     const QuotesData* quotesDataA = rareInheritedData->quotes.get();
618     const QuotesData* quotesDataB = other->rareInheritedData->quotes.get();
619     if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB)))
620         return true;
621
622     if (position() != StaticPosition) {
623         if (surround->offset != other->surround->offset) {
624             // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
625             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
626             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
627             if (position() != AbsolutePosition)
628                 return true;
629
630             // Optimize for the case where a positioned layer is moving but not changing size.
631             if (!positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
632                 return true;
633         }
634     }
635     
636     return false;
637 }
638
639 bool RenderStyle::changeRequiresPositionedLayoutOnly(const RenderStyle* other, unsigned&) const
640 {
641     if (position() == StaticPosition)
642         return false;
643
644     if (surround->offset != other->surround->offset) {
645         // Optimize for the case where a positioned layer is moving but not changing size.
646         if (position() == AbsolutePosition && positionChangeIsMovementOnly(surround->offset, other->surround->offset, m_box->width()))
647             return true;
648     }
649     
650     return false;
651 }
652
653 bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
654 {
655     if (position() != StaticPosition) {
656         if (m_box->zIndex() != other->m_box->zIndex()
657             || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
658             || visual->clip != other->visual->clip
659             || visual->hasClip != other->visual->hasClip)
660             return true;
661     }
662
663 #if ENABLE(CSS_COMPOSITING)
664     if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
665         return true;
666 #endif
667
668     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
669         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
670         // Don't return; keep looking for another change.
671     }
672
673 #if ENABLE(CSS_FILTERS)
674     if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
675         && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
676         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
677         // Don't return; keep looking for another change.
678     }
679 #endif
680
681     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
682         || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
683         return true;
684
685     return false;
686 }
687
688 bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const
689 {
690     if (inherited_flags._visibility != other->inherited_flags._visibility
691         || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
692         || inherited_flags._insideLink != other->inherited_flags._insideLink
693         || surround->border != other->surround->border
694         || !m_background->isEquivalentForPainting(*other->m_background)
695         || rareInheritedData->userModify != other->rareInheritedData->userModify
696         || rareInheritedData->userSelect != other->rareInheritedData->userSelect
697         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
698         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
699         || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
700         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
701         return true;
702
703 #if ENABLE(CSS_SHAPES)
704     if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
705         return true;
706 #endif
707
708     if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
709         return true;
710
711     return false;
712 }
713
714 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
715 {
716     if (inherited->color != other->inherited->color
717         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
718         || visual->textDecoration != other->visual->textDecoration
719         || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
720         || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
721         || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip
722         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
723         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
724         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
725         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
726         return true;
727
728     return false;
729 }
730
731 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const
732 {
733     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
734         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
735             || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
736             || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
737             || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
738             || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
739             return true;
740     }
741
742     return false;
743 }
744
745 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
746 {
747     changedContextSensitiveProperties = ContextSensitivePropertyNone;
748
749     StyleDifference svgChange = StyleDifferenceEqual;
750     if (m_svgStyle != other->m_svgStyle) {
751         svgChange = m_svgStyle->diff(other->m_svgStyle.get());
752         if (svgChange == StyleDifferenceLayout)
753             return svgChange;
754     }
755
756     if (changeRequiresLayout(other, changedContextSensitiveProperties))
757         return StyleDifferenceLayout;
758
759     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
760     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
761     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
762     // that are relevant for SVG and might return StyleDifferenceLayout.
763     if (svgChange != StyleDifferenceEqual)
764         return svgChange;
765
766     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
767         return StyleDifferenceLayoutPositionedMovementOnly;
768
769     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
770         return StyleDifferenceRepaintLayer;
771
772     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
773         return StyleDifferenceRepaint;
774
775     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
776         return StyleDifferenceRecompositeLayer;
777
778     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
779         return StyleDifferenceRepaintIfTextOrBorderOrOutline;
780
781     // Cursors are not checked, since they will be set appropriately in response to mouse events,
782     // so they don't need to cause any repaint or layout.
783
784     // 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
785     // the resulting transition properly.
786     return StyleDifferenceEqual;
787 }
788
789 bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const
790 {
791     unsigned changedContextSensitiveProperties = 0;
792     return changeRequiresRepaint(style, changedContextSensitiveProperties);
793 }
794
795 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
796 {
797     StyleVisualData* data = visual.access();
798     data->clip.m_top = top;
799     data->clip.m_right = right;
800     data->clip.m_bottom = bottom;
801     data->clip.m_left = left;
802 }
803
804 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
805 {
806     if (!rareInheritedData.access()->cursorData)
807         rareInheritedData.access()->cursorData = CursorList::create();
808     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
809 }
810
811 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
812 {
813     rareInheritedData.access()->cursorData = other;
814 }
815
816 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
817 {
818     if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q))
819         return;
820
821     rareInheritedData.access()->quotes = q;
822 }
823
824 void RenderStyle::clearCursorList()
825 {
826     if (rareInheritedData->cursorData)
827         rareInheritedData.access()->cursorData = 0;
828 }
829
830 void RenderStyle::clearContent()
831 {
832     if (rareNonInheritedData->m_content)
833         rareNonInheritedData.access()->m_content = nullptr;
834 }
835
836 void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData)
837 {
838     auto& content = rareNonInheritedData.access()->m_content;
839     ContentData* lastContent = content.get();
840     while (lastContent && lastContent->next())
841         lastContent = lastContent->next();
842
843     if (lastContent)
844         lastContent->setNext(std::move(contentData));
845     else
846         content = std::move(contentData);
847 }
848
849 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
850 {
851     if (!image)
852         return;
853         
854     if (add) {
855         appendContent(std::make_unique<ImageContentData>(image));
856         return;
857     }
858
859     rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image);
860     if (!rareNonInheritedData.access()->m_altText.isNull())
861         rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText);
862 }
863
864 void RenderStyle::setContent(const String& string, bool add)
865 {
866     auto& content = rareNonInheritedData.access()->m_content;
867     if (add) {
868         ContentData* lastContent = content.get();
869         while (lastContent && lastContent->next())
870             lastContent = lastContent->next();
871
872         if (lastContent) {
873             // We attempt to merge with the last ContentData if possible.
874             if (lastContent->isText()) {
875                 TextContentData* textContent = toTextContentData(lastContent);
876                 textContent->setText(textContent->text() + string);
877             } else
878                 lastContent->setNext(std::make_unique<TextContentData>(string));
879
880             if (!rareNonInheritedData.access()->m_altText.isNull())
881                 lastContent->setAltText(rareNonInheritedData.access()->m_altText);
882             return;
883         }
884     }
885
886     content = std::make_unique<TextContentData>(string);
887     if (!rareNonInheritedData.access()->m_altText.isNull())
888         content->setAltText(rareNonInheritedData.access()->m_altText);
889 }
890
891 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
892 {
893     if (!counter)
894         return;
895
896     if (add) {
897         appendContent(std::make_unique<CounterContentData>(std::move(counter)));
898         return;
899     }
900
901     rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(std::move(counter));
902 }
903
904 void RenderStyle::setContent(QuoteType quote, bool add)
905 {
906     if (add) {
907         appendContent(std::make_unique<QuoteContentData>(quote));
908         return;
909     }
910
911     rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote);
912 }
913
914 void RenderStyle::setContentAltText(const String& string)
915 {
916     rareNonInheritedData.access()->m_altText = string;
917     
918     if (rareNonInheritedData.access()->m_content)
919         rareNonInheritedData.access()->m_content->setAltText(string);
920 }
921
922 const String& RenderStyle::contentAltText() const
923 {
924     return rareNonInheritedData->m_altText;
925 }
926
927 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
928 {
929     // transform-origin brackets the transform with translate operations.
930     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
931     // in that case.
932     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
933         return false;
934
935     for (auto& operation : transformOperations) {
936         TransformOperation::OperationType type = operation->type();
937         if (type != TransformOperation::TRANSLATE_X
938             && type != TransformOperation::TRANSLATE_Y
939             && type != TransformOperation::TRANSLATE 
940             && type != TransformOperation::TRANSLATE_Z
941             && type != TransformOperation::TRANSLATE_3D)
942             return true;
943     }
944
945     return false;
946 }
947
948 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
949 {
950     auto& operations = rareNonInheritedData->m_transform->m_operations.operations();
951     bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
952
953     float offsetX = transformOriginX().isPercentNotCalculated() ? boundingBox.x() : 0;
954     float offsetY = transformOriginY().isPercentNotCalculated() ? boundingBox.y() : 0;
955
956     if (applyTransformOrigin) {
957         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
958                               floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
959                               transformOriginZ());
960     }
961
962     for (auto& operation : operations)
963         operation->apply(transform, boundingBox.size());
964
965     if (applyTransformOrigin) {
966         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
967                               -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
968                               -transformOriginZ());
969     }
970 }
971
972 void RenderStyle::setPageScaleTransform(float scale)
973 {
974     if (scale == 1)
975         return;
976     TransformOperations transform;
977     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
978     setTransform(transform);
979     setTransformOriginX(Length(0, Fixed));
980     setTransformOriginY(Length(0, Fixed));
981 }
982
983 void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
984 {
985     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
986
987     StyleRareInheritedData* rareData = rareInheritedData.access();
988     if (!add) {
989         rareData->textShadow = std::move(shadowData);
990         return;
991     }
992
993     shadowData->setNext(std::move(rareData->textShadow));
994     rareData->textShadow = std::move(shadowData);
995 }
996
997 void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
998 {
999     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
1000     if (!add) {
1001         rareData->m_boxShadow = std::move(shadowData);
1002         return;
1003     }
1004
1005     shadowData->setNext(std::move(rareData->m_boxShadow));
1006     rareData->m_boxShadow = std::move(shadowData);
1007 }
1008
1009 static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size, RenderView* renderView)
1010 {
1011     return RoundedRect::Radii(
1012         LayoutSize(valueForLength(border.topLeft().width(), size.width(), renderView),
1013             valueForLength(border.topLeft().height(), size.height(), renderView)),
1014         LayoutSize(valueForLength(border.topRight().width(), size.width(), renderView),
1015             valueForLength(border.topRight().height(), size.height(), renderView)),
1016         LayoutSize(valueForLength(border.bottomLeft().width(), size.width(), renderView),
1017             valueForLength(border.bottomLeft().height(), size.height(), renderView)),
1018         LayoutSize(valueForLength(border.bottomRight().width(), size.width(), renderView),
1019             valueForLength(border.bottomRight().height(), size.height(), renderView)));
1020 }
1021
1022 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
1023 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
1024 {
1025     if (rareInheritedData->listStyleImage != v)
1026         rareInheritedData.access()->listStyleImage = v;
1027 }
1028
1029 Color RenderStyle::color() const { return inherited->color; }
1030 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
1031 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
1032 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
1033
1034 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
1035 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
1036 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
1037 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
1038
1039 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1040 {
1041     RoundedRect roundedRect(borderRect);
1042     if (hasBorderRadius()) {
1043         RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size(), renderView);
1044         radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
1045         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1046     }
1047     return roundedRect;
1048 }
1049
1050 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1051 {
1052     bool horizontal = isHorizontalWritingMode();
1053
1054     LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1055     LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1056     LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1057     LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1058
1059     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1060 }
1061
1062 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
1063     LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1064 {
1065     LayoutRect innerRect(borderRect.x() + leftWidth, 
1066                borderRect.y() + topWidth, 
1067                borderRect.width() - leftWidth - rightWidth, 
1068                borderRect.height() - topWidth - bottomWidth);
1069
1070     RoundedRect roundedRect(innerRect);
1071
1072     if (hasBorderRadius()) {
1073         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1074         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1075         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1076     }
1077     return roundedRect;
1078 }
1079
1080 static bool allLayersAreFixed(const FillLayer* layer)
1081 {
1082     bool allFixed = true;
1083     
1084     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1085         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1086
1087     return layer && allFixed;
1088 }
1089
1090 bool RenderStyle::hasEntirelyFixedBackground() const
1091 {
1092     return allLayersAreFixed(backgroundLayers());
1093 }
1094
1095 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1096 {
1097     return rareNonInheritedData->m_counterDirectives.get();
1098 }
1099
1100 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1101 {
1102     auto& map = rareNonInheritedData.access()->m_counterDirectives;
1103     if (!map)
1104         map = std::make_unique<CounterDirectiveMap>();
1105     return *map;
1106 }
1107
1108 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1109 {
1110     if (const CounterDirectiveMap* directives = counterDirectives())
1111         return directives->get(identifier);
1112     return CounterDirectives();
1113 }
1114
1115 const AtomicString& RenderStyle::hyphenString() const
1116 {
1117     ASSERT(hyphens() != HyphensNone);
1118
1119     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1120     if (!hyphenationString.isNull())
1121         return hyphenationString;
1122
1123     // FIXME: This should depend on locale.
1124     DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
1125     DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
1126     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1127 }
1128
1129 const AtomicString& RenderStyle::textEmphasisMarkString() const
1130 {
1131     switch (textEmphasisMark()) {
1132     case TextEmphasisMarkNone:
1133         return nullAtom;
1134     case TextEmphasisMarkCustom:
1135         return textEmphasisCustomMark();
1136     case TextEmphasisMarkDot: {
1137         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
1138         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
1139         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1140     }
1141     case TextEmphasisMarkCircle: {
1142         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
1143         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
1144         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1145     }
1146     case TextEmphasisMarkDoubleCircle: {
1147         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
1148         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
1149         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1150     }
1151     case TextEmphasisMarkTriangle: {
1152         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
1153         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
1154         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1155     }
1156     case TextEmphasisMarkSesame: {
1157         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
1158         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
1159         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1160     }
1161     case TextEmphasisMarkAuto:
1162         ASSERT_NOT_REACHED();
1163         return nullAtom;
1164     }
1165
1166     ASSERT_NOT_REACHED();
1167     return nullAtom;
1168 }
1169
1170 #if ENABLE(DASHBOARD_SUPPORT)
1171 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1172 {
1173     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
1174     return emptyList;
1175 }
1176
1177 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1178 {
1179     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
1180     static bool noneListInitialized = false;
1181
1182     if (!noneListInitialized) {
1183         StyleDashboardRegion region;
1184         region.label = "";
1185         region.offset.m_top  = Length();
1186         region.offset.m_right = Length();
1187         region.offset.m_bottom = Length();
1188         region.offset.m_left = Length();
1189         region.type = StyleDashboardRegion::None;
1190         noneList.append(region);
1191         noneListInitialized = true;
1192     }
1193     return noneList;
1194 }
1195 #endif
1196
1197 void RenderStyle::adjustAnimations()
1198 {
1199     AnimationList* animationList = rareNonInheritedData->m_animations.get();
1200     if (!animationList)
1201         return;
1202
1203     // Get rid of empty animations and anything beyond them
1204     for (size_t i = 0; i < animationList->size(); ++i) {
1205         if (animationList->animation(i).isEmpty()) {
1206             animationList->resize(i);
1207             break;
1208         }
1209     }
1210
1211     if (animationList->isEmpty()) {
1212         clearAnimations();
1213         return;
1214     }
1215
1216     // Repeat patterns into layers that don't have some properties set.
1217     animationList->fillUnsetProperties();
1218 }
1219
1220 void RenderStyle::adjustTransitions()
1221 {
1222     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1223     if (!transitionList)
1224         return;
1225
1226     // Get rid of empty transitions and anything beyond them
1227     for (size_t i = 0; i < transitionList->size(); ++i) {
1228         if (transitionList->animation(i).isEmpty()) {
1229             transitionList->resize(i);
1230             break;
1231         }
1232     }
1233
1234     if (transitionList->isEmpty()) {
1235         clearTransitions();
1236         return;
1237     }
1238
1239     // Repeat patterns into layers that don't have some properties set.
1240     transitionList->fillUnsetProperties();
1241
1242     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1243     // but the lists tend to be very short, so it is probably ok
1244     for (size_t i = 0; i < transitionList->size(); ++i) {
1245         for (size_t j = i+1; j < transitionList->size(); ++j) {
1246             if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1247                 // toss i
1248                 transitionList->remove(i);
1249                 j = i;
1250             }
1251         }
1252     }
1253 }
1254
1255 AnimationList* RenderStyle::accessAnimations()
1256 {
1257     if (!rareNonInheritedData.access()->m_animations)
1258         rareNonInheritedData.access()->m_animations = std::make_unique<AnimationList>();
1259     return rareNonInheritedData->m_animations.get();
1260 }
1261
1262 AnimationList* RenderStyle::accessTransitions()
1263 {
1264     if (!rareNonInheritedData.access()->m_transitions)
1265         rareNonInheritedData.access()->m_transitions = std::make_unique<AnimationList>();
1266     return rareNonInheritedData->m_transitions.get();
1267 }
1268
1269 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1270 {
1271     if (transitions()) {
1272         for (size_t i = 0; i < transitions()->size(); ++i) {
1273             const Animation& p = transitions()->animation(i);
1274             if (p.animationMode() == Animation::AnimateAll || p.property() == property) {
1275                 return &p;
1276             }
1277         }
1278     }
1279     return 0;
1280 }
1281
1282 const Font& RenderStyle::font() const { return inherited->font; }
1283 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
1284 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
1285 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
1286 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
1287 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
1288
1289 const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; }
1290 float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1291
1292 bool RenderStyle::setFontDescription(const FontDescription& v)
1293 {
1294     if (inherited->font.fontDescription() != v) {
1295         inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1296         return true;
1297     }
1298     return false;
1299 }
1300
1301 #if ENABLE(IOS_TEXT_AUTOSIZING)
1302 const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; }
1303 void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); }
1304 #else
1305 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1306 #endif
1307
1308 Length RenderStyle::lineHeight() const
1309 {
1310     const Length& lh = inherited->line_height;
1311 #if ENABLE(TEXT_AUTOSIZING)
1312     // Unlike fontDescription().computedSize() and hence fontSize(), this is
1313     // recalculated on demand as we only store the specified line height.
1314     // FIXME: Should consider scaling the fixed part of any calc expressions
1315     // too, though this involves messily poking into CalcExpressionLength.
1316     float multiplier = textAutosizingMultiplier();
1317     if (multiplier > 1 && lh.isFixed())
1318         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1319 #endif
1320     return lh;
1321 }
1322 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1323
1324 int RenderStyle::computedLineHeight(RenderView* renderView) const
1325 {
1326     const Length& lh = lineHeight();
1327
1328     // Negative value means the line height is not set. Use the font's built-in spacing.
1329     if (lh.isNegative())
1330         return fontMetrics().lineSpacing();
1331
1332     if (lh.isPercent())
1333         return minimumValueForLength(lh, fontSize());
1334
1335     if (lh.isViewportPercentage())
1336         return valueForLength(lh, 0, renderView);
1337
1338     return lh.value();
1339 }
1340
1341 void RenderStyle::setWordSpacing(Length value)
1342 {
1343     float fontWordSpacing;
1344     switch (value.type()) {
1345     case Auto:
1346         fontWordSpacing = 0;
1347         break;
1348     case Percent:
1349         fontWordSpacing = value.percent() * font().spaceWidth() / 100;
1350         break;
1351     case Fixed:
1352         fontWordSpacing = value.value();
1353         break;
1354     default:
1355         ASSERT_NOT_REACHED();
1356         fontWordSpacing = 0;
1357         break;
1358     }
1359     inherited.access()->font.setWordSpacing(fontWordSpacing);
1360     rareInheritedData.access()->wordSpacing = std::move(value);
1361 }
1362
1363 void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
1364
1365 void RenderStyle::setFontSize(float size)
1366 {
1367     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1368     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1369
1370     ASSERT(std::isfinite(size));
1371     if (!std::isfinite(size) || size < 0)
1372         size = 0;
1373     else
1374         size = std::min(maximumAllowedFontSize, size);
1375
1376     FontSelector* currentFontSelector = font().fontSelector();
1377     FontDescription desc(fontDescription());
1378     desc.setSpecifiedSize(size);
1379     desc.setComputedSize(size);
1380
1381 #if ENABLE(TEXT_AUTOSIZING)
1382     float multiplier = textAutosizingMultiplier();
1383     if (multiplier > 1) {
1384         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1385         desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1386     }
1387 #endif
1388
1389     setFontDescription(desc);
1390     font().update(currentFontSelector);
1391 }
1392
1393 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1394 {
1395     top = 0;
1396     right = 0;
1397     bottom = 0;
1398     left = 0;
1399
1400     for ( ; shadow; shadow = shadow->next()) {
1401         if (shadow->style() == Inset)
1402             continue;
1403
1404         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1405         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1406         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1407         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1408         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1409     }
1410 }
1411
1412 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1413 {
1414     LayoutUnit top = 0;
1415     LayoutUnit right = 0;
1416     LayoutUnit bottom = 0;
1417     LayoutUnit left = 0;
1418
1419     for ( ; shadow; shadow = shadow->next()) {
1420         if (shadow->style() == Normal)
1421             continue;
1422
1423         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1424         top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1425         right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1426         bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1427         left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1428     }
1429
1430     return LayoutBoxExtent(top, right, bottom, left);
1431 }
1432
1433 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1434 {
1435     left = 0;
1436     right = 0;
1437
1438     for ( ; shadow; shadow = shadow->next()) {
1439         if (shadow->style() == Inset)
1440             continue;
1441
1442         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1443         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1444         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1445     }
1446 }
1447
1448 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1449 {
1450     top = 0;
1451     bottom = 0;
1452
1453     for ( ; shadow; shadow = shadow->next()) {
1454         if (shadow->style() == Inset)
1455             continue;
1456
1457         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1458         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1459         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1460     }
1461 }
1462
1463 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1464 {
1465     Color result;
1466     EBorderStyle borderStyle = BNONE;
1467     switch (colorProperty) {
1468     case CSSPropertyBackgroundColor:
1469         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1470     case CSSPropertyBorderLeftColor:
1471         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1472         borderStyle = borderLeftStyle();
1473         break;
1474     case CSSPropertyBorderRightColor:
1475         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1476         borderStyle = borderRightStyle();
1477         break;
1478     case CSSPropertyBorderTopColor:
1479         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1480         borderStyle = borderTopStyle();
1481         break;
1482     case CSSPropertyBorderBottomColor:
1483         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1484         borderStyle = borderBottomStyle();
1485         break;
1486     case CSSPropertyColor:
1487         result = visitedLink ? visitedLinkColor() : color();
1488         break;
1489     case CSSPropertyOutlineColor:
1490         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1491         break;
1492     case CSSPropertyWebkitColumnRuleColor:
1493         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1494         break;
1495     case CSSPropertyWebkitTextDecorationColor:
1496         // Text decoration color fallback is handled in RenderObject::decorationColor.
1497         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1498     case CSSPropertyWebkitTextEmphasisColor:
1499         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1500         break;
1501     case CSSPropertyWebkitTextFillColor:
1502         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1503         break;
1504     case CSSPropertyWebkitTextStrokeColor:
1505         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1506         break;
1507     default:
1508         ASSERT_NOT_REACHED();
1509         break;
1510     }
1511
1512     if (!result.isValid()) {
1513         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1514             result.setRGB(238, 238, 238);
1515         else
1516             result = visitedLink ? visitedLinkColor() : color();
1517     }
1518     return result;
1519 }
1520
1521 Color RenderStyle::visitedDependentColor(int colorProperty) const
1522 {
1523     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1524     if (insideLink() != InsideVisitedLink)
1525         return unvisitedColor;
1526
1527     Color visitedColor = colorIncludingFallback(colorProperty, true);
1528
1529     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1530     if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1531         return visitedColor;
1532
1533     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1534     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1535     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1536     // have to match, it makes more sense to return the unvisited background color if specified than it
1537     // does to return black. This behavior matches what Firefox 4 does as well.
1538     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1539         return unvisitedColor;
1540
1541     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1542     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1543 }
1544
1545 const BorderValue& RenderStyle::borderBefore() const
1546 {
1547     switch (writingMode()) {
1548     case TopToBottomWritingMode:
1549         return borderTop();
1550     case BottomToTopWritingMode:
1551         return borderBottom();
1552     case LeftToRightWritingMode:
1553         return borderLeft();
1554     case RightToLeftWritingMode:
1555         return borderRight();
1556     }
1557     ASSERT_NOT_REACHED();
1558     return borderTop();
1559 }
1560
1561 const BorderValue& RenderStyle::borderAfter() const
1562 {
1563     switch (writingMode()) {
1564     case TopToBottomWritingMode:
1565         return borderBottom();
1566     case BottomToTopWritingMode:
1567         return borderTop();
1568     case LeftToRightWritingMode:
1569         return borderRight();
1570     case RightToLeftWritingMode:
1571         return borderLeft();
1572     }
1573     ASSERT_NOT_REACHED();
1574     return borderBottom();
1575 }
1576
1577 const BorderValue& RenderStyle::borderStart() const
1578 {
1579     if (isHorizontalWritingMode())
1580         return isLeftToRightDirection() ? borderLeft() : borderRight();
1581     return isLeftToRightDirection() ? borderTop() : borderBottom();
1582 }
1583
1584 const BorderValue& RenderStyle::borderEnd() const
1585 {
1586     if (isHorizontalWritingMode())
1587         return isLeftToRightDirection() ? borderRight() : borderLeft();
1588     return isLeftToRightDirection() ? borderBottom() : borderTop();
1589 }
1590
1591 float RenderStyle::borderBeforeWidth() const
1592 {
1593     switch (writingMode()) {
1594     case TopToBottomWritingMode:
1595         return borderTopWidth();
1596     case BottomToTopWritingMode:
1597         return borderBottomWidth();
1598     case LeftToRightWritingMode:
1599         return borderLeftWidth();
1600     case RightToLeftWritingMode:
1601         return borderRightWidth();
1602     }
1603     ASSERT_NOT_REACHED();
1604     return borderTopWidth();
1605 }
1606
1607 float RenderStyle::borderAfterWidth() const
1608 {
1609     switch (writingMode()) {
1610     case TopToBottomWritingMode:
1611         return borderBottomWidth();
1612     case BottomToTopWritingMode:
1613         return borderTopWidth();
1614     case LeftToRightWritingMode:
1615         return borderRightWidth();
1616     case RightToLeftWritingMode:
1617         return borderLeftWidth();
1618     }
1619     ASSERT_NOT_REACHED();
1620     return borderBottomWidth();
1621 }
1622
1623 float RenderStyle::borderStartWidth() const
1624 {
1625     if (isHorizontalWritingMode())
1626         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1627     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1628 }
1629
1630 float RenderStyle::borderEndWidth() const
1631 {
1632     if (isHorizontalWritingMode())
1633         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1634     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1635 }
1636
1637 void RenderStyle::setMarginStart(Length margin)
1638 {
1639     if (isHorizontalWritingMode()) {
1640         if (isLeftToRightDirection())
1641             setMarginLeft(margin);
1642         else
1643             setMarginRight(margin);
1644     } else {
1645         if (isLeftToRightDirection())
1646             setMarginTop(margin);
1647         else
1648             setMarginBottom(margin);
1649     }
1650 }
1651
1652 void RenderStyle::setMarginEnd(Length margin)
1653 {
1654     if (isHorizontalWritingMode()) {
1655         if (isLeftToRightDirection())
1656             setMarginRight(margin);
1657         else
1658             setMarginLeft(margin);
1659     } else {
1660         if (isLeftToRightDirection())
1661             setMarginBottom(margin);
1662         else
1663             setMarginTop(margin);
1664     }
1665 }
1666
1667 TextEmphasisMark RenderStyle::textEmphasisMark() const
1668 {
1669     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1670     if (mark != TextEmphasisMarkAuto)
1671         return mark;
1672
1673     if (isHorizontalWritingMode())
1674         return TextEmphasisMarkDot;
1675
1676     return TextEmphasisMarkSesame;
1677 }
1678
1679 #if ENABLE(TOUCH_EVENTS)
1680 Color RenderStyle::initialTapHighlightColor()
1681 {
1682     return RenderTheme::tapHighlightColor();
1683 }
1684 #endif
1685
1686 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1687 {
1688     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1689                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1690                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1691                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1692 }
1693
1694 void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
1695 {
1696     if (isHorizontalWritingMode()) {
1697         fontOrientation = Horizontal;
1698         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1699         return;
1700     }
1701
1702     switch (textOrientation()) {
1703     case TextOrientationVerticalRight:
1704         fontOrientation = Vertical;
1705         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1706         return;
1707     case TextOrientationUpright:
1708         fontOrientation = Vertical;
1709         glyphOrientation = NonCJKGlyphOrientationUpright;
1710         return;
1711     case TextOrientationSideways:
1712         if (writingMode() == LeftToRightWritingMode) {
1713             // FIXME: This should map to sideways-left, which is not supported yet.
1714             fontOrientation = Vertical;
1715             glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1716             return;
1717         }
1718         fontOrientation = Horizontal;
1719         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1720         return;
1721     case TextOrientationSidewaysRight:
1722         fontOrientation = Horizontal;
1723         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1724         return;
1725     default:
1726         ASSERT_NOT_REACHED();
1727         fontOrientation = Horizontal;
1728         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1729         return;
1730     }
1731 }
1732
1733 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1734 {
1735     if (surround->border.m_image.image() == image.get())
1736         return;
1737     surround.access()->border.m_image.setImage(image);
1738 }
1739
1740 void RenderStyle::setBorderImageSlices(LengthBox slices)
1741 {
1742     if (surround->border.m_image.imageSlices() == slices)
1743         return;
1744     surround.access()->border.m_image.setImageSlices(slices);
1745 }
1746
1747 void RenderStyle::setBorderImageWidth(LengthBox slices)
1748 {
1749     if (surround->border.m_image.borderSlices() == slices)
1750         return;
1751     surround.access()->border.m_image.setBorderSlices(slices);
1752 }
1753
1754 void RenderStyle::setBorderImageOutset(LengthBox outset)
1755 {
1756     if (surround->border.m_image.outset() == outset)
1757         return;
1758     surround.access()->border.m_image.setOutset(outset);
1759 }
1760
1761 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
1762 {
1763     if (paginationMode == Pagination::Unpaginated)
1764         return;
1765     
1766     setColumnFill(ColumnFillAuto);
1767     
1768     switch (paginationMode) {
1769     case Pagination::LeftToRightPaginated:
1770         setColumnAxis(HorizontalColumnAxis);
1771         if (isHorizontalWritingMode())
1772             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1773         else
1774             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1775         break;
1776     case Pagination::RightToLeftPaginated:
1777         setColumnAxis(HorizontalColumnAxis);
1778         if (isHorizontalWritingMode())
1779             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1780         else
1781             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1782         break;
1783     case Pagination::TopToBottomPaginated:
1784         setColumnAxis(VerticalColumnAxis);
1785         if (isHorizontalWritingMode())
1786             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1787         else
1788             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1789         break;
1790     case Pagination::BottomToTopPaginated:
1791         setColumnAxis(VerticalColumnAxis);
1792         if (isHorizontalWritingMode())
1793             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1794         else
1795             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1796         break;
1797     case Pagination::Unpaginated:
1798         ASSERT_NOT_REACHED();
1799         break;
1800     }
1801 }
1802
1803 } // namespace WebCore