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