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