OSDN Git Service

Merge "Bug2811469 - wide space in RTL layout"
[android-x86/external-webkit.git] / 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 "CSSPropertyNames.h"
26 #include "CSSStyleSelector.h"
27 #include "FontSelector.h"
28 #include "RenderArena.h"
29 #include "RenderObject.h"
30 #include "StyleImage.h"
31 #include <wtf/StdLibExtras.h>
32 #include <algorithm>
33
34 using namespace std;
35
36 namespace WebCore {
37
38 inline RenderStyle* defaultStyle()
39 {
40     static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().releaseRef();
41     return s_defaultStyle;
42 }
43
44 PassRefPtr<RenderStyle> RenderStyle::create()
45 {
46     return adoptRef(new RenderStyle());
47 }
48
49 PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
50 {
51     return adoptRef(new RenderStyle(true));
52 }
53
54 PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
55 {
56     return adoptRef(new RenderStyle(*other));
57 }
58
59 ALWAYS_INLINE RenderStyle::RenderStyle()
60     : m_affectedByAttributeSelectors(false)
61     , m_unique(false)
62     , m_affectedByEmpty(false)
63     , m_emptyState(false)
64     , m_childrenAffectedByFirstChildRules(false)
65     , m_childrenAffectedByLastChildRules(false)
66     , m_childrenAffectedByDirectAdjacentRules(false)
67     , m_childrenAffectedByForwardPositionalRules(false)
68     , m_childrenAffectedByBackwardPositionalRules(false)
69     , m_firstChildState(false)
70     , m_lastChildState(false)
71     , m_childIndex(0)
72     , m_box(defaultStyle()->m_box)
73     , visual(defaultStyle()->visual)
74     , m_background(defaultStyle()->m_background)
75     , surround(defaultStyle()->surround)
76     , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
77     , rareInheritedData(defaultStyle()->rareInheritedData)
78     , inherited(defaultStyle()->inherited)
79 #if ENABLE(SVG)
80     , m_svgStyle(defaultStyle()->m_svgStyle)
81 #endif
82 {
83     setBitDefaults(); // Would it be faster to copy this from the default style?
84 }
85
86 ALWAYS_INLINE RenderStyle::RenderStyle(bool)
87     : m_affectedByAttributeSelectors(false)
88     , m_unique(false)
89     , m_affectedByEmpty(false)
90     , m_emptyState(false)
91     , m_childrenAffectedByFirstChildRules(false)
92     , m_childrenAffectedByLastChildRules(false)
93     , m_childrenAffectedByDirectAdjacentRules(false)
94     , m_childrenAffectedByForwardPositionalRules(false)
95     , m_childrenAffectedByBackwardPositionalRules(false)
96     , m_firstChildState(false)
97     , m_lastChildState(false)
98     , m_childIndex(0)
99 {
100     setBitDefaults();
101
102     m_box.init();
103     visual.init();
104     m_background.init();
105     surround.init();
106     rareNonInheritedData.init();
107     rareNonInheritedData.access()->flexibleBox.init();
108     rareNonInheritedData.access()->marquee.init();
109     rareNonInheritedData.access()->m_multiCol.init();
110     rareNonInheritedData.access()->m_transform.init();
111     rareInheritedData.init();
112     inherited.init();
113
114 #if ENABLE(SVG)
115     m_svgStyle.init();
116 #endif
117 }
118
119 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
120     : RefCounted<RenderStyle>()
121     , m_affectedByAttributeSelectors(false)
122     , m_unique(false)
123     , m_affectedByEmpty(false)
124     , m_emptyState(false)
125     , m_childrenAffectedByFirstChildRules(false)
126     , m_childrenAffectedByLastChildRules(false)
127     , m_childrenAffectedByDirectAdjacentRules(false)
128     , m_childrenAffectedByForwardPositionalRules(false)
129     , m_childrenAffectedByBackwardPositionalRules(false)
130     , m_firstChildState(false)
131     , m_lastChildState(false)
132     , m_childIndex(0)
133     , m_box(o.m_box)
134     , visual(o.visual)
135     , m_background(o.m_background)
136     , surround(o.surround)
137     , rareNonInheritedData(o.rareNonInheritedData)
138     , rareInheritedData(o.rareInheritedData)
139     , inherited(o.inherited)
140 #if ENABLE(SVG)
141     , m_svgStyle(o.m_svgStyle)
142 #endif
143     , inherited_flags(o.inherited_flags)
144     , noninherited_flags(o.noninherited_flags)
145 {
146 }
147
148 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
149 {
150     rareInheritedData = inheritParent->rareInheritedData;
151     inherited = inheritParent->inherited;
152     inherited_flags = inheritParent->inherited_flags;
153 #if ENABLE(SVG)
154     if (m_svgStyle != inheritParent->m_svgStyle)
155         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
156 #endif
157 }
158
159 RenderStyle::~RenderStyle()
160 {
161 }
162
163 bool RenderStyle::operator==(const RenderStyle& o) const
164 {
165     // compare everything except the pseudoStyle pointer
166     return inherited_flags == o.inherited_flags &&
167             noninherited_flags == o.noninherited_flags &&
168             m_box == o.m_box &&
169             visual == o.visual &&
170             m_background == o.m_background &&
171             surround == o.surround &&
172             rareNonInheritedData == o.rareNonInheritedData &&
173             rareInheritedData == o.rareInheritedData &&
174             inherited == o.inherited
175 #if ENABLE(SVG)
176             && m_svgStyle == o.m_svgStyle
177 #endif
178             ;
179 }
180
181 bool RenderStyle::isStyleAvailable() const
182 {
183     return this != CSSStyleSelector::styleNotYetAvailable();
184 }
185
186 static inline int pseudoBit(PseudoId pseudo)
187 {
188     return 1 << (pseudo - 1);
189 }
190
191 bool RenderStyle::hasAnyPublicPseudoStyles() const
192 {
193     return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
194 }
195
196 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
197 {
198     ASSERT(pseudo > NOPSEUDO);
199     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
200     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
201 }
202
203 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
204 {
205     ASSERT(pseudo > NOPSEUDO);
206     ASSERT(pseudo < FIRST_INTERNAL_PSEUDOID);
207     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
208 }
209
210 RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
211 {
212     ASSERT(styleType() != VISITED_LINK);
213
214     if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
215         return 0;
216
217     if (styleType() != NOPSEUDO) {
218         if (pid == VISITED_LINK)
219             return m_cachedPseudoStyles->at(0)->styleType() == VISITED_LINK ? m_cachedPseudoStyles->at(0).get() : 0;
220         return 0;
221     }
222
223     for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
224         RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
225         if (pseudoStyle->styleType() == pid)
226             return pseudoStyle;
227     }
228
229     return 0;
230 }
231
232 RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
233 {
234     if (!pseudo)
235         return 0;
236     
237     RenderStyle* result = pseudo.get();
238
239     if (!m_cachedPseudoStyles)
240         m_cachedPseudoStyles.set(new PseudoStyleCache);
241
242     m_cachedPseudoStyles->append(pseudo);
243
244     return result;
245 }
246
247 bool RenderStyle::inheritedNotEqual(const RenderStyle* other) const
248 {
249     return inherited_flags != other->inherited_flags ||
250            inherited != other->inherited ||
251 #if ENABLE(SVG)
252            m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
253 #endif
254            rareInheritedData != other->rareInheritedData;
255 }
256
257 static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b)
258 {
259     // If any unit types are different, then we can't guarantee
260     // that this was just a movement.
261     if (a.left().type() != b.left().type() ||
262         a.right().type() != b.right().type() ||
263         a.top().type() != b.top().type() ||
264         a.bottom().type() != b.bottom().type())
265         return false;
266
267     // Only one unit can be non-auto in the horizontal direction and
268     // in the vertical direction.  Otherwise the adjustment of values
269     // is changing the size of the box.
270     if (!a.left().isIntrinsicOrAuto() && !a.right().isIntrinsicOrAuto())
271         return false;
272     if (!a.top().isIntrinsicOrAuto() && !a.bottom().isIntrinsicOrAuto())
273         return false;
274
275     // One of the units is fixed or percent in both directions and stayed
276     // that way in the new style.  Therefore all we are doing is moving.
277     return true;
278 }
279
280 /*
281   compares two styles. The result gives an idea of the action that
282   needs to be taken when replacing the old style with a new one.
283
284   CbLayout: The containing block of the object needs a relayout.
285   Layout: the RenderObject needs a relayout after the style change
286   Visible: The change is visible, but no relayout is needed
287   NonVisible: The object does need neither repaint nor relayout after
288        the change.
289
290   ### TODO:
291   A lot can be optimised here based on the display type, lots of
292   optimisations are unimplemented, and currently result in the
293   worst case result causing a relayout of the containing block.
294 */
295 StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
296 {
297     changedContextSensitiveProperties = ContextSensitivePropertyNone;
298
299 #if ENABLE(SVG)
300     if (m_svgStyle != other->m_svgStyle)
301         return m_svgStyle->diff(other->m_svgStyle.get());
302 #endif
303
304     if (m_box->width() != other->m_box->width() ||
305         m_box->minWidth() != other->m_box->minWidth() ||
306         m_box->maxWidth() != other->m_box->maxWidth() ||
307         m_box->height() != other->m_box->height() ||
308         m_box->minHeight() != other->m_box->minHeight() ||
309         m_box->maxHeight() != other->m_box->maxHeight())
310         return StyleDifferenceLayout;
311
312     if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
313         return StyleDifferenceLayout;
314
315     if (m_box->boxSizing() != other->m_box->boxSizing())
316         return StyleDifferenceLayout;
317
318     if (surround->margin != other->surround->margin)
319         return StyleDifferenceLayout;
320
321     if (surround->padding != other->surround->padding)
322         return StyleDifferenceLayout;
323
324     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
325         if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance ||
326             rareNonInheritedData->marginTopCollapse != other->rareNonInheritedData->marginTopCollapse ||
327             rareNonInheritedData->marginBottomCollapse != other->rareNonInheritedData->marginBottomCollapse ||
328             rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp ||
329             rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
330             return StyleDifferenceLayout;
331
332         if (rareNonInheritedData->flexibleBox.get() != other->rareNonInheritedData->flexibleBox.get() &&
333             *rareNonInheritedData->flexibleBox.get() != *other->rareNonInheritedData->flexibleBox.get())
334             return StyleDifferenceLayout;
335
336         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
337         if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
338             return StyleDifferenceLayout;
339
340         if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
341             return StyleDifferenceLayout;
342
343         if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get() &&
344             *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
345             return StyleDifferenceLayout;
346
347         if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get() &&
348             *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
349 #if USE(ACCELERATED_COMPOSITING)
350             changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
351             // Don't return; keep looking for another change
352 #else
353             return StyleDifferenceLayout;
354 #endif
355         }
356
357 #if !USE(ACCELERATED_COMPOSITING)
358         if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
359             if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
360                 rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
361                 rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
362                 rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
363                 rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
364                 return StyleDifferenceLayout;
365         }
366 #endif
367
368 #if ENABLE(DASHBOARD_SUPPORT)
369         // If regions change, trigger a relayout to re-calc regions.
370         if (rareNonInheritedData->m_dashboardRegions != other->rareNonInheritedData->m_dashboardRegions)
371             return StyleDifferenceLayout;
372 #endif
373     }
374
375     if (rareInheritedData.get() != other->rareInheritedData.get()) {
376         if (rareInheritedData->highlight != other->rareInheritedData->highlight ||
377             rareInheritedData->indent != other->rareInheritedData->indent ||
378             rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom ||
379             rareInheritedData->textSizeAdjust != other->rareInheritedData->textSizeAdjust ||
380             rareInheritedData->wordBreak != other->rareInheritedData->wordBreak ||
381             rareInheritedData->wordWrap != other->rareInheritedData->wordWrap ||
382             rareInheritedData->nbspMode != other->rareInheritedData->nbspMode ||
383             rareInheritedData->khtmlLineBreak != other->rareInheritedData->khtmlLineBreak ||
384             rareInheritedData->textSecurity != other->rareInheritedData->textSecurity ||
385             rareInheritedData->hyphens != other->rareInheritedData->hyphens ||
386             rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString ||
387             rareInheritedData->hyphenationLocale != other->rareInheritedData->hyphenationLocale)
388             return StyleDifferenceLayout;
389
390         if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
391             return StyleDifferenceLayout;
392
393         if (textStrokeWidth() != other->textStrokeWidth())
394             return StyleDifferenceLayout;
395     }
396
397     if (inherited->line_height != other->inherited->line_height ||
398         inherited->list_style_image != other->inherited->list_style_image ||
399         inherited->font != other->inherited->font ||
400         inherited->horizontal_border_spacing != other->inherited->horizontal_border_spacing ||
401         inherited->vertical_border_spacing != other->inherited->vertical_border_spacing ||
402         inherited_flags._box_direction != other->inherited_flags._box_direction ||
403         inherited_flags._visuallyOrdered != other->inherited_flags._visuallyOrdered ||
404         noninherited_flags._position != other->noninherited_flags._position ||
405         noninherited_flags._floating != other->noninherited_flags._floating ||
406         noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
407         return StyleDifferenceLayout;
408
409
410     if (((int)noninherited_flags._effectiveDisplay) >= TABLE) {
411         if (inherited_flags._border_collapse != other->inherited_flags._border_collapse ||
412             inherited_flags._empty_cells != other->inherited_flags._empty_cells ||
413             inherited_flags._caption_side != other->inherited_flags._caption_side ||
414             noninherited_flags._table_layout != other->noninherited_flags._table_layout)
415             return StyleDifferenceLayout;
416
417         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
418         // does not, so these style differences can be width differences.
419         if (inherited_flags._border_collapse &&
420             ((borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE) ||
421              (borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN) ||
422              (borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE) ||
423              (borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN) ||
424              (borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE) ||
425              (borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN) ||
426              (borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE) ||
427              (borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN)))
428             return StyleDifferenceLayout;
429     }
430
431     if (noninherited_flags._effectiveDisplay == LIST_ITEM) {
432         if (inherited_flags._list_style_type != other->inherited_flags._list_style_type ||
433             inherited_flags._list_style_position != other->inherited_flags._list_style_position)
434             return StyleDifferenceLayout;
435     }
436
437     if (inherited_flags._text_align != other->inherited_flags._text_align ||
438         inherited_flags._text_transform != other->inherited_flags._text_transform ||
439         inherited_flags._direction != other->inherited_flags._direction ||
440         inherited_flags._white_space != other->inherited_flags._white_space ||
441         noninherited_flags._clear != other->noninherited_flags._clear)
442         return StyleDifferenceLayout;
443
444     // Check block flow direction.
445     if (inherited_flags._blockFlow != other->inherited_flags._blockFlow)
446         return StyleDifferenceLayout;
447
448     // Overflow returns a layout hint.
449     if (noninherited_flags._overflowX != other->noninherited_flags._overflowX ||
450         noninherited_flags._overflowY != other->noninherited_flags._overflowY)
451         return StyleDifferenceLayout;
452
453     // If our border widths change, then we need to layout.  Other changes to borders
454     // only necessitate a repaint.
455     if (borderLeftWidth() != other->borderLeftWidth() ||
456         borderTopWidth() != other->borderTopWidth() ||
457         borderBottomWidth() != other->borderBottomWidth() ||
458         borderRightWidth() != other->borderRightWidth())
459         return StyleDifferenceLayout;
460
461     // If the counter directives change, trigger a relayout to re-calculate counter values and rebuild the counter node tree.
462     const CounterDirectiveMap* mapA = rareNonInheritedData->m_counterDirectives.get();
463     const CounterDirectiveMap* mapB = other->rareNonInheritedData->m_counterDirectives.get();
464     if (!(mapA == mapB || (mapA && mapB && *mapA == *mapB)))
465         return StyleDifferenceLayout;
466     if (rareNonInheritedData->m_counterIncrement != other->rareNonInheritedData->m_counterIncrement ||
467         rareNonInheritedData->m_counterReset != other->rareNonInheritedData->m_counterReset)
468         return StyleDifferenceLayout;
469
470     if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1) ||
471         (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
472         // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
473         return StyleDifferenceLayout;
474     }
475
476     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
477         return StyleDifferenceLayout;
478
479     // Make sure these left/top/right/bottom checks stay below all layout checks and above
480     // all visible checks.
481     if (position() != StaticPosition) {
482         if (surround->offset != other->surround->offset) {
483              // Optimize for the case where a positioned layer is moving but not changing size.
484             if (position() == AbsolutePosition && positionedObjectMoved(surround->offset, other->surround->offset))
485                 return StyleDifferenceLayoutPositionedMovementOnly;
486
487             // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
488             // can stop doing a layout when relative positioned objects move.  In particular, we'll need
489             // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
490             //if (other->position() == RelativePosition)
491             //    return RepaintLayer;
492             //else
493                 return StyleDifferenceLayout;
494         } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex() ||
495                  visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
496             return StyleDifferenceRepaintLayer;
497     }
498
499     if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
500 #if USE(ACCELERATED_COMPOSITING)
501         changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
502         // Don't return; keep looking for another change.
503 #else
504         return StyleDifferenceRepaintLayer;
505 #endif
506     }
507
508     if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask ||
509         rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
510         return StyleDifferenceRepaintLayer;
511
512     if (inherited->color != other->inherited->color ||
513         inherited_flags._visibility != other->inherited_flags._visibility ||
514         inherited_flags._text_decorations != other->inherited_flags._text_decorations ||
515         inherited_flags._force_backgrounds_to_white != other->inherited_flags._force_backgrounds_to_white ||
516         inherited_flags._insideLink != other->inherited_flags._insideLink ||
517         surround->border != other->surround->border ||
518         *m_background.get() != *other->m_background.get() ||
519         visual->textDecoration != other->visual->textDecoration ||
520         rareInheritedData->userModify != other->rareInheritedData->userModify ||
521         rareInheritedData->userSelect != other->rareInheritedData->userSelect ||
522         rareNonInheritedData->userDrag != other->rareNonInheritedData->userDrag ||
523         rareNonInheritedData->m_borderFit != other->rareNonInheritedData->m_borderFit ||
524         rareInheritedData->textFillColor != other->rareInheritedData->textFillColor ||
525         rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor)
526         return StyleDifferenceRepaint;
527
528 #if USE(ACCELERATED_COMPOSITING)
529     if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
530         if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D ||
531             rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility ||
532             rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective ||
533             rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX ||
534             rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
535             return StyleDifferenceRecompositeLayer;
536     }
537 #endif
538
539     // Cursors are not checked, since they will be set appropriately in response to mouse events,
540     // so they don't need to cause any repaint or layout.
541
542     // 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
543     // the resulting transition properly.
544     return StyleDifferenceEqual;
545 }
546
547 void RenderStyle::setClip(Length top, Length right, Length bottom, Length left)
548 {
549     StyleVisualData* data = visual.access();
550     data->clip.m_top = top;
551     data->clip.m_right = right;
552     data->clip.m_bottom = bottom;
553     data->clip.m_left = left;
554 }
555
556 void RenderStyle::addCursor(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
557 {
558     if (!rareInheritedData.access()->cursorData)
559         rareInheritedData.access()->cursorData = CursorList::create();
560     rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
561 }
562
563 void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
564 {
565     rareInheritedData.access()->cursorData = other;
566 }
567
568 void RenderStyle::clearCursorList()
569 {
570     if (rareInheritedData->cursorData)
571         rareInheritedData.access()->cursorData = 0;
572 }
573
574 void RenderStyle::clearContent()
575 {
576     if (rareNonInheritedData->m_content)
577         rareNonInheritedData->m_content->clear();
578 }
579
580 ContentData* RenderStyle::prepareToSetContent(StringImpl* string, bool add)
581 {
582     OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
583     ContentData* lastContent = content.get();
584     while (lastContent && lastContent->next())
585         lastContent = lastContent->next();
586
587     if (string && add && lastContent && lastContent->isText()) {
588         // Augment the existing string and share the existing ContentData node.
589         String newText = lastContent->text();
590         newText.append(string);
591         lastContent->setText(newText.impl());
592         return 0;
593     }
594
595     bool reuseContent = !add;
596     OwnPtr<ContentData> newContentData;
597     if (reuseContent && content) {
598         content->clear();
599         newContentData = content.release();
600     } else
601         newContentData = adoptPtr(new ContentData);
602
603     ContentData* result = newContentData.get();
604
605     if (lastContent && !reuseContent)
606         lastContent->setNext(newContentData.release());
607     else
608         content = newContentData.release();
609
610     return result;
611 }
612
613 void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
614 {
615     if (!image)
616         return;
617     prepareToSetContent(0, add)->setImage(image);
618 }
619
620 void RenderStyle::setContent(PassRefPtr<StringImpl> string, bool add)
621 {
622     if (!string)
623         return;
624     if (ContentData* data = prepareToSetContent(string.get(), add))
625         data->setText(string);
626 }
627
628 void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
629 {
630     if (!counter)
631         return;
632     prepareToSetContent(0, add)->setCounter(counter);
633 }
634
635 void RenderStyle::applyTransform(TransformationMatrix& transform, const IntSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
636 {
637     // transform-origin brackets the transform with translate operations.
638     // Optimize for the case where the only transform is a translation, since the transform-origin is irrelevant
639     // in that case.
640     bool applyTransformOrigin = false;
641     unsigned s = rareNonInheritedData->m_transform->m_operations.operations().size();
642     unsigned i;
643     if (applyOrigin == IncludeTransformOrigin) {
644         for (i = 0; i < s; i++) {
645             TransformOperation::OperationType type = rareNonInheritedData->m_transform->m_operations.operations()[i]->getOperationType();
646             if (type != TransformOperation::TRANSLATE_X &&
647                     type != TransformOperation::TRANSLATE_Y &&
648                     type != TransformOperation::TRANSLATE && 
649                     type != TransformOperation::TRANSLATE_Z && 
650                     type != TransformOperation::TRANSLATE_3D
651                     ) {
652                 applyTransformOrigin = true;
653                 break;
654             }
655         }
656     }
657
658     if (applyTransformOrigin) {
659         transform.translate3d(transformOriginX().calcFloatValue(borderBoxSize.width()), transformOriginY().calcFloatValue(borderBoxSize.height()), transformOriginZ());
660     }
661
662     for (i = 0; i < s; i++)
663         rareNonInheritedData->m_transform->m_operations.operations()[i]->apply(transform, borderBoxSize);
664
665     if (applyTransformOrigin) {
666         transform.translate3d(-transformOriginX().calcFloatValue(borderBoxSize.width()), -transformOriginY().calcFloatValue(borderBoxSize.height()), -transformOriginZ());
667     }
668 }
669
670 void RenderStyle::setTextShadow(ShadowData* val, bool add)
671 {
672     ASSERT(!val || (!val->spread() && val->style() == Normal));
673
674     StyleRareInheritedData* rareData = rareInheritedData.access();
675     if (!add) {
676         delete rareData->textShadow;
677         rareData->textShadow = val;
678         return;
679     }
680
681     val->setNext(rareData->textShadow);
682     rareData->textShadow = val;
683 }
684
685 void RenderStyle::setBoxShadow(ShadowData* shadowData, bool add)
686 {
687     StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
688     if (!add) {
689         rareData->m_boxShadow.set(shadowData);
690         return;
691     }
692
693     shadowData->setNext(rareData->m_boxShadow.leakPtr());
694     rareData->m_boxShadow.set(shadowData);
695 }
696
697 static void constrainCornerRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight)
698 {
699     // Constrain corner radii using CSS3 rules:
700     // http://www.w3.org/TR/css3-background/#the-border-radius
701     
702     float factor = 1;
703     unsigned radiiSum;
704
705     // top
706     radiiSum = static_cast<unsigned>(topLeft.width()) + static_cast<unsigned>(topRight.width()); // Casts to avoid integer overflow.
707     if (radiiSum > static_cast<unsigned>(r.width()))
708         factor = min(static_cast<float>(r.width()) / radiiSum, factor);
709
710     // bottom
711     radiiSum = static_cast<unsigned>(bottomLeft.width()) + static_cast<unsigned>(bottomRight.width());
712     if (radiiSum > static_cast<unsigned>(r.width()))
713         factor = min(static_cast<float>(r.width()) / radiiSum, factor);
714     
715     // left
716     radiiSum = static_cast<unsigned>(topLeft.height()) + static_cast<unsigned>(bottomLeft.height());
717     if (radiiSum > static_cast<unsigned>(r.height()))
718         factor = min(static_cast<float>(r.height()) / radiiSum, factor);
719     
720     // right
721     radiiSum = static_cast<unsigned>(topRight.height()) + static_cast<unsigned>(bottomRight.height());
722     if (radiiSum > static_cast<unsigned>(r.height()))
723         factor = min(static_cast<float>(r.height()) / radiiSum, factor);
724     
725     // Scale all radii by f if necessary.
726     if (factor < 1) {
727         // If either radius on a corner becomes zero, reset both radii on that corner.
728         topLeft.scale(factor);
729         if (!topLeft.width() || !topLeft.height())
730             topLeft = IntSize();
731         topRight.scale(factor);
732         if (!topRight.width() || !topRight.height())
733             topRight = IntSize();
734         bottomLeft.scale(factor);
735         if (!bottomLeft.width() || !bottomLeft.height())
736             bottomLeft = IntSize();
737         bottomRight.scale(factor);
738         if (!bottomRight.width() || !bottomRight.height())
739             bottomRight = IntSize();
740     }
741 }
742
743 void RenderStyle::getBorderRadiiForRect(const IntRect& r, IntSize& topLeft, IntSize& topRight, IntSize& bottomLeft, IntSize& bottomRight) const
744 {
745     topLeft = IntSize(surround->border.topLeft().width().calcValue(r.width()), surround->border.topLeft().height().calcValue(r.height()));
746     topRight = IntSize(surround->border.topRight().width().calcValue(r.width()), surround->border.topRight().height().calcValue(r.height()));
747     
748     bottomLeft = IntSize(surround->border.bottomLeft().width().calcValue(r.width()), surround->border.bottomLeft().height().calcValue(r.height()));
749     bottomRight = IntSize(surround->border.bottomRight().width().calcValue(r.width()), surround->border.bottomRight().height().calcValue(r.height()));
750
751     constrainCornerRadiiForRect(r, topLeft, topRight, bottomLeft, bottomRight);
752 }
753
754 void RenderStyle::getInnerBorderRadiiForRectWithBorderWidths(const IntRect& innerRect, unsigned short topWidth, unsigned short bottomWidth, unsigned short leftWidth, unsigned short rightWidth, IntSize& innerTopLeft, IntSize& innerTopRight, IntSize& innerBottomLeft, IntSize& innerBottomRight) const
755 {
756     innerTopLeft = IntSize(surround->border.topLeft().width().calcValue(innerRect.width()), surround->border.topLeft().height().calcValue(innerRect.height()));
757     innerTopRight = IntSize(surround->border.topRight().width().calcValue(innerRect.width()), surround->border.topRight().height().calcValue(innerRect.height()));
758     innerBottomLeft = IntSize(surround->border.bottomLeft().width().calcValue(innerRect.width()), surround->border.bottomLeft().height().calcValue(innerRect.height()));
759     innerBottomRight = IntSize(surround->border.bottomRight().width().calcValue(innerRect.width()), surround->border.bottomRight().height().calcValue(innerRect.height()));
760
761
762     innerTopLeft.setWidth(max(0, innerTopLeft.width() - leftWidth));
763     innerTopLeft.setHeight(max(0, innerTopLeft.height() - topWidth));
764
765     innerTopRight.setWidth(max(0, innerTopRight.width() - rightWidth));
766     innerTopRight.setHeight(max(0, innerTopRight.height() - topWidth));
767
768     innerBottomLeft.setWidth(max(0, innerBottomLeft.width() - leftWidth));
769     innerBottomLeft.setHeight(max(0, innerBottomLeft.height() - bottomWidth));
770
771     innerBottomRight.setWidth(max(0, innerBottomRight.width() - rightWidth));
772     innerBottomRight.setHeight(max(0, innerBottomRight.height() - bottomWidth));
773
774     constrainCornerRadiiForRect(innerRect, innerTopLeft, innerTopRight, innerBottomLeft, innerBottomRight);
775 }
776
777 const CounterDirectiveMap* RenderStyle::counterDirectives() const
778 {
779     return rareNonInheritedData->m_counterDirectives.get();
780 }
781
782 CounterDirectiveMap& RenderStyle::accessCounterDirectives()
783 {
784     OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
785     if (!map)
786         map.set(new CounterDirectiveMap);
787     return *map.get();
788 }
789
790 const AtomicString& RenderStyle::hyphenString() const
791 {
792     ASSERT(hyphens() == HyphensAuto);
793
794     const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
795     if (!hyphenationString.isNull())
796         return hyphenationString;
797
798     // FIXME: This should depend on locale.
799     DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphen, 1));
800     return hyphenMinusString;
801 }
802
803 #if ENABLE(DASHBOARD_SUPPORT)
804 const Vector<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
805 {
806     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, emptyList, ());
807     return emptyList;
808 }
809
810 const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
811 {
812     DEFINE_STATIC_LOCAL(Vector<StyleDashboardRegion>, noneList, ());
813     static bool noneListInitialized = false;
814
815     if (!noneListInitialized) {
816         StyleDashboardRegion region;
817         region.label = "";
818         region.offset.m_top  = Length();
819         region.offset.m_right = Length();
820         region.offset.m_bottom = Length();
821         region.offset.m_left = Length();
822         region.type = StyleDashboardRegion::None;
823         noneList.append(region);
824         noneListInitialized = true;
825     }
826     return noneList;
827 }
828 #endif
829
830 void RenderStyle::adjustAnimations()
831 {
832     AnimationList* animationList = rareNonInheritedData->m_animations.get();
833     if (!animationList)
834         return;
835
836     // Get rid of empty animations and anything beyond them
837     for (size_t i = 0; i < animationList->size(); ++i) {
838         if (animationList->animation(i)->isEmpty()) {
839             animationList->resize(i);
840             break;
841         }
842     }
843
844     if (animationList->isEmpty()) {
845         clearAnimations();
846         return;
847     }
848
849     // Repeat patterns into layers that don't have some properties set.
850     animationList->fillUnsetProperties();
851 }
852
853 void RenderStyle::adjustTransitions()
854 {
855     AnimationList* transitionList = rareNonInheritedData->m_transitions.get();
856     if (!transitionList)
857         return;
858
859     // Get rid of empty transitions and anything beyond them
860     for (size_t i = 0; i < transitionList->size(); ++i) {
861         if (transitionList->animation(i)->isEmpty()) {
862             transitionList->resize(i);
863             break;
864         }
865     }
866
867     if (transitionList->isEmpty()) {
868         clearTransitions();
869         return;
870     }
871
872     // Repeat patterns into layers that don't have some properties set.
873     transitionList->fillUnsetProperties();
874
875     // Make sure there are no duplicate properties. This is an O(n^2) algorithm
876     // but the lists tend to be very short, so it is probably ok
877     for (size_t i = 0; i < transitionList->size(); ++i) {
878         for (size_t j = i+1; j < transitionList->size(); ++j) {
879             if (transitionList->animation(i)->property() == transitionList->animation(j)->property()) {
880                 // toss i
881                 transitionList->remove(i);
882                 j = i;
883             }
884         }
885     }
886 }
887
888 AnimationList* RenderStyle::accessAnimations()
889 {
890     if (!rareNonInheritedData.access()->m_animations)
891         rareNonInheritedData.access()->m_animations.set(new AnimationList());
892     return rareNonInheritedData->m_animations.get();
893 }
894
895 AnimationList* RenderStyle::accessTransitions()
896 {
897     if (!rareNonInheritedData.access()->m_transitions)
898         rareNonInheritedData.access()->m_transitions.set(new AnimationList());
899     return rareNonInheritedData->m_transitions.get();
900 }
901
902 const Animation* RenderStyle::transitionForProperty(int property) const
903 {
904     if (transitions()) {
905         for (size_t i = 0; i < transitions()->size(); ++i) {
906             const Animation* p = transitions()->animation(i);
907             if (p->property() == cAnimateAll || p->property() == property) {
908                 return p;
909             }
910         }
911     }
912     return 0;
913 }
914
915 void RenderStyle::setBlendedFontSize(int size)
916 {
917     FontSelector* currentFontSelector = font().fontSelector();
918     FontDescription desc(fontDescription());
919     desc.setSpecifiedSize(size);
920     desc.setComputedSize(size);
921     setFontDescription(desc);
922     font().update(currentFontSelector);
923 }
924
925 void RenderStyle::getBoxShadowExtent(int &top, int &right, int &bottom, int &left) const
926 {
927     top = 0;
928     right = 0;
929     bottom = 0;
930     left = 0;
931
932     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
933         if (boxShadow->style() == Inset)
934             continue;
935         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
936
937         top = min(top, boxShadow->y() - blurAndSpread);
938         right = max(right, boxShadow->x() + blurAndSpread);
939         bottom = max(bottom, boxShadow->y() + blurAndSpread);
940         left = min(left, boxShadow->x() - blurAndSpread);
941     }
942 }
943
944 void RenderStyle::getBoxShadowHorizontalExtent(int &left, int &right) const
945 {
946     left = 0;
947     right = 0;
948
949     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
950         if (boxShadow->style() == Inset)
951             continue;
952         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
953
954         left = min(left, boxShadow->x() - blurAndSpread);
955         right = max(right, boxShadow->x() + blurAndSpread);
956     }
957 }
958
959 void RenderStyle::getBoxShadowVerticalExtent(int &top, int &bottom) const
960 {
961     top = 0;
962     bottom = 0;
963
964     for (const ShadowData* boxShadow = this->boxShadow(); boxShadow; boxShadow = boxShadow->next()) {
965         if (boxShadow->style() == Inset)
966             continue;
967         int blurAndSpread = boxShadow->blur() + boxShadow->spread();
968
969         top = min(top, boxShadow->y() - blurAndSpread);
970         bottom = max(bottom, boxShadow->y() + blurAndSpread);
971     }
972 }
973
974 static EBorderStyle borderStyleForColorProperty(const RenderStyle* style, int colorProperty)
975 {
976     EBorderStyle borderStyle;
977     switch (colorProperty) {
978     case CSSPropertyBorderLeftColor:
979         borderStyle = style->borderLeftStyle();
980         break;
981     case CSSPropertyBorderRightColor:
982         borderStyle = style->borderRightStyle();
983         break;
984     case CSSPropertyBorderTopColor:
985         borderStyle = style->borderTopStyle();
986         break;
987     case CSSPropertyBorderBottomColor:
988         borderStyle = style->borderBottomStyle();
989         break;
990     default:
991         borderStyle = BNONE;
992         break;
993     }
994     return borderStyle;
995 }
996
997 const Color RenderStyle::colorIncludingFallback(int colorProperty, EBorderStyle borderStyle) const
998 {
999     Color result;
1000     switch (colorProperty) {
1001     case CSSPropertyBackgroundColor:
1002         return backgroundColor(); // Background color doesn't fall back.
1003     case CSSPropertyBorderLeftColor:
1004         result = borderLeftColor();
1005         borderStyle = borderLeftStyle();
1006         break;
1007     case CSSPropertyBorderRightColor:
1008         result = borderRightColor();
1009         borderStyle = borderRightStyle();
1010         break;
1011     case CSSPropertyBorderTopColor:
1012         result = borderTopColor();
1013         borderStyle = borderTopStyle();
1014         break;
1015     case CSSPropertyBorderBottomColor:
1016         result = borderBottomColor();
1017         borderStyle = borderBottomStyle();
1018         break;
1019     case CSSPropertyColor:
1020         result = color();
1021         break;
1022     case CSSPropertyOutlineColor:
1023         result = outlineColor();
1024         break;
1025     case CSSPropertyWebkitColumnRuleColor:
1026         result = columnRuleColor();
1027         break;
1028     case CSSPropertyWebkitTextFillColor:
1029         result = textFillColor();
1030         break;
1031     case CSSPropertyWebkitTextStrokeColor:
1032         result = textStrokeColor();
1033         break;
1034     default:
1035         ASSERT_NOT_REACHED();
1036         break;
1037     }
1038
1039     if (!result.isValid()) {
1040         if ((colorProperty == CSSPropertyBorderLeftColor || colorProperty == CSSPropertyBorderRightColor
1041             || colorProperty == CSSPropertyBorderTopColor || colorProperty == CSSPropertyBorderBottomColor)
1042             && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
1043             result.setRGB(238, 238, 238);
1044         else
1045             result = color();
1046     }
1047
1048     return result;
1049 }
1050
1051 const Color RenderStyle::visitedDependentColor(int colorProperty) const
1052 {
1053     EBorderStyle borderStyle = borderStyleForColorProperty(this, colorProperty);
1054     Color unvisitedColor = colorIncludingFallback(colorProperty, borderStyle);
1055     if (insideLink() != InsideVisitedLink)
1056         return unvisitedColor;
1057
1058     RenderStyle* visitedStyle = getCachedPseudoStyle(VISITED_LINK);
1059     if (!visitedStyle)
1060         return unvisitedColor;
1061     Color visitedColor = visitedStyle->colorIncludingFallback(colorProperty, borderStyle);
1062
1063     // Take the alpha from the unvisited color, but get the RGB values from the visited color.
1064     return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
1065 }
1066
1067 Length RenderStyle::logicalWidth() const
1068 {
1069     if (isVerticalBlockFlow())
1070         return width();
1071     return height();
1072 }
1073
1074 Length RenderStyle::logicalHeight() const
1075 {
1076     if (isVerticalBlockFlow())
1077         return height();
1078     return width();
1079 }
1080
1081 Length RenderStyle::logicalMinWidth() const
1082 {
1083     if (isVerticalBlockFlow())
1084         return minWidth();
1085     return minHeight();
1086 }
1087
1088 Length RenderStyle::logicalMaxWidth() const
1089 {
1090     if (isVerticalBlockFlow())
1091         return maxWidth();
1092     return maxHeight();
1093 }
1094
1095 Length RenderStyle::logicalMinHeight() const
1096 {
1097     if (isVerticalBlockFlow())
1098         return minHeight();
1099     return minWidth();
1100 }
1101
1102 Length RenderStyle::logicalMaxHeight() const
1103 {
1104     if (isVerticalBlockFlow())
1105         return maxHeight();
1106     return maxWidth();
1107 }
1108
1109 unsigned short RenderStyle::borderBeforeWidth() const
1110 {
1111     switch (blockFlow()) {
1112     case TopToBottomBlockFlow:
1113         return borderTopWidth();
1114     case BottomToTopBlockFlow:
1115         return borderBottomWidth();
1116     case LeftToRightBlockFlow:
1117         return borderLeftWidth();
1118     case RightToLeftBlockFlow:
1119         return borderRightWidth();
1120     }
1121     ASSERT_NOT_REACHED();
1122     return borderTopWidth();
1123 }
1124
1125 unsigned short RenderStyle::borderAfterWidth() const
1126 {
1127     switch (blockFlow()) {
1128     case TopToBottomBlockFlow:
1129         return borderBottomWidth();
1130     case BottomToTopBlockFlow:
1131         return borderTopWidth();
1132     case LeftToRightBlockFlow:
1133         return borderRightWidth();
1134     case RightToLeftBlockFlow:
1135         return borderLeftWidth();
1136     }
1137     ASSERT_NOT_REACHED();
1138     return borderBottomWidth();
1139 }
1140
1141 unsigned short RenderStyle::borderStartWidth() const
1142 {
1143     if (isVerticalBlockFlow())
1144         return direction() == LTR ? borderLeftWidth() : borderRightWidth();
1145     return direction() == LTR ? borderTopWidth() : borderBottomWidth();
1146 }
1147
1148 unsigned short RenderStyle::borderEndWidth() const
1149 {
1150     if (isVerticalBlockFlow())
1151         return direction() == LTR ? borderRightWidth() : borderLeftWidth();
1152     return direction() == LTR ? borderBottomWidth() : borderTopWidth();
1153 }
1154     
1155 Length RenderStyle::marginBefore() const
1156 {
1157     switch (blockFlow()) {
1158     case TopToBottomBlockFlow:
1159         return marginTop();
1160     case BottomToTopBlockFlow:
1161         return marginBottom();
1162     case LeftToRightBlockFlow:
1163         return marginLeft();
1164     case RightToLeftBlockFlow:
1165         return marginRight();
1166     }
1167     ASSERT_NOT_REACHED();
1168     return marginTop();
1169 }
1170
1171 Length RenderStyle::marginAfter() const
1172 {
1173     switch (blockFlow()) {
1174     case TopToBottomBlockFlow:
1175         return marginBottom();
1176     case BottomToTopBlockFlow:
1177         return marginTop();
1178     case LeftToRightBlockFlow:
1179         return marginRight();
1180     case RightToLeftBlockFlow:
1181         return marginLeft();
1182     }
1183     ASSERT_NOT_REACHED();
1184     return marginBottom();
1185 }
1186
1187 Length RenderStyle::marginStart() const
1188 {
1189     if (isVerticalBlockFlow())
1190         return direction() == LTR ? marginLeft() : marginRight();
1191     return direction() == LTR ? marginTop() : marginBottom();
1192 }
1193
1194 Length RenderStyle::marginEnd() const
1195 {
1196     if (isVerticalBlockFlow())
1197         return direction() == LTR ? marginRight() : marginLeft();
1198     return direction() == LTR ? marginBottom() : marginTop();
1199 }
1200     
1201 Length RenderStyle::paddingBefore() const
1202 {
1203     switch (blockFlow()) {
1204     case TopToBottomBlockFlow:
1205         return paddingTop();
1206     case BottomToTopBlockFlow:
1207         return paddingBottom();
1208     case LeftToRightBlockFlow:
1209         return paddingLeft();
1210     case RightToLeftBlockFlow:
1211         return paddingRight();
1212     }
1213     ASSERT_NOT_REACHED();
1214     return paddingTop();
1215 }
1216
1217 Length RenderStyle::paddingAfter() const
1218 {
1219     switch (blockFlow()) {
1220     case TopToBottomBlockFlow:
1221         return paddingBottom();
1222     case BottomToTopBlockFlow:
1223         return paddingTop();
1224     case LeftToRightBlockFlow:
1225         return paddingRight();
1226     case RightToLeftBlockFlow:
1227         return paddingLeft();
1228     }
1229     ASSERT_NOT_REACHED();
1230     return paddingBottom();
1231 }
1232
1233 Length RenderStyle::paddingStart() const
1234 {
1235     if (isVerticalBlockFlow())
1236         return direction() == LTR ? paddingLeft() : paddingRight();
1237     return direction() == LTR ? paddingTop() : paddingBottom();
1238 }
1239
1240 Length RenderStyle::paddingEnd() const
1241 {
1242     if (isVerticalBlockFlow())
1243         return direction() == LTR ? paddingRight() : paddingLeft();
1244     return direction() == LTR ? paddingBottom() : paddingTop();
1245 }
1246
1247 } // namespace WebCore