2 * This file is part of the html renderer for KDE.
4 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5 * (C) 1999 Antti Koivisto (koivisto@kde.org)
6 * (C) 2000 Dirk Mueller (mueller@kde.org)
7 * (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
8 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 * Boston, MA 02111-1307, USA.
28 #include "RenderObject.h"
30 #include "AXObjectCache.h"
31 #include "AffineTransform.h"
32 #include "CachedImage.h"
34 #include "CounterNode.h"
35 #include "CounterResetNode.h"
38 #include "EventHandler.h"
39 #include "EventNames.h"
40 #include "FloatRect.h"
42 #include "FrameView.h"
43 #include "GraphicsContext.h"
44 #include "HTMLNames.h"
45 #include "HTMLOListElement.h"
46 #include "HitTestRequest.h"
47 #include "HitTestResult.h"
51 #include "RenderArena.h"
52 #include "RenderFlexibleBox.h"
53 #include "RenderImage.h"
54 #include "RenderInline.h"
55 #include "RenderListItem.h"
56 #include "RenderTableCell.h"
57 #include "RenderTableCol.h"
58 #include "RenderTableRow.h"
59 #include "RenderText.h"
60 #include "RenderTheme.h"
61 #include "RenderView.h"
63 #include "TextResourceDecoder.h"
64 #include "TextStream.h"
65 #include "cssstyleselector.h"
72 using namespace EventNames;
73 using namespace HTMLNames;
76 static void* baseOfRenderObjectBeingDeleted;
79 typedef HashMap<String, CounterNode*> CounterNodeMap;
80 typedef HashMap<const RenderObject*, CounterNodeMap*> RenderObjectsToCounterNodeMaps;
82 static RenderObjectsToCounterNodeMaps* getRenderObjectsToCounterNodeMaps()
84 static RenderObjectsToCounterNodeMaps objectsMap;
88 void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
90 return renderArena->allocate(sz);
93 void RenderObject::operator delete(void* ptr, size_t sz)
95 ASSERT(baseOfRenderObjectBeingDeleted == ptr);
97 // Stash size where destroy can find it.
101 RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
104 RenderArena* arena = node->document()->renderArena();
106 if (ContentData* contentData = style->contentData()) {
107 RenderImage* contentImage = new (arena) RenderImage(node);
109 contentImage->setStyle(style);
110 contentImage->setContentObject(contentData->contentObject());
111 contentImage->setIsAnonymousImage(true);
116 switch (style->display()) {
120 o = new (arena) RenderInline(node);
123 o = new (arena) RenderBlock(node);
126 o = new (arena) RenderBlock(node);
129 o = new (arena) RenderListItem(node);
133 o = new (arena) RenderBlock(node);
137 o = new (arena) RenderTable(node);
139 case TABLE_ROW_GROUP:
140 case TABLE_HEADER_GROUP:
141 case TABLE_FOOTER_GROUP:
142 o = new (arena) RenderTableSection(node);
145 o = new (arena) RenderTableRow(node);
147 case TABLE_COLUMN_GROUP:
149 o = new (arena) RenderTableCol(node);
152 o = new (arena) RenderTableCell(node);
155 o = new (arena) RenderBlock(node);
159 o = new (arena) RenderFlexibleBox(node);
166 struct RenderObjectCounter {
168 ~RenderObjectCounter() { if (count != 0) fprintf(stderr, "LEAK: %d RenderObject\n", count); }
170 int RenderObjectCounter::count;
171 static RenderObjectCounter renderObjectCounter;
174 RenderObject::RenderObject(Node* node)
175 : CachedResourceClient()
181 , m_verticalPosition(PositionUndefined)
182 , m_needsLayout(false)
183 , m_normalChildNeedsLayout(false)
184 , m_posChildNeedsLayout(false)
185 , m_minMaxKnown(false)
187 , m_positioned(false)
188 , m_relPositioned(false)
189 , m_paintBackground(false)
190 , m_isAnonymous(node == node->document())
191 , m_recalcMinMax(false)
195 , m_isDragging(false)
196 , m_hasOverflowClip(false)
197 , m_hasCounterNodeMap(false)
200 ++RenderObjectCounter::count;
204 RenderObject::~RenderObject()
207 --RenderObjectCounter::count;
211 bool RenderObject::isDescendantOf(const RenderObject* obj) const
213 for (const RenderObject* r = this; r; r = r->m_parent) {
220 bool RenderObject::isRoot() const
222 return element() && element()->renderer() == this && element()->document()->documentElement() == element();
225 bool RenderObject::isBody() const
227 return element() && element()->renderer() == this && element()->hasTagName(bodyTag);
230 bool RenderObject::isHR() const
232 return element() && element()->hasTagName(hrTag);
235 bool RenderObject::isHTMLMarquee() const
237 return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
240 bool RenderObject::canHaveChildren() const
245 RenderFlow* RenderObject::continuation() const
250 bool RenderObject::isInlineContinuation() const
255 void RenderObject::addChild(RenderObject*, RenderObject*)
257 ASSERT_NOT_REACHED();
260 RenderObject* RenderObject::removeChildNode(RenderObject*)
262 ASSERT_NOT_REACHED();
266 void RenderObject::removeChild(RenderObject*)
268 ASSERT_NOT_REACHED();
271 void RenderObject::appendChildNode(RenderObject*)
273 ASSERT_NOT_REACHED();
276 void RenderObject::insertChildNode(RenderObject*, RenderObject*)
278 ASSERT_NOT_REACHED();
281 RenderObject* RenderObject::nextInPreOrder() const
283 if (RenderObject* o = firstChild())
286 return nextInPreOrderAfterChildren();
289 RenderObject* RenderObject::nextInPreOrderAfterChildren() const
292 if (!(o = nextSibling())) {
294 while (o && !o->nextSibling())
297 o = o->nextSibling();
303 RenderObject* RenderObject::previousInPreOrder() const
305 if (RenderObject* o = previousSibling()) {
306 while (o->lastChild())
314 RenderObject* RenderObject::childAt(unsigned index) const
316 RenderObject* child = firstChild();
317 for (unsigned i = 0; child && i < index; i++)
318 child = child->nextSibling();
322 bool RenderObject::isEditable() const
324 RenderText* textRenderer = 0;
326 textRenderer = static_cast<RenderText*>(const_cast<RenderObject*>(this));
328 return style()->visibility() == VISIBLE &&
329 element() && element()->isContentEditable() &&
330 ((isBlockFlow() && !firstChild()) ||
333 (textRenderer && textRenderer->firstTextBox()));
336 RenderObject* RenderObject::nextEditable() const
338 RenderObject* r = const_cast<RenderObject*>(this);
339 RenderObject* n = firstChild();
348 return r->nextEditable();
350 n = r->nextSibling();
360 return r->nextEditable();
365 n = r->nextSibling();
376 return r->nextEditable();
384 RenderObject* RenderObject::previousEditable() const
386 RenderObject* r = const_cast<RenderObject*>(this);
387 RenderObject* n = firstChild();
396 return r->previousEditable();
398 n = r->previousSibling();
408 return r->previousEditable();
413 n = r->previousSibling();
424 return r->previousEditable();
432 RenderObject* RenderObject::firstLeafChild() const
434 RenderObject* r = firstChild();
445 RenderObject* RenderObject::lastLeafChild() const
447 RenderObject* r = lastChild();
458 static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
459 RenderLayer*& beforeChild)
462 if (!beforeChild && newObject) {
463 // We need to figure out the layer that follows newObject. We only do
464 // this the first time we find a child layer, and then we update the
465 // pointer values for newObject and beforeChild used by everyone else.
466 beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
469 parentLayer->addChild(obj->layer(), beforeChild);
473 for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
474 addLayers(curr, parentLayer, newObject, beforeChild);
477 void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
482 RenderObject* object = newObject;
483 RenderLayer* beforeChild = 0;
484 WebCore::addLayers(this, parentLayer, object, beforeChild);
487 void RenderObject::removeLayers(RenderLayer* parentLayer)
493 parentLayer->removeChild(layer());
497 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
498 curr->removeLayers(parentLayer);
501 void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
508 oldParent->removeChild(layer());
509 newParent->addChild(layer());
513 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
514 curr->moveLayers(oldParent, newParent);
517 RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
520 // Error check the parent layer passed in. If it's null, we can't find anything.
524 // Step 1: If our layer is a child of the desired parent, then return our layer.
525 RenderLayer* ourLayer = layer();
526 if (ourLayer && ourLayer->parent() == parentLayer)
529 // Step 2: If we don't have a layer, or our layer is the desired parent, then descend
530 // into our siblings trying to find the next layer whose parent is the desired parent.
531 if (!ourLayer || ourLayer == parentLayer) {
532 for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
533 curr; curr = curr->nextSibling()) {
534 RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
540 // Step 3: If our layer is the desired parent layer, then we're finished. We didn't
542 if (parentLayer == ourLayer)
545 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
546 // follow us to see if we can locate a layer.
547 if (checkParent && parent())
548 return parent()->findNextLayer(parentLayer, this, true);
553 RenderLayer* RenderObject::enclosingLayer() const
555 const RenderObject* curr = this;
557 RenderLayer* layer = curr->layer();
560 curr = curr->parent();
565 bool RenderObject::requiresLayer()
567 return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip();
570 RenderBlock* RenderObject::firstLineBlock() const
575 void RenderObject::updateFirstLetter()
579 int RenderObject::offsetLeft() const
581 RenderObject* offsetPar = offsetParent();
585 if (!isPositioned()) {
586 if (isRelPositioned())
587 x += static_cast<const RenderBox*>(this)->relativePositionOffsetX();
588 RenderObject* curr = parent();
589 while (curr && curr != offsetPar) {
591 curr = curr->parent();
597 int RenderObject::offsetTop() const
599 RenderObject* offsetPar = offsetParent();
603 if (!isPositioned()) {
604 if (isRelPositioned())
605 y += static_cast<const RenderBox*>(this)->relativePositionOffsetY();
606 RenderObject* curr = parent();
607 while (curr && curr != offsetPar) {
608 if (!curr->isTableRow())
610 curr = curr->parent();
616 RenderObject* RenderObject::offsetParent() const
618 // FIXME: It feels like this function could almost be written using containing blocks.
622 bool skipTables = isPositioned() || isRelPositioned();
623 RenderObject* curr = parent();
624 while (curr && (!curr->element() ||
625 (!curr->isPositioned() && !curr->isRelPositioned() &&
626 !(!style()->htmlHacks() && skipTables ? curr->isRoot() : curr->isBody())))) {
627 if (!skipTables && curr->element() && (curr->isTableCell() || curr->isTable()))
629 curr = curr->parent();
634 // More IE extensions. clientWidth and clientHeight represent the interior of an object
635 // excluding border and scrollbar.
636 int RenderObject::clientWidth() const
638 return width() - borderLeft() - borderRight() -
639 (includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0);
642 int RenderObject::clientHeight() const
644 return height() - borderTop() - borderBottom() -
645 (includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0);
648 // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
649 // object has overflow:hidden/scroll/auto specified and also has overflow.
650 int RenderObject::scrollWidth() const
652 return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
655 int RenderObject::scrollHeight() const
657 return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
660 int RenderObject::scrollLeft() const
662 return hasOverflowClip() ? layer()->scrollXOffset() : 0;
665 int RenderObject::scrollTop() const
667 return hasOverflowClip() ? layer()->scrollYOffset() : 0;
670 void RenderObject::setScrollLeft(int newLeft)
672 if (hasOverflowClip())
673 layer()->scrollToXOffset(newLeft);
676 void RenderObject::setScrollTop(int newTop)
678 if (hasOverflowClip())
679 layer()->scrollToYOffset(newTop);
682 bool RenderObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
684 RenderLayer* l = layer();
685 if (l && l->scroll(direction, granularity, multiplier))
687 RenderBlock* b = containingBlock();
688 if (b && !b->isRenderView())
689 return b->scroll(direction, granularity, multiplier);
693 bool RenderObject::shouldAutoscroll() const
695 return ((isRoot()) || (hasOverflowClip() && (scrollsOverflow() || (node() && node()->isContentEditable()))));
698 void RenderObject::autoscroll()
700 if (RenderLayer* l = layer())
704 bool RenderObject::hasStaticX() const
706 return (style()->left().isAuto() && style()->right().isAuto()) || style()->left().isStatic() || style()->right().isStatic();
709 bool RenderObject::hasStaticY() const
711 return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
714 void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
718 void RenderObject::setNeedsLayout(bool b, bool markParents)
720 bool alreadyNeededLayout = m_needsLayout;
723 if (!alreadyNeededLayout && markParents)
724 markContainingBlocksForLayout();
726 m_posChildNeedsLayout = false;
727 m_normalChildNeedsLayout = false;
731 void RenderObject::setChildNeedsLayout(bool b, bool markParents)
733 bool alreadyNeededLayout = m_normalChildNeedsLayout;
734 m_normalChildNeedsLayout = b;
736 if (!alreadyNeededLayout && markParents)
737 markContainingBlocksForLayout();
739 m_posChildNeedsLayout = false;
740 m_normalChildNeedsLayout = false;
744 void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout)
746 RenderObject* o = container();
747 RenderObject* last = this;
750 if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
751 if (o->m_posChildNeedsLayout)
753 o->m_posChildNeedsLayout = true;
755 if (o->m_normalChildNeedsLayout)
757 o->m_normalChildNeedsLayout = true;
761 if (scheduleRelayout && (last->isTextField() || last->isTextArea()))
766 if (scheduleRelayout)
767 last->scheduleRelayout();
770 RenderBlock* RenderObject::containingBlock() const
773 return static_cast<const RenderTableCell*>(this)->table();
775 return (RenderBlock*)this;
777 RenderObject* o = parent();
778 if (!isText() && m_style->position() == FixedPosition) {
779 while ( o && !o->isRenderView() )
781 } else if (!isText() && m_style->position() == AbsolutePosition) {
782 while (o && (o->style()->position() == StaticPosition || (o->isInline() && !o->isReplaced())) && !o->isRenderView()) {
783 // For relpositioned inlines, we return the nearest enclosing block. We don't try
784 // to return the inline itself. This allows us to avoid having a positioned objects
785 // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
786 // from this method. The container() method can actually be used to obtain the
788 if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced())
789 return o->containingBlock();
793 while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
794 || o->isTableCol() || o->isFrameSet()
796 || o->isKCanvasContainer()
802 if (!o || !o->isRenderBlock())
803 return 0; // Probably doesn't happen any more, but leave just in case. -dwh
805 return static_cast<RenderBlock*>(o);
808 int RenderObject::containingBlockWidth() const
811 return containingBlock()->contentWidth();
814 int RenderObject::containingBlockHeight() const
817 return containingBlock()->contentHeight();
820 bool RenderObject::mustRepaintBackgroundOrBorder() const
822 // If we don't have a background/border, then nothing to do.
823 if (!shouldPaintBackgroundOrBorder())
826 // Ok, let's check the background first.
827 const BackgroundLayer* bgLayer = style()->backgroundLayers();
829 // Nobody will use multiple background layers without wanting fancy positioning.
833 // Make sure we have a valid background image.
834 CachedImage* bg = bgLayer->backgroundImage();
835 bool shouldPaintBackgroundImage = bg && bg->canRender();
837 // These are always percents or auto.
838 if (shouldPaintBackgroundImage &&
839 (bgLayer->backgroundXPosition().value() != 0 || bgLayer->backgroundYPosition().value() != 0 ||
840 bgLayer->backgroundSize().width.isPercent() || bgLayer->backgroundSize().height.isPercent()))
841 // The background image will shift unpredictably if the size changes.
844 // Background is ok. Let's check border.
845 if (style()->hasBorder()) {
846 // Border images are not ok.
847 CachedImage* borderImage = style()->borderImage().image();
848 bool shouldPaintBorderImage = borderImage && borderImage->canRender();
850 // If the image hasn't loaded, we're still using the normal border style.
851 if (shouldPaintBorderImage && borderImage->isLoaded())
858 void RenderObject::drawBorderArc(GraphicsContext* graphicsContext, int x, int y, float thickness, IntSize radius,
859 int angleStart, int angleSpan, BorderSide s, Color c, const Color& textColor,
860 EBorderStyle style, bool firstCorner)
862 if ((style == DOUBLE && thickness / 2 < 3) || ((style == RIDGE || style == GROOVE) && thickness / 2 < 2))
866 if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
867 c.setRGB(238, 238, 238);
877 graphicsContext->setPen(Pen(c, thickness == 1 ? 0 : static_cast<int>(thickness), Pen::DotLine));
880 graphicsContext->setPen(Pen(c, thickness == 1 ? 0 : static_cast<int>(thickness), Pen::DashLine));
883 graphicsContext->drawArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), thickness, angleStart, angleSpan);
887 float third = thickness / 3.0f;
888 float innerThird = (thickness + 1.0f) / 6.0f;
889 int shiftForInner = static_cast<int>(innerThird * 2.5f);
890 graphicsContext->setPen(Pen::NoPen);
893 int outerHeight = radius.height() * 2;
894 int innerX = x + shiftForInner;
895 int innerY = y + shiftForInner;
896 int innerWidth = (radius.width() - shiftForInner) * 2;
897 int innerHeight = (radius.height() - shiftForInner) * 2;
898 if (innerThird > 1 && (s == BSTop || (firstCorner && (s == BSLeft || s == BSRight)))) {
903 graphicsContext->drawArc(IntRect(x, outerY, radius.width() * 2, outerHeight), third, angleStart, angleSpan);
904 graphicsContext->drawArc(IntRect(innerX, innerY, innerWidth, innerHeight), (innerThird > 2) ? innerThird - 1 : innerThird,
905 angleStart, angleSpan);
911 if ((style == RIDGE && (s == BSTop || s == BSLeft)) ||
912 (style == GROOVE && (s == BSBottom || s == BSRight)))
919 graphicsContext->setPen(Pen::NoPen);
920 graphicsContext->setFillColor(c);
921 graphicsContext->drawArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), thickness, angleStart, angleSpan);
923 float halfThickness = (thickness + 1.0f) / 4.0f;
924 int shiftForInner = static_cast<int>(halfThickness * 1.5f);
925 graphicsContext->setFillColor(c2);
926 graphicsContext->drawArc(IntRect(x + shiftForInner, y + shiftForInner, (radius.width() - shiftForInner) * 2,
927 (radius.height() - shiftForInner) * 2), (halfThickness > 2) ? halfThickness - 1 : halfThickness,
928 angleStart, angleSpan);
932 if (s == BSTop || s == BSLeft)
935 if (style == OUTSET && (s == BSBottom || s == BSRight))
938 graphicsContext->setPen(Pen::NoPen);
939 graphicsContext->setFillColor(c);
940 graphicsContext->drawArc(IntRect(x, y, radius.width() * 2, radius.height() * 2), thickness, angleStart, angleSpan);
945 void RenderObject::drawBorder(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
946 BorderSide s, Color c, const Color& textcolor, EBorderStyle style,
947 int adjbw1, int adjbw2)
949 int width = (s == BSTop || s == BSBottom ? y2 - y1 : x2 - x1);
951 if (style == DOUBLE && width < 3)
955 if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
956 c.setRGB(238, 238, 238);
967 graphicsContext->setPen(Pen(c, width == 1 ? 0 : width, style == DASHED ? Pen::DashLine : Pen::DotLine));
973 graphicsContext->drawLine(IntPoint(x1, (y1 + y2) / 2), IntPoint(x2, (y1 + y2) / 2));
977 graphicsContext->drawLine(IntPoint((x1 + x2) / 2, y1), IntPoint((x1 + x2) / 2, y2));
982 int third = (width + 1) / 3;
984 if (adjbw1 == 0 && adjbw2 == 0) {
985 graphicsContext->setPen(Pen::NoPen);
986 graphicsContext->setFillColor(c);
990 graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, third));
991 graphicsContext->drawRect(IntRect(x1, y2 - third, x2 - x1, third));
994 graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1));
995 graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1));
998 graphicsContext->drawRect(IntRect(x1, y1 + 1, third, y2 - y1 - 1));
999 graphicsContext->drawRect(IntRect(x2 - third, y1 + 1, third, y2 - y1 - 1));
1003 int adjbw1bigthird = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 3;
1004 int adjbw2bigthird = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 3;
1008 drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
1009 y1, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y1 + third,
1010 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1011 drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
1012 y2 - third, x2 - max((adjbw2 * 2 + 1) / 3, 0), y2,
1013 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1016 drawBorder(graphicsContext, x1, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
1017 x1 + third, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
1018 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1019 drawBorder(graphicsContext, x2 - third, y1 + max((adjbw1 * 2 + 1) / 3, 0),
1020 x2, y2 - max((adjbw2 * 2 + 1) / 3, 0),
1021 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1024 drawBorder(graphicsContext, x1 + max((adjbw1 * 2 + 1) / 3, 0),
1025 y1, x2 - max((adjbw2 * 2 + 1) / 3, 0), y1 + third,
1026 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1027 drawBorder(graphicsContext, x1 + max((-adjbw1 * 2 + 1) / 3, 0),
1028 y2 - third, x2 - max((-adjbw2 * 2 + 1) / 3, 0), y2,
1029 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1032 drawBorder(graphicsContext, x1, y1 + max((adjbw1 * 2 + 1) / 3, 0),
1033 x1 + third, y2 - max(( adjbw2 * 2 + 1) / 3, 0),
1034 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1035 drawBorder(graphicsContext, x2 - third, y1 + max((-adjbw1 * 2 + 1) / 3, 0),
1036 x2, y2 - max((-adjbw2 * 2 + 1) / 3, 0),
1037 s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
1050 if (style == GROOVE) {
1058 int adjbw1bighalf = ((adjbw1 > 0) ? adjbw1 + 1 : adjbw1 - 1) / 2;
1059 int adjbw2bighalf = ((adjbw2 > 0) ? adjbw2 + 1 : adjbw2 - 1) / 2;
1063 drawBorder(graphicsContext, x1 + max(-adjbw1, 0) / 2, y1, x2 - max(-adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
1064 s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
1065 drawBorder(graphicsContext, x1 + max(adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjbw2 + 1, 0) / 2, y2,
1066 s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
1069 drawBorder(graphicsContext, x1, y1 + max(-adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjbw2, 0) / 2,
1070 s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
1071 drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjbw1 + 1, 0) / 2, x2, y2 - max(adjbw2 + 1, 0) / 2,
1072 s, c, textcolor, s2, adjbw1 / 2, adjbw2 / 2);
1075 drawBorder(graphicsContext, x1 + max(adjbw1, 0) / 2, y1, x2 - max(adjbw2, 0) / 2, (y1 + y2 + 1) / 2,
1076 s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
1077 drawBorder(graphicsContext, x1 + max(-adjbw1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjbw2 + 1, 0) / 2, y2,
1078 s, c, textcolor, s1, adjbw1/2, adjbw2/2);
1081 drawBorder(graphicsContext, x1, y1 + max(adjbw1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjbw2, 0) / 2,
1082 s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
1083 drawBorder(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjbw1 + 1, 0) / 2, x2, y2 - max(-adjbw2 + 1, 0) / 2,
1084 s, c, textcolor, s1, adjbw1/2, adjbw2/2);
1090 if (s == BSTop || s == BSLeft)
1094 if (style == OUTSET && (s == BSBottom || s == BSRight))
1099 graphicsContext->setPen(Pen::NoPen);
1100 graphicsContext->setFillColor(c);
1103 if (!adjbw1 && !adjbw2) {
1104 graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1));
1110 quad[0] = FloatPoint(x1 + max(-adjbw1, 0), y1);
1111 quad[1] = FloatPoint(x1 + max(adjbw1, 0), y2);
1112 quad[2] = FloatPoint(x2 - max(adjbw2, 0), y2);
1113 quad[3] = FloatPoint(x2 - max(-adjbw2, 0), y1);
1116 quad[0] = FloatPoint(x1 + max(adjbw1, 0), y1);
1117 quad[1] = FloatPoint(x1 + max(-adjbw1, 0), y2);
1118 quad[2] = FloatPoint(x2 - max(-adjbw2, 0), y2);
1119 quad[3] = FloatPoint(x2 - max(adjbw2, 0), y1);
1122 quad[0] = FloatPoint(x1, y1 + max(-adjbw1, 0));
1123 quad[1] = FloatPoint(x1, y2 - max(-adjbw2, 0));
1124 quad[2] = FloatPoint(x2, y2 - max(adjbw2, 0));
1125 quad[3] = FloatPoint(x2, y1 + max(adjbw1, 0));
1128 quad[0] = FloatPoint(x1, y1 + max(adjbw1, 0));
1129 quad[1] = FloatPoint(x1, y2 - max(adjbw2, 0));
1130 quad[2] = FloatPoint(x2, y2 - max(-adjbw2, 0));
1131 quad[3] = FloatPoint(x2, y1 + max(-adjbw1, 0));
1134 graphicsContext->drawConvexPolygon(4, quad);
1140 bool RenderObject::paintBorderImage(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
1142 CachedImage* borderImage = style->borderImage().image();
1143 if (!borderImage->isLoaded())
1144 return true; // Never paint a border image incrementally, but don't paint the fallback borders either.
1146 // If we have a border radius, the border image gets clipped to the rounded rect.
1147 bool clipped = false;
1148 if (style->hasBorderRadius()) {
1149 IntRect clipRect(tx, ty, w, h);
1150 graphicsContext->save();
1151 graphicsContext->addRoundedRectClip(clipRect, style->borderTopLeftRadius(), style->borderTopRightRadius(),
1152 style->borderBottomLeftRadius(), style->borderBottomRightRadius());
1156 int imageWidth = borderImage->image()->width();
1157 int imageHeight = borderImage->image()->height();
1159 int topSlice = min(imageHeight, style->borderImage().m_slices.top.calcValue(borderImage->image()->height()));
1160 int bottomSlice = min(imageHeight, style->borderImage().m_slices.bottom.calcValue(borderImage->image()->height()));
1161 int leftSlice = min(imageWidth, style->borderImage().m_slices.left.calcValue(borderImage->image()->width()));
1162 int rightSlice = min(imageWidth, style->borderImage().m_slices.right.calcValue(borderImage->image()->width()));
1164 EBorderImageRule hRule = style->borderImage().horizontalRule();
1165 EBorderImageRule vRule = style->borderImage().verticalRule();
1167 bool drawLeft = leftSlice > 0 && style->borderLeftWidth() > 0;
1168 bool drawTop = topSlice > 0 && style->borderTopWidth() > 0;
1169 bool drawRight = rightSlice > 0 && style->borderRightWidth() > 0;
1170 bool drawBottom = bottomSlice > 0 && style->borderBottomWidth() > 0;
1171 bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - style->borderLeftWidth() - style->borderRightWidth()) > 0 &&
1172 (imageHeight - topSlice - bottomSlice) > 0 && (h - style->borderTopWidth() - style->borderBottomWidth()) > 0;
1175 // Paint the top and bottom left corners.
1177 // The top left corner rect is (tx, ty, leftWidth, topWidth)
1178 // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
1180 graphicsContext->drawImage(borderImage->image(), IntRect(tx, ty, style->borderLeftWidth(), style->borderTopWidth()),
1181 IntRect(0, 0, leftSlice, topSlice));
1183 // The bottom left corner rect is (tx, ty + h - bottomWidth, leftWidth, bottomWidth)
1184 // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
1186 graphicsContext->drawImage(borderImage->image(), IntRect(tx, ty + h - style->borderBottomWidth(), style->borderLeftWidth(), style->borderBottomWidth()),
1187 IntRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice));
1189 // Paint the left edge.
1190 // Have to scale and tile into the border rect.
1191 graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx, ty + style->borderTopWidth(), style->borderLeftWidth(),
1192 h - style->borderTopWidth() - style->borderBottomWidth()),
1193 IntRect(0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice),
1194 Image::StretchTile, (Image::TileRule)vRule);
1198 // Paint the top and bottom right corners
1199 // The top right corner rect is (tx + w - rightWidth, ty, rightWidth, topWidth)
1200 // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
1202 graphicsContext->drawImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty, style->borderRightWidth(), style->borderTopWidth()),
1203 IntRect(imageWidth - rightSlice, 0, rightSlice, topSlice));
1205 // The bottom right corner rect is (tx + w - rightWidth, ty + h - bottomWidth, rightWidth, bottomWidth)
1206 // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, botomSlice)
1208 graphicsContext->drawImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty + h - style->borderBottomWidth(), style->borderRightWidth(), style->borderBottomWidth()),
1209 IntRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice));
1211 // Paint the right edge.
1212 graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + w - style->borderRightWidth(), ty + style->borderTopWidth(), style->borderRightWidth(),
1213 h - style->borderTopWidth() - style->borderBottomWidth()),
1214 IntRect(imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice),
1215 Image::StretchTile, (Image::TileRule)vRule);
1218 // Paint the top edge.
1220 graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty, w - style->borderLeftWidth() - style->borderRightWidth(), style->borderTopWidth()),
1221 IntRect(leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice),
1222 (Image::TileRule)hRule, Image::StretchTile);
1224 // Paint the bottom edge.
1226 graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty + h - style->borderBottomWidth(),
1227 w - style->borderLeftWidth() - style->borderRightWidth(), style->borderBottomWidth()),
1228 IntRect(leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice),
1229 (Image::TileRule)hRule, Image::StretchTile);
1231 // Paint the middle.
1233 graphicsContext->drawTiledImage(borderImage->image(), IntRect(tx + style->borderLeftWidth(), ty + style->borderTopWidth(), w - style->borderLeftWidth() - style->borderRightWidth(),
1234 h - style->borderTopWidth() - style->borderBottomWidth()),
1235 IntRect(leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice),
1236 (Image::TileRule)hRule, (Image::TileRule)vRule);
1238 // Clear the clip for the border radius.
1240 graphicsContext->restore();
1245 void RenderObject::paintBorder(GraphicsContext* graphicsContext, int tx, int ty, int w, int h,
1246 const RenderStyle* style, bool begin, bool end)
1248 CachedImage* borderImage = style->borderImage().image();
1249 bool shouldPaintBackgroundImage = borderImage && borderImage->canRender();
1250 if (shouldPaintBackgroundImage)
1251 shouldPaintBackgroundImage = paintBorderImage(graphicsContext, tx, ty, w, h, style);
1253 if (shouldPaintBackgroundImage)
1256 const Color& tc = style->borderTopColor();
1257 const Color& bc = style->borderBottomColor();
1258 const Color& lc = style->borderLeftColor();
1259 const Color& rc = style->borderRightColor();
1261 bool tt = style->borderTopIsTransparent();
1262 bool bt = style->borderBottomIsTransparent();
1263 bool rt = style->borderRightIsTransparent();
1264 bool lt = style->borderLeftIsTransparent();
1266 EBorderStyle ts = style->borderTopStyle();
1267 EBorderStyle bs = style->borderBottomStyle();
1268 EBorderStyle ls = style->borderLeftStyle();
1269 EBorderStyle rs = style->borderRightStyle();
1271 bool renderTop = ts > BHIDDEN && !tt;
1272 bool renderLeft = ls > BHIDDEN && begin && !lt;
1273 bool renderRight = rs > BHIDDEN && end && !rt;
1274 bool renderBottom = bs > BHIDDEN && !bt;
1276 // Need sufficient width and height to contain border radius curves. Sanity check our top/bottom
1277 // values and our width/height values to make sure the curves can all fit. If not, then we won't paint
1278 // any border radii.
1279 bool renderRadii = false;
1280 IntSize topLeft = style->borderTopLeftRadius();
1281 IntSize topRight = style->borderTopRightRadius();
1282 IntSize bottomLeft = style->borderBottomLeftRadius();
1283 IntSize bottomRight = style->borderBottomRightRadius();
1285 if (style->hasBorderRadius()) {
1286 int requiredWidth = max(topLeft.width() + topRight.width(), bottomLeft.width() + bottomRight.width());
1287 int requiredHeight = max(topLeft.height() + bottomLeft.height(), topRight.height() + bottomRight.height());
1288 renderRadii = (requiredWidth <= w && requiredHeight <= h);
1291 // Clip to the rounded rectangle.
1293 graphicsContext->save();
1294 graphicsContext->addRoundedRectClip(IntRect(tx, ty, w, h), topLeft, topRight, bottomLeft, bottomRight);
1297 int firstAngleStart, secondAngleStart, firstAngleSpan, secondAngleSpan;
1299 bool upperLeftBorderStylesMatch = renderLeft && (ts == ls) && (tc == lc) && (ts != INSET) && (ts != GROOVE);
1300 bool upperRightBorderStylesMatch = renderRight && (ts == rs) && (tc == rc) && (ts != OUTSET) && (ts != RIDGE);
1301 bool lowerLeftBorderStylesMatch = renderLeft && (bs == ls) && (bc == lc) && (bs != OUTSET) && (bs != RIDGE);
1302 bool lowerRightBorderStylesMatch = renderRight && (bs == rs) && (bc == rc) && (bs != INSET) && (bs != GROOVE);
1305 bool ignore_left = (renderRadii && topLeft.width() > 0) ||
1306 (tc == lc && tt == lt && ts >= OUTSET &&
1307 (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1309 bool ignore_right = (renderRadii && topRight.width() > 0) ||
1310 (tc == rc && tt == rt && ts >= OUTSET &&
1311 (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1316 x += topLeft.width();
1317 x2 -= topRight.width();
1320 drawBorder(graphicsContext, x, ty, x2, ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
1321 ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
1326 int rightX = tx + w - topRight.width() * 2;
1327 firstAngleStart = 90;
1328 firstAngleSpan = upperLeftBorderStylesMatch ? 90 : 45;
1330 // We make the arc double thick and let the clip rect take care of clipping the extra off.
1331 // We're doing this because it doesn't seem possible to match the curve of the clip exactly
1332 // with the arc-drawing function.
1333 thickness = style->borderTopWidth() * 2;
1335 if (upperRightBorderStylesMatch) {
1336 secondAngleStart = 0;
1337 secondAngleSpan = 90;
1339 secondAngleStart = 45;
1340 secondAngleSpan = 45;
1343 // The inner clip clips inside the arc. This is especially important for 1px borders.
1344 bool applyLeftInnerClip = (style->borderLeftWidth() < topLeft.width())
1345 && (style->borderTopWidth() < topLeft.height())
1346 && (ts != DOUBLE || style->borderTopWidth() > 6);
1347 if (applyLeftInnerClip) {
1348 graphicsContext->save();
1349 graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, topLeft.width() * 2, topLeft.height() * 2),
1350 style->borderTopWidth());
1353 // Draw upper left arc
1354 drawBorderArc(graphicsContext, leftX, leftY, thickness, topLeft, firstAngleStart, firstAngleSpan,
1355 BSTop, tc, style->color(), ts, true);
1356 if (applyLeftInnerClip)
1357 graphicsContext->restore();
1359 bool applyRightInnerClip = (style->borderRightWidth() < topRight.width())
1360 && (style->borderTopWidth() < topRight.height())
1361 && (ts != DOUBLE || style->borderTopWidth() > 6);
1362 if (applyRightInnerClip) {
1363 graphicsContext->save();
1364 graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, topRight.width() * 2, topRight.height() * 2),
1365 style->borderTopWidth());
1368 // Draw upper right arc
1369 drawBorderArc(graphicsContext, rightX, leftY, thickness, topRight, secondAngleStart, secondAngleSpan,
1370 BSTop, tc, style->color(), ts, false);
1371 if (applyRightInnerClip)
1372 graphicsContext->restore();
1377 bool ignore_left = (renderRadii && bottomLeft.width() > 0) ||
1378 (bc == lc && bt == lt && bs >= OUTSET &&
1379 (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1381 bool ignore_right = (renderRadii && bottomRight.width() > 0) ||
1382 (bc == rc && bt == rt && bs >= OUTSET &&
1383 (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1388 x += bottomLeft.width();
1389 x2 -= bottomRight.width();
1392 drawBorder(graphicsContext, x, ty + h - style->borderBottomWidth(), x2, ty + h, BSBottom, bc, style->color(), bs,
1393 ignore_left ? 0 : style->borderLeftWidth(), ignore_right ? 0 : style->borderRightWidth());
1397 int leftY = ty + h - bottomLeft.height() * 2;
1398 int rightX = tx + w - bottomRight.width() * 2;
1399 secondAngleStart = 270;
1400 secondAngleSpan = upperRightBorderStylesMatch ? 90 : 45;
1401 thickness = style->borderBottomWidth() * 2;
1403 if (upperLeftBorderStylesMatch) {
1404 firstAngleStart = 180;
1405 firstAngleSpan = 90;
1407 firstAngleStart = 225;
1408 firstAngleSpan = 45;
1411 bool applyLeftInnerClip = (style->borderLeftWidth() < bottomLeft.width())
1412 && (style->borderBottomWidth() < bottomLeft.height())
1413 && (bs != DOUBLE || style->borderBottomWidth() > 6);
1414 if (applyLeftInnerClip) {
1415 graphicsContext->save();
1416 graphicsContext->addInnerRoundedRectClip(IntRect(leftX, leftY, bottomLeft.width() * 2, bottomLeft.height() * 2),
1417 style->borderBottomWidth());
1420 // Draw lower left arc
1421 drawBorderArc(graphicsContext, leftX, leftY, thickness, bottomLeft, firstAngleStart, firstAngleSpan,
1422 BSBottom, bc, style->color(), bs, true);
1423 if (applyLeftInnerClip)
1424 graphicsContext->restore();
1426 bool applyRightInnerClip = (style->borderRightWidth() < bottomRight.width())
1427 && (style->borderBottomWidth() < bottomRight.height())
1428 && (bs != DOUBLE || style->borderBottomWidth() > 6);
1429 if (applyRightInnerClip) {
1430 graphicsContext->save();
1431 graphicsContext->addInnerRoundedRectClip(IntRect(rightX, leftY, bottomRight.width() * 2, bottomRight.height() * 2),
1432 style->borderBottomWidth());
1435 // Draw lower right arc
1436 drawBorderArc(graphicsContext, rightX, leftY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
1437 BSBottom, bc, style->color(), bs, false);
1438 if (applyRightInnerClip)
1439 graphicsContext->restore();
1444 bool ignore_top = (renderRadii && topLeft.height() > 0) ||
1445 (tc == lc && tt == lt && ls >= OUTSET &&
1446 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1448 bool ignore_bottom = (renderRadii && bottomLeft.height() > 0) ||
1449 (bc == lc && bt == lt && ls >= OUTSET &&
1450 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1455 y += topLeft.height();
1456 y2 -= bottomLeft.height();
1459 drawBorder(graphicsContext, tx, y, tx + style->borderLeftWidth(), y2, BSLeft, lc, style->color(), ls,
1460 ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
1462 if (renderRadii && (!upperLeftBorderStylesMatch || !lowerLeftBorderStylesMatch)) {
1465 int bottomY = ty + h - bottomLeft.height() * 2;
1466 firstAngleStart = 135;
1467 secondAngleStart = 180;
1468 firstAngleSpan = secondAngleSpan = 45;
1469 thickness = style->borderLeftWidth() * 2;
1471 bool applyTopInnerClip = (style->borderLeftWidth() < topLeft.width())
1472 && (style->borderTopWidth() < topLeft.height())
1473 && (ls != DOUBLE || style->borderLeftWidth() > 6);
1474 if (applyTopInnerClip) {
1475 graphicsContext->save();
1476 graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topLeft.width() * 2, topLeft.height() * 2),
1477 style->borderLeftWidth());
1480 // Draw top left arc
1481 drawBorderArc(graphicsContext, topX, topY, thickness, topLeft, firstAngleStart, firstAngleSpan,
1482 BSLeft, lc, style->color(), ls, true);
1483 if (applyTopInnerClip)
1484 graphicsContext->restore();
1486 bool applyBottomInnerClip = (style->borderLeftWidth() < bottomLeft.width())
1487 && (style->borderBottomWidth() < bottomLeft.height())
1488 && (ls != DOUBLE || style->borderLeftWidth() > 6);
1489 if (applyBottomInnerClip) {
1490 graphicsContext->save();
1491 graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, bottomLeft.width() * 2, bottomLeft.height() * 2),
1492 style->borderLeftWidth());
1495 // Draw bottom left arc
1496 drawBorderArc(graphicsContext, topX, bottomY, thickness, bottomLeft, secondAngleStart, secondAngleSpan,
1497 BSLeft, lc, style->color(), ls, false);
1498 if (applyBottomInnerClip)
1499 graphicsContext->restore();
1504 bool ignore_top = (renderRadii && topRight.height() > 0) ||
1505 ((tc == rc) && (tt == rt) &&
1506 (rs >= DOTTED || rs == INSET) &&
1507 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1509 bool ignore_bottom = (renderRadii && bottomRight.height() > 0) ||
1510 ((bc == rc) && (bt == rt) &&
1511 (rs >= DOTTED || rs == INSET) &&
1512 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1517 y += topRight.height();
1518 y2 -= bottomRight.height();
1521 drawBorder(graphicsContext, tx + w - style->borderRightWidth(), y, tx + w, y2, BSRight, rc, style->color(), rs,
1522 ignore_top ? 0 : style->borderTopWidth(), ignore_bottom ? 0 : style->borderBottomWidth());
1524 if (renderRadii && (!upperRightBorderStylesMatch || !lowerRightBorderStylesMatch)) {
1525 int topX = tx + w - topRight.width() * 2;
1527 int bottomY = ty + h - bottomRight.height() * 2;
1528 firstAngleStart = 0;
1529 secondAngleStart = 315;
1530 firstAngleSpan = secondAngleSpan = 45;
1531 thickness = style->borderRightWidth() * 2;
1533 bool applyTopInnerClip = (style->borderRightWidth() < topRight.width())
1534 && (style->borderTopWidth() < topRight.height())
1535 && (rs != DOUBLE || style->borderRightWidth() > 6);
1536 if (applyTopInnerClip) {
1537 graphicsContext->save();
1538 graphicsContext->addInnerRoundedRectClip(IntRect(topX, topY, topRight.width() * 2, topRight.height() * 2),
1539 style->borderRightWidth());
1542 // Draw top right arc
1543 drawBorderArc(graphicsContext, topX, topY, thickness, topRight, firstAngleStart, firstAngleSpan,
1544 BSRight, rc, style->color(), rs, true);
1545 if (applyTopInnerClip)
1546 graphicsContext->restore();
1548 bool applyBottomInnerClip = (style->borderRightWidth() < bottomRight.width())
1549 && (style->borderBottomWidth() < bottomRight.height())
1550 && (rs != DOUBLE || style->borderRightWidth() > 6);
1551 if (applyBottomInnerClip) {
1552 graphicsContext->save();
1553 graphicsContext->addInnerRoundedRectClip(IntRect(topX, bottomY, bottomRight.width() * 2, bottomRight.height() * 2),
1554 style->borderRightWidth());
1557 // Draw bottom right arc
1558 drawBorderArc(graphicsContext, topX, bottomY, thickness, bottomRight, secondAngleStart, secondAngleSpan,
1559 BSRight, rc, style->color(), rs, false);
1560 if (applyBottomInnerClip)
1561 graphicsContext->restore();
1566 graphicsContext->restore();
1569 void RenderObject::addLineBoxRects(Vector<IntRect>&, unsigned startOffset, unsigned endOffset)
1573 void RenderObject::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
1575 // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1576 // inline boxes above and below us (thus getting merged with them to form a single irregular
1578 if (continuation()) {
1579 rects.append(IntRect(tx, ty - collapsedMarginTop(),
1580 width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
1581 continuation()->absoluteRects(rects,
1582 tx - xPos() + continuation()->containingBlock()->xPos(),
1583 ty - yPos() + continuation()->containingBlock()->yPos());
1585 rects.append(IntRect(tx, ty, width(), height() + borderTopExtra() + borderBottomExtra()));
1588 IntRect RenderObject::absoluteBoundingBoxRect()
1591 absolutePosition(x, y);
1592 Vector<IntRect> rects;
1593 absoluteRects(rects, x, y);
1595 size_t n = rects.size();
1599 IntRect result = rects[0];
1600 for (size_t i = 1; i < n; ++i)
1601 result.unite(rects[i]);
1605 void RenderObject::addAbsoluteRectForLayer(IntRect& result)
1608 result.unite(absoluteBoundingBoxRect());
1609 for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1610 current->addAbsoluteRectForLayer(result);
1613 IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
1615 IntRect result = absoluteBoundingBoxRect();
1616 topLevelRect = result;
1617 for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1618 current->addAbsoluteRectForLayer(result);
1622 void RenderObject::addPDFURLRect(GraphicsContext* graphicsContext, IntRect rect)
1624 Node* node = element();
1626 if (graphicsContext) {
1627 if (rect.width() > 0 && rect.height() > 0) {
1628 Element* element = static_cast<Element*>(node);
1630 if (element->isLink())
1631 href = element->getAttribute(hrefAttr);
1633 if (!href.isNull()) {
1634 KURL link = element->document()->completeURL(href.deprecatedString());
1636 graphicsContext->setURLForRect(link, rect);
1644 void RenderObject::addFocusRingRects(GraphicsContext* graphicsContext, int tx, int ty)
1646 // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1647 // inline boxes above and below us (thus getting merged with them to form a single irregular
1649 if (continuation()) {
1650 graphicsContext->addFocusRingRect(IntRect(tx, ty - collapsedMarginTop(), width(), height() + collapsedMarginTop() + collapsedMarginBottom()));
1651 continuation()->addFocusRingRects(graphicsContext,
1652 tx - xPos() + continuation()->containingBlock()->xPos(),
1653 ty - yPos() + continuation()->containingBlock()->yPos());
1655 graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
1658 void RenderObject::paintOutline(GraphicsContext* graphicsContext, int tx, int ty, int w, int h, const RenderStyle* style)
1663 int ow = style->outlineWidth();
1665 EBorderStyle os = style->outlineStyle();
1667 Color oc = style->outlineColor();
1669 oc = style->color();
1671 int offset = style->outlineOffset();
1673 if (style->outlineStyleIsAuto() || hasOutlineAnnotation()) {
1674 if (!theme()->supportsFocusRing(style)) {
1675 // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
1676 graphicsContext->initFocusRing(ow, offset);
1677 if (style->outlineStyleIsAuto())
1678 addFocusRingRects(graphicsContext, tx, ty);
1680 addPDFURLRect(graphicsContext, graphicsContext->focusRingBoundingRect());
1681 graphicsContext->drawFocusRing(oc);
1682 graphicsContext->clearFocusRing();
1686 if (style->outlineStyleIsAuto() || style->outlineStyle() <= BHIDDEN)
1694 drawBorder(graphicsContext, tx - ow, ty - ow, tx, ty + h + ow,
1695 BSLeft, Color(oc), style->color(), os, ow, ow);
1697 drawBorder(graphicsContext, tx - ow, ty - ow, tx + w + ow, ty,
1698 BSTop, Color(oc), style->color(), os, ow, ow);
1700 drawBorder(graphicsContext, tx + w, ty - ow, tx + w + ow, ty + h + ow,
1701 BSRight, Color(oc), style->color(), os, ow, ow);
1703 drawBorder(graphicsContext, tx - ow, ty + h, tx + w + ow, ty + h + ow,
1704 BSBottom, Color(oc), style->color(), os, ow, ow);
1707 void RenderObject::paint(PaintInfo& /*paintInfo*/, int /*tx*/, int /*ty*/)
1711 void RenderObject::repaint(bool immediate)
1713 // Can't use view(), since we might be unrooted.
1714 RenderObject* o = this;
1717 if (!o->isRenderView())
1719 RenderView* view = static_cast<RenderView*>(o);
1720 if (view->printingMode())
1721 return; // Don't repaint if we're printing.
1722 view->repaintViewRectangle(getAbsoluteRepaintRect(), immediate);
1725 void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
1727 // Can't use view(), since we might be unrooted.
1728 RenderObject* o = this;
1731 if (!o->isRenderView())
1733 RenderView* view = static_cast<RenderView*>(o);
1734 if (view->printingMode())
1735 return; // Don't repaint if we're printing.
1737 computeAbsoluteRepaintRect(absRect);
1738 view->repaintViewRectangle(absRect, immediate);
1741 bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldFullBounds)
1743 RenderView* v = view();
1744 if (v->printingMode())
1745 return false; // Don't repaint if we're printing.
1747 IntRect newBounds, newFullBounds;
1748 getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
1749 if (newBounds == oldBounds && !selfNeedsLayout())
1752 bool fullRepaint = selfNeedsLayout() || newBounds.location() != oldBounds.location() || mustRepaintBackgroundOrBorder();
1754 v->repaintViewRectangle(oldFullBounds);
1755 if (newBounds != oldBounds)
1756 v->repaintViewRectangle(newFullBounds);
1760 // We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
1761 // two rectangles (but typically only one).
1762 int ow = style() ? style()->outlineSize() : 0;
1763 int width = abs(newBounds.width() - oldBounds.width());
1765 v->repaintViewRectangle(IntRect(min(newBounds.x() + newBounds.width(), oldBounds.x() + oldBounds.width()) - borderRight() - ow,
1767 width + borderRight() + ow,
1768 max(newBounds.height(), oldBounds.height())));
1769 int height = abs(newBounds.height() - oldBounds.height());
1771 v->repaintViewRectangle(IntRect(newBounds.x(),
1772 min(newBounds.bottom(), oldBounds.bottom()) - borderBottom() - ow,
1773 max(newBounds.width(), oldBounds.width()),
1774 height + borderBottom() + ow));
1778 void RenderObject::repaintDuringLayoutIfMoved(const IntRect& rect)
1782 void RenderObject::repaintOverhangingFloats(bool paintAllDescendants)
1786 bool RenderObject::checkForRepaintDuringLayout() const
1788 return !document()->view()->needsFullRepaint() && !layer();
1791 void RenderObject::repaintObjectsBeforeLayout()
1793 if (!needsLayout() || isText())
1796 bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
1797 if (selfNeedsLayout()) {
1799 if (blockWithInlineChildren)
1803 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1804 if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
1805 current->repaintObjectsBeforeLayout();
1809 IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
1811 IntRect r(getAbsoluteRepaintRect());
1814 if (continuation() && !isInline())
1815 r.inflateY(collapsedMarginTop());
1817 if (isInlineFlow()) {
1818 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
1819 if (!curr->isText())
1820 r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
1827 IntRect RenderObject::getAbsoluteRepaintRect()
1830 return parent()->getAbsoluteRepaintRect();
1834 void RenderObject::getAbsoluteRepaintRectIncludingFloats(IntRect& bounds, IntRect& fullBounds)
1836 bounds = fullBounds = getAbsoluteRepaintRect();
1839 void RenderObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
1842 return parent()->computeAbsoluteRepaintRect(r, f);
1845 void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
1851 DeprecatedString RenderObject::information() const
1853 DeprecatedString str;
1854 TextStream ts(&str);
1856 << "(" << (style() ? style()->refCount() : 0) << ")"
1857 << ": " << (void*)this << " ";
1860 if (childrenInline())
1866 if (isRelPositioned())
1874 if (style() && style()->zIndex())
1875 ts << "zI: " << style()->zIndex();
1877 if (element()->active())
1879 if (element()->isLink())
1881 if (element()->focused())
1883 ts << " <" << element()->localName().deprecatedString() << ">";
1884 ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")";
1885 if (isTableCell()) {
1886 const RenderTableCell* cell = static_cast<const RenderTableCell*>(this);
1887 ts << " [r=" << cell->row() << " c=" << cell->col() << " rs=" << cell->rowSpan() << " cs=" << cell->colSpan() << "]";
1893 void RenderObject::dump(TextStream* stream, DeprecatedString ind) const
1896 *stream << " anonymous";
1898 *stream << " floating";
1900 *stream << " positioned";
1901 if (isRelPositioned())
1902 *stream << " relPositioned";
1906 *stream << " inline";
1908 *stream << " replaced";
1909 if (shouldPaintBackgroundOrBorder())
1910 *stream << " paintBackground";
1912 *stream << " needsLayout";
1914 *stream << " minMaxKnown";
1917 RenderObject* child = firstChild();
1919 *stream << ind << child->renderName() << ": ";
1920 child->dump(stream, ind + " ");
1921 child = child->nextSibling();
1925 void RenderObject::showTreeForThis() const
1928 element()->showTreeForThis();
1933 static Node* selectStartNode(const RenderObject* object)
1936 bool forcedOn = false;
1938 for (const RenderObject* curr = object; curr; curr = curr->parent()) {
1939 if (curr->style()->userSelect() == SELECT_TEXT)
1941 if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
1945 node = curr->element();
1948 // somewhere up the render tree there must be an element!
1954 bool RenderObject::canSelect() const
1956 return selectStartNode(this) != 0;
1959 bool RenderObject::shouldSelect() const
1961 if (Node* node = selectStartNode(this))
1962 return EventTargetNodeCast(node)->dispatchHTMLEvent(selectstartEvent, true, true);
1967 Color RenderObject::selectionBackgroundColor() const
1970 if (style()->userSelect() != SELECT_NONE) {
1971 RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1972 if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
1973 color = pseudoStyle->backgroundColor().blendWithWhite();
1975 color = document()->frame()->isActive() ?
1976 theme()->activeSelectionBackgroundColor() :
1977 theme()->inactiveSelectionBackgroundColor();
1983 Color RenderObject::selectionForegroundColor() const
1986 if (style()->userSelect() != SELECT_NONE) {
1987 RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1989 color = pseudoStyle->color();
1991 color = document()->frame()->isActive() ?
1992 theme()->platformActiveSelectionForegroundColor() :
1993 theme()->platformInactiveSelectionForegroundColor();
1999 Node* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
2001 if (!dhtmlOK && !uaOK)
2004 for (const RenderObject* curr = this; curr; curr = curr->parent()) {
2005 Node* elt = curr->element();
2006 if (elt && elt->nodeType() == Node::TEXT_NODE) {
2007 // Since there's no way for the author to address the -webkit-user-drag style for a text node,
2008 // we use our own judgement.
2009 if (uaOK && view()->frameView()->frame()->eventHandler()->shouldDragAutoNode(curr->node(), IntPoint(x, y))) {
2010 dhtmlWillDrag = false;
2011 return curr->node();
2013 if (curr->shouldSelect())
2014 // In this case we have a click in the unselected portion of text. If this text is
2015 // selectable, we want to start the selection process instead of looking for a parent
2019 EUserDrag dragMode = curr->style()->userDrag();
2020 if (dhtmlOK && dragMode == DRAG_ELEMENT) {
2021 dhtmlWillDrag = true;
2022 return curr->node();
2024 if (uaOK && dragMode == DRAG_AUTO
2025 && view()->frameView()->frame()->eventHandler()->shouldDragAutoNode(curr->node(), IntPoint(x, y))) {
2026 dhtmlWillDrag = false;
2027 return curr->node();
2034 void RenderObject::selectionStartEnd(int& spos, int& epos)
2036 view()->selectionStartEnd(spos, epos);
2039 RenderBlock* RenderObject::createAnonymousBlock()
2041 RenderStyle* newStyle = new (renderArena()) RenderStyle();
2042 newStyle->inheritFrom(m_style);
2043 newStyle->setDisplay(BLOCK);
2045 RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
2046 newBox->setStyle(newStyle);
2050 void RenderObject::handleDynamicFloatPositionChange()
2052 // We have gone from not affecting the inline status of the parent flow to suddenly
2053 // having an impact. See if there is a mismatch between the parent flow's
2054 // childrenInline() state and our state.
2055 setInline(style()->isDisplayInlineType());
2056 if (isInline() != parent()->childrenInline()) {
2058 if (parent()->isRenderInline()) {
2059 // We have to split the parent flow.
2060 RenderInline* parentInline = static_cast<RenderInline*>(parent());
2061 RenderBlock* newBox = parentInline->createAnonymousBlock();
2063 RenderFlow* oldContinuation = parent()->continuation();
2064 parentInline->setContinuation(newBox);
2066 RenderObject* beforeChild = nextSibling();
2067 parent()->removeChildNode(this);
2068 parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
2069 } else if (parent()->isRenderBlock())
2070 static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
2072 // An anonymous block must be made to wrap this inline.
2073 RenderBlock* box = createAnonymousBlock();
2074 parent()->insertChildNode(box, this);
2075 box->appendChildNode(parent()->removeChildNode(this));
2080 void RenderObject::setStyle(RenderStyle* style)
2082 if (m_style == style)
2085 bool affectsParentBlock = false;
2086 RenderStyle::Diff d = RenderStyle::Equal;
2088 // If our z-index changes value or our visibility changes,
2089 // we need to dirty our stacking context's z-order list.
2092 if (m_style->visibility() != style->visibility() ||
2093 m_style->zIndex() != style->zIndex() ||
2094 m_style->hasAutoZIndex() != style->hasAutoZIndex())
2095 document()->setDashboardRegionsDirty(true);
2098 if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2099 m_style->zIndex() != style->zIndex() ||
2100 m_style->visibility() != style->visibility()) && layer()) {
2101 layer()->stackingContext()->dirtyZOrderLists();
2102 if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2103 m_style->visibility() != style->visibility())
2104 layer()->dirtyZOrderLists();
2106 // keep layer hierarchy visibility bits up to date if visibility changes
2107 if (m_style->visibility() != style->visibility()) {
2108 RenderLayer* l = enclosingLayer();
2109 if (style->visibility() == VISIBLE && l)
2110 l->setHasVisibleContent(true);
2111 else if (l && l->hasVisibleContent() &&
2112 (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE))
2113 l->dirtyVisibleContentStatus();
2117 d = m_style->diff(style);
2119 // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
2120 if (d == RenderStyle::RepaintLayer && !layer())
2121 d = RenderStyle::Repaint;
2123 // The background of the root element or the body element could propagate up to
2124 // the canvas. Just dirty the entire canvas when our style changes substantially.
2125 if (d >= RenderStyle::Repaint && element() &&
2126 (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
2128 else if (m_parent && !isText()) {
2129 // Do a repaint with the old style first, e.g., for example if we go from
2130 // having an outline to not having an outline.
2131 if (d == RenderStyle::RepaintLayer) {
2132 layer()->repaintIncludingDescendants();
2133 if (!(m_style->clip() == style->clip()))
2134 layer()->clearClipRects();
2135 } else if (d == RenderStyle::Repaint || style->outlineSize() < m_style->outlineSize())
2139 // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
2140 // end up being destroyed.
2141 if (d == RenderStyle::Layout && layer() &&
2142 (m_style->position() != style->position() ||
2143 m_style->zIndex() != style->zIndex() ||
2144 m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
2145 !(m_style->clip() == style->clip()) ||
2146 m_style->hasClip() != style->hasClip() ||
2147 m_style->opacity() != style->opacity()))
2148 layer()->repaintIncludingDescendants();
2150 // When a layout hint happens and an object's position style changes, we have to do a layout
2151 // to dirty the render tree using the old position value now.
2152 if (d == RenderStyle::Layout && m_parent && m_style->position() != style->position()) {
2153 markContainingBlocksForLayout();
2154 if (m_style->position() == StaticPosition)
2156 if (isRenderBlock()) {
2157 if (style->position() == StaticPosition)
2158 // Clear our positioned objects list. Our absolutely positioned descendants will be
2159 // inserted into our containing block's positioned objects list during layout.
2160 removePositionedObjects(0);
2161 else if (m_style->position() == StaticPosition) {
2162 // Remove our absolutely positioned descendants from their current containing block.
2163 // They will be inserted into our positioned objects list during layout.
2164 RenderObject* cb = parent();
2165 while (cb && (cb->style()->position() == StaticPosition || (cb->isInline() && !cb->isReplaced())) && !cb->isRoot() && !cb->isRenderView()) {
2166 if (cb->style()->position() == RelativePosition && cb->isInline() && !cb->isReplaced()) {
2167 cb = cb->containingBlock();
2172 cb->removePositionedObjects(static_cast<RenderBlock*>(this));
2177 if (isFloating() && (m_style->floating() != style->floating()))
2178 // For changes in float styles, we need to conceivably remove ourselves
2179 // from the floating objects list.
2180 removeFromObjectLists();
2181 else if (isPositioned() && (style->position() != AbsolutePosition && style->position() != FixedPosition))
2182 // For changes in positioning styles, we need to conceivably remove ourselves
2183 // from the positioned objects list.
2184 removeFromObjectLists();
2186 affectsParentBlock = m_style && isFloatingOrPositioned() &&
2187 (!style->isFloating() && style->position() != AbsolutePosition && style->position() != FixedPosition)
2188 && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
2190 // reset style flags
2192 m_positioned = false;
2193 m_relPositioned = false;
2194 m_paintBackground = false;
2195 m_hasOverflowClip = false;
2198 if (view()->frameView()) {
2199 // FIXME: A better solution would be to only invalidate the fixed regions when scrolling. It's overkill to
2200 // prevent the entire view from blitting on a scroll.
2201 bool oldStyleSlowScroll = style && (style->position() == FixedPosition || style->hasFixedBackgroundImage());
2202 bool newStyleSlowScroll = m_style && (m_style->position() == FixedPosition || m_style->hasFixedBackgroundImage());
2203 if (oldStyleSlowScroll != newStyleSlowScroll) {
2204 if (oldStyleSlowScroll)
2205 view()->frameView()->removeSlowRepaintObject();
2206 if (newStyleSlowScroll)
2207 view()->frameView()->addSlowRepaintObject();
2211 RenderStyle* oldStyle = m_style;
2214 updateBackgroundImages(oldStyle);
2220 oldStyle->deref(renderArena());
2222 setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance());
2224 if (affectsParentBlock)
2225 handleDynamicFloatPositionChange();
2227 // No need to ever schedule repaints from a style change of a text run, since
2228 // we already did this for the parent of the text run.
2229 if (d == RenderStyle::Layout && m_parent)
2230 setNeedsLayoutAndMinMaxRecalc();
2231 else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
2232 // Do a repaint with the new style now, e.g., for example if we go from
2233 // not having an outline to having an outline.
2237 void RenderObject::setStyleInternal(RenderStyle* style)
2239 if (m_style == style)
2242 m_style->deref(renderArena());
2248 void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
2250 // FIXME: This will be slow when a large number of images is used. Fix by using a dict.
2251 const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
2252 const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
2253 for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
2254 if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
2255 currOld->backgroundImage()->deref(this);
2257 for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
2258 if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
2259 currNew->backgroundImage()->ref(this);
2262 CachedImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
2263 CachedImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
2264 if (oldBorderImage != newBorderImage) {
2266 oldBorderImage->deref(this);
2268 newBorderImage->ref(this);
2272 IntRect RenderObject::viewRect() const
2274 return view()->viewRect();
2277 bool RenderObject::absolutePosition(int& xPos, int& yPos, bool f)
2279 RenderObject* o = parent();
2281 o->absolutePosition(xPos, yPos, f);
2282 yPos += o->borderTopExtra();
2283 if (o->hasOverflowClip())
2284 o->layer()->subtractScrollOffset(xPos, yPos);
2292 IntRect RenderObject::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
2294 if (extraWidthToEndOfLine)
2295 *extraWidthToEndOfLine = 0;
2300 int RenderObject::paddingTop() const
2303 Length padding = m_style->paddingTop();
2304 if (padding.isPercent())
2305 w = containingBlock()->contentWidth();
2306 w = padding.calcMinValue(w);
2307 if (isTableCell() && padding.isAuto())
2308 w = static_cast<const RenderTableCell*>(this)->table()->cellPadding();
2312 int RenderObject::paddingBottom() const
2315 Length padding = style()->paddingBottom();
2316 if (padding.isPercent())
2317 w = containingBlock()->contentWidth();
2318 w = padding.calcMinValue(w);
2319 if (isTableCell() && padding.isAuto())
2320 w = static_cast<const RenderTableCell*>(this)->table()->cellPadding();
2324 int RenderObject::paddingLeft() const
2327 Length padding = style()->paddingLeft();
2328 if (padding.isPercent())
2329 w = containingBlock()->contentWidth();
2330 w = padding.calcMinValue(w);
2331 if (isTableCell() && padding.isAuto())
2332 w = static_cast<const RenderTableCell*>(this)->table()->cellPadding();
2336 int RenderObject::paddingRight() const
2339 Length padding = style()->paddingRight();
2340 if (padding.isPercent())
2341 w = containingBlock()->contentWidth();
2342 w = padding.calcMinValue(w);
2343 if (isTableCell() && padding.isAuto())
2344 w = static_cast<const RenderTableCell*>(this)->table()->cellPadding();
2348 int RenderObject::tabWidth() const
2350 if (style()->collapseWhiteSpace())
2353 return containingBlock()->tabWidth(true);
2356 RenderView* RenderObject::view() const
2358 return static_cast<RenderView*>(document()->renderer());
2361 bool RenderObject::hasOutlineAnnotation() const
2363 return element() && element()->isLink() && document()->printing();
2366 RenderObject* RenderObject::container() const
2368 // This method is extremely similar to containingBlock(), but with a few notable
2370 // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
2371 // the object is not part of the primary document subtree yet.
2372 // (2) For normal flow elements, it just returns the parent.
2373 // (3) For absolute positioned elements, it will return a relative positioned inline.
2374 // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
2375 // the layout of the positioned object. This does mean that calcAbsoluteHorizontal and
2376 // calcAbsoluteVertical have to use container().
2377 EPosition pos = m_style->position();
2378 RenderObject* o = parent();
2379 if (!isText() && pos == FixedPosition) {
2380 // container() can be called on an object that is not in the
2381 // tree yet. We don't call view() since it will assert if it
2382 // can't get back to the canvas. Instead we just walk as high up
2383 // as we can. If we're in the tree, we'll get the root. If we
2384 // aren't we'll get the root of our little subtree (most likely
2385 // we'll just return 0).
2386 while (o && o->parent())
2388 } else if (!isText() && pos == AbsolutePosition) {
2389 // Same goes here. We technically just want our containing block, but
2390 // we may not have one if we're part of an uninstalled subtree. We'll
2391 // climb as high as we can though.
2392 while (o && o->style()->position() == StaticPosition && !o->isRenderView())
2399 // This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
2400 // content (and perhaps XBL). That's why it uses the render tree and not the DOM tree.
2401 RenderObject* RenderObject::hoverAncestor() const
2403 return (!isInline() && continuation()) ? continuation() : parent();
2406 bool RenderObject::isSelectionBorder() const
2408 SelectionState st = selectionState();
2409 return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
2412 void RenderObject::removeFromObjectLists()
2414 if (documentBeingDestroyed())
2418 RenderBlock* outermostBlock = containingBlock();
2419 for (RenderBlock* p = outermostBlock; p && !p->isRenderView(); p = p->containingBlock()) {
2420 if (p->containsFloat(this))
2425 outermostBlock->markAllDescendantsWithFloatsForLayout(this);
2428 if (isPositioned()) {
2430 for (p = parent(); p; p = p->parent()) {
2431 if (p->isRenderBlock())
2432 static_cast<RenderBlock*>(p)->removePositionedObject(this);
2437 RenderArena* RenderObject::renderArena() const
2439 Document* doc = document();
2440 return doc ? doc->renderArena() : 0;
2443 bool RenderObject::documentBeingDestroyed() const
2445 return !document()->renderer();
2448 void RenderObject::destroy()
2450 // If this renderer is being autoscrolled, stop the autoscroll timer
2451 if (document() && document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this)
2452 document()->frame()->eventHandler()->stopAutoscrollTimer(true);
2454 if (m_hasCounterNodeMap) {
2455 RenderObjectsToCounterNodeMaps* objectsMap = getRenderObjectsToCounterNodeMaps();
2456 if (CounterNodeMap* counterNodesMap = objectsMap->get(this)) {
2457 CounterNodeMap::const_iterator end = counterNodesMap->end();
2458 for (CounterNodeMap::const_iterator it = counterNodesMap->begin(); it != end; ++it) {
2459 CounterNode* counterNode = it->second;
2460 counterNode->remove();
2464 objectsMap->remove(this);
2465 delete counterNodesMap;
2469 document()->axObjectCache()->remove(this);
2471 // By default no ref-counting. RenderWidget::destroy() doesn't call
2472 // this function because it needs to do ref-counting. If anything
2473 // in this function changes, be sure to fix RenderWidget::destroy() as well.
2477 arenaDelete(document()->renderArena(), this);
2480 void RenderObject::arenaDelete(RenderArena* arena, void* base)
2482 if (m_style->backgroundImage())
2483 m_style->backgroundImage()->deref(this);
2485 m_style->deref(arena);
2488 void* savedBase = baseOfRenderObjectBeingDeleted;
2489 baseOfRenderObjectBeingDeleted = base;
2493 baseOfRenderObjectBeingDeleted = savedBase;
2496 // Recover the size left there for us by operator delete and free the memory.
2497 arena->free(*(size_t*)base, base);
2500 VisiblePosition RenderObject::positionForCoordinates(int x, int y)
2502 return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
2505 void RenderObject::updateDragState(bool dragOn)
2507 bool valueChanged = (dragOn != m_isDragging);
2508 m_isDragging = dragOn;
2509 if (valueChanged && style()->affectedByDragRules())
2510 element()->setChanged();
2511 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2512 curr->updateDragState(dragOn);
2514 continuation()->updateDragState(dragOn);
2517 bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
2519 bool inside = false;
2520 if (hitTestFilter != HitTestSelf) {
2521 // First test the foreground layer (lines and inlines).
2522 inside = nodeAtPoint(request, result, x, y, tx, ty, HitTestForeground);
2524 // Test floats next.
2526 inside = nodeAtPoint(request, result, x, y, tx, ty, HitTestFloat);
2528 // Finally test to see if the mouse is in the background (within a child block's background).
2530 inside = nodeAtPoint(request, result, x, y, tx, ty, HitTestChildBlockBackgrounds);
2533 // See if the mouse is inside us but not any of our descendants
2534 if (hitTestFilter != HitTestDescendants && !inside)
2535 inside = nodeAtPoint(request, result, x, y, tx, ty, HitTestBlockBackground);
2540 void RenderObject::setInnerNode(HitTestResult& result)
2542 if (result.innerNode())
2545 Node* node = element();
2547 node = document()->documentElement();
2548 else if (!isInline() && continuation())
2549 // We are in the margins of block elements that are part of a continuation. In
2550 // this case we're actually still inside the enclosing inline element that was
2551 // split. Go ahead and set our inner node accordingly.
2552 node = continuation()->element();
2555 result.setInnerNode(node);
2556 if (!result.innerNonSharedNode())
2557 result.setInnerNonSharedNode(node);
2561 bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, int /*x*/, int /*y*/, int /*tx*/, int /*ty*/, HitTestAction)
2566 short RenderObject::verticalPositionHint(bool firstLine) const
2568 short vpos = m_verticalPosition;
2569 if (m_verticalPosition == PositionUndefined || firstLine) {
2570 vpos = getVerticalPosition(firstLine);
2572 m_verticalPosition = vpos;
2578 short RenderObject::getVerticalPosition(bool firstLine) const
2583 // This method determines the vertical position for inline elements.
2585 EVerticalAlign va = style()->verticalAlign();
2588 else if (va == BOTTOM)
2589 vpos = PositionBottom;
2590 else if (va == LENGTH)
2591 vpos = -style()->verticalAlignLength().calcValue(lineHeight(firstLine));
2593 bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
2594 vpos = checkParent ? parent()->verticalPositionHint(firstLine) : 0;
2595 // don't allow elements nested inside text-top to have a different valignment.
2599 const Font& f = parent()->font(firstLine);
2600 int fontsize = f.pixelSize();
2603 vpos += fontsize / 5 + 1;
2604 else if (va == SUPER)
2605 vpos -= fontsize / 3 + 1;
2606 else if (va == TEXT_TOP)
2607 vpos += baselinePosition(firstLine) - f.ascent();
2608 else if (va == MIDDLE)
2609 vpos += -static_cast<int>(f.xHeight() / 2) - lineHeight(firstLine) / 2 + baselinePosition(firstLine);
2610 else if (va == TEXT_BOTTOM) {
2611 vpos += f.descent();
2613 vpos -= font(firstLine).descent();
2614 } else if (va == BASELINE_MIDDLE)
2615 vpos += -lineHeight(firstLine) / 2 + baselinePosition(firstLine);
2621 short RenderObject::lineHeight(bool firstLine, bool /*isRootLineBox*/) const
2623 RenderStyle* s = style(firstLine);
2625 Length lh = s->lineHeight();
2627 // its "unset", choose nice default
2629 return s->font().lineSpacing();
2632 return lh.calcMinValue(s->fontSize());
2638 short RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
2640 const Font& f = font(firstLine);
2641 return f.ascent() + (lineHeight(firstLine, isRootLineBox) - f.height()) / 2;
2644 void RenderObject::invalidateVerticalPositions()
2646 m_verticalPosition = PositionUndefined;
2647 RenderObject* child = firstChild();
2649 child->invalidateVerticalPositions();
2650 child = child->nextSibling();
2654 void RenderObject::recalcMinMaxWidths()
2656 ASSERT(m_recalcMinMax);
2659 updateFirstLetter();
2661 RenderObject* child = firstChild();
2666 if ((m_minMaxKnown && child->m_recalcMinMax) || !child->m_minMaxKnown) {
2667 cmin = child->minWidth();
2668 cmax = child->maxWidth();
2671 if (child->m_recalcMinMax)
2672 child->recalcMinMaxWidths();
2673 if (!child->m_minMaxKnown)
2674 child->calcMinMaxWidth();
2675 if (m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()))
2676 m_minMaxKnown = false;
2677 child = child->nextSibling();
2680 // we need to recalculate, if the contains inline children, as the change could have
2681 // happened somewhere deep inside the child tree. Also do this for blocks or tables that
2682 // are inline (i.e., inline-block and inline-table).
2683 if ((!isInline() || isInlineBlockOrInlineTable()) && childrenInline())
2684 m_minMaxKnown = false;
2688 m_recalcMinMax = false;
2691 void RenderObject::scheduleRelayout()
2693 if (isRenderView()) {
2694 FrameView* view = static_cast<RenderView*>(this)->frameView();
2696 view->scheduleRelayout();
2698 FrameView* v = view() ? view()->frameView() : 0;
2700 v->scheduleRelayoutOfSubtree(node());
2704 void RenderObject::removeLeftoverAnonymousBoxes()
2708 InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
2710 ASSERT(!isRootLineBox);
2711 return new (renderArena()) InlineBox(this);
2714 void RenderObject::dirtyLineBoxes(bool, bool)
2718 InlineBox* RenderObject::inlineBoxWrapper() const
2723 void RenderObject::setInlineBoxWrapper(InlineBox*)
2727 void RenderObject::deleteLineBoxWrapper()
2731 RenderStyle* RenderObject::firstLineStyle() const
2733 RenderStyle* s = m_style;
2734 const RenderObject* obj = isText() ? parent() : this;
2735 if (obj->isBlockFlow()) {
2736 RenderBlock* firstLineBlock = obj->firstLineBlock();
2738 s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style());
2739 } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
2740 RenderStyle* parentStyle = obj->parent()->firstLineStyle();
2741 if (parentStyle != obj->parent()->style()) {
2742 // A first-line style is in effect. We need to cache a first-line style
2744 style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
2745 s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
2751 RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
2753 if (!style()->hasPseudoStyle(pseudo))
2757 parentStyle = style();
2759 RenderStyle* result = style()->getPseudoStyle(pseudo);
2763 Node* node = element();
2765 node = element()->parentNode();
2769 if (pseudo == RenderStyle::FIRST_LINE_INHERITED) {
2770 result = document()->styleSelector()->styleForElement(static_cast<Element*>(node), parentStyle, false);
2771 result->setStyleType(RenderStyle::FIRST_LINE_INHERITED);
2773 result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<Element*>(node), parentStyle);
2775 style()->addPseudoStyle(result);
2776 result->deref(document()->renderArena());
2781 void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
2782 Color& linethrough, bool quirksMode)
2784 RenderObject* curr = this;
2786 int currDecs = curr->style()->textDecoration();
2788 if (currDecs & UNDERLINE) {
2789 decorations &= ~UNDERLINE;
2790 underline = curr->style()->color();
2792 if (currDecs & OVERLINE) {
2793 decorations &= ~OVERLINE;
2794 overline = curr->style()->color();
2796 if (currDecs & LINE_THROUGH) {
2797 decorations &= ~LINE_THROUGH;
2798 linethrough = curr->style()->color();
2801 curr = curr->parent();
2802 if (curr && curr->isRenderBlock() && curr->continuation())
2803 curr = curr->continuation();
2804 } while (curr && decorations && (!quirksMode || !curr->element() ||
2805 (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
2807 // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2808 if (decorations && curr) {
2809 if (decorations & UNDERLINE)
2810 underline = curr->style()->color();
2811 if (decorations & OVERLINE)
2812 overline = curr->style()->color();
2813 if (decorations & LINE_THROUGH)
2814 linethrough = curr->style()->color();
2818 void RenderObject::updateWidgetPosition()
2822 void RenderObject::addDashboardRegions(Vector<DashboardRegionValue>& regions)
2824 // Convert the style regions to absolute coordinates.
2825 if (style()->visibility() != VISIBLE)
2828 const Vector<StyleDashboardRegion>& styleRegions = style()->dashboardRegions();
2829 unsigned i, count = styleRegions.size();
2830 for (i = 0; i < count; i++) {
2831 StyleDashboardRegion styleRegion = styleRegions[i];
2836 DashboardRegionValue region;
2837 region.label = styleRegion.label;
2838 region.bounds = IntRect(styleRegion.offset.left.value(),
2839 styleRegion.offset.top.value(),
2840 w - styleRegion.offset.left.value() - styleRegion.offset.right.value(),
2841 h - styleRegion.offset.top.value() - styleRegion.offset.bottom.value());
2842 region.type = styleRegion.type;
2844 region.clip = region.bounds;
2845 computeAbsoluteRepaintRect(region.clip);
2846 if (region.clip.height() < 0) {
2847 region.clip.setHeight(0);
2848 region.clip.setWidth(0);
2852 absolutePosition(x, y);
2853 region.bounds.setX(x + styleRegion.offset.left.value());
2854 region.bounds.setY(y + styleRegion.offset.top.value());
2856 if (document()->frame()) {
2857 float pageScaleFactor = document()->frame()->page()->chrome()->scaleFactor();
2858 if (pageScaleFactor != 1.0f) {
2859 region.bounds.scale(pageScaleFactor);
2860 region.clip.scale(pageScaleFactor);
2864 regions.append(region);
2868 void RenderObject::collectDashboardRegions(Vector<DashboardRegionValue>& regions)
2870 // RenderTexts don't have their own style, they just use their parent's style,
2871 // so we don't want to include them.
2875 addDashboardRegions(regions);
2876 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2877 curr->collectDashboardRegions(regions);
2880 void RenderObject::collectBorders(DeprecatedValueList<CollapsedBorderValue>& borderStyles)
2882 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2883 curr->collectBorders(borderStyles);
2886 bool RenderObject::avoidsFloats() const
2888 return isReplaced() || hasOverflowClip() || isHR();
2891 bool RenderObject::usesLineWidth() const
2893 // 1. All auto-width objects that avoid floats should always use lineWidth
2894 // 2. For objects with a specified width, we match WinIE's behavior:
2895 // (a) tables use contentWidth
2896 // (b) <hr>s use lineWidth
2897 // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
2898 return (avoidsFloats() && (style()->width().isAuto() || isHR() || (style()->htmlHacks() && !isTable())));
2901 CounterNode* RenderObject::findCounter(const String& counterName, bool willNeedLayout,
2902 bool usesSeparator, bool createIfNotFound)
2907 RenderObjectsToCounterNodeMaps* objectsMap = getRenderObjectsToCounterNodeMaps();
2908 CounterNode* newNode = 0;
2909 if (CounterNodeMap* counterNodesMap = objectsMap->get(this)) {
2910 if (counterNodesMap)
2911 newNode = counterNodesMap->get(counterName);
2918 if (style()->hasCounterReset(counterName) || isRoot()) {
2919 newNode = new CounterResetNode(this);
2920 val = style()->counterReset(counterName);
2921 if (style()->hasCounterIncrement(counterName))
2922 val += style()->counterIncrement(counterName);
2923 newNode->setValue(val);
2924 } else if (style()->hasCounterIncrement(counterName)) {
2925 newNode = new CounterNode(this);
2926 newNode->setValue(style()->counterIncrement(counterName));
2927 } else if (counterName == "list-item") {
2930 String v = static_cast<Element*>(element())->getAttribute("value");
2932 newNode = new CounterResetNode(this);
2938 newNode = new CounterNode(this);
2942 newNode->setValue(val);
2943 } else if (element() && element()->hasTagName(olTag)) {
2944 newNode = new CounterResetNode(this);
2945 newNode->setValue(static_cast<HTMLOListElement*>(element())->start());
2946 } else if (element() &&
2947 (element()->hasTagName(ulTag) ||
2948 element()->hasTagName(menuTag) ||
2949 element()->hasTagName(dirTag))) {
2950 newNode = new CounterResetNode(this);
2951 newNode->setValue(0);
2955 if (!newNode && !createIfNotFound)
2957 else if (!newNode) {
2958 newNode = new CounterNode(this);
2959 newNode->setValue(0);
2963 newNode->setWillNeedLayout();
2965 newNode->setUsesSeparator();
2967 CounterNodeMap* nodeMap;
2968 if (m_hasCounterNodeMap)
2969 nodeMap = objectsMap->get(this);
2971 nodeMap = new CounterNodeMap;
2972 objectsMap->set(this, nodeMap);
2973 m_hasCounterNodeMap = true;
2976 nodeMap->set(counterName, newNode);
2979 RenderObject* n = !isListItem() && previousSibling()
2980 ? previousSibling()->previousSibling() : previousSibling();
2982 CounterNode* current = 0;
2983 for (; n; n = n->previousSibling()) {
2984 current = n->findCounter(counterName, false, false, false);
2989 CounterNode* last = current;
2990 CounterNode* sibling = current;
2991 if (last && !newNode->isReset()) {
2992 // Found render-sibling, now search for later counter-siblings among its render-children
2995 current = n->findCounter(counterName, false, false, false);
2996 if (current && (last->parent() == current->parent() || sibling == current->parent())) {
2998 // If the current counter is not the last, search deeper
2999 if (current->nextSibling()) {
3005 n = n->previousSibling();
3008 if (sibling->isReset()) {
3009 if (last != sibling)
3010 sibling->insertAfter(newNode, last);
3012 sibling->insertAfter(newNode, 0);
3014 last->parent()->insertAfter(newNode, last);
3016 // Nothing found among siblings, let our parent search
3017 last = parent()->findCounter(counterName, false);
3018 if (last->isReset())
3019 last->insertAfter(newNode, 0);
3021 last->parent()->insertAfter(newNode, last);
3028 UChar RenderObject::backslashAsCurrencySymbol() const
3030 if (Node *node = element()) {
3031 if (TextResourceDecoder* decoder = node->document()->decoder())
3032 return decoder->encoding().backslashAsCurrencySymbol();
3037 void RenderObject::imageChanged(CachedImage* image)
3039 // Repaint when the background image or border image finishes loading.
3040 // This is needed for RenderBox objects, and also for table objects that hold
3041 // backgrounds that are then respected by the table cells (which are RenderBox
3042 // subclasses). It would be even better to find a more elegant way of doing this that
3043 // would avoid putting this function and the CachedResourceClient base class into RenderObject.
3044 if (image && image->canRender() && parent()) {
3045 if (view() && element() && (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
3046 // repaint the entire canvas since the background gets propagated up
3049 // repaint object, which is a box or a container with boxes inside it
3054 bool RenderObject::willRenderImage(CachedImage*)
3056 // Without visibility we won't render (and therefore don't care about animation).
3057 if (style()->visibility() != VISIBLE)
3060 // If we're not in a window (i.e., we're dormant from being put in the b/f cache or in a background tab)
3061 // then we don't want to render either.
3062 return !document()->inPageCache() && document()->view()->inWindow();
3065 int RenderObject::maximalOutlineSize(PaintPhase p) const
3067 if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
3069 return static_cast<RenderView*>(document()->renderer())->maximalOutlineSize();
3072 int RenderObject::caretMinOffset() const
3077 int RenderObject::caretMaxOffset() const
3079 return isReplaced() ? 1 : 0;
3082 unsigned RenderObject::caretMaxRenderedOffset() const
3087 int RenderObject::previousOffset(int current) const
3092 int RenderObject::nextOffset(int current) const
3097 InlineBox* RenderObject::inlineBox(int offset, EAffinity affinity)
3099 return inlineBoxWrapper();
3102 int RenderObject::maxTopMargin(bool positive) const
3104 return positive ? max(0, marginTop()) : -min(0, marginTop());
3107 int RenderObject::maxBottomMargin(bool positive) const
3109 return positive ? max(0, marginBottom()) : -min(0, marginBottom());
3114 FloatRect RenderObject::relativeBBox(bool) const
3119 AffineTransform RenderObject::localTransform() const
3121 return AffineTransform(1, 0, 0, 1, xPos(), yPos());
3124 void RenderObject::setLocalTransform(const AffineTransform&)
3129 AffineTransform RenderObject::absoluteTransform() const
3132 return localTransform() * parent()->absoluteTransform();
3133 return localTransform();
3136 #endif // SVG_SUPPORT
3138 } // namespace WebCore
3142 void showTree(const WebCore::RenderObject* ro)
3145 ro->showTreeForThis();