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