Patch written mostly by Ken Kraisler, but also by me.
[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 "Element.h"
37 #include "EventNames.h"
38 #include "FloatRect.h"
39 #include "Frame.h"
40 #include "GraphicsContext.h"
41 #include "HTMLNames.h"
42 #include "HTMLOListElement.h"
43 #include "KURL.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() const
549 {
550     const 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() || last->isTextArea()))
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::addPDFURLRect(GraphicsContext* p, IntRect rect)
1643 {
1644     Node* node = element();
1645     if (node) {
1646         if (p) {
1647             if (rect.width() > 0 && rect.height() > 0) {
1648                 Element* element = static_cast<Element*>(node);
1649                 String href;
1650                 if (element->isLink())
1651                     href = element->getAttribute(hrefAttr);
1652                     
1653                 if (!href.isNull()) {
1654                     KURL link = element->document()->completeURL(href.deprecatedString());
1655                     if (link.isValid())
1656                         p->setURLForRect(link, rect);
1657                 }
1658             }
1659         }
1660     }
1661 }
1662
1663
1664 void RenderObject::addFocusRingRects(GraphicsContext* p, int _tx, int _ty)
1665 {
1666     // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1667     // inline boxes above and below us (thus getting merged with them to form a single irregular
1668     // shape).
1669     if (continuation()) {
1670         p->addFocusRingRect(IntRect(_tx, _ty - collapsedMarginTop(), width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1671         continuation()->addFocusRingRects(p, 
1672                                           _tx - xPos() + continuation()->containingBlock()->xPos(),
1673                                           _ty - yPos() + continuation()->containingBlock()->yPos());
1674     }
1675     else
1676         p->addFocusRingRect(IntRect(_tx, _ty, width(), height()));
1677 }
1678
1679 void RenderObject::paintOutline(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1680 {
1681     if (!hasOutline())
1682         return;
1683     
1684     int ow = style->outlineWidth();
1685
1686     EBorderStyle os = style->outlineStyle();
1687     
1688     Color oc = style->outlineColor();
1689     if (!oc.isValid())
1690         oc = style->color();
1691     
1692     int offset = style->outlineOffset();
1693     
1694     if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) {
1695         if (!theme()->supportsFocusRing(style)) {
1696             // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
1697             p->initFocusRing(ow, offset);
1698             if (style->outlineStyleIsAuto())
1699                 addFocusRingRects(p, _tx, _ty);
1700             else
1701                 addPDFURLRect(p, p->focusRingBoundingRect());
1702             p->drawFocusRing(oc);
1703             p->clearFocusRing();
1704         }
1705     }
1706
1707     if (style->outlineStyleIsAuto() || style->outlineStyle() <= BHIDDEN)
1708         return;
1709
1710     _tx -= offset;
1711     _ty -= offset;
1712     w += 2*offset;
1713     h += 2*offset;
1714     
1715     drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
1716                Color(oc), style->color(),
1717                os, ow, ow);
1718
1719     drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
1720                Color(oc), style->color(),
1721                os, ow, ow);
1722
1723     drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
1724                Color(oc), style->color(),
1725                os, ow, ow);
1726
1727     drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
1728                Color(oc), style->color(),
1729                os, ow, ow);
1730
1731 }
1732
1733 void RenderObject::paint(PaintInfo& i, int tx, int ty)
1734 {
1735 }
1736
1737 void RenderObject::repaint(bool immediate)
1738 {
1739     // Can't use view(), since we might be unrooted.
1740     RenderObject* o = this;
1741     while ( o->parent() ) o = o->parent();
1742     if (!o->isRenderView())
1743         return;
1744     RenderView* c = static_cast<RenderView*>(o);
1745     if (c->printingMode())
1746         return; // Don't repaint if we're printing.
1747     c->repaintViewRectangle(getAbsoluteRepaintRect(), immediate);    
1748 }
1749
1750 void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
1751 {
1752     // Can't use view(), since we might be unrooted.
1753     RenderObject* o = this;
1754     while ( o->parent() ) o = o->parent();
1755     if (!o->isRenderView())
1756         return;
1757     RenderView* c = static_cast<RenderView*>(o);
1758     if (c->printingMode())
1759         return; // Don't repaint if we're printing.
1760     IntRect absRect(r);
1761     computeAbsoluteRepaintRect(absRect);
1762     c->repaintViewRectangle(absRect, immediate);
1763 }
1764
1765 bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldFullBounds)
1766 {
1767     RenderView* c = view();
1768     if (c->printingMode())
1769         return false; // Don't repaint if we're printing.
1770             
1771     IntRect newBounds, newFullBounds;
1772     getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
1773     if (newBounds == oldBounds && !selfNeedsLayout())
1774         return false;
1775
1776     bool fullRepaint = selfNeedsLayout() || newBounds.location() != oldBounds.location() || mustRepaintBackgroundOrBorder();
1777     if (fullRepaint) {
1778         c->repaintViewRectangle(oldFullBounds);
1779         if (newBounds != oldBounds)
1780             c->repaintViewRectangle(newFullBounds);
1781         return true;
1782     }
1783
1784     // We didn't move, but we did change size.  Invalidate the delta, which will consist of possibly 
1785     // two rectangles (but typically only one).
1786     int ow = style() ? style()->outlineSize() : 0;
1787     int width = abs(newBounds.width() - oldBounds.width());
1788     if (width)
1789         c->repaintViewRectangle(IntRect(min(newBounds.x() + newBounds.width(), oldBounds.x() + oldBounds.width()) - borderRight() - ow,
1790             newBounds.y(),
1791             width + borderRight() + ow,
1792             max(newBounds.height(), oldBounds.height())));
1793     int height = abs(newBounds.height() - oldBounds.height());
1794     if (height)
1795         c->repaintViewRectangle(IntRect(newBounds.x(),
1796             min(newBounds.bottom(), oldBounds.bottom()) - borderBottom() - ow,
1797             max(newBounds.width(), oldBounds.width()),
1798             height + borderBottom() + ow));
1799     return false;
1800 }
1801
1802 void RenderObject::repaintDuringLayoutIfMoved(int x, int y)
1803 {
1804 }
1805
1806 void RenderObject::repaintOverhangingFloats(bool paintAllDescendants)
1807 {
1808 }
1809
1810 bool RenderObject::checkForRepaintDuringLayout() const
1811 {
1812     return !document()->view()->needsFullRepaint() && !layer();
1813 }
1814
1815 void RenderObject::repaintObjectsBeforeLayout()
1816 {
1817     if (!needsLayout() || isText())
1818         return;
1819     
1820     bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
1821     if (selfNeedsLayout()) {
1822         repaint();
1823         if (blockWithInlineChildren)
1824             return;
1825     }
1826
1827     for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1828         if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
1829             current->repaintObjectsBeforeLayout();
1830     }
1831 }
1832
1833 IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
1834 {
1835     IntRect r(getAbsoluteRepaintRect());
1836     r.inflate(ow);
1837
1838     if (continuation() && !isInline())
1839         r.inflateY(collapsedMarginTop());
1840     
1841     if (isInlineFlow())
1842         for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
1843             if (!curr->isText())
1844                 r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
1845
1846     return r;
1847 }
1848
1849 IntRect RenderObject::getAbsoluteRepaintRect()
1850 {
1851     if (parent())
1852         return parent()->getAbsoluteRepaintRect();
1853     return IntRect();
1854 }
1855
1856 void RenderObject::getAbsoluteRepaintRectIncludingFloats(IntRect& bounds, IntRect& fullBounds)
1857 {
1858     bounds = fullBounds = getAbsoluteRepaintRect();
1859 }
1860
1861 void RenderObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
1862 {
1863     if (parent())
1864         return parent()->computeAbsoluteRepaintRect(r, f);
1865 }
1866
1867 void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
1868 {
1869 }
1870
1871 #ifndef NDEBUG
1872
1873 DeprecatedString RenderObject::information() const
1874 {
1875     DeprecatedString str;
1876     TextStream ts(&str);
1877     ts << renderName()
1878         << "(" << (style() ? style()->refCount() : 0) << ")"
1879        << ": " << (void*)this << "  ";
1880     if (isInline()) ts << "il ";
1881     if (childrenInline()) ts << "ci ";
1882     if (isFloating()) ts << "fl ";
1883     if (isAnonymous()) ts << "an ";
1884     if (isRelPositioned()) ts << "rp ";
1885     if (isPositioned()) ts << "ps ";
1886     if (needsLayout()) ts << "nl ";
1887     if (m_recalcMinMax) ts << "rmm ";
1888     if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
1889     if (element()) {
1890         if (element()->active())
1891             ts << "act ";
1892         if (element()->isLink())
1893             ts << "anchor ";
1894         if (element()->focused())
1895             ts << "focus ";
1896         ts << " <" <<  element()->localName().deprecatedString() << ">";
1897         ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")";
1898         if (isTableCell()) {
1899             const RenderTableCell* cell = static_cast<const RenderTableCell *>(this);
1900             ts << " [r=" << cell->row() << " c=" << cell->col() << " rs=" << cell->rowSpan() << " cs=" << cell->colSpan() << "]";
1901         }
1902     }
1903     return str;
1904 }
1905
1906 void RenderObject::dump(TextStream *stream, DeprecatedString ind) const
1907 {
1908     if (isAnonymous()) { *stream << " anonymous"; }
1909     if (isFloating()) { *stream << " floating"; }
1910     if (isPositioned()) { *stream << " positioned"; }
1911     if (isRelPositioned()) { *stream << " relPositioned"; }
1912     if (isText()) { *stream << " text"; }
1913     if (isInline()) { *stream << " inline"; }
1914     if (isReplaced()) { *stream << " replaced"; }
1915     if (shouldPaintBackgroundOrBorder()) { *stream << " paintBackground"; }
1916     if (needsLayout()) { *stream << " needsLayout"; }
1917     if (minMaxKnown()) { *stream << " minMaxKnown"; }
1918     *stream << endl;
1919
1920     RenderObject *child = firstChild();
1921     while( child != 0 )
1922     {
1923         *stream << ind << child->renderName() << ": ";
1924         child->dump(stream,ind+"  ");
1925         child = child->nextSibling();
1926     }
1927 }
1928
1929 void RenderObject::showTreeForThis() const
1930 {
1931     if (element())
1932         element()->showTreeForThis();
1933 }
1934
1935 #endif
1936
1937 static Node *selectStartNode(const RenderObject *object)
1938 {
1939     Node *node = 0;
1940     bool forcedOn = false;
1941
1942     for (const RenderObject *curr = object; curr; curr = curr->parent()) {
1943         if (curr->style()->userSelect() == SELECT_TEXT)
1944             forcedOn = true;
1945         if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
1946             return 0;
1947
1948         if (!node)
1949             node = curr->element();
1950     }
1951
1952     // somewhere up the render tree there must be an element!
1953     ASSERT(node);
1954
1955     return node;
1956 }
1957
1958 bool RenderObject::canSelect() const
1959 {
1960     return selectStartNode(this) != 0;
1961 }
1962
1963 bool RenderObject::shouldSelect() const
1964 {
1965     if (Node *node = selectStartNode(this))
1966         return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
1967
1968     return false;
1969 }
1970
1971 Color RenderObject::selectionBackgroundColor() const
1972 {
1973     Color color;
1974     if (style()->userSelect() != SELECT_NONE) {
1975         RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1976         if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
1977             color = pseudoStyle->backgroundColor().blendWithWhite();
1978         else
1979             color = document()->frame()->isActive() ?
1980                     theme()->activeSelectionBackgroundColor() :
1981                     theme()->inactiveSelectionBackgroundColor();
1982     }
1983
1984     return color;
1985 }
1986
1987 Color RenderObject::selectionForegroundColor() const
1988 {
1989     Color color;
1990     if (style()->userSelect() != SELECT_NONE) {
1991         RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1992         if (pseudoStyle)
1993             color = pseudoStyle->color();
1994         else
1995             color = document()->frame()->isActive() ?
1996                     theme()->platformActiveSelectionForegroundColor() :
1997                     theme()->platformInactiveSelectionForegroundColor();
1998     }
1999
2000     return color;
2001 }
2002
2003 Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
2004 {
2005     if (!dhtmlOK && !uaOK)
2006         return 0;
2007
2008     const RenderObject* curr = this;
2009     while (curr) {
2010         Node *elt = curr->element();
2011         if (elt && elt->nodeType() == Node::TEXT_NODE) {
2012             // Since there's no way for the author to address the -webkit-user-drag style for a text node,
2013             // we use our own judgement.
2014             if (uaOK && view()->frameView()->frame()->shouldDragAutoNode(curr->node(), IntPoint(x, y))) {
2015                 dhtmlWillDrag = false;
2016                 return curr->node();
2017             } else if (curr->shouldSelect()) {
2018                 // In this case we have a click in the unselected portion of text.  If this text is
2019                 // selectable, we want to start the selection process instead of looking for a parent
2020                 // to try to drag.
2021                 return 0;
2022             }
2023         } else {
2024             EUserDrag dragMode = curr->style()->userDrag();
2025             if (dhtmlOK && dragMode == DRAG_ELEMENT) {
2026                 dhtmlWillDrag = true;
2027                 return curr->node();
2028             } else if (uaOK && dragMode == DRAG_AUTO
2029                        && view()->frameView()->frame()->shouldDragAutoNode(curr->node(), IntPoint(x, y)))
2030             {
2031                 dhtmlWillDrag = false;
2032                 return curr->node();
2033             }
2034         }
2035         curr = curr->parent();
2036     }
2037     return 0;
2038 }
2039
2040 void RenderObject::selectionStartEnd(int& spos, int& epos)
2041 {
2042     view()->selectionStartEnd(spos, epos);
2043 }
2044
2045 RenderBlock* RenderObject::createAnonymousBlock()
2046 {
2047     RenderStyle *newStyle = new (renderArena()) RenderStyle();
2048     newStyle->inheritFrom(m_style);
2049     newStyle->setDisplay(BLOCK);
2050
2051     RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
2052     newBox->setStyle(newStyle);
2053     return newBox;
2054 }
2055
2056 void RenderObject::handleDynamicFloatPositionChange()
2057 {
2058     // We have gone from not affecting the inline status of the parent flow to suddenly
2059     // having an impact.  See if there is a mismatch between the parent flow's
2060     // childrenInline() state and our state.
2061     setInline(style()->isDisplayInlineType());
2062     if (isInline() != parent()->childrenInline()) {
2063         if (!isInline()) {
2064             if (parent()->isRenderInline()) {
2065                 // We have to split the parent flow.
2066                 RenderInline* parentInline = static_cast<RenderInline*>(parent());
2067                 RenderBlock* newBox = parentInline->createAnonymousBlock();
2068                 
2069                 RenderFlow* oldContinuation = parent()->continuation();
2070                 parentInline->setContinuation(newBox);
2071
2072                 RenderObject* beforeChild = nextSibling();
2073                 parent()->removeChildNode(this);
2074                 parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
2075             }
2076             else if (parent()->isRenderBlock())
2077                 static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
2078         }
2079         else {
2080             // An anonymous block must be made to wrap this inline.
2081             RenderBlock* box = createAnonymousBlock();
2082             parent()->insertChildNode(box, this);
2083             box->appendChildNode(parent()->removeChildNode(this));
2084         }
2085     }
2086 }
2087
2088 void RenderObject::setStyle(RenderStyle *style)
2089 {
2090     if (m_style == style)
2091         return;
2092
2093     bool affectsParentBlock = false;
2094     RenderStyle::Diff d = RenderStyle::Equal;
2095     if (m_style) {
2096         // If our z-index changes value or our visibility changes,
2097         // we need to dirty our stacking context's z-order list.
2098         if (style) {
2099 #if __APPLE__
2100             if (m_style->visibility() != style->visibility() ||
2101                 m_style->zIndex() != style->zIndex() ||
2102                 m_style->hasAutoZIndex() != style->hasAutoZIndex())
2103                 document()->setDashboardRegionsDirty(true);
2104 #endif
2105
2106             if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2107                  m_style->zIndex() != style->zIndex() ||
2108                  m_style->visibility() != style->visibility()) && layer()) {
2109                 layer()->stackingContext()->dirtyZOrderLists();
2110                 if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2111                     m_style->visibility() != style->visibility())
2112                     layer()->dirtyZOrderLists();
2113             }
2114             // keep layer hierarchy visibility bits up to date if visibility changes
2115             if (m_style->visibility() != style->visibility()) {
2116                 RenderLayer* l = enclosingLayer(); 
2117                 if (style->visibility() == VISIBLE && l)
2118                     l->setHasVisibleContent(true);
2119                 else if (l && l->hasVisibleContent() && 
2120                     (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE))
2121                     l->dirtyVisibleContentStatus();
2122             }            
2123         }
2124
2125         d = m_style->diff(style);
2126
2127         // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
2128         if (d == RenderStyle::RepaintLayer && !layer())
2129             d = RenderStyle::Repaint;
2130         
2131         // The background of the root element or the body element could propagate up to
2132         // the canvas.  Just dirty the entire canvas when our style changes substantially.
2133         if (d >= RenderStyle::Repaint && element() &&
2134             (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
2135             view()->repaint();
2136         else if (m_parent && !isText()) {
2137             // Do a repaint with the old style first, e.g., for example if we go from
2138             // having an outline to not having an outline.
2139             if (d == RenderStyle::RepaintLayer) {
2140                 layer()->repaintIncludingDescendants();
2141                 if (!(m_style->clip() == style->clip()))
2142                     layer()->clearClipRects();
2143             } else if (d == RenderStyle::Repaint || style->outlineSize() < m_style->outlineSize())
2144                 repaint();
2145         }
2146
2147         // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
2148         // end up being destroyed.
2149         if (d == RenderStyle::Layout && layer() &&
2150             (m_style->position() != style->position() ||
2151              m_style->zIndex() != style->zIndex() ||
2152              m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2153              !(m_style->clip() == style->clip()) ||
2154              m_style->hasClip() != style->hasClip() ||
2155              m_style->opacity() != style->opacity()))
2156             layer()->repaintIncludingDescendants();
2157
2158         // When a layout hint happens and an object's position style changes, we have to do a layout
2159         // to dirty the render tree using the old position value now.
2160         if (d == RenderStyle::Layout && m_parent && m_style->position() != style->position()) {
2161             markContainingBlocksForLayout();
2162             if (m_style->position() == StaticPosition)
2163                 repaint();
2164             if (isRenderBlock()) {
2165                 if (style->position() == StaticPosition) {
2166                     // Clear our positioned objects list. Our absolutely positioned descendants will be
2167                     // inserted into our containing block's positioned objects list during layout.
2168                     removePositionedObjects(0);
2169                 } else if (m_style->position() == StaticPosition) {
2170                     // Remove our absolutely positioned descendants from their current containing block.
2171                     // They will be inserted into our positioned objects list during layout.
2172                     RenderObject* cb = parent();
2173                     while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRoot() && !cb->isRenderView()) {
2174                         if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
2175                             cb =  cb->containingBlock();
2176                             break;
2177                         }
2178                         cb = cb->parent();
2179                     }
2180                     cb->removePositionedObjects(static_cast<RenderBlock*>(this));
2181                 }
2182             }
2183         }
2184         
2185         if (isFloating() && (m_style->floating() != style->floating()))
2186             // For changes in float styles, we need to conceivably remove ourselves
2187             // from the floating objects list.
2188             removeFromObjectLists();
2189         else if (isPositioned() && (style->position() != AbsolutePosition && style->position() != FixedPosition))
2190             // For changes in positioning styles, we need to conceivably remove ourselves
2191             // from the positioned objects list.
2192             removeFromObjectLists();
2193         
2194         affectsParentBlock = m_style && isFloatingOrPositioned() &&
2195             (!style->isFloating() && style->position() != AbsolutePosition && style->position() != FixedPosition)
2196             && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
2197         
2198         // reset style flags
2199         m_floating = false;
2200         m_positioned = false;
2201         m_relPositioned = false;
2202         m_paintBackground = false;
2203         m_hasOverflowClip = false;
2204     }
2205
2206     if (view()->frameView()) {
2207         // FIXME: A better solution would be to only invalidate the fixed regions when scrolling.  It's overkill to
2208         // prevent the entire view from blitting on a scroll.
2209         bool oldStyleSlowScroll = style && (style->position() == FixedPosition || style->hasFixedBackgroundImage());
2210         bool newStyleSlowScroll = m_style && (m_style->position() == FixedPosition || m_style->hasFixedBackgroundImage());
2211         if (oldStyleSlowScroll != newStyleSlowScroll) {
2212             if (oldStyleSlowScroll)
2213                 view()->frameView()->removeSlowRepaintObject();
2214             if (newStyleSlowScroll)
2215                 view()->frameView()->addSlowRepaintObject();
2216         }
2217     }
2218
2219     RenderStyle *oldStyle = m_style;
2220     m_style = style;
2221
2222     updateBackgroundImages(oldStyle);
2223     
2224     if (m_style)
2225         m_style->ref();
2226     
2227     if (oldStyle)
2228         oldStyle->deref(renderArena());
2229
2230     setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance());
2231
2232     if (affectsParentBlock)
2233         handleDynamicFloatPositionChange();
2234     
2235     // No need to ever schedule repaints from a style change of a text run, since
2236     // we already did this for the parent of the text run.
2237     if (d == RenderStyle::Layout && m_parent)
2238         setNeedsLayoutAndMinMaxRecalc();
2239     else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
2240         // Do a repaint with the new style now, e.g., for example if we go from
2241         // not having an outline to having an outline.
2242         repaint();
2243 }
2244
2245 void RenderObject::setStyleInternal(RenderStyle* st)
2246 {
2247     if (m_style == st)
2248         return;
2249     if (m_style)
2250         m_style->deref(renderArena());
2251     m_style = st;
2252     if (m_style)
2253         m_style->ref();
2254 }
2255
2256 void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
2257 {
2258     // FIXME: This will be slow when a large number of images is used.  Fix by using a dict.
2259     const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
2260     const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
2261     for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
2262         if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
2263             currOld->backgroundImage()->deref(this);
2264     }
2265     for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
2266         if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
2267             currNew->backgroundImage()->ref(this);
2268     }
2269     
2270     CachedImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
2271     CachedImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
2272     if (oldBorderImage != newBorderImage) {
2273         if (oldBorderImage)
2274             oldBorderImage->deref(this);
2275         if (newBorderImage)
2276             newBorderImage->ref(this);
2277     }
2278 }
2279
2280 IntRect RenderObject::viewRect() const
2281 {
2282     return view()->viewRect();
2283 }
2284
2285 bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
2286 {
2287     RenderObject* o = parent();
2288     if (o) {
2289         o->absolutePosition(xPos, yPos, f);
2290         yPos += o->borderTopExtra();
2291         if (o->hasOverflowClip())
2292             o->layer()->subtractScrollOffset(xPos, yPos); 
2293         return true;
2294     }
2295     else
2296     {
2297         xPos = yPos = 0;
2298         return false;
2299     }
2300 }
2301
2302 IntRect RenderObject::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
2303 {
2304    if (extraWidthToEndOfLine)
2305        *extraWidthToEndOfLine = 0;
2306
2307     return IntRect();
2308 }
2309
2310 int RenderObject::paddingTop() const
2311 {
2312     int w = 0;
2313     Length padding = m_style->paddingTop();
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::paddingBottom() const
2323 {
2324     int w = 0;
2325     Length padding = style()->paddingBottom();
2326     if (padding.isPercent())
2327         w = containingBlock()->contentWidth();
2328     w = padding.calcMinValue(w);
2329     if ( isTableCell() && padding.isAuto() )
2330         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
2331     return w;
2332 }
2333
2334 int RenderObject::paddingLeft() const
2335 {
2336     int w = 0;
2337     Length padding = style()->paddingLeft();
2338     if (padding.isPercent())
2339         w = containingBlock()->contentWidth();
2340     w = padding.calcMinValue(w);
2341     if ( isTableCell() && padding.isAuto() )
2342         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
2343     return w;
2344 }
2345
2346 int RenderObject::paddingRight() const
2347 {
2348     int w = 0;
2349     Length padding = style()->paddingRight();
2350     if (padding.isPercent())
2351         w = containingBlock()->contentWidth();
2352     w = padding.calcMinValue(w);
2353     if ( isTableCell() && padding.isAuto() )
2354         w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
2355     return w;
2356 }
2357
2358 int RenderObject::tabWidth() const
2359 {
2360     if (style()->collapseWhiteSpace())
2361         return 0;
2362         
2363     return containingBlock()->tabWidth(true);
2364 }
2365
2366 RenderView* RenderObject::view() const
2367 {
2368     return static_cast<RenderView*>(document()->renderer());
2369 }
2370
2371 RenderObject *RenderObject::container() const
2372 {
2373     // This method is extremely similar to containingBlock(), but with a few notable
2374     // exceptions.
2375     // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
2376     // the object is not part of the primary document subtree yet.
2377     // (2) For normal flow elements, it just returns the parent.
2378     // (3) For absolute positioned elements, it will return a relative positioned inline.
2379     // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
2380     // the layout of the positioned object.  This does mean that calcAbsoluteHorizontal and
2381     // calcAbsoluteVertical have to use container().
2382     EPosition pos = m_style->position();
2383     RenderObject *o = 0;
2384     if (!isText() && pos == FixedPosition) {
2385         // container() can be called on an object that is not in the
2386         // tree yet.  We don't call view() since it will assert if it
2387         // can't get back to the canvas.  Instead we just walk as high up
2388         // as we can.  If we're in the tree, we'll get the root.  If we
2389         // aren't we'll get the root of our little subtree (most likely
2390         // we'll just return 0).
2391         o = parent();
2392         while (o && o->parent()) o = o->parent();
2393     }
2394     else if (!isText() && pos == AbsolutePosition) {
2395         // Same goes here.  We technically just want our containing block, but
2396         // we may not have one if we're part of an uninstalled subtree.  We'll
2397         // climb as high as we can though.
2398         o = parent();
2399         while (o && o->style()->position() == StaticPosition && !o->isRoot() && !o->isRenderView())
2400             o = o->parent();
2401     }
2402     else
2403         o = parent();
2404     return o;
2405 }
2406
2407 // This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
2408 // content (and perhaps XBL).  That's why it uses the render tree and not the DOM tree.
2409 RenderObject* RenderObject::hoverAncestor() const
2410 {
2411     return (!isInline() && continuation()) ? continuation() : parent();
2412 }
2413
2414 bool RenderObject::isSelectionBorder() const
2415 {
2416     SelectionState st = selectionState();
2417     return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
2418 }
2419
2420
2421 void RenderObject::removeFromObjectLists()
2422 {
2423     if (documentBeingDestroyed())
2424         return;
2425
2426     if (isFloating()) {
2427         RenderBlock* outermostBlock = containingBlock();
2428         for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
2429             if (p->containsFloat(this))
2430                 outermostBlock = p;
2431         }
2432         
2433         if (outermostBlock)
2434             outermostBlock->markAllDescendantsWithFloatsForLayout(this);
2435     }
2436
2437     if (isPositioned()) {
2438         RenderObject *p;
2439         for (p = parent(); p; p = p->parent()) {
2440             if (p->isRenderBlock())
2441                 static_cast<RenderBlock*>(p)->removePositionedObject(this);
2442         }
2443     }
2444 }
2445
2446 RenderArena* RenderObject::renderArena() const
2447 {
2448     Document* doc = document();
2449     return doc ? doc->renderArena() : 0;
2450 }
2451
2452 bool RenderObject::documentBeingDestroyed() const
2453 {
2454     return !document()->renderer();
2455 }
2456
2457 void RenderObject::destroy()
2458 {
2459     // If this renderer is being autoscrolled, stop the autoscroll timer
2460     if (document() && document()->frame() && document()->frame()->autoscrollRenderer() == this)
2461         document()->frame()->stopAutoscrollTimer();
2462
2463     if (m_hasCounterNodeMap) {
2464         RenderObjectsToCounterNodeMaps* objectsMap = getRenderObjectsToCounterNodeMaps();
2465         if (CounterNodeMap* counterNodesMap = objectsMap->get(this)) {
2466             CounterNodeMap::const_iterator end = counterNodesMap->end();
2467             for (CounterNodeMap::const_iterator it = counterNodesMap->begin(); it != end; ++it) {
2468                 CounterNode* counterNode = it->second;
2469                 counterNode->remove();
2470                 delete counterNode;
2471                 counterNode = 0;
2472             }
2473             objectsMap->remove(this);
2474             delete counterNodesMap;
2475         }
2476     }
2477     
2478     document()->axObjectCache()->remove(this);
2479
2480     // By default no ref-counting. RenderWidget::destroy() doesn't call
2481     // this function because it needs to do ref-counting. If anything
2482     // in this function changes, be sure to fix RenderWidget::destroy() as well. 
2483
2484     remove();
2485     
2486     arenaDelete(document()->renderArena(), this);
2487 }
2488
2489 void RenderObject::arenaDelete(RenderArena *arena, void *base)
2490 {
2491     if (m_style->backgroundImage())
2492         m_style->backgroundImage()->deref(this);
2493     if (m_style)
2494         m_style->deref(arena);
2495     
2496 #ifndef NDEBUG
2497     void *savedBase = baseOfRenderObjectBeingDeleted;
2498     baseOfRenderObjectBeingDeleted = base;
2499 #endif
2500     delete this;
2501 #ifndef NDEBUG
2502     baseOfRenderObjectBeingDeleted = savedBase;
2503 #endif
2504     
2505     // Recover the size left there for us by operator delete and free the memory.
2506     arena->free(*(size_t *)base, base);
2507 }
2508
2509 VisiblePosition RenderObject::positionForCoordinates(int x, int y)
2510 {
2511     return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
2512 }
2513
2514 bool RenderObject::isDragging() const
2515
2516     return m_isDragging; 
2517 }
2518
2519 void RenderObject::updateDragState(bool dragOn)
2520 {
2521     bool valueChanged = (dragOn != m_isDragging);
2522     m_isDragging = dragOn;
2523     if (valueChanged && style()->affectedByDragRules())
2524         element()->setChanged();
2525     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2526         curr->updateDragState(dragOn);
2527     if (continuation())
2528         continuation()->updateDragState(dragOn);
2529 }
2530
2531 bool RenderObject::hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
2532 {
2533     bool inside = false;
2534     if (hitTestFilter != HitTestSelf) {
2535         // First test the foreground layer (lines and inlines).
2536         inside = nodeAtPoint(info, x, y, tx, ty, HitTestForeground);
2537         
2538         // Test floats next.
2539         if (!inside)
2540             inside = nodeAtPoint(info, x, y, tx, ty, HitTestFloat);
2541
2542         // Finally test to see if the mouse is in the background (within a child block's background).
2543         if (!inside)
2544             inside = nodeAtPoint(info, x, y, tx, ty, HitTestChildBlockBackgrounds);
2545     }
2546     
2547     // See if the mouse is inside us but not any of our descendants
2548     if (hitTestFilter != HitTestDescendants && !inside)
2549         inside = nodeAtPoint(info, x, y, tx, ty, HitTestBlockBackground);
2550         
2551     return inside;
2552 }
2553
2554 void RenderObject::setInnerNode(NodeInfo& info)
2555 {
2556     if (!info.innerNode() && !isInline() && continuation()) {
2557         // We are in the margins of block elements that are part of a continuation.  In
2558         // this case we're actually still inside the enclosing inline element that was
2559         // split.  Go ahead and set our inner node accordingly.
2560         info.setInnerNode(continuation()->element());
2561         if (!info.innerNonSharedNode())
2562             info.setInnerNonSharedNode(continuation()->element());
2563     }
2564
2565     if (!info.innerNode() && element())
2566         info.setInnerNode(element());
2567             
2568     if(!info.innerNonSharedNode() && element())
2569         info.setInnerNonSharedNode(element());
2570 }
2571
2572 bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
2573                                HitTestAction hitTestAction)
2574 {
2575     return false;
2576 }
2577
2578 short RenderObject::verticalPositionHint( bool firstLine ) const
2579 {
2580     short vpos = m_verticalPosition;
2581     if ( m_verticalPosition == PositionUndefined || firstLine ) {
2582         vpos = getVerticalPosition( firstLine );
2583         if ( !firstLine )
2584             m_verticalPosition = vpos;
2585     }
2586     return vpos;
2587
2588 }
2589
2590 short RenderObject::getVerticalPosition( bool firstLine ) const
2591 {
2592     if (!isInline())
2593         return 0;
2594
2595     // This method determines the vertical position for inline elements.
2596     int vpos = 0;
2597     EVerticalAlign va = style()->verticalAlign();
2598     if ( va == TOP ) {
2599         vpos = PositionTop;
2600     } else if ( va == BOTTOM ) {
2601         vpos = PositionBottom;
2602     } else if ( va == LENGTH ) {
2603         vpos = -style()->verticalAlignLength().calcValue( lineHeight( firstLine ) );
2604     } else  {
2605         bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
2606         vpos = checkParent ? parent()->verticalPositionHint( firstLine ) : 0;
2607         // don't allow elements nested inside text-top to have a different valignment.
2608         if ( va == BASELINE )
2609             return vpos;
2610
2611         const Font &f = parent()->font(firstLine);
2612         int fontsize = f.pixelSize();
2613     
2614         if (va == SUB)
2615             vpos += fontsize/5 + 1;
2616         else if (va == SUPER)
2617             vpos -= fontsize/3 + 1;
2618         else if (va == TEXT_TOP)
2619             vpos += baselinePosition(firstLine) - f.ascent();
2620         else if (va == MIDDLE)
2621             vpos += - (int)(f.xHeight()/2) - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2622         else if (va == TEXT_BOTTOM) {
2623             vpos += f.descent();
2624             if (!isReplaced())
2625                 vpos -= font(firstLine).descent();
2626         } else if ( va == BASELINE_MIDDLE )
2627             vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2628     }
2629     
2630     return vpos;
2631 }
2632
2633 short RenderObject::lineHeight( bool firstLine, bool ) const
2634 {
2635     RenderStyle* s = style(firstLine);
2636     
2637     Length lh = s->lineHeight();
2638
2639     // its "unset", choose nice default
2640     if (lh.value() < 0)
2641         return s->font().lineSpacing();
2642
2643     if (lh.isPercent())
2644         return lh.calcMinValue(s->fontSize());
2645
2646     // its fixed
2647     return lh.value();
2648 }
2649
2650 short RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
2651 {
2652     const Font& f = font(firstLine);
2653     return f.ascent() + (lineHeight(firstLine, isRootLineBox) - f.height()) / 2;
2654 }
2655
2656 void RenderObject::invalidateVerticalPositions()
2657 {
2658     m_verticalPosition = PositionUndefined;
2659     RenderObject *child = firstChild();
2660     while( child ) {
2661         child->invalidateVerticalPositions();
2662         child = child->nextSibling();
2663     }
2664 }
2665
2666 void RenderObject::recalcMinMaxWidths()
2667 {
2668     ASSERT( m_recalcMinMax );
2669
2670 #ifdef DEBUG_LAYOUT
2671     kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
2672 #endif
2673
2674     if (m_recalcMinMax)
2675         updateFirstLetter();
2676     
2677     RenderObject *child = firstChild();
2678     while( child ) {
2679         int cmin = 0;
2680         int cmax = 0;
2681         bool test = false;
2682         if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
2683             cmin = child->minWidth();
2684             cmax = child->maxWidth();
2685             test = true;
2686         }
2687         if ( child->m_recalcMinMax )
2688             child->recalcMinMaxWidths();
2689         if ( !child->m_minMaxKnown )
2690             child->calcMinMaxWidth();
2691         if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
2692             m_minMaxKnown = false;
2693         child = child->nextSibling();
2694     }
2695
2696     // we need to recalculate, if the contains inline children, as the change could have
2697     // happened somewhere deep inside the child tree. Also do this for blocks or tables that
2698     // are inline (i.e., inline-block and inline-table).
2699     if ((!isInline() || isInlineBlockOrInlineTable()) && childrenInline())
2700         m_minMaxKnown = false;
2701
2702     if ( !m_minMaxKnown )
2703         calcMinMaxWidth();
2704     m_recalcMinMax = false;
2705 }
2706
2707 void RenderObject::scheduleRelayout()
2708 {
2709      if (isRenderView()) {
2710          FrameView* view = static_cast<RenderView*>(this)->frameView();
2711          if (view)
2712              view->scheduleRelayout();
2713      } else {
2714          FrameView* v = view() ? view()->frameView() : 0;
2715          if (v)
2716              v->scheduleRelayoutOfSubtree(node());
2717      }
2718 }
2719
2720
2721 void RenderObject::removeLeftoverAnonymousBoxes()
2722 {
2723 }
2724
2725 InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
2726 {
2727     ASSERT(!isRootLineBox);
2728     return new (renderArena()) InlineBox(this);
2729 }
2730
2731 void RenderObject::dirtyLineBoxes(bool, bool)
2732 {
2733 }
2734
2735 InlineBox* RenderObject::inlineBoxWrapper() const
2736 {
2737     return 0;
2738 }
2739
2740 void RenderObject::setInlineBoxWrapper(InlineBox* b)
2741 {
2742 }
2743
2744 void RenderObject::deleteLineBoxWrapper()
2745 {
2746 }
2747
2748 RenderStyle* RenderObject::firstLineStyle() const 
2749 {
2750     RenderStyle *s = m_style; 
2751     const RenderObject* obj = isText() ? parent() : this;
2752     if (obj->isBlockFlow()) {
2753         RenderBlock* firstLineBlock = obj->firstLineBlock();
2754         if (firstLineBlock)
2755             s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style());
2756     } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
2757         RenderStyle* parentStyle = obj->parent()->firstLineStyle();
2758         if (parentStyle != obj->parent()->style()) {
2759             // A first-line style is in effect. We need to cache a first-line style
2760             // for ourselves.
2761             style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
2762             s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
2763         }
2764     }
2765     return s;
2766 }
2767
2768 RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
2769 {
2770     if (!style()->hasPseudoStyle(pseudo))
2771         return 0;
2772     
2773     if (!parentStyle)
2774         parentStyle = style();
2775
2776     RenderStyle* result = style()->getPseudoStyle(pseudo);
2777     if (result)
2778         return result;
2779     
2780     Node* node = element();
2781     if (isText())
2782         node = element()->parentNode();
2783     if (!node)
2784         return 0;
2785     
2786     if (pseudo == RenderStyle::FIRST_LINE_INHERITED) {
2787         result = document()->styleSelector()->styleForElement(static_cast<Element*>(node), parentStyle, false);
2788         result->setStyleType(RenderStyle::FIRST_LINE_INHERITED);
2789     } else
2790         result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(node), parentStyle);
2791     if (result) {
2792         style()->addPseudoStyle(result);
2793         result->deref(document()->renderArena());
2794     }
2795     return result;
2796 }
2797
2798 void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
2799                                            Color& linethrough, bool quirksMode)
2800 {
2801     RenderObject* curr = this;
2802     do {
2803         int currDecs = curr->style()->textDecoration();
2804         if (currDecs) {
2805             if (currDecs & UNDERLINE) {
2806                 decorations &= ~UNDERLINE;
2807                 underline = curr->style()->color();
2808             }
2809             if (currDecs & OVERLINE) {
2810                 decorations &= ~OVERLINE;
2811                 overline = curr->style()->color();
2812             }
2813             if (currDecs & LINE_THROUGH) {
2814                 decorations &= ~LINE_THROUGH;
2815                 linethrough = curr->style()->color();
2816             }
2817         }
2818         curr = curr->parent();
2819         if (curr && curr->isRenderBlock() && curr->continuation())
2820             curr = curr->continuation();
2821     } while (curr && decorations && (!quirksMode || !curr->element() ||
2822                                      (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
2823
2824     // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2825     if (decorations && curr) {
2826         if (decorations & UNDERLINE)
2827             underline = curr->style()->color();
2828         if (decorations & OVERLINE)
2829             overline = curr->style()->color();
2830         if (decorations & LINE_THROUGH)
2831             linethrough = curr->style()->color();
2832     }        
2833 }
2834
2835 void RenderObject::updateWidgetPosition()
2836 {
2837 }
2838
2839 void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions)
2840 {
2841     // Convert the style regions to absolute coordinates.
2842     if (style()->visibility() != VISIBLE) 
2843         return;
2844
2845     const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
2846     unsigned i, count = styleRegions.size();
2847     for (i = 0; i < count; i++){
2848         StyleDashboardRegion styleRegion = styleRegions[i];
2849         
2850         int w = width();
2851         int h = height();
2852         
2853         DashboardRegionValue region;
2854         region.label = styleRegion.label;
2855         region.bounds = IntRect (
2856             styleRegion.offset.left.value(),
2857             styleRegion.offset.top.value(),
2858             w - styleRegion.offset.left.value() - styleRegion.offset.right.value(),
2859             h - styleRegion.offset.top.value() - styleRegion.offset.bottom.value());
2860         region.type = styleRegion.type;
2861
2862         region.clip = region.bounds;
2863         computeAbsoluteRepaintRect(region.clip);
2864         if (region.clip.height() < 0) {
2865             region.clip.setHeight(0);
2866             region.clip.setWidth(0);
2867         }
2868
2869         int x, y;
2870         absolutePosition(x, y);
2871         region.bounds.setX(x + styleRegion.offset.left.value());
2872         region.bounds.setY(y + styleRegion.offset.top.value());
2873         
2874         if (document()->frame()) {
2875             float pageScaleFactor = scaleFactor(document()->frame()->page());
2876             if (pageScaleFactor != 1.0f) {
2877                 region.bounds.scale(pageScaleFactor);
2878                 region.clip.scale(pageScaleFactor);
2879             }
2880         }
2881         
2882         regions.append(region);
2883     }
2884 }
2885
2886 void RenderObject::collectDashboardRegions(Vector<DashboardRegionValue>& regions)
2887 {
2888     // RenderTexts don't have their own style, they just use their parent's style,
2889     // so we don't want to include them.
2890     if (isText())
2891         return;
2892         
2893     addDashboardRegions(regions);
2894     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2895         curr->collectDashboardRegions(regions);
2896 }
2897
2898
2899 void RenderObject::collectBorders(DeprecatedValueList<CollapsedBorderValue>& borderStyles)
2900 {
2901     for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2902         curr->collectBorders(borderStyles);
2903 }
2904
2905 bool RenderObject::avoidsFloats() const
2906 {
2907     return isReplaced() || hasOverflowClip() || isHR(); 
2908 }
2909
2910 bool RenderObject::usesLineWidth() const
2911 {
2912     // 1. All auto-width objects that avoid floats should always use lineWidth
2913     // 2. For objects with a specified width, we match WinIE's behavior:
2914     // (a) tables use contentWidth
2915     // (b) <hr>s use lineWidth
2916     // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
2917     return (avoidsFloats() && (style()->width().isAuto() || isHR() || (style()->htmlHacks() && !isTable())));
2918 }
2919
2920 CounterNode* RenderObject::findCounter(const String& counterName, bool willNeedLayout,
2921     bool usesSeparator, bool createIfNotFound)
2922 {
2923     if (!style())
2924         return 0;
2925
2926     RenderObjectsToCounterNodeMaps* objectsMap = getRenderObjectsToCounterNodeMaps();
2927     CounterNode* newNode = 0;
2928     if (CounterNodeMap* counterNodesMap = objectsMap->get(this))
2929         if (counterNodesMap)
2930             newNode = counterNodesMap->get(counterName);
2931         
2932     if (newNode)
2933         return newNode;
2934
2935     int val = 0;
2936     if (style()->hasCounterReset(counterName) || isRoot()) {
2937         newNode = new CounterResetNode(this);
2938         val = style()->counterReset(counterName);
2939         if (style()->hasCounterIncrement(counterName))
2940             val += style()->counterIncrement(counterName);
2941         newNode->setValue(val);
2942     } else if (style()->hasCounterIncrement(counterName)) {
2943         newNode = new CounterNode(this);
2944         newNode->setValue(style()->counterIncrement(counterName));
2945     } else if (counterName == "list-item") {
2946         if (isListItem()) {
2947             if (element()) {
2948                 String v = static_cast<Element*>(element())->getAttribute("value");
2949                 if (!v.isEmpty()) {
2950                     newNode = new CounterResetNode(this);
2951                     val = v.toInt();
2952                 }
2953             } 
2954             
2955             if (!newNode) {
2956                 newNode = new CounterNode(this);
2957                 val = 1;
2958             }
2959
2960             newNode->setValue(val);
2961         } else if (element() && element()->hasTagName(olTag)) {
2962             newNode = new CounterResetNode(this);
2963             newNode->setValue(static_cast<HTMLOListElement*>(element())->start());
2964         } else if (element() &&
2965             (element()->hasTagName(ulTag) ||
2966              element()->hasTagName(menuTag) ||
2967              element()->hasTagName(dirTag))) {
2968             newNode = new CounterResetNode(this);
2969             newNode->setValue(0);
2970         }
2971     } 
2972     
2973     if (!newNode && !createIfNotFound)
2974         return 0;
2975     else if (!newNode) {
2976         newNode = new CounterNode(this);
2977         newNode->setValue(0);
2978     }
2979
2980     if (willNeedLayout)
2981         newNode->setWillNeedLayout();
2982     if (usesSeparator)
2983         newNode->setUsesSeparator();
2984
2985     CounterNodeMap* nodeMap;
2986     if (m_hasCounterNodeMap)
2987         nodeMap = objectsMap->get(this);
2988     else {
2989         nodeMap = new CounterNodeMap;
2990         objectsMap->set(this, nodeMap);
2991         m_hasCounterNodeMap = true;
2992     }
2993     
2994     nodeMap->set(counterName, newNode);
2995
2996     if (!isRoot()) {
2997         RenderObject* n = !isListItem() && previousSibling()
2998             ? previousSibling()->previousSibling() : previousSibling();
2999
3000         CounterNode* current = 0;
3001         for (; n; n = n->previousSibling()) {
3002             current = n->findCounter(counterName, false, false, false);
3003             if (current)
3004                 break;
3005         }
3006         
3007         CounterNode* last = current;
3008         CounterNode* sibling = current;
3009         if (last && !newNode->isReset()) {
3010             // Found render-sibling, now search for later counter-siblings among its render-children
3011             n = n->lastChild();
3012             while (n) {
3013                 current = n->findCounter(counterName, false, false, false);
3014                 if (current && (last->parent() == current->parent() || sibling == current->parent())) {
3015                     last = current;
3016                     // If the current counter is not the last, search deeper
3017                     if (current->nextSibling()) {
3018                         n = n->lastChild();
3019                         continue;
3020                     } else
3021                         break;
3022                 }
3023                 n = n->previousSibling();
3024             }
3025             
3026             if (sibling->isReset()) {
3027                 if (last != sibling)
3028                     sibling->insertAfter(newNode, last);
3029                 else
3030                     sibling->insertAfter(newNode, 0);
3031             } else
3032                 last->parent()->insertAfter(newNode, last);
3033         } else {
3034             // Nothing found among siblings, let our parent search
3035             last = parent()->findCounter(counterName, false);
3036             if (last->isReset())
3037                 last->insertAfter(newNode, 0);
3038             else
3039                 last->parent()->insertAfter(newNode, last);
3040         }
3041     }
3042
3043     return newNode;
3044 }
3045
3046 UChar RenderObject::backslashAsCurrencySymbol() const
3047 {
3048     if (Node *node = element())
3049         if (Decoder *decoder = node->document()->decoder())
3050             return decoder->encoding().backslashAsCurrencySymbol();
3051     return '\\';
3052 }
3053
3054 void RenderObject::imageChanged(CachedImage *image)
3055 {
3056     // Repaint when the background image or border image finishes loading.
3057     // This is needed for RenderBox objects, and also for table objects that hold
3058     // backgrounds that are then respected by the table cells (which are RenderBox
3059     // subclasses). It would be even better to find a more elegant way of doing this that
3060     // would avoid putting this function and the CachedResourceClient base class into RenderObject.
3061     if (image && image->canRender() && parent()) {
3062         if (view() && element() && (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
3063             view()->repaint();    // repaint the entire canvas since the background gets propagated up
3064         else
3065             repaint();              // repaint object, which is a box or a container with boxes inside it
3066     }
3067 }
3068
3069 bool RenderObject::willRenderImage(CachedImage*)
3070 {
3071     // Without visibility we won't render (and therefore don't care about animation).
3072     if (style()->visibility() != VISIBLE)
3073         return false;
3074
3075     // 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)
3076     // then we don't want to render either.
3077     return !document()->inPageCache() && document()->view()->inWindow();
3078 }
3079
3080 int RenderObject::maximalOutlineSize(PaintPhase p) const
3081 {
3082     if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
3083         return 0;
3084     return static_cast<RenderView*>(document()->renderer())->maximalOutlineSize();
3085 }
3086
3087 int RenderObject::caretMinOffset() const
3088 {
3089     return 0;
3090 }
3091
3092 int RenderObject::caretMaxOffset() const
3093 {
3094     return isReplaced() ? 1 : 0;
3095 }
3096
3097 unsigned RenderObject::caretMaxRenderedOffset() const
3098 {
3099     return 0;
3100 }
3101
3102 int RenderObject::previousOffset (int current) const
3103 {
3104     int previousOffset = current - 1;
3105     return previousOffset;
3106 }
3107
3108 int RenderObject::nextOffset (int current) const
3109 {
3110     int nextOffset = current + 1;
3111     return nextOffset;
3112 }
3113
3114 InlineBox *RenderObject::inlineBox(int offset, EAffinity affinity)
3115 {
3116     return inlineBoxWrapper();
3117 }
3118
3119 #ifdef SVG_SUPPORT
3120
3121 FloatRect RenderObject::relativeBBox(bool) const
3122 {
3123     return FloatRect();
3124 }
3125
3126 AffineTransform RenderObject::localTransform() const
3127 {
3128     return AffineTransform(1, 0, 0, 1, xPos(), yPos());
3129 }
3130  
3131 void RenderObject::setLocalTransform(const AffineTransform&)
3132 {
3133     ASSERT(false);
3134 }
3135
3136 AffineTransform RenderObject::absoluteTransform() const
3137 {
3138     if (parent())
3139         return localTransform() * parent()->absoluteTransform();
3140     return localTransform();
3141 }
3142
3143 #endif
3144
3145 }
3146
3147 #ifndef NDEBUG
3148
3149 void showTree(const WebCore::RenderObject* ro)
3150 {
3151     if (ro)
3152         ro->showTreeForThis();
3153 }
3154
3155 #endif