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 * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
27 #include "render_object.h"
29 #include "CachedImage.h"
30 #include "DocumentImpl.h"
31 #include "EventNames.h"
32 #include "FloatRect.h"
34 #include "FrameView.h"
35 #include "GraphicsContext.h"
36 #include "IntPointArray.h"
37 #include "KWQAccObjectCache.h"
38 #include "RenderBlock.h"
39 #include "RenderTable.h"
40 #include "RenderTableCell.h"
41 #include "RenderTableCol.h"
42 #include "RenderTableRow.h"
43 #include "RenderText.h"
44 #include "cssstyleselector.h"
45 #include "dom2_eventsimpl.h"
46 #include "dom_elementimpl.h"
47 #include "dom_position.h"
48 #include "htmlnames.h"
49 #include "render_arena.h"
50 #include "render_canvas.h"
51 #include "render_flexbox.h"
52 #include "render_inline.h"
53 #include "render_line.h"
54 #include "render_list.h"
55 #include "render_theme.h"
56 #include "VisiblePosition.h"
58 #include "TextEncoding.h"
59 #include <qtextstream.h>
63 using namespace EventNames;
64 using namespace HTMLNames;
67 static void *baseOfRenderObjectBeingDeleted;
70 void* RenderObject::operator new(size_t sz, RenderArena* renderArena) throw()
72 return renderArena->allocate(sz);
75 void RenderObject::operator delete(void* ptr, size_t sz)
77 ASSERT(baseOfRenderObjectBeingDeleted == ptr);
79 // Stash size where destroy can find it.
83 RenderObject *RenderObject::createObject(DOM::NodeImpl* node, RenderStyle* style)
86 RenderArena* arena = node->getDocument()->renderArena();
87 switch(style->display())
92 o = new (arena) RenderInline(node);
95 o = new (arena) RenderBlock(node);
98 o = new (arena) RenderBlock(node);
101 o = new (arena) RenderListItem(node);
105 o = new (arena) RenderBlock(node);
109 o = new (arena) RenderTable(node);
111 case TABLE_ROW_GROUP:
112 case TABLE_HEADER_GROUP:
113 case TABLE_FOOTER_GROUP:
114 o = new (arena) RenderTableSection(node);
117 o = new (arena) RenderTableRow(node);
119 case TABLE_COLUMN_GROUP:
121 o = new (arena) RenderTableCol(node);
124 o = new (arena) RenderTableCell(node);
127 o = new (arena) RenderBlock(node);
131 o = new (arena) RenderFlexibleBox(node);
138 struct RenderObjectCounter {
140 ~RenderObjectCounter() { if (count != 0) fprintf(stderr, "LEAK: %d RenderObject\n", count); }
142 int RenderObjectCounter::count;
143 static RenderObjectCounter renderObjectCounter;
146 RenderObject::RenderObject(DOM::NodeImpl* node)
147 : CachedObjectClient(),
153 m_verticalPosition( PositionUndefined ),
154 m_needsLayout( false ),
155 m_normalChildNeedsLayout( false ),
156 m_posChildNeedsLayout( false ),
157 m_minMaxKnown( false ),
160 m_positioned( false ),
161 m_relPositioned( false ),
162 m_paintBackground( false ),
164 m_isAnonymous( node == node->getDocument() ),
165 m_recalcMinMax( false ),
170 m_isDragging( false ),
171 m_hasOverflowClip(false)
174 ++RenderObjectCounter::count;
178 RenderObject::~RenderObject()
181 --RenderObjectCounter::count;
185 bool RenderObject::hasAncestor(const RenderObject *obj) const
187 for (const RenderObject *r = this; r; r = r->m_parent)
193 bool RenderObject::isRoot() const
195 return element() && element()->renderer() == this &&
196 element()->getDocument()->documentElement() == element();
199 bool RenderObject::isBody() const
201 return element() && element()->renderer() == this && element()->hasTagName(bodyTag);
204 bool RenderObject::isHR() const
206 return element() && element()->hasTagName(hrTag);
209 bool RenderObject::isHTMLMarquee() const
211 return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
214 bool RenderObject::canHaveChildren() const
219 RenderFlow* RenderObject::continuation() const
224 bool RenderObject::isInlineContinuation() const
229 void RenderObject::addChild(RenderObject* , RenderObject *)
234 RenderObject* RenderObject::removeChildNode(RenderObject* )
240 void RenderObject::removeChild(RenderObject* )
245 void RenderObject::appendChildNode(RenderObject*)
250 void RenderObject::insertChildNode(RenderObject*, RenderObject*)
255 RenderObject *RenderObject::nextRenderer() const
261 return nextSibling();
263 const RenderObject *r = this;
264 while (r && !r->nextSibling())
267 return r->nextSibling();
272 RenderObject *RenderObject::previousRenderer() const
274 if (previousSibling()) {
275 RenderObject *r = previousSibling();
276 while (r->lastChild())
284 bool RenderObject::isEditable() const
286 RenderText *textRenderer = 0;
288 textRenderer = static_cast<RenderText *>(const_cast<RenderObject *>(this));
291 return style()->visibility() == VISIBLE &&
292 element() && element()->isContentEditable() &&
293 ((isBlockFlow() && !firstChild()) ||
296 (textRenderer && textRenderer->firstTextBox()));
299 RenderObject *RenderObject::nextEditable() const
301 RenderObject *r = const_cast<RenderObject *>(this);
302 RenderObject *n = firstChild();
311 return r->nextEditable();
313 n = r->nextSibling();
323 return r->nextEditable();
328 n = r->nextSibling();
339 return r->nextEditable();
346 RenderObject *RenderObject::previousEditable() const
348 RenderObject *r = const_cast<RenderObject *>(this);
349 RenderObject *n = firstChild();
358 return r->previousEditable();
360 n = r->previousSibling();
370 return r->previousEditable();
375 n = r->previousSibling();
386 return r->previousEditable();
393 RenderObject *RenderObject::firstLeafChild() const
395 RenderObject *r = firstChild();
406 RenderObject *RenderObject::lastLeafChild() const
408 RenderObject *r = lastChild();
419 static void addLayers(RenderObject* obj, RenderLayer* parentLayer, RenderObject*& newObject,
420 RenderLayer*& beforeChild)
423 if (!beforeChild && newObject) {
424 // We need to figure out the layer that follows newObject. We only do
425 // this the first time we find a child layer, and then we update the
426 // pointer values for newObject and beforeChild used by everyone else.
427 beforeChild = newObject->parent()->findNextLayer(parentLayer, newObject);
430 parentLayer->addChild(obj->layer(), beforeChild);
434 for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
435 addLayers(curr, parentLayer, newObject, beforeChild);
438 void RenderObject::addLayers(RenderLayer* parentLayer, RenderObject* newObject)
443 RenderObject* object = newObject;
444 RenderLayer* beforeChild = 0;
445 WebCore::addLayers(this, parentLayer, object, beforeChild);
448 void RenderObject::removeLayers(RenderLayer* parentLayer)
454 parentLayer->removeChild(layer());
458 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
459 curr->removeLayers(parentLayer);
462 void RenderObject::moveLayers(RenderLayer* oldParent, RenderLayer* newParent)
469 oldParent->removeChild(layer());
470 newParent->addChild(layer());
474 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
475 curr->moveLayers(oldParent, newParent);
478 RenderLayer* RenderObject::findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint,
481 // Error check the parent layer passed in. If it's null, we can't find anything.
485 // Step 1: Descend into our siblings trying to find the next layer. If we do find
486 // a layer, and if its parent layer matches our desired parent layer, then we have
488 for (RenderObject* curr = startPoint ? startPoint->nextSibling() : firstChild();
489 curr; curr = curr->nextSibling()) {
490 RenderLayer* nextLayer = curr->findNextLayer(parentLayer, 0, false);
492 if (nextLayer->parent() == parentLayer)
498 // Step 2: If our layer is the desired parent layer, then we're finished. We didn't
500 RenderLayer* ourLayer = layer();
501 if (parentLayer == ourLayer)
504 // Step 3: If we have a layer, then return that layer. It will be checked against
505 // the desired parent layer in the for loop above.
509 // Step 4: If |checkParent| is set, climb up to our parent and check its siblings that
510 // follow us to see if we can locate a layer.
511 if (checkParent && parent())
512 return parent()->findNextLayer(parentLayer, this, true);
517 RenderLayer* RenderObject::enclosingLayer()
519 RenderObject* curr = this;
521 RenderLayer *layer = curr->layer();
524 curr = curr->parent();
529 bool RenderObject::requiresLayer()
531 return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip();
534 RenderBlock* RenderObject::firstLineBlock() const
539 void RenderObject::updateFirstLetter()
542 int RenderObject::offsetLeft() const
545 if (!isPositioned()) {
546 if (isRelPositioned()) {
548 ((RenderBox*)this)->relativePositionOffset(x, y);
551 RenderObject* offsetPar = offsetParent();
552 RenderObject* curr = parent();
553 while (curr && curr != offsetPar) {
555 curr = curr->parent();
561 int RenderObject::offsetTop() const
564 if (!isPositioned()) {
565 if (isRelPositioned()) {
567 ((RenderBox*)this)->relativePositionOffset(x, y);
569 RenderObject* offsetPar = offsetParent();
570 RenderObject* curr = parent();
571 while (curr && curr != offsetPar) {
573 curr = curr->parent();
579 RenderObject* RenderObject::offsetParent() const
581 // FIXME: It feels like this function could almost be written using containing blocks.
582 bool skipTables = isPositioned() || isRelPositioned();
583 RenderObject* curr = parent();
584 while (curr && (!curr->element() ||
585 (!curr->isPositioned() && !curr->isRelPositioned() &&
586 !(!style()->htmlHacks() && skipTables ? curr->isRoot() : curr->isBody())))) {
587 if (!skipTables && curr->element() && (curr->isTableCell() || curr->isTable()))
589 curr = curr->parent();
594 // More IE extensions. clientWidth and clientHeight represent the interior of an object
595 // excluding border and scrollbar.
597 RenderObject::clientWidth() const
599 return width() - borderLeft() - borderRight() -
600 (includeScrollbarSize() ? layer()->verticalScrollbarWidth() : 0);
604 RenderObject::clientHeight() const
606 return height() - borderTop() - borderBottom() -
607 (includeScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0);
610 // scrollWidth/scrollHeight will be the same as clientWidth/clientHeight unless the
611 // object has overflow:hidden/scroll/auto specified and also has overflow.
613 RenderObject::scrollWidth() const
615 return hasOverflowClip() ? layer()->scrollWidth() : overflowWidth();
619 RenderObject::scrollHeight() const
621 return hasOverflowClip() ? layer()->scrollHeight() : overflowHeight();
624 bool RenderObject::scroll(KWQScrollDirection direction, KWQScrollGranularity granularity, float multiplier)
626 RenderLayer *l = layer();
627 if (l != 0 && l->scroll(direction, granularity, multiplier)) {
630 RenderBlock *b = containingBlock();
631 if (b != 0 && !b->isCanvas()) {
632 return b->scroll(direction, granularity, multiplier);
638 RenderObject::hasStaticX() const
640 return (style()->left().isAuto() && style()->right().isAuto()) ||
641 style()->left().isStatic() ||
642 style()->right().isStatic();
646 RenderObject::hasStaticY() const
648 return (style()->top().isAuto() && style()->bottom().isAuto()) || style()->top().isStatic();
651 void RenderObject::markAllDescendantsWithFloatsForLayout(RenderObject*)
655 void RenderObject::setNeedsLayout(bool b, bool markParents)
657 bool alreadyNeededLayout = m_needsLayout;
660 if (!alreadyNeededLayout && markParents)
661 markContainingBlocksForLayout();
664 m_posChildNeedsLayout = false;
665 m_normalChildNeedsLayout = false;
669 void RenderObject::setChildNeedsLayout(bool b, bool markParents)
671 bool alreadyNeededLayout = m_normalChildNeedsLayout;
672 m_normalChildNeedsLayout = b;
674 if (!alreadyNeededLayout && markParents)
675 markContainingBlocksForLayout();
678 m_posChildNeedsLayout = false;
679 m_normalChildNeedsLayout = false;
683 void RenderObject::markContainingBlocksForLayout()
685 RenderObject *o = container();
686 RenderObject *last = this;
689 if (!last->isText() && (last->style()->position() == FixedPosition || last->style()->position() == AbsolutePosition)) {
690 if (o->m_posChildNeedsLayout)
692 o->m_posChildNeedsLayout = true;
695 if (o->m_normalChildNeedsLayout)
697 o->m_normalChildNeedsLayout = true;
704 last->scheduleRelayout();
707 RenderBlock* RenderObject::containingBlock() const
710 return static_cast<const RenderTableCell *>(this)->table();
712 return (RenderBlock*)this;
714 RenderObject *o = parent();
715 if (!isText() && m_style->position() == FixedPosition) {
716 while ( o && !o->isCanvas() )
719 else if (!isText() && m_style->position() == AbsolutePosition) {
720 while (o && (o->style()->position() == StaticPosition || (o->isInline() && !o->isReplaced()))
721 && !o->isRoot() && !o->isCanvas()) {
722 // For relpositioned inlines, we return the nearest enclosing block. We don't try
723 // to return the inline itself. This allows us to avoid having a positioned objects
724 // list in all RenderInlines and lets us return a strongly-typed RenderBlock* result
725 // from this method. The container() method can actually be used to obtain the
727 if (o->style()->position() == RelativePosition && o->isInline() && !o->isReplaced())
728 return o->containingBlock();
732 while (o && ((o->isInline() && !o->isReplaced()) || o->isTableRow() || o->isTableSection()
733 || o->isTableCol() || o->isFrameSet()
735 || o->isKCanvasContainer()
741 if (!o || !o->isRenderBlock())
742 return 0; // Probably doesn't happen any more, but leave just in case. -dwh
744 return static_cast<RenderBlock*>(o);
747 int RenderObject::containingBlockWidth() const
750 return containingBlock()->contentWidth();
753 int RenderObject::containingBlockHeight() const
756 return containingBlock()->contentHeight();
759 bool RenderObject::mustRepaintBackgroundOrBorder() const
761 // If we don't have a background/border, then nothing to do.
762 if (!shouldPaintBackgroundOrBorder())
765 // Ok, let's check the background first.
766 const BackgroundLayer* bgLayer = style()->backgroundLayers();
768 return true; // Nobody will use multiple background layers without wanting fancy positioning.
770 // Make sure we have a valid background image.
771 CachedImage* bg = bgLayer->backgroundImage();
772 bool shouldPaintBackgroundImage = bg && bg->canRender();
774 // These are always percents or auto.
775 if (shouldPaintBackgroundImage &&
776 (bgLayer->backgroundXPosition().value() != 0 || bgLayer->backgroundYPosition().value() != 0))
777 return true; // The background image will shift unpredictably if the size changes.
779 // Background is ok. Let's check border.
780 if (style()->hasBorder()) {
781 // Border images are not ok.
782 CachedImage* borderImage = style()->borderImage().image();
783 bool shouldPaintBorderImage = borderImage && borderImage->canRender();
784 if (shouldPaintBorderImage && borderImage->isLoaded())
785 return true; // If the image hasn't loaded, we're still using the normal border style.
791 void RenderObject::drawBorder(GraphicsContext* p, int x1, int y1, int x2, int y2,
792 BorderSide s, Color c, const Color& textcolor, EBorderStyle style,
793 int adjbw1, int adjbw2, bool invalidisInvert)
795 int width = (s==BSTop||s==BSBottom?y2-y1:x2-x1);
797 if(style == DOUBLE && width < 3)
803 // FIXME: The original KHTML did XOR here -- what do we want to do instead?
807 if (style == INSET || style == OUTSET || style == RIDGE || style == GROOVE)
808 c.setRgb(238, 238, 238);
820 p->setPen(Pen(c, width == 1 ? 0 : width, Pen::DotLine));
824 p->setPen(Pen(c, width == 1 ? 0 : width, Pen::DashLine));
831 p->drawLine(x1, (y1+y2)/2, x2, (y1+y2)/2);
835 p->drawLine((x1+x2)/2, y1, (x1+x2)/2, y2);
843 int third = (width+1)/3;
845 if (adjbw1 == 0 && adjbw2 == 0)
847 p->setPen(Pen::NoPen);
853 p->drawRect(x1, y1 , x2-x1, third);
854 p->drawRect(x1, y2-third, x2-x1, third);
857 p->drawRect(x1 , y1+1, third, y2-y1-1);
858 p->drawRect(x2-third, y1+1, third, y2-y1-1);
861 p->drawRect(x1 , y1+1, third, y2-y1-1);
862 p->drawRect(x2-third, y1+1, third, y2-y1-1);
869 if (adjbw1>0) adjbw1bigthird = adjbw1+1;
870 else adjbw1bigthird = adjbw1 - 1;
874 if (adjbw2>0) adjbw2bigthird = adjbw2 + 1;
875 else adjbw2bigthird = adjbw2 - 1;
881 drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y1 , x2-kMax((-adjbw2*2+1)/3,0), y1 + third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
882 drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y2 - third, x2-kMax(( adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
885 drawBorder(p, x1 , y1+kMax((-adjbw1*2+1)/3,0), x1+third, y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
886 drawBorder(p, x2 - third, y1+kMax(( adjbw1*2+1)/3,0), x2 , y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
889 drawBorder(p, x1+kMax(( adjbw1*2+1)/3,0), y1 , x2-kMax(( adjbw2*2+1)/3,0), y1+third, s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
890 drawBorder(p, x1+kMax((-adjbw1*2+1)/3,0), y2-third, x2-kMax((-adjbw2*2+1)/3,0), y2 , s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
893 drawBorder(p, x1 , y1+kMax(( adjbw1*2+1)/3,0), x1+third, y2-kMax(( adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
894 drawBorder(p, x2-third, y1+kMax((-adjbw1*2+1)/3,0), x2 , y2-kMax((-adjbw2*2+1)/3,0), s, c, textcolor, SOLID, adjbw1bigthird, adjbw2bigthird);
920 if (adjbw1>0) adjbw1bighalf=adjbw1+1;
921 else adjbw1bighalf=adjbw1-1;
924 if (adjbw2>0) adjbw2bighalf=adjbw2+1;
925 else adjbw2bighalf=adjbw2-1;
931 drawBorder(p, x1+kMax(-adjbw1 ,0)/2, y1 , x2-kMax(-adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
932 drawBorder(p, x1+kMax( adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax( adjbw2+1,0)/2, y2 , s, c, textcolor, s2, adjbw1/2, adjbw2/2);
935 drawBorder(p, x1 , y1+kMax(-adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax(-adjbw2,0)/2, s, c, textcolor, s1, adjbw1bighalf, adjbw2bighalf);
936 drawBorder(p, (x1+x2+1)/2, y1+kMax( adjbw1+1,0)/2, x2 , y2-kMax( adjbw2+1,0)/2, s, c, textcolor, s2, adjbw1/2, adjbw2/2);
939 drawBorder(p, x1+kMax( adjbw1 ,0)/2, y1 , x2-kMax( adjbw2,0)/2, (y1+y2+1)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
940 drawBorder(p, x1+kMax(-adjbw1+1,0)/2, (y1+y2+1)/2, x2-kMax(-adjbw2+1,0)/2, y2 , s, c, textcolor, s1, adjbw1/2, adjbw2/2);
943 drawBorder(p, x1 , y1+kMax( adjbw1 ,0)/2, (x1+x2+1)/2, y2-kMax( adjbw2,0)/2, s, c, textcolor, s2, adjbw1bighalf, adjbw2bighalf);
944 drawBorder(p, (x1+x2+1)/2, y1+kMax(-adjbw1+1,0)/2, x2 , y2-kMax(-adjbw2+1,0)/2, s, c, textcolor, s1, adjbw1/2, adjbw2/2);
950 if(s == BSTop || s == BSLeft)
955 if(style == OUTSET && (s == BSBottom || s == BSRight))
959 IntPointArray quad(4);
960 p->setPen(Pen::NoPen);
964 if (adjbw1==0 && adjbw2 == 0)
966 p->drawRect(x1,y1,x2-x1,y2-y1);
972 x1+kMax(-adjbw1,0), y1,
973 x1+kMax( adjbw1,0), y2,
974 x2-kMax( adjbw2,0), y2,
975 x2-kMax(-adjbw2,0), y1);
979 x1+kMax( adjbw1,0), y1,
980 x1+kMax(-adjbw1,0), y2,
981 x2-kMax(-adjbw2,0), y2,
982 x2-kMax( adjbw2,0), y1);
986 x1, y1+kMax(-adjbw1,0),
987 x1, y2-kMax(-adjbw2,0),
988 x2, y2-kMax( adjbw2,0),
989 x2, y1+kMax( adjbw1,0));
993 x1, y1+kMax( adjbw1,0),
994 x1, y2-kMax( adjbw2,0),
995 x2, y2-kMax(-adjbw2,0),
996 x2, y1+kMax(-adjbw1,0));
999 p->drawConvexPolygon(quad);
1004 bool RenderObject::paintBorderImage(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1006 CachedImage* borderImage = style->borderImage().image();
1007 if (!borderImage->isLoaded())
1008 return true; // Never paint a border image incrementally, but don't paint the fallback borders either.
1010 // If we have a border radius, the border image gets clipped to the rounded rect.
1011 bool clipped = false;
1012 if (style->hasBorderRadius()) {
1013 IntRect clipRect(_tx, _ty, w, h);
1015 p->addRoundedRectClip(clipRect,
1016 style->borderTopLeftRadius(), style->borderTopRightRadius(),
1017 style->borderBottomLeftRadius(), style->borderBottomRightRadius());
1021 int imageWidth = borderImage->image()->width();
1022 int imageHeight = borderImage->image()->height();
1024 int topSlice = kMin(imageHeight, style->borderImage().m_slices.top.calcValue(borderImage->image()->height()));
1025 int bottomSlice = kMin(imageHeight, style->borderImage().m_slices.bottom.calcValue(borderImage->image()->height()));
1026 int leftSlice = kMin(imageWidth, style->borderImage().m_slices.left.calcValue(borderImage->image()->width()));
1027 int rightSlice = kMin(imageWidth, style->borderImage().m_slices.right.calcValue(borderImage->image()->width()));
1029 EBorderImageRule hRule = style->borderImage().horizontalRule();
1030 EBorderImageRule vRule = style->borderImage().verticalRule();
1032 bool drawLeft = leftSlice > 0 && style->borderLeftWidth() > 0;
1033 bool drawTop = topSlice > 0 && style->borderTopWidth() > 0;
1034 bool drawRight = rightSlice > 0 && style->borderRightWidth() > 0;
1035 bool drawBottom = bottomSlice > 0 && style->borderBottomWidth() > 0;
1036 bool drawMiddle = (imageWidth - leftSlice - rightSlice) > 0 && (w - style->borderLeftWidth() - style->borderRightWidth()) > 0 &&
1037 (imageHeight - topSlice - bottomSlice) > 0 && (h - style->borderTopWidth() - style->borderBottomWidth()) > 0;
1040 // Paint the top and bottom left corners.
1042 // The top left corner rect is (_tx, _ty, leftWidth, topWidth)
1043 // The rect to use from within the image is obtained from our slice, and is (0, 0, leftSlice, topSlice)
1045 p->drawImage(borderImage->image(), _tx, _ty, style->borderLeftWidth(), style->borderTopWidth(),
1046 0, 0, leftSlice, topSlice);
1048 // The bottom left corner rect is (_tx, _ty + h - bottomWidth, leftWidth, bottomWidth)
1049 // The rect to use from within the image is (0, imageHeight - bottomSlice, leftSlice, botomSlice)
1051 p->drawImage(borderImage->image(), _tx, _ty + h - style->borderBottomWidth(), style->borderLeftWidth(), style->borderBottomWidth(),
1052 0, imageHeight - bottomSlice, leftSlice, bottomSlice);
1054 // Paint the left edge.
1055 // Have to scale and tile into the border rect.
1056 p->drawScaledAndTiledImage(borderImage->image(), _tx, _ty + style->borderTopWidth(), style->borderLeftWidth(),
1057 h - style->borderTopWidth() - style->borderBottomWidth(),
1058 0, topSlice, leftSlice, imageHeight - topSlice - bottomSlice,
1059 Image::StretchTile, (Image::TileRule)vRule);
1063 // Paint the top and bottom right corners
1064 // The top right corner rect is (_tx + w - rightWidth, _ty, rightWidth, topWidth)
1065 // The rect to use from within the image is obtained from our slice, and is (imageWidth - rightSlice, 0, rightSlice, topSlice)
1067 p->drawImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty, style->borderRightWidth(), style->borderTopWidth(),
1068 imageWidth - rightSlice, 0, rightSlice, topSlice);
1070 // The bottom right corner rect is (_tx + w - rightWidth, _ty + h - bottomWidth, rightWidth, bottomWidth)
1071 // The rect to use from within the image is (imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, botomSlice)
1073 p->drawImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty + h - style->borderBottomWidth(), style->borderRightWidth(), style->borderBottomWidth(),
1074 imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice);
1076 // Paint the right edge.
1077 p->drawScaledAndTiledImage(borderImage->image(), _tx + w - style->borderRightWidth(), _ty + style->borderTopWidth(), style->borderRightWidth(),
1078 h - style->borderTopWidth() - style->borderBottomWidth(),
1079 imageWidth - rightSlice, topSlice, rightSlice, imageHeight - topSlice - bottomSlice,
1080 Image::StretchTile, (Image::TileRule)vRule);
1083 // Paint the top edge.
1085 p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty, w - style->borderLeftWidth() - style->borderRightWidth(),
1086 style->borderTopWidth(),
1087 leftSlice, 0, imageWidth - rightSlice - leftSlice, topSlice,
1088 (Image::TileRule)hRule, Image::StretchTile);
1090 // Paint the bottom edge.
1092 p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty + h - style->borderBottomWidth(),
1093 w - style->borderLeftWidth() - style->borderRightWidth(),
1094 style->borderBottomWidth(),
1095 leftSlice, imageHeight - bottomSlice, imageWidth - rightSlice - leftSlice, bottomSlice,
1096 (Image::TileRule)hRule, Image::StretchTile);
1098 // Paint the middle.
1100 p->drawScaledAndTiledImage(borderImage->image(), _tx + style->borderLeftWidth(), _ty + style->borderTopWidth(), w - style->borderLeftWidth() - style->borderRightWidth(),
1101 h - style->borderTopWidth() - style->borderBottomWidth(),
1102 leftSlice, topSlice, imageWidth - rightSlice - leftSlice, imageHeight - topSlice - bottomSlice,
1103 (Image::TileRule)hRule, (Image::TileRule)vRule);
1105 // Clear the clip for the border radius.
1112 void RenderObject::paintBorder(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style, bool begin, bool end)
1114 CachedImage* borderImage = style->borderImage().image();
1115 bool shouldPaintBackgroundImage = borderImage && borderImage->canRender();
1116 if (shouldPaintBackgroundImage)
1117 shouldPaintBackgroundImage = paintBorderImage(p, _tx, _ty, w, h, style);
1119 if (shouldPaintBackgroundImage)
1122 const Color& tc = style->borderTopColor();
1123 const Color& bc = style->borderBottomColor();
1124 const Color& lc = style->borderLeftColor();
1125 const Color& rc = style->borderRightColor();
1127 bool tt = style->borderTopIsTransparent();
1128 bool bt = style->borderBottomIsTransparent();
1129 bool rt = style->borderRightIsTransparent();
1130 bool lt = style->borderLeftIsTransparent();
1132 EBorderStyle ts = style->borderTopStyle();
1133 EBorderStyle bs = style->borderBottomStyle();
1134 EBorderStyle ls = style->borderLeftStyle();
1135 EBorderStyle rs = style->borderRightStyle();
1137 bool render_t = ts > BHIDDEN && !tt;
1138 bool render_l = ls > BHIDDEN && begin && !lt;
1139 bool render_r = rs > BHIDDEN && end && !rt;
1140 bool render_b = bs > BHIDDEN && !bt;
1142 // Need sufficient width and height to contain border radius curves. Sanity check our top/bottom
1143 // values and our width/height values to make sure the curves can all fit. If not, then we won't paint
1144 // any border radii.
1145 bool render_radii = false;
1146 IntSize topLeft = style->borderTopLeftRadius();
1147 IntSize topRight = style->borderTopRightRadius();
1148 IntSize bottomLeft = style->borderBottomLeftRadius();
1149 IntSize bottomRight = style->borderBottomRightRadius();
1151 if (style->hasBorderRadius()) {
1152 int requiredWidth = kMax(topLeft.width() + topRight.width(), bottomLeft.width() + bottomRight.width());
1153 int requiredHeight = kMax(topLeft.height() + bottomLeft.height(), topRight.height() + bottomRight.height());
1154 render_radii = (requiredWidth <= w && requiredHeight <= h);
1157 // Clip to the rounded rectangle.
1160 p->addRoundedRectClip(IntRect(_tx, _ty, w, h), topLeft, topRight, bottomLeft, bottomRight);
1164 bool ignore_left = (render_radii && topLeft.width() > 0) ||
1165 ((tc == lc) && (tt == lt) &&
1167 (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1169 bool ignore_right = (render_radii && topRight.width() > 0) ||
1170 ((tc == rc) && (tt == rt) &&
1172 (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1177 x += topLeft.width();
1178 x2 -= topRight.width();
1181 drawBorder(p, x, _ty, x2, _ty + style->borderTopWidth(), BSTop, tc, style->color(), ts,
1182 ignore_left ? 0 : style->borderLeftWidth(),
1183 ignore_right? 0 : style->borderRightWidth());
1187 bool ignore_left = (render_radii && bottomLeft.width() > 0) ||
1188 ((bc == lc) && (bt == lt) &&
1190 (ls == DOTTED || ls == DASHED || ls == SOLID || ls == OUTSET));
1192 bool ignore_right = (render_radii && bottomRight.width() > 0) ||
1193 ((bc == rc) && (bt == rt) &&
1195 (rs == DOTTED || rs == DASHED || rs == SOLID || rs == INSET));
1200 x += bottomLeft.width();
1201 x2 -= bottomRight.width();
1204 drawBorder(p, x, _ty + h - style->borderBottomWidth(), x2, _ty + h, BSBottom, bc, style->color(), bs,
1205 ignore_left ? 0 :style->borderLeftWidth(),
1206 ignore_right? 0 :style->borderRightWidth());
1210 bool ignore_top = (render_radii && topLeft.height() > 0) ||
1211 ((tc == lc) && (tt == lt) &&
1213 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1215 bool ignore_bottom = (render_radii && bottomLeft.height() > 0) ||
1216 ((bc == lc) && (bt == lt) &&
1218 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1223 y += topLeft.height();
1224 y2 -= bottomLeft.height();
1227 drawBorder(p, _tx, y, _tx + style->borderLeftWidth(), y2, BSLeft, lc, style->color(), ls,
1228 ignore_top?0:style->borderTopWidth(),
1229 ignore_bottom?0:style->borderBottomWidth());
1233 bool ignore_top = (render_radii && topRight.height() > 0) ||
1234 ((tc == rc) && (tt == rt) &&
1235 (rs >= DOTTED || rs == INSET) &&
1236 (ts == DOTTED || ts == DASHED || ts == SOLID || ts == OUTSET));
1238 bool ignore_bottom = (render_radii && bottomRight.height() > 0) ||
1239 ((bc == rc) && (bt == rt) &&
1240 (rs >= DOTTED || rs == INSET) &&
1241 (bs == DOTTED || bs == DASHED || bs == SOLID || bs == INSET));
1246 y += topRight.height();
1247 y2 -= bottomRight.height();
1250 drawBorder(p, _tx + w - style->borderRightWidth(), y, _tx + w, y2, BSRight, rc, style->color(), rs,
1251 ignore_top?0:style->borderTopWidth(),
1252 ignore_bottom?0:style->borderBottomWidth());
1256 p->restore(); // Undo the clip.
1259 QValueList<IntRect> RenderObject::lineBoxRects()
1261 return QValueList<IntRect>();
1264 void RenderObject::absoluteRects(QValueList<IntRect>& rects, int _tx, int _ty)
1266 // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1267 // inline boxes above and below us (thus getting merged with them to form a single irregular
1269 if (continuation()) {
1270 rects.append(IntRect(_tx, _ty - collapsedMarginTop(),
1271 width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1272 continuation()->absoluteRects(rects,
1273 _tx - xPos() + continuation()->containingBlock()->xPos(),
1274 _ty - yPos() + continuation()->containingBlock()->yPos());
1277 rects.append(IntRect(_tx, _ty, width(), height() + borderTopExtra() + borderBottomExtra()));
1280 IntRect RenderObject::absoluteBoundingBoxRect()
1283 absolutePosition(x, y);
1284 QValueList<IntRect> rects;
1285 absoluteRects(rects, x, y);
1287 if (rects.isEmpty())
1290 QValueList<IntRect>::ConstIterator it = rects.begin();
1291 IntRect result = *it;
1292 while (++it != rects.end())
1297 void RenderObject::addAbsoluteRectForLayer(IntRect& result)
1300 result.unite(absoluteBoundingBoxRect());
1301 for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1302 current->addAbsoluteRectForLayer(result);
1305 IntRect RenderObject::paintingRootRect(IntRect& topLevelRect)
1307 IntRect result = absoluteBoundingBoxRect();
1308 topLevelRect = result;
1309 for (RenderObject* current = firstChild(); current; current = current->nextSibling())
1310 current->addAbsoluteRectForLayer(result);
1314 void RenderObject::addFocusRingRects(GraphicsContext* p, int _tx, int _ty)
1316 // For blocks inside inlines, we go ahead and include margins so that we run right up to the
1317 // inline boxes above and below us (thus getting merged with them to form a single irregular
1319 if (continuation()) {
1320 p->addFocusRingRect(IntRect(_tx, _ty - collapsedMarginTop(), width(), height()+collapsedMarginTop()+collapsedMarginBottom()));
1321 continuation()->addFocusRingRects(p,
1322 _tx - xPos() + continuation()->containingBlock()->xPos(),
1323 _ty - yPos() + continuation()->containingBlock()->yPos());
1326 p->addFocusRingRect(IntRect(_tx, _ty, width(), height()));
1329 void RenderObject::paintOutline(GraphicsContext* p, int _tx, int _ty, int w, int h, const RenderStyle* style)
1331 int ow = style->outlineWidth();
1334 EBorderStyle os = style->outlineStyle();
1338 Color oc = style->outlineColor();
1340 oc = style->color();
1342 int offset = style->outlineOffset();
1344 if (style->outlineStyleIsAuto()) {
1345 if (!theme()->supportsFocusRing(style)) {
1346 // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
1347 p->initFocusRing(ow, offset);
1348 addFocusRingRects(p, _tx, _ty);
1349 p->drawFocusRing(oc);
1350 p->clearFocusRing();
1360 drawBorder(p, _tx-ow, _ty-ow, _tx, _ty+h+ow, BSLeft,
1361 Color(oc), style->color(),
1364 drawBorder(p, _tx-ow, _ty-ow, _tx+w+ow, _ty, BSTop,
1365 Color(oc), style->color(),
1368 drawBorder(p, _tx+w, _ty-ow, _tx+w+ow, _ty+h+ow, BSRight,
1369 Color(oc), style->color(),
1372 drawBorder(p, _tx-ow, _ty+h, _tx+w+ow, _ty+h+ow, BSBottom,
1373 Color(oc), style->color(),
1378 void RenderObject::paint(PaintInfo& i, int tx, int ty)
1382 void RenderObject::repaint(bool immediate)
1384 // Can't use canvas(), since we might be unrooted.
1385 RenderObject* o = this;
1386 while ( o->parent() ) o = o->parent();
1389 RenderCanvas* c = static_cast<RenderCanvas*>(o);
1390 if (c->printingMode())
1391 return; // Don't repaint if we're printing.
1392 c->repaintViewRectangle(getAbsoluteRepaintRect(), immediate);
1395 void RenderObject::repaintRectangle(const IntRect& r, bool immediate)
1397 // Can't use canvas(), since we might be unrooted.
1398 RenderObject* o = this;
1399 while ( o->parent() ) o = o->parent();
1402 RenderCanvas* c = static_cast<RenderCanvas*>(o);
1403 if (c->printingMode())
1404 return; // Don't repaint if we're printing.
1406 computeAbsoluteRepaintRect(absRect);
1407 c->repaintViewRectangle(absRect, immediate);
1410 bool RenderObject::repaintAfterLayoutIfNeeded(const IntRect& oldBounds, const IntRect& oldFullBounds)
1412 RenderCanvas* c = canvas();
1413 if (c->printingMode())
1414 return false; // Don't repaint if we're printing.
1416 IntRect newBounds, newFullBounds;
1417 getAbsoluteRepaintRectIncludingFloats(newBounds, newFullBounds);
1418 if (newBounds == oldBounds && !selfNeedsLayout())
1421 bool fullRepaint = selfNeedsLayout() || newBounds.location() != oldBounds.location() || mustRepaintBackgroundOrBorder();
1423 c->repaintViewRectangle(oldFullBounds);
1424 if (newBounds != oldBounds)
1425 c->repaintViewRectangle(newFullBounds);
1429 // We didn't move, but we did change size. Invalidate the delta, which will consist of possibly
1430 // two rectangles (but typically only one).
1431 int width = abs(newBounds.width() - oldBounds.width());
1433 c->repaintViewRectangle(IntRect(kMin(newBounds.x() + newBounds.width(), oldBounds.x() + oldBounds.width()) - borderRight(),
1435 width + borderRight(),
1436 kMax(newBounds.height(), oldBounds.height())));
1437 int height = abs(newBounds.height() - oldBounds.height());
1439 c->repaintViewRectangle(IntRect(newBounds.x(),
1440 kMin(newBounds.bottom(), oldBounds.bottom()) - borderBottom(),
1441 kMax(newBounds.width(), oldBounds.width()),
1442 height + borderBottom()));
1446 void RenderObject::repaintDuringLayoutIfMoved(int x, int y)
1450 void RenderObject::repaintFloatingDescendants()
1454 bool RenderObject::checkForRepaintDuringLayout() const
1456 return !document()->view()->needsFullRepaint() && !layer();
1459 void RenderObject::repaintObjectsBeforeLayout()
1461 if (!needsLayout() || isText())
1464 bool blockWithInlineChildren = (isRenderBlock() && !isTable() && normalChildNeedsLayout() && childrenInline());
1465 if (selfNeedsLayout()) {
1467 if (blockWithInlineChildren)
1471 for (RenderObject* current = firstChild(); current; current = current->nextSibling()) {
1472 if (!current->isPositioned()) // RenderBlock subclass method handles walking the positioned objects.
1473 current->repaintObjectsBeforeLayout();
1477 IntRect RenderObject::getAbsoluteRepaintRectWithOutline(int ow)
1479 IntRect r(getAbsoluteRepaintRect());
1482 if (continuation() && !isInline())
1483 r.inflateY(collapsedMarginTop());
1486 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
1487 if (!curr->isText())
1488 r.unite(curr->getAbsoluteRepaintRectWithOutline(ow));
1493 IntRect RenderObject::getAbsoluteRepaintRect()
1496 return parent()->getAbsoluteRepaintRect();
1500 void RenderObject::getAbsoluteRepaintRectIncludingFloats(IntRect& bounds, IntRect& fullBounds)
1502 bounds = fullBounds = getAbsoluteRepaintRect();
1505 void RenderObject::computeAbsoluteRepaintRect(IntRect& r, bool f)
1508 return parent()->computeAbsoluteRepaintRect(r, f);
1511 void RenderObject::dirtyLinesFromChangedChild(RenderObject* child)
1517 QString RenderObject::information() const
1520 QTextStream ts(&str);
1522 << "(" << (style() ? style()->refCount() : 0) << ")"
1523 << ": " << (void*)this << " ";
1524 if (isInline()) ts << "il ";
1525 if (childrenInline()) ts << "ci ";
1526 if (isFloating()) ts << "fl ";
1527 if (isAnonymous()) ts << "an ";
1528 if (isRelPositioned()) ts << "rp ";
1529 if (isPositioned()) ts << "ps ";
1530 if (needsLayout()) ts << "nl ";
1531 if (m_recalcMinMax) ts << "rmm ";
1532 if (style() && style()->zIndex()) ts << "zI: " << style()->zIndex();
1533 if (element() && element()->active()) ts << "act ";
1534 if (element() && element()->isLink()) ts << "anchor ";
1535 if (element() && element()->focused()) ts << "focus ";
1536 if (element()) ts << " <" << element()->localName().qstring() << ">";
1537 ts << " (" << xPos() << "," << yPos() << "," << width() << "," << height() << ")"
1539 ( QString::fromLatin1(" [r=") +
1540 QString::number( static_cast<const RenderTableCell *>(this)->row() ) +
1541 QString::fromLatin1(" c=") +
1542 QString::number( static_cast<const RenderTableCell *>(this)->col() ) +
1543 QString::fromLatin1(" rs=") +
1544 QString::number( static_cast<const RenderTableCell *>(this)->rowSpan() ) +
1545 QString::fromLatin1(" cs=") +
1546 QString::number( static_cast<const RenderTableCell *>(this)->colSpan() ) +
1547 QString::fromLatin1("]") ) : QString::null );
1551 void RenderObject::dump(QTextStream *stream, QString ind) const
1553 if (isAnonymous()) { *stream << " anonymous"; }
1554 if (isFloating()) { *stream << " floating"; }
1555 if (isPositioned()) { *stream << " positioned"; }
1556 if (isRelPositioned()) { *stream << " relPositioned"; }
1557 if (isText()) { *stream << " text"; }
1558 if (isInline()) { *stream << " inline"; }
1559 if (isReplaced()) { *stream << " replaced"; }
1560 if (shouldPaintBackgroundOrBorder()) { *stream << " paintBackground"; }
1561 if (needsLayout()) { *stream << " needsLayout"; }
1562 if (minMaxKnown()) { *stream << " minMaxKnown"; }
1565 RenderObject *child = firstChild();
1568 *stream << ind << child->renderName() << ": ";
1569 child->dump(stream,ind+" ");
1570 child = child->nextSibling();
1574 void RenderObject::showTree() const
1577 element()->showTree();
1580 void showTree(const RenderObject *ro)
1587 static NodeImpl *selectStartNode(const RenderObject *object)
1589 DOM::NodeImpl *node = 0;
1590 bool forcedOn = false;
1592 for (const RenderObject *curr = object; curr; curr = curr->parent()) {
1593 if (curr->style()->userSelect() == SELECT_TEXT)
1595 if (!forcedOn && curr->style()->userSelect() == SELECT_NONE)
1599 node = curr->element();
1602 // somewhere up the render tree there must be an element!
1608 bool RenderObject::canSelect() const
1610 return selectStartNode(this) != 0;
1613 bool RenderObject::shouldSelect() const
1615 NodeImpl *node = selectStartNode(this);
1618 return node->dispatchHTMLEvent(selectstartEvent, true, true);
1621 Color RenderObject::selectionColor(GraphicsContext* p) const
1624 if (style()->userSelect() != SELECT_NONE) {
1625 RenderStyle* pseudoStyle = getPseudoStyle(RenderStyle::SELECTION);
1626 if (pseudoStyle && pseudoStyle->backgroundColor().isValid())
1627 color = pseudoStyle->backgroundColor();
1629 color = p->selectedTextBackgroundColor();
1635 DOM::NodeImpl* RenderObject::draggableNode(bool dhtmlOK, bool uaOK, int x, int y, bool& dhtmlWillDrag) const
1637 if (!dhtmlOK && !uaOK)
1640 const RenderObject* curr = this;
1642 DOM::NodeImpl *elt = curr->element();
1643 if (elt && elt->nodeType() == NodeImpl::TEXT_NODE) {
1644 // Since there's no way for the author to address the -khtml-user-drag style for a text node,
1645 // we use our own judgement.
1646 if (uaOK && canvas()->view()->frame()->shouldDragAutoNode(curr->node(), x, y)) {
1647 dhtmlWillDrag = false;
1648 return curr->node();
1649 } else if (curr->shouldSelect()) {
1650 // In this case we have a click in the unselected portion of text. If this text is
1651 // selectable, we want to start the selection process instead of looking for a parent
1656 EUserDrag dragMode = curr->style()->userDrag();
1657 if (dhtmlOK && dragMode == DRAG_ELEMENT) {
1658 dhtmlWillDrag = true;
1659 return curr->node();
1660 } else if (uaOK && dragMode == DRAG_AUTO
1661 && canvas()->view()->frame()->shouldDragAutoNode(curr->node(), x, y))
1663 dhtmlWillDrag = false;
1664 return curr->node();
1667 curr = curr->parent();
1672 void RenderObject::selectionStartEnd(int& spos, int& epos)
1674 canvas()->selectionStartEnd(spos, epos);
1677 RenderBlock* RenderObject::createAnonymousBlock()
1679 RenderStyle *newStyle = new (renderArena()) RenderStyle();
1680 newStyle->inheritFrom(m_style);
1681 newStyle->setDisplay(BLOCK);
1683 RenderBlock *newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
1684 newBox->setStyle(newStyle);
1688 void RenderObject::handleDynamicFloatPositionChange()
1690 // We have gone from not affecting the inline status of the parent flow to suddenly
1691 // having an impact. See if there is a mismatch between the parent flow's
1692 // childrenInline() state and our state.
1693 setInline(style()->isDisplayInlineType());
1694 if (isInline() != parent()->childrenInline()) {
1696 if (parent()->isRenderInline()) {
1697 // We have to split the parent flow.
1698 RenderInline* parentInline = static_cast<RenderInline*>(parent());
1699 RenderBlock* newBox = parentInline->createAnonymousBlock();
1701 RenderFlow* oldContinuation = parent()->continuation();
1702 parentInline->setContinuation(newBox);
1704 RenderObject* beforeChild = nextSibling();
1705 parent()->removeChildNode(this);
1706 parentInline->splitFlow(beforeChild, newBox, this, oldContinuation);
1708 else if (parent()->isRenderBlock())
1709 static_cast<RenderBlock*>(parent())->makeChildrenNonInline();
1712 // An anonymous block must be made to wrap this inline.
1713 RenderBlock* box = createAnonymousBlock();
1714 parent()->insertChildNode(box, this);
1715 box->appendChildNode(parent()->removeChildNode(this));
1720 void RenderObject::setStyle(RenderStyle *style)
1722 if (m_style == style)
1725 bool affectsParentBlock = false;
1726 RenderStyle::Diff d = RenderStyle::Equal;
1728 // If our z-index changes value or our visibility changes,
1729 // we need to dirty our stacking context's z-order list.
1732 if (m_style->visibility() != style->visibility() ||
1733 m_style->zIndex() != style->zIndex() ||
1734 m_style->hasAutoZIndex() != style->hasAutoZIndex())
1735 document()->setDashboardRegionsDirty(true);
1738 if ((m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1739 m_style->zIndex() != style->zIndex() ||
1740 m_style->visibility() != style->visibility()) && layer()) {
1741 layer()->stackingContext()->dirtyZOrderLists();
1742 if (m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1743 m_style->visibility() != style->visibility())
1744 layer()->dirtyZOrderLists();
1748 d = m_style->diff(style);
1750 // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
1751 if (d == RenderStyle::RepaintLayer && !layer())
1752 d = RenderStyle::Repaint;
1754 // The background of the root element or the body element could propagate up to
1755 // the canvas. Just dirty the entire canvas when our style changes substantially.
1756 if (d >= RenderStyle::Repaint && element() &&
1757 (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
1758 canvas()->repaint();
1759 else if (m_parent && !isText()) {
1760 // Do a repaint with the old style first, e.g., for example if we go from
1761 // having an outline to not having an outline.
1762 if (d == RenderStyle::RepaintLayer) {
1763 layer()->repaintIncludingDescendants();
1764 if (!(m_style->clip() == style->clip()))
1765 layer()->clearClipRects();
1767 else if (d == RenderStyle::Repaint)
1771 // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
1772 // end up being destroyed.
1773 if (d == RenderStyle::Layout && layer() &&
1774 (m_style->position() != style->position() ||
1775 m_style->zIndex() != style->zIndex() ||
1776 m_style->hasAutoZIndex() != style->hasAutoZIndex() ||
1777 !(m_style->clip() == style->clip()) ||
1778 m_style->hasClip() != style->hasClip() ||
1779 m_style->opacity() != style->opacity()))
1780 layer()->repaintIncludingDescendants();
1782 // When a layout hint happens and an object's position style changes, we have to do a layout
1783 // to dirty the render tree using the old position value now.
1784 if (d == RenderStyle::Layout && m_parent && m_style->position() != style->position())
1785 markContainingBlocksForLayout();
1787 if (isFloating() && (m_style->floating() != style->floating()))
1788 // For changes in float styles, we need to conceivably remove ourselves
1789 // from the floating objects list.
1790 removeFromObjectLists();
1791 else if (isPositioned() && (style->position() != AbsolutePosition && style->position() != FixedPosition))
1792 // For changes in positioning styles, we need to conceivably remove ourselves
1793 // from the positioned objects list.
1794 removeFromObjectLists();
1796 affectsParentBlock = m_style && isFloatingOrPositioned() &&
1797 (!style->isFloating() && style->position() != AbsolutePosition && style->position() != FixedPosition)
1798 && parent() && (parent()->isBlockFlow() || parent()->isInlineFlow());
1800 // reset style flags
1802 m_positioned = false;
1803 m_relPositioned = false;
1804 m_paintBackground = false;
1805 m_hasOverflowClip = false;
1808 RenderStyle *oldStyle = m_style;
1811 updateBackgroundImages(oldStyle);
1817 oldStyle->deref(renderArena());
1819 setShouldPaintBackgroundOrBorder(m_style->hasBorder() || m_style->hasBackground() || m_style->hasAppearance());
1821 if (affectsParentBlock)
1822 handleDynamicFloatPositionChange();
1824 // No need to ever schedule repaints from a style change of a text run, since
1825 // we already did this for the parent of the text run.
1826 if (d == RenderStyle::Layout && m_parent)
1827 setNeedsLayoutAndMinMaxRecalc();
1828 else if (m_parent && !isText() && (d == RenderStyle::RepaintLayer || d == RenderStyle::Repaint))
1829 // Do a repaint with the new style now, e.g., for example if we go from
1830 // not having an outline to having an outline.
1834 void RenderObject::setStyleInternal(RenderStyle* st)
1839 m_style->deref(renderArena());
1845 void RenderObject::updateBackgroundImages(RenderStyle* oldStyle)
1847 // FIXME: This will be slow when a large number of images is used. Fix by using a dict.
1848 const BackgroundLayer* oldLayers = oldStyle ? oldStyle->backgroundLayers() : 0;
1849 const BackgroundLayer* newLayers = m_style ? m_style->backgroundLayers() : 0;
1850 for (const BackgroundLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
1851 if (currOld->backgroundImage() && (!newLayers || !newLayers->containsImage(currOld->backgroundImage())))
1852 currOld->backgroundImage()->deref(this);
1854 for (const BackgroundLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
1855 if (currNew->backgroundImage() && (!oldLayers || !oldLayers->containsImage(currNew->backgroundImage())))
1856 currNew->backgroundImage()->ref(this);
1859 CachedImage* oldBorderImage = oldStyle ? oldStyle->borderImage().image() : 0;
1860 CachedImage* newBorderImage = m_style ? m_style->borderImage().image() : 0;
1861 if (oldBorderImage != newBorderImage) {
1863 oldBorderImage->deref(this);
1865 newBorderImage->ref(this);
1869 IntRect RenderObject::viewRect() const
1871 return canvas()->viewRect();
1874 bool RenderObject::absolutePosition(int &xPos, int &yPos, bool f)
1876 RenderObject* o = parent();
1878 o->absolutePosition(xPos, yPos, f);
1879 yPos += o->borderTopExtra();
1880 if (o->hasOverflowClip())
1881 o->layer()->subtractScrollOffset(xPos, yPos);
1891 IntRect RenderObject::caretRect(int offset, EAffinity affinity, int *extraWidthToEndOfLine)
1893 if (extraWidthToEndOfLine)
1894 *extraWidthToEndOfLine = 0;
1899 int RenderObject::paddingTop() const
1902 Length padding = m_style->paddingTop();
1903 if (padding.isPercent())
1904 w = containingBlock()->contentWidth();
1905 w = padding.calcMinValue(w);
1906 if ( isTableCell() && padding.isAuto() )
1907 w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1911 int RenderObject::paddingBottom() const
1914 Length padding = style()->paddingBottom();
1915 if (padding.isPercent())
1916 w = containingBlock()->contentWidth();
1917 w = padding.calcMinValue(w);
1918 if ( isTableCell() && padding.isAuto() )
1919 w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1923 int RenderObject::paddingLeft() const
1926 Length padding = style()->paddingLeft();
1927 if (padding.isPercent())
1928 w = containingBlock()->contentWidth();
1929 w = padding.calcMinValue(w);
1930 if ( isTableCell() && padding.isAuto() )
1931 w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1935 int RenderObject::paddingRight() const
1938 Length padding = style()->paddingRight();
1939 if (padding.isPercent())
1940 w = containingBlock()->contentWidth();
1941 w = padding.calcMinValue(w);
1942 if ( isTableCell() && padding.isAuto() )
1943 w = static_cast<const RenderTableCell *>(this)->table()->cellPadding();
1947 int RenderObject::tabWidth() const
1949 if (style()->collapseWhiteSpace())
1952 return containingBlock()->tabWidth(true);
1955 RenderCanvas* RenderObject::canvas() const
1957 return static_cast<RenderCanvas*>(document()->renderer());
1960 RenderObject *RenderObject::container() const
1962 // This method is extremely similar to containingBlock(), but with a few notable
1964 // (1) It can be used on orphaned subtrees, i.e., it can be called safely even when
1965 // the object is not part of the primary document subtree yet.
1966 // (2) For normal flow elements, it just returns the parent.
1967 // (3) For absolute positioned elements, it will return a relative positioned inline.
1968 // containingBlock() simply skips relpositioned inlines and lets an enclosing block handle
1969 // the layout of the positioned object. This does mean that calcAbsoluteHorizontal and
1970 // calcAbsoluteVertical have to use container().
1971 EPosition pos = m_style->position();
1972 RenderObject *o = 0;
1973 if (!isText() && pos == FixedPosition) {
1974 // container() can be called on an object that is not in the
1975 // tree yet. We don't call canvas() since it will assert if it
1976 // can't get back to the canvas. Instead we just walk as high up
1977 // as we can. If we're in the tree, we'll get the root. If we
1978 // aren't we'll get the root of our little subtree (most likely
1979 // we'll just return 0).
1981 while (o && o->parent()) o = o->parent();
1983 else if (!isText() && pos == AbsolutePosition) {
1984 // Same goes here. We technically just want our containing block, but
1985 // we may not have one if we're part of an uninstalled subtree. We'll
1986 // climb as high as we can though.
1988 while (o && o->style()->position() == StaticPosition && !o->isRoot() && !o->isCanvas())
1996 // This code has been written to anticipate the addition of CSS3-::outside and ::inside generated
1997 // content (and perhaps XBL). That's why it uses the render tree and not the DOM tree.
1998 RenderObject* RenderObject::hoverAncestor() const
2000 return (!isInline() && continuation()) ? continuation() : parent();
2003 bool RenderObject::isSelectionBorder() const
2005 SelectionState st = selectionState();
2006 return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
2010 void RenderObject::removeFromObjectLists()
2013 RenderBlock* outermostBlock = containingBlock();
2014 for (RenderBlock* p = outermostBlock; p && !p->isCanvas(); p = p->containingBlock()) {
2015 if (p->containsFloat(this))
2020 outermostBlock->markAllDescendantsWithFloatsForLayout(this);
2023 if (isPositioned()) {
2025 for (p = parent(); p; p = p->parent()) {
2026 if (p->isRenderBlock())
2027 static_cast<RenderBlock*>(p)->removePositionedObject(this);
2032 RenderArena* RenderObject::renderArena() const
2034 DOM::DocumentImpl* doc = document();
2035 return doc ? doc->renderArena() : 0;
2038 void RenderObject::remove()
2041 // Delete our accessibility object if we have one.
2042 document()->getAccObjectCache()->detach(this);
2045 removeFromObjectLists();
2048 //have parent, take care of the tree integrity
2049 parent()->removeChild(this);
2051 deleteLineBoxWrapper();
2054 bool RenderObject::documentBeingDestroyed() const
2056 return !document()->renderer();
2059 void RenderObject::destroy()
2061 // By default no ref-counting. RenderWidget::destroy() doesn't call
2062 // this function because it needs to do ref-counting. If anything
2063 // in this function changes, be sure to fix RenderWidget::destroy() as well.
2067 arenaDelete(document()->renderArena(), this);
2070 void RenderObject::arenaDelete(RenderArena *arena, void *base)
2072 if (m_style->backgroundImage())
2073 m_style->backgroundImage()->deref(this);
2075 m_style->deref(arena);
2078 void *savedBase = baseOfRenderObjectBeingDeleted;
2079 baseOfRenderObjectBeingDeleted = base;
2083 baseOfRenderObjectBeingDeleted = savedBase;
2086 // Recover the size left there for us by operator delete and free the memory.
2087 arena->free(*(size_t *)base, base);
2090 VisiblePosition RenderObject::positionForCoordinates(int x, int y)
2092 return VisiblePosition(element(), caretMinOffset(), DOWNSTREAM);
2095 bool RenderObject::isDragging() const
2097 return m_isDragging;
2100 void RenderObject::updateDragState(bool dragOn)
2102 bool valueChanged = (dragOn != m_isDragging);
2103 m_isDragging = dragOn;
2104 if (valueChanged && style()->affectedByDragRules())
2105 element()->setChanged();
2106 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2107 curr->updateDragState(dragOn);
2109 continuation()->updateDragState(dragOn);
2112 bool RenderObject::hitTest(NodeInfo& info, int x, int y, int tx, int ty, HitTestFilter hitTestFilter)
2114 bool inside = false;
2115 if (hitTestFilter != HitTestSelf) {
2116 // First test the foreground layer (lines and inlines).
2117 inside = nodeAtPoint(info, x, y, tx, ty, HitTestForeground);
2119 // Test floats next.
2121 inside = nodeAtPoint(info, x, y, tx, ty, HitTestFloat);
2123 // Finally test to see if the mouse is in the background (within a child block's background).
2125 inside = nodeAtPoint(info, x, y, tx, ty, HitTestChildBlockBackgrounds);
2128 // See if the mouse is inside us but not any of our descendants
2129 if (hitTestFilter != HitTestDescendants && !inside)
2130 inside = nodeAtPoint(info, x, y, tx, ty, HitTestBlockBackground);
2135 void RenderObject::setInnerNode(NodeInfo& info)
2137 if (!info.innerNode() && !isInline() && continuation()) {
2138 // We are in the margins of block elements that are part of a continuation. In
2139 // this case we're actually still inside the enclosing inline element that was
2140 // split. Go ahead and set our inner node accordingly.
2141 info.setInnerNode(continuation()->element());
2142 if (!info.innerNonSharedNode())
2143 info.setInnerNonSharedNode(continuation()->element());
2146 if (!info.innerNode() && element())
2147 info.setInnerNode(element());
2149 if(!info.innerNonSharedNode() && element())
2150 info.setInnerNonSharedNode(element());
2153 bool RenderObject::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty,
2154 HitTestAction hitTestAction)
2159 short RenderObject::verticalPositionHint( bool firstLine ) const
2161 short vpos = m_verticalPosition;
2162 if ( m_verticalPosition == PositionUndefined || firstLine ) {
2163 vpos = getVerticalPosition( firstLine );
2165 m_verticalPosition = vpos;
2171 short RenderObject::getVerticalPosition( bool firstLine ) const
2176 // This method determines the vertical position for inline elements.
2178 EVerticalAlign va = style()->verticalAlign();
2181 } else if ( va == BOTTOM ) {
2182 vpos = PositionBottom;
2183 } else if ( va == LENGTH ) {
2184 vpos = -style()->verticalAlignLength().calcValue( lineHeight( firstLine ) );
2186 bool checkParent = parent()->isInline() && !parent()->isInlineBlockOrInlineTable() && parent()->style()->verticalAlign() != TOP && parent()->style()->verticalAlign() != BOTTOM;
2187 vpos = checkParent ? parent()->verticalPositionHint( firstLine ) : 0;
2188 // don't allow elements nested inside text-top to have a different valignment.
2189 if ( va == BASELINE )
2192 const Font &f = parent()->font(firstLine);
2193 int fontsize = f.pixelSize();
2196 vpos += fontsize/5 + 1;
2197 else if (va == SUPER)
2198 vpos -= fontsize/3 + 1;
2199 else if (va == TEXT_TOP)
2200 vpos += baselinePosition(firstLine) - f.ascent();
2201 else if (va == MIDDLE)
2202 vpos += - (int)(f.xHeight()/2) - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2203 else if (va == TEXT_BOTTOM) {
2204 vpos += f.descent();
2206 vpos -= font(firstLine).descent();
2207 } else if ( va == BASELINE_MIDDLE )
2208 vpos += - lineHeight( firstLine )/2 + baselinePosition( firstLine );
2214 short RenderObject::lineHeight( bool firstLine, bool ) const
2216 RenderStyle* s = style(firstLine);
2218 Length lh = s->lineHeight();
2220 // its "unset", choose nice default
2222 return s->font().lineSpacing();
2225 return lh.calcMinValue(s->fontSize());
2231 short RenderObject::baselinePosition(bool firstLine, bool isRootLineBox) const
2233 const Font& f = font(firstLine);
2234 return f.ascent() + (lineHeight(firstLine, isRootLineBox) - f.height()) / 2;
2237 void RenderObject::invalidateVerticalPositions()
2239 m_verticalPosition = PositionUndefined;
2240 RenderObject *child = firstChild();
2242 child->invalidateVerticalPositions();
2243 child = child->nextSibling();
2247 void RenderObject::recalcMinMaxWidths()
2249 KHTMLAssert( m_recalcMinMax );
2252 kdDebug( 6040 ) << renderName() << " recalcMinMaxWidths() this=" << this <<endl;
2256 updateFirstLetter();
2258 RenderObject *child = firstChild();
2263 if ( ( m_minMaxKnown && child->m_recalcMinMax ) || !child->m_minMaxKnown ) {
2264 cmin = child->minWidth();
2265 cmax = child->maxWidth();
2268 if ( child->m_recalcMinMax )
2269 child->recalcMinMaxWidths();
2270 if ( !child->m_minMaxKnown )
2271 child->calcMinMaxWidth();
2272 if ( m_minMaxKnown && test && (cmin != child->minWidth() || cmax != child->maxWidth()) )
2273 m_minMaxKnown = false;
2274 child = child->nextSibling();
2277 // we need to recalculate, if the contains inline children, as the change could have
2278 // happened somewhere deep inside the child tree. Also do this for blocks or tables that
2279 // are inline (i.e., inline-block and inline-table).
2280 if ((!isInline() || isInlineBlockOrInlineTable()) && childrenInline())
2281 m_minMaxKnown = false;
2283 if ( !m_minMaxKnown )
2285 m_recalcMinMax = false;
2288 void RenderObject::scheduleRelayout()
2290 if (!isCanvas()) return;
2291 FrameView *view = static_cast<RenderCanvas *>(this)->view();
2293 view->scheduleRelayout();
2297 void RenderObject::removeLeftoverAnonymousBoxes()
2301 InlineBox* RenderObject::createInlineBox(bool, bool isRootLineBox, bool)
2303 KHTMLAssert(!isRootLineBox);
2304 return new (renderArena()) InlineBox(this);
2307 void RenderObject::dirtyLineBoxes(bool, bool)
2311 InlineBox* RenderObject::inlineBoxWrapper() const
2316 void RenderObject::setInlineBoxWrapper(InlineBox* b)
2320 void RenderObject::deleteLineBoxWrapper()
2324 RenderStyle* RenderObject::firstLineStyle() const
2326 RenderStyle *s = m_style;
2327 const RenderObject* obj = isText() ? parent() : this;
2328 if (obj->isBlockFlow()) {
2329 RenderBlock* firstLineBlock = obj->firstLineBlock();
2331 s = firstLineBlock->getPseudoStyle(RenderStyle::FIRST_LINE, style());
2332 } else if (!obj->isAnonymous() && obj->isInlineFlow()) {
2333 RenderStyle* parentStyle = obj->parent()->firstLineStyle();
2334 if (parentStyle != obj->parent()->style()) {
2335 // A first-line style is in effect. We need to cache a first-line style
2337 style()->setHasPseudoStyle(RenderStyle::FIRST_LINE_INHERITED);
2338 s = obj->getPseudoStyle(RenderStyle::FIRST_LINE_INHERITED, parentStyle);
2344 RenderStyle* RenderObject::getPseudoStyle(RenderStyle::PseudoId pseudo, RenderStyle* parentStyle) const
2346 if (!style()->hasPseudoStyle(pseudo))
2350 parentStyle = style();
2352 RenderStyle* result = style()->getPseudoStyle(pseudo);
2353 if (result) return result;
2355 DOM::NodeImpl* node = element();
2357 node = element()->parentNode();
2358 if (!node) return 0;
2360 if (pseudo == RenderStyle::FIRST_LINE_INHERITED)
2361 result = document()->styleSelector()->styleForElement(static_cast<DOM::ElementImpl*>(node),
2362 parentStyle, false);
2364 result = document()->styleSelector()->pseudoStyleForElement(pseudo, static_cast<DOM::ElementImpl*>(node),
2367 style()->addPseudoStyle(result);
2371 void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
2372 Color& linethrough, bool quirksMode)
2374 RenderObject* curr = this;
2376 int currDecs = curr->style()->textDecoration();
2378 if (currDecs & UNDERLINE) {
2379 decorations &= ~UNDERLINE;
2380 underline = curr->style()->color();
2382 if (currDecs & OVERLINE) {
2383 decorations &= ~OVERLINE;
2384 overline = curr->style()->color();
2386 if (currDecs & LINE_THROUGH) {
2387 decorations &= ~LINE_THROUGH;
2388 linethrough = curr->style()->color();
2391 curr = curr->parent();
2392 if (curr && curr->isRenderBlock() && curr->continuation())
2393 curr = curr->continuation();
2394 } while (curr && decorations && (!quirksMode || !curr->element() ||
2395 (!curr->element()->hasTagName(aTag) && !curr->element()->hasTagName(fontTag))));
2397 // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
2398 if (decorations && curr) {
2399 if (decorations & UNDERLINE)
2400 underline = curr->style()->color();
2401 if (decorations & OVERLINE)
2402 overline = curr->style()->color();
2403 if (decorations & LINE_THROUGH)
2404 linethrough = curr->style()->color();
2408 void RenderObject::updateWidgetPosition()
2412 QValueList<DashboardRegionValue> RenderObject::computeDashboardRegions()
2414 QValueList<DashboardRegionValue> regions;
2415 collectDashboardRegions(regions);
2419 void RenderObject::addDashboardRegions (QValueList<DashboardRegionValue>& regions)
2421 // Convert the style regions to absolute coordinates.
2422 if (style()->visibility() != VISIBLE)
2425 QValueList<StyleDashboardRegion> styleRegions = style()->dashboardRegions();
2426 if (styleRegions.count() > 0) {
2427 uint i, count = styleRegions.count();
2428 for (i = 0; i < count; i++){
2429 StyleDashboardRegion styleRegion = styleRegions[i];
2434 DashboardRegionValue region;
2435 region.label = styleRegion.label;
2436 region.bounds = IntRect (
2437 styleRegion.offset.left.value(),
2438 styleRegion.offset.top.value(),
2439 w - styleRegion.offset.left.value() - styleRegion.offset.right.value(),
2440 h - styleRegion.offset.top.value() - styleRegion.offset.bottom.value());
2441 region.type = styleRegion.type;
2443 region.clip = region.bounds;
2444 computeAbsoluteRepaintRect(region.clip);
2445 if (region.clip.height() < 0) {
2446 region.clip.setHeight(0);
2447 region.clip.setWidth(0);
2451 absolutePosition(x, y);
2452 region.bounds.setX(x + styleRegion.offset.left.value());
2453 region.bounds.setY(y + styleRegion.offset.top.value());
2455 regions.append(region);
2460 void RenderObject::collectDashboardRegions (QValueList<DashboardRegionValue>& regions)
2462 // RenderTexts don't have their own style, they just use their parent's style,
2463 // so we don't want to include them.
2467 addDashboardRegions (regions);
2468 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
2469 curr->collectDashboardRegions(regions);
2474 void RenderObject::collectBorders(QValueList<CollapsedBorderValue>& borderStyles)
2476 for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
2477 curr->collectBorders(borderStyles);
2480 bool RenderObject::avoidsFloats() const
2482 return isReplaced() || isTable() || hasOverflowClip() || isHR() || isFlexibleBox();
2485 bool RenderObject::usesLineWidth() const
2487 // 1. All auto-width objects that avoid floats should always use lineWidth
2488 // 2. For objects with a specified width, we match WinIE's behavior:
2489 // (a) tables use contentWidth
2490 // (b) <hr>s use lineWidth
2491 // (c) all other objects use lineWidth in quirks mode and contentWidth in strict mode.
2492 return (avoidsFloats() && (style()->width().isAuto() || isHR() || (style()->htmlHacks() && !isTable())));
2495 QChar RenderObject::backslashAsCurrencySymbol() const
2497 NodeImpl *node = element();
2500 DocumentImpl *document = node->getDocument();
2503 Decoder *decoder = document->decoder();
2506 return decoder->encoding().backslashAsCurrencySymbol();
2509 void RenderObject::imageChanged(CachedImage *image)
2511 // Repaint when the background image or border image finishes loading.
2512 // This is needed for RenderBox objects, and also for table objects that hold
2513 // backgrounds that are then respected by the table cells (which are RenderBox
2514 // subclasses). It would be even better to find a more elegant way of doing this that
2515 // would avoid putting this function and the CachedObjectClient base class into RenderObject.
2516 if (image && image->canRender() && parent()) {
2517 if (canvas() && element() && (element()->hasTagName(htmlTag) || element()->hasTagName(bodyTag)))
2518 canvas()->repaint(); // repaint the entire canvas since the background gets propagated up
2520 repaint(); // repaint object, which is a box or a container with boxes inside it
2524 bool RenderObject::willRenderImage(CachedImage*)
2526 // Without visibility we won't render (and therefore don't care about animation).
2527 if (style()->visibility() != VISIBLE)
2530 // 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)
2531 // then we don't want to render either.
2532 return !document()->inPageCache() && document()->view()->inWindow();
2535 int RenderObject::maximalOutlineSize(PaintAction p) const
2537 if (p != PaintActionOutline)
2539 return static_cast<RenderCanvas*>(document()->renderer())->maximalOutlineSize();
2542 int RenderObject::caretMinOffset() const
2547 int RenderObject::caretMaxOffset() const
2552 unsigned RenderObject::caretMaxRenderedOffset() const
2557 int RenderObject::previousOffset (int current) const
2559 int previousOffset = current - 1;
2560 return previousOffset;
2563 int RenderObject::nextOffset (int current) const
2565 int nextOffset = current + 1;
2569 InlineBox *RenderObject::inlineBox(int offset, EAffinity affinity)
2571 return inlineBoxWrapper();
2576 FloatRect RenderObject::relativeBBox(bool) const
2581 QMatrix RenderObject::localTransform() const
2583 return QMatrix(1, 0, 0, 1, xPos(), yPos());
2586 void RenderObject::setLocalTransform(const QMatrix&)
2591 QMatrix RenderObject::absoluteTransform() const
2594 return localTransform() * parent()->absoluteTransform();
2595 return localTransform();