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;