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