Title: [92004] trunk/Source/WebCore
Revision
92004
Author
[email protected]
Date
2011-07-29 13:19:03 -0700 (Fri, 29 Jul 2011)

Log Message

https://bugs.webkit.org/show_bug.cgi?id=65342

Add support for positioned floats being placed into a RenderBlock's FloatingObject list and for
correct propagation of those floating objects into descendants.

Reviewed by Sam Weinig.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layoutBlock):
The positioned float layout algorithm is 2-pass. You lay out without the positioned objects, and then
once they have been placed, you lay out again and use that placement to determine the float positions.
layoutBlock now has an extra parameter to indicate which layout pass you are in.
        
(WebCore::RenderBlock::addOverflowFromFloats):
Don't add overflow from positioned floats ever, since the positioning overflow function takes care of that
already.

(WebCore::RenderBlock::layoutBlockChild):
Include positioned floats in the lowestFloatLogicalBottom we look at so that overhang is computed properly.

(WebCore::RenderBlock::simplifiedLayout):
If layoutPositionedObjects indicates that a positioned float moved, then we can't do simplified layout. Bail
instead and do a full layout.

(WebCore::RenderBlock::positionedFloatsNeedRelayout):
Helper for layoutBlock in order to bypass the 2-pass model if we can detect that none of the positioned objects
will actually need to lay out again. This allows incremental layout to not always fault back to 2-pass as normal
flow content streams in.

(WebCore::RenderBlock::layoutPositionedObjects):
Modified to return a boolean indicating whether a positioned float got a layout. If so, we will lay out again
once our positioned objects are placed.

(WebCore::RenderBlock::insertFloatingObject):
insertFloatingObject can now handle positioned objects being inserted.

(WebCore::RenderBlock::positionNewFloats):
positionNewFloats doesn't attempt to position this new type of float. It only handles left/right floats.

(WebCore::RenderBlock::addPositionedFloats):
Helper to add in the floating objects for positioned floats. This is used instead of positionNewFloats and
just walks the positioned objects instead.

(WebCore::RenderBlock::clearFloats):
clearFloats now handles adding in positioned floats if the layout pass says they should be included.

(WebCore::RenderBlock::marginLogicalLeftForChild):
(WebCore::RenderBlock::marginLogicalRightForChild):
New helpers used by addPositionedFloats.
    
(WebCore::RenderBlock::FloatingObjects::clear):
(WebCore::RenderBlock::FloatingObjects::increaseObjectsCount):
(WebCore::RenderBlock::FloatingObjects::decreaseObjectsCount):
Make sure the object count tracking handles positioned floats as well as left/right floats.
    
* rendering/RenderBlock.h:
(WebCore::RenderBlock::logicalLeftForChild):
New helper used by addPositionedFloats.

(WebCore::RenderBlock::FloatingObject::FloatingObject):
Change the constructor to take the RenderStyle enum. This makes the construction simpler.

(WebCore::RenderBlock::hasPositionedFloats):
A bit tracks whether or not a block has positioned floats in its positioned objects list.

(WebCore::RenderBlock::hasOverhangingFloats):
Modified to include positioned floats.

(WebCore::RenderBlock::lowestFloatLogicalBottom):
This function excludes positioned floats by default, so that places that - for example - expand to
encompass their lowestFloatLogicalBottom won't accidentally expand to encompass positioned objects.

(WebCore::RenderBlock::lowestFloatLogicalBottomIncludingPositionedFloats):
A new function that includes positioned floats for callers that care.

(WebCore::RenderBlock::FloatingObjects::FloatingObjects):
(WebCore::RenderBlock::FloatingObjects::hasPositionedObjects):
The object count tracking for positioned floats within a block's FloatingObjects list.

* rendering/RenderBox.cpp:
(WebCore::RenderBox::updateBoxModelInfoFromStyle):
Make sure isFloating is set even if isPositioned is also set for the positioned float case.

* rendering/RenderDeprecatedFlexibleBox.cpp:
(WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
Modified to do the extra layout pass if needed.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (92003 => 92004)


--- trunk/Source/WebCore/ChangeLog	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/ChangeLog	2011-07-29 20:19:03 UTC (rev 92004)
@@ -1,3 +1,92 @@
+2011-07-28  David Hyatt  <[email protected]>
+
+        https://bugs.webkit.org/show_bug.cgi?id=65342
+
+        Add support for positioned floats being placed into a RenderBlock's FloatingObject list and for
+        correct propagation of those floating objects into descendants.
+
+        Reviewed by Sam Weinig.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::layoutBlock):
+        The positioned float layout algorithm is 2-pass. You lay out without the positioned objects, and then
+        once they have been placed, you lay out again and use that placement to determine the float positions.
+        layoutBlock now has an extra parameter to indicate which layout pass you are in.
+        
+        (WebCore::RenderBlock::addOverflowFromFloats):
+        Don't add overflow from positioned floats ever, since the positioning overflow function takes care of that
+        already.
+
+        (WebCore::RenderBlock::layoutBlockChild):
+        Include positioned floats in the lowestFloatLogicalBottom we look at so that overhang is computed properly.
+
+        (WebCore::RenderBlock::simplifiedLayout):
+        If layoutPositionedObjects indicates that a positioned float moved, then we can't do simplified layout. Bail
+        instead and do a full layout.
+
+        (WebCore::RenderBlock::positionedFloatsNeedRelayout):
+        Helper for layoutBlock in order to bypass the 2-pass model if we can detect that none of the positioned objects
+        will actually need to lay out again. This allows incremental layout to not always fault back to 2-pass as normal
+        flow content streams in.
+
+        (WebCore::RenderBlock::layoutPositionedObjects):
+        Modified to return a boolean indicating whether a positioned float got a layout. If so, we will lay out again
+        once our positioned objects are placed.
+
+        (WebCore::RenderBlock::insertFloatingObject):
+        insertFloatingObject can now handle positioned objects being inserted.
+
+        (WebCore::RenderBlock::positionNewFloats):
+        positionNewFloats doesn't attempt to position this new type of float. It only handles left/right floats.
+
+        (WebCore::RenderBlock::addPositionedFloats):
+        Helper to add in the floating objects for positioned floats. This is used instead of positionNewFloats and
+        just walks the positioned objects instead.
+
+        (WebCore::RenderBlock::clearFloats):
+        clearFloats now handles adding in positioned floats if the layout pass says they should be included.
+
+        (WebCore::RenderBlock::marginLogicalLeftForChild):
+        (WebCore::RenderBlock::marginLogicalRightForChild):
+        New helpers used by addPositionedFloats.
+    
+        (WebCore::RenderBlock::FloatingObjects::clear):
+        (WebCore::RenderBlock::FloatingObjects::increaseObjectsCount):
+        (WebCore::RenderBlock::FloatingObjects::decreaseObjectsCount):
+        Make sure the object count tracking handles positioned floats as well as left/right floats.
+    
+        * rendering/RenderBlock.h:
+        (WebCore::RenderBlock::logicalLeftForChild):
+        New helper used by addPositionedFloats.
+
+        (WebCore::RenderBlock::FloatingObject::FloatingObject):
+        Change the constructor to take the RenderStyle enum. This makes the construction simpler.
+
+        (WebCore::RenderBlock::hasPositionedFloats):
+        A bit tracks whether or not a block has positioned floats in its positioned objects list.
+
+        (WebCore::RenderBlock::hasOverhangingFloats):
+        Modified to include positioned floats.
+
+        (WebCore::RenderBlock::lowestFloatLogicalBottom):
+        This function excludes positioned floats by default, so that places that - for example - expand to
+        encompass their lowestFloatLogicalBottom won't accidentally expand to encompass positioned objects.
+
+        (WebCore::RenderBlock::lowestFloatLogicalBottomIncludingPositionedFloats):
+        A new function that includes positioned floats for callers that care.
+
+        (WebCore::RenderBlock::FloatingObjects::FloatingObjects):
+        (WebCore::RenderBlock::FloatingObjects::hasPositionedObjects):
+        The object count tracking for positioned floats within a block's FloatingObjects list.
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::updateBoxModelInfoFromStyle):
+        Make sure isFloating is set even if isPositioned is also set for the positioned float case.
+
+        * rendering/RenderDeprecatedFlexibleBox.cpp:
+        (WebCore::RenderDeprecatedFlexibleBox::layoutBlock):
+        Modified to do the extra layout pass if needed.
+
 2011-07-29  Scott Byer  <[email protected]>
 
         Scroll animation refinements.

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-07-29 20:19:03 UTC (rev 92004)
@@ -118,6 +118,7 @@
       : RenderBox(node)
       , m_lineHeight(-1)
       , m_beingDestroyed(false)
+      , m_hasPositionedFloats(false)
 {
     setChildrenInline(true);
 }
@@ -1165,7 +1166,7 @@
         clearLayoutOverflow();
 }
 
-void RenderBlock::layoutBlock(bool relayoutChildren, int pageLogicalHeight)
+void RenderBlock::layoutBlock(bool relayoutChildren, int pageLogicalHeight, BlockLayoutPass layoutPass)
 {
     ASSERT(needsLayout());
 
@@ -1188,7 +1189,12 @@
     if (oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth())
         relayoutChildren = true;
 
-    clearFloats();
+    // If nothing changed about our floating positioned objects, let's go ahead and try to place them as
+    // floats to avoid doing two passes.
+    BlockLayoutPass floatsLayoutPass = layoutPass;
+    if (floatsLayoutPass == NormalLayoutPass && !relayoutChildren && !positionedFloatsNeedRelayout())
+        floatsLayoutPass = PositionedFloatLayoutPass;
+    clearFloats(floatsLayoutPass);
 
     int previousHeight = logicalHeight();
     setLogicalHeight(0);
@@ -1282,7 +1288,7 @@
             for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
                 if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
                     RenderBlock* block = toRenderBlock(child);
-                    if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
+                    if (block->lowestFloatLogicalBottomIncludingPositionedFloats() + block->logicalTop() > newHeight)
                         addOverhangingFloats(block, -block->logicalLeft(), -block->logicalTop(), false);
                 }
             }
@@ -1292,7 +1298,7 @@
     if (previousHeight != newHeight)
         relayoutChildren = true;
 
-    layoutPositionedObjects(relayoutChildren || isRoot());
+    bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot());
 
     // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
     computeOverflow(oldClientAfterEdge);
@@ -1350,7 +1356,12 @@
                 repaintRectangle(reflectedRect(repaintRect));
         }
     }
-    setNeedsLayout(false);
+    
+    if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) {
+        setChildNeedsLayout(true, false);
+        layoutBlock(false, pageLogicalHeight, PositionedFloatLayoutPass);
+    } else
+        setNeedsLayout(false);
 }
 
 void RenderBlock::addOverflowFromChildren()
@@ -1429,7 +1440,7 @@
     FloatingObjectSetIterator end = floatingObjectSet.end();
     for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
         FloatingObject* r = *it;
-        if (r->m_isDescendant)
+        if (r->m_isDescendant && !r->m_renderer->isPositioned())
             addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
     }
     return;
@@ -1981,7 +1992,7 @@
     else if (!child->avoidsFloats() || child->shrinkToAvoidFloats()) {
         // If an element might be affected by the presence of floats, then always mark it for
         // layout.
-        int fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
+        int fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottomIncludingPositionedFloats());
         if (fb > logicalTopEstimate)
             markDescendantsWithFloats = true;
     }
@@ -1990,7 +2001,7 @@
         if (markDescendantsWithFloats)
             childRenderBlock->markAllDescendantsWithFloatsForLayout();
         if (!child->isWritingModeRoot())
-            previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
+            previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottomIncludingPositionedFloats());
     }
 
     if (!child->needsLayout())
@@ -2159,8 +2170,8 @@
         simplifiedNormalFlowLayout();
 
     // Lay out our positioned objects if our positioned child bit is set.
-    if (posChildNeedsLayout())
-        layoutPositionedObjects(false);
+    if (posChildNeedsLayout() && layoutPositionedObjects(false))
+        return false; // If a positioned float is causing our normal flow to change, then we have to bail and do a full layout.
 
     // Recompute our overflow information.
     // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
@@ -2180,14 +2191,41 @@
     return true;
 }
 
-void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
+bool RenderBlock::positionedFloatsNeedRelayout()
 {
+    if (!hasPositionedFloats())
+        return false;
+    
+    RenderBox* positionedObject;
+    Iterator end = m_positionedObjects->end();
+    for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+        positionedObject = *it;
+        if (!positionedObject->isFloating())
+            continue;
+
+        if (positionedObject->needsLayout())
+            return true;
+
+        if (positionedObject->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && positionedObject->parent() != this && positionedObject->parent()->isBlockFlow())
+            return true;
+        
+        if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(logicalTop()) != pageLogicalOffset()))
+            return true;
+    }
+    
+    return false;
+}
+
+bool RenderBlock::layoutPositionedObjects(bool relayoutChildren)
+{
     if (!m_positionedObjects)
-        return;
+        return false;
         
     if (hasColumns())
         view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
 
+    bool didFloatingBoxRelayout = false;
+
     RenderBox* r;
     Iterator end = m_positionedObjects->end();
     for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
@@ -2205,6 +2243,11 @@
         
         if (!r->needsLayout())
             r->markForPaginationRelayoutIfNeeded();
+        
+        // FIXME: Technically we could check the old placement and the new placement of the box and only invalidate if
+        // the margin box of the object actually changed.
+        if (r->needsLayout() && r->isFloating())
+            didFloatingBoxRelayout = true;
 
         // 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
         // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
@@ -2215,6 +2258,8 @@
     
     if (hasColumns())
         view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
+        
+    return didFloatingBoxRelayout;
 }
 
 void RenderBlock::markPositionedObjectsForLayout()
@@ -3156,20 +3201,22 @@
 
     // Create the special object entry & append it to the list
 
-    FloatingObject* newObj = new FloatingObject(o->style()->floating() == LeftFloat ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
+    FloatingObject* newObj = new FloatingObject(o->style()->floating());
     
     // Our location is irrelevant if we're unsplittable or no pagination is in effect.
     // Just go ahead and lay out the float.
-    bool isChildRenderBlock = o->isRenderBlock();
-    if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
-        o->setChildNeedsLayout(true, false);
-        
-    bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageLogicalHeight;
-    if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
-        o->layoutIfNeeded();
-    else {
-        o->computeLogicalWidth();
-        o->computeBlockDirectionMargins(this);
+    if (!o->isPositioned()) {
+        bool isChildRenderBlock = o->isRenderBlock();
+        if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
+            o->setChildNeedsLayout(true, false);
+            
+        bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageLogicalHeight;
+        if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
+            o->layoutIfNeeded();
+        else {
+            o->computeLogicalWidth();
+            o->computeBlockDirectionMargins(this);
+        }
     }
     setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
 
@@ -3276,8 +3323,9 @@
     for (; it != end; ++it) {
          FloatingObject* floatingObject = *it;
         // The containing block is responsible for positioning floats, so if we have floats in our
-        // list that come from somewhere else, do not attempt to position them.
-        if (floatingObject->renderer()->containingBlock() != this)
+        // list that come from somewhere else, do not attempt to position them. Also don't attempt to handle
+        // positioned floats, since the positioning layout code handles those.
+        if (floatingObject->renderer()->containingBlock() != this || floatingObject->renderer()->isPositioned())
             continue;
 
         RenderBox* childBox = floatingObject->renderer();
@@ -3592,14 +3640,45 @@
     }
 }
 
-void RenderBlock::clearFloats()
+void RenderBlock::addPositionedFloats()
 {
+    if (!m_positionedObjects)
+        return;
+    
+    Iterator end = m_positionedObjects->end();
+    for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+        RenderBox* positionedObject = *it;
+        if (!positionedObject->isFloating())
+            continue;
+
+        ASSERT(!positionedObject->needsLayout());
+
+        // If we're a positioned float, then we need to insert ourselves as a floating object also. We only do
+        // this after the positioned object has received a layout, since otherwise the dimensions and placement
+        // won't be correct.
+        FloatingObject* floatingObject = insertFloatingObject(positionedObject);
+        setLogicalLeftForFloat(floatingObject, logicalLeftForChild(positionedObject) - marginLogicalLeftForChild(positionedObject));
+        setLogicalTopForFloat(floatingObject, logicalTopForChild(positionedObject) - marginBeforeForChild(positionedObject));
+        setLogicalHeightForFloat(floatingObject, logicalHeightForChild(positionedObject) + marginBeforeForChild(positionedObject) + marginAfterForChild(positionedObject));
+        floatingObject->setIsPlaced(true);
+        
+        m_hasPositionedFloats = true;
+    }
+}
+
+void RenderBlock::clearFloats(BlockLayoutPass layoutPass)
+{
+    // Clear our positioned floats boolean.
+    m_hasPositionedFloats = false;
+
     // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
     if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
         if (m_floatingObjects) {
             deleteAllValues(m_floatingObjects->set());
             m_floatingObjects->clear();
         }
+        if (layoutPass == PositionedFloatLayoutPass)
+            addPositionedFloats();
         return;
     }
 
@@ -3619,6 +3698,9 @@
         m_floatingObjects->clear();
     }
 
+    if (layoutPass == PositionedFloatLayoutPass)
+        addPositionedFloats();
+
     // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add 
     // floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
     // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
@@ -3628,13 +3710,13 @@
     // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
     // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
     // to avoid floats.
-    bool parentHasFloats = false;
     RenderBlock* parentBlock = toRenderBlock(parent());
+    bool parentHasFloats = parentBlock->hasPositionedFloats();
     RenderObject* prev = previousSibling();
     while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
         if (prev->isFloating())
             parentHasFloats = true;
-         prev = prev->previousSibling();
+        prev = prev->previousSibling();
     }
 
     // First add in floats from the parent.
@@ -3645,17 +3727,14 @@
     int logicalLeftOffset = 0;
     if (prev)
         logicalTopOffset -= toRenderBox(prev)->logicalTop();
-    else {
+    else if (!parentHasFloats) {
         prev = parentBlock;
         logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
     }
 
-    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
-    if (!prev || !prev->isRenderBlock())
-        return;
-    
+    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.    
     RenderBlock* block = toRenderBlock(prev);
-    if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
+    if (block && block->m_floatingObjects && block->lowestFloatLogicalBottomIncludingPositionedFloats() > logicalTopOffset)
         addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
 
     if (childrenInline()) {
@@ -6182,7 +6261,21 @@
     ASSERT_NOT_REACHED();
     return child->marginBottom();
 }
-    
+
+LayoutUnit RenderBlock::marginLogicalLeftForChild(RenderBoxModelObject* child) const
+{
+    if (isHorizontalWritingMode())
+        return child->marginLeft();
+    return child->marginTop();
+}
+
+LayoutUnit RenderBlock::marginLogicalRightForChild(RenderBoxModelObject* child) const
+{
+    if (isHorizontalWritingMode())
+        return child->marginRight();
+    return child->marginBottom();
+}
+
 LayoutUnit RenderBlock::marginStartForChild(RenderBoxModelObject* child) const
 {
     if (isHorizontalWritingMode())
@@ -6352,22 +6445,27 @@
     m_set.clear();
     m_leftObjectsCount = 0;
     m_rightObjectsCount = 0;
+    m_positionedObjectsCount = 0;
 }
 
 inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
 {    
     if (type == FloatingObject::FloatLeft)
         m_leftObjectsCount++;
+    else if (type == FloatingObject::FloatRight)
+        m_rightObjectsCount++;
     else
-        m_rightObjectsCount++;
+        m_positionedObjectsCount++;
 }
 
 inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
 {
     if (type == FloatingObject::FloatLeft)
         m_leftObjectsCount--;
+    else if (type == FloatingObject::FloatRight)
+        m_rightObjectsCount--;
     else
-        m_rightObjectsCount--;
+        m_positionedObjectsCount--;
 }
 
 TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2011-07-29 20:19:03 UTC (rev 92004)
@@ -89,7 +89,8 @@
     virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
     virtual void removeChild(RenderObject*);
 
-    virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0);
+    enum BlockLayoutPass { NormalLayoutPass, PositionedFloatLayoutPass };
+    virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass);
 
     void insertPositionedObject(RenderBox*);
     void removePositionedObject(RenderBox*);
@@ -198,12 +199,15 @@
     int logicalWidthForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
     int logicalHeightForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
     int logicalTopForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
+    int logicalLeftForChild(RenderBox* child) { return isHorizontalWritingMode() ? child->x() : child->y(); }
     void setLogicalLeftForChild(RenderBox* child, int logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
     void setLogicalTopForChild(RenderBox* child, int logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
     LayoutUnit marginBeforeForChild(RenderBoxModelObject* child) const;
     LayoutUnit marginAfterForChild(RenderBoxModelObject* child) const;
     LayoutUnit marginStartForChild(RenderBoxModelObject* child) const;
     LayoutUnit marginEndForChild(RenderBoxModelObject* child) const;
+    LayoutUnit marginLogicalLeftForChild(RenderBoxModelObject* child) const;
+    LayoutUnit marginLogicalRightForChild(RenderBoxModelObject* child) const;
     void setMarginStartForChild(RenderBox* child, LayoutUnit);
     void setMarginEndForChild(RenderBox* child, LayoutUnit);
     void setMarginBeforeForChild(RenderBox* child, LayoutUnit);
@@ -295,7 +299,7 @@
 
     virtual void layout();
 
-    void layoutPositionedObjects(bool relayoutChildren);
+    bool layoutPositionedObjects(bool relayoutChildren);
 
     virtual void paint(PaintInfo&, const LayoutPoint&);
     virtual void paintObject(PaintInfo&, const LayoutPoint&);
@@ -406,18 +410,25 @@
     struct FloatingObject {
         WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
     public:
-        // Note that Type uses bits so you can use FloatBoth as a mask to query for both left and right.
-        enum Type { FloatLeft = 1, FloatRight = 2, FloatBoth = 3 };
+        // FloatLeftRight is a mask to query for both left and right but not positioned.
+        // FloatAll is a mask to query for all types of floats.
+        enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3, FloatPositioned = 4, FloatAll = 7 };
 
-        FloatingObject(Type type)
+        FloatingObject(EFloat type)
             : m_renderer(0)
             , m_originatingLine(0)
             , m_paginationStrut(0)
-            , m_type(type)
-            , m_shouldPaint(true)
+            , m_shouldPaint(false)
             , m_isDescendant(false)
             , m_isPlaced(false)
         {
+            ASSERT(type != NoFloat);
+            if (type == LeftFloat)
+                m_type = FloatLeft;
+            else if (type == RightFloat)
+                m_type = FloatRight;
+            else if (type == PositionedFloat)
+                m_type = FloatPositioned;
         }
 
         FloatingObject(Type type, const IntRect& frameRect)
@@ -426,7 +437,7 @@
             , m_frameRect(frameRect)
             , m_paginationStrut(0)
             , m_type(type)
-            , m_shouldPaint(true)
+            , m_shouldPaint(type != FloatPositioned)
             , m_isDescendant(false)
             , m_isPlaced(true)
         {
@@ -457,7 +468,7 @@
         RootInlineBox* m_originatingLine;
         IntRect m_frameRect;
         int m_paginationStrut;
-        unsigned m_type : 2; // Type (left or right aligned)
+        unsigned m_type : 3; // Type (left/right aligned or positioned)
         bool m_shouldPaint : 1;
         bool m_isDescendant : 1;
         bool m_isPlaced : 1;
@@ -581,17 +592,23 @@
     // Returns true if and only if it has positioned any floats.
     bool positionNewFloats();
 
-    void clearFloats();
+    bool hasPositionedFloats() const { return m_hasPositionedFloats; }
+    void addPositionedFloats();
+    bool positionedFloatsNeedRelayout();
+
+    void clearFloats(BlockLayoutPass);
     int getClearDelta(RenderBox* child, int yPos);
 
     virtual bool avoidsFloats() const;
 
-    bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
+    bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottomIncludingPositionedFloats() > logicalHeight(); }
     bool hasOverhangingFloat(RenderBox*);
     void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
     int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset, bool makeChildPaintOtherFloats);
 
-    int lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatBoth) const;
+    int lowestFloatLogicalBottom() const { return lowestFloatLogicalBottom(FloatingObject::FloatLeftRight); }
+    int lowestFloatLogicalBottomIncludingPositionedFloats() const { return lowestFloatLogicalBottom(FloatingObject::FloatAll); }
+    int lowestFloatLogicalBottom(FloatingObject::Type) const;
     int nextFloatLogicalBottomBelow(int) const;
     
     virtual bool hitTestColumns(const HitTestRequest&, HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
@@ -783,6 +800,7 @@
         FloatingObjects()
             : m_leftObjectsCount(0)
             , m_rightObjectsCount(0)
+            , m_positionedObjectsCount(0)
         {
         }
 
@@ -791,12 +809,14 @@
         void decreaseObjectsCount(FloatingObject::Type);
         bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
         bool hasRightObjects() const { return m_rightObjectsCount > 0; }
+        bool hasPositionedObjects() const { return m_positionedObjectsCount > 0; }
         FloatingObjectSet& set() { return m_set; }
 
     private:
         FloatingObjectSet m_set;
         unsigned m_leftObjectsCount;
         unsigned m_rightObjectsCount;
+        unsigned m_positionedObjectsCount;
     };
     OwnPtr<FloatingObjects> m_floatingObjects;
     
@@ -842,8 +862,9 @@
     RenderObjectChildList m_children;
     RenderLineBoxList m_lineBoxes;   // All of the root line boxes created for this block flow.  For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
 
-    mutable signed m_lineHeight : 31;
+    mutable signed m_lineHeight : 30;
     bool m_beingDestroyed : 1;
+    bool m_hasPositionedFloats : 1;
 
     // RenderRubyBase objects need to be able to split and merge, moving their children around
     // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2011-07-29 20:19:03 UTC (rev 92004)
@@ -354,7 +354,7 @@
         setHasBoxDecorations(true);
 
     setPositioned(style()->position() == AbsolutePosition || style()->position() == FixedPosition);
-    setFloating(!isPositioned() && style()->isFloating());
+    setFloating(style()->isFloating() && (!isPositioned() || style()->floating() == PositionedFloat));
 
     // We also handle <body> and <html>, whose overflow applies to the viewport.
     if (style()->overflowX() != OVISIBLE && !isRootObject && (isRenderBlock() || isTableRow() || isTableSection())) {

Modified: trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.cpp	2011-07-29 20:19:03 UTC (rev 92004)
@@ -198,7 +198,7 @@
     setPreferredLogicalWidthsDirty(false);
 }
 
-void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, int /*pageHeight FIXME: Implement */)
+void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, int pageLogicalHeight, BlockLayoutPass layoutPass)
 {
     ASSERT(needsLayout());
 
@@ -245,7 +245,7 @@
     if (previousSize.height() != height())
         relayoutChildren = true;
 
-    layoutPositionedObjects(relayoutChildren || isRoot());
+    bool needAnotherLayoutPass = layoutPositionedObjects(relayoutChildren || isRoot());
 
     if (!isFloatingOrPositioned() && height() == 0) {
         // We are a block with no border and padding and a computed height
@@ -282,7 +282,11 @@
     // Repaint with our new bounds if they are different from our old bounds.
     repainter.repaintAfterLayout();
 
-    setNeedsLayout(false);
+    if (needAnotherLayoutPass && layoutPass == NormalLayoutPass) {
+        setChildNeedsLayout(true, false);
+        layoutBlock(false, pageLogicalHeight);
+    } else
+        setNeedsLayout(false);
 }
 
 // The first walk over our kids is to find out if we have any flexible children.

Modified: trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderDeprecatedFlexibleBox.h	2011-07-29 20:19:03 UTC (rev 92004)
@@ -40,7 +40,7 @@
     void calcHorizontalPrefWidths();
     void calcVerticalPrefWidths();
 
-    virtual void layoutBlock(bool relayoutChildren, int pageHeight);
+    virtual void layoutBlock(bool relayoutChildren, int pageHeight = 0, BlockLayoutPass = NormalLayoutPass);
     void layoutHorizontalBox(bool relayoutChildren);
     void layoutVerticalBox(bool relayoutChildren);
 

Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.h (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderFlexibleBox.h	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.h	2011-07-29 20:19:03 UTC (rev 92004)
@@ -46,7 +46,7 @@
 
     virtual bool isFlexibleBox() const { return true; }
 
-    virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight);
+    virtual void layoutBlock(bool relayoutChildren, int pageLogicalHeight = 0, BlockLayoutPass = NormalLayoutPass);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (92003 => 92004)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2011-07-29 19:56:19 UTC (rev 92003)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2011-07-29 20:19:03 UTC (rev 92004)
@@ -2241,7 +2241,7 @@
                     RenderBlock* block = toRenderBlock(renderer());
                     block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow,
                                              box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
-                    block->layoutBlock(true);
+                    block->layoutBlock(true); // FIXME: Need to handle positioned floats triggering extra relayouts.
                 } else
                     renderer()->layout();
                 m_inOverflowRelayout = false;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to