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