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