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