https://bugs.webkit.org/show_bug.cgi?id=69966
[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  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  *
20  */
21
22 #include "config.h"
23 #include "RenderStyle.h"
24
25 #include "ContentData.h"
26 #include "CursorList.h"
27 #include "CSSPropertyNames.h"
28 #include "CSSStyleSelector.h"
29 #include "CSSWrapShapes.h"
30 #include "FontSelector.h"
31 #include "QuotesData.h"
32 #include "RenderArena.h"
33 #include "RenderObject.h"
34 #include "ScaleTransformOperation.h"
35 #include "ShadowData.h"
36 #include "StyleImage.h"
37 #if ENABLE(TOUCH_EVENTS)
38 #include "RenderTheme.h"
39 #endif
40 #include <wtf/StdLibExtras.h>
41 #include <algorithm>
42
43 using namespace std;
44
45 namespace WebCore {
46
47 inline RenderStyle* defaultStyle()
48 {
49     static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().leakRef();
50     return s_defaultStyle;
51 }
52
53 PassRefPtr<RenderStyle> RenderStyle::create()
54 {
55     return adoptRef(new RenderStyle());
56 }
57
58 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
59 {
60     return adoptRef(new RenderStyle(true));
61 }
62
63 PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyle(const RenderStyle* parentStyle)
64 {
65     RefPtr<RenderStyle> newStyle = RenderStyle::create();
66     newStyle->inheritFrom(parentStyle);
67     newStyle->inheritUnicodeBidiFrom(parentStyle);
68     return newStyle;
69 }
70
71 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
72 {
73     return adoptRef(new RenderStyle(*other));
74 }
75
76 ALWAYS_INLINE RenderStyle::RenderStyle()
77     : m_affectedByUncommonAttributeSelectors(false)
78     , m_unique(false)
79     , m_affectedByEmpty(false)
80     , m_emptyState(false)
81     , m_childrenAffectedByFirstChildRules(false)
82     , m_childrenAffectedByLastChildRules(false)
83     , m_childrenAffectedByForwardPositionalRules(false)
84     , m_childrenAffectedByBackwardPositionalRules(false)
85     , m_firstChildState(false)
86     , m_lastChildState(false)
87     , m_affectedByDirectAdjacentRules(false)
88     , m_childIndex(0)
89     , m_box(defaultStyle()->m_box)
90     , visual(defaultStyle()->visual)
91     , m_background(defaultStyle()->m_background)
92     , surround(defaultStyle()->surround)
93     , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
94     , rareInheritedData(defaultStyle()->rareInheritedData)
95     , inherited(defaultStyle()->inherited)
96 #if ENABLE(SVG)
97     , m_svgStyle(defaultStyle()->m_svgStyle)
98 #endif
99 {
100     setBitDefaults(); // Would it be faster to copy this from the default style?
101 }
102
103 ALWAYS_INLINE RenderStyle::RenderStyle(bool)
104     : m_affectedByUncommonAttributeSelectors(false)
105     , m_unique(false)
106     , m_affectedByEmpty(false)
107     , m_emptyState(false)
108     , m_childrenAffectedByFirstChildRules(false)
109     , m_childrenAffectedByLastChildRules(false)
110     , m_childrenAffectedByForwardPositionalRules(false)
111     , m_childrenAffectedByBackwardPositionalRules(false)
112     , m_firstChildState(false)
113     , m_lastChildState(false)
114     , m_affectedByDirectAdjacentRules(false)
115     , m_childIndex(0)
116 {
117     setBitDefaults();
118
119     m_box.init();
120     visual.init();
121     m_background.init();
122     surround.init();
123     rareNonInheritedData.init();
124     rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
125 #if ENABLE(CSS3_FLEXBOX)
126     rareNonInheritedData.access()->m_flexibleBox.init();
127 #endif
128     rareNonInheritedData.access()->m_marquee.init();
129     rareNonInheritedData.access()->m_multiCol.init();
130     rareNonInheritedData.access()->m_transform.init();
131 #if ENABLE(CSS_FILTERS)
132     rareNonInheritedData.access()->m_filter.init();
133 #endif
134     rareInheritedData.init();
135     inherited.init();
136
137 #if ENABLE(SVG)
138     m_svgStyle.init();
139 #endif
140 }
141
142 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
143     : RefCounted<RenderStyle>()
144     , m_affectedByUncommonAttributeSelectors(false)
145     , m_unique(false)
146     , m_affectedByEmpty(false)
147     , m_emptyState(false)
148     , m_childrenAffectedByFirstChildRules(false)
149     , m_childrenAffectedByLastChildRules(false)
150     , m_childrenAffectedByForwardPositionalRules(false)
151     , m_childrenAffectedByBackwardPositionalRules(false)
152     , m_firstChildState(false)
153     , m_lastChildState(false)
154     , m_affectedByDirectAdjacentRules(false)
155     , m_childIndex(0)
156     , m_box(o.m_box)
157     , visual(o.visual)
158     , m_background(o.m_background)
159     , surround(o.surround)
160     , rareNonInheritedData(o.rareNonInheritedData)
161     , rareInheritedData(o.rareInheritedData)
162     , inherited(o.inherited)
163 #if ENABLE(SVG)
164     , m_svgStyle(o.m_svgStyle)
165 #endif
166     , inherited_flags(o.inherited_flags)
167     , noninherited_flags(o.noninherited_flags)
168 {
169 }
170
171 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
172 {
173     rareInheritedData = inheritParent->rareInheritedData;
174     inherited = inheritParent->inherited;
175     inherited_flags = inheritParent->inherited_flags;
176 #if ENABLE(SVG)
177     if (m_svgStyle != inheritParent->m_svgStyle)
178         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
179 #endif
180 }
181
182 RenderStyle::~RenderStyle()
183 {
184 }
185
186 bool RenderStyle::operator==(const RenderStyle& o) const
187 {
188     // compare everything except the pseudoStyle pointer
189     return inherited_flags == o.inherited_flags
190         && noninherited_flags == o.noninherited_flags
191         && m_box == o.m_box
192         && visual == o.visual
193         && m_background == o.m_background
194         && surround == o.surround
195         && rareNonInheritedData == o.rareNonInheritedData
196         && rareInheritedData == o.rareInheritedData
197         && inherited == o.inherited
198 #if ENABLE(SVG)
199         && m_svgStyle == o.m_svgStyle
200 #endif
201             ;
202 }
203
204 bool RenderStyle::isStyleAvailable() const
205 {
206     return this != CSSStyleSelector::styleNotYetAvailable();
207 }
208
209 static inline int pseudoBit(PseudoId pseudo)
210 {
211     return 1 << (pseudo - 1);
212 }
213
214 bool RenderStyle::hasAnyPublicPseudoStyles() const
215 {
216     return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
217 }
218
219 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
220 {
221     ASSERT(pseudo > NOPSEUDO);
222     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
223     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
224 }
225
226 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
227 {
228     ASSERT(pseudo > NOPSEUDO);
229     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
230     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
231 }
232
233 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
234 {
235     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
236         return 0;
237
238     if (styleType() != NOPSEUDO) 
239         return 0;
240
241     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
242         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
243         if (pseudoStyle->styleType() == pid)
244             return pseudoStyle;
245     }
246
247     return 0;
248 }
249
250 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
251 {
252     if (!pseudo)
253         return 0;
254
255     ASSERT(pseudo->styleType() > NOPSEUDO);
256
257     RenderStyle* result = pseudo.get();
258
259     if (!m_cachedPseudoStyles)
260         m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
261
262     m_cachedPseudoStyles->append(pseudo);
263
264     return result;
265 }
266
267 void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
268 {
269     if (!m_cachedPseudoStyles)
270         return;
271     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
272         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
273         if (pseudoStyle->styleType() == pid) {
274             m_cachedPseudoStyles->remove(i);
275             return;
276         }
277     }
278 }
279
280 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
281 {
282     return inherited_flags != other->inherited_flags
283            || inherited != other->inherited
284 #if ENABLE(SVG)
285            || m_svgStyle->inheritedNotEqual(other->m_svgStyle.get())
286 #endif
287            || rareInheritedData != other->rareInheritedData;
288 }
289
290 static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
291 {
292     // If any unit types are different, then we can't guarantee
293     // that this was just a movement.
294     if (a.left().type() != b.left().type()
295         || a.right().type() != b.right().type()
296         || a.top().type() != b.top().type()
297         || a.bottom().type() != b.bottom().type())
298         return false;
299
300     // Only one unit can be non-auto in the horizontal direction and
301     // in the vertical direction.  Otherwise the adjustment of values
302     // is changing the size of the box.
303     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
304         return false;
305     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
306         return false;
307
308     // One of the units is fixed or percent in both directions and stayed
309     // that way in the new style.  Therefore all we are doing is moving.
310     return true;
311 }
312
313 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
314 {
315     changedContextSensitiveProperties = ContextSensitivePropertyNone;
316
317 #if ENABLE(SVG)
318     StyleDifference svgChange = StyleDifferenceEqual;
319     if (m_svgStyle != other->m_svgStyle) {
320         svgChange = m_svgStyle->diff(other->m_svgStyle.get());
321         if (svgChange == StyleDifferenceLayout)
322             return svgChange;
323     }
324 #endif
325
326     if (m_box->width() != other->m_box->width()
327         || m_box->minWidth() != other->m_box->minWidth()
328         || m_box->maxWidth() != other->m_box->maxWidth()
329         || m_box->height() != other->m_box->height()
330         || m_box->minHeight() != other->m_box->minHeight()
331         || m_box->maxHeight() != other->m_box->maxHeight())
332         return StyleDifferenceLayout;
333
334     if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
335         return StyleDifferenceLayout;
336
337     if (m_box->boxSizing() != other->m_box->boxSizing())
338         return StyleDifferenceLayout;
339
340     if (surround->margin != other->surround->margin)
341         return StyleDifferenceLayout;
342
343     if (surround->padding != other->surround->padding)
344         return StyleDifferenceLayout;
345
346     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
347         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 
348             || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
349             || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
350             || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
351             || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
352             return StyleDifferenceLayout;
353
354         if (rareNonInheritedData->m_regionOverflow != other->rareNonInheritedData->m_regionOverflow)
355             return StyleDifferenceLayout;
356
357         if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
358             && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
359             return StyleDifferenceLayout;
360
361 #if ENABLE(CSS3_FLEXBOX)
362         if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
363             && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
364             return StyleDifferenceLayout;
365 #endif
366
367         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
368         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
369             return StyleDifferenceLayout;
370
371         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
372             return StyleDifferenceLayout;
373
374         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
375             && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
376             return StyleDifferenceLayout;
377
378         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
379             && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
380 #if USE(ACCELERATED_COMPOSITING)
381             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
382             // Don't return; keep looking for another change
383 #else
384             return StyleDifferenceLayout;
385 #endif
386         }
387
388 #if !USE(ACCELERATED_COMPOSITING)
389         if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
390             if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
391                 || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
392                 || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
393                 || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
394                 || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
395                 return StyleDifferenceLayout;
396         }
397 #endif
398
399 #if ENABLE(DASHBOARD_SUPPORT)
400         // If regions change, trigger a relayout to re-calc regions.
401         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
402             return StyleDifferenceLayout;
403 #endif
404     }
405
406     if (rareInheritedData.get() != other->rareInheritedData.get()) {
407         if (rareInheritedData->highlight != other->rareInheritedData->highlight
408             || rareInheritedData->indent != other->rareInheritedData->indent
409             || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
410             || rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust
411             || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
412             || rareInheritedData->wordWrap != other->rareInheritedData->wordWrap
413             || rareInheritedData->nbspMode != other->rareInheritedData->nbspMode
414             || rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak
415             || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
416             || rareInheritedData->hyphens != other->rareInheritedData->hyphens
417             || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
418             || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
419             || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
420             || rareInheritedData->locale != other->rareInheritedData->locale
421             || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
422             || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
423             || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
424             || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain)
425             return StyleDifferenceLayout;
426
427         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
428             return StyleDifferenceLayout;
429
430         if (textStrokeWidth() != other->textStrokeWidth())
431             return StyleDifferenceLayout;
432     }
433
434     if (inherited->line_height != other->inherited->line_height
435         || inherited->list_style_image != other->inherited->list_style_image
436         || inherited->font != other->inherited->font
437         || inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing
438         || inherited->vertical_border_spacing != other->inherited->vertical_border_spacing
439         || inherited_flags._box_direction != other->inherited_flags._box_direction
440         || inherited_flags.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
441         || noninherited_flags._position != other->noninherited_flags._position
442         || noninherited_flags._floating != other->noninherited_flags._floating
443         || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
444         return StyleDifferenceLayout;
445
446
447     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
448         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse
449             || inherited_flags._empty_cells != other->inherited_flags._empty_cells
450             || inherited_flags._caption_side != other->inherited_flags._caption_side
451             || noninherited_flags._table_layout != other->noninherited_flags._table_layout)
452             return StyleDifferenceLayout;
453
454         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
455         // does not, so these style differences can be width differences.
456         if (inherited_flags._border_collapse
457             && ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE)
458                 || (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN)
459                 || (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE)
460                 || (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN)
461                 || (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE)
462                 || (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN)
463                 || (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE)
464                 || (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
465             return StyleDifferenceLayout;
466     }
467
468     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
469         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type
470             || inherited_flags._list_style_position != other->inherited_flags._list_style_position)
471             return StyleDifferenceLayout;
472     }
473
474     if (inherited_flags._text_align != other->inherited_flags._text_align
475         || inherited_flags._text_transform != other->inherited_flags._text_transform
476         || inherited_flags._direction != other->inherited_flags._direction
477         || inherited_flags._white_space != other->inherited_flags._white_space
478         || noninherited_flags._clear != other->noninherited_flags._clear
479         || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
480         return StyleDifferenceLayout;
481
482     // Check block flow direction.
483     if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
484         return StyleDifferenceLayout;
485
486     // Check text combine mode.
487     if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
488         return StyleDifferenceLayout;
489
490     // Overflow returns a layout hint.
491     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
492         || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
493         return StyleDifferenceLayout;
494
495     // If our border widths change, then we need to layout.  Other changes to borders
496     // only necessitate a repaint.
497     if (borderLeftWidth() != other->borderLeftWidth()
498         || borderTopWidth() != other->borderTopWidth()
499         || borderBottomWidth() != other->borderBottomWidth()
500         || borderRightWidth() != other->borderRightWidth())
501         return StyleDifferenceLayout;
502
503     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
504     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
505     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
506     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
507         return StyleDifferenceLayout;
508     if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement
509         || rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
510         return StyleDifferenceLayout;
511
512     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
513         return StyleDifferenceLayout;
514
515     if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1)
516         || (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
517         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
518         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
519         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
520         // In addition we need to solve the floating object issue when layers come and go. Right now
521         // a full layout is necessary to keep floating object lists sane.
522         return StyleDifferenceLayout;
523     }
524
525 #if ENABLE(SVG)
526     // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
527     // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
528     // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
529     // that are relevant for SVG and might return StyleDifferenceLayout.
530     if (svgChange != StyleDifferenceEqual)
531         return svgChange;
532 #endif
533
534     // Make sure these left/top/right/bottom checks stay below all layout checks and above
535     // all visible checks.
536     if (position() != StaticPosition) {
537         if (surround->offset != other->surround->offset) {
538              // Optimize for the case where a positioned layer is moving but not changing size.
539             if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
540                 return StyleDifferenceLayoutPositionedMovementOnly;
541
542             // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
543             // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
544             // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
545             return StyleDifferenceLayout;
546         } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
547                  || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
548             return StyleDifferenceRepaintLayer;
549     }
550
551     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
552 #if USE(ACCELERATED_COMPOSITING)
553         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
554         // Don't return; keep looking for another change.
555 #else
556         return StyleDifferenceRepaintLayer;
557 #endif
558     }
559
560     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
561         || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
562         return StyleDifferenceRepaintLayer;
563
564     if (inherited->color != other->inherited->color
565         || inherited_flags._visibility != other->inherited_flags._visibility
566         || inherited_flags._text_decorations != other->inherited_flags._text_decorations
567         || inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white
568         || inherited_flags._insideLink != other->inherited_flags._insideLink
569         || surround->border != other->surround->border
570         || *m_background.get() != *other->m_background.get()
571         || visual->textDecoration != other->visual->textDecoration
572         || rareInheritedData->userModify != other->rareInheritedData->userModify
573         || rareInheritedData->userSelect != other->rareInheritedData->userSelect
574         || rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag
575         || rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit
576         || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
577         || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
578         || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
579         || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill
580         || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
581         return StyleDifferenceRepaint;
582         
583         // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected 
584         // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout 
585         // the parent container. For sure, I will have to revisit this code, but for now I've added this in order 
586         // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
587         // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
588         if (rareNonInheritedData->m_wrapShape != other->rareNonInheritedData->m_wrapShape)
589             return StyleDifferenceRepaint;
590
591 #if USE(ACCELERATED_COMPOSITING)
592     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
593         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
594             || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
595             || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
596             || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
597             || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
598             return StyleDifferenceRecompositeLayer;
599     }
600 #endif
601
602     // Cursors are not checked, since they will be set appropriately in response to mouse events,
603     // so they don't need to cause any repaint or layout.
604
605     // 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
606     // the resulting transition properly.
607     return StyleDifferenceEqual;
608 }
609
610 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
611 {
612     StyleVisualData* data = visual.access();
613     data->clip.m_top = top;
614     data->clip.m_right = right;
615     data->clip.m_bottom = bottom;
616     data->clip.m_left = left;
617 }
618
619 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
620 {
621     if (!rareInheritedData.access()->cursorData)
622         rareInheritedData.access()->cursorData = CursorList::create();
623     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
624 }
625
626 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
627 {
628     rareInheritedData.access()->cursorData = other;
629 }
630
631 void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
632 {
633     if (QuotesData::equal(rareInheritedData->quotes.get(), q.get()))
634         return;
635     rareInheritedData.access()->quotes = q;
636 }
637
638 void RenderStyle::clearCursorList()
639 {
640     if (rareInheritedData->cursorData)
641         rareInheritedData.access()->cursorData = 0;
642 }
643
644 void RenderStyle::clearContent()
645 {
646     if (rareNonInheritedData->m_content)
647         rareNonInheritedData.access()->m_content = nullptr;
648 }
649
650 void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
651 {
652     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
653     ContentData* lastContent = content.get();
654     while (lastContent && lastContent->next())
655         lastContent = lastContent->next();
656
657     if (lastContent)
658         lastContent->setNext(contentData);
659     else
660         content = contentData;
661 }
662
663 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
664 {
665     if (!image)
666         return;
667         
668     if (add) {
669         appendContent(ContentData::create(image));
670         return;
671     }
672
673     rareNonInheritedData.access()->m_content = ContentData::create(image);
674 }
675
676 void RenderStyle::setContent(const String& string, bool add)
677 {
678     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
679     if (add) {
680         ContentData* lastContent = content.get();
681         while (lastContent && lastContent->next())
682             lastContent = lastContent->next();
683
684         if (lastContent) {
685             // We attempt to merge with the last ContentData if possible.
686             if (lastContent->isText()) {
687                 TextContentData* textContent = static_cast<TextContentData*>(lastContent);
688                 String text = textContent->text();
689                 text += string;
690                 textContent->setText(text);
691             } else
692                 lastContent->setNext(ContentData::create(string));
693
694             return;
695         }
696     }
697
698     content = ContentData::create(string);
699 }
700
701 void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
702 {
703     if (!counter)
704         return;
705
706     if (add) {
707         appendContent(ContentData::create(counter));
708         return;
709     }
710
711     rareNonInheritedData.access()->m_content = ContentData::create(counter);
712 }
713
714 void RenderStyle::setContent(QuoteType quote, bool add)
715 {
716     if (add) {
717         appendContent(ContentData::create(quote));
718         return;
719     }
720
721     rareNonInheritedData.access()->m_content = ContentData::create(quote);
722 }
723
724 void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
725 {
726     // transform-origin brackets the transform with translate operations.
727     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
728     // in that case.
729     bool applyTransformOrigin = false;
730     unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
731     unsigned i;
732     if (applyOrigin == IncludeTransformOrigin) {
733         for (i = 0; i < s; i++) {
734             TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
735             if (type != TransformOperation::TRANSLATE_X
736                     && type != TransformOperation::TRANSLATE_Y
737                     && type != TransformOperation::TRANSLATE 
738                     && type != TransformOperation::TRANSLATE_Z
739                     && type != TransformOperation::TRANSLATE_3D
740                     ) {
741                 applyTransformOrigin = true;
742                 break;
743             }
744         }
745     }
746
747     if (applyTransformOrigin) {
748         transform.translate3d(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()), transformOriginZ());
749     }
750
751     for (i = 0; i < s; i++)
752         rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
753
754     if (applyTransformOrigin) {
755         transform.translate3d(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()), -transformOriginZ());
756     }
757 }
758
759 void RenderStyle::setPageScaleTransform(float scale)
760 {
761     if (scale == 1)
762         return;
763     TransformOperations transform;
764     transform.operations().append(ScaleTransformOperation::create(scale, scale, ScaleTransformOperation::SCALE));
765     setTransform(transform);
766     setTransformOriginX(Length(0, Fixed));
767     setTransformOriginY(Length(0, Fixed));
768 }
769
770 void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add)
771 {
772     ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
773
774     StyleRareInheritedData* rareData = rareInheritedData.access();
775     if (!add) {
776         rareData->textShadow = shadowData;
777         return;
778     }
779
780     shadowData->setNext(rareData->textShadow.release());
781     rareData->textShadow = shadowData;
782 }
783
784 void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
785 {
786     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
787     if (!add) {
788         rareData->m_boxShadow = shadowData;
789         return;
790     }
791
792     shadowData->setNext(rareData->m_boxShadow.release());
793     rareData->m_boxShadow = shadowData;
794 }
795
796 static RoundedRect::Radii calcRadiiFor(const BorderData& border, LayoutSize size)
797 {
798     return RoundedRect::Radii(
799         LayoutSize(border.topLeft().width().calcValue(size.width()), 
800                    border.topLeft().height().calcValue(size.height())),
801         LayoutSize(border.topRight().width().calcValue(size.width()),
802                    border.topRight().height().calcValue(size.height())),
803         LayoutSize(border.bottomLeft().width().calcValue(size.width()), 
804                    border.bottomLeft().height().calcValue(size.height())),
805         LayoutSize(border.bottomRight().width().calcValue(size.width()), 
806                    border.bottomRight().height().calcValue(size.height())));
807 }
808
809 static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
810 {
811     // Constrain corner radii using CSS3 rules:
812     // http://www.w3.org/TR/css3-background/#the-border-radius
813     
814     float factor = 1;
815     unsigned radiiSum;
816
817     // top
818     radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
819     if (radiiSum > static_cast<unsigned>(rect.width()))
820         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
821
822     // bottom
823     radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
824     if (radiiSum > static_cast<unsigned>(rect.width()))
825         factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
826     
827     // left
828     radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
829     if (radiiSum > static_cast<unsigned>(rect.height()))
830         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
831     
832     // right
833     radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
834     if (radiiSum > static_cast<unsigned>(rect.height()))
835         factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
836     
837     ASSERT(factor <= 1);
838     return factor;
839 }
840
841 RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
842 {
843     RoundedRect roundedRect(borderRect);
844     if (hasBorderRadius()) {
845         RoundedRect::Radii radii = calcRadiiFor(surround->border, borderRect.size());
846         radii.scale(calcConstraintScaleFor(borderRect, radii));
847         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
848     }
849     return roundedRect;
850 }
851
852 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
853 {
854     bool horizontal = isHorizontalWritingMode();
855
856     LayoutUnit leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
857     LayoutUnit rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
858     LayoutUnit topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
859     LayoutUnit bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
860
861     return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
862 }
863
864 RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
865     LayoutUnit topWidth, LayoutUnit bottomWidth, LayoutUnit leftWidth, LayoutUnit rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
866 {
867     LayoutRect innerRect(borderRect.x() + leftWidth, 
868                borderRect.y() + topWidth, 
869                borderRect.width() - leftWidth - rightWidth, 
870                borderRect.height() - topWidth - bottomWidth);
871
872     RoundedRect roundedRect(innerRect);
873
874     if (hasBorderRadius()) {
875         RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
876         radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
877         roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
878     }
879     return roundedRect;
880 }
881
882 const CounterDirectiveMap* RenderStyle::counterDirectives() const
883 {
884     return rareNonInheritedData->m_counterDirectives.get();
885 }
886
887 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
888 {
889     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
890     if (!map)
891         map = adoptPtr(new CounterDirectiveMap);
892     return *map;
893 }
894
895 const AtomicString& RenderStyle::hyphenString() const
896 {
897     ASSERT(hyphens() != HyphensNone);
898
899     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
900     if (!hyphenationString.isNull())
901         return hyphenationString;
902
903     // FIXME: This should depend on locale.
904     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
905     DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
906     return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
907 }
908
909 const AtomicString& RenderStyle::textEmphasisMarkString() const
910 {
911     switch (textEmphasisMark()) {
912     case TextEmphasisMarkNone:
913         return nullAtom;
914     case TextEmphasisMarkCustom:
915         return textEmphasisCustomMark();
916     case TextEmphasisMarkDot: {
917         DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
918         DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
919         return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
920     }
921     case TextEmphasisMarkCircle: {
922         DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
923         DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
924         return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
925     }
926     case TextEmphasisMarkDoubleCircle: {
927         DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
928         DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
929         return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
930     }
931     case TextEmphasisMarkTriangle: {
932         DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
933         DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
934         return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
935     }
936     case TextEmphasisMarkSesame: {
937         DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
938         DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
939         return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
940     }
941     case TextEmphasisMarkAuto:
942         ASSERT_NOT_REACHED();
943         return nullAtom;
944     }
945
946     ASSERT_NOT_REACHED();
947     return nullAtom;
948 }
949
950 #if ENABLE(DASHBOARD_SUPPORT)
951 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
952 {
953     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
954     return emptyList;
955 }
956
957 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
958 {
959     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
960     static bool noneListInitialized = false;
961
962     if (!noneListInitialized) {
963         StyleDashboardRegion region;
964         region.label = "";
965         region.offset.m_top  = Length();
966         region.offset.m_right = Length();
967         region.offset.m_bottom = Length();
968         region.offset.m_left = Length();
969         region.type = StyleDashboardRegion::None;
970         noneList.append(region);
971         noneListInitialized = true;
972     }
973     return noneList;
974 }
975 #endif
976
977 void RenderStyle::adjustAnimations()
978 {
979     AnimationList* animationList = rareNonInheritedData->m_animations.get();
980     if (!animationList)
981         return;
982
983     // Get rid of empty animations and anything beyond them
984     for (size_t i = 0; i < animationList->size(); ++i) {
985         if (animationList->animation(i)->isEmpty()) {
986             animationList->resize(i);
987             break;
988         }
989     }
990
991     if (animationList->isEmpty()) {
992         clearAnimations();
993         return;
994     }
995
996     // Repeat patterns into layers that don't have some properties set.
997     animationList->fillUnsetProperties();
998 }
999
1000 void RenderStyle::adjustTransitions()
1001 {
1002     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
1003     if (!transitionList)
1004         return;
1005
1006     // Get rid of empty transitions and anything beyond them
1007     for (size_t i = 0; i < transitionList->size(); ++i) {
1008         if (transitionList->animation(i)->isEmpty()) {
1009             transitionList->resize(i);
1010             break;
1011         }
1012     }
1013
1014     if (transitionList->isEmpty()) {
1015         clearTransitions();
1016         return;
1017     }
1018
1019     // Repeat patterns into layers that don't have some properties set.
1020     transitionList->fillUnsetProperties();
1021
1022     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
1023     // but the lists tend to be very short, so it is probably ok
1024     for (size_t i = 0; i < transitionList->size(); ++i) {
1025         for (size_t j = i+1; j < transitionList->size(); ++j) {
1026             if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
1027                 // toss i
1028                 transitionList->remove(i);
1029                 j = i;
1030             }
1031         }
1032     }
1033 }
1034
1035 AnimationList* RenderStyle::accessAnimations()
1036 {
1037     if (!rareNonInheritedData.access()->m_animations)
1038         rareNonInheritedData.access()->m_animations = adoptPtr(new AnimationList());
1039     return rareNonInheritedData->m_animations.get();
1040 }
1041
1042 AnimationList* RenderStyle::accessTransitions()
1043 {
1044     if (!rareNonInheritedData.access()->m_transitions)
1045         rareNonInheritedData.access()->m_transitions = adoptPtr(new AnimationList());
1046     return rareNonInheritedData->m_transitions.get();
1047 }
1048
1049 const Animation* RenderStyle::transitionForProperty(int property) const
1050 {
1051     if (transitions()) {
1052         for (size_t i = 0; i < transitions()->size(); ++i) {
1053             const Animation* p = transitions()->animation(i);
1054             if (p->property() == cAnimateAll || p->property() == property) {
1055                 return p;
1056             }
1057         }
1058     }
1059     return 0;
1060 }
1061
1062 void RenderStyle::setBlendedFontSize(int size)
1063 {
1064     FontSelector* currentFontSelector = font().fontSelector();
1065     FontDescription desc(fontDescription());
1066     desc.setSpecifiedSize(size);
1067     desc.setComputedSize(size);
1068     setFontDescription(desc);
1069     font().update(currentFontSelector);
1070 }
1071
1072 void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
1073 {
1074     top = 0;
1075     right = 0;
1076     bottom = 0;
1077     left = 0;
1078
1079     for ( ; shadow; shadow = shadow->next()) {
1080         if (shadow->style() == Inset)
1081             continue;
1082         int blurAndSpread = shadow->blur() + shadow->spread();
1083
1084         top = min(top, shadow->y() - blurAndSpread);
1085         right = max(right, shadow->x() + blurAndSpread);
1086         bottom = max(bottom, shadow->y() + blurAndSpread);
1087         left = min(left, shadow->x() - blurAndSpread);
1088     }
1089 }
1090
1091 void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
1092 {
1093     left = 0;
1094     right = 0;
1095
1096     for ( ; shadow; shadow = shadow->next()) {
1097         if (shadow->style() == Inset)
1098             continue;
1099         int blurAndSpread = shadow->blur() + shadow->spread();
1100
1101         left = min(left, shadow->x() - blurAndSpread);
1102         right = max(right, shadow->x() + blurAndSpread);
1103     }
1104 }
1105
1106 void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
1107 {
1108     top = 0;
1109     bottom = 0;
1110
1111     for ( ; shadow; shadow = shadow->next()) {
1112         if (shadow->style() == Inset)
1113             continue;
1114         int blurAndSpread = shadow->blur() + shadow->spread();
1115
1116         top = min(top, shadow->y() - blurAndSpread);
1117         bottom = max(bottom, shadow->y() + blurAndSpread);
1118     }
1119 }
1120
1121 Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
1122 {
1123     Color result;
1124     EBorderStyle borderStyle = BNONE;
1125     switch (colorProperty) {
1126     case CSSPropertyBackgroundColor:
1127         return visitedLink ? rareNonInheritedData->m_visitedLinkBackgroundColor : backgroundColor(); // Background color doesn't fall back.
1128     case CSSPropertyBorderLeftColor:
1129         result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderLeftColor : borderLeftColor();
1130         borderStyle = borderLeftStyle();
1131         break;
1132     case CSSPropertyBorderRightColor:
1133         result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderRightColor : borderRightColor();
1134         borderStyle = borderRightStyle();
1135         break;
1136     case CSSPropertyBorderTopColor:
1137         result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderTopColor : borderTopColor();
1138         borderStyle = borderTopStyle();
1139         break;
1140     case CSSPropertyBorderBottomColor:
1141         result = visitedLink ? rareNonInheritedData->m_visitedLinkBorderBottomColor : borderBottomColor();
1142         borderStyle = borderBottomStyle();
1143         break;
1144     case CSSPropertyColor:
1145         result = visitedLink ? inherited->visitedLinkColor : color();
1146         break;
1147     case CSSPropertyOutlineColor:
1148         result = visitedLink ? rareNonInheritedData->m_visitedLinkOutlineColor : outlineColor();
1149         break;
1150     case CSSPropertyWebkitColumnRuleColor:
1151         result = visitedLink ? rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor : columnRuleColor();
1152         break;
1153     case CSSPropertyWebkitTextEmphasisColor:
1154         result = visitedLink ? rareInheritedData->visitedLinkTextEmphasisColor : textEmphasisColor();
1155         break;
1156     case CSSPropertyWebkitTextFillColor:
1157         result = visitedLink ? rareInheritedData->visitedLinkTextFillColor : textFillColor();
1158         break;
1159     case CSSPropertyWebkitTextStrokeColor:
1160         result = visitedLink ? rareInheritedData->visitedLinkTextStrokeColor : textStrokeColor();
1161         break;
1162     default:
1163         ASSERT_NOT_REACHED();
1164         break;
1165     }
1166
1167     if (!result.isValid()) {
1168         if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1169             result.setRGB(238, 238, 238);
1170         else
1171             result = visitedLink ? inherited->visitedLinkColor : color();
1172     }
1173     return result;
1174 }
1175
1176 Color RenderStyle::visitedDependentColor(int colorProperty) const
1177 {
1178     Color unvisitedColor = colorIncludingFallback(colorProperty, false);
1179     if (insideLink() != InsideVisitedLink)
1180         return unvisitedColor;
1181
1182     Color visitedColor = colorIncludingFallback(colorProperty, true);
1183
1184     // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
1185     // assume that if the background color is transparent that it wasn't set. Note that it's weird that
1186     // we're returning unvisited info for a visited link, but given our restriction that the alpha values
1187     // have to match, it makes more sense to return the unvisited background color if specified than it
1188     // does to return black. This behavior matches what Firefox 4 does as well.
1189     if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
1190         return unvisitedColor;
1191
1192     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1193     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1194 }
1195
1196 Length RenderStyle::logicalWidth() const
1197 {
1198     if (isHorizontalWritingMode())
1199         return width();
1200     return height();
1201 }
1202
1203 Length RenderStyle::logicalHeight() const
1204 {
1205     if (isHorizontalWritingMode())
1206         return height();
1207     return width();
1208 }
1209
1210 Length RenderStyle::logicalMinWidth() const
1211 {
1212     if (isHorizontalWritingMode())
1213         return minWidth();
1214     return minHeight();
1215 }
1216
1217 Length RenderStyle::logicalMaxWidth() const
1218 {
1219     if (isHorizontalWritingMode())
1220         return maxWidth();
1221     return maxHeight();
1222 }
1223
1224 Length RenderStyle::logicalMinHeight() const
1225 {
1226     if (isHorizontalWritingMode())
1227         return minHeight();
1228     return minWidth();
1229 }
1230
1231 Length RenderStyle::logicalMaxHeight() const
1232 {
1233     if (isHorizontalWritingMode())
1234         return maxHeight();
1235     return maxWidth();
1236 }
1237
1238 const BorderValue& RenderStyle::borderBefore() const
1239 {
1240     switch (writingMode()) {
1241     case TopToBottomWritingMode:
1242         return borderTop();
1243     case BottomToTopWritingMode:
1244         return borderBottom();
1245     case LeftToRightWritingMode:
1246         return borderLeft();
1247     case RightToLeftWritingMode:
1248         return borderRight();
1249     }
1250     ASSERT_NOT_REACHED();
1251     return borderTop();
1252 }
1253
1254 const BorderValue& RenderStyle::borderAfter() const
1255 {
1256     switch (writingMode()) {
1257     case TopToBottomWritingMode:
1258         return borderBottom();
1259     case BottomToTopWritingMode:
1260         return borderTop();
1261     case LeftToRightWritingMode:
1262         return borderRight();
1263     case RightToLeftWritingMode:
1264         return borderLeft();
1265     }
1266     ASSERT_NOT_REACHED();
1267     return borderBottom();
1268 }
1269
1270 const BorderValue& RenderStyle::borderStart() const
1271 {
1272     if (isHorizontalWritingMode())
1273         return isLeftToRightDirection() ? borderLeft() : borderRight();
1274     return isLeftToRightDirection() ? borderTop() : borderBottom();
1275 }
1276
1277 const BorderValue& RenderStyle::borderEnd() const
1278 {
1279     if (isHorizontalWritingMode())
1280         return isLeftToRightDirection() ? borderRight() : borderLeft();
1281     return isLeftToRightDirection() ? borderBottom() : borderTop();
1282 }
1283
1284 unsigned short RenderStyle::borderBeforeWidth() const
1285 {
1286     switch (writingMode()) {
1287     case TopToBottomWritingMode:
1288         return borderTopWidth();
1289     case BottomToTopWritingMode:
1290         return borderBottomWidth();
1291     case LeftToRightWritingMode:
1292         return borderLeftWidth();
1293     case RightToLeftWritingMode:
1294         return borderRightWidth();
1295     }
1296     ASSERT_NOT_REACHED();
1297     return borderTopWidth();
1298 }
1299
1300 unsigned short RenderStyle::borderAfterWidth() const
1301 {
1302     switch (writingMode()) {
1303     case TopToBottomWritingMode:
1304         return borderBottomWidth();
1305     case BottomToTopWritingMode:
1306         return borderTopWidth();
1307     case LeftToRightWritingMode:
1308         return borderRightWidth();
1309     case RightToLeftWritingMode:
1310         return borderLeftWidth();
1311     }
1312     ASSERT_NOT_REACHED();
1313     return borderBottomWidth();
1314 }
1315
1316 unsigned short RenderStyle::borderStartWidth() const
1317 {
1318     if (isHorizontalWritingMode())
1319         return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
1320     return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
1321 }
1322
1323 unsigned short RenderStyle::borderEndWidth() const
1324 {
1325     if (isHorizontalWritingMode())
1326         return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
1327     return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
1328 }
1329     
1330 Length RenderStyle::marginBefore() const
1331 {
1332     switch (writingMode()) {
1333     case TopToBottomWritingMode:
1334         return marginTop();
1335     case BottomToTopWritingMode:
1336         return marginBottom();
1337     case LeftToRightWritingMode:
1338         return marginLeft();
1339     case RightToLeftWritingMode:
1340         return marginRight();
1341     }
1342     ASSERT_NOT_REACHED();
1343     return marginTop();
1344 }
1345
1346 Length RenderStyle::marginAfter() const
1347 {
1348     switch (writingMode()) {
1349     case TopToBottomWritingMode:
1350         return marginBottom();
1351     case BottomToTopWritingMode:
1352         return marginTop();
1353     case LeftToRightWritingMode:
1354         return marginRight();
1355     case RightToLeftWritingMode:
1356         return marginLeft();
1357     }
1358     ASSERT_NOT_REACHED();
1359     return marginBottom();
1360 }
1361
1362 Length RenderStyle::marginBeforeUsing(const RenderStyle* otherStyle) const
1363 {
1364     switch (otherStyle->writingMode()) {
1365     case TopToBottomWritingMode:
1366         return marginTop();
1367     case BottomToTopWritingMode:
1368         return marginBottom();
1369     case LeftToRightWritingMode:
1370         return marginLeft();
1371     case RightToLeftWritingMode:
1372         return marginRight();
1373     }
1374     ASSERT_NOT_REACHED();
1375     return marginTop();
1376 }
1377
1378 Length RenderStyle::marginAfterUsing(const RenderStyle* otherStyle) const
1379 {
1380     switch (otherStyle->writingMode()) {
1381     case TopToBottomWritingMode:
1382         return marginBottom();
1383     case BottomToTopWritingMode:
1384         return marginTop();
1385     case LeftToRightWritingMode:
1386         return marginRight();
1387     case RightToLeftWritingMode:
1388         return marginLeft();
1389     }
1390     ASSERT_NOT_REACHED();
1391     return marginBottom();
1392 }
1393
1394 Length RenderStyle::marginStart() const
1395 {
1396     if (isHorizontalWritingMode())
1397         return isLeftToRightDirection() ? marginLeft() : marginRight();
1398     return isLeftToRightDirection() ? marginTop() : marginBottom();
1399 }
1400
1401 Length RenderStyle::marginEnd() const
1402 {
1403     if (isHorizontalWritingMode())
1404         return isLeftToRightDirection() ? marginRight() : marginLeft();
1405     return isLeftToRightDirection() ? marginBottom() : marginTop();
1406 }
1407     
1408 Length RenderStyle::marginStartUsing(const RenderStyle* otherStyle) const
1409 {
1410     if (otherStyle->isHorizontalWritingMode())
1411         return otherStyle->isLeftToRightDirection() ? marginLeft() : marginRight();
1412     return otherStyle->isLeftToRightDirection() ? marginTop() : marginBottom();
1413 }
1414
1415 Length RenderStyle::marginEndUsing(const RenderStyle* otherStyle) const
1416 {
1417     if (otherStyle->isHorizontalWritingMode())
1418         return otherStyle->isLeftToRightDirection() ? marginRight() : marginLeft();
1419     return otherStyle->isLeftToRightDirection() ? marginBottom() : marginTop();
1420 }
1421
1422 void RenderStyle::setMarginStart(Length margin)
1423 {
1424     if (isHorizontalWritingMode()) {
1425         if (isLeftToRightDirection())
1426             setMarginLeft(margin);
1427         else
1428             setMarginRight(margin);
1429     } else {
1430         if (isLeftToRightDirection())
1431             setMarginTop(margin);
1432         else
1433             setMarginBottom(margin);
1434     }
1435 }
1436
1437 void RenderStyle::setMarginEnd(Length margin)
1438 {
1439     if (isHorizontalWritingMode()) {
1440         if (isLeftToRightDirection())
1441             setMarginRight(margin);
1442         else
1443             setMarginLeft(margin);
1444     } else {
1445         if (isLeftToRightDirection())
1446             setMarginBottom(margin);
1447         else
1448             setMarginTop(margin);
1449     }
1450 }
1451
1452 Length RenderStyle::paddingBefore() const
1453 {
1454     switch (writingMode()) {
1455     case TopToBottomWritingMode:
1456         return paddingTop();
1457     case BottomToTopWritingMode:
1458         return paddingBottom();
1459     case LeftToRightWritingMode:
1460         return paddingLeft();
1461     case RightToLeftWritingMode:
1462         return paddingRight();
1463     }
1464     ASSERT_NOT_REACHED();
1465     return paddingTop();
1466 }
1467
1468 Length RenderStyle::paddingAfter() const
1469 {
1470     switch (writingMode()) {
1471     case TopToBottomWritingMode:
1472         return paddingBottom();
1473     case BottomToTopWritingMode:
1474         return paddingTop();
1475     case LeftToRightWritingMode:
1476         return paddingRight();
1477     case RightToLeftWritingMode:
1478         return paddingLeft();
1479     }
1480     ASSERT_NOT_REACHED();
1481     return paddingBottom();
1482 }
1483
1484 Length RenderStyle::paddingStart() const
1485 {
1486     if (isHorizontalWritingMode())
1487         return isLeftToRightDirection() ? paddingLeft() : paddingRight();
1488     return isLeftToRightDirection() ? paddingTop() : paddingBottom();
1489 }
1490
1491 Length RenderStyle::paddingEnd() const
1492 {
1493     if (isHorizontalWritingMode())
1494         return isLeftToRightDirection() ? paddingRight() : paddingLeft();
1495     return isLeftToRightDirection() ? paddingBottom() : paddingTop();
1496 }
1497
1498 TextEmphasisMark RenderStyle::textEmphasisMark() const
1499 {
1500     TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
1501     if (mark != TextEmphasisMarkAuto)
1502         return mark;
1503
1504     if (isHorizontalWritingMode())
1505         return TextEmphasisMarkDot;
1506
1507     return TextEmphasisMarkSesame;
1508 }
1509
1510 #if ENABLE(TOUCH_EVENTS)
1511 Color RenderStyle::initialTapHighlightColor()
1512 {
1513     return RenderTheme::tapHighlightColor();
1514 }
1515 #endif
1516
1517 void RenderStyle::getImageOutsets(const NinePieceImage& image, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const
1518 {
1519     top = NinePieceImage::computeOutset(image.outset().top(), borderTopWidth());
1520     right = NinePieceImage::computeOutset(image.outset().right(), borderRightWidth());
1521     bottom = NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth());
1522     left = NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth());
1523 }
1524
1525 void RenderStyle::getImageHorizontalOutsets(const NinePieceImage& image, LayoutUnit& left, LayoutUnit& right) const
1526 {
1527     right = NinePieceImage::computeOutset(image.outset().right(), borderRightWidth());
1528     left = NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth());
1529 }
1530
1531 void RenderStyle::getImageVerticalOutsets(const NinePieceImage& image, LayoutUnit& top, LayoutUnit& bottom) const
1532 {
1533     top = NinePieceImage::computeOutset(image.outset().top(), borderTopWidth());
1534     bottom = NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth());
1535 }
1536
1537 } // namespace WebCore