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