Text decorations do not contribute to visual overflow
[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 "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
56 namespace WebCore {
57
58 struct SameSizeAsBorderValue {
59     float m_width;
60     RGBA32 m_color;
61     int m_restBits;
62 };
63
64 COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
65
66 struct 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
79 COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
80
81 inline RenderStyle& defaultStyle()
82 {
83     static RenderStyle& style = RenderStyle::createDefaultStyle().leakRef();
84     return style;
85 }
86
87 PassRef<RenderStyle> RenderStyle::create()
88 {
89     return adoptRef(*new RenderStyle(defaultStyle()));
90 }
91
92 PassRef<RenderStyle> RenderStyle::createDefaultStyle()
93 {
94     return adoptRef(*new RenderStyle(true));
95 }
96
97 PassRef<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
106 PassRef<RenderStyle> RenderStyle::clone(const RenderStyle* other)
107 {
108     return adoptRef(*new RenderStyle(*other));
109 }
110
111 PassRef<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
120 ALWAYS_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
156 ALWAYS_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
171 void 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
187 void 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
202 bool 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
218 bool RenderStyle::isStyleAvailable() const
219 {
220     return this != StyleResolver::styleNotYetAvailable();
221 }
222
223 bool 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
237 RenderStyle* 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
254 RenderStyle* 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
271 void 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
284 bool 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)
293 inline 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
302 uint32_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
327 bool 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
350 bool 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
359 static 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
386 inline 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
406 bool 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
660 bool 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
674 bool RenderStyle::changeRequiresLayerRepaint(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
675 {
676     if (position() != StaticPosition) {
677         if (m_box->zIndex() != other->m_box->zIndex()
678             || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
679             || visual->clip != other->visual->clip
680             || visual->hasClip != other->visual->hasClip)
681             return true;
682     }
683
684 #if ENABLE(CSS_COMPOSITING)
685     if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
686         return true;
687 #endif
688
689     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
690         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
691         // Don't return; keep looking for another change.
692     }
693
694 #if ENABLE(CSS_FILTERS)
695     if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
696         && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
697         changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
698         // Don't return; keep looking for another change.
699     }
700 #endif
701
702     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
703         || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
704         return true;
705
706     return false;
707 }
708
709 bool RenderStyle::changeRequiresRepaint(const RenderStyle* other, unsigned&) const
710 {
711     if (inherited_flags._visibility != other->inherited_flags._visibility
712         || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
713         || inherited_flags._insideLink != other->inherited_flags._insideLink
714         || surround->border != other->surround->border
715         || !m_background->isEquivalentForPainting(*other->m_background)
716         || rareInheritedData->userModify != other->rareInheritedData->userModify
717         || rareInheritedData->userSelect != other->rareInheritedData->userSelect
718         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
719         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
720         || rareNonInheritedData->m_objectFit != other->rareNonInheritedData->m_objectFit
721         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
722         return true;
723
724 #if ENABLE(CSS_SHAPES)
725     if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
726         return true;
727 #endif
728
729     if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
730         return true;
731
732     return false;
733 }
734
735 bool RenderStyle::changeRequiresRepaintIfTextOrBorderOrOutline(const RenderStyle* other, unsigned&) const
736 {
737     if (inherited->color != other->inherited->color
738         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
739         || visual->textDecoration != other->visual->textDecoration
740         || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
741         || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
742         || rareInheritedData->m_textDecorationSkip != other->rareInheritedData->m_textDecorationSkip
743         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
744         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
745         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
746         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill)
747         return true;
748
749     return false;
750 }
751
752 bool RenderStyle::changeRequiresRecompositeLayer(const RenderStyle* other, unsigned&) const
753 {
754     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
755         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
756             || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
757             || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
758             || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
759             || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
760             return true;
761     }
762
763     return false;
764 }
765
766 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
767 {
768     changedContextSensitiveProperties = ContextSensitivePropertyNone;
769
770     StyleDifference svgChange = StyleDifferenceEqual;
771     if (m_svgStyle != other->m_svgStyle) {
772         svgChange = m_svgStyle->diff(other->m_svgStyle.get());
773         if (svgChange == StyleDifferenceLayout)
774             return svgChange;
775     }
776
777     if (changeRequiresLayout(other, changedContextSensitiveProperties))
778         return StyleDifferenceLayout;
779
780     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
781     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
782     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
783     // that are relevant for SVG and might return StyleDifferenceLayout.
784     if (svgChange != StyleDifferenceEqual)
785         return svgChange;
786
787     if (changeRequiresPositionedLayoutOnly(other, changedContextSensitiveProperties))
788         return StyleDifferenceLayoutPositionedMovementOnly;
789
790     if (changeRequiresLayerRepaint(other, changedContextSensitiveProperties))
791         return StyleDifferenceRepaintLayer;
792
793     if (changeRequiresRepaint(other, changedContextSensitiveProperties))
794         return StyleDifferenceRepaint;
795
796     if (changeRequiresRecompositeLayer(other, changedContextSensitiveProperties))
797         return StyleDifferenceRecompositeLayer;
798
799     if (changeRequiresRepaintIfTextOrBorderOrOutline(other, changedContextSensitiveProperties))
800         return StyleDifferenceRepaintIfTextOrBorderOrOutline;
801
802     // Cursors are not checked, since they will be set appropriately in response to mouse events,
803     // so they don't need to cause any repaint or layout.
804
805     // 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
806     // the resulting transition properly.
807     return StyleDifferenceEqual;
808 }
809
810 bool RenderStyle::diffRequiresRepaint(const RenderStyle* style) const
811 {
812     unsigned changedContextSensitiveProperties = 0;
813     return changeRequiresRepaint(style, changedContextSensitiveProperties);
814 }
815
816 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
817 {
818     StyleVisualData* data = visual.access();
819     data->clip.m_top = top;
820     data->clip.m_right = right;
821     data->clip.m_bottom = bottom;
822     data->clip.m_left = left;
823 }
824
825 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
826 {
827     if (!rareInheritedData.access()->cursorData)
828         rareInheritedData.access()->cursorData = CursorList::create();
829     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
830 }
831
832 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
833 {
834     rareInheritedData.access()->cursorData = other;
835 }
836
837 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
838 {
839     if (rareInheritedData->quotes == q || (rareInheritedData->quotes && q && *rareInheritedData->quotes == *q))
840         return;
841
842     rareInheritedData.access()->quotes = q;
843 }
844
845 void RenderStyle::clearCursorList()
846 {
847     if (rareInheritedData->cursorData)
848         rareInheritedData.access()->cursorData = 0;
849 }
850
851 void RenderStyle::clearContent()
852 {
853     if (rareNonInheritedData->m_content)
854         rareNonInheritedData.access()->m_content = nullptr;
855 }
856
857 void RenderStyle::appendContent(std::unique_ptr<ContentData> contentData)
858 {
859     auto& content = rareNonInheritedData.access()->m_content;
860     ContentData* lastContent = content.get();
861     while (lastContent && lastContent->next())
862         lastContent = lastContent->next();
863
864     if (lastContent)
865         lastContent->setNext(std::move(contentData));
866     else
867         content = std::move(contentData);
868 }
869
870 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
871 {
872     if (!image)
873         return;
874         
875     if (add) {
876         appendContent(std::make_unique<ImageContentData>(image));
877         return;
878     }
879
880     rareNonInheritedData.access()->m_content = std::make_unique<ImageContentData>(image);
881     if (!rareNonInheritedData.access()->m_altText.isNull())
882         rareNonInheritedData.access()->m_content->setAltText(rareNonInheritedData.access()->m_altText);
883 }
884
885 void RenderStyle::setContent(const String& string, bool add)
886 {
887     auto& content = rareNonInheritedData.access()->m_content;
888     if (add) {
889         ContentData* lastContent = content.get();
890         while (lastContent && lastContent->next())
891             lastContent = lastContent->next();
892
893         if (lastContent) {
894             // We attempt to merge with the last ContentData if possible.
895             if (lastContent->isText()) {
896                 TextContentData* textContent = toTextContentData(lastContent);
897                 textContent->setText(textContent->text() + string);
898             } else
899                 lastContent->setNext(std::make_unique<TextContentData>(string));
900
901             if (!rareNonInheritedData.access()->m_altText.isNull())
902                 lastContent->setAltText(rareNonInheritedData.access()->m_altText);
903             return;
904         }
905     }
906
907     content = std::make_unique<TextContentData>(string);
908     if (!rareNonInheritedData.access()->m_altText.isNull())
909         content->setAltText(rareNonInheritedData.access()->m_altText);
910 }
911
912 void RenderStyle::setContent(std::unique_ptr<CounterContent> counter, bool add)
913 {
914     if (!counter)
915         return;
916
917     if (add) {
918         appendContent(std::make_unique<CounterContentData>(std::move(counter)));
919         return;
920     }
921
922     rareNonInheritedData.access()->m_content = std::make_unique<CounterContentData>(std::move(counter));
923 }
924
925 void RenderStyle::setContent(QuoteType quote, bool add)
926 {
927     if (add) {
928         appendContent(std::make_unique<QuoteContentData>(quote));
929         return;
930     }
931
932     rareNonInheritedData.access()->m_content = std::make_unique<QuoteContentData>(quote);
933 }
934
935 void RenderStyle::setContentAltText(const String& string)
936 {
937     rareNonInheritedData.access()->m_altText = string;
938     
939     if (rareNonInheritedData.access()->m_content)
940         rareNonInheritedData.access()->m_content->setAltText(string);
941 }
942
943 const String& RenderStyle::contentAltText() const
944 {
945     return rareNonInheritedData->m_altText;
946 }
947
948 static inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation>>& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
949 {
950     // transform-origin brackets the transform with translate operations.
951     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
952     // in that case.
953     if (applyOrigin != RenderStyle::IncludeTransformOrigin)
954         return false;
955
956     for (auto& operation : transformOperations) {
957         TransformOperation::OperationType type = operation->type();
958         if (type != TransformOperation::TRANSLATE_X
959             && type != TransformOperation::TRANSLATE_Y
960             && type != TransformOperation::TRANSLATE 
961             && type != TransformOperation::TRANSLATE_Z
962             && type != TransformOperation::TRANSLATE_3D)
963             return true;
964     }
965
966     return false;
967 }
968
969 void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
970 {
971     auto& operations = rareNonInheritedData->m_transform->m_operations.operations();
972     bool applyTransformOrigin = requireTransformOrigin(operations, applyOrigin);
973
974     float offsetX = transformOriginX().isPercentNotCalculated() ? boundingBox.x() : 0;
975     float offsetY = transformOriginY().isPercentNotCalculated() ? boundingBox.y() : 0;
976
977     if (applyTransformOrigin) {
978         transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
979                               floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
980                               transformOriginZ());
981     }
982
983     for (auto& operation : operations)
984         operation->apply(transform, boundingBox.size());
985
986     if (applyTransformOrigin) {
987         transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
988                               -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
989                               -transformOriginZ());
990     }
991 }
992
993 void RenderStyle::setPageScaleTransform(float scale)
994 {
995     if (scale == 1)
996         return;
997     TransformOperations transform;
998     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
999     setTransform(transform);
1000     setTransformOriginX(Length(0, Fixed));
1001     setTransformOriginY(Length(0, Fixed));
1002 }
1003
1004 void RenderStyle::setTextShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1005 {
1006     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
1007
1008     StyleRareInheritedData* rareData = rareInheritedData.access();
1009     if (!add) {
1010         rareData->textShadow = std::move(shadowData);
1011         return;
1012     }
1013
1014     shadowData->setNext(std::move(rareData->textShadow));
1015     rareData->textShadow = std::move(shadowData);
1016 }
1017
1018 void RenderStyle::setBoxShadow(std::unique_ptr<ShadowData> shadowData, bool add)
1019 {
1020     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
1021     if (!add) {
1022         rareData->m_boxShadow = std::move(shadowData);
1023         return;
1024     }
1025
1026     shadowData->setNext(std::move(rareData->m_boxShadow));
1027     rareData->m_boxShadow = std::move(shadowData);
1028 }
1029
1030 static RoundedRect::Radii calcRadiiFor(const BorderData& border, const LayoutSize& size, RenderView* renderView)
1031 {
1032     return RoundedRect::Radii(
1033         LayoutSize(valueForLength(border.topLeft().width(), size.width(), renderView),
1034             valueForLength(border.topLeft().height(), size.height(), renderView)),
1035         LayoutSize(valueForLength(border.topRight().width(), size.width(), renderView),
1036             valueForLength(border.topRight().height(), size.height(), renderView)),
1037         LayoutSize(valueForLength(border.bottomLeft().width(), size.width(), renderView),
1038             valueForLength(border.bottomLeft().height(), size.height(), renderView)),
1039         LayoutSize(valueForLength(border.bottomRight().width(), size.width(), renderView),
1040             valueForLength(border.bottomRight().height(), size.height(), renderView)));
1041 }
1042
1043 StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
1044 void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
1045 {
1046     if (rareInheritedData->listStyleImage != v)
1047         rareInheritedData.access()->listStyleImage = v;
1048 }
1049
1050 Color RenderStyle::color() const { return inherited->color; }
1051 Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
1052 void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
1053 void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
1054
1055 short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
1056 short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
1057 void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
1058 void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
1059
1060 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1061 {
1062     RoundedRect roundedRect(borderRect);
1063     if (hasBorderRadius()) {
1064         RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size(), renderView);
1065         radii.scale(calcBorderRadiiConstraintScaleFor(borderRect, radii));
1066         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1067     }
1068     return roundedRect;
1069 }
1070
1071 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1072 {
1073     bool horizontal = isHorizontalWritingMode();
1074
1075     LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
1076     LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
1077     LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
1078     LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
1079
1080     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
1081 }
1082
1083 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, LayoutUnit topWidth, LayoutUnit bottomWidth,
1084     LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
1085 {
1086     LayoutRect innerRect(borderRect.x() + leftWidth, 
1087                borderRect.y() + topWidth, 
1088                borderRect.width() - leftWidth - rightWidth, 
1089                borderRect.height() - topWidth - bottomWidth);
1090
1091     RoundedRect roundedRect(innerRect);
1092
1093     if (hasBorderRadius()) {
1094         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
1095         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
1096         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
1097     }
1098     return roundedRect;
1099 }
1100
1101 static bool allLayersAreFixed(const FillLayer* layer)
1102 {
1103     bool allFixed = true;
1104     
1105     for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
1106         allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
1107
1108     return layer && allFixed;
1109 }
1110
1111 bool RenderStyle::hasEntirelyFixedBackground() const
1112 {
1113     return allLayersAreFixed(backgroundLayers());
1114 }
1115
1116 const CounterDirectiveMap* RenderStyle::counterDirectives() const
1117 {
1118     return rareNonInheritedData->m_counterDirectives.get();
1119 }
1120
1121 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
1122 {
1123     auto& map = rareNonInheritedData.access()->m_counterDirectives;
1124     if (!map)
1125         map = std::make_unique<CounterDirectiveMap>();
1126     return *map;
1127 }
1128
1129 const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
1130 {
1131     if (const CounterDirectiveMap* directives = counterDirectives())
1132         return directives->get(identifier);
1133     return CounterDirectives();
1134 }
1135
1136 const AtomicString& RenderStyle::hyphenString() const
1137 {
1138     ASSERT(hyphens() != HyphensNone);
1139
1140     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
1141     if (!hyphenationString.isNull())
1142         return hyphenationString;
1143
1144     // FIXME: This should depend on locale.
1145     DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
1146     DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
1147     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
1148 }
1149
1150 const AtomicString& RenderStyle::textEmphasisMarkString() const
1151 {
1152     switch (textEmphasisMark()) {
1153     case TextEmphasisMarkNone:
1154         return nullAtom;
1155     case TextEmphasisMarkCustom:
1156         return textEmphasisCustomMark();
1157     case TextEmphasisMarkDot: {
1158         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
1159         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
1160         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
1161     }
1162     case TextEmphasisMarkCircle: {
1163         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
1164         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
1165         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
1166     }
1167     case TextEmphasisMarkDoubleCircle: {
1168         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
1169         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
1170         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
1171     }
1172     case TextEmphasisMarkTriangle: {
1173         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
1174         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
1175         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
1176     }
1177     case TextEmphasisMarkSesame: {
1178         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
1179         DEPRECATED_DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
1180         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
1181     }
1182     case TextEmphasisMarkAuto:
1183         ASSERT_NOT_REACHED();
1184         return nullAtom;
1185     }
1186
1187     ASSERT_NOT_REACHED();
1188     return nullAtom;
1189 }
1190
1191 #if ENABLE(DASHBOARD_SUPPORT)
1192 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1193 {
1194     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
1195     return emptyList;
1196 }
1197
1198 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1199 {
1200     DEPRECATED_DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
1201     static bool noneListInitialized = false;
1202
1203     if (!noneListInitialized) {
1204         StyleDashboardRegion region;
1205         region.label = "";
1206         region.offset.m_top  = Length();
1207         region.offset.m_right = Length();
1208         region.offset.m_bottom = Length();
1209         region.offset.m_left = Length();
1210         region.type = StyleDashboardRegion::None;
1211         noneList.append(region);
1212         noneListInitialized = true;
1213     }
1214     return noneList;
1215 }
1216 #endif
1217
1218 void RenderStyle::adjustAnimations()
1219 {
1220     AnimationList* animationList = rareNonInheritedData->m_animations.get();
1221     if (!animationList)
1222         return;
1223
1224     // Get rid of empty animations and anything beyond them
1225     for (size_t i = 0; i < animationList->size(); ++i) {
1226         if (animationList->animation(i).isEmpty()) {
1227             animationList->resize(i);
1228             break;
1229         }
1230     }
1231
1232     if (animationList->isEmpty()) {
1233         clearAnimations();
1234         return;
1235     }
1236
1237     // Repeat patterns into layers that don't have some properties set.
1238     animationList->fillUnsetProperties();
1239 }
1240
1241 void RenderStyle::adjustTransitions()
1242 {
1243     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1244     if (!transitionList)
1245         return;
1246
1247     // Get rid of empty transitions and anything beyond them
1248     for (size_t i = 0; i < transitionList->size(); ++i) {
1249         if (transitionList->animation(i).isEmpty()) {
1250             transitionList->resize(i);
1251             break;
1252         }
1253     }
1254
1255     if (transitionList->isEmpty()) {
1256         clearTransitions();
1257         return;
1258     }
1259
1260     // Repeat patterns into layers that don't have some properties set.
1261     transitionList->fillUnsetProperties();
1262
1263     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1264     // but the lists tend to be very short, so it is probably ok
1265     for (size_t i = 0; i < transitionList->size(); ++i) {
1266         for (size_t j = i+1; j < transitionList->size(); ++j) {
1267             if (transitionList->animation(i).property() == transitionList->animation(j).property()) {
1268                 // toss i
1269                 transitionList->remove(i);
1270                 j = i;
1271             }
1272         }
1273     }
1274 }
1275
1276 AnimationList* RenderStyle::accessAnimations()
1277 {
1278     if (!rareNonInheritedData.access()->m_animations)
1279         rareNonInheritedData.access()->m_animations = std::make_unique<AnimationList>();
1280     return rareNonInheritedData->m_animations.get();
1281 }
1282
1283 AnimationList* RenderStyle::accessTransitions()
1284 {
1285     if (!rareNonInheritedData.access()->m_transitions)
1286         rareNonInheritedData.access()->m_transitions = std::make_unique<AnimationList>();
1287     return rareNonInheritedData->m_transitions.get();
1288 }
1289
1290 const Animation* RenderStyle::transitionForProperty(CSSPropertyID property) const
1291 {
1292     if (transitions()) {
1293         for (size_t i = 0; i < transitions()->size(); ++i) {
1294             const Animation& p = transitions()->animation(i);
1295             if (p.animationMode() == Animation::AnimateAll || p.property() == property) {
1296                 return &p;
1297             }
1298         }
1299     }
1300     return 0;
1301 }
1302
1303 const Font& RenderStyle::font() const { return inherited->font; }
1304 const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
1305 const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
1306 float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
1307 float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
1308 int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
1309
1310 const Length& RenderStyle::wordSpacing() const { return rareInheritedData->wordSpacing; }
1311 float RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
1312
1313 bool RenderStyle::setFontDescription(const FontDescription& v)
1314 {
1315     if (inherited->font.fontDescription() != v) {
1316         inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
1317         return true;
1318     }
1319     return false;
1320 }
1321
1322 #if ENABLE(IOS_TEXT_AUTOSIZING)
1323 const Length& RenderStyle::specifiedLineHeight() const { return inherited->specifiedLineHeight; }
1324 void RenderStyle::setSpecifiedLineHeight(Length v) { SET_VAR(inherited, specifiedLineHeight, v); }
1325 #else
1326 const Length& RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
1327 #endif
1328
1329 Length RenderStyle::lineHeight() const
1330 {
1331     const Length& lh = inherited->line_height;
1332 #if ENABLE(TEXT_AUTOSIZING)
1333     // Unlike fontDescription().computedSize() and hence fontSize(), this is
1334     // recalculated on demand as we only store the specified line height.
1335     // FIXME: Should consider scaling the fixed part of any calc expressions
1336     // too, though this involves messily poking into CalcExpressionLength.
1337     float multiplier = textAutosizingMultiplier();
1338     if (multiplier > 1 && lh.isFixed())
1339         return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
1340 #endif
1341     return lh;
1342 }
1343 void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
1344
1345 int RenderStyle::computedLineHeight(RenderView* renderView) const
1346 {
1347     const Length& lh = lineHeight();
1348
1349     // Negative value means the line height is not set. Use the font's built-in spacing.
1350     if (lh.isNegative())
1351         return fontMetrics().lineSpacing();
1352
1353     if (lh.isPercent())
1354         return minimumValueForLength(lh, fontSize());
1355
1356     if (lh.isViewportPercentage())
1357         return valueForLength(lh, 0, renderView);
1358
1359     return lh.value();
1360 }
1361
1362 void RenderStyle::setWordSpacing(Length value)
1363 {
1364     float fontWordSpacing;
1365     switch (value.type()) {
1366     case Auto:
1367         fontWordSpacing = 0;
1368         break;
1369     case Percent:
1370         fontWordSpacing = value.percent() * font().spaceWidth() / 100;
1371         break;
1372     case Fixed:
1373         fontWordSpacing = value.value();
1374         break;
1375     default:
1376         ASSERT_NOT_REACHED();
1377         fontWordSpacing = 0;
1378         break;
1379     }
1380     inherited.access()->font.setWordSpacing(fontWordSpacing);
1381     rareInheritedData.access()->wordSpacing = std::move(value);
1382 }
1383
1384 void RenderStyle::setLetterSpacing(float v) { inherited.access()->font.setLetterSpacing(v); }
1385
1386 void RenderStyle::setFontSize(float size)
1387 {
1388     // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
1389     // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
1390
1391     ASSERT(std::isfinite(size));
1392     if (!std::isfinite(size) || size < 0)
1393         size = 0;
1394     else
1395         size = std::min(maximumAllowedFontSize, size);
1396
1397     FontSelector* currentFontSelector = font().fontSelector();
1398     FontDescription desc(fontDescription());
1399     desc.setSpecifiedSize(size);
1400     desc.setComputedSize(size);
1401
1402 #if ENABLE(TEXT_AUTOSIZING)
1403     float multiplier = textAutosizingMultiplier();
1404     if (multiplier > 1) {
1405         float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
1406         desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
1407     }
1408 #endif
1409
1410     setFontDescription(desc);
1411     font().update(currentFontSelector);
1412 }
1413
1414 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1415 {
1416     top = 0;
1417     right = 0;
1418     bottom = 0;
1419     left = 0;
1420
1421     for ( ; shadow; shadow = shadow->next()) {
1422         if (shadow->style() == Inset)
1423             continue;
1424
1425         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1426         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1427         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1428         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1429         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1430     }
1431 }
1432
1433 LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
1434 {
1435     LayoutUnit top = 0;
1436     LayoutUnit right = 0;
1437     LayoutUnit bottom = 0;
1438     LayoutUnit left = 0;
1439
1440     for ( ; shadow; shadow = shadow->next()) {
1441         if (shadow->style() == Normal)
1442             continue;
1443
1444         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1445         top = std::max<LayoutUnit>(top, shadow->y() + extentAndSpread);
1446         right = std::min<LayoutUnit>(right, shadow->x() - extentAndSpread);
1447         bottom = std::min<LayoutUnit>(bottom, shadow->y() - extentAndSpread);
1448         left = std::max<LayoutUnit>(left, shadow->x() + extentAndSpread);
1449     }
1450
1451     return LayoutBoxExtent(top, right, bottom, left);
1452 }
1453
1454 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1455 {
1456     left = 0;
1457     right = 0;
1458
1459     for ( ; shadow; shadow = shadow->next()) {
1460         if (shadow->style() == Inset)
1461             continue;
1462
1463         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1464         left = std::min<LayoutUnit>(left, shadow->x() - extentAndSpread);
1465         right = std::max<LayoutUnit>(right, shadow->x() + extentAndSpread);
1466     }
1467 }
1468
1469 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1470 {
1471     top = 0;
1472     bottom = 0;
1473
1474     for ( ; shadow; shadow = shadow->next()) {
1475         if (shadow->style() == Inset)
1476             continue;
1477
1478         int extentAndSpread = shadow->paintingExtent() + shadow->spread();
1479         top = std::min<LayoutUnit>(top, shadow->y() - extentAndSpread);
1480         bottom = std::max<LayoutUnit>(bottom, shadow->y() + extentAndSpread);
1481     }
1482 }
1483
1484 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1485 {
1486     Color result;
1487     EBorderStyle borderStyle = BNONE;
1488     switch (colorProperty) {
1489     case CSSPropertyBackgroundColor:
1490         return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
1491     case CSSPropertyBorderLeftColor:
1492         result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
1493         borderStyle = borderLeftStyle();
1494         break;
1495     case CSSPropertyBorderRightColor:
1496         result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
1497         borderStyle = borderRightStyle();
1498         break;
1499     case CSSPropertyBorderTopColor:
1500         result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
1501         borderStyle = borderTopStyle();
1502         break;
1503     case CSSPropertyBorderBottomColor:
1504         result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
1505         borderStyle = borderBottomStyle();
1506         break;
1507     case CSSPropertyColor:
1508         result = visitedLink ? visitedLinkColor() : color();
1509         break;
1510     case CSSPropertyOutlineColor:
1511         result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
1512         break;
1513     case CSSPropertyWebkitColumnRuleColor:
1514         result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
1515         break;
1516     case CSSPropertyWebkitTextDecorationColor:
1517         // Text decoration color fallback is handled in RenderObject::decorationColor.
1518         return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
1519     case CSSPropertyWebkitTextEmphasisColor:
1520         result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
1521         break;
1522     case CSSPropertyWebkitTextFillColor:
1523         result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
1524         break;
1525     case CSSPropertyWebkitTextStrokeColor:
1526         result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
1527         break;
1528     default:
1529         ASSERT_NOT_REACHED();
1530         break;
1531     }
1532
1533     if (!result.isValid()) {
1534         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1535             result.setRGB(238, 238, 238);
1536         else
1537             result = visitedLink ? visitedLinkColor() : color();
1538     }
1539     return result;
1540 }
1541
1542 Color RenderStyle::visitedDependentColor(int colorProperty) const
1543 {
1544     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1545     if (insideLink() != InsideVisitedLink)
1546         return unvisitedColor;
1547
1548     Color visitedColor = colorIncludingFallback(colorProperty, true);
1549
1550     // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
1551     if (colorProperty == CSSPropertyWebkitTextDecorationColor)
1552         return visitedColor;
1553
1554     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1555     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1556     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1557     // have to match, it makes more sense to return the unvisited background color if specified than it
1558     // does to return black. This behavior matches what Firefox 4 does as well.
1559     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1560         return unvisitedColor;
1561
1562     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1563     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1564 }
1565
1566 const BorderValue& RenderStyle::borderBefore() const
1567 {
1568     switch (writingMode()) {
1569     case TopToBottomWritingMode:
1570         return borderTop();
1571     case BottomToTopWritingMode:
1572         return borderBottom();
1573     case LeftToRightWritingMode:
1574         return borderLeft();
1575     case RightToLeftWritingMode:
1576         return borderRight();
1577     }
1578     ASSERT_NOT_REACHED();
1579     return borderTop();
1580 }
1581
1582 const BorderValue& RenderStyle::borderAfter() const
1583 {
1584     switch (writingMode()) {
1585     case TopToBottomWritingMode:
1586         return borderBottom();
1587     case BottomToTopWritingMode:
1588         return borderTop();
1589     case LeftToRightWritingMode:
1590         return borderRight();
1591     case RightToLeftWritingMode:
1592         return borderLeft();
1593     }
1594     ASSERT_NOT_REACHED();
1595     return borderBottom();
1596 }
1597
1598 const BorderValue& RenderStyle::borderStart() const
1599 {
1600     if (isHorizontalWritingMode())
1601         return isLeftToRightDirection() ? borderLeft() : borderRight();
1602     return isLeftToRightDirection() ? borderTop() : borderBottom();
1603 }
1604
1605 const BorderValue& RenderStyle::borderEnd() const
1606 {
1607     if (isHorizontalWritingMode())
1608         return isLeftToRightDirection() ? borderRight() : borderLeft();
1609     return isLeftToRightDirection() ? borderBottom() : borderTop();
1610 }
1611
1612 float RenderStyle::borderBeforeWidth() const
1613 {
1614     switch (writingMode()) {
1615     case TopToBottomWritingMode:
1616         return borderTopWidth();
1617     case BottomToTopWritingMode:
1618         return borderBottomWidth();
1619     case LeftToRightWritingMode:
1620         return borderLeftWidth();
1621     case RightToLeftWritingMode:
1622         return borderRightWidth();
1623     }
1624     ASSERT_NOT_REACHED();
1625     return borderTopWidth();
1626 }
1627
1628 float RenderStyle::borderAfterWidth() const
1629 {
1630     switch (writingMode()) {
1631     case TopToBottomWritingMode:
1632         return borderBottomWidth();
1633     case BottomToTopWritingMode:
1634         return borderTopWidth();
1635     case LeftToRightWritingMode:
1636         return borderRightWidth();
1637     case RightToLeftWritingMode:
1638         return borderLeftWidth();
1639     }
1640     ASSERT_NOT_REACHED();
1641     return borderBottomWidth();
1642 }
1643
1644 float RenderStyle::borderStartWidth() const
1645 {
1646     if (isHorizontalWritingMode())
1647         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1648     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1649 }
1650
1651 float RenderStyle::borderEndWidth() const
1652 {
1653     if (isHorizontalWritingMode())
1654         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1655     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1656 }
1657
1658 void RenderStyle::setMarginStart(Length margin)
1659 {
1660     if (isHorizontalWritingMode()) {
1661         if (isLeftToRightDirection())
1662             setMarginLeft(margin);
1663         else
1664             setMarginRight(margin);
1665     } else {
1666         if (isLeftToRightDirection())
1667             setMarginTop(margin);
1668         else
1669             setMarginBottom(margin);
1670     }
1671 }
1672
1673 void RenderStyle::setMarginEnd(Length margin)
1674 {
1675     if (isHorizontalWritingMode()) {
1676         if (isLeftToRightDirection())
1677             setMarginRight(margin);
1678         else
1679             setMarginLeft(margin);
1680     } else {
1681         if (isLeftToRightDirection())
1682             setMarginBottom(margin);
1683         else
1684             setMarginTop(margin);
1685     }
1686 }
1687
1688 TextEmphasisMark RenderStyle::textEmphasisMark() const
1689 {
1690     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1691     if (mark != TextEmphasisMarkAuto)
1692         return mark;
1693
1694     if (isHorizontalWritingMode())
1695         return TextEmphasisMarkDot;
1696
1697     return TextEmphasisMarkSesame;
1698 }
1699
1700 #if ENABLE(TOUCH_EVENTS)
1701 Color RenderStyle::initialTapHighlightColor()
1702 {
1703     return RenderTheme::tapHighlightColor();
1704 }
1705 #endif
1706
1707 LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
1708 {
1709     return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
1710                            NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
1711                            NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
1712                            NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
1713 }
1714
1715 void RenderStyle::getFontAndGlyphOrientation(FontOrientation& fontOrientation, NonCJKGlyphOrientation& glyphOrientation)
1716 {
1717     if (isHorizontalWritingMode()) {
1718         fontOrientation = Horizontal;
1719         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1720         return;
1721     }
1722
1723     switch (textOrientation()) {
1724     case TextOrientationVerticalRight:
1725         fontOrientation = Vertical;
1726         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1727         return;
1728     case TextOrientationUpright:
1729         fontOrientation = Vertical;
1730         glyphOrientation = NonCJKGlyphOrientationUpright;
1731         return;
1732     case TextOrientationSideways:
1733         if (writingMode() == LeftToRightWritingMode) {
1734             // FIXME: This should map to sideways-left, which is not supported yet.
1735             fontOrientation = Vertical;
1736             glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1737             return;
1738         }
1739         fontOrientation = Horizontal;
1740         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1741         return;
1742     case TextOrientationSidewaysRight:
1743         fontOrientation = Horizontal;
1744         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1745         return;
1746     default:
1747         ASSERT_NOT_REACHED();
1748         fontOrientation = Horizontal;
1749         glyphOrientation = NonCJKGlyphOrientationVerticalRight;
1750         return;
1751     }
1752 }
1753
1754 void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
1755 {
1756     if (surround->border.m_image.image() == image.get())
1757         return;
1758     surround.access()->border.m_image.setImage(image);
1759 }
1760
1761 void RenderStyle::setBorderImageSlices(LengthBox slices)
1762 {
1763     if (surround->border.m_image.imageSlices() == slices)
1764         return;
1765     surround.access()->border.m_image.setImageSlices(slices);
1766 }
1767
1768 void RenderStyle::setBorderImageWidth(LengthBox slices)
1769 {
1770     if (surround->border.m_image.borderSlices() == slices)
1771         return;
1772     surround.access()->border.m_image.setBorderSlices(slices);
1773 }
1774
1775 void RenderStyle::setBorderImageOutset(LengthBox outset)
1776 {
1777     if (surround->border.m_image.outset() == outset)
1778         return;
1779     surround.access()->border.m_image.setOutset(outset);
1780 }
1781
1782 void RenderStyle::setColumnStylesFromPaginationMode(const Pagination::Mode& paginationMode)
1783 {
1784     if (paginationMode == Pagination::Unpaginated)
1785         return;
1786     
1787     setColumnFill(ColumnFillAuto);
1788     
1789     switch (paginationMode) {
1790     case Pagination::LeftToRightPaginated:
1791         setColumnAxis(HorizontalColumnAxis);
1792         if (isHorizontalWritingMode())
1793             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1794         else
1795             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1796         break;
1797     case Pagination::RightToLeftPaginated:
1798         setColumnAxis(HorizontalColumnAxis);
1799         if (isHorizontalWritingMode())
1800             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1801         else
1802             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1803         break;
1804     case Pagination::TopToBottomPaginated:
1805         setColumnAxis(VerticalColumnAxis);
1806         if (isHorizontalWritingMode())
1807             setColumnProgression(isFlippedBlocksWritingMode() ? ReverseColumnProgression : NormalColumnProgression);
1808         else
1809             setColumnProgression(isLeftToRightDirection() ? NormalColumnProgression : ReverseColumnProgression);
1810         break;
1811     case Pagination::BottomToTopPaginated:
1812         setColumnAxis(VerticalColumnAxis);
1813         if (isHorizontalWritingMode())
1814             setColumnProgression(isFlippedBlocksWritingMode() ? NormalColumnProgression : ReverseColumnProgression);
1815         else
1816             setColumnProgression(isLeftToRightDirection() ? ReverseColumnProgression : NormalColumnProgression);
1817         break;
1818     case Pagination::Unpaginated:
1819         ASSERT_NOT_REACHED();
1820         break;
1821     }
1822 }
1823
1824 } // namespace WebCore