422c5ba9819e33c990f208e5784656e29d136c3e
[WebKit-https.git] / WebCore / khtml / rendering / render_style.cpp
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
5  * Copyright (C) 2003 Apple Computer, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB.  If not, write to
19  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  *
22  */
23
24 #include "xml/dom_stringimpl.h"
25
26 #include "render_style.h"
27 #include "css/cssstyleselector.h"
28 #include "render_arena.h"
29
30 #include "kdebug.h"
31
32 using namespace khtml;
33
34 using DOM::DOMStringImpl;
35 using DOM::DOMString;
36
37 StyleSurroundData::StyleSurroundData()
38     : margin( Fixed ), padding( Variable )
39 {
40 }
41
42 StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
43     : Shared<StyleSurroundData>(),
44       offset( o.offset ), margin( o.margin ), padding( o.padding ),
45       border( o.border )
46 {
47 }
48
49 bool StyleSurroundData::operator==(const StyleSurroundData& o) const
50 {
51     return offset==o.offset && margin==o.margin &&
52         padding==o.padding && border==o.border;
53 }
54
55 StyleBoxData::StyleBoxData()
56     : z_index( 0 ), z_auto(true)
57 {
58     // Initialize our min/max widths/heights.
59     min_width = min_height = RenderStyle::initialMinSize();
60     max_width = max_height = RenderStyle::initialMaxSize();
61 }
62
63 StyleBoxData::StyleBoxData(const StyleBoxData& o )
64     : Shared<StyleBoxData>(),
65       width( o.width ), height( o.height ),
66       min_width( o.min_width ), max_width( o.max_width ),
67       min_height ( o.min_height ), max_height( o.max_height ),
68       z_index( o.z_index ), z_auto( o.z_auto )
69 {
70 }
71
72 bool StyleBoxData::operator==(const StyleBoxData& o) const
73 {
74     return
75             width == o.width &&
76             height == o.height &&
77             min_width == o.min_width &&
78             max_width == o.max_width &&
79             min_height == o.min_height &&
80             max_height == o.max_height &&
81             z_index == o.z_index &&
82         z_auto == o.z_auto;
83 }
84
85
86 StyleVisualData::StyleVisualData()
87       : hasClip(false), 
88       textDecoration(RenderStyle::initialTextDecoration()), 
89       colspan( 1 ), counter_increment( 0 ), counter_reset( 0 ),
90       palette( QApplication::palette() )
91 {
92 }
93
94 StyleVisualData::~StyleVisualData() {
95 }
96
97 StyleVisualData::StyleVisualData(const StyleVisualData& o )
98     : Shared<StyleVisualData>(),
99       clip( o.clip ), hasClip( o.hasClip ), textDecoration(o.textDecoration), colspan( o.colspan ),
100       counter_increment( o.counter_increment ), counter_reset( o.counter_reset ),
101       palette( o.palette )
102 {
103 }
104
105
106
107 StyleBackgroundData::StyleBackgroundData()
108     : image( RenderStyle::initialBackgroundImage() )
109 {
110 }
111
112 StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o )
113     : Shared<StyleBackgroundData>(),
114       color( o.color ), image( o.image ),
115       x_position( o.x_position ), y_position( o.y_position ),
116       outline( o.outline )
117 {
118 }
119
120 bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
121 {
122     return
123         color == o.color &&
124         image == o.image &&
125         x_position == o.x_position &&
126         y_position == o.y_position &&
127         outline == o.outline;
128 }
129
130 StyleMarqueeData::StyleMarqueeData()
131 {
132     increment = RenderStyle::initialMarqueeIncrement();
133     speed = RenderStyle::initialMarqueeSpeed();
134     direction = RenderStyle::initialMarqueeDirection();
135     behavior = RenderStyle::initialMarqueeBehavior();
136     loops = RenderStyle::initialMarqueeLoopCount();
137 }
138
139 StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
140 :Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
141  behavior(o.behavior), direction(o.direction) 
142 {}
143
144 bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
145 {
146     return (increment == o.increment && speed == o.speed && direction == o.direction &&
147             behavior == o.behavior && loops == o.loops);
148 }
149
150 StyleFlexibleBoxData::StyleFlexibleBoxData()
151 : Shared<StyleFlexibleBoxData>()
152 {
153     flex = RenderStyle::initialBoxFlex();
154     flex_group = RenderStyle::initialBoxFlexGroup();
155     ordinal_group = RenderStyle::initialBoxOrdinalGroup();
156     align = RenderStyle::initialBoxAlign();
157     pack = RenderStyle::initialBoxPack();
158     orient = RenderStyle::initialBoxOrient();
159     lines = RenderStyle::initialBoxLines();
160 }
161
162 StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o)
163 : Shared<StyleFlexibleBoxData>()
164 {
165     flex = o.flex;
166     flex_group = o.flex_group;
167     ordinal_group = o.ordinal_group;
168     align = o.align;
169     pack = o.pack;
170     orient = o.orient;
171     lines = o.lines;
172 }
173
174 bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
175 {
176     return flex == o.flex && flex_group == o.flex_group &&
177            ordinal_group == o.ordinal_group && align == o.align &&
178            pack == o.pack && orient == o.orient && lines == o.lines;
179 }
180
181 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
182 :Shared<StyleCSS3NonInheritedData>(), 
183 #if APPLE_CHANGES
184 lineClamp(RenderStyle::initialLineClamp()),
185 #endif
186 opacity(RenderStyle::initialOpacity()),
187 userDrag(RenderStyle::initialUserDrag()),
188 userSelect(RenderStyle::initialUserSelect()),
189 textOverflow(RenderStyle::initialTextOverflow()),
190 marginTopCollapse(MCOLLAPSE),
191 marginBottomCollapse(MCOLLAPSE)
192 #ifndef KHTML_NO_XBL
193 , bindingURI(0)
194 #endif
195 {
196 }
197
198 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
199 :Shared<StyleCSS3NonInheritedData>(), 
200 #if APPLE_CHANGES
201 lineClamp(o.lineClamp),
202 #endif
203 opacity(o.opacity), flexibleBox(o.flexibleBox), marquee(o.marquee),
204 userDrag(o.userDrag), userSelect(o.userSelect), textOverflow(o.textOverflow),
205 marginTopCollapse(o.marginTopCollapse), marginBottomCollapse(o.marginBottomCollapse)
206 {
207 #ifndef KHTML_NO_XBL
208     bindingURI = o.bindingURI ? o.bindingURI->copy() : 0;
209 #endif
210 }
211
212 StyleCSS3NonInheritedData::~StyleCSS3NonInheritedData()
213 {
214 #ifndef KHTML_NO_XBL
215     delete bindingURI;
216 #endif
217 }
218
219 #ifndef KHTML_NO_XBL
220 bool StyleCSS3NonInheritedData::bindingsEquivalent(const StyleCSS3NonInheritedData& o) const
221 {
222     if (this == &o) return true;
223     if (!bindingURI && o.bindingURI || bindingURI && !o.bindingURI)
224         return false;
225     if (bindingURI && o.bindingURI && (*bindingURI != *o.bindingURI))
226         return false;
227     return true;
228 }
229 #endif
230
231 bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
232 {
233     return opacity == o.opacity && flexibleBox == o.flexibleBox && marquee == o.marquee &&
234            userDrag == o.userDrag && userSelect == o.userSelect && textOverflow == o.textOverflow &&
235            marginTopCollapse == o.marginTopCollapse && marginBottomCollapse == o.marginBottomCollapse
236 #ifndef KHTML_NO_XBL
237            && bindingsEquivalent(o)
238 #endif
239 #if APPLE_CHANGES
240            && lineClamp == o.lineClamp
241 #endif
242     ;
243 }
244
245 StyleCSS3InheritedData::StyleCSS3InheritedData()
246 :Shared<StyleCSS3InheritedData>(), textShadow(0), userModify(READ_ONLY), wordWrap(WBNORMAL)
247 #if APPLE_CHANGES
248 , textSizeAdjust(RenderStyle::initialTextSizeAdjust())
249 #endif
250 {
251
252 }
253
254 StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
255 :Shared<StyleCSS3InheritedData>()
256 {
257     textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
258     userModify = o.userModify;
259     wordWrap = o.wordWrap;
260 #if APPLE_CHANGES
261     textSizeAdjust = o.textSizeAdjust;
262 #endif
263 }
264
265 StyleCSS3InheritedData::~StyleCSS3InheritedData()
266 {
267     delete textShadow;
268 }
269
270 bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
271 {
272     return (userModify == o.userModify) && shadowDataEquivalent(o) && (wordWrap == o.wordWrap) 
273 #if APPLE_CHANGES
274             && (textSizeAdjust == o.textSizeAdjust)
275 #endif
276     ;
277 }
278
279 bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
280 {
281     if (!textShadow && o.textShadow || textShadow && !o.textShadow)
282         return false;
283     if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
284         return false;
285     return true;
286 }
287
288 StyleInheritedData::StyleInheritedData()
289     : indent( RenderStyle::initialTextIndent() ), line_height( RenderStyle::initialLineHeight() ), 
290       style_image( RenderStyle::initialListStyleImage() ),
291       cursor_image( 0 ), font(), color( RenderStyle::initialColor() ), 
292       horizontal_border_spacing( RenderStyle::initialHorizontalBorderSpacing() ), 
293       vertical_border_spacing( RenderStyle::initialVerticalBorderSpacing() ),
294       widows( RenderStyle::initialWidows() ), orphans( RenderStyle::initialOrphans() ),
295       page_break_inside( RenderStyle::initialPageBreak() )
296 {
297 }
298
299 StyleInheritedData::~StyleInheritedData()
300 {
301 }
302
303 StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
304     : Shared<StyleInheritedData>(),
305       indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
306       cursor_image( o.cursor_image ), font( o.font ),
307       color( o.color ),
308       horizontal_border_spacing( o.horizontal_border_spacing ),
309       vertical_border_spacing( o.vertical_border_spacing ),
310       widows(o.widows), orphans(o.orphans), page_break_inside(o.page_break_inside)
311 {
312 }
313
314 bool StyleInheritedData::operator==(const StyleInheritedData& o) const
315 {
316     return
317         indent == o.indent &&
318         line_height == o.line_height &&
319         style_image == o.style_image &&
320         cursor_image == o.cursor_image &&
321         font == o.font &&
322         color == o.color &&
323         horizontal_border_spacing == o.horizontal_border_spacing &&
324         vertical_border_spacing == o.vertical_border_spacing &&
325         widows == o.widows &&
326         orphans == o.orphans &&
327         page_break_inside == o.page_break_inside;
328 }
329
330 // ----------------------------------------------------------
331
332 void* RenderStyle::operator new(size_t sz, RenderArena* renderArena) throw()
333 {
334     return renderArena->allocate(sz);
335 }
336
337 void RenderStyle::operator delete(void* ptr, size_t sz)
338 {
339     // Stash size where detach can find it.
340     *(size_t *)ptr = sz;
341 }
342
343 void RenderStyle::arenaDelete(RenderArena *arena)
344 {
345     RenderStyle *ps = pseudoStyle;
346     RenderStyle *prev = 0;
347     
348     while (ps) {
349         prev = ps;
350         ps = ps->pseudoStyle;
351         // to prevent a double deletion.
352         // this works only because the styles below aren't really shared
353         // Dirk said we need another construct as soon as these are shared
354         prev->pseudoStyle = 0;
355         prev->deref(arena);
356     }
357     delete content;
358     
359     delete this;
360     
361     // Recover the size left there for us by operator delete and free the memory.
362     arena->free(*(size_t *)this, this);
363 }
364
365 RenderStyle::RenderStyle()
366 :m_pseudoState(PseudoUnknown), m_affectedByAttributeSelectors(false)
367 {
368     m_ref = 0;
369     
370     if (!_default)
371         _default = ::new RenderStyle(true);
372
373     box = _default->box;
374     visual = _default->visual;
375     background = _default->background;
376     surround = _default->surround;
377     css3NonInheritedData = _default->css3NonInheritedData;
378     css3InheritedData = _default->css3InheritedData;
379     
380     inherited = _default->inherited;
381
382     setBitDefaults();
383
384     pseudoStyle = 0;
385     content = 0;
386 }
387
388 RenderStyle::RenderStyle(bool)
389 :m_pseudoState(PseudoUnknown), m_affectedByAttributeSelectors(false)
390 {
391     setBitDefaults();
392
393     box.init();
394     visual.init();
395     background.init();
396     surround.init();
397     css3NonInheritedData.init();
398     css3NonInheritedData.access()->flexibleBox.init();
399     css3NonInheritedData.access()->marquee.init();
400     css3InheritedData.init();
401     inherited.init();
402
403     pseudoStyle = 0;
404     content = 0;
405     m_ref = 1;
406 }
407
408 RenderStyle::RenderStyle(const RenderStyle& o)
409     : inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
410       box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ),
411       css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
412       inherited( o.inherited ), pseudoStyle( 0 ), content( o.content ), m_pseudoState(o.m_pseudoState),
413       m_affectedByAttributeSelectors(false)
414 {
415     m_ref = 0;
416 }
417
418 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
419 {
420     css3InheritedData = inheritParent->css3InheritedData;
421     inherited = inheritParent->inherited;
422     inherited_flags = inheritParent->inherited_flags;
423 }
424
425 RenderStyle::~RenderStyle()
426 {
427 }
428
429 bool RenderStyle::operator==(const RenderStyle& o) const
430 {
431 // compare everything except the pseudoStyle pointer
432     return (inherited_flags == o.inherited_flags &&
433             noninherited_flags == o.noninherited_flags &&
434             box == o.box &&
435             visual == o.visual &&
436             background == o.background &&
437             surround == o.surround &&
438             css3NonInheritedData == o.css3NonInheritedData &&
439             css3InheritedData == o.css3InheritedData &&
440             inherited == o.inherited);
441 }
442
443 bool RenderStyle::isStyleAvailable() const
444 {
445     return this != CSSStyleSelector::styleNotYetAvailable;
446 }
447
448 enum EPseudoBit { NO_BIT = 0x0, BEFORE_BIT = 0x1, AFTER_BIT = 0x2, FIRST_LINE_BIT = 0x4,
449                   FIRST_LETTER_BIT = 0x8, SELECTION_BIT = 0x10, FIRST_LINE_INHERITED_BIT = 0x20 };
450
451 static int pseudoBit(RenderStyle::PseudoId pseudo)
452 {
453     switch (pseudo) {
454         case RenderStyle::BEFORE:
455             return BEFORE_BIT;
456         case RenderStyle::AFTER:
457             return AFTER_BIT;
458         case RenderStyle::FIRST_LINE:
459             return FIRST_LINE_BIT;
460         case RenderStyle::FIRST_LETTER:
461             return FIRST_LETTER_BIT;
462         case RenderStyle::SELECTION:
463             return SELECTION_BIT;
464         case RenderStyle::FIRST_LINE_INHERITED:
465             return FIRST_LINE_INHERITED_BIT;
466         default:
467             return NO_BIT;
468     }
469 }
470
471 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
472 {
473     return (pseudoBit(pseudo) & noninherited_flags._pseudoBits) != 0;
474 }
475
476 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
477 {
478     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
479 }
480
481 RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid)
482 {
483     RenderStyle *ps = 0;
484     if (noninherited_flags._styleType==NOPSEUDO) {
485         ps = pseudoStyle;
486         while (ps) {
487             if (ps->noninherited_flags._styleType==pid)
488                     break;
489     
490             ps = ps->pseudoStyle;
491         }
492     }
493     return ps;
494 }
495
496 void RenderStyle::addPseudoStyle(RenderStyle* pseudo)
497 {
498     if (!pseudo) return;
499     
500     pseudo->ref();
501     pseudo->pseudoStyle = pseudoStyle;
502     pseudoStyle = pseudo;
503 }
504
505 bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
506 {
507     return inherited_flags != other->inherited_flags ||
508            inherited != other->inherited ||
509            css3InheritedData != other->css3InheritedData;
510 }
511
512 /*
513   compares two styles. The result gives an idea of the action that
514   needs to be taken when replacing the old style with a new one.
515
516   CbLayout: The containing block of the object needs a relayout.
517   Layout: the RenderObject needs a relayout after the style change
518   Visible: The change is visible, but no relayout is needed
519   NonVisible: The object does need neither repaint nor relayout after
520        the change.
521
522   ### TODO:
523   A lot can be optimised here based on the display type, lots of
524   optimisations are unimplemented, and currently result in the
525   worst case result causing a relayout of the containing block.
526 */
527 RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
528 {
529     // we anyway assume they are the same
530 //      EDisplay _effectiveDisplay : 5;
531
532     // NonVisible:
533 //      ECursor _cursor_style : 4;
534
535 // ### this needs work to know more exactly if we need a relayout
536 //     or just a repaint
537
538 // non-inherited attributes
539 //     DataRef<StyleBoxData> box;
540 //     DataRef<StyleVisualData> visual;
541 //     DataRef<StyleSurroundData> surround;
542
543 // inherited attributes
544 //     DataRef<StyleInheritedData> inherited;
545
546     if ( box->width != other->box->width ||
547          box->min_width != other->box->min_width ||
548          box->max_width != other->box->max_width ||
549          box->height != other->box->height ||
550          box->min_height != other->box->min_height ||
551          box->max_height != other->box->max_height ||
552          box->vertical_align != other->box->vertical_align ||
553          !(surround->margin == other->surround->margin) ||
554          !(surround->padding == other->surround->padding) ||
555          css3NonInheritedData->marginTopCollapse != other->css3NonInheritedData->marginTopCollapse ||
556          css3NonInheritedData->marginBottomCollapse != other->css3NonInheritedData->marginBottomCollapse ||
557          *css3NonInheritedData->flexibleBox.get() != *other->css3NonInheritedData->flexibleBox.get() ||
558 #if APPLE_CHANGES
559          (css3NonInheritedData->lineClamp != other->css3NonInheritedData->lineClamp) ||
560          (css3InheritedData->textSizeAdjust != other->css3InheritedData->textSizeAdjust) ||
561 #endif
562          (css3InheritedData->wordWrap != other->css3InheritedData->wordWrap) ||
563         !(inherited->indent == other->inherited->indent) ||
564         !(inherited->line_height == other->inherited->line_height) ||
565         !(inherited->style_image == other->inherited->style_image) ||
566         !(inherited->cursor_image == other->inherited->cursor_image) ||
567         !(inherited->font == other->inherited->font) ||
568         !(inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing) ||
569         !(inherited->vertical_border_spacing == other->inherited->vertical_border_spacing) ||
570         !(inherited_flags._box_direction == other->inherited_flags._box_direction) ||
571         !(inherited_flags._visuallyOrdered == other->inherited_flags._visuallyOrdered) ||
572         !(inherited_flags._htmlHacks == other->inherited_flags._htmlHacks) ||
573         !(noninherited_flags._position == other->noninherited_flags._position) ||
574         !(noninherited_flags._floating == other->noninherited_flags._floating) ||
575         !(noninherited_flags._originalDisplay == other->noninherited_flags._originalDisplay) ||
576          visual->colspan != other->visual->colspan ||
577          visual->counter_increment != other->visual->counter_increment ||
578          visual->counter_reset != other->visual->counter_reset ||
579          css3NonInheritedData->textOverflow != other->css3NonInheritedData->textOverflow)
580         return Layout;
581    
582     // changes causing Layout changes:
583
584 // only for tables:
585 //      _border_collapse
586 //      EEmptyCell _empty_cells : 2 ;
587 //      ECaptionSide _caption_side : 2;
588 //     ETableLayout _table_layout : 1;
589 //     EPosition _position : 2;
590 //     EFloat _floating : 2;
591     if ( ((int)noninherited_flags._effectiveDisplay) >= TABLE ) {
592         // Stupid gcc gives a compile error on
593         // a != other->b if a and b are bitflags. Using
594         // !(a== other->b) instead.
595         if ( !(inherited_flags._border_collapse == other->inherited_flags._border_collapse) ||
596              !(inherited_flags._empty_cells == other->inherited_flags._empty_cells) ||
597              !(inherited_flags._caption_side == other->inherited_flags._caption_side) ||
598              !(noninherited_flags._table_layout == other->noninherited_flags._table_layout))
599         return Layout;
600     }
601
602 // only for lists:
603 //      EListStyleType _list_style_type : 5 ;
604 //      EListStylePosition _list_style_position :1;
605     if (noninherited_flags._effectiveDisplay == LIST_ITEM ) {
606         if ( !(inherited_flags._list_style_type == other->inherited_flags._list_style_type) ||
607              !(inherited_flags._list_style_position == other->inherited_flags._list_style_position) )
608             return Layout;
609     }
610
611 // ### These could be better optimised
612 //      ETextAlign _text_align : 3;
613 //      ETextTransform _text_transform : 4;
614 //      EDirection _direction : 1;
615 //      EWhiteSpace _white_space : 2;
616 //      EFontVariant _font_variant : 1;
617 //     EClear _clear : 2;
618     if ( !(inherited_flags._text_align == other->inherited_flags._text_align) ||
619          !(inherited_flags._text_transform == other->inherited_flags._text_transform) ||
620          !(inherited_flags._direction == other->inherited_flags._direction) ||
621          !(inherited_flags._white_space == other->inherited_flags._white_space) ||
622          !(noninherited_flags._clear == other->noninherited_flags._clear)
623         )
624         return Layout;
625
626 // only for inline:
627 //     EVerticalAlign _vertical_align : 4;
628
629     if ( !(noninherited_flags._effectiveDisplay == INLINE) &&
630          !(noninherited_flags._vertical_align == other->noninherited_flags._vertical_align))
631         return Layout;
632
633     // If our border widths change, then we need to layout.  Other changes to borders
634     // only necessitate a repaint.
635     if (borderLeftWidth() != other->borderLeftWidth() ||
636         borderTopWidth() != other->borderTopWidth() ||
637         borderBottomWidth() != other->borderBottomWidth() ||
638         borderRightWidth() != other->borderRightWidth())
639         return Layout;
640
641 #if APPLE_CHANGES
642     // If regions change trigger a relayout to re-calc regions.
643     if (!(css3NonInheritedData->m_dashboardRegions == other->css3NonInheritedData->m_dashboardRegions))
644         return Layout;
645 #endif
646
647     // Make sure these left/top/right/bottom checks stay below all layout checks and above
648     // all visible checks.
649     if (other->position() != STATIC) {
650         if (!(surround->offset == other->surround->offset)) {
651             // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
652             // can stop doing a layout when relative positioned objects move.  In particular, we'll need
653             // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
654             //if (other->position() == RELATIVE)
655             //    return RepaintLayer;
656             //else
657                 return Layout;
658         }
659         else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
660                  !(visual->clip == other->visual->clip) || visual->hasClip != other->visual->hasClip)
661             return RepaintLayer;
662     }
663
664     if (css3NonInheritedData->opacity != other->css3NonInheritedData->opacity)
665         return RepaintLayer;
666
667     // Repaint:
668 //      EVisibility _visibility : 2;
669 //     EOverflow _overflow : 4 ;
670 //     EBackgroundRepeat _bg_repeat : 2;
671 //     bool _bg_attachment : 1;
672 //      int _text_decoration : 4;
673 //     DataRef<StyleBackgroundData> background;
674     if (inherited->color != other->inherited->color ||
675         !(inherited_flags._visibility == other->inherited_flags._visibility) ||
676         !(noninherited_flags._overflow == other->noninherited_flags._overflow) ||
677         !(noninherited_flags._bg_repeat == other->noninherited_flags._bg_repeat) ||
678         !(noninherited_flags._bg_attachment == other->noninherited_flags._bg_attachment) ||
679         !(inherited_flags._text_decorations == other->inherited_flags._text_decorations) ||
680         !(inherited_flags._should_correct_text_color == other->inherited_flags._should_correct_text_color) ||
681         !(surround->border == other->surround->border) ||
682         *background.get() != *other->background.get() ||
683         visual->textDecoration != other->visual->textDecoration ||
684         !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get()) ||
685         css3InheritedData->userModify != other->css3InheritedData->userModify ||
686         css3NonInheritedData->userSelect != other->css3NonInheritedData->userSelect ||
687         css3NonInheritedData->userDrag != other->css3NonInheritedData->userDrag ||
688         !(visual->palette == other->visual->palette)
689         )
690         return Repaint;
691
692     return Equal;
693 }
694
695
696 RenderStyle* RenderStyle::_default = 0;
697 //int RenderStyle::counter = 0;
698 //int SharedData::counter = 0;
699
700 void RenderStyle::cleanup()
701 {
702     delete _default;
703     _default = 0;
704 //    counter = 0;
705 //    SharedData::counter = 0;
706 }
707
708 void RenderStyle::setPaletteColor(QPalette::ColorGroup g, QColorGroup::ColorRole r, const QColor& c)
709 {
710     visual.access()->palette.setColor(g,r,c);
711 }
712
713 void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
714 {
715     StyleVisualData *data = visual.access();
716     data->clip.top = top;
717     data->clip.right = right;
718     data->clip.bottom = bottom;
719     data->clip.left = left;
720 }
721
722 bool RenderStyle::contentDataEquivalent(RenderStyle* otherStyle)
723 {
724     ContentData* c1 = content;
725     ContentData* c2 = otherStyle->content;
726
727     while (c1 && c2) {
728         if (c1->_contentType != c2->_contentType)
729             return false;
730         if (c1->_contentType == CONTENT_TEXT) {
731             DOMString c1Str(c1->_content.text);
732             DOMString c2Str(c2->_content.text);
733             if (c1Str != c2Str)
734                 return false;
735         }
736         else if (c1->_contentType == CONTENT_OBJECT) {
737             if (c1->_content.object != c2->_content.object)
738                 return false;
739         }
740
741         c1 = c1->_nextContent;
742         c2 = c2->_nextContent;
743     }
744
745     return !c1 && !c2;
746 }
747
748 void RenderStyle::setContent(CachedObject* o, bool add)
749 {
750     if (!o)
751         return; // The object is null. Nothing to do. Just bail.
752
753     ContentData* lastContent = content;
754     while (lastContent && lastContent->_nextContent)
755         lastContent = lastContent->_nextContent;
756
757     bool reuseContent = !add;
758     ContentData* newContentData = 0;
759     if (reuseContent && content) {
760         content->clearContent();
761         newContentData = content;
762     }
763     else
764         newContentData = new ContentData;
765
766     if (lastContent && !reuseContent)
767         lastContent->_nextContent = newContentData;
768     else
769         content = newContentData;
770
771     //    o->ref();
772     newContentData->_content.object = o;
773     newContentData->_contentType = CONTENT_OBJECT;
774 }
775
776 void RenderStyle::setContent(DOMStringImpl* s, bool add)
777 {
778     if (!s)
779         return; // The string is null. Nothing to do. Just bail.
780     
781     ContentData* lastContent = content;
782     while (lastContent && lastContent->_nextContent)
783         lastContent = lastContent->_nextContent;
784
785     bool reuseContent = !add;
786     if (add) {
787         if (!lastContent)
788             return; // Something's wrong.  We had no previous content, and we should have.
789
790         if (lastContent->_contentType == CONTENT_TEXT) {
791             // We can augment the existing string and share this ContentData node.
792             DOMStringImpl* oldStr = lastContent->_content.text;
793             DOMStringImpl* newStr = oldStr->copy();
794             newStr->ref();
795             oldStr->deref();
796             newStr->append(s);
797             lastContent->_content.text = newStr;
798             return;
799         }
800     }
801
802     ContentData* newContentData = 0;
803     if (reuseContent && content) {
804         content->clearContent();
805         newContentData = content;
806     }
807     else
808         newContentData = new ContentData;
809     
810     if (lastContent && !reuseContent)
811         lastContent->_nextContent = newContentData;
812     else
813         content = newContentData;
814     
815     newContentData->_content.text = s;
816     newContentData->_content.text->ref();
817     newContentData->_contentType = CONTENT_TEXT;
818 }
819
820 ContentData::~ContentData()
821 {
822     clearContent();
823 }
824
825 void ContentData::clearContent()
826 {
827     delete _nextContent;
828     _nextContent = 0;
829     
830     switch (_contentType)
831     {
832         case CONTENT_OBJECT:
833 //            _content.object->deref();
834             _content.object = 0;
835             break;
836         case CONTENT_TEXT:
837             _content.text->deref();
838             _content.text = 0;
839         default:
840             ;
841     }
842 }
843
844 #ifndef KHTML_NO_XBL
845 BindingURI::BindingURI(DOM::DOMStringImpl* uri) 
846 :m_next(0)
847
848     m_uri = uri;
849     if (uri) uri->ref();
850 }
851
852 BindingURI::~BindingURI()
853 {
854     if (m_uri)
855         m_uri->deref();
856     delete m_next;
857 }
858
859 BindingURI* BindingURI::copy()
860 {
861     BindingURI* newBinding = new BindingURI(m_uri);
862     if (next()) {
863         BindingURI* nextCopy = next()->copy();
864         newBinding->setNext(nextCopy);
865     }
866     
867     return newBinding;
868 }
869
870 bool BindingURI::operator==(const BindingURI& o) const
871 {
872     if ((m_next && !o.m_next) || (!m_next && o.m_next) ||
873         (m_next && o.m_next && *m_next != *o.m_next))
874         return false;
875     
876     if (m_uri == o.m_uri)
877         return true;
878     if (!m_uri || !o.m_uri)
879         return false;
880     
881     return DOMString(m_uri) == DOMString(o.m_uri);
882 }
883
884 void RenderStyle::addBindingURI(DOM::DOMStringImpl* uri)
885 {
886     BindingURI* binding = new BindingURI(uri);
887     if (!bindingURIs())
888         SET_VAR(css3NonInheritedData, bindingURI, binding)
889     else 
890         for (BindingURI* b = bindingURIs(); b; b = b->next()) {
891             if (!b->next())
892                 b->setNext(binding);
893         }
894 }
895 #endif
896
897 void RenderStyle::setTextShadow(ShadowData* val, bool add)
898 {
899     StyleCSS3InheritedData* css3Data = css3InheritedData.access(); 
900     if (!add) {
901         delete css3Data->textShadow;
902         css3Data->textShadow = val;
903         return;
904     }
905
906     ShadowData* last = css3Data->textShadow;
907     while (last->next) last = last->next;
908     last->next = val;
909 }
910
911 ShadowData::ShadowData(const ShadowData& o)
912 :x(o.x), y(o.y), blur(o.blur), color(o.color)
913 {
914     next = o.next ? new ShadowData(*o.next) : 0;
915 }
916
917 bool ShadowData::operator==(const ShadowData& o) const
918 {
919     if ((next && !o.next) || (!next && o.next) ||
920         (next && o.next && *next != *o.next))
921         return false;
922     
923     return x == o.x && y == o.y && blur == o.blur && color == o.color;
924 }