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