2009-01-31 David Hyatt <hyatt@apple.com>
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2009 21:38:13 +0000 (21:38 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 31 Jan 2009 21:38:13 +0000 (21:38 +0000)
        More removal of code from RenderContainer.  Move removeLeftoverAnonymousBlock down into RenderBlock.
        Move destroyLeftoverChildren into the RenderObjectChildList.  Convert all containers to use the
        RenderObjectChildList.

        Reviewed by Sam Weinig

        * WebCore.xcodeproj/project.pbxproj:
        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::destroy):
        (WebCore::RenderBlock::addChild):
        (WebCore::RenderBlock::removeLeftoverAnonymousBlock):
        (WebCore::RenderBlock::layoutPositionedObjects):
        (WebCore::RenderBlock::childBecameNonInline):
        * rendering/RenderBlock.h:
        * rendering/RenderBox.cpp:
        (WebCore::RenderBox::layout):
        * rendering/RenderBox.h:
        (WebCore::RenderBox::firstChildBox):
        (WebCore::RenderBox::lastChildBox):
        * rendering/RenderContainer.cpp:
        (WebCore::RenderContainer::addChild):
        (WebCore::RenderContainer::removeChildNode):
        (WebCore::RenderContainer::updateBeforeAfterContentForContainer):
        (WebCore::RenderContainer::appendChildNode):
        (WebCore::RenderContainer::insertChildNode):
        (WebCore::RenderContainer::positionForCoordinates):
        (WebCore::RenderContainer::addLineBoxRects):
        (WebCore::RenderContainer::collectAbsoluteLineBoxQuads):
        * rendering/RenderContainer.h:
        (WebCore::RenderContainer::virtualChildren):
        (WebCore::RenderContainer::children):
        * rendering/RenderInline.cpp:
        (WebCore::RenderInline::destroy):
        * rendering/RenderInline.h:
        (WebCore::RenderInline::layout):
        * rendering/RenderMedia.cpp:
        (WebCore::RenderMedia::destroy):
        (WebCore::RenderMedia::children):
        * rendering/RenderMedia.h:
        (WebCore::RenderMedia::virtualChildren):
        * rendering/RenderObject.cpp:
        (WebCore::RenderObject::destroy):
        (WebCore::RenderObject::layout):
        * rendering/RenderObject.h:
        (WebCore::RenderObject::firstChild):
        (WebCore::RenderObject::lastChild):
        (WebCore::RenderObject::virtualChildren):
        (WebCore::RenderObject::canHaveChildren):
        * rendering/RenderObjectChildList.cpp: Added.
        (WebCore::RenderObjectChildList::destroyLeftoverChildren):
        * rendering/RenderObjectChildList.h:
        * rendering/RenderReplaced.h:
        (WebCore::RenderReplaced::canHaveChildren):
        * rendering/RenderSVGContainer.cpp:
        (WebCore::RenderSVGContainer::RenderSVGContainer):
        (WebCore::RenderSVGContainer::destroy):
        (WebCore::RenderSVGContainer::removeChildNode):
        (WebCore::RenderSVGContainer::appendChildNode):
        (WebCore::RenderSVGContainer::insertChildNode):
        * rendering/RenderSVGContainer.h:
        (WebCore::RenderSVGContainer::virtualChildren):
        (WebCore::RenderSVGContainer::children):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40461 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderBox.cpp
WebCore/rendering/RenderBox.h
WebCore/rendering/RenderContainer.cpp
WebCore/rendering/RenderContainer.h
WebCore/rendering/RenderInline.cpp
WebCore/rendering/RenderInline.h
WebCore/rendering/RenderMedia.cpp
WebCore/rendering/RenderMedia.h
WebCore/rendering/RenderObject.cpp
WebCore/rendering/RenderObject.h
WebCore/rendering/RenderObjectChildList.cpp [new file with mode: 0644]
WebCore/rendering/RenderObjectChildList.h
WebCore/rendering/RenderReplaced.h
WebCore/rendering/RenderSVGContainer.cpp
WebCore/rendering/RenderSVGContainer.h

index 3f1f9bb13f6c84d167ff8f665e103cda89097677..46baabeab3e13804597c5c8b21ec63b191477e90 100644 (file)
@@ -1,3 +1,68 @@
+2009-01-31  David Hyatt  <hyatt@apple.com>
+
+        More removal of code from RenderContainer.  Move removeLeftoverAnonymousBlock down into RenderBlock.
+        Move destroyLeftoverChildren into the RenderObjectChildList.  Convert all containers to use the
+        RenderObjectChildList.
+
+        Reviewed by Sam Weinig
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::destroy):
+        (WebCore::RenderBlock::addChild):
+        (WebCore::RenderBlock::removeLeftoverAnonymousBlock):
+        (WebCore::RenderBlock::layoutPositionedObjects):
+        (WebCore::RenderBlock::childBecameNonInline):
+        * rendering/RenderBlock.h:
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::layout):
+        * rendering/RenderBox.h:
+        (WebCore::RenderBox::firstChildBox):
+        (WebCore::RenderBox::lastChildBox):
+        * rendering/RenderContainer.cpp:
+        (WebCore::RenderContainer::addChild):
+        (WebCore::RenderContainer::removeChildNode):
+        (WebCore::RenderContainer::updateBeforeAfterContentForContainer):
+        (WebCore::RenderContainer::appendChildNode):
+        (WebCore::RenderContainer::insertChildNode):
+        (WebCore::RenderContainer::positionForCoordinates):
+        (WebCore::RenderContainer::addLineBoxRects):
+        (WebCore::RenderContainer::collectAbsoluteLineBoxQuads):
+        * rendering/RenderContainer.h:
+        (WebCore::RenderContainer::virtualChildren):
+        (WebCore::RenderContainer::children):
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::destroy):
+        * rendering/RenderInline.h:
+        (WebCore::RenderInline::layout):
+        * rendering/RenderMedia.cpp:
+        (WebCore::RenderMedia::destroy):
+        (WebCore::RenderMedia::children):
+        * rendering/RenderMedia.h:
+        (WebCore::RenderMedia::virtualChildren):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::destroy):
+        (WebCore::RenderObject::layout):
+        * rendering/RenderObject.h:
+        (WebCore::RenderObject::firstChild):
+        (WebCore::RenderObject::lastChild):
+        (WebCore::RenderObject::virtualChildren):
+        (WebCore::RenderObject::canHaveChildren):
+        * rendering/RenderObjectChildList.cpp: Added.
+        (WebCore::RenderObjectChildList::destroyLeftoverChildren):
+        * rendering/RenderObjectChildList.h:
+        * rendering/RenderReplaced.h:
+        (WebCore::RenderReplaced::canHaveChildren):
+        * rendering/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::RenderSVGContainer):
+        (WebCore::RenderSVGContainer::destroy):
+        (WebCore::RenderSVGContainer::removeChildNode):
+        (WebCore::RenderSVGContainer::appendChildNode):
+        (WebCore::RenderSVGContainer::insertChildNode):
+        * rendering/RenderSVGContainer.h:
+        (WebCore::RenderSVGContainer::virtualChildren):
+        (WebCore::RenderSVGContainer::children):
+
 2009-01-31  David Hyatt  <hyatt@apple.com>
 
         Fix for https://bugs.webkit.org/show_bug.cgi?id=11363
index c3e1e68eaeaf40bb0ec49c80f38a6cbcbd8921b2..c4d0ab195f3b5902a0835721a49a49f0c0258e78 100644 (file)
                BC60DA5B0D2A31F700B9918F /* XPathException.h in Headers */ = {isa = PBXBuildFile; fileRef = BC60DA590D2A31F700B9918F /* XPathException.h */; };
                BC60DB490D2A3D1E00B9918F /* JSXPathException.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC60DB470D2A3D1E00B9918F /* JSXPathException.cpp */; };
                BC60DB4A0D2A3D1E00B9918F /* JSXPathException.h in Headers */ = {isa = PBXBuildFile; fileRef = BC60DB480D2A3D1E00B9918F /* JSXPathException.h */; };
+               BC60EFB70F33A0E700812A93 /* RenderObjectChildList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC60EFB60F33A0E700812A93 /* RenderObjectChildList.cpp */; };
                BC64B4CB0CB4295D005F2B62 /* CachedFont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC64B4C90CB4295D005F2B62 /* CachedFont.cpp */; };
                BC64B4CC0CB4295D005F2B62 /* CachedFont.h in Headers */ = {isa = PBXBuildFile; fileRef = BC64B4CA0CB4295D005F2B62 /* CachedFont.h */; };
                BC64B4D50CB4298A005F2B62 /* CSSFontFace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC64B4CD0CB4298A005F2B62 /* CSSFontFace.cpp */; };
                BC60DA5A0D2A31F700B9918F /* XPathException.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XPathException.idl; sourceTree = "<group>"; };
                BC60DB470D2A3D1E00B9918F /* JSXPathException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXPathException.cpp; sourceTree = "<group>"; };
                BC60DB480D2A3D1E00B9918F /* JSXPathException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXPathException.h; sourceTree = "<group>"; };
+               BC60EFB60F33A0E700812A93 /* RenderObjectChildList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderObjectChildList.cpp; sourceTree = "<group>"; };
                BC64B4C90CB4295D005F2B62 /* CachedFont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedFont.cpp; sourceTree = "<group>"; };
                BC64B4CA0CB4295D005F2B62 /* CachedFont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedFont.h; sourceTree = "<group>"; };
                BC64B4CD0CB4298A005F2B62 /* CSSFontFace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSFontFace.cpp; sourceTree = "<group>"; };
                                ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */,
                                BCEA4840097D93020094C9E4 /* RenderObject.cpp */,
                                BCEA4841097D93020094C9E4 /* RenderObject.h */,
+                               BC60EFB60F33A0E700812A93 /* RenderObjectChildList.cpp */,
                                BC2CC8DE0F32881000A9DF26 /* RenderObjectChildList.h */,
                                A871DEC80A1530C700B12A68 /* RenderPart.cpp */,
                                A871DECF0A1530C700B12A68 /* RenderPart.h */,
                                1A569D220D7E2B82007C3983 /* runtime_object.cpp in Sources */,
                                1A569D240D7E2B82007C3983 /* runtime_root.cpp in Sources */,
                                93309E1D099E64920056E581 /* visible_units.cpp in Sources */,
+                               BC60EFB70F33A0E700812A93 /* RenderObjectChildList.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 246cda3a47e29c6d8f0af227f6772942512d9e4d..7eee3a04a6079fe9f888381d445f80198db37357 100644 (file)
@@ -163,7 +163,7 @@ void RenderBlock::destroy()
     
     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
     // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.
-    RenderContainer::destroyLeftoverChildren();
+    children()->destroyLeftoverChildren();
 
     if (!documentBeingDestroyed()) {
         if (firstLineBox()) {
@@ -322,10 +322,9 @@ void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
     }
 
     RenderContainer::addChild(newChild, beforeChild);
-    // ### care about aligned stuff
 
-    if (madeBoxesNonInline && parent() && isAnonymousBlock())
-        parent()->removeLeftoverAnonymousBlock(this);
+    if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
+        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
     // this object may be dead here
 }
 
@@ -443,6 +442,48 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
     repaint();
 }
 
+void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
+{
+    ASSERT(child->isAnonymousBlock());
+    ASSERT(!child->childrenInline());
+    
+    if (child->inlineContinuation()) 
+        return;
+    
+    RenderObject* firstAnChild = child->m_children.firstChild();
+    RenderObject* lastAnChild = child->m_children.lastChild();
+    if (firstAnChild) {
+        RenderObject* o = firstAnChild;
+        while (o) {
+            o->setParent(this);
+            o = o->nextSibling();
+        }
+        firstAnChild->setPreviousSibling(child->previousSibling());
+        lastAnChild->setNextSibling(child->nextSibling());
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(firstAnChild);
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(lastAnChild);
+    } else {
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(child->nextSibling());
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(child->previousSibling());
+    }
+    if (child == m_children.firstChild())
+        m_children.setFirstChild(firstAnChild);
+    if (child == m_children.lastChild())
+        m_children.setLastChild(lastAnChild);
+    child->setParent(0);
+    child->setPreviousSibling(0);
+    child->setNextSibling(0);
+    
+    child->children()->setFirstChild(0);
+    child->m_next = 0;
+
+    child->destroy();
+}
+
 void RenderBlock::removeChild(RenderObject* oldChild)
 {
     // If this child is a block, and if our previous and next siblings are
@@ -1446,7 +1487,7 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
                 r->setChildNeedsLayout(true, false);
                 
             // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
-            if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
+            //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
                 r->setPrefWidthsDirty(true, false);
             
             // We don't have to do a full layout.  We just have to update our position. Try that first. If we have shrink-to-fit width
@@ -4777,8 +4818,8 @@ RenderStyle* RenderBlock::outlineStyleForRepaint() const
 void RenderBlock::childBecameNonInline(RenderObject*)
 {
     makeChildrenNonInline();
-    if (isAnonymousBlock() && parent())
-        parent()->removeLeftoverAnonymousBlock(this);
+    if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
+        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
     // |this| may be dead here
 }
 
index 1e36b74e7702a0467242fb55beb9065bf3d1687a..d51b8500451b0df22dcbd2b1596c75c11f90deca 100644 (file)
@@ -63,6 +63,7 @@ public:
     virtual bool isInlineBlockOrInlineTable() const { return isInline() && isReplaced(); }
 
     void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
 
     RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
     const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
index 5948ef895c309a8a5da9d0807ae66a9b62cc6e09..f66d8a0e3d76aefdb1afb42c175ead4673942018 100644 (file)
@@ -277,6 +277,25 @@ void RenderBox::styleDidChange(RenderStyle::Diff diff, const RenderStyle* oldSty
         document()->setTextColor(style()->color());
 }
 
+void RenderBox::layout()
+{
+    ASSERT(needsLayout());
+
+    RenderObject* child = firstChild();
+    if (!child) {
+        setNeedsLayout(false);
+        return;
+    }
+
+    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+        child = child->nextSibling();
+    }
+    statePusher.pop();
+    setNeedsLayout(false);
+}
 
 int RenderBox::offsetLeft() const
 {
index 2cbf34b0133c71249d1ee297d941aeb7614250e7..211afdce02dd213f1822d5af27ec195f4211a155 100644 (file)
@@ -37,6 +37,10 @@ public:
 
     virtual const char* renderName() const { return "RenderBox"; }
 
+    // Use this with caution! No type checking is done!
+    RenderBox* firstChildBox() const;
+    RenderBox* lastChildBox() const;
+
     int x() const { return m_frameRect.x(); }
     int y() const { return m_frameRect.y(); }
     int width() const { ASSERT(!isRenderInline()); return m_frameRect.width(); }
@@ -158,6 +162,7 @@ public:
     // Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
     IntRect reflectedRect(const IntRect&) const;
 
+    virtual void layout();
     virtual void paint(PaintInfo&, int tx, int ty);
     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int x, int y, int tx, int ty, HitTestAction);
 
@@ -409,6 +414,16 @@ inline RenderBox* RenderBox::parentBox() const
     return toRenderBox(parent());
 }
 
+inline RenderBox* RenderBox::firstChildBox() const
+{
+    return toRenderBox(firstChild());
+}
+
+inline RenderBox* RenderBox::lastChildBox() const
+{
+    return toRenderBox(lastChild());
+}
+
 } // namespace WebCore
 
 #endif // RenderBox_h
index 71e5d094b2dc7e966ddf657de7bca2157c20684e..6522db816cafa3f96bdc96e2a864774734a731d8 100644 (file)
@@ -49,31 +49,6 @@ RenderContainer::~RenderContainer()
 {
 }
 
-void RenderContainer::destroy()
-{
-    destroyLeftoverChildren();
-    RenderBox::destroy();
-}
-
-void RenderContainer::destroyLeftoverChildren()
-{
-    while (m_children.firstChild()) {
-        if (m_children.firstChild()->isListMarker() || (m_children.firstChild()->style()->styleType() == RenderStyle::FIRST_LETTER && !m_children.firstChild()->isText()))
-            m_children.firstChild()->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
-        else {
-        // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
-            if (m_children.firstChild()->element())
-                m_children.firstChild()->element()->setRenderer(0);
-            m_children.firstChild()->destroy();
-        }
-    }
-}
-
-bool RenderContainer::canHaveChildren() const
-{
-    return true;
-}
-
 static void updateListMarkerNumbers(RenderObject* child)
 {
     for (RenderObject* r = child; r; r = r->nextSibling())
@@ -86,7 +61,7 @@ void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild
     bool needsTable = false;
 
     if (newChild->isListItem())
-        updateListMarkerNumbers(beforeChild ? beforeChild : m_children.lastChild());
+        updateListMarkerNumbers(beforeChild ? beforeChild : children()->lastChild());
     else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
         needsTable = !isTable();
     else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
@@ -101,13 +76,13 @@ void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild
         // change we recurse infinitely when trying to render the CSS2 test page:
         // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
         // See Radar 2925291.
-        if (needsTable && isTableCell() && !m_children.firstChild() && !newChild->isTableCell())
+        if (needsTable && isTableCell() && !children()->firstChild() && !newChild->isTableCell())
             needsTable = false;
     }
 
     if (needsTable) {
         RenderTable* table;
-        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_children.lastChild();
+        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children()->lastChild();
         if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
             table = static_cast<RenderTable*>(afterChild);
         else {
@@ -181,10 +156,10 @@ RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild, bool full
     if (oldChild->nextSibling())
         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
 
-    if (m_children.firstChild() == oldChild)
-        m_children.setFirstChild(oldChild->nextSibling());
-    if (m_children.lastChild() == oldChild)
-        m_children.setLastChild(oldChild->previousSibling());
+    if (children()->firstChild() == oldChild)
+        children()->setFirstChild(oldChild->nextSibling());
+    if (children()->lastChild() == oldChild)
+        children()->setLastChild(oldChild->previousSibling());
 
     oldChild->setPreviousSibling(0);
     oldChild->setNextSibling(0);
@@ -290,7 +265,7 @@ void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId
         if (child && child->style()->styleType() == type) {
             oldContentPresent = false;
             child->destroy();
-            child = (type == RenderStyle::BEFORE) ? m_children.firstChild() : m_children.lastChild();
+            child = (type == RenderStyle::BEFORE) ? children()->firstChild() : children()->lastChild();
         }
     }
 
@@ -337,7 +312,7 @@ void RenderContainer::updateBeforeAfterContentForContainer(RenderStyle::PseudoId
         return; // We've updated the generated content. That's all we needed to do.
     }
     
-    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? m_children.firstChild() : 0;
+    RenderObject* insertBefore = (type == RenderStyle::BEFORE) ? children()->firstChild() : 0;
 
     // Generated content consists of a single container that houses multiple children (specified
     // by the content property).  This generated content container gets the pseudo-element style set on it.
@@ -422,15 +397,15 @@ void RenderContainer::appendChildNode(RenderObject* newChild, bool fullAppend)
     ASSERT(!isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
 
     newChild->setParent(this);
-    RenderObject* lChild = m_children.lastChild();
+    RenderObject* lChild = children()->lastChild();
 
     if (lChild) {
         newChild->setPreviousSibling(lChild);
         lChild->setNextSibling(newChild);
     } else
-        m_children.setFirstChild(newChild);
+        children()->setFirstChild(newChild);
 
-    m_children.setLastChild(newChild);
+    children()->setLastChild(newChild);
     
     if (fullAppend) {
         // Keep our layer hierarchy updated.  Optimize for the common case where we don't have any children
@@ -476,8 +451,8 @@ void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeC
 
     ASSERT(!isBlockFlow() || (!child->isTableSection() && !child->isTableRow() && !child->isTableCell()));
 
-    if (beforeChild == m_children.firstChild())
-        m_children.setFirstChild(child);
+    if (beforeChild == children()->firstChild())
+        children()->setFirstChild(child);
 
     RenderObject* prev = beforeChild->previousSibling();
     child->setNextSibling(beforeChild);
@@ -518,70 +493,10 @@ void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeC
         document()->axObjectCache()->childrenChanged(this);
 }
 
-void RenderContainer::layout()
-{
-    ASSERT(needsLayout());
-
-    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
-
-    RenderObject* child = m_children.firstChild();
-    while (child) {
-        child->layoutIfNeeded();
-        ASSERT(child->isRenderInline() || !child->needsLayout());
-        child = child->nextSibling();
-    }
-
-    statePusher.pop();
-    setNeedsLayout(false);
-}
-
-void RenderContainer::removeLeftoverAnonymousBlock(RenderBlock* child)
-{
-    ASSERT(child->isAnonymousBlock());
-    ASSERT(!child->childrenInline());
-    
-    if (child->inlineContinuation()) 
-        return;
-    
-    RenderObject* firstAnChild = child->m_children.firstChild();
-    RenderObject* lastAnChild = child->m_children.lastChild();
-    if (firstAnChild) {
-        RenderObject* o = firstAnChild;
-        while(o) {
-            o->setParent(this);
-            o = o->nextSibling();
-        }
-        firstAnChild->setPreviousSibling(child->previousSibling());
-        lastAnChild->setNextSibling(child->nextSibling());
-        if (child->previousSibling())
-            child->previousSibling()->setNextSibling(firstAnChild);
-        if (child->nextSibling())
-            child->nextSibling()->setPreviousSibling(lastAnChild);
-    } else {
-        if (child->previousSibling())
-            child->previousSibling()->setNextSibling(child->nextSibling());
-        if (child->nextSibling())
-            child->nextSibling()->setPreviousSibling(child->previousSibling());
-    }
-    if (child == m_children.firstChild())
-        m_children.setFirstChild(firstAnChild);
-    if (child == m_children.lastChild())
-        m_children.setLastChild(lastAnChild);
-    child->setParent(0);
-    child->setPreviousSibling(0);
-    child->setNextSibling(0);
-    if (!child->isText()) {
-        RenderContainer* c = static_cast<RenderContainer*>(child);
-        c->m_children.setFirstChild(0);
-        c->m_next = 0;
-    }
-    child->destroy();
-}
-
 VisiblePosition RenderContainer::positionForCoordinates(int xPos, int yPos)
 {
     // no children...return this render object's element, if there is one, and offset 0
-    if (!m_children.firstChild())
+    if (!children()->firstChild())
         return VisiblePosition(element(), 0, DOWNSTREAM);
         
     if (isTable() && element()) {
@@ -605,7 +520,7 @@ VisiblePosition RenderContainer::positionForCoordinates(int xPos, int yPos)
         newX += x();
         newY += y();
     }
-    for (RenderObject* renderObject = m_children.firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
+    for (RenderObject* renderObject = children()->firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
         if (!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow() 
             || renderObject->style()->visibility() != VISIBLE)
             continue;
@@ -668,13 +583,13 @@ VisiblePosition RenderContainer::positionForCoordinates(int xPos, int yPos)
 
 void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, unsigned end, bool)
 {
-    if (!m_children.firstChild() && (isInline() || isAnonymousBlock())) {
+    if (!children()->firstChild() && (isInline() || isAnonymousBlock())) {
         FloatPoint absPos = localToAbsolute(FloatPoint());
         absoluteRects(rects, absPos.x(), absPos.y());
         return;
     }
 
-    if (!m_children.firstChild())
+    if (!children()->firstChild())
         return;
 
     unsigned offset = start;
@@ -688,12 +603,12 @@ void RenderContainer::addLineBoxRects(Vector<IntRect>& rects, unsigned start, un
 
 void RenderContainer::collectAbsoluteLineBoxQuads(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool /*useSelectionHeight*/)
 {
-    if (!m_children.firstChild() && (isInline() || isAnonymousBlock())) {
+    if (!children()->firstChild() && (isInline() || isAnonymousBlock())) {
         absoluteQuads(quads);
         return;
     }
 
-    if (!m_children.firstChild())
+    if (!children()->firstChild())
         return;
 
     unsigned offset = start;
index 690745400c105808ff5a43e9af5823dea7a5d28f..d947d669a8fcb790e78865b2d75de20f772a7d4c 100644 (file)
@@ -22,7 +22,6 @@
 #define RenderContainer_h
 
 #include "RenderBox.h"
-#include "RenderObjectChildList.h"
 
 namespace WebCore {
 
@@ -32,21 +31,15 @@ public:
     RenderContainer(Node*);
     virtual ~RenderContainer();
 
-    virtual RenderObject* firstChild() const { return m_children.firstChild(); }
-    virtual RenderObject* lastChild() const { return m_children.lastChild(); }
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
 
-    // Use this with caution! No type checking is done!
-    RenderBox* firstChildBox() const { ASSERT(!firstChild() || firstChild()->isBox()); return toRenderBox(firstChild()); }
-    RenderBox* lastChildBox() const { ASSERT(!lastChild() || lastChild()->isBox()); return toRenderBox(lastChild()); }
-    
-    virtual bool canHaveChildren() const;
     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
     virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); }
     virtual void removeChild(RenderObject*);
 
-    virtual void destroy();
-    void destroyLeftoverChildren();
-
     virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
     virtual void appendChildNode(RenderObject*, bool fullAppend = true);
     virtual void insertChildNode(RenderObject* child, RenderObject* before, bool fullInsert = true);
@@ -55,11 +48,8 @@ public:
     // change in parentage is not going to affect anything.
     virtual void moveChildNode(RenderObject* child) { appendChildNode(child->parent()->removeChildNode(child, false), false); }
     
-    virtual void layout();
     virtual void calcPrefWidths() { setPrefWidthsDirty(false); }
 
-    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-
     RenderObject* beforeAfterContainer(RenderStyle::PseudoId);
     virtual void updateBeforeAfterContent(RenderStyle::PseudoId);
     void updateBeforeAfterContentForContainer(RenderStyle::PseudoId, RenderContainer*);
index e12cbab50403581bb3654f48e37d1d60a4c71869..920b12b6978699eb28c2fe45a79f56a54e83abcb 100644 (file)
@@ -58,7 +58,7 @@ void RenderInline::destroy()
     
     // Make sure to destroy anonymous children first while they are still connected to the rest of the tree, so that they will
     // properly dirty line boxes that they are removed from.  Effects that do :before/:after only on hover could crash otherwise.
-    RenderContainer::destroyLeftoverChildren();
+    children()->destroyLeftoverChildren();
 
     if (!documentBeingDestroyed()) {
         if (firstLineBox()) {
index 08ab0c0021b6333b0bc6d99d4310c6e972017ca7..720128e27870f766d70ed151b0219060c71d5e90 100644 (file)
@@ -52,7 +52,7 @@ public:
     void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
                    RenderObject* newChild, RenderContainer* oldCont);
 
-    virtual void layout() { } // Do nothing for layout()
+    virtual void layout() { ASSERT_NOT_REACHED(); } // Do nothing for layout()
 
     virtual void paint(PaintInfo&, int tx, int ty);
 
index 80bf5867972736f276f13af5c6a8ca6dfc6b1888..405a91ab88937faac1d4f0909dbbac2027f01d86 100644 (file)
@@ -89,6 +89,7 @@ void RenderMedia::destroy()
 
         removeChild(m_controlsShadowRoot->renderer());
         m_controlsShadowRoot->detach();
+        m_controlsShadowRoot = 0;
     }
     RenderReplaced::destroy();
 }
@@ -123,16 +124,16 @@ void RenderMedia::layout()
     }
 }
 
-RenderObject* RenderMedia::firstChild() const 
-{ 
-    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0; 
+const RenderObjectChildList* RenderMedia::children() const
+{
+    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer()->virtualChildren() : 0; 
 }
 
-RenderObject* RenderMedia::lastChild() const 
-{ 
-    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer() : 0;
+RenderObjectChildList* RenderMedia::children()
+{
+    return m_controlsShadowRoot ? m_controlsShadowRoot->renderer()->virtualChildren() : 0; 
 }
-    
+   
 void RenderMedia::removeChild(RenderObject* child)
 {
     ASSERT(m_controlsShadowRoot);
index a4670e9170d2187838c49b67ca0e801b1e7b098b..899a1b70fc756d00b944694f31a09dfdb3e57e14 100644 (file)
@@ -49,8 +49,11 @@ public:
     RenderMedia(HTMLMediaElement*, const IntSize& intrinsicSize);
     virtual ~RenderMedia();
     
-    virtual RenderObject* firstChild() const;
-    virtual RenderObject* lastChild() const;
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+    const RenderObjectChildList* children() const;
+    RenderObjectChildList* children();
+
     virtual void removeChild(RenderObject*);
     virtual void destroy();
     
index b9e01e3b9046e0482b659ab662c71cc204d81aa4..4ce5a6a1ae9e514fc0dbb725d6c6060473d62430 100644 (file)
@@ -229,11 +229,6 @@ bool RenderObject::isHTMLMarquee() const
     return element() && element()->renderer() == this && element()->hasTagName(marqueeTag);
 }
 
-bool RenderObject::canHaveChildren() const
-{
-    return false;
-}
-
 void RenderObject::addChild(RenderObject*, RenderObject*)
 {
     ASSERT_NOT_REACHED();
@@ -2289,6 +2284,11 @@ bool RenderObject::documentBeingDestroyed() const
 
 void RenderObject::destroy()
 {
+    // Destroy any leftover anonymous children.
+    RenderObjectChildList* children = virtualChildren();
+    if (children)
+        children->destroyLeftoverChildren();
+
     // If this renderer is being autoscrolled, stop the autoscroll timer
     if (document()->frame() && document()->frame()->eventHandler()->autoscrollRenderer() == this)
         document()->frame()->eventHandler()->stopAutoscrollTimer(true);
@@ -2492,8 +2492,16 @@ void RenderObject::scheduleRelayout()
     }
 }
 
-void RenderObject::removeLeftoverAnonymousBlock(RenderBlock*)
+void RenderObject::layout()
 {
+    ASSERT(needsLayout());
+    RenderObject* child = firstChild();
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+        child = child->nextSibling();
+    }
+    setNeedsLayout(false);
 }
 
 InlineBox* RenderObject::createInlineBox(bool, bool unusedIsRootLineBox, bool)
index e3725b656c2c711740925f14e9579e72318a8b0d..070be812757743eed0826c6e2ff75adb69838cc4 100644 (file)
@@ -28,6 +28,7 @@
 #include "CachedResourceClient.h"
 #include "FloatQuad.h"
 #include "Document.h"
+#include "RenderObjectChildList.h"
 #include "RenderStyle.h"
 
 namespace WebCore {
@@ -111,6 +112,7 @@ struct DashboardRegionValue {
 
 // Base class for all rendering tree objects.
 class RenderObject : public CachedResourceClient {
+    friend class RenderBlock;
     friend class RenderContainer;
     friend class RenderLayer;
     friend class RenderSVGContainer;
@@ -128,8 +130,20 @@ public:
     RenderObject* previousSibling() const { return m_previous; }
     RenderObject* nextSibling() const { return m_next; }
 
-    virtual RenderObject* firstChild() const { return 0; }
-    virtual RenderObject* lastChild() const { return 0; }
+    RenderObject* firstChild() const
+    {
+        if (const RenderObjectChildList* children = virtualChildren())
+            return children->firstChild();
+        return 0;
+    }
+    RenderObject* lastChild() const
+    {
+        if (const RenderObjectChildList* children = virtualChildren())
+            return children->lastChild();
+        return 0;
+    }
+    virtual RenderObjectChildList* virtualChildren() { return 0; }
+    virtual const RenderObjectChildList* virtualChildren() const { return 0; }
 
     RenderObject* nextInPreOrder() const;
     RenderObject* nextInPreOrder(RenderObject* stayWithin) const;
@@ -194,7 +208,7 @@ public:
 
     // RenderObject tree manipulation
     //////////////////////////////////////////
-    virtual bool canHaveChildren() const;
+    virtual bool canHaveChildren() const { return virtualChildren(); }
     virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; }
     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
     virtual void removeChild(RenderObject*);
@@ -455,17 +469,8 @@ public:
      */
     virtual void calcWidth() { }
 
-    /*
-     * This function should cause the Element to calculate its
-     * width and height and the layout of its content
-     *
-     * when the Element calls setNeedsLayout(false), layout() is no
-     * longer called during relayouts, as long as there is no
-     * style sheet change. When that occurs, m_needsLayout will be
-     * set to true and the Element receives layout() calls
-     * again.
-     */
-    virtual void layout() = 0;
+    // Recursive function that computes the size and position of this object and all its descendants.
+    virtual void layout();
 
     /* This function performs a layout only if one is needed. */
     void layoutIfNeeded() { if (needsLayout()) layout(); }
@@ -763,9 +768,7 @@ public:
     void remove() { if (parent()) parent()->removeChild(this); }
 
     void invalidateVerticalPosition() { m_verticalPosition = PositionUndefined; }
-    
-    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
-    
+
     virtual void capsLockStateMayHaveChanged() { }
 
     AnimationController* animation() const;
diff --git a/WebCore/rendering/RenderObjectChildList.cpp b/WebCore/rendering/RenderObjectChildList.cpp
new file mode 100644 (file)
index 0000000..71b549e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2009 Apple Inc.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "RenderObjectChildList.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+void RenderObjectChildList::destroyLeftoverChildren()
+{
+    while (firstChild()) {
+        if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == RenderStyle::FIRST_LETTER && !firstChild()->isText()))
+            firstChild()->remove();  // List markers are owned by their enclosing list and so don't get destroyed by this container. Similarly, first letters are destroyed by their remaining text fragment.
+        else {
+            // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
+            if (firstChild()->element())
+                firstChild()->element()->setRenderer(0);
+            firstChild()->destroy();
+        }
+    }
+}
+
+}
index a9c2df72df7052a3a9496caf0818d871e5871ace..4807e91ac82297aab8e5973df910120d1545bebf 100644 (file)
@@ -46,6 +46,8 @@ public:
     void setFirstChild(RenderObject* child) { m_firstChild = child; }
     void setLastChild(RenderObject* child) { m_lastChild = child; }
     
+    void destroyLeftoverChildren();
+
 private:
     RenderObject* m_firstChild;
     RenderObject* m_lastChild;
index 53f818de15788a104c7a46cfba66ccc8b05c796f..4121eeca9efa0ffeceaac5a9b9a0a438c729e8b7 100644 (file)
@@ -34,6 +34,8 @@ public:
 
     virtual const char* renderName() const { return "RenderReplaced"; }
 
+    virtual bool canHaveChildren() const { return false; }
+
     virtual int lineHeight(bool firstLine, bool isRootLineBox = false) const;
     virtual int baselinePosition(bool firstLine, bool isRootLineBox = false) const;
 
index 39deb0a65ee8a0d658603c8505a8fee4681e209d..d6e2adc11274ee641e620ca54371f118dcc248f9 100644 (file)
@@ -39,8 +39,6 @@ namespace WebCore {
 
 RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
     : RenderObject(node)
-    , m_firstChild(0)
-    , m_lastChild(0)
     , m_width(0)
     , m_height(0)
     , m_drawsContents(true)
@@ -51,11 +49,6 @@ RenderSVGContainer::~RenderSVGContainer()
 {
 }
 
-bool RenderSVGContainer::canHaveChildren() const
-{
-    return true;
-}
-
 void RenderSVGContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
 {
     insertChildNode(newChild, beforeChild);
@@ -73,21 +66,10 @@ void RenderSVGContainer::removeChild(RenderObject* oldChild)
 
 void RenderSVGContainer::destroy()
 {
-    destroyLeftoverChildren();
+    children()->destroyLeftoverChildren();
     RenderObject::destroy();
 }
 
-void RenderSVGContainer::destroyLeftoverChildren()
-{
-    while (m_firstChild) {
-        // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
-        if (m_firstChild->element())
-            m_firstChild->element()->setRenderer(0);
-
-        m_firstChild->destroy();
-    }
-}
-
 RenderObject* RenderSVGContainer::removeChildNode(RenderObject* oldChild, bool fullRemove)
 {
     ASSERT(oldChild->parent() == this);
@@ -118,10 +100,10 @@ RenderObject* RenderSVGContainer::removeChildNode(RenderObject* oldChild, bool f
     if (oldChild->nextSibling())
         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
 
-    if (m_firstChild == oldChild)
-        m_firstChild = oldChild->nextSibling();
-    if (m_lastChild == oldChild)
-        m_lastChild = oldChild->previousSibling();
+    if (children()->firstChild() == oldChild)
+        children()->setFirstChild(oldChild->nextSibling());
+    if (children()->lastChild() == oldChild)
+        children()->setLastChild(oldChild->previousSibling());
 
     oldChild->setPreviousSibling(0);
     oldChild->setNextSibling(0);
@@ -139,15 +121,15 @@ void RenderSVGContainer::appendChildNode(RenderObject* newChild, bool)
     ASSERT(newChild->element()->isSVGElement());
 
     newChild->setParent(this);
-    RenderObject* lChild = m_lastChild;
+    RenderObject* lChild = children()->lastChild();
 
     if (lChild) {
         newChild->setPreviousSibling(lChild);
         lChild->setNextSibling(newChild);
     } else
-        m_firstChild = newChild;
+        children()->setFirstChild(newChild);
 
-    m_lastChild = newChild;
+    children()->setLastChild(newChild);
 
     newChild->setNeedsLayoutAndPrefWidthsRecalc(); // Goes up the containing block hierarchy.
     if (!normalChildNeedsLayout())
@@ -168,8 +150,8 @@ void RenderSVGContainer::insertChildNode(RenderObject* child, RenderObject* befo
     ASSERT(beforeChild->parent() == this);
     ASSERT(child->element()->isSVGElement());
 
-    if (beforeChild == m_firstChild)
-        m_firstChild = child;
+    if (beforeChild == children()->firstChild())
+        children()->setFirstChild(child);
 
     RenderObject* prev = beforeChild->previousSibling();
     child->setNextSibling(beforeChild);
index e498a8a5938065e9e20a0cf88e7adbde908b841e..49bb73e4ac7d5761b6971f92248487da0fd35943 100644 (file)
@@ -37,18 +37,18 @@ public:
     RenderSVGContainer(SVGStyledElement*);
     ~RenderSVGContainer();
 
-    virtual RenderObject* firstChild() const { return m_firstChild; }
-    virtual RenderObject* lastChild() const { return m_lastChild; }
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
 
     int width() const { return m_width; }
     int height() const { return m_height; }
 
-    virtual bool canHaveChildren() const;
     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
     virtual void removeChild(RenderObject*);
 
     virtual void destroy();
-    void destroyLeftoverChildren();
 
     virtual RenderObject* removeChildNode(RenderObject*, bool fullRemove = true);
     virtual void appendChildNode(RenderObject*, bool fullAppend = true);
@@ -101,8 +101,7 @@ private:
     int calcReplacedWidth() const;
     int calcReplacedHeight() const;
 
-    RenderObject* m_firstChild;
-    RenderObject* m_lastChild;
+    RenderObjectChildList m_children;
 
     int m_width;
     int m_height;