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