Fix for 7837, make opacity work with table rows. Make transparent backgrounds
[WebKit-https.git] / WebCore / rendering / render_object.cpp
1 /**
2  * This file is part of the html renderer for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2000 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22  * Boston, MA 02111-1307, USA.
23  *
24  */
25
26 #include "config.h"
27 #include "render_object.h"
28
29 #include "CachedImage.h"
30 #include "DocumentImpl.h"
31 #include "EventNames.h"
32 #include "FloatRect.h"
33 #include "Frame.h"
34 #include "FrameView.h"
35 #include "GraphicsContext.h"
36 #include "IntPointArray.h"
37 #include "KWQAccObjectCache.h" 
38 #include "RenderBlock.h"
39 #include "RenderTable.h"
40 #include "RenderTableCell.h"
41 #include "RenderTableCol.h"
42 #include "RenderTableRow.h"
43 #include "RenderText.h"
44 #include "cssstyleselector.h"
45 #include "dom2_eventsimpl.h"
46 #include "dom_elementimpl.h"
47 #include "dom_position.h"
48 #include "htmlnames.h"
49 #include "render_arena.h"
50 #include "render_canvas.h"
51 #include "render_flexbox.h"
52 #include "render_inline.h"
53 #include "render_line.h"
54 #include "render_list.h"
55 #include "render_theme.h"
56 #include "VisiblePosition.h"
57 #include <qmatrix.h>
58 #include "TextEncoding.h"
59 #include <qtextstream.h>
60
61 namespace WebCore {
62
63 using namespace EventNames;
64 using namespace HTMLNames;
65
66 #ifndef NDEBUG
67 static void *baseOfRenderObjectBeingDeleted;
68 #endif
69
70 void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
71 {
72     return renderArena->allocate(sz);
73 }
74
75 void RenderObject::operator delete(void* ptr, size_t sz)
76 {
77     ASSERT(baseOfRenderObjectBeingDeleted == ptr);
78     
79     // Stash size where destroy can find it.
80     *(size_t *)ptr = sz;
81 }
82
83 RenderObject *RenderObject::createObject(DOM::NodeImpl* node,  RenderStyle* style)
84 {
85     RenderObject *o = 0;
86     RenderArena* arena = node->getDocument()->renderArena();
87     switch(style->display())
88     {
89     case NONE:
90         break;
91     case INLINE:
92         o = new (arena) RenderInline(node);
93         break;
94     case BLOCK:
95         o = new (arena) RenderBlock(node);
96         break;
97     case INLINE_BLOCK:
98         o = new (arena) RenderBlock(node);
99         break;
100     case LIST_ITEM:
101         o = new (arena) RenderListItem(node);
102         break;
103     case RUN_IN:
104     case COMPACT:
105         o = new (arena) RenderBlock(node);
106         break;
107     case TABLE:
108     case INLINE_TABLE:
109         o = new (arena) RenderTable(node);
110         break;
111     case TABLE_ROW_GROUP:
112     case TABLE_HEADER_GROUP:
113     case TABLE_FOOTER_GROUP:
114         o = new (arena) RenderTableSection(node);
115         break;
116     case TABLE_ROW:
117         o = new (arena) RenderTableRow(node);
118         break;
119     case TABLE_COLUMN_GROUP:
120     case TABLE_COLUMN:
121         o = new (arena) RenderTableCol(node);
122         break;
123     case TABLE_CELL:
124         o = new (arena) RenderTableCell(node);
125         break;
126     case TABLE_CAPTION:
127         o = new (arena) RenderBlock(node);
128         break;
129     case BOX:
130     case INLINE_BOX:
131         o = new (arena) RenderFlexibleBox(node);
132         break;
133     }
134     return o;
135 }
136
137 #ifndef NDEBUG
138 struct RenderObjectCounter { 
139     static int count; 
140     ~RenderObjectCounter() { if (count != 0) fprintf(stderr, "LEAK: %d RenderObject\n", count); } 
141 };
142 int RenderObjectCounter::count;
143 static RenderObjectCounter renderObjectCounter;
144 #endif NDEBUG
145
146 RenderObject::RenderObject(DOM::NodeImpl* node)
147     : CachedObjectClient(),
148 m_style( 0 ),
149 m_node( node ),
150 m_parent( 0 ),
151 m_previous( 0 ),
152 m_next( 0 ),
153 m_verticalPosition( PositionUndefined ),
154 m_needsLayout( false ),
155 m_normalChildNeedsLayout( false ),
156 m_posChildNeedsLayout( false ),
157 m_minMaxKnown( false ),
158 m_floating( false ),
159
160 m_positioned( false ),
161 m_relPositioned( false ),
162 m_paintBackground( false ),
163
164 m_isAnonymous( node == node->getDocument() ),
165 m_recalcMinMax( false ),
166 m_isText( false ),
167 m_inline( true ),
168
169 m_replaced( false ),
170 m_isDragging( false ),
171 m_hasOverflowClip(false)
172 {
173 #ifndef NDEBUG
174     ++RenderObjectCounter::count;
175 #endif
176 }
177
178 RenderObject::~RenderObject()
179 {
180 #ifndef NDEBUG
181     --RenderObjectCounter::count;
182 #endif
183 }
184
185 bool RenderObject::hasAncestor(const RenderObject *obj) const
186 {
187     for (const RenderObject *r = this; r; r = r->m_parent)
188         if (r == obj)
189             return true;
190     return false;
191 }
192
193 bool RenderObject::isRoot() const
194 {
195     return element() && element()->renderer() == this &&
196            element()->getDocument()->documentElement() == element();
197 }
198
199 bool RenderObject::isBody() const
200 {
201     return element() && element()->renderer() == this && element()->hasTagName(bodyTag);
202 }
203
204 bool RenderObject::isHR() const
205 {
206     return element() && element()->hasTagName(hrTag);
207 }
208
209 bool RenderObject::isHTMLMarquee() const
210 {
211     return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
212 }
213
214 bool RenderObject::canHaveChildren() const
215 {
216     return false;
217 }
218
219 RenderFlow* RenderObject::continuation() const
220 {
221     return 0;
222 }
223
224 bool RenderObject::isInlineContinuation() const
225 {
226     return false;
227 }
228
229 void RenderObject::addChild(RenderObject* , RenderObject *)
230 {
231     KHTMLAssert(0);
232 }
233
234 RenderObject* RenderObject::removeChildNode(RenderObject* )
235 {
236     KHTMLAssert(0);
237     return 0;
238 }
239
240 void RenderObject::removeChild(RenderObject* )
241 {
242     KHTMLAssert(0);
243 }
244
245 void RenderObject::appendChildNode(RenderObject*)
246 {
247     KHTMLAssert(0);
248 }
249
250 void RenderObject::insertChildNode(RenderObject*, RenderObject*)
251 {
252     KHTMLAssert(0);
253 }
254
255 RenderObject *RenderObject::nextRenderer() const
256 {
257     if (firstChild())
258         return firstChild();
259
260     if (nextSibling())
261         return nextSibling();
262
263     const RenderObject *r = this;
264     while (r && !r->nextSibling())
265         r = r->parent();
266     if (r)
267         return r->nextSibling();
268
269     return 0;
270 }
271
272 RenderObject *RenderObject::previousRenderer() const
273 {
274     if (previousSibling()) {
275         RenderObject *r = previousSibling();
276         while (r->lastChild())
277             r = r->lastChild();
278         return r;
279     }
280
281     return parent();
282 }
283
284 bool RenderObject::isEditable() const
285 {
286     RenderText *textRenderer = 0;
287     if (isText()) {
288         textRenderer = static_cast<RenderText *>(const_cast<RenderObject *>(this));
289     }
290
291     return style()->visibility() == VISIBLE && 
292         element() && element()->isContentEditable() &&
293         ((isBlockFlow() && !firstChild()) || 
294         isReplaced() || 
295         isBR() || 
296         (textRenderer && textRenderer->firstTextBox()));
297 }
298
299 RenderObject *RenderObject::nextEditable() const
300 {
301     RenderObject *r = const_cast<RenderObject *>(this);
302     RenderObject *n = firstChild();
303     if (n) {
304         while (n) { 
305             r = n; 
306             n = n->firstChild(); 
307         }
308         if (r->isEditable())
309             return r;
310         else 
311             return r->nextEditable();
312     }
313     n = r->nextSibling();
314     if (n) {
315         r = n;
316         while (n) { 
317             r = n; 
318             n = n->firstChild(); 
319         }
320         if (r->isEditable())
321             return r;
322         else 
323             return r->nextEditable();
324     }
325     n = r->parent();
326     while (n) {
327         r = n;
328         n = r->nextSibling();
329         if (n) {
330             r = n;
331             n = r->firstChild();
332             while (n) { 
333                 r = n; 
334                 n = n->firstChild(); 
335             }
336             if (r->isEditable())
337                 return r;
338             else 
339                 return r->nextEditable();
340         }
341         n = r->parent();
342     }
343     return 0;
344 }
345
346 RenderObject *RenderObject::previousEditable() const
347 {
348     RenderObject *r = const_cast<RenderObject *>(this);
349     RenderObject *n = firstChild();
350     if (n) {
351         while (n) { 
352             r = n; 
353             n = n->lastChild(); 
354         }
355         if (r->isEditable())
356             return r;
357         else 
358             return r->previousEditable();
359     }
360     n = r->previousSibling();
361     if (n) {
362         r = n;
363         while (n) { 
364             r = n; 
365             n = n->lastChild(); 
366         }
367         if (r->isEditable())
368             return r;
369         else 
370             return r->previousEditable();
371     }    
372     n = r->parent();
373     while (n) {
374         r = n;
375         n = r->previousSibling();
376         if (n) {
377             r = n;
378             n = r->lastChild();
379             while (n) { 
380                 r = n; 
381                 n = n->lastChild(); 
382             }
383             if (r->isEditable())
384                 return r;
385             else 
386                 return r->previousEditable();
387         }
388         n = r->parent();
389     }
390     return 0;
391
392
393 RenderObject *RenderObject::firstLeafChild() const
394 {
395     RenderObject *r = firstChild();
396     while (r) {
397         RenderObject *n = 0;
398         n = r->firstChild();
399         if (!n)
400             break;
401         r = n;
402     }
403     return r;
404 }
405
406 RenderObject *RenderObject::lastLeafChild() const
407 {
408     RenderObject *r = lastChild();
409     while (r) {
410         RenderObject *n = 0;
411         n = r->lastChild();
412         if (!n)
413             break;
414         r = n;
415     }
416     return r;
417 }
418
419 static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
420                       RenderLayer*& beforeChild)
421 {
422     if (obj->layer()) {
423         if (!beforeChild && newObject) {
424             // We need to figure out the layer that follows newObject.  We only do
425             // this the first time we find a child layer, and then we update the
426             // pointer values for newObject and beforeChild used by everyone else.
427             beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
428             newObject = 0;
429         }
430         parentLayer->addChild(obj->layer(), beforeChild);
431         return;
432     }
433
434     for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
435         addLayers(curr, parentLayer, newObject, beforeChild);
436 }
437
438 void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
439 {
440     if (!parentLayer)
441         return;
442     
443     RenderObject* object = newObject;
444     RenderLayer* beforeChild = 0;
445     WebCore::addLayers(this, parentLayer, object, beforeChild);
446 }
447
448 void RenderObject::removeLayers(RenderLayer* parentLayer)
449 {
450     if (!parentLayer)
451         return;
452     
453     if (layer()) {
454         parentLayer->removeChild(layer());
455         return;
456     }
457
458     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
459         curr->removeLayers(parentLayer);
460 }
461
462 void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
463 {
464     if (!newParent)
465         return;
466     
467     if (layer()) {
468         if (oldParent)
469             oldParent->removeChild(layer());
470         newParent->addChild(layer());
471         return;
472     }
473
474     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
475         curr->moveLayers(oldParent, newParent);
476 }
477
478 RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
479                                          bool checkParent)
480 {
481     // Error check the parent layer passed in.  If it's null, we can't find anything.
482     if (!parentLayer)
483         return 0;
484         
485     // Step 1: Descend into our siblings trying to find the next layer.  If we do find
486     // a layer, and if its parent layer matches our desired parent layer, then we have
487     // a match.
488     for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
489          curr; curr = curr->nextSibling()) {
490         RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
491         if (nextLayer) {
492             if (nextLayer->parent() == parentLayer)
493                 return nextLayer;
494             return 0;
495         }
496     }
497     
498     // Step 2: If our layer is the desired parent layer, then we're finished.  We didn't
499     // find anything.
500     RenderLayer* ourLayer = layer();
501     if (parentLayer == ourLayer)
502         return 0;
503     
504     // Step 3: If we have a layer, then return that layer.  It will be checked against
505     // the desired parent layer in the for loop above.
506     if (ourLayer)
507         return ourLayer;
508     
509     // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
510     // follow us to see if we can locate a layer.
511     if (checkParent && parent())
512         return parent()->findNextLayer(parentLayer, this, true);
513     
514     return 0;
515 }
516     
517 RenderLayer* RenderObject::enclosingLayer()
518 {
519     RenderObject* curr = this;
520     while (curr) {
521         RenderLayer *layer = curr->layer();
522         if (layer)
523             return layer;
524         curr = curr->parent();
525     }
526     return 0;
527 }
528
529 bool RenderObject::requiresLayer()
530 {
531     return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip();
532 }
533
534 RenderBlock* RenderObject::firstLineBlock() const
535 {
536     return 0;
537 }
538
539 void RenderObject::updateFirstLetter()
540 {}
541
542 int RenderObject::offsetLeft() const
543 {
544     int x = xPos();
545     if (!isPositioned()) {
546         if (isRelPositioned()) {
547             int y = 0;
548             ((RenderBox*)this)->relativePositionOffset(x, y);
549         }
550         
551         RenderObject* offsetPar = offsetParent();
552         RenderObject* curr = parent();
553         while (curr && curr != offsetPar) {
554             x += curr->xPos();
555             curr = curr->parent();
556         }
557     }
558     return x;
559 }
560
561 int RenderObject::offsetTop() const
562 {
563     int y = yPos();
564     if (!isPositioned()) {
565         if (isRelPositioned()) {
566             int x = 0;
567             ((RenderBox*)this)->relativePositionOffset(x, y);
568         }
569         RenderObject* offsetPar = offsetParent();
570         RenderObject* curr = parent();
571         while (curr && curr != offsetPar) {
572             y += curr->yPos();
573             curr = curr->parent();
574         }
575     }
576     return y;
577 }
578     
579 RenderObject* RenderObject::offsetParent() const
580 {
581     // FIXME: It feels like this function could almost be written using containing blocks.
582     bool skipTables = isPositioned() || isRelPositioned();
583     RenderObject* curr = parent();
584     while (curr && (!curr->element() || 
585                     (!curr->isPositioned() && !curr->isRelPositioned() && 
586                         !(!style()->htmlHacks() && skipTables ? curr->isRoot() : curr->isBody())))) {
587         if (!skipTables && curr->element() && (curr->isTableCell() || curr->isTable()))
588             break;
589         curr = curr->parent();
590     }
591     return curr;
592 }
593
594 // More IE extensions.  clientWidth and clientHeight represent the interior of an object
595 // excluding border and scrollbar.
596 int
597 RenderObject::clientWidth() const
598 {
599     return width() - borderLeft() - borderRight() -
600         (includeScrollbarSize() ? layer()->verticalScrollbarWidth() : 0);
601 }
602
603 int
604 RenderObject::clientHeight() const
605 {
606     return height() - borderTop() - borderBottom() -
607       (includeScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0);
608 }
609
610 // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
611 // object has overflow:hidden/scroll/auto specified and also has overflow.
612 int
613 RenderObject::scrollWidth() const
614 {
615     return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
616 }
617
618 int
619 RenderObject::scrollHeight() const
620 {
621     return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
622 }
623
624 bool RenderObject::scroll(KWQScrollDirection direction, KWQScrollGranularity granularity, float multiplier)
625 {
626     RenderLayer *l = layer();
627     if (l != 0 && l->scroll(direction, granularity, multiplier)) {
628         return true;
629     }
630     RenderBlock *b = containingBlock();
631     if (b != 0 && !b->isCanvas()) {
632         return b->scroll(direction, granularity, multiplier);
633     }
634     return false;
635 }
636
637 bool
638 RenderObject::hasStaticX() const
639 {
640     return (style()->left().isAuto() && style()->right().isAuto()) ||
641             style()->left().isStatic() ||
642             style()->right().isStatic();
643 }
644
645 bool
646 RenderObject::hasStaticY() const
647 {
648     return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
649 }
650
651 void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
652 {
653 }
654
655 void RenderObject::setNeedsLayout(bool b, bool markParents) 
656 {
657     bool alreadyNeededLayout = m_needsLayout;
658     m_needsLayout = b;
659     if (b) {
660         if (!alreadyNeededLayout && markParents)
661             markContainingBlocksForLayout();
662     }
663     else {
664         m_posChildNeedsLayout = false;
665         m_normalChildNeedsLayout = false;
666     }
667 }
668
669 void RenderObject::setChildNeedsLayout(bool b, bool markParents)
670 {
671     bool alreadyNeededLayout = m_normalChildNeedsLayout;
672     m_normalChildNeedsLayout = b;
673     if (b) {
674         if (!alreadyNeededLayout && markParents)
675             markContainingBlocksForLayout();
676     }
677     else {
678         m_posChildNeedsLayout = false;
679         m_normalChildNeedsLayout = false;
680     }
681 }
682
683 void RenderObject::markContainingBlocksForLayout()
684 {
685     RenderObject *o = container();
686     RenderObject *last = this;
687
688     while (o) {
689         if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
690             if (o->m_posChildNeedsLayout)
691                 return;
692             o->m_posChildNeedsLayout = true;
693         }
694         else {
695             if (o->m_normalChildNeedsLayout)
696                 return;
697             o->m_normalChildNeedsLayout = true;
698         }
699
700         last = o;
701         o = o->container();
702     }
703
704     last->scheduleRelayout();
705 }
706
707 RenderBlock* RenderObject::containingBlock() const
708 {
709     if(isTableCell())
710         return static_cast<const RenderTableCell *>(this)->table();
711     if (isCanvas())
712         return (RenderBlock*)this;
713
714     RenderObject *o = parent();
715     if (!isText() && m_style->position() == FixedPosition) {
716         while ( o && !o->isCanvas() )
717             o = o->parent();
718     }
719     else if (!isText() && m_style->position() == AbsolutePosition) {
720         while (o && (o->style()->position() == StaticPosition || (o->isInline() && !o->isReplaced()))
721                && !o->isRoot() && !o->isCanvas()) {
722             // For relpositioned inlines, we return the nearest enclosing block.  We don't try
723             // to return the inline itself.  This allows us to avoid having a positioned objects
724             // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
725             // from this method.  The container() method can actually be used to obtain the
726             // inline directly.
727             if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced())
728                 return o->containingBlock();
729             o = o->parent();
730         }
731     } else {
732         while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
733                      || o->isTableCol() || o->isFrameSet()
734 #if SVG_SUPPORT
735                      || o->isKCanvasContainer()
736 #endif
737                      ))
738             o = o->parent();
739     }
740
741     if (!o || !o->isRenderBlock())
742         return 0; // Probably doesn't happen any more, but leave just in case. -dwh
743     
744     return static_cast<RenderBlock*>(o);
745 }
746
747 int RenderObject::containingBlockWidth() const
748 {
749     // ###
750     return containingBlock()->contentWidth();
751 }
752
753 int RenderObject::containingBlockHeight() const
754 {
755     // ###
756     return containingBlock()->contentHeight();
757 }
758
759 bool RenderObject::mustRepaintBackgroundOrBorder() const
760 {
761     // If we don't have a background/border, then nothing to do.
762     if (!shouldPaintBackgroundOrBorder())
763         return false;
764     
765     // Ok, let's check the background first.
766     const BackgroundLayer* bgLayer = style()->backgroundLayers();
767     if (bgLayer->next())
768         return true; // Nobody will use multiple background layers without wanting fancy positioning.
769     
770     // Make sure we have a valid background image.
771     CachedImage* bg = bgLayer->backgroundImage();
772     bool shouldPaintBackgroundImage = bg && bg->canRender();
773     
774     // These are always percents or auto.
775     if (shouldPaintBackgroundImage && 
776         (bgLayer->backgroundXPosition().value() != 0 || bgLayer->backgroundYPosition().value() != 0))
777         return true; // The background image will shift unpredictably if the size changes.
778         
779     // Background is ok.  Let's check border.
780     if (style()->hasBorder()) {
781         // Border images are not ok.
782         CachedImage* borderImage = style()->borderImage().image();
783         bool shouldPaintBorderImage = borderImage && borderImage->canRender();
784         if (shouldPaintBorderImage && borderImage->isLoaded())
785             return true; // If the image hasn't loaded, we're still using the normal border style.
786     }
787
788     return false;
789 }
790
791 void RenderObject::drawBorder(GraphicsContext* p, int x1, int y1, int x2, int y2,
792                               BorderSide s, Color c, const Color& textcolor, EBorderStyle style,
793                               int adjbw1, int adjbw2, bool invalidisInvert)
794 {
795     int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
796
797     if(style == DOUBLE && width < 3)
798         style = SOLID;
799
800     if(!c.isValid()) {
801         if(invalidisInvert)
802         {
803             // FIXME: The original KHTML did XOR here -- what do we want to do instead?
804             c = Color::white;
805         }
806         else {
807             if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
808                 c.setRgb(238, 238, 238);
809             else
810                 c = textcolor;
811         }
812     }
813
814     switch(style)
815     {
816     case BNONE:
817     case BHIDDEN:
818         return;
819     case DOTTED:
820         p->setPen(Pen(c, width == 1 ? 0 : width, Pen::DotLine));
821         /* nobreak; */
822     case DASHED:
823         if(style == DASHED)
824             p->setPen(Pen(c, width == 1 ? 0 : width, Pen::DashLine));
825
826         if (width > 0)
827             switch(s)
828             {
829             case BSBottom:
830             case BSTop:
831                 p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
832                 break;
833             case BSRight:
834             case BSLeft:
835                 p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
836                 break;
837             }
838                 
839         break;
840
841     case DOUBLE:
842     {
843         int third = (width+1)/3;
844
845         if (adjbw1 == 0 && adjbw2 == 0)
846         {
847             p->setPen(Pen::NoPen);
848             p->setBrush(c);
849             switch(s)
850             {
851             case BSTop:
852             case BSBottom:
853                 p->drawRect(x1, y1      , x2-x1, third);
854                 p->drawRect(x1, y2-third, x2-x1, third);
855                 break;
856             case BSLeft:
857                 p->drawRect(x1      , y1+1, third, y2-y1-1);
858                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
859                 break;
860             case BSRight:
861                 p->drawRect(x1      , y1+1, third, y2-y1-1);
862                 p->drawRect(x2-third, y1+1, third, y2-y1-1);
863                 break;
864             }
865         }
866         else
867         {
868             int adjbw1bigthird;
869             if (adjbw1>0) adjbw1bigthird = adjbw1+1;
870             else adjbw1bigthird = adjbw1 - 1;
871             adjbw1bigthird /= 3;
872
873             int adjbw2bigthird;
874             if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
875             else adjbw2bigthird = adjbw2 - 1;
876             adjbw2bigthird /= 3;
877
878           switch(s)
879             {
880             case BSTop:
881               drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y1        , x2-kMax((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
882               drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y2 - third, x2-kMax(( adjbw2*2+1)/3,0), y2        , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
883               break;
884             case BSLeft:
885               drawBorder(p, x1        , y1+kMax((-adjbw1*2+1)/3,0), x1+third, y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
886               drawBorder(p, x2 - third, y1+kMax(( adjbw1*2+1)/3,0), x2      , y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
887               break;
888             case BSBottom:
889               drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y1      , x2-kMax(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
890               drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y2-third, x2-kMax((-adjbw2*2+1)/3,0), y2      , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
891               break;
892             case BSRight:
893             drawBorder(p, x1      , y1+kMax(( adjbw1*2+1)/3,0), x1+third, y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
894             drawBorder(p, x2-third, y1+kMax((-adjbw1*2+1)/3,0), x2      , y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
895               break;
896             default:
897               break;
898             }
899         }
900         break;
901     }
902     case RIDGE:
903     case GROOVE:
904     {
905         EBorderStyle s1;
906         EBorderStyle s2;
907         if (style==GROOVE)
908         {
909             s1 = INSET;
910             s2 = OUTSET;
911         }
912         else
913         {
914             s1 = OUTSET;
915             s2 = INSET;
916         }
917
918         int adjbw1bighalf;
919         int adjbw2bighalf;
920         if (adjbw1>0) adjbw1bighalf=adjbw1+1;
921         else adjbw1bighalf=adjbw1-1;
922         adjbw1bighalf/=2;
923
924         if (adjbw2>0) adjbw2bighalf=adjbw2+1;
925         else adjbw2bighalf=adjbw2-1;
926         adjbw2bighalf/=2;
927
928         switch (s)
929         {
930         case BSTop:
931             drawBorder(p, x1+kMax(-adjbw1  ,0)/2,  y1        , x2-kMax(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
932             drawBorder(p, x1+kMax( adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax( adjbw2+1,0)/2,  y2        , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
933             break;
934         case BSLeft:
935             drawBorder(p,  x1        , y1+kMax(-adjbw1  ,0)/2, (x1+x2+1)/2, y2-kMax(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
936             drawBorder(p, (x1+x2+1)/2, y1+kMax( adjbw1+1,0)/2,  x2        , y2-kMax( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
937             break;
938         case BSBottom:
939             drawBorder(p, x1+kMax( adjbw1  ,0)/2,  y1        , x2-kMax( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2,  adjbw1bighalf, adjbw2bighalf);
940             drawBorder(p, x1+kMax(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax(-adjbw2+1,0)/2,  y2        , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
941             break;
942         case BSRight:
943             drawBorder(p,  x1        , y1+kMax( adjbw1  ,0)/2, (x1+x2+1)/2, y2-kMax( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
944             drawBorder(p, (x1+x2+1)/2, y1+kMax(-adjbw1+1,0)/2,  x2        , y2-kMax(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
945             break;
946         }
947         break;
948     }
949     case INSET:
950         if(s == BSTop || s == BSLeft)
951             c = c.dark();
952
953         /* nobreak; */
954     case OUTSET:
955         if(style == OUTSET && (s == BSBottom || s == BSRight))
956             c = c.dark();
957         /* nobreak; */
958     case SOLID:
959         IntPointArray quad(4);
960         p->setPen(Pen::NoPen);
961         p->setBrush(c);
962         ASSERT(x2 >= x1);
963         ASSERT(y2 >= y1);
964         if (adjbw1==0 && adjbw2 == 0)
965           {
966             p->drawRect(x1,y1,x2-x1,y2-y1);
967             return;
968           }
969         switch(s) {
970         case BSTop:
971             quad.setPoints(4,
972                            x1+kMax(-adjbw1,0), y1,
973                            x1+kMax( adjbw1,0), y2,
974                            x2-kMax( adjbw2,0), y2,
975                            x2-kMax(-adjbw2,0), y1);
976             break;
977         case BSBottom:
978             quad.setPoints(4,
979                            x1+kMax( adjbw1,0), y1,
980                            x1+kMax(-adjbw1,0), y2,
981                            x2-kMax(-adjbw2,0), y2,
982                            x2-kMax( adjbw2,0), y1);
983             break;
984         case BSLeft:
985           quad.setPoints(4,
986                          x1, y1+kMax(-adjbw1,0),
987                          x1, y2-kMax(-adjbw2,0),
988                          x2, y2-kMax( adjbw2,0),
989                          x2, y1+kMax( adjbw1,0));
990             break;
991         case BSRight:
992           quad.setPoints(4,
993                          x1, y1+kMax( adjbw1,0),
994                          x1, y2-kMax( adjbw2,0),
995                          x2, y2-kMax(-adjbw2,0),
996                          x2, y1+kMax(-adjbw1,0));
997             break;
998         }
999         p->drawConvexPolygon(quad);
1000         break;
1001     }
1002 }
1003
1004 bool RenderObject::paintBorderImage(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1005 {
1006     CachedImage* borderImage = style->borderImage().image();
1007     if (!borderImage->isLoaded())
1008         return true; // Never paint a border image incrementally, but don't paint the fallback borders either.
1009     
1010     // If we have a border radius, the border image gets clipped to the rounded rect.
1011     bool clipped = false;
1012     if (style->hasBorderRadius()) {
1013         IntRect clipRect(_tx, _ty, w, h);
1014         p->save();
1015         p->addRoundedRectClip(clipRect,
1016             style->borderTopLeftRadius(), style->borderTopRightRadius(),
1017             style->borderBottomLeftRadius(), style->borderBottomRightRadius());
1018         clipped = true;
1019     }
1020
1021     int imageWidth = borderImage->image()->width();
1022     int imageHeight = borderImage->image()->height();
1023
1024     int topSlice = kMin(imageHeight, style->borderImage().m_slices.top.calcValue(borderImage->image()->height()));
1025     int bottomSlice = kMin(imageHeight, style->borderImage().m_slices.bottom.calcValue(borderImage->image()->height()));
1026     int leftSlice = kMin(imageWidth, style->borderImage().m_slices.left.calcValue(borderImage->image()->width()));    
1027     int rightSlice = kMin(imageWidth, style->borderImage().m_slices.right.calcValue(borderImage->image()->width()));
1028
1029     EBorderImageRule hRule = style->borderImage().horizontalRule();
1030     EBorderImageRule vRule = style->borderImage().verticalRule();
1031     
1032     bool drawLeft = leftSlice > 0 && style->borderLeftWidth() > 0;
1033     bool drawTop = topSlice > 0 && style->borderTopWidth() > 0;
1034     bool drawRight = rightSlice > 0 && style->borderRightWidth() > 0;
1035     bool drawBottom = bottomSlice > 0 && style->borderBottomWidth() > 0;
1036     bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - style->borderLeftWidth() - style->borderRightWidth()) > 0 &&
1037                       (imageHeight - topSlice - bottomSlice) > 0 && (h - style->borderTopWidth() - style->borderBottomWidth()) > 0;
1038
1039     if (drawLeft) {
1040         // Paint the top and bottom left corners.
1041         
1042         // The top left corner rect is (_tx, _ty, leftWidth, topWidth)
1043         // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
1044         if (drawTop)
1045             p->drawImage(borderImage->image(), _tx, _ty, style->borderLeftWidth(), style->borderTopWidth(),
1046                          0, 0, leftSlice, topSlice);
1047         
1048         // The bottom left corner rect is (_tx, _ty + h - bottomWidth, leftWidth, bottomWidth)
1049         // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
1050         if (drawBottom)
1051             p->drawImage(borderImage->image(), _tx, _ty + h - style->borderBottomWidth(), style->borderLeftWidth(), style->borderBottomWidth(),
1052                          0, imageHeight - bottomSlice, leftSlice, bottomSlice);
1053                       
1054         // Paint the left edge.
1055         // Have to scale and tile into the border rect.
1056         p->drawScaledAndTiledImage(borderImage->image(), _tx, _ty + style->borderTopWidth(), style->borderLeftWidth(),
1057                                     h - style->borderTopWidth() - style->borderBottomWidth(),
1058                                     0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice, 
1059                                     Image::StretchTile, (Image::TileRule)vRule);
1060     }
1061     
1062     if (drawRight) {
1063         // Paint the top and bottom right corners
1064         // The top right corner rect is (_tx + w - rightWidth, _ty, rightWidth, topWidth)
1065         // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
1066         if (drawTop)
1067             p->drawImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty, style->borderRightWidth(), style->borderTopWidth(),
1068                          imageWidth - rightSlice, 0, rightSlice, topSlice);
1069         
1070         // The bottom right corner rect is (_tx + w - rightWidth, _ty + h - bottomWidth, rightWidth, bottomWidth)
1071         // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, botomSlice)
1072         if (drawBottom)
1073             p->drawImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty + h - style->borderBottomWidth(), style->borderRightWidth(), style->borderBottomWidth(),
1074                          imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice);
1075                       
1076         // Paint the right edge.
1077         p->drawScaledAndTiledImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty + style->borderTopWidth(), style->borderRightWidth(),
1078                           h - style->borderTopWidth() - style->borderBottomWidth(),
1079                           imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice,
1080                           Image::StretchTile, (Image::TileRule)vRule);
1081     }
1082
1083     // Paint the top edge.
1084     if (drawTop)
1085         p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty, w - style->borderLeftWidth() - style->borderRightWidth(),
1086                           style->borderTopWidth(),
1087                           leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice,
1088                           (Image::TileRule)hRule, Image::StretchTile);
1089     
1090     // Paint the bottom edge.
1091     if (drawBottom)
1092         p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty + h - style->borderBottomWidth(), 
1093                           w - style->borderLeftWidth() - style->borderRightWidth(),
1094                           style->borderBottomWidth(),
1095                           leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice,
1096                           (Image::TileRule)hRule, Image::StretchTile);
1097     
1098     // Paint the middle.
1099     if (drawMiddle)
1100         p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty + style->borderTopWidth(), w - style->borderLeftWidth() - style->borderRightWidth(),
1101                           h - style->borderTopWidth() - style->borderBottomWidth(),
1102                           leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice,
1103                           (Image::TileRule)hRule, (Image::TileRule)vRule);
1104
1105     // Clear the clip for the border radius.
1106     if (clipped)
1107         p->restore();
1108
1109     return true;
1110 }
1111
1112 void RenderObject::paintBorder(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
1113 {
1114     CachedImage* borderImage = style->borderImage().image();
1115     bool shouldPaintBackgroundImage = borderImage && borderImage->canRender();
1116     if (shouldPaintBackgroundImage)
1117         shouldPaintBackgroundImage = paintBorderImage(p, _tx, _ty, w, h, style);
1118     
1119     if (shouldPaintBackgroundImage)
1120         return;
1121
1122     const Color& tc = style->borderTopColor();
1123     const Color& bc = style->borderBottomColor();
1124     const Color& lc = style->borderLeftColor();
1125     const Color& rc = style->borderRightColor();
1126
1127     bool tt = style->borderTopIsTransparent();
1128     bool bt = style->borderBottomIsTransparent();
1129     bool rt = style->borderRightIsTransparent();
1130     bool lt = style->borderLeftIsTransparent();
1131     
1132     EBorderStyle ts = style->borderTopStyle();
1133     EBorderStyle bs = style->borderBottomStyle();
1134     EBorderStyle ls = style->borderLeftStyle();
1135     EBorderStyle rs = style->borderRightStyle();
1136
1137     bool render_t = ts > BHIDDEN && !tt;
1138     bool render_l = ls > BHIDDEN && begin && !lt;
1139     bool render_r = rs > BHIDDEN && end && !rt;
1140     bool render_b = bs > BHIDDEN && !bt;
1141
1142     // Need sufficient width and height to contain border radius curves.  Sanity check our top/bottom
1143     // values and our width/height values to make sure the curves can all fit. If not, then we won't paint
1144     // any border radii.
1145     bool render_radii = false;
1146     IntSize topLeft = style->borderTopLeftRadius();
1147     IntSize topRight = style->borderTopRightRadius();
1148     IntSize bottomLeft = style->borderBottomLeftRadius();
1149     IntSize bottomRight = style->borderBottomRightRadius();
1150
1151     if (style->hasBorderRadius()) {
1152         int requiredWidth = kMax(topLeft.width() + topRight.width(), bottomLeft.width() + bottomRight.width());
1153         int requiredHeight = kMax(topLeft.height() + bottomLeft.height(), topRight.height() + bottomRight.height());
1154         render_radii = (requiredWidth <= w && requiredHeight <= h);
1155     }
1156     
1157     // Clip to the rounded rectangle.
1158     if (render_radii) {
1159         p->save();
1160         p->addRoundedRectClip(IntRect(_tx, _ty, w, h), topLeft, topRight, bottomLeft, bottomRight);
1161     }
1162
1163     if (render_t) {
1164         bool ignore_left = (render_radii && topLeft.width() > 0) ||
1165             ((tc == lc) && (tt == lt) &&
1166             (ts >= OUTSET) &&
1167             (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1168
1169         bool ignore_right = (render_radii && topRight.width() > 0) ||
1170             ((tc == rc) && (tt == rt) &&
1171             (ts >= OUTSET) &&
1172             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1173         
1174         int x = _tx;
1175         int x2 = _tx + w;
1176         if (render_radii) {
1177             x += topLeft.width();
1178             x2 -= topRight.width();
1179         }
1180         
1181         drawBorder(p, x, _ty, x2, _ty +  style->borderTopWidth(), BSTop, tc, style->color(), ts,
1182                    ignore_left ? 0 : style->borderLeftWidth(),
1183                    ignore_right? 0 : style->borderRightWidth());
1184     }
1185
1186     if (render_b) {
1187         bool ignore_left = (render_radii && bottomLeft.width() > 0) ||
1188         ((bc == lc) && (bt == lt) &&
1189         (bs >= OUTSET) &&
1190         (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1191
1192         bool ignore_right = (render_radii && bottomRight.width() > 0) ||
1193             ((bc == rc) && (bt == rt) &&
1194             (bs >= OUTSET) &&
1195             (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1196         
1197         int x = _tx;
1198         int x2 = _tx + w;
1199         if (render_radii) {
1200             x += bottomLeft.width();
1201             x2 -= bottomRight.width();
1202         }
1203
1204         drawBorder(p, x, _ty + h - style->borderBottomWidth(), x2, _ty + h, BSBottom, bc, style->color(), bs,
1205                    ignore_left ? 0 :style->borderLeftWidth(),
1206                    ignore_right? 0 :style->borderRightWidth());
1207     }
1208     
1209     if (render_l) {
1210         bool ignore_top = (render_radii && topLeft.height() > 0) ||
1211           ((tc == lc) && (tt == lt) &&
1212           (ls >= OUTSET) &&
1213           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1214
1215         bool ignore_bottom = (render_radii && bottomLeft.height() > 0) ||
1216           ((bc == lc) && (bt == lt) &&
1217           (ls >= OUTSET) &&
1218           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1219
1220         int y = _ty;
1221         int y2 = _ty + h;
1222         if (render_radii) {
1223             y += topLeft.height();
1224             y2 -= bottomLeft.height();
1225         }
1226         
1227         drawBorder(p, _tx, y, _tx + style->borderLeftWidth(), y2, BSLeft, lc, style->color(), ls,
1228                    ignore_top?0:style->borderTopWidth(),
1229                    ignore_bottom?0:style->borderBottomWidth());
1230     }
1231
1232     if (render_r) {
1233         bool ignore_top = (render_radii && topRight.height() > 0) ||
1234           ((tc == rc) && (tt == rt) &&
1235           (rs >= DOTTED || rs == INSET) &&
1236           (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1237
1238         bool ignore_bottom = (render_radii && bottomRight.height() > 0) ||
1239           ((bc == rc) && (bt == rt) &&
1240           (rs >= DOTTED || rs == INSET) &&
1241           (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1242
1243         int y = _ty;
1244         int y2 = _ty + h;
1245         if (render_radii) {
1246             y += topRight.height();
1247             y2 -= bottomRight.height();
1248         }
1249
1250         drawBorder(p, _tx + w - style->borderRightWidth(), y, _tx + w, y2, BSRight, rc, style->color(), rs,
1251                    ignore_top?0:style->borderTopWidth(),
1252                    ignore_bottom?0:style->borderBottomWidth());
1253     }
1254     
1255     if (render_radii)
1256         p->restore(); // Undo the clip.
1257 }
1258
1259 QValueList<IntRect> RenderObject::lineBoxRects()
1260 {
1261     return QValueList<IntRect>();
1262 }
1263
1264 void RenderObject::absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty)
1265 {
1266     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1267     // inline boxes above and below us (thus getting merged with them to form a single irregular
1268     // shape).
1269     if (continuation()) {
1270         rects.append(IntRect(_tx, _ty - collapsedMarginTop(), 
1271                            width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1272         continuation()->absoluteRects(rects, 
1273                                       _tx - xPos() + continuation()->containingBlock()->xPos(),
1274                                       _ty - yPos() + continuation()->containingBlock()->yPos());
1275     }
1276     else
1277         rects.append(IntRect(_tx, _ty, width(), height() + borderTopExtra() + borderBottomExtra()));
1278 }
1279
1280 IntRect RenderObject::absoluteBoundingBoxRect()
1281 {
1282     int x = 0, y = 0;
1283     absolutePosition(x, y);
1284     QValueList<IntRect> rects;
1285     absoluteRects(rects, x, y);
1286
1287     if (rects.isEmpty())
1288         return IntRect();
1289
1290     QValueList<IntRect>::ConstIterator it = rects.begin();
1291     IntRect result = *it;
1292     while (++it != rects.end())
1293         result.unite(*it);
1294     return result;
1295 }
1296
1297 void RenderObject::addAbsoluteRectForLayer(IntRect& result)
1298 {
1299     if (layer())
1300         result.unite(absoluteBoundingBoxRect());
1301     for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1302         current->addAbsoluteRectForLayer(result);
1303 }
1304
1305 IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
1306 {
1307     IntRect result = absoluteBoundingBoxRect();
1308     topLevelRect = result;
1309     for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1310         current->addAbsoluteRectForLayer(result);
1311     return result;
1312 }
1313
1314 void RenderObject::addFocusRingRects(GraphicsContext* p, int _tx, int _ty)
1315 {
1316     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1317     // inline boxes above and below us (thus getting merged with them to form a single irregular
1318     // shape).
1319     if (continuation()) {
1320         p->addFocusRingRect(IntRect(_tx, _ty - collapsedMarginTop(), width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1321         continuation()->addFocusRingRects(p, 
1322                                           _tx - xPos() + continuation()->containingBlock()->xPos(),
1323                                           _ty - yPos() + continuation()->containingBlock()->yPos());
1324     }
1325     else
1326         p->addFocusRingRect(IntRect(_tx, _ty, width(), height()));
1327 }
1328
1329 void RenderObject::paintOutline(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1330 {
1331     int ow = style->outlineWidth();
1332     if(!ow) return;
1333
1334     EBorderStyle os = style->outlineStyle();
1335     if (os <= BHIDDEN)
1336         return;
1337     
1338     Color oc = style->outlineColor();
1339     if (!oc.isValid())
1340         oc = style->color();
1341     
1342     int offset = style->outlineOffset();
1343     
1344     if (style->outlineStyleIsAuto()) {
1345         if (!theme()->supportsFocusRing(style)) {
1346             // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
1347             p->initFocusRing(ow, offset);
1348             addFocusRingRects(p, _tx, _ty);
1349             p->drawFocusRing(oc);
1350             p->clearFocusRing();
1351         }
1352         return;
1353     }
1354
1355     _tx -= offset;
1356     _ty -= offset;
1357     w += 2*offset;
1358     h += 2*offset;
1359     
1360     drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
1361                Color(oc), style->color(),
1362                os, ow, ow, true);
1363
1364     drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
1365                Color(oc), style->color(),
1366                os, ow, ow, true);
1367
1368     drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
1369                Color(oc), style->color(),
1370                os, ow, ow, true);
1371
1372     drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
1373                Color(oc), style->color(),
1374                os, ow, ow, true);
1375
1376 }
1377
1378 void RenderObject::paint(PaintInfo& i, int tx, int ty)
1379 {
1380 }
1381
1382 void RenderObject::repaint(bool immediate)
1383 {
1384     // Can't use canvas(), since we might be unrooted.
1385     RenderObject* o = this;
1386     while ( o->parent() ) o = o->parent();
1387     if (!o->isCanvas())
1388         return;
1389     RenderCanvas* c = static_cast<RenderCanvas*>(o);
1390     if (c->printingMode())
1391         return; // Don't repaint if we're printing.
1392     c->repaintViewRectangle(getAbsoluteRepaintRect(), immediate);    
1393 }
1394
1395 void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
1396 {
1397     // Can't use canvas(), since we might be unrooted.
1398     RenderObject* o = this;
1399     while ( o->parent() ) o = o->parent();
1400     if (!o->isCanvas())
1401         return;
1402     RenderCanvas* c = static_cast<RenderCanvas*>(o);
1403     if (c->printingMode())
1404         return; // Don't repaint if we're printing.
1405     IntRect absRect(r);
1406     computeAbsoluteRepaintRect(absRect);
1407     c->repaintViewRectangle(absRect, immediate);
1408 }
1409
1410 bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldFullBounds)
1411 {
1412     RenderCanvas* c = canvas();
1413     if (c->printingMode())
1414         return false; // Don't repaint if we're printing.
1415             
1416     IntRect newBounds, newFullBounds;
1417     getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
1418     if (newBounds == oldBounds && !selfNeedsLayout())
1419         return false;
1420
1421     bool fullRepaint = selfNeedsLayout() || newBounds.location() != oldBounds.location() || mustRepaintBackgroundOrBorder();
1422     if (fullRepaint) {
1423         c->repaintViewRectangle(oldFullBounds);
1424         if (newBounds != oldBounds)
1425             c->repaintViewRectangle(newFullBounds);
1426         return true;
1427     }
1428
1429     // We didn't move, but we did change size.  Invalidate the delta, which will consist of possibly 
1430     // two rectangles (but typically only one).
1431     int width = abs(newBounds.width() - oldBounds.width());
1432     if (width)
1433         c->repaintViewRectangle(IntRect(kMin(newBounds.x() + newBounds.width(), oldBounds.x() + oldBounds.width()) - borderRight(),
1434             newBounds.y(),
1435             width + borderRight(),
1436             kMax(newBounds.height(), oldBounds.height())));
1437     int height = abs(newBounds.height() - oldBounds.height());
1438     if (height)
1439         c->repaintViewRectangle(IntRect(newBounds.x(),
1440             kMin(newBounds.bottom(), oldBounds.bottom()) - borderBottom(),
1441             kMax(newBounds.width(), oldBounds.width()),
1442             height + borderBottom()));
1443     return false;
1444 }
1445
1446 void RenderObject::repaintDuringLayoutIfMoved(int x, int y)
1447 {
1448 }
1449
1450 void RenderObject::repaintFloatingDescendants()
1451 {
1452 }
1453
1454 bool RenderObject::checkForRepaintDuringLayout() const
1455 {
1456     return !document()->view()->needsFullRepaint() && !layer();
1457 }
1458
1459 void RenderObject::repaintObjectsBeforeLayout()
1460 {
1461     if (!needsLayout() || isText())
1462         return;
1463     
1464     bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
1465     if (selfNeedsLayout()) {
1466         repaint();
1467         if (blockWithInlineChildren)
1468             return;
1469     }
1470
1471     for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1472         if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
1473             current->repaintObjectsBeforeLayout();
1474     }
1475 }
1476
1477 IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
1478 {
1479     IntRect r(getAbsoluteRepaintRect());
1480     r.inflate(ow);
1481
1482     if (continuation() && !isInline())
1483         r.inflateY(collapsedMarginTop());
1484     
1485     if (isInlineFlow())
1486         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
1487             if (!curr->isText())
1488                 r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
1489
1490     return r;
1491 }
1492
1493 IntRect RenderObject::getAbsoluteRepaintRect()
1494 {
1495     if (parent())
1496         return parent()->getAbsoluteRepaintRect();
1497     return IntRect();
1498 }
1499
1500 void RenderObject::getAbsoluteRepaintRectIncludingFloats(IntRect& bounds, IntRect& fullBounds)
1501 {
1502     bounds = fullBounds = getAbsoluteRepaintRect();
1503 }
1504
1505 void RenderObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
1506 {
1507     if (parent())
1508         return parent()->computeAbsoluteRepaintRect(r, f);
1509 }
1510
1511 void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
1512 {
1513 }
1514
1515 #ifndef NDEBUG
1516
1517 QString RenderObject::information() const
1518 {
1519     QString str;
1520     QTextStream ts(&str);
1521     ts << renderName()
1522         << "(" << (style() ? style()->refCount() : 0) << ")"
1523        << ": " << (void*)this << "  ";
1524     if (isInline()) ts << "il ";
1525     if (childrenInline()) ts << "ci ";
1526     if (isFloating()) ts << "fl ";
1527     if (isAnonymous()) ts << "an ";
1528     if (isRelPositioned()) ts << "rp ";
1529     if (isPositioned()) ts << "ps ";
1530     if (needsLayout()) ts << "nl ";
1531     if (m_recalcMinMax) ts << "rmm ";
1532     if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
1533     if (element() && element()->active()) ts << "act ";
1534     if (element() && element()->isLink()) ts << "anchor ";
1535     if (element() && element()->focused()) ts << "focus ";
1536     if (element()) ts << " <" <<  element()->localName().qstring() << ">";
1537     ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
1538         << (isTableCell() ?
1539             ( QString::fromLatin1(" [r=") +
1540               QString::number( static_cast<const RenderTableCell *>(this)->row() ) +
1541               QString::fromLatin1(" c=") +
1542               QString::number( static_cast<const RenderTableCell *>(this)->col() ) +
1543               QString::fromLatin1(" rs=") +
1544               QString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
1545               QString::fromLatin1(" cs=") +
1546               QString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
1547               QString::fromLatin1("]") ) : QString::null );
1548         return str;
1549 }
1550
1551 void RenderObject::dump(QTextStream *stream, QString ind) const
1552 {
1553     if (isAnonymous()) { *stream << " anonymous"; }
1554     if (isFloating()) { *stream << " floating"; }
1555     if (isPositioned()) { *stream << " positioned"; }
1556     if (isRelPositioned()) { *stream << " relPositioned"; }
1557     if (isText()) { *stream << " text"; }
1558     if (isInline()) { *stream << " inline"; }
1559     if (isReplaced()) { *stream << " replaced"; }
1560     if (shouldPaintBackgroundOrBorder()) { *stream << " paintBackground"; }
1561     if (needsLayout()) { *stream << " needsLayout"; }
1562     if (minMaxKnown()) { *stream << " minMaxKnown"; }
1563     *stream << endl;
1564
1565     RenderObject *child = firstChild();
1566     while( child != 0 )
1567     {
1568         *stream << ind << child->renderName() << ": ";
1569         child->dump(stream,ind+"  ");
1570         child = child->nextSibling();
1571     }
1572 }
1573
1574 void RenderObject::showTree() const
1575 {
1576     if (element())
1577         element()->showTree();
1578 }
1579
1580 void showTree(const RenderObject *ro)
1581 {
1582     if (ro)
1583         ro->showTree();
1584 }
1585 #endif
1586
1587 static NodeImpl *selectStartNode(const RenderObject *object)
1588 {
1589     DOM::NodeImpl *node = 0;
1590     bool forcedOn = false;
1591
1592     for (const RenderObject *curr = object; curr; curr = curr->parent()) {
1593         if (curr->style()->userSelect() == SELECT_TEXT)
1594             forcedOn = true;
1595         if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
1596             return 0;
1597
1598         if (!node)
1599             node = curr->element();
1600     }
1601
1602     // somewhere up the render tree there must be an element!
1603     ASSERT(node);
1604
1605     return node;
1606 }
1607
1608 bool RenderObject::canSelect() const
1609 {
1610     return selectStartNode(this) != 0;
1611 }
1612
1613 bool RenderObject::shouldSelect() const
1614 {
1615     NodeImpl *node = selectStartNode(this);
1616     if (!node)
1617         return false;
1618     return node->dispatchHTMLEvent(selectstartEvent, true, true);
1619 }
1620
1621 Color RenderObject::selectionColor(GraphicsContext* p) const
1622 {
1623     Color color;
1624     if (style()->userSelect() != SELECT_NONE) {
1625         RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1626         if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
1627             color = pseudoStyle->backgroundColor();
1628         else
1629             color = p->selectedTextBackgroundColor();
1630     }
1631
1632     return color;
1633 }
1634
1635 DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
1636 {
1637     if (!dhtmlOK && !uaOK)
1638         return 0;
1639
1640     const RenderObject* curr = this;
1641     while (curr) {
1642         DOM::NodeImpl *elt = curr->element();
1643         if (elt && elt->nodeType() == NodeImpl::TEXT_NODE) {
1644             // Since there's no way for the author to address the -khtml-user-drag style for a text node,
1645             // we use our own judgement.
1646             if (uaOK && canvas()->view()->frame()->shouldDragAutoNode(curr->node(), x, y)) {
1647                 dhtmlWillDrag = false;
1648                 return curr->node();
1649             } else if (curr->shouldSelect()) {
1650                 // In this case we have a click in the unselected portion of text.  If this text is
1651                 // selectable, we want to start the selection process instead of looking for a parent
1652                 // to try to drag.
1653                 return 0;
1654             }
1655         } else {
1656             EUserDrag dragMode = curr->style()->userDrag();
1657             if (dhtmlOK && dragMode == DRAG_ELEMENT) {
1658                 dhtmlWillDrag = true;
1659                 return curr->node();
1660             } else if (uaOK && dragMode == DRAG_AUTO
1661                        && canvas()->view()->frame()->shouldDragAutoNode(curr->node(), x, y))
1662             {
1663                 dhtmlWillDrag = false;
1664                 return curr->node();
1665             }
1666         }
1667         curr = curr->parent();
1668     }
1669     return 0;
1670 }
1671
1672 void RenderObject::selectionStartEnd(int& spos, int& epos)
1673 {
1674     canvas()->selectionStartEnd(spos, epos);
1675 }
1676
1677 RenderBlock* RenderObject::createAnonymousBlock()
1678 {
1679     RenderStyle *newStyle = new (renderArena()) RenderStyle();
1680     newStyle->inheritFrom(m_style);
1681     newStyle->setDisplay(BLOCK);
1682
1683     RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
1684     newBox->setStyle(newStyle);
1685     return newBox;
1686 }
1687
1688 void RenderObject::handleDynamicFloatPositionChange()
1689 {
1690     // We have gone from not affecting the inline status of the parent flow to suddenly
1691     // having an impact.  See if there is a mismatch between the parent flow's
1692     // childrenInline() state and our state.
1693     setInline(style()->isDisplayInlineType());
1694     if (isInline() != parent()->childrenInline()) {
1695         if (!isInline()) {
1696             if (parent()->isRenderInline()) {
1697                 // We have to split the parent flow.
1698                 RenderInline* parentInline = static_cast<RenderInline*>(parent());
1699                 RenderBlock* newBox = parentInline->createAnonymousBlock();
1700                 
1701                 RenderFlow* oldContinuation = parent()->continuation();
1702                 parentInline->setContinuation(newBox);
1703
1704                 RenderObject* beforeChild = nextSibling();
1705                 parent()->removeChildNode(this);
1706                 parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
1707             }
1708             else if (parent()->isRenderBlock())
1709                 static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
1710         }
1711         else {
1712             // An anonymous block must be made to wrap this inline.
1713             RenderBlock* box = createAnonymousBlock();
1714             parent()->insertChildNode(box, this);
1715             box->appendChildNode(parent()->removeChildNode(this));
1716         }
1717     }
1718 }
1719
1720 void RenderObject::setStyle(RenderStyle *style)
1721 {
1722     if (m_style == style)
1723         return;
1724
1725     bool affectsParentBlock = false;
1726     RenderStyle::Diff d = RenderStyle::Equal;
1727     if (m_style) {
1728         // If our z-index changes value or our visibility changes,
1729         // we need to dirty our stacking context's z-order list.
1730         if (style) {
1731 #if __APPLE__
1732             if (m_style->visibility() != style->visibility() ||
1733                 m_style->zIndex() != style->zIndex() ||
1734                 m_style->hasAutoZIndex() != style->hasAutoZIndex())
1735                 document()->setDashboardRegionsDirty(true);
1736 #endif
1737
1738             if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1739                  m_style->zIndex() != style->zIndex() ||
1740                  m_style->visibility() != style->visibility()) && layer()) {
1741                 layer()->stackingContext()->dirtyZOrderLists();
1742                 if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1743                     m_style->visibility() != style->visibility())
1744                     layer()->dirtyZOrderLists();
1745             }
1746         }
1747
1748         d = m_style->diff(style);
1749
1750         // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
1751         if (d == RenderStyle::RepaintLayer && !layer())
1752             d = RenderStyle::Repaint;
1753         
1754         // The background of the root element or the body element could propagate up to
1755         // the canvas.  Just dirty the entire canvas when our style changes substantially.
1756         if (d >= RenderStyle::Repaint && element() &&
1757             (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
1758             canvas()->repaint();
1759         else if (m_parent && !isText()) {
1760             // Do a repaint with the old style first, e.g., for example if we go from
1761             // having an outline to not having an outline.
1762             if (d == RenderStyle::RepaintLayer) {
1763                 layer()->repaintIncludingDescendants();
1764                 if (!(m_style->clip() == style->clip()))
1765                     layer()->clearClipRects();
1766             }
1767             else if (d == RenderStyle::Repaint)
1768                 repaint();
1769         }
1770
1771         // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
1772         // end up being destroyed.
1773         if (d == RenderStyle::Layout && layer() &&
1774             (m_style->position() != style->position() ||
1775              m_style->zIndex() != style->zIndex() ||
1776              m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1777              !(m_style->clip() == style->clip()) ||
1778              m_style->hasClip() != style->hasClip() ||
1779              m_style->opacity() != style->opacity()))
1780             layer()->repaintIncludingDescendants();
1781
1782         // When a layout hint happens and an object's position style changes, we have to do a layout
1783         // to dirty the render tree using the old position value now.
1784         if (d == RenderStyle::Layout && m_parent && m_style->position() != style->position())
1785             markContainingBlocksForLayout();
1786         
1787         if (isFloating() && (m_style->floating() != style->floating()))
1788             // For changes in float styles, we need to conceivably remove ourselves
1789             // from the floating objects list.
1790             removeFromObjectLists();
1791         else if (isPositioned() && (style->position() != AbsolutePosition && style->position() != FixedPosition))
1792             // For changes in positioning styles, we need to conceivably remove ourselves
1793             // from the positioned objects list.
1794             removeFromObjectLists();
1795         
1796         affectsParentBlock = m_style && isFloatingOrPositioned() &&
1797             (!style->isFloating() && style->position() != AbsolutePosition && style->position() != FixedPosition)
1798             && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
1799         
1800         // reset style flags
1801         m_floating = false;
1802         m_positioned = false;
1803         m_relPositioned = false;
1804         m_paintBackground = false;
1805         m_hasOverflowClip = false;
1806     }
1807
1808     RenderStyle *oldStyle = m_style;
1809     m_style = style;
1810
1811     updateBackgroundImages(oldStyle);
1812     
1813     if (m_style)
1814         m_style->ref();
1815     
1816     if (oldStyle)
1817         oldStyle->deref(renderArena());
1818
1819     setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance());
1820
1821     if (affectsParentBlock)
1822         handleDynamicFloatPositionChange();
1823     
1824     // No need to ever schedule repaints from a style change of a text run, since
1825     // we already did this for the parent of the text run.
1826     if (d == RenderStyle::Layout && m_parent)
1827         setNeedsLayoutAndMinMaxRecalc();
1828     else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
1829         // Do a repaint with the new style now, e.g., for example if we go from
1830         // not having an outline to having an outline.
1831         repaint();
1832 }
1833
1834 void RenderObject::setStyleInternal(RenderStyle* st)
1835 {
1836     if (m_style == st)
1837         return;
1838     if (m_style)
1839         m_style->deref(renderArena());
1840     m_style = st;
1841     if (m_style)
1842         m_style->ref();
1843 }
1844
1845 void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
1846 {
1847     // FIXME: This will be slow when a large number of images is used.  Fix by using a dict.
1848     const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
1849     const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
1850     for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
1851         if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
1852             currOld->backgroundImage()->deref(this);
1853     }
1854     for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
1855         if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
1856             currNew->backgroundImage()->ref(this);
1857     }
1858     
1859     CachedImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
1860     CachedImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
1861     if (oldBorderImage != newBorderImage) {
1862         if (oldBorderImage)
1863             oldBorderImage->deref(this);
1864         if (newBorderImage)
1865             newBorderImage->ref(this);
1866     }
1867 }
1868
1869 IntRect RenderObject::viewRect() const
1870 {
1871     return canvas()->viewRect();
1872 }
1873
1874 bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
1875 {
1876     RenderObject* o = parent();
1877     if (o) {
1878         o->absolutePosition(xPos, yPos, f);
1879         yPos += o->borderTopExtra();
1880         if (o->hasOverflowClip())
1881             o->layer()->subtractScrollOffset(xPos, yPos); 
1882         return true;
1883     }
1884     else
1885     {
1886         xPos = yPos = 0;
1887         return false;
1888     }
1889 }
1890
1891 IntRect RenderObject::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
1892 {
1893    if (extraWidthToEndOfLine)
1894        *extraWidthToEndOfLine = 0;
1895
1896     return IntRect();
1897 }
1898
1899 int RenderObject::paddingTop() const
1900 {
1901     int w = 0;
1902     Length padding = m_style->paddingTop();
1903     if (padding.isPercent())
1904         w = containingBlock()->contentWidth();
1905     w = padding.calcMinValue(w);
1906     if ( isTableCell() && padding.isAuto() )
1907         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1908     return w;
1909 }
1910
1911 int RenderObject::paddingBottom() const
1912 {
1913     int w = 0;
1914     Length padding = style()->paddingBottom();
1915     if (padding.isPercent())
1916         w = containingBlock()->contentWidth();
1917     w = padding.calcMinValue(w);
1918     if ( isTableCell() && padding.isAuto() )
1919         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1920     return w;
1921 }
1922
1923 int RenderObject::paddingLeft() const
1924 {
1925     int w = 0;
1926     Length padding = style()->paddingLeft();
1927     if (padding.isPercent())
1928         w = containingBlock()->contentWidth();
1929     w = padding.calcMinValue(w);
1930     if ( isTableCell() && padding.isAuto() )
1931         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1932     return w;
1933 }
1934
1935 int RenderObject::paddingRight() const
1936 {
1937     int w = 0;
1938     Length padding = style()->paddingRight();
1939     if (padding.isPercent())
1940         w = containingBlock()->contentWidth();
1941     w = padding.calcMinValue(w);
1942     if ( isTableCell() && padding.isAuto() )
1943         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1944     return w;
1945 }
1946
1947 int RenderObject::tabWidth() const
1948 {
1949     if (style()->collapseWhiteSpace())
1950         return 0;
1951         
1952     return containingBlock()->tabWidth(true);
1953 }
1954
1955 RenderCanvas* RenderObject::canvas() const
1956 {
1957     return static_cast<RenderCanvas*>(document()->renderer());
1958 }
1959
1960 RenderObject *RenderObject::container() const
1961 {
1962     // This method is extremely similar to containingBlock(), but with a few notable
1963     // exceptions.
1964     // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
1965     // the object is not part of the primary document subtree yet.
1966     // (2) For normal flow elements, it just returns the parent.
1967     // (3) For absolute positioned elements, it will return a relative positioned inline.
1968     // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
1969     // the layout of the positioned object.  This does mean that calcAbsoluteHorizontal and
1970     // calcAbsoluteVertical have to use container().
1971     EPosition pos = m_style->position();
1972     RenderObject *o = 0;
1973     if (!isText() && pos == FixedPosition) {
1974         // container() can be called on an object that is not in the
1975         // tree yet.  We don't call canvas() since it will assert if it
1976         // can't get back to the canvas.  Instead we just walk as high up
1977         // as we can.  If we're in the tree, we'll get the root.  If we
1978         // aren't we'll get the root of our little subtree (most likely
1979         // we'll just return 0).
1980         o = parent();
1981         while (o && o->parent()) o = o->parent();
1982     }
1983     else if (!isText() && pos == AbsolutePosition) {
1984         // Same goes here.  We technically just want our containing block, but
1985         // we may not have one if we're part of an uninstalled subtree.  We'll
1986         // climb as high as we can though.
1987         o = parent();
1988         while (o && o->style()->position() == StaticPosition && !o->isRoot() && !o->isCanvas())
1989             o = o->parent();
1990     }
1991     else
1992         o = parent();
1993     return o;
1994 }
1995
1996 // This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
1997 // content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.
1998 RenderObject* RenderObject::hoverAncestor() const
1999 {
2000     return (!isInline() && continuation()) ? continuation() : parent();
2001 }
2002
2003 bool RenderObject::isSelectionBorder() const
2004 {
2005     SelectionState st = selectionState();
2006     return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
2007 }
2008
2009
2010 void RenderObject::removeFromObjectLists()
2011 {
2012     if (isFloating()) {
2013         RenderBlock* outermostBlock = containingBlock();
2014         for (RenderBlock* p = outermostBlock; p && !p->isCanvas(); p = p->containingBlock()) {
2015             if (p->containsFloat(this))
2016                 outermostBlock = p;
2017         }
2018         
2019         if (outermostBlock)
2020             outermostBlock->markAllDescendantsWithFloatsForLayout(this);
2021     }
2022
2023     if (isPositioned()) {
2024         RenderObject *p;
2025         for (p = parent(); p; p = p->parent()) {
2026             if (p->isRenderBlock())
2027                 static_cast<RenderBlock*>(p)->removePositionedObject(this);
2028         }
2029     }
2030 }
2031
2032 RenderArena* RenderObject::renderArena() const
2033 {
2034     DOM::DocumentImpl* doc = document();
2035     return doc ? doc->renderArena() : 0;
2036 }
2037
2038 void RenderObject::remove()
2039 {
2040 #if __APPLE__
2041     // Delete our accessibility object if we have one.
2042     document()->getAccObjectCache()->detach(this);
2043 #endif
2044
2045     removeFromObjectLists();
2046
2047     if (parent())
2048         //have parent, take care of the tree integrity
2049         parent()->removeChild(this);
2050     
2051     deleteLineBoxWrapper();
2052 }
2053
2054 bool RenderObject::documentBeingDestroyed() const
2055 {
2056     return !document()->renderer();
2057 }
2058
2059 void RenderObject::destroy()
2060 {
2061     // By default no ref-counting. RenderWidget::destroy() doesn't call
2062     // this function because it needs to do ref-counting. If anything
2063     // in this function changes, be sure to fix RenderWidget::destroy() as well. 
2064
2065     remove();
2066     
2067     arenaDelete(document()->renderArena(), this);
2068 }
2069
2070 void RenderObject::arenaDelete(RenderArena *arena, void *base)
2071 {
2072     if (m_style->backgroundImage())
2073         m_style->backgroundImage()->deref(this);
2074     if (m_style)
2075         m_style->deref(arena);
2076     
2077 #ifndef NDEBUG
2078     void *savedBase = baseOfRenderObjectBeingDeleted;
2079     baseOfRenderObjectBeingDeleted = base;
2080 #endif
2081     delete this;
2082 #ifndef NDEBUG
2083     baseOfRenderObjectBeingDeleted = savedBase;
2084 #endif
2085     
2086     // Recover the size left there for us by operator delete and free the memory.
2087     arena->free(*(size_t *)base, base);
2088 }
2089
2090 VisiblePosition RenderObject::positionForCoordinates(int x, int y)
2091 {
2092     return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
2093 }
2094
2095 bool RenderObject::isDragging() const
2096
2097     return m_isDragging; 
2098 }
2099
2100 void RenderObject::updateDragState(bool dragOn)
2101 {
2102     bool valueChanged = (dragOn != m_isDragging);
2103     m_isDragging = dragOn;
2104     if (valueChanged && style()->affectedByDragRules())
2105         element()->setChanged();
2106     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2107         curr->updateDragState(dragOn);
2108     if (continuation())
2109         continuation()->updateDragState(dragOn);
2110 }
2111
2112 bool RenderObject::hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
2113 {
2114     bool inside = false;
2115     if (hitTestFilter != HitTestSelf) {
2116         // First test the foreground layer (lines and inlines).
2117         inside = nodeAtPoint(info, x, y, tx, ty, HitTestForeground);
2118         
2119         // Test floats next.
2120         if (!inside)
2121             inside = nodeAtPoint(info, x, y, tx, ty, HitTestFloat);
2122
2123         // Finally test to see if the mouse is in the background (within a child block's background).
2124         if (!inside)
2125             inside = nodeAtPoint(info, x, y, tx, ty, HitTestChildBlockBackgrounds);
2126     }
2127     
2128     // See if the mouse is inside us but not any of our descendants
2129     if (hitTestFilter != HitTestDescendants && !inside)
2130         inside = nodeAtPoint(info, x, y, tx, ty, HitTestBlockBackground);
2131         
2132     return inside;
2133 }
2134
2135 void RenderObject::setInnerNode(NodeInfo& info)
2136 {
2137     if (!info.innerNode() && !isInline() && continuation()) {
2138         // We are in the margins of block elements that are part of a continuation.  In
2139         // this case we're actually still inside the enclosing inline element that was
2140         // split.  Go ahead and set our inner node accordingly.
2141         info.setInnerNode(continuation()->element());
2142         if (!info.innerNonSharedNode())
2143             info.setInnerNonSharedNode(continuation()->element());
2144     }
2145
2146     if (!info.innerNode() && element())
2147         info.setInnerNode(element());
2148             
2149     if(!info.innerNonSharedNode() && element())
2150         info.setInnerNonSharedNode(element());
2151 }
2152
2153 bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
2154                                HitTestAction hitTestAction)
2155 {
2156     return false;
2157 }
2158
2159 short RenderObject::verticalPositionHint( bool firstLine ) const
2160 {
2161     short vpos = m_verticalPosition;
2162     if ( m_verticalPosition == PositionUndefined || firstLine ) {
2163         vpos = getVerticalPosition( firstLine );
2164         if ( !firstLine )
2165             m_verticalPosition = vpos;
2166     }
2167     return vpos;
2168
2169 }
2170
2171 short RenderObject::getVerticalPosition( bool firstLine ) const
2172 {
2173     if (!isInline())
2174         return 0;
2175
2176     // This method determines the vertical position for inline elements.
2177     int vpos = 0;
2178     EVerticalAlign va = style()->verticalAlign();
2179     if ( va == TOP ) {
2180         vpos = PositionTop;
2181     } else if ( va == BOTTOM ) {
2182         vpos = PositionBottom;
2183     } else if ( va == LENGTH ) {
2184         vpos = -style()->verticalAlignLength().calcValue( lineHeight( firstLine ) );
2185     } else  {
2186         bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
2187         vpos = checkParent ? parent()->verticalPositionHint( firstLine ) : 0;
2188         // don't allow elements nested inside text-top to have a different valignment.
2189         if ( va == BASELINE )
2190             return vpos;
2191
2192         const Font &f = parent()->font(firstLine);
2193         int fontsize = f.pixelSize();
2194     
2195         if (va == SUB)
2196             vpos += fontsize/5 + 1;
2197         else if (va == SUPER)
2198             vpos -= fontsize/3 + 1;
2199         else if (va == TEXT_TOP)
2200             vpos += baselinePosition(firstLine) - f.ascent();
2201         else if (va == MIDDLE)
2202             vpos += - (int)(f.xHeight()/2) - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2203         else if (va == TEXT_BOTTOM) {
2204             vpos += f.descent();
2205             if (!isReplaced())
2206                 vpos -= font(firstLine).descent();
2207         } else if ( va == BASELINE_MIDDLE )
2208             vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2209     }
2210     
2211     return vpos;
2212 }
2213
2214 short RenderObject::lineHeight( bool firstLine, bool ) const
2215 {
2216     RenderStyle* s = style(firstLine);
2217     
2218     Length lh = s->lineHeight();
2219
2220     // its "unset", choose nice default
2221     if (lh.value() < 0)
2222         return s->font().lineSpacing();
2223
2224     if (lh.isPercent())
2225         return lh.calcMinValue(s->fontSize());
2226
2227     // its fixed
2228     return lh.value();
2229 }
2230
2231 short RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
2232 {
2233     const Font& f = font(firstLine);
2234     return f.ascent() + (lineHeight(firstLine, isRootLineBox) - f.height()) / 2;
2235 }
2236
2237 void RenderObject::invalidateVerticalPositions()
2238 {
2239     m_verticalPosition = PositionUndefined;
2240     RenderObject *child = firstChild();
2241     while( child ) {
2242         child->invalidateVerticalPositions();
2243         child = child->nextSibling();
2244     }
2245 }
2246
2247 void RenderObject::recalcMinMaxWidths()
2248 {
2249     KHTMLAssert( m_recalcMinMax );
2250
2251 #ifdef DEBUG_LAYOUT
2252     kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
2253 #endif
2254
2255     if (m_recalcMinMax)
2256         updateFirstLetter();
2257     
2258     RenderObject *child = firstChild();
2259     while( child ) {
2260         int cmin = 0;
2261         int cmax = 0;
2262         bool test = false;
2263         if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
2264             cmin = child->minWidth();
2265             cmax = child->maxWidth();
2266             test = true;
2267         }
2268         if ( child->m_recalcMinMax )
2269             child->recalcMinMaxWidths();
2270         if ( !child->m_minMaxKnown )
2271             child->calcMinMaxWidth();
2272         if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
2273             m_minMaxKnown = false;
2274         child = child->nextSibling();
2275     }
2276
2277     // we need to recalculate, if the contains inline children, as the change could have
2278     // happened somewhere deep inside the child tree. Also do this for blocks or tables that
2279     // are inline (i.e., inline-block and inline-table).
2280     if ((!isInline() || isInlineBlockOrInlineTable()) && childrenInline())
2281         m_minMaxKnown = false;
2282
2283     if ( !m_minMaxKnown )
2284         calcMinMaxWidth();
2285     m_recalcMinMax = false;
2286 }
2287
2288 void RenderObject::scheduleRelayout()
2289 {
2290     if (!isCanvas()) return;
2291     FrameView *view = static_cast<RenderCanvas *>(this)->view();
2292     if (view)
2293         view->scheduleRelayout();
2294 }
2295
2296
2297 void RenderObject::removeLeftoverAnonymousBoxes()
2298 {
2299 }
2300
2301 InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
2302 {
2303     KHTMLAssert(!isRootLineBox);
2304     return new (renderArena()) InlineBox(this);
2305 }
2306
2307 void RenderObject::dirtyLineBoxes(bool, bool)
2308 {
2309 }
2310
2311 InlineBox* RenderObject::inlineBoxWrapper() const
2312 {
2313     return 0;
2314 }
2315
2316 void RenderObject::setInlineBoxWrapper(InlineBox* b)
2317 {
2318 }
2319
2320 void RenderObject::deleteLineBoxWrapper()
2321 {
2322 }
2323
2324 RenderStyle* RenderObject::firstLineStyle() const 
2325 {
2326     RenderStyle *s = m_style; 
2327     const RenderObject* obj = isText() ? parent() : this;
2328     if (obj->isBlockFlow()) {
2329         RenderBlock* firstLineBlock = obj->firstLineBlock();
2330         if (firstLineBlock)
2331             s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style());
2332     } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
2333         RenderStyle* parentStyle = obj->parent()->firstLineStyle();
2334         if (parentStyle != obj->parent()->style()) {
2335             // A first-line style is in effect. We need to cache a first-line style
2336             // for ourselves.
2337             style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
2338             s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
2339         }
2340     }
2341     return s;
2342 }
2343
2344 RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
2345 {
2346     if (!style()->hasPseudoStyle(pseudo))
2347         return 0;
2348     
2349     if (!parentStyle)
2350         parentStyle = style();
2351
2352     RenderStyle* result = style()->getPseudoStyle(pseudo);
2353     if (result) return result;
2354     
2355     DOM::NodeImpl* node = element();
2356     if (isText())
2357         node = element()->parentNode();
2358     if (!node) return 0;
2359     
2360     if (pseudo == RenderStyle::FIRST_LINE_INHERITED)
2361         result = document()->styleSelector()->styleForElement(static_cast<DOM::ElementImpl*>(node), 
2362                                                               parentStyle, false);
2363     else
2364         result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<DOM::ElementImpl*>(node), 
2365                                                                     parentStyle);
2366     if (result)
2367         style()->addPseudoStyle(result);
2368     return result;
2369 }
2370
2371 void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
2372                                            Color& linethrough, bool quirksMode)
2373 {
2374     RenderObject* curr = this;
2375     do {
2376         int currDecs = curr->style()->textDecoration();
2377         if (currDecs) {
2378             if (currDecs & UNDERLINE) {
2379                 decorations &= ~UNDERLINE;
2380                 underline = curr->style()->color();
2381             }
2382             if (currDecs & OVERLINE) {
2383                 decorations &= ~OVERLINE;
2384                 overline = curr->style()->color();
2385             }
2386             if (currDecs & LINE_THROUGH) {
2387                 decorations &= ~LINE_THROUGH;
2388                 linethrough = curr->style()->color();
2389             }
2390         }
2391         curr = curr->parent();
2392         if (curr && curr->isRenderBlock() && curr->continuation())
2393             curr = curr->continuation();
2394     } while (curr && decorations && (!quirksMode || !curr->element() ||
2395                                      (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
2396
2397     // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2398     if (decorations && curr) {
2399         if (decorations & UNDERLINE)
2400             underline = curr->style()->color();
2401         if (decorations & OVERLINE)
2402             overline = curr->style()->color();
2403         if (decorations & LINE_THROUGH)
2404             linethrough = curr->style()->color();
2405     }        
2406 }
2407
2408 void RenderObject::updateWidgetPosition()
2409 {
2410 }
2411
2412 QValueList<DashboardRegionValue> RenderObject::computeDashboardRegions()
2413 {
2414     QValueList<DashboardRegionValue> regions;
2415     collectDashboardRegions(regions);
2416     return regions;
2417 }
2418
2419 void RenderObject::addDashboardRegions (QValueList<DashboardRegionValue>& regions)
2420 {
2421     // Convert the style regions to absolute coordinates.
2422     if (style()->visibility() != VISIBLE) 
2423         return;
2424
2425     QValueList<StyleDashboardRegion> styleRegions = style()->dashboardRegions();
2426     if (styleRegions.count() > 0) {
2427         uint i, count = styleRegions.count();
2428         for (i = 0; i < count; i++){
2429             StyleDashboardRegion styleRegion = styleRegions[i];
2430             
2431             int w = width();
2432             int h = height();
2433             
2434             DashboardRegionValue region;
2435             region.label = styleRegion.label;
2436             region.bounds = IntRect (
2437                 styleRegion.offset.left.value(),
2438                 styleRegion.offset.top.value(),
2439                 w - styleRegion.offset.left.value() - styleRegion.offset.right.value(),
2440                 h - styleRegion.offset.top.value() - styleRegion.offset.bottom.value());
2441             region.type = styleRegion.type;
2442
2443             region.clip = region.bounds;
2444             computeAbsoluteRepaintRect(region.clip);
2445             if (region.clip.height() < 0) {
2446                 region.clip.setHeight(0);
2447                 region.clip.setWidth(0);
2448             }
2449
2450             int x, y;
2451             absolutePosition(x, y);
2452             region.bounds.setX(x + styleRegion.offset.left.value());
2453             region.bounds.setY(y + styleRegion.offset.top.value());
2454             
2455             regions.append(region);
2456         }
2457     }
2458 }
2459
2460 void RenderObject::collectDashboardRegions (QValueList<DashboardRegionValue>& regions)
2461 {
2462     // RenderTexts don't have their own style, they just use their parent's style,
2463     // so we don't want to include them.
2464     if (isText())
2465         return;
2466         
2467     addDashboardRegions (regions);
2468     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
2469         curr->collectDashboardRegions(regions);
2470     }
2471 }
2472
2473
2474 void RenderObject::collectBorders(QValueList<CollapsedBorderValue>& borderStyles)
2475 {
2476     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2477         curr->collectBorders(borderStyles);
2478 }
2479
2480 bool RenderObject::avoidsFloats() const
2481 {
2482     return isReplaced() || isTable() || hasOverflowClip() || isHR() || isFlexibleBox(); 
2483 }
2484
2485 bool RenderObject::usesLineWidth() const
2486 {
2487     // 1. All auto-width objects that avoid floats should always use lineWidth
2488     // 2. For objects with a specified width, we match WinIE's behavior:
2489     // (a) tables use contentWidth
2490     // (b) <hr>s use lineWidth
2491     // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
2492     return (avoidsFloats() && (style()->width().isAuto() || isHR() || (style()->htmlHacks() && !isTable())));
2493 }
2494
2495 QChar RenderObject::backslashAsCurrencySymbol() const
2496 {
2497     NodeImpl *node = element();
2498     if (!node)
2499         return '\\';
2500     DocumentImpl *document = node->getDocument();
2501     if (!document)
2502         return '\\';
2503     Decoder *decoder = document->decoder();
2504     if (!decoder)
2505         return '\\';
2506     return decoder->encoding().backslashAsCurrencySymbol();
2507 }
2508
2509 void RenderObject::imageChanged(CachedImage *image)
2510 {
2511     // Repaint when the background image or border image finishes loading.
2512     // This is needed for RenderBox objects, and also for table objects that hold
2513     // backgrounds that are then respected by the table cells (which are RenderBox
2514     // subclasses). It would be even better to find a more elegant way of doing this that
2515     // would avoid putting this function and the CachedObjectClient base class into RenderObject.
2516     if (image && image->canRender() && parent()) {
2517         if (canvas() && element() && (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
2518             canvas()->repaint();    // repaint the entire canvas since the background gets propagated up
2519         else
2520             repaint();              // repaint object, which is a box or a container with boxes inside it
2521     }
2522 }
2523
2524 bool RenderObject::willRenderImage(CachedImage*)
2525 {
2526     // Without visibility we won't render (and therefore don't care about animation).
2527     if (style()->visibility() != VISIBLE)
2528         return false;
2529
2530     // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
2531     // then we don't want to render either.
2532     return !document()->inPageCache() && document()->view()->inWindow();
2533 }
2534
2535 int RenderObject::maximalOutlineSize(PaintAction p) const
2536 {
2537     if (p != PaintActionOutline)
2538         return 0;
2539     return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();
2540 }
2541
2542 int RenderObject::caretMinOffset() const
2543 {
2544     return 0;
2545 }
2546
2547 int RenderObject::caretMaxOffset() const
2548 {
2549     return 0;
2550 }
2551
2552 unsigned RenderObject::caretMaxRenderedOffset() const
2553 {
2554     return 0;
2555 }
2556
2557 int RenderObject::previousOffset (int current) const
2558 {
2559     int previousOffset = current - 1;
2560     return previousOffset;
2561 }
2562
2563 int RenderObject::nextOffset (int current) const
2564 {
2565     int nextOffset = current + 1;
2566     return nextOffset;
2567 }
2568
2569 InlineBox *RenderObject::inlineBox(int offset, EAffinity affinity)
2570 {
2571     return inlineBoxWrapper();
2572 }
2573
2574 #if SVG_SUPPORT
2575
2576 FloatRect RenderObject::relativeBBox(bool) const
2577 {
2578     return FloatRect();
2579 }
2580
2581 QMatrix RenderObject::localTransform() const
2582 {
2583     return QMatrix(1, 0, 0, 1, xPos(), yPos());
2584 }
2585  
2586 void RenderObject::setLocalTransform(const QMatrix&)
2587 {
2588     ASSERT(false);
2589 }
2590
2591 QMatrix RenderObject::absoluteTransform() const
2592 {
2593     if (parent())
2594         return localTransform() * parent()->absoluteTransform();
2595     return localTransform();
2596 }
2597
2598 #endif
2599
2600 }