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