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