summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderBlock.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-07-11 13:45:28 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-07-11 13:45:28 +0200
commitd6a599dbc9d824a462b2b206316e102bf8136446 (patch)
treeecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/WebCore/rendering/RenderBlock.cpp
parent3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff)
downloadqtwebkit-d6a599dbc9d824a462b2b206316e102bf8136446.tar.gz
Imported WebKit commit 8ff1f22783a32de82fee915abd55bd1b298f2644 (http://svn.webkit.org/repository/webkit/trunk@122325)
New snapshot that should work with the latest Qt build system changes
Diffstat (limited to 'Source/WebCore/rendering/RenderBlock.cpp')
-rwxr-xr-xSource/WebCore/rendering/RenderBlock.cpp154
1 files changed, 120 insertions, 34 deletions
diff --git a/Source/WebCore/rendering/RenderBlock.cpp b/Source/WebCore/rendering/RenderBlock.cpp
index fdb1c0384..030b18711 100755
--- a/Source/WebCore/rendering/RenderBlock.cpp
+++ b/Source/WebCore/rendering/RenderBlock.cpp
@@ -2033,7 +2033,7 @@ LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo
RenderObject* prev = child->previousSibling();
if (prev && prev->isBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
RenderBlock* block = toRenderBlock(prev);
- if (block->containsFloats() && block->lowestFloatLogicalBottom() > logicalTop)
+ if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop)
addOverhangingFloats(block, false);
}
@@ -2071,10 +2071,10 @@ LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& margin
// Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
// of the parent block).
- setLogicalHeight(child->y() - max(ZERO_LAYOUT_UNIT, marginInfo.margin()));
+ setLogicalHeight(child->logicalTop() - max(ZERO_LAYOUT_UNIT, marginInfo.margin()));
} else
// Increase our height by the amount we had to clear.
- setLogicalHeight(height() + heightIncrease);
+ setLogicalHeight(logicalHeight() + heightIncrease);
if (marginInfo.canCollapseWithMarginBefore()) {
// We can no longer collapse with the top of the block since a clear
@@ -2089,14 +2089,60 @@ LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& margin
return yPos + heightIncrease;
}
+void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const
+{
+ // FIXME: We could get even more quirks mode cases right if we dealt with quirk containers.
+ // FIXME: We should deal with the margin-collapse-* style extensions that prevent collapsing and that discard margins.
+ LayoutUnit beforeChildMargin = marginBeforeForChild(child);
+ positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin);
+ negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin);
+
+ if (!child->isRenderBlock())
+ return;
+
+ RenderBlock* childBlock = toRenderBlock(child);
+ if (childBlock->childrenInline() || childBlock->isWritingModeRoot())
+ return;
+
+ MarginInfo childMarginInfo(childBlock, childBlock->borderBefore() + childBlock->paddingBefore(), childBlock->borderAfter() + childBlock->paddingAfter());
+ if (!childMarginInfo.canCollapseMarginBeforeWithChildren())
+ return;
+
+ RenderBox* grandchildBox = childBlock->firstChildBox();
+ for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) {
+ if (!grandchildBox->isFloatingOrOutOfFlowPositioned())
+ break;
+ }
+
+ // Give up if there is clearance on the box, since it probably won't collapse into us.
+ if (!grandchildBox || grandchildBox->style()->clear() != CNONE)
+ return;
+
+ // Collapse the margin of the grandchild box with our own to produce an estimate.
+ childBlock->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore);
+}
+
LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
{
// FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
// relayout if there are intruding floats.
LayoutUnit logicalTopEstimate = logicalHeight();
if (!marginInfo.canCollapseWithMarginBefore()) {
- LayoutUnit childMarginBefore = child->selfNeedsLayout() ? marginBeforeForChild(child) : collapsedMarginBeforeForChild(child);
- logicalTopEstimate += max(marginInfo.margin(), childMarginBefore);
+ LayoutUnit positiveMarginBefore = ZERO_LAYOUT_UNIT;
+ LayoutUnit negativeMarginBefore = ZERO_LAYOUT_UNIT;
+ if (child->selfNeedsLayout()) {
+ // Try to do a basic estimation of how the collapse is going to go.
+ marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore);
+ } else {
+ // Use the cached collapsed margin values from a previous layout. Most of the time they
+ // will be right.
+ MarginValues marginValues = marginValuesForChild(child);
+ positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore());
+ negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore());
+ }
+
+ // Collapse the result with our current margins.
+ logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore);
}
// Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
@@ -2137,7 +2183,8 @@ LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const Re
if (region)
blockOffset = max(blockOffset, blockOffset + (region->offsetFromLogicalTopOfFirstPage() - offsetFromLogicalTopOfFirstPage));
- LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage);
+ LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage, logicalHeightForChild(child));
+
if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
if (childMarginStart < 0)
startOff += childMarginStart;
@@ -3961,27 +4008,48 @@ void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox* parent)
}
}
+static bool rangesIntersect(int floatTop, int floatBottom, int objectTop, int objectBottom)
+{
+ if (objectTop >= floatBottom || objectBottom < floatTop)
+ return false;
+
+ // The top of the object overlaps the float
+ if (objectTop >= floatTop)
+ return true;
+
+ // The object encloses the float
+ if (objectTop < floatTop && objectBottom > floatBottom)
+ return true;
+
+ // The bottom of the object overlaps the float
+ if (objectBottom > objectTop && objectBottom > floatTop && objectBottom <= floatBottom)
+ return true;
+
+ return false;
+}
+
template <RenderBlock::FloatingObject::Type FloatTypeValue>
inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval) const
{
const FloatingObject* r = interval.data();
- if (r->type() == FloatTypeValue && interval.low() <= m_value && m_value < interval.high()) {
- // All the objects returned from the tree should be already placed.
- ASSERT(r->isPlaced() && m_renderer->pixelSnappedLogicalTopForFloat(r) <= m_value && m_renderer->pixelSnappedLogicalBottomForFloat(r) > m_value);
+ if (r->type() != FloatTypeValue || !rangesIntersect(interval.low(), interval.high(), m_lowValue, m_highValue))
+ return;
- if (FloatTypeValue == FloatingObject::FloatLeft
- && m_renderer->logicalRightForFloat(r) > m_offset) {
- m_offset = m_renderer->logicalRightForFloat(r);
- if (m_heightRemaining)
- *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value;
- }
+ // All the objects returned from the tree should be already placed.
+ ASSERT(r->isPlaced() && rangesIntersect(m_renderer->pixelSnappedLogicalTopForFloat(r), m_renderer->pixelSnappedLogicalBottomForFloat(r), m_lowValue, m_highValue));
- if (FloatTypeValue == FloatingObject::FloatRight
- && m_renderer->logicalLeftForFloat(r) < m_offset) {
- m_offset = m_renderer->logicalLeftForFloat(r);
- if (m_heightRemaining)
- *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value;
- }
+ if (FloatTypeValue == FloatingObject::FloatLeft
+ && m_renderer->logicalRightForFloat(r) > m_offset) {
+ m_offset = m_renderer->logicalRightForFloat(r);
+ if (m_heightRemaining)
+ *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
+ }
+
+ if (FloatTypeValue == FloatingObject::FloatRight
+ && m_renderer->logicalLeftForFloat(r) < m_offset) {
+ m_offset = m_renderer->logicalLeftForFloat(r);
+ if (m_heightRemaining)
+ *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
}
}
@@ -4015,14 +4083,14 @@ LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region, Layou
return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
}
-LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const
+LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
{
LayoutUnit left = fixedOffset;
if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) {
if (heightRemaining)
*heightRemaining = 1;
- FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, roundToInt(logicalTop), left, heightRemaining);
+ FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), left, heightRemaining);
m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
}
@@ -4062,7 +4130,7 @@ LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUn
return left;
}
-LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const
+LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
{
LayoutUnit right = fixedOffset;
if (m_floatingObjects && m_floatingObjects->hasRightObjects()) {
@@ -4070,7 +4138,7 @@ LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutU
*heightRemaining = 1;
LayoutUnit rightFloatOffset = fixedOffset;
- FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, roundToInt(logicalTop), rightFloatOffset, heightRemaining);
+ FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), rightFloatOffset, heightRemaining);
m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
right = min(right, rightFloatOffset);
}
@@ -4511,7 +4579,7 @@ LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
if (!result && child->avoidsFloats()) {
LayoutUnit newLogicalTop = logicalTop;
while (true) {
- LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false);
+ LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
return newLogicalTop - logicalTop;
@@ -5083,6 +5151,13 @@ bool RenderBlock::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, Layo
if (!hasColumns())
return false;
+ OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
+ if (childrenInline())
+ addOverflowFromInlineChildren();
+ else
+ addOverflowFromBlockChildren();
+ LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore();
+
// FIXME: We don't balance properly at all in the presence of forced page breaks. We need to understand what
// the distance between forced page breaks is so that we can avoid making the minimum column height too tall.
ColumnInfo* colInfo = columnInfo();
@@ -5095,12 +5170,12 @@ bool RenderBlock::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, Layo
// maximum page break distance.
if (!pageLogicalHeight) {
LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
- view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + contentLogicalHeight()) - colInfo->forcedBreakOffset());
+ view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
}
- } else if (contentLogicalHeight() > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
+ } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
// Now that we know the intrinsic height of the columns, we have to rebalance them.
- columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)contentLogicalHeight() / desiredColumnCount));
+ columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount));
}
if (columnHeight && columnHeight != pageLogicalHeight) {
@@ -5110,14 +5185,15 @@ bool RenderBlock::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, Layo
return true;
}
}
-
+
if (pageLogicalHeight)
- colInfo->setColumnCountAndHeight(ceilf((float)contentLogicalHeight() / pageLogicalHeight), pageLogicalHeight);
+ colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight);
if (columnCount(colInfo)) {
setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
m_overflow.clear();
- }
+ } else
+ m_overflow = savedOverflow.release();
return false;
}
@@ -5490,7 +5566,7 @@ static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
{
- LayoutUnit snappedResult = ceilf(result);
+ LayoutUnit snappedResult = LayoutUnit::fromFloatCeil(result);
preferredWidth = max(snappedResult, preferredWidth);
}
@@ -7035,7 +7111,7 @@ LayoutUnit RenderBlock::collapsedMarginAfterForChild(const RenderBox* child) co
return marginAfterForChild(child);
}
-RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
+RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child) const
{
LayoutUnit childBeforePositive = 0;
LayoutUnit childBeforeNegative = 0;
@@ -7275,6 +7351,16 @@ RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const Rend
}
#ifndef NDEBUG
+void RenderBlock::checkPositionedObjectsNeedLayout()
+{
+ if (PositionedObjectsListHashSet* positionedObjects = this->positionedObjects()) {
+ PositionedObjectsListHashSet::const_iterator end = positionedObjects->end();
+ for (PositionedObjectsListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* currBox = *it;
+ ASSERT(!currBox->needsLayout());
+ }
+ }
+}
void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj) const
{