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