summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering/RenderBlock.cpp')
-rw-r--r--WebCore/rendering/RenderBlock.cpp575
1 files changed, 236 insertions, 339 deletions
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index e10c331..902a5b3 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -33,6 +33,7 @@
#include "HTMLNames.h"
#include "HitTestResult.h"
#include "InlineTextBox.h"
+#include "RenderFlexibleBox.h"
#include "RenderImage.h"
#include "RenderInline.h"
#include "RenderMarquee.h"
@@ -118,8 +119,6 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int top, int bottom)
m_posMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(true) : 0;
m_negMargin = m_canCollapseTopWithChildren ? block->maxTopMargin(false) : 0;
-
- m_selfCollapsingBlockClearedFloat = false;
m_topQuirk = m_bottomQuirk = m_determinedTopQuirk = false;
}
@@ -132,10 +131,6 @@ RenderBlock::RenderBlock(Node* node)
, m_positionedObjects(0)
, m_inlineContinuation(0)
, m_maxMargin(0)
- , m_overflowHeight(0)
- , m_overflowWidth(0)
- , m_overflowLeft(0)
- , m_overflowTop(0)
, m_lineHeight(-1)
{
setChildrenInline(true);
@@ -554,103 +549,6 @@ void RenderBlock::removeChild(RenderObject* oldChild)
}
}
-int RenderBlock::overflowHeight(bool includeInterior) const
-{
- if (!includeInterior && hasOverflowClip()) {
- int shadowTop;
- int shadowBottom;
- style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
-
- int inflatedHeight = height() + shadowBottom;
- if (hasReflection())
- inflatedHeight = max(inflatedHeight, reflectionBox().bottom());
- return inflatedHeight;
- }
- return m_overflowHeight;
-}
-
-int RenderBlock::overflowWidth(bool includeInterior) const
-{
- if (!includeInterior && hasOverflowClip()) {
- int shadowLeft;
- int shadowRight;
- style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
-
- int inflatedWidth = width() + shadowRight;
- if (hasReflection())
- inflatedWidth = max(inflatedWidth, reflectionBox().right());
- return inflatedWidth;
- }
- return m_overflowWidth;
-}
-
-int RenderBlock::overflowLeft(bool includeInterior) const
-{
- if (!includeInterior && hasOverflowClip()) {
- int shadowLeft;
- int shadowRight;
- style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
-
- int left = shadowLeft;
- if (hasReflection())
- left = min(left, reflectionBox().x());
- return left;
- }
- return m_overflowLeft;
-}
-
-int RenderBlock::overflowTop(bool includeInterior) const
-{
- if (!includeInterior && hasOverflowClip()) {
- int shadowTop;
- int shadowBottom;
- style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
-
- int top = shadowTop;
- if (hasReflection())
- top = min(top, reflectionBox().y());
- return top;
- }
- return m_overflowTop;
-}
-
-IntRect RenderBlock::overflowRect(bool includeInterior) const
-{
- if (!includeInterior && hasOverflowClip()) {
- IntRect box = borderBoxRect();
-
- int shadowLeft;
- int shadowRight;
- int shadowTop;
- int shadowBottom;
- style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
-
- box.move(shadowLeft, shadowTop);
- box.setWidth(box.width() - shadowLeft + shadowRight);
- box.setHeight(box.height() - shadowTop + shadowBottom);
-
- if (hasReflection()) {
- IntRect reflection(reflectionBox());
- int reflectTop = min(box.y(), reflection.y());
- int reflectBottom = max(box.bottom(), reflection.bottom());
- box.setHeight(reflectBottom - reflectTop);
- box.setY(reflectTop);
-
- int reflectLeft = min(box.x(), reflection.x());
- int reflectRight = max(box.right(), reflection.right());
- box.setWidth(reflectRight - reflectLeft);
- box.setX(reflectLeft);
- }
- return box;
- }
-
- if (!includeInterior && hasOverflowClip())
- return borderBoxRect();
- int l = overflowLeft(includeInterior);
- int t = overflowTop(includeInterior);
- return IntRect(l, t, overflowWidth(includeInterior) - l, max(overflowHeight(includeInterior), height()) - t);
-}
-
bool RenderBlock::isSelfCollapsingBlock() const
{
// We are not self-collapsing if we
@@ -744,13 +642,9 @@ void RenderBlock::layout()
layoutBlock(false);
// It's safe to check for control clip here, since controls can never be table cells.
- if (hasControlClip()) {
- // Because of the lightweight clip, there can never be any overflow from children.
- m_overflowWidth = width();
- m_overflowHeight = height();
- m_overflowLeft = 0;
- m_overflowTop = 0;
- }
+ // If we have a lightweight clip, there can never be any overflow from children.
+ if (hasControlClip() && m_overflow)
+ clearLayoutOverflow();
}
void RenderBlock::layoutBlock(bool relayoutChildren)
@@ -776,8 +670,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
calcWidth();
calcColumnWidth();
- m_overflowWidth = width();
- m_overflowLeft = 0;
+ m_overflow.clear();
if (oldWidth != width() || oldColumnWidth != desiredColumnWidth())
relayoutChildren = true;
@@ -795,8 +688,6 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
int previousHeight = height();
setHeight(0);
- m_overflowHeight = 0;
-
// We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
// our current maximal positive and negative margins. These values are used when we
// are collapsed with adjacent blocks, so for example, if you have block A and B
@@ -861,50 +752,35 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
}
}
}
+
// We have to rebalance columns to the new height.
layoutColumns(singleColumnBottom);
-
- // If the block got expanded in size, then increase our overflowheight to match.
- if (m_overflowHeight > height())
- m_overflowHeight -= toAdd;
- if (m_overflowHeight < height())
- m_overflowHeight = height();
}
+
if (previousHeight != height())
relayoutChildren = true;
- if ((isCell || isInline() || isFloatingOrPositioned() || isRoot()) && !hasOverflowClip() && !hasControlClip())
- addVisualOverflow(floatRect());
+ // It's weird that we're treating float information as normal flow overflow, but we do this because floatRect() isn't
+ // able to be propagated up the render tree yet. Overflow information is however. This check is designed to catch anyone
+ // who wasn't going to propagate float information up to the parent and yet could potentially be painted by its ancestor.
+ if (isRoot() || expandsToEncloseOverhangingFloats())
+ addOverflowFromFloats();
- layoutPositionedObjects(relayoutChildren || isRoot());
+ // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
+ if (!hasColumns()) {
+ if (childrenInline())
+ addOverflowFromInlineChildren();
+ else
+ addOverflowFromBlockChildren();
+ }
- positionListMarker();
+ // Add visual overflow from box-shadow and reflections.
+ addShadowOverflow();
- // Always ensure our overflow width/height are at least as large as our width/height.
- m_overflowWidth = max(m_overflowWidth, width());
- m_overflowHeight = max(m_overflowHeight, height());
-
- if (!hasOverflowClip()) {
- int shadowLeft;
- int shadowRight;
- int shadowTop;
- int shadowBottom;
- style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
-
- m_overflowLeft = min(m_overflowLeft, shadowLeft);
- m_overflowWidth = max(m_overflowWidth, width() + shadowRight);
- m_overflowTop = min(m_overflowTop, shadowTop);
- m_overflowHeight = max(m_overflowHeight, height() + shadowBottom);
-
- if (hasReflection()) {
- IntRect reflection(reflectionBox());
- m_overflowLeft = min(m_overflowLeft, reflection.x());
- m_overflowWidth = max(m_overflowWidth, reflection.right());
- m_overflowTop = min(m_overflowTop, reflection.y());
- m_overflowHeight = max(m_overflowHeight, reflection.bottom());
- }
- }
+ layoutPositionedObjects(relayoutChildren || isRoot());
+ positionListMarker();
+
statePusher.pop();
// Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
@@ -914,7 +790,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
// Repaint with our new bounds if they are different from our old bounds.
bool didFullRepaint = repainter.repaintAfterLayout();
if (!didFullRepaint && repaintTop != repaintBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
- IntRect repaintRect(m_overflowLeft, repaintTop, m_overflowWidth - m_overflowLeft, repaintBottom - repaintTop);
+ int repaintLeft = min(leftVisualOverflow(), leftLayoutOverflow());
+ int repaintRight = max(rightVisualOverflow(), rightLayoutOverflow());
+ IntRect repaintRect(repaintLeft, repaintTop, repaintRight - repaintLeft, repaintBottom - repaintTop);
// FIXME: Deal with multiple column repainting. We have to split the repaint
// rect up into multiple rects if it spans columns.
@@ -943,6 +821,28 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
setNeedsLayout(false);
}
+void RenderBlock::addOverflowFromBlockChildren()
+{
+ for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+ if (!child->isFloatingOrPositioned())
+ addOverflowFromChild(child);
+ }
+}
+
+void RenderBlock::addOverflowFromFloats()
+{
+ IntRect result;
+ if (!m_floatingObjects)
+ return;
+ FloatingObject* r;
+ DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for (; (r = it.current()); ++it) {
+ if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer())
+ addOverflowFromChild(r->m_renderer, IntSize(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop()));
+ }
+ return;
+}
+
bool RenderBlock::expandsToEncloseOverhangingFloats() const
{
return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox()) || hasColumns() || isTableCell() || isFieldset();
@@ -1032,7 +932,10 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
// See if we have a run-in element with inline children. If the
// children aren't inline, then just treat the run-in as a normal
// block.
- if (!child->isRunIn() || !child->childrenInline() && !child->isReplaced())
+ if (!child->isRunIn() || !child->childrenInline())
+ return false;
+ // FIXME: We don't handle non-block elements with run-in for now.
+ if (!child->isRenderBlock())
return false;
// Get the next non-positioned/non-floating RenderBlock.
@@ -1166,8 +1069,6 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
if (marginInfo.margin())
marginInfo.setBottomQuirk(child->isBottomMarginQuirk() || style()->marginBottomCollapse() == MDISCARD);
-
- marginInfo.setSelfCollapsingBlockClearedFloat(false);
}
return ypos;
@@ -1183,16 +1084,26 @@ int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, i
// For self-collapsing blocks that clear, they can still collapse their
// margins with following siblings. Reset the current margins to represent
// the self-collapsing block's margins only.
- marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
- marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
+ // CSS2.1 states:
+ // "An element that has had clearance applied to it never collapses its top margin with its parent block's bottom margin.
+ // Therefore if we are at the bottom of the block, let's go ahead and reset margins to only include the
+ // self-collapsing block's bottom margin.
+ bool atBottomOfBlock = true;
+ for (RenderBox* curr = child->nextSiblingBox(); curr && atBottomOfBlock; curr = curr->nextSiblingBox()) {
+ if (!curr->isFloatingOrPositioned())
+ atBottomOfBlock = false;
+ }
+ if (atBottomOfBlock) {
+ marginInfo.setPosMargin(child->maxBottomMargin(true));
+ marginInfo.setNegMargin(child->maxBottomMargin(false));
+ } else {
+ marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
+ marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
+ }
- // Adjust our height such that we are ready to be collapsed with subsequent siblings.
+ // Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
+ // of the parent block).
setHeight(child->y() - max(0, marginInfo.margin()));
-
- // Set a flag that we cleared a float so that we know both to increase the height of the block
- // to compensate for the clear and to avoid collapsing our margins with the parent block's
- // bottom margin.
- marginInfo.setSelfCollapsingBlockClearedFloat(true);
} else
// Increase our height by the amount we had to clear.
setHeight(height() + heightIncrease);
@@ -1296,17 +1207,7 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
{
- // If our last flow was a self-collapsing block that cleared a float, then we don't
- // collapse it with the bottom of the block.
- if (!marginInfo.selfCollapsingBlockClearedFloat())
- marginInfo.setAtBottomOfBlock(true);
- else {
- // We have to special case the negative margin situation (where the collapsed
- // margin of the self-collapsing block is negative), since there's no need
- // to make an adjustment in that case.
- if (marginInfo.margin() < 0)
- marginInfo.clearMargin();
- }
+ marginInfo.setAtBottomOfBlock(true);
// If we can't collapse with children then go ahead and add in the bottom margin.
if (!marginInfo.canCollapseWithBottom() && !marginInfo.canCollapseWithTop()
@@ -1320,9 +1221,6 @@ void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInf
// If this happens, ensure that the computed height is increased to the minimal height.
setHeight(max(height(), top + bottom));
- // Always make sure our overflow height is at least our height.
- m_overflowHeight = max(height(), m_overflowHeight);
-
// Update our bottom collapsed margin info.
setCollapsedBottomMargin(marginInfo);
}
@@ -1350,8 +1248,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
int top = borderTop() + paddingTop();
int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
- m_overflowHeight = top;
- setHeight(m_overflowHeight);
+ setHeight(top);
// The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
MarginInfo marginInfo(this, top, bottom);
@@ -1372,9 +1269,6 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
if (legend == child)
continue; // Skip the legend, since it has already been positioned up in the fieldset's border.
- int oldTopPosMargin = maxTopPosMargin();
- int oldTopNegMargin = maxTopNegMargin();
-
// Make sure we layout children if they need it.
// FIXME: Technically percentage height objects only need a relayout if their percentage isn't going to be turned into
// an auto value. Add a method to determine this, so that we can avoid the relayout.
@@ -1390,127 +1284,127 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
if (handleSpecialChild(child, marginInfo))
continue;
- // The child is a normal flow object. Compute its vertical margins now.
- child->calcVerticalMargins();
+ // Lay out the child.
+ layoutBlockChild(child, marginInfo, previousFloatBottom, maxFloatBottom);
+ }
+
+ // Now do the handling of the bottom of the block, adding in our bottom border/padding and
+ // determining the correct collapsed bottom margin information.
+ handleBottomOfBlock(top, bottom, marginInfo);
+}
- // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
- if (child->style()->marginTopCollapse() == MSEPARATE) {
- marginInfo.setAtTopOfBlock(false);
- marginInfo.clearMargin();
- }
+void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatBottom, int& maxFloatBottom)
+{
+ int oldTopPosMargin = maxTopPosMargin();
+ int oldTopNegMargin = maxTopNegMargin();
- // Try to guess our correct y position. In most cases this guess will
- // be correct. Only if we're wrong (when we compute the real y position)
- // will we have to potentially relayout.
- int yPosEstimate = estimateVerticalPosition(child, marginInfo);
+ // The child is a normal flow object. Compute its vertical margins now.
+ child->calcVerticalMargins();
- // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
- IntRect oldRect(child->x(), child->y() , child->width(), child->height());
+ // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
+ if (child->style()->marginTopCollapse() == MSEPARATE) {
+ marginInfo.setAtTopOfBlock(false);
+ marginInfo.clearMargin();
+ }
+
+ // Try to guess our correct y position. In most cases this guess will
+ // be correct. Only if we're wrong (when we compute the real y position)
+ // will we have to potentially relayout.
+ int yPosEstimate = estimateVerticalPosition(child, marginInfo);
+
+ // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
+ IntRect oldRect(child->x(), child->y() , child->width(), child->height());
#ifndef NDEBUG
- IntSize oldLayoutDelta = view()->layoutDelta();
+ IntSize oldLayoutDelta = view()->layoutDelta();
#endif
- // Go ahead and position the child as though it didn't collapse with the top.
- view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate));
- child->setLocation(child->x(), yPosEstimate);
-
- bool markDescendantsWithFloats = false;
- if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ // Go ahead and position the child as though it didn't collapse with the top.
+ view()->addLayoutDelta(IntSize(0, child->y() - yPosEstimate));
+ child->setLocation(child->x(), yPosEstimate);
+
+ bool markDescendantsWithFloats = false;
+ if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ markDescendantsWithFloats = true;
+ 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(previousFloatBottom, floatBottom());
+ if (fb > yPosEstimate)
markDescendantsWithFloats = true;
- 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(previousFloatBottom, floatBottom());
- if (fb > yPosEstimate)
- markDescendantsWithFloats = true;
- }
+ }
- if (child->isRenderBlock()) {
- if (markDescendantsWithFloats)
- toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
+ if (child->isRenderBlock()) {
+ if (markDescendantsWithFloats)
+ toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
- previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom());
- }
+ previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom());
+ }
- bool childHadLayout = child->m_everHadLayout;
- bool childNeededLayout = child->needsLayout();
- if (childNeededLayout)
- child->layout();
+ bool childHadLayout = child->m_everHadLayout;
+ bool childNeededLayout = child->needsLayout();
+ if (childNeededLayout)
+ child->layout();
- // Now determine the correct ypos based off examination of collapsing margin
- // values.
- int yBeforeClear = collapseMargins(child, marginInfo);
+ // Now determine the correct ypos based off examination of collapsing margin
+ // values.
+ int yBeforeClear = collapseMargins(child, marginInfo);
- // Now check for clear.
- int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear);
-
- view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear));
- child->setLocation(child->x(), yAfterClear);
+ // Now check for clear.
+ int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear);
- // Now we have a final y position. See if it really does end up being different from our estimate.
- if (yAfterClear != yPosEstimate) {
- if (child->shrinkToAvoidFloats()) {
- // The child's width depends on the line width.
- // When the child shifts to clear an item, its width can
- // change (because it has more available line width).
- // So go ahead and mark the item as dirty.
- child->setChildNeedsLayout(true, false);
- }
- if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
- toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
- // Our guess was wrong. Make the child lay itself out again.
- child->layoutIfNeeded();
+ view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear));
+ child->setLocation(child->x(), yAfterClear);
+
+ // Now we have a final y position. See if it really does end up being different from our estimate.
+ if (yAfterClear != yPosEstimate) {
+ if (child->shrinkToAvoidFloats()) {
+ // The child's width depends on the line width.
+ // When the child shifts to clear an item, its width can
+ // change (because it has more available line width).
+ // So go ahead and mark the item as dirty.
+ child->setChildNeedsLayout(true, false);
}
+ if (!child->avoidsFloats() && child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ toRenderBlock(child)->markAllDescendantsWithFloatsForLayout();
+ // Our guess was wrong. Make the child lay itself out again.
+ child->layoutIfNeeded();
+ }
- // We are no longer at the top of the block if we encounter a non-empty child.
- // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
- if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
- marginInfo.setAtTopOfBlock(false);
-
- // Now place the child in the correct horizontal position
- determineHorizontalPosition(child);
+ // We are no longer at the top of the block if we encounter a non-empty child.
+ // This has to be done after checking for clear, so that margins can be reset if a clear occurred.
+ if (marginInfo.atTopOfBlock() && !child->isSelfCollapsingBlock())
+ marginInfo.setAtTopOfBlock(false);
- // Update our height now that the child has been placed in the correct position.
- setHeight(height() + child->height());
- if (child->style()->marginBottomCollapse() == MSEPARATE) {
- setHeight(height() + child->marginBottom());
- marginInfo.clearMargin();
- }
- // If the child has overhanging floats that intrude into following siblings (or possibly out
- // of this block), then the parent gets notified of the floats now.
- if (child->isBlockFlow() && toRenderBlock(child)->containsFloats())
- maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout));
-
- // Update our visual overflow in case the child spills out the block, but only if we were going to paint
- // the child block ourselves.
- if (!child->hasSelfPaintingLayer()) {
- m_overflowTop = min(m_overflowTop, child->y() + child->overflowTop(false));
- m_overflowHeight = max(m_overflowHeight, height() + child->overflowHeight(false) - child->height());
- m_overflowWidth = max(child->x() + child->overflowWidth(false), m_overflowWidth);
- m_overflowLeft = min(child->x() + child->overflowLeft(false), m_overflowLeft);
- }
+ // Now place the child in the correct horizontal position
+ determineHorizontalPosition(child);
- IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
- if (childOffset.width() || childOffset.height()) {
- view()->addLayoutDelta(childOffset);
+ // Update our height now that the child has been placed in the correct position.
+ setHeight(height() + child->height());
+ if (child->style()->marginBottomCollapse() == MSEPARATE) {
+ setHeight(height() + child->marginBottom());
+ marginInfo.clearMargin();
+ }
+ // If the child has overhanging floats that intrude into following siblings (or possibly out
+ // of this block), then the parent gets notified of the floats now.
+ if (child->isBlockFlow() && toRenderBlock(child)->containsFloats())
+ maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout));
- // If the child moved, we have to repaint it as well as any floating/positioned
- // descendants. An exception is if we need a layout. In this case, we know we're going to
- // repaint ourselves (and the child) anyway.
- if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
- child->repaintDuringLayoutIfMoved(oldRect);
- }
+ IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
+ if (childOffset.width() || childOffset.height()) {
+ view()->addLayoutDelta(childOffset);
- if (!childHadLayout && child->checkForRepaintDuringLayout()) {
- child->repaint();
- child->repaintOverhangingFloats(true);
- }
+ // If the child moved, we have to repaint it as well as any floating/positioned
+ // descendants. An exception is if we need a layout. In this case, we know we're going to
+ // repaint ourselves (and the child) anyway.
+ if (childHadLayout && !selfNeedsLayout() && child->checkForRepaintDuringLayout())
+ child->repaintDuringLayoutIfMoved(oldRect);
+ }
- ASSERT(oldLayoutDelta == view()->layoutDelta());
+ if (!childHadLayout && child->checkForRepaintDuringLayout()) {
+ child->repaint();
+ child->repaintOverhangingFloats(true);
}
- // Now do the handling of the bottom of the block, adding in our bottom border/padding and
- // determining the correct collapsed bottom margin information.
- handleBottomOfBlock(top, bottom, marginInfo);
+ ASSERT(oldLayoutDelta == view()->layoutDelta());
}
bool RenderBlock::layoutOnlyPositionedObjects()
@@ -1534,7 +1428,7 @@ bool RenderBlock::layoutOnlyPositionedObjects()
updateScrollInfoAfterLayout();
#ifdef ANDROID_FIX
- // iframe flatten will call FrameView::layout() which calls performPostLayoutTasks,
+ // iframe flatten will call FrameView::layout() which calls performPostLayoutTasks,
// which may make us need to layout again
if (!posChildNeedsLayout() || normalChildNeedsLayout() || selfNeedsLayout())
return false;
@@ -1623,7 +1517,7 @@ void RenderBlock::paint(PaintInfo& paintInfo, int tx, int ty)
// FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
// paints the root's background.
if (!isRoot()) {
- IntRect overflowBox = overflowRect(false);
+ IntRect overflowBox = visibleOverflowRect();
overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.move(tx, ty);
if (!overflowBox.intersects(paintInfo.rect))
@@ -2160,9 +2054,9 @@ GapRects RenderBlock::fillInlineSelectionGaps(RenderBlock* rootBlock, int blockX
if (lastSelectedLine && selectionState() != SelectionEnd && selectionState() != SelectionBoth) {
// Go ahead and update our lastY to be the bottom of the last selected line.
- lastTop = (ty - blockY) + lastSelectedLine->bottomOverflow();
- lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
- lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->bottomOverflow());
+ lastTop = (ty - blockY) + lastSelectedLine->selectionBottom();
+ lastLeft = leftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
+ lastRight = rightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
}
return result;
}
@@ -2713,13 +2607,13 @@ RenderBlock::floatBottom() const
IntRect RenderBlock::floatRect() const
{
IntRect result;
- if (!m_floatingObjects || hasOverflowClip())
+ if (!m_floatingObjects || hasOverflowClip() || hasColumns())
return result;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for (; (r = it.current()); ++it) {
if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
- IntRect childRect = r->m_renderer->overflowRect(false);
+ IntRect childRect = r->m_renderer->visibleOverflowRect();
childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
result.unite(childRect);
}
@@ -2730,10 +2624,11 @@ IntRect RenderBlock::floatRect() const
int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
{
+ int bottom = includeSelf && width() > 0 ? height() : 0;
+
if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && width() > 0 ? overflowHeight(false) : 0;
+ return bottom;
- int bottom = includeSelf && width() > 0 ? height() : 0;
if (!hasColumns()) {
// FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
// For now, we have to descend into all the children, since we may have a huge abs div inside
@@ -2757,7 +2652,7 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0;
if (includeSelf)
- bottom = max(bottom, m_overflowHeight + relativeOffset);
+ bottom = max(bottom, bottomLayoutOverflow() + relativeOffset);
if (m_positionedObjects) {
RenderBox* r;
@@ -2799,8 +2694,8 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
if (!includeSelf) {
bottom = max(bottom, borderTop() + paddingTop() + paddingBottom() + relativeOffset);
if (childrenInline()) {
- if (lastLineBox()) {
- int childBottomEdge = lastLineBox()->y() + lastLineBox()->height();
+ if (lastRootBox()) {
+ int childBottomEdge = lastRootBox()->selectionBottom();
bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
}
} else {
@@ -2820,11 +2715,11 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
- if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && height() > 0 ? overflowWidth(false) : 0;
-
int right = includeSelf && height() > 0 ? width() : 0;
+ if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+ return right;
+
if (!hasColumns()) {
// FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
// For now, we have to descend into all the children, since we may have a huge abs div inside
@@ -2847,7 +2742,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
if (includeSelf)
- right = max(right, m_overflowWidth + relativeOffset);
+ right = max(right, rightLayoutOverflow() + relativeOffset);
if (m_positionedObjects) {
RenderBox* r;
@@ -2914,10 +2809,11 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
{
+ int left = includeSelf && height() > 0 ? 0 : width();
+
if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return includeSelf && height() > 0 ? overflowLeft(false) : width();
+ return left;
- int left = includeSelf && height() > 0 ? 0 : width();
if (!hasColumns()) {
// FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
// For now, we have to descend into all the children, since we may have a huge abs div inside
@@ -2940,7 +2836,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetX() : 0;
if (includeSelf)
- left = min(left, m_overflowLeft + relativeOffset);
+ left = min(left, leftLayoutOverflow() + relativeOffset);
if (m_positionedObjects) {
RenderBox* r;
@@ -3134,9 +3030,8 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
int lowestFloatBottom = 0;
- // Floats that will remain the child's responsiblity to paint should factor into its
- // visual overflow.
- IntRect floatsOverflowRect;
+ // Floats that will remain the child's responsibility to paint should factor into its
+ // overflow.
DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
for (FloatingObject* r; (r = it.current()); ++it) {
int bottom = child->y() + r->m_bottom;
@@ -3177,13 +3072,9 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
// it should paint.
r->m_shouldPaint = true;
- if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
- IntRect floatOverflowRect = r->m_renderer->overflowRect(false);
- floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
- floatsOverflowRect.unite(floatOverflowRect);
- }
+ if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer())
+ child->addOverflowFromChild(r->m_renderer, IntSize(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop()));
}
- child->addVisualOverflow(floatsOverflowRect);
return lowestFloatBottom;
}
@@ -3298,26 +3189,20 @@ int RenderBlock::getClearDelta(RenderBox* child, int yPos)
// We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
// FIXME: Note that the remaining space checks aren't quite accurate, since you should be able to clear only some floats (the minimum # needed
// to fit) and not all (we should be using nextFloatBottomBelow and looping).
- // Do not allow tables to wrap in quirks or even in almost strict mode
- // (ebay on the PLT, finance.yahoo.com in the real world, versiontracker.com forces even almost strict mode not to work)
int result = clearSet ? max(0, bottom - yPos) : 0;
- if (!result && child->avoidsFloats() && child->style()->width().isFixed() &&
- child->minPrefWidth() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth() &&
- document()->inStrictMode())
- result = max(0, floatBottom() - yPos);
+ if (!result && child->avoidsFloats()) {
+ int oldYPos = child->y();
+ int oldWidth = child->width();
+ child->setY(yPos);
+ child->calcWidth();
+ if (child->width() > lineWidth(yPos, false) && child->minPrefWidth() <= availableWidth())
+ result = max(0, floatBottom() - yPos);
+ child->setY(oldYPos);
+ child->setWidth(oldWidth);
+ }
return result;
}
-void RenderBlock::addVisualOverflow(const IntRect& r)
-{
- if (r.isEmpty())
- return;
- m_overflowLeft = min(m_overflowLeft, r.x());
- m_overflowWidth = max(m_overflowWidth, r.right());
- m_overflowTop = min(m_overflowTop, r.y());
- m_overflowHeight = max(m_overflowHeight, r.bottom());
-}
-
bool RenderBlock::isPointInOverflowControl(HitTestResult& result, int _x, int _y, int _tx, int _ty)
{
if (!scrollsOverflow())
@@ -3333,7 +3218,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
if (!isRenderView()) {
// Check if we need to do anything at all.
- IntRect overflowBox = overflowRect(false);
+ IntRect overflowBox = visibleOverflowRect();
overflowBox.move(tx, ty);
if (!overflowBox.contains(_x, _y))
return false;
@@ -3542,9 +3427,9 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint&
if (root->nextRootBox()) {
// FIXME: We would prefer to make the break point halfway between the bottom
// of the previous root box and the top of the next root box.
- bottom = root->nextRootBox()->topOverflow();
+ bottom = root->nextRootBox()->lineTop();
} else
- bottom = root->bottomOverflow() + verticalLineClickFudgeFactor;
+ bottom = root->lineBottom() + verticalLineClickFudgeFactor;
// check if this root line box is located at this y coordinate
if (pointInContents.y() < bottom) {
@@ -3563,7 +3448,7 @@ VisiblePosition RenderBlock::positionForPointWithInlineChildren(const IntPoint&
}
if (closestBox) {
- if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->topOverflow() - verticalLineClickFudgeFactor) {
+ if (!useWindowsBehavior && pointInContents.y() < firstRootBoxWithChildren->lineTop() - verticalLineClickFudgeFactor) {
// y coordinate is above first root line box, so return the start of the first
return VisiblePosition(positionForBox(firstRootBoxWithChildren->firstLeafChild(), true), DOWNSTREAM);
}
@@ -3699,7 +3584,7 @@ void RenderBlock::calcColumnWidth()
void RenderBlock::setDesiredColumnCountAndWidth(int count, int width)
{
- if (count == 1) {
+ if (count == 1 && style()->hasAutoColumnWidth()) {
if (hasColumns()) {
delete gColumnInfoMap->take(this);
setHasColumns(false);
@@ -3836,14 +3721,16 @@ int RenderBlock::layoutColumns(int endOfContent)
colCount++;
}
- m_overflowWidth = max(width(), currX - colGap);
- m_overflowLeft = min(0, currX + desiredColumnWidth + colGap);
-
- m_overflowHeight = maxColBottom;
+ int overflowRight = max(width(), currX - colGap);
+ int overflowLeft = min(0, currX + desiredColumnWidth + colGap);
+ int overflowHeight = maxColBottom;
int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
if (computeIntrinsicHeight)
- setHeight(m_overflowHeight + toAdd);
+ setHeight(maxColBottom + toAdd);
+
+ m_overflow.clear();
+ addLayoutOverflow(IntRect(overflowLeft, 0, overflowRight - overflowLeft, overflowHeight));
v->setPrintRect(IntRect());
v->setTruncatedAt(0);
@@ -4767,7 +4654,7 @@ static int getHeightForLineCount(RenderBlock* block, int l, bool includeBottom,
if (block->childrenInline()) {
for (RootInlineBox* box = block->firstRootBox(); box; box = box->nextRootBox()) {
if (++count == l)
- return box->bottomOverflow() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
+ return box->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : 0);
}
}
else {
@@ -5098,8 +4985,11 @@ void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, in
graphicsContext->addFocusRingRect(IntRect(tx, ty, width(), height()));
if (!hasOverflowClip() && !hasControlClip()) {
- for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
- graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + curr->y(), curr->width(), curr->height()));
+ for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+ int top = max(curr->lineTop(), curr->y());
+ int bottom = min(curr->lineBottom(), curr->y() + curr->height());
+ graphicsContext->addFocusRingRect(IntRect(tx + curr->x(), ty + top, curr->width(), bottom - top));
+ }
for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
@@ -5121,13 +5011,20 @@ void RenderBlock::addFocusRingRects(GraphicsContext* graphicsContext, int tx, in
ty - y() + inlineContinuation()->containingBlock()->y());
}
-RenderBlock* RenderBlock::createAnonymousBlock() const
+RenderBlock* RenderBlock::createAnonymousBlock(bool isFlexibleBox) const
{
RefPtr<RenderStyle> newStyle = RenderStyle::create();
newStyle->inheritFrom(style());
- newStyle->setDisplay(BLOCK);
- RenderBlock* newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
+ RenderBlock* newBox = 0;
+ if (isFlexibleBox) {
+ newStyle->setDisplay(BOX);
+ newBox = new (renderArena()) RenderFlexibleBox(document() /* anonymous box */);
+ } else {
+ newStyle->setDisplay(BLOCK);
+ newBox = new (renderArena()) RenderBlock(document() /* anonymous box */);
+ }
+
newBox->setStyle(newStyle.release());
return newBox;
}