LayoutTests:
[WebKit-https.git] / WebCore / 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) 2004, 2005 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 "config.h"
25 #include "render_style.h"
26
27 #include "cssstyleselector.h"
28 #include "RenderArena.h"
29
30 namespace WebCore {
31
32 static RenderStyle* defaultStyle;
33
34 StyleSurroundData::StyleSurroundData()
35     : margin( Fixed ), padding( Auto )
36 {
37 }
38
39 StyleSurroundData::StyleSurroundData(const StyleSurroundData& o )
40     : Shared<StyleSurroundData>(),
41       offset( o.offset ), margin( o.margin ), padding( o.padding ),
42       border( o.border )
43 {
44 }
45
46 bool StyleSurroundData::operator==(const StyleSurroundData& o) const
47 {
48     return offset==o.offset && margin==o.margin &&
49         padding==o.padding && border==o.border;
50 }
51
52 StyleBoxData::StyleBoxData()
53     : z_index( 0 ), z_auto(true), boxSizing(CONTENT_BOX)
54 {
55     // Initialize our min/max widths/heights.
56     min_width = min_height = RenderStyle::initialMinSize();
57     max_width = max_height = RenderStyle::initialMaxSize();
58 }
59
60 StyleBoxData::StyleBoxData(const StyleBoxData& o )
61     : Shared<StyleBoxData>(),
62       width( o.width ), height( o.height ),
63       min_width( o.min_width ), max_width( o.max_width ),
64       min_height ( o.min_height ), max_height( o.max_height ),
65       z_index( o.z_index ), z_auto( o.z_auto ), boxSizing(o.boxSizing)
66 {
67 }
68
69 bool StyleBoxData::operator==(const StyleBoxData& o) const
70 {
71     return width == o.width &&
72            height == o.height &&
73            min_width == o.min_width &&
74            max_width == o.max_width &&
75            min_height == o.min_height &&
76            max_height == o.max_height &&
77            z_index == o.z_index &&
78            z_auto == o.z_auto &&
79            boxSizing == o.boxSizing;
80 }
81
82
83 StyleVisualData::StyleVisualData()
84       : hasClip(false), 
85       textDecoration(RenderStyle::initialTextDecoration()), 
86       colspan( 1 ), counter_increment( 0 ), counter_reset( 0 )
87 {
88 }
89
90 StyleVisualData::~StyleVisualData() {
91 }
92
93 StyleVisualData::StyleVisualData(const StyleVisualData& o )
94     : Shared<StyleVisualData>(),
95       clip( o.clip ), hasClip( o.hasClip ), textDecoration(o.textDecoration), colspan( o.colspan ),
96       counter_increment( o.counter_increment ), counter_reset( o.counter_reset )
97 {
98 }
99
100 BackgroundLayer::BackgroundLayer()
101 :m_image(RenderStyle::initialBackgroundImage()),
102  m_bgAttachment(RenderStyle::initialBackgroundAttachment()),
103  m_bgClip(RenderStyle::initialBackgroundClip()),
104  m_bgOrigin(RenderStyle::initialBackgroundOrigin()),
105  m_bgRepeat(RenderStyle::initialBackgroundRepeat()),
106  m_backgroundSize(RenderStyle::initialBackgroundSize()),
107  m_next(0)
108 {
109     m_imageSet = m_attachmentSet = m_clipSet = m_originSet = 
110             m_repeatSet = m_xPosSet = m_yPosSet = m_backgroundSizeSet = false;     
111 }
112
113 BackgroundLayer::BackgroundLayer(const BackgroundLayer& o)
114 {
115     m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
116     m_image = o.m_image;
117     m_xPosition = o.m_xPosition;
118     m_yPosition = o.m_yPosition;
119     m_bgAttachment = o.m_bgAttachment;
120     m_bgClip = o.m_bgClip;
121     m_bgOrigin = o.m_bgOrigin;
122     m_bgRepeat = o.m_bgRepeat;
123     m_backgroundSize = o.m_backgroundSize;
124     m_imageSet = o.m_imageSet;
125     m_attachmentSet = o.m_attachmentSet;
126     m_clipSet = o.m_clipSet;
127     m_originSet = o.m_originSet;
128     m_repeatSet = o.m_repeatSet;
129     m_xPosSet = o.m_xPosSet;
130     m_yPosSet = o.m_yPosSet;
131     m_backgroundSizeSet = o.m_backgroundSizeSet;
132 }
133
134 BackgroundLayer::~BackgroundLayer()
135 {
136     delete m_next;
137 }
138
139 BackgroundLayer& BackgroundLayer::operator=(const BackgroundLayer& o) {
140     if (m_next != o.m_next) {
141         delete m_next;
142         m_next = o.m_next ? new BackgroundLayer(*o.m_next) : 0;
143     }
144     
145     m_image = o.m_image;
146     m_xPosition = o.m_xPosition;
147     m_yPosition = o.m_yPosition;
148     m_bgAttachment = o.m_bgAttachment;
149     m_bgClip = o.m_bgClip;
150     m_bgOrigin = o.m_bgOrigin;
151     m_bgRepeat = o.m_bgRepeat;
152     m_backgroundSize = o.m_backgroundSize;
153     
154     m_imageSet = o.m_imageSet;
155     m_attachmentSet = o.m_attachmentSet;
156     m_clipSet = o.m_clipSet;
157     m_originSet = o.m_originSet;
158     m_repeatSet = o.m_repeatSet;
159     m_xPosSet = o.m_xPosSet;
160     m_yPosSet = o.m_yPosSet;
161     m_backgroundSizeSet = o.m_backgroundSizeSet;
162     
163     return *this;
164 }
165
166 bool BackgroundLayer::operator==(const BackgroundLayer& o) const {
167     return m_image == o.m_image && m_xPosition == o.m_xPosition && m_yPosition == o.m_yPosition &&
168            m_bgAttachment == o.m_bgAttachment && m_bgClip == o.m_bgClip && m_bgOrigin == o.m_bgOrigin && m_bgRepeat == o.m_bgRepeat &&
169            m_backgroundSize.width == o.m_backgroundSize.width && m_backgroundSize.height == o.m_backgroundSize.height && 
170            m_imageSet == o.m_imageSet && m_attachmentSet == o.m_attachmentSet && m_repeatSet == o.m_repeatSet && 
171            m_xPosSet == o.m_xPosSet && m_yPosSet == o.m_yPosSet && m_backgroundSizeSet == o.m_backgroundSizeSet && 
172            ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next);
173 }
174
175 void BackgroundLayer::fillUnsetProperties()
176 {
177     BackgroundLayer* curr;
178     for (curr = this; curr && curr->isBackgroundImageSet(); curr = curr->next());
179     if (curr && curr != this) {
180         // We need to fill in the remaining values with the pattern specified.
181         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
182             curr->m_image = pattern->m_image;
183             pattern = pattern->next();
184             if (pattern == curr || !pattern)
185                 pattern = this;
186         }
187     }
188     
189     for (curr = this; curr && curr->isBackgroundXPositionSet(); curr = curr->next());
190     if (curr && curr != this) {
191         // We need to fill in the remaining values with the pattern specified.
192         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
193             curr->m_xPosition = pattern->m_xPosition;
194             pattern = pattern->next();
195             if (pattern == curr || !pattern)
196                 pattern = this;
197         }
198     }
199     
200     for (curr = this; curr && curr->isBackgroundYPositionSet(); curr = curr->next());
201     if (curr && curr != this) {
202         // We need to fill in the remaining values with the pattern specified.
203         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
204             curr->m_yPosition = pattern->m_yPosition;
205             pattern = pattern->next();
206             if (pattern == curr || !pattern)
207                 pattern = this;
208         }
209     }
210     
211     for (curr = this; curr && curr->isBackgroundAttachmentSet(); curr = curr->next());
212     if (curr && curr != this) {
213         // We need to fill in the remaining values with the pattern specified.
214         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
215             curr->m_bgAttachment = pattern->m_bgAttachment;
216             pattern = pattern->next();
217             if (pattern == curr || !pattern)
218                 pattern = this;
219         }
220     }
221     
222     for (curr = this; curr && curr->isBackgroundClipSet(); curr = curr->next());
223     if (curr && curr != this) {
224         // We need to fill in the remaining values with the pattern specified.
225         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
226             curr->m_bgClip = pattern->m_bgClip;
227             pattern = pattern->next();
228             if (pattern == curr || !pattern)
229                 pattern = this;
230         }
231     }
232
233     for (curr = this; curr && curr->isBackgroundOriginSet(); curr = curr->next());
234     if (curr && curr != this) {
235         // We need to fill in the remaining values with the pattern specified.
236         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
237             curr->m_bgOrigin = pattern->m_bgOrigin;
238             pattern = pattern->next();
239             if (pattern == curr || !pattern)
240                 pattern = this;
241         }
242     }
243
244     for (curr = this; curr && curr->isBackgroundRepeatSet(); curr = curr->next());
245     if (curr && curr != this) {
246         // We need to fill in the remaining values with the pattern specified.
247         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
248             curr->m_bgRepeat = pattern->m_bgRepeat;
249             pattern = pattern->next();
250             if (pattern == curr || !pattern)
251                 pattern = this;
252         }
253     }
254     
255     for (curr = this; curr && curr->isBackgroundSizeSet(); curr = curr->next());
256     if (curr && curr != this) {
257         // We need to fill in the remaining values with the pattern specified.
258         for (BackgroundLayer* pattern = this; curr; curr = curr->next()) {
259             curr->m_backgroundSize = pattern->m_backgroundSize;
260             pattern = pattern->next();
261             if (pattern == curr || !pattern)
262                 pattern = this;
263         }
264     }
265 }
266
267 void BackgroundLayer::cullEmptyLayers()
268 {
269     BackgroundLayer *next;
270     for (BackgroundLayer *p = this; p; p = next) {
271         next = p->m_next;
272         if (next && !next->isBackgroundImageSet() &&
273             !next->isBackgroundXPositionSet() && !next->isBackgroundYPositionSet() &&
274             !next->isBackgroundAttachmentSet() && !next->isBackgroundClipSet() &&
275             !next->isBackgroundOriginSet() && !next->isBackgroundRepeatSet() &&
276             !next->isBackgroundSizeSet()) {
277             delete next;
278             p->m_next = 0;
279             break;
280         }
281     }
282 }
283
284 StyleBackgroundData::StyleBackgroundData()
285 {}
286
287 StyleBackgroundData::StyleBackgroundData(const StyleBackgroundData& o)
288     : Shared<StyleBackgroundData>(), m_background(o.m_background), m_outline(o.m_outline)
289 {}
290
291 bool StyleBackgroundData::operator==(const StyleBackgroundData& o) const
292 {
293     return m_background == o.m_background && m_color == o.m_color && m_outline == o.m_outline;
294 }
295
296 StyleMarqueeData::StyleMarqueeData()
297 {
298     increment = RenderStyle::initialMarqueeIncrement();
299     speed = RenderStyle::initialMarqueeSpeed();
300     direction = RenderStyle::initialMarqueeDirection();
301     behavior = RenderStyle::initialMarqueeBehavior();
302     loops = RenderStyle::initialMarqueeLoopCount();
303 }
304
305 StyleMarqueeData::StyleMarqueeData(const StyleMarqueeData& o)
306 :Shared<StyleMarqueeData>(), increment(o.increment), speed(o.speed), loops(o.loops),
307  behavior(o.behavior), direction(o.direction) 
308 {}
309
310 bool StyleMarqueeData::operator==(const StyleMarqueeData& o) const
311 {
312     return (increment == o.increment && speed == o.speed && direction == o.direction &&
313             behavior == o.behavior && loops == o.loops);
314 }
315
316 StyleFlexibleBoxData::StyleFlexibleBoxData()
317 : Shared<StyleFlexibleBoxData>()
318 {
319     flex = RenderStyle::initialBoxFlex();
320     flex_group = RenderStyle::initialBoxFlexGroup();
321     ordinal_group = RenderStyle::initialBoxOrdinalGroup();
322     align = RenderStyle::initialBoxAlign();
323     pack = RenderStyle::initialBoxPack();
324     orient = RenderStyle::initialBoxOrient();
325     lines = RenderStyle::initialBoxLines();
326 }
327
328 StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o)
329 : Shared<StyleFlexibleBoxData>()
330 {
331     flex = o.flex;
332     flex_group = o.flex_group;
333     ordinal_group = o.ordinal_group;
334     align = o.align;
335     pack = o.pack;
336     orient = o.orient;
337     lines = o.lines;
338 }
339
340 bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
341 {
342     return flex == o.flex && flex_group == o.flex_group &&
343            ordinal_group == o.ordinal_group && align == o.align &&
344            pack == o.pack && orient == o.orient && lines == o.lines;
345 }
346
347 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData()
348 :Shared<StyleCSS3NonInheritedData>(), 
349 lineClamp(RenderStyle::initialLineClamp()),
350 opacity(RenderStyle::initialOpacity()),
351 userDrag(RenderStyle::initialUserDrag()),
352 userSelect(RenderStyle::initialUserSelect()),
353 textOverflow(RenderStyle::initialTextOverflow()),
354 marginTopCollapse(MCOLLAPSE),
355 marginBottomCollapse(MCOLLAPSE),
356 m_appearance(RenderStyle::initialAppearance())
357 #ifndef KHTML_NO_XBL
358 , bindingURI(0)
359 #endif
360 {
361 }
362
363 StyleCSS3NonInheritedData::StyleCSS3NonInheritedData(const StyleCSS3NonInheritedData& o)
364 :Shared<StyleCSS3NonInheritedData>(), 
365 lineClamp(o.lineClamp),
366 opacity(o.opacity), flexibleBox(o.flexibleBox), marquee(o.marquee),
367 userDrag(o.userDrag), userSelect(o.userSelect), textOverflow(o.textOverflow),
368 marginTopCollapse(o.marginTopCollapse), marginBottomCollapse(o.marginBottomCollapse),
369 m_appearance(o.m_appearance)
370 {
371 #ifndef KHTML_NO_XBL
372     bindingURI = o.bindingURI ? o.bindingURI->copy() : 0;
373 #endif
374 }
375
376 StyleCSS3NonInheritedData::~StyleCSS3NonInheritedData()
377 {
378 #ifndef KHTML_NO_XBL
379     delete bindingURI;
380 #endif
381 }
382
383 #ifndef KHTML_NO_XBL
384 bool StyleCSS3NonInheritedData::bindingsEquivalent(const StyleCSS3NonInheritedData& o) const
385 {
386     if (this == &o) return true;
387     if (!bindingURI && o.bindingURI || bindingURI && !o.bindingURI)
388         return false;
389     if (bindingURI && o.bindingURI && (*bindingURI != *o.bindingURI))
390         return false;
391     return true;
392 }
393 #endif
394
395 bool StyleCSS3NonInheritedData::operator==(const StyleCSS3NonInheritedData& o) const
396 {
397     return opacity == o.opacity && flexibleBox == o.flexibleBox && marquee == o.marquee &&
398            userDrag == o.userDrag && userSelect == o.userSelect && textOverflow == o.textOverflow &&
399            marginTopCollapse == o.marginTopCollapse && marginBottomCollapse == o.marginBottomCollapse &&
400            m_appearance == o.m_appearance
401 #ifndef KHTML_NO_XBL
402            && bindingsEquivalent(o)
403 #endif
404            && lineClamp == o.lineClamp && m_dashboardRegions == o.m_dashboardRegions
405     ;
406 }
407
408 StyleCSS3InheritedData::StyleCSS3InheritedData()
409 :Shared<StyleCSS3InheritedData>(), textShadow(0), userModify(READ_ONLY), wordWrap(WBNORMAL), 
410     nbspMode(NBNORMAL), khtmlLineBreak(LBNORMAL)
411 , textSizeAdjust(RenderStyle::initialTextSizeAdjust())
412 {
413
414 }
415
416 StyleCSS3InheritedData::StyleCSS3InheritedData(const StyleCSS3InheritedData& o)
417 :Shared<StyleCSS3InheritedData>()
418 {
419     textShadow = o.textShadow ? new ShadowData(*o.textShadow) : 0;
420     userModify = o.userModify;
421     wordWrap = o.wordWrap;
422     nbspMode = o.nbspMode;
423     khtmlLineBreak = o.khtmlLineBreak;
424     textSizeAdjust = o.textSizeAdjust;
425 }
426
427 StyleCSS3InheritedData::~StyleCSS3InheritedData()
428 {
429     delete textShadow;
430 }
431
432 bool StyleCSS3InheritedData::operator==(const StyleCSS3InheritedData& o) const
433 {
434     return (userModify == o.userModify) && shadowDataEquivalent(o) && (wordWrap == o.wordWrap) &&
435         (nbspMode == o.nbspMode) && (khtmlLineBreak == o.khtmlLineBreak)
436             && (textSizeAdjust == o.textSizeAdjust)
437     ;
438 }
439
440 bool StyleCSS3InheritedData::shadowDataEquivalent(const StyleCSS3InheritedData& o) const
441 {
442     if (!textShadow && o.textShadow || textShadow && !o.textShadow)
443         return false;
444     if (textShadow && o.textShadow && (*textShadow != *o.textShadow))
445         return false;
446     return true;
447 }
448
449 StyleInheritedData::StyleInheritedData()
450     : indent( RenderStyle::initialTextIndent() ), line_height( RenderStyle::initialLineHeight() ), 
451       style_image( RenderStyle::initialListStyleImage() ),
452       cursor_image( 0 ), font(), color( RenderStyle::initialColor() ), 
453       horizontal_border_spacing( RenderStyle::initialHorizontalBorderSpacing() ), 
454       vertical_border_spacing( RenderStyle::initialVerticalBorderSpacing() ),
455       widows( RenderStyle::initialWidows() ), orphans( RenderStyle::initialOrphans() ),
456       page_break_inside( RenderStyle::initialPageBreak() )
457 {
458 }
459
460 StyleInheritedData::~StyleInheritedData()
461 {
462 }
463
464 StyleInheritedData::StyleInheritedData(const StyleInheritedData& o )
465     : Shared<StyleInheritedData>(),
466       indent( o.indent ), line_height( o.line_height ), style_image( o.style_image ),
467       cursor_image( o.cursor_image ), font( o.font ),
468       color( o.color ),
469       horizontal_border_spacing( o.horizontal_border_spacing ),
470       vertical_border_spacing( o.vertical_border_spacing ),
471       widows(o.widows), orphans(o.orphans), page_break_inside(o.page_break_inside)
472 {
473 }
474
475 bool StyleInheritedData::operator==(const StyleInheritedData& o) const
476 {
477     return
478         indent == o.indent &&
479         line_height == o.line_height &&
480         style_image == o.style_image &&
481         cursor_image == o.cursor_image &&
482         font == o.font &&
483         color == o.color &&
484         horizontal_border_spacing == o.horizontal_border_spacing &&
485         vertical_border_spacing == o.vertical_border_spacing &&
486         widows == o.widows &&
487         orphans == o.orphans &&
488         page_break_inside == o.page_break_inside;
489 }
490
491 // ----------------------------------------------------------
492
493 void* RenderStyle::operator new(size_t sz, RenderArena* renderArena) throw()
494 {
495     return renderArena->allocate(sz);
496 }
497
498 void RenderStyle::operator delete(void* ptr, size_t sz)
499 {
500     // Stash size where destroy can find it.
501     *(size_t *)ptr = sz;
502 }
503
504 void RenderStyle::arenaDelete(RenderArena *arena)
505 {
506     RenderStyle *ps = pseudoStyle;
507     RenderStyle *prev = 0;
508     
509     while (ps) {
510         prev = ps;
511         ps = ps->pseudoStyle;
512         // to prevent a double deletion.
513         // this works only because the styles below aren't really shared
514         // Dirk said we need another construct as soon as these are shared
515         prev->pseudoStyle = 0;
516         prev->deref(arena);
517     }
518     delete content;
519     
520     delete this;
521     
522     // Recover the size left there for us by operator delete and free the memory.
523     arena->free(*(size_t *)this, this);
524 }
525
526 inline RenderStyle *initDefaultStyle()
527 {
528     if (!defaultStyle)
529         defaultStyle = ::new RenderStyle(true);
530     return defaultStyle;
531 }
532
533 RenderStyle::RenderStyle()
534     : box(initDefaultStyle()->box)
535     , visual(defaultStyle->visual)
536     , background(defaultStyle->background)
537     , surround(defaultStyle->surround)
538     , css3NonInheritedData(defaultStyle->css3NonInheritedData)
539     , css3InheritedData(defaultStyle->css3InheritedData)
540     , inherited(defaultStyle->inherited)
541     , pseudoStyle(0)
542     , content(0)
543     , m_pseudoState(PseudoUnknown)
544     , m_affectedByAttributeSelectors(false)
545     , m_ref(0)
546 #if SVG_SUPPORT
547     , m_svgStyle(defaultStyle->m_svgStyle)
548 #endif
549
550 {
551     setBitDefaults(); // Would it be faster to copy this from the default style?
552 }
553
554 RenderStyle::RenderStyle(bool)
555 :m_pseudoState(PseudoUnknown), m_affectedByAttributeSelectors(false)
556 {
557     setBitDefaults();
558
559     box.init();
560     visual.init();
561     background.init();
562     surround.init();
563     css3NonInheritedData.init();
564     css3NonInheritedData.access()->flexibleBox.init();
565     css3NonInheritedData.access()->marquee.init();
566     css3InheritedData.init();
567     inherited.init();
568     
569 #if SVG_SUPPORT
570     m_svgStyle.init();
571 #endif
572
573     pseudoStyle = 0;
574     content = 0;
575     m_ref = 1;
576 }
577
578 RenderStyle::RenderStyle(const RenderStyle& o)
579     : inherited_flags( o.inherited_flags ), noninherited_flags( o.noninherited_flags ),
580       box( o.box ), visual( o.visual ), background( o.background ), surround( o.surround ),
581       css3NonInheritedData( o.css3NonInheritedData ), css3InheritedData( o.css3InheritedData ),
582       inherited( o.inherited ), pseudoStyle( 0 ), content( o.content ), m_pseudoState(o.m_pseudoState),
583       m_affectedByAttributeSelectors(false)
584 {
585 #if SVG_SUPPORT
586     m_svgStyle = o.m_svgStyle;
587 #endif
588     m_ref = 0;
589 }
590
591 void RenderStyle::inheritFrom(const RenderStyle* inheritParent)
592 {
593     css3InheritedData = inheritParent->css3InheritedData;
594     inherited = inheritParent->inherited;
595     inherited_flags = inheritParent->inherited_flags;
596 #if SVG_SUPPORT
597     if (m_svgStyle != inheritParent->m_svgStyle)
598         m_svgStyle.access()->inheritFrom(inheritParent->m_svgStyle.get());
599 #endif
600 }
601
602 RenderStyle::~RenderStyle()
603 {
604 }
605
606 bool RenderStyle::operator==(const RenderStyle& o) const
607 {
608 // compare everything except the pseudoStyle pointer
609     return (inherited_flags == o.inherited_flags &&
610             noninherited_flags == o.noninherited_flags &&
611             box == o.box &&
612             visual == o.visual &&
613             background == o.background &&
614             surround == o.surround &&
615             css3NonInheritedData == o.css3NonInheritedData &&
616             css3InheritedData == o.css3InheritedData &&
617             inherited == o.inherited
618 #if SVG_SUPPORT
619             && m_svgStyle == o.m_svgStyle
620 #endif
621             );
622 }
623
624 bool RenderStyle::isStyleAvailable() const
625 {
626     return this != CSSStyleSelector::styleNotYetAvailable;
627 }
628
629 enum EPseudoBit { NO_BIT = 0x0, BEFORE_BIT = 0x1, AFTER_BIT = 0x2, FIRST_LINE_BIT = 0x4,
630                   FIRST_LETTER_BIT = 0x8, SELECTION_BIT = 0x10, FIRST_LINE_INHERITED_BIT = 0x20 };
631
632 static inline int pseudoBit(RenderStyle::PseudoId pseudo)
633 {
634     switch (pseudo) {
635         case RenderStyle::BEFORE:
636             return BEFORE_BIT;
637         case RenderStyle::AFTER:
638             return AFTER_BIT;
639         case RenderStyle::FIRST_LINE:
640             return FIRST_LINE_BIT;
641         case RenderStyle::FIRST_LETTER:
642             return FIRST_LETTER_BIT;
643         case RenderStyle::SELECTION:
644             return SELECTION_BIT;
645         case RenderStyle::FIRST_LINE_INHERITED:
646             return FIRST_LINE_INHERITED_BIT;
647         default:
648             return NO_BIT;
649     }
650 }
651
652 bool RenderStyle::hasPseudoStyle(PseudoId pseudo) const
653 {
654     return pseudoBit(pseudo) & noninherited_flags._pseudoBits;
655 }
656
657 void RenderStyle::setHasPseudoStyle(PseudoId pseudo)
658 {
659     noninherited_flags._pseudoBits |= pseudoBit(pseudo);
660 }
661
662 RenderStyle* RenderStyle::getPseudoStyle(PseudoId pid)
663 {
664     if (!pseudoStyle || styleType() != NOPSEUDO)
665         return 0;
666     RenderStyle* ps = pseudoStyle;
667     while (ps && ps->styleType() != pid)
668         ps = ps->pseudoStyle;
669     return ps;
670 }
671
672 void RenderStyle::addPseudoStyle(RenderStyle* pseudo)
673 {
674     if (!pseudo)
675         return;
676     pseudo->ref();
677     pseudo->pseudoStyle = pseudoStyle;
678     pseudoStyle = pseudo;
679 }
680
681 bool RenderStyle::inheritedNotEqual( RenderStyle *other ) const
682 {
683     return inherited_flags != other->inherited_flags ||
684            inherited != other->inherited ||
685 #if SVG_SUPPORT
686            m_svgStyle->inheritedNotEqual(other->m_svgStyle.get()) ||
687 #endif
688            css3InheritedData != other->css3InheritedData;
689 }
690
691 /*
692   compares two styles. The result gives an idea of the action that
693   needs to be taken when replacing the old style with a new one.
694
695   CbLayout: The containing block of the object needs a relayout.
696   Layout: the RenderObject needs a relayout after the style change
697   Visible: The change is visible, but no relayout is needed
698   NonVisible: The object does need neither repaint nor relayout after
699        the change.
700
701   ### TODO:
702   A lot can be optimised here based on the display type, lots of
703   optimisations are unimplemented, and currently result in the
704   worst case result causing a relayout of the containing block.
705 */
706 RenderStyle::Diff RenderStyle::diff( const RenderStyle *other ) const
707 {
708 #if SVG_SUPPORT
709     // This is horribly inefficient.  Eventually we'll have to integrate
710     // this more directly by calling: Diff svgDiff = svgStyle->diff(other)
711     // and then checking svgDiff and returning from the appropraite places below.
712     if (m_svgStyle != other->m_svgStyle)
713         return Layout;
714 #endif
715
716     // we anyway assume they are the same
717 //      EDisplay _effectiveDisplay : 5;
718
719     // NonVisible:
720 //      ECursor _cursor_style : 4;
721
722 // ### this needs work to know more exactly if we need a relayout
723 //     or just a repaint
724
725 // non-inherited attributes
726 //     DataRef<StyleBoxData> box;
727 //     DataRef<StyleVisualData> visual;
728 //     DataRef<StyleSurroundData> surround;
729
730 // inherited attributes
731 //     DataRef<StyleInheritedData> inherited;
732
733     if ( box->width != other->box->width ||
734          box->min_width != other->box->min_width ||
735          box->max_width != other->box->max_width ||
736          box->height != other->box->height ||
737          box->min_height != other->box->min_height ||
738          box->max_height != other->box->max_height ||
739          box->vertical_align != other->box->vertical_align ||
740          box->boxSizing != other->box->boxSizing ||
741          !(surround->margin == other->surround->margin) ||
742          !(surround->padding == other->surround->padding) ||
743          css3NonInheritedData->m_appearance != other->css3NonInheritedData->m_appearance ||
744          css3NonInheritedData->marginTopCollapse != other->css3NonInheritedData->marginTopCollapse ||
745          css3NonInheritedData->marginBottomCollapse != other->css3NonInheritedData->marginBottomCollapse ||
746          *css3NonInheritedData->flexibleBox.get() != *other->css3NonInheritedData->flexibleBox.get() ||
747          (css3NonInheritedData->lineClamp != other->css3NonInheritedData->lineClamp) ||
748          (css3InheritedData->textSizeAdjust != other->css3InheritedData->textSizeAdjust) ||
749          (css3InheritedData->wordWrap != other->css3InheritedData->wordWrap) ||
750          (css3InheritedData->nbspMode != other->css3InheritedData->nbspMode) ||
751          (css3InheritedData->khtmlLineBreak != other->css3InheritedData->khtmlLineBreak) ||
752         !(inherited->indent == other->inherited->indent) ||
753         !(inherited->line_height == other->inherited->line_height) ||
754         !(inherited->style_image == other->inherited->style_image) ||
755         !(inherited->cursor_image == other->inherited->cursor_image) ||
756         !(inherited->font == other->inherited->font) ||
757         !(inherited->horizontal_border_spacing == other->inherited->horizontal_border_spacing) ||
758         !(inherited->vertical_border_spacing == other->inherited->vertical_border_spacing) ||
759         !(inherited_flags._box_direction == other->inherited_flags._box_direction) ||
760         !(inherited_flags._visuallyOrdered == other->inherited_flags._visuallyOrdered) ||
761         !(inherited_flags._htmlHacks == other->inherited_flags._htmlHacks) ||
762         !(noninherited_flags._position == other->noninherited_flags._position) ||
763         !(noninherited_flags._floating == other->noninherited_flags._floating) ||
764         !(noninherited_flags._originalDisplay == other->noninherited_flags._originalDisplay) ||
765          visual->colspan != other->visual->colspan ||
766          visual->counter_increment != other->visual->counter_increment ||
767          visual->counter_reset != other->visual->counter_reset ||
768          css3NonInheritedData->textOverflow != other->css3NonInheritedData->textOverflow)
769         return Layout;
770    
771     // changes causing Layout changes:
772
773 // only for tables:
774 //     _border_collapse
775 //     EEmptyCell _empty_cells : 2 ;
776 //     ECaptionSide _caption_side : 2;
777 //     ETableLayout _table_layout : 1;
778 //     EPosition _position : 2;
779 //     EFloat _floating : 2;
780     if ( ((int)noninherited_flags._effectiveDisplay) >= TABLE ) {
781         // Stupid gcc gives a compile error on
782         // a != other->b if a and b are bitflags. Using
783         // !(a== other->b) instead.
784         if ( !(inherited_flags._border_collapse == other->inherited_flags._border_collapse) ||
785              !(inherited_flags._empty_cells == other->inherited_flags._empty_cells) ||
786              !(inherited_flags._caption_side == other->inherited_flags._caption_side) ||
787              !(noninherited_flags._table_layout == other->noninherited_flags._table_layout))
788             return Layout;
789         
790         // In the collapsing border model, 'hidden' suppresses other borders, while 'none'
791         // does not, so these style differences can be width differences.
792         if (inherited_flags._border_collapse &&
793             (borderTopStyle() == BHIDDEN && other->borderTopStyle() == BNONE ||
794              borderTopStyle() == BNONE && other->borderTopStyle() == BHIDDEN ||
795              borderBottomStyle() == BHIDDEN && other->borderBottomStyle() == BNONE ||
796              borderBottomStyle() == BNONE && other->borderBottomStyle() == BHIDDEN ||
797              borderLeftStyle() == BHIDDEN && other->borderLeftStyle() == BNONE ||
798              borderLeftStyle() == BNONE && other->borderLeftStyle() == BHIDDEN ||
799              borderRightStyle() == BHIDDEN && other->borderRightStyle() == BNONE ||
800              borderRightStyle() == BNONE && other->borderRightStyle() == BHIDDEN))
801             return Layout;
802     }
803
804 // only for lists:
805 //      EListStyleType _list_style_type : 5 ;
806 //      EListStylePosition _list_style_position :1;
807     if (noninherited_flags._effectiveDisplay == LIST_ITEM ) {
808         if ( !(inherited_flags._list_style_type == other->inherited_flags._list_style_type) ||
809              !(inherited_flags._list_style_position == other->inherited_flags._list_style_position) )
810             return Layout;
811     }
812
813 // ### These could be better optimised
814 //      ETextAlign _text_align : 3;
815 //      ETextTransform _text_transform : 4;
816 //      EDirection _direction : 1;
817 //      EWhiteSpace _white_space : 2;
818 //      EFontVariant _font_variant : 1;
819 //     EClear _clear : 2;
820     if ( !(inherited_flags._text_align == other->inherited_flags._text_align) ||
821          !(inherited_flags._text_transform == other->inherited_flags._text_transform) ||
822          !(inherited_flags._direction == other->inherited_flags._direction) ||
823          !(inherited_flags._white_space == other->inherited_flags._white_space) ||
824          !(noninherited_flags._clear == other->noninherited_flags._clear) ||
825          !css3InheritedData->shadowDataEquivalent(*other->css3InheritedData.get())
826         )
827         return Layout;
828
829 // only for inline:
830 //     EVerticalAlign _vertical_align : 4;
831
832     if ( !(noninherited_flags._effectiveDisplay == INLINE) &&
833          !(noninherited_flags._vertical_align == other->noninherited_flags._vertical_align))
834         return Layout;
835
836     // If our border widths change, then we need to layout.  Other changes to borders
837     // only necessitate a repaint.
838     if (borderLeftWidth() != other->borderLeftWidth() ||
839         borderTopWidth() != other->borderTopWidth() ||
840         borderBottomWidth() != other->borderBottomWidth() ||
841         borderRightWidth() != other->borderRightWidth())
842         return Layout;
843
844     // If regions change trigger a relayout to re-calc regions.
845     if (!(css3NonInheritedData->m_dashboardRegions == other->css3NonInheritedData->m_dashboardRegions))
846         return Layout;
847
848     // Make sure these left/top/right/bottom checks stay below all layout checks and above
849     // all visible checks.
850     if (other->position() != StaticPosition) {
851         if (!(surround->offset == other->surround->offset)) {
852             // FIXME: We will need to do a bit of work in RenderObject/Box::setStyle before we
853             // can stop doing a layout when relative positioned objects move.  In particular, we'll need
854             // to update scrolling positions and figure out how to do a repaint properly of the updated layer.
855             //if (other->position() == RelativePosition)
856             //    return RepaintLayer;
857             //else
858                 return Layout;
859         }
860         else if (box->z_index != other->box->z_index || box->z_auto != other->box->z_auto ||
861                  !(visual->clip == other->visual->clip) || visual->hasClip != other->visual->hasClip)
862             return RepaintLayer;
863     }
864
865     if (css3NonInheritedData->opacity != other->css3NonInheritedData->opacity)
866         return RepaintLayer;
867
868     // Repaint:
869 //      EVisibility _visibility : 2;
870 //     EOverflow _overflow : 4 ;
871 //      int _text_decoration : 4;
872 //     DataRef<StyleBackgroundData> background;
873     if (inherited->color != other->inherited->color ||
874         !(inherited_flags._visibility == other->inherited_flags._visibility) ||
875         !(noninherited_flags._overflow == other->noninherited_flags._overflow) ||
876         !(inherited_flags._text_decorations == other->inherited_flags._text_decorations) ||
877         !(inherited_flags._force_backgrounds_to_white == other->inherited_flags._force_backgrounds_to_white) ||
878         !(surround->border == other->surround->border) ||
879         *background.get() != *other->background.get() ||
880         visual->textDecoration != other->visual->textDecoration ||
881         css3InheritedData->userModify != other->css3InheritedData->userModify ||
882         css3NonInheritedData->userSelect != other->css3NonInheritedData->userSelect ||
883         css3NonInheritedData->userDrag != other->css3NonInheritedData->userDrag
884         )
885         return Repaint;
886
887     return Equal;
888 }
889
890
891 //int RenderStyle::counter = 0;
892 //int SharedData::counter = 0;
893
894 void RenderStyle::cleanup()
895 {
896 //    counter = 0;
897 //    SharedData::counter = 0;
898 }
899
900
901 void RenderStyle::adjustBackgroundLayers()
902 {
903     if (backgroundLayers()->next()) {
904         // First we cull out layers that have no properties set.
905         accessBackgroundLayers()->cullEmptyLayers();
906         
907         // Next we repeat patterns into layers that don't have some properties set.
908         accessBackgroundLayers()->fillUnsetProperties();
909     }
910 }
911
912 void RenderStyle::setClip( Length top, Length right, Length bottom, Length left )
913 {
914     StyleVisualData *data = visual.access();
915     data->clip.top = top;
916     data->clip.right = right;
917     data->clip.bottom = bottom;
918     data->clip.left = left;
919 }
920
921 bool RenderStyle::contentDataEquivalent(const RenderStyle* otherStyle) const
922 {
923     ContentData* c1 = content;
924     ContentData* c2 = otherStyle->content;
925
926     while (c1 && c2) {
927         if (c1->_contentType != c2->_contentType)
928             return false;
929         if (c1->_contentType == CONTENT_TEXT) {
930             String c1Str(c1->_content.text);
931             String c2Str(c2->_content.text);
932             if (c1Str != c2Str)
933                 return false;
934         }
935         else if (c1->_contentType == CONTENT_OBJECT) {
936             if (c1->_content.object != c2->_content.object)
937                 return false;
938         }
939
940         c1 = c1->_nextContent;
941         c2 = c2->_nextContent;
942     }
943
944     return !c1 && !c2;
945 }
946
947 void RenderStyle::setContent(CachedObject* o, bool add)
948 {
949     if (!o)
950         return; // The object is null. Nothing to do. Just bail.
951
952     ContentData* lastContent = content;
953     while (lastContent && lastContent->_nextContent)
954         lastContent = lastContent->_nextContent;
955
956     bool reuseContent = !add;
957     ContentData* newContentData = 0;
958     if (reuseContent && content) {
959         content->clearContent();
960         newContentData = content;
961     }
962     else
963         newContentData = new ContentData;
964
965     if (lastContent && !reuseContent)
966         lastContent->_nextContent = newContentData;
967     else
968         content = newContentData;
969
970     //    o->ref();
971     newContentData->_content.object = o;
972     newContentData->_contentType = CONTENT_OBJECT;
973 }
974
975 void RenderStyle::setContent(StringImpl* s, bool add)
976 {
977     if (!s)
978         return; // The string is null. Nothing to do. Just bail.
979     
980     ContentData* lastContent = content;
981     while (lastContent && lastContent->_nextContent)
982         lastContent = lastContent->_nextContent;
983
984     bool reuseContent = !add;
985     if (add && lastContent) {
986         if (lastContent->_contentType == CONTENT_TEXT) {
987             // We can augment the existing string and share this ContentData node.
988             StringImpl* oldStr = lastContent->_content.text;
989             StringImpl* newStr = oldStr->copy();
990             newStr->ref();
991             oldStr->deref();
992             newStr->append(s);
993             lastContent->_content.text = newStr;
994             return;
995         }
996     }
997
998     ContentData* newContentData = 0;
999     if (reuseContent && content) {
1000         content->clearContent();
1001         newContentData = content;
1002     }
1003     else
1004         newContentData = new ContentData;
1005     
1006     if (lastContent && !reuseContent)
1007         lastContent->_nextContent = newContentData;
1008     else
1009         content = newContentData;
1010     
1011     newContentData->_content.text = s;
1012     newContentData->_content.text->ref();
1013     newContentData->_contentType = CONTENT_TEXT;
1014 }
1015
1016 ContentData::~ContentData()
1017 {
1018     clearContent();
1019 }
1020
1021 void ContentData::clearContent()
1022 {
1023     delete _nextContent;
1024     _nextContent = 0;
1025     
1026     switch (_contentType)
1027     {
1028         case CONTENT_OBJECT:
1029 //            _content.object->deref();
1030             _content.object = 0;
1031             break;
1032         case CONTENT_TEXT:
1033             _content.text->deref();
1034             _content.text = 0;
1035         default:
1036             ;
1037     }
1038 }
1039
1040 #ifndef KHTML_NO_XBL
1041 BindingURI::BindingURI(WebCore::StringImpl* uri) 
1042 :m_next(0)
1043
1044     m_uri = uri;
1045     if (uri) uri->ref();
1046 }
1047
1048 BindingURI::~BindingURI()
1049 {
1050     if (m_uri)
1051         m_uri->deref();
1052     delete m_next;
1053 }
1054
1055 BindingURI* BindingURI::copy()
1056 {
1057     BindingURI* newBinding = new BindingURI(m_uri);
1058     if (next()) {
1059         BindingURI* nextCopy = next()->copy();
1060         newBinding->setNext(nextCopy);
1061     }
1062     
1063     return newBinding;
1064 }
1065
1066 bool BindingURI::operator==(const BindingURI& o) const
1067 {
1068     if ((m_next && !o.m_next) || (!m_next && o.m_next) ||
1069         (m_next && o.m_next && *m_next != *o.m_next))
1070         return false;
1071     
1072     if (m_uri == o.m_uri)
1073         return true;
1074     if (!m_uri || !o.m_uri)
1075         return false;
1076     
1077     return String(m_uri) == String(o.m_uri);
1078 }
1079
1080 void RenderStyle::addBindingURI(WebCore::StringImpl* uri)
1081 {
1082     BindingURI* binding = new BindingURI(uri);
1083     if (!bindingURIs())
1084         SET_VAR(css3NonInheritedData, bindingURI, binding)
1085     else 
1086         for (BindingURI* b = bindingURIs(); b; b = b->next()) {
1087             if (!b->next())
1088                 b->setNext(binding);
1089         }
1090 }
1091 #endif
1092
1093 void RenderStyle::setTextShadow(ShadowData* val, bool add)
1094 {
1095     StyleCSS3InheritedData* css3Data = css3InheritedData.access(); 
1096     if (!add) {
1097         delete css3Data->textShadow;
1098         css3Data->textShadow = val;
1099         return;
1100     }
1101
1102     ShadowData* last = css3Data->textShadow;
1103     while (last->next) last = last->next;
1104     last->next = val;
1105 }
1106
1107 ShadowData::ShadowData(const ShadowData& o)
1108 :x(o.x), y(o.y), blur(o.blur), color(o.color)
1109 {
1110     next = o.next ? new ShadowData(*o.next) : 0;
1111 }
1112
1113 bool ShadowData::operator==(const ShadowData& o) const
1114 {
1115     if ((next && !o.next) || (!next && o.next) ||
1116         (next && o.next && *next != *o.next))
1117         return false;
1118     
1119     return x == o.x && y == o.y && blur == o.blur && color == o.color;
1120 }
1121
1122 const DeprecatedValueList<StyleDashboardRegion>& RenderStyle::initialDashboardRegions()
1123
1124     static DeprecatedValueList<StyleDashboardRegion> emptyList;
1125     return emptyList;
1126 }
1127
1128 const DeprecatedValueList<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
1129
1130     static DeprecatedValueList<StyleDashboardRegion> noneList;
1131     static bool noneListInitialized = false;
1132     
1133     if (!noneListInitialized) {
1134         StyleDashboardRegion region;
1135         region.label = "";
1136         region.offset.top  = Length();
1137         region.offset.right = Length();
1138         region.offset.bottom = Length();
1139         region.offset.left = Length();
1140         region.type = StyleDashboardRegion::None;
1141         noneList.append (region);
1142         noneListInitialized = true;
1143     }
1144     return noneList;
1145 }
1146
1147 }