diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-07-11 13:45:28 +0200 |
commit | d6a599dbc9d824a462b2b206316e102bf8136446 (patch) | |
tree | ecb257a5e55b2239d74b90fdad62fccd661cf286 /Source/WebCore/rendering/RenderBlock.cpp | |
parent | 3ccc3a85f09a83557b391aae380d3bf5f81a2911 (diff) | |
download | qtwebkit-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-x | Source/WebCore/rendering/RenderBlock.cpp | 154 |
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 { |