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