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