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.cpp1402
1 files changed, 876 insertions, 526 deletions
diff --git a/WebCore/rendering/RenderBlock.cpp b/WebCore/rendering/RenderBlock.cpp
index 1e378d8..d951277 100644
--- a/WebCore/rendering/RenderBlock.cpp
+++ b/WebCore/rendering/RenderBlock.cpp
@@ -94,7 +94,7 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int beforeBorderPadding,
// we're positioned, floating, a table cell.
m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isPositioned()
&& !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
- && !block->isBlockFlowRoot();
+ && !block->isWritingModeRoot();
m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && (beforeBorderPadding == 0) && block->style()->marginBeforeCollapse() != MSEPARATE;
@@ -108,8 +108,8 @@ RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, int beforeBorderPadding,
m_quirkContainer = block->isTableCell() || block->isBody() || block->style()->marginBeforeCollapse() == MDISCARD ||
block->style()->marginAfterCollapse() == MDISCARD;
- m_posMargin = m_canCollapseMarginBeforeWithChildren ? block->maxMarginBefore(RenderBox::PositiveMargin) : 0;
- m_negMargin = m_canCollapseMarginBeforeWithChildren ? block->maxMarginBefore(RenderBox::NegativeMargin) : 0;
+ m_positiveMargin = m_canCollapseMarginBeforeWithChildren ? block->maxPositiveMarginBefore() : 0;
+ m_negativeMargin = m_canCollapseMarginBeforeWithChildren ? block->maxNegativeMarginBefore() : 0;
}
// -------------------------------------------------------------------------------------------------------
@@ -1023,24 +1023,25 @@ bool RenderBlock::isSelfCollapsingBlock() const
// (c) have border/padding,
// (d) have a min-height
// (e) have specified that one of our margins can't collapse using a CSS extension
- if (height() > 0
- || isTable() || borderAndPaddingHeight()
- || style()->minHeight().isPositive()
+ if (logicalHeight() > 0
+ || isTable() || borderAndPaddingLogicalHeight()
+ || style()->logicalMinHeight().isPositive()
|| style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
return false;
- bool hasAutoHeight = style()->height().isAuto();
- if (style()->height().isPercent() && !document()->inQuirksMode()) {
+ Length logicalHeightLength = style()->logicalHeight();
+ bool hasAutoHeight = logicalHeightLength.isAuto();
+ if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
hasAutoHeight = true;
for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
- if (cb->style()->height().isFixed() || cb->isTableCell())
+ if (cb->style()->logicalHeight().isFixed() || cb->isTableCell())
hasAutoHeight = false;
}
}
// If the height is 0 or auto, then whether or not we are a self-collapsing block depends
// on whether we have content that is all self-collapsing or not.
- if (hasAutoHeight || ((style()->height().isFixed() || style()->height().isPercent()) && style()->height().isZero())) {
+ if (hasAutoHeight || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.isZero())) {
// If the block has inline children, see if we generated any line boxes. If we have any
// line boxes, then we can't be self-collapsing, since we have content.
if (childrenInline())
@@ -1125,7 +1126,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
LayoutRepainter repainter(*this, m_everHadLayout && checkForRepaintDuringLayout());
- int oldWidth = width();
+ int oldWidth = logicalWidth();
int oldColumnWidth = desiredColumnWidth();
computeLogicalWidth();
@@ -1145,6 +1146,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
int previousHeight = logicalHeight();
setLogicalHeight(0);
bool hasSpecifiedPageHeight = false;
+ bool pageHeightChanged = false;
ColumnInfo* colInfo = columnInfo();
if (hasColumns()) {
if (!pageHeight) {
@@ -1160,14 +1162,14 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
}
if (colInfo->columnHeight() != pageHeight && m_everHadLayout) {
colInfo->setColumnHeight(pageHeight);
- markDescendantBlocksAndLinesForLayout(); // We need to dirty all descendant blocks and lines, since the column height is different now.
+ pageHeightChanged = true;
}
if (!hasSpecifiedPageHeight && !pageHeight)
colInfo->clearForcedBreaks();
}
- LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, colInfo);
+ LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, pageHeightChanged, colInfo);
// We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
// our current maximal positive and negative margins. These values are used when we
@@ -1204,20 +1206,20 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
layer()->setHasVerticalScrollbar(true);
}
- int repaintTop = 0;
- int repaintBottom = 0;
- int maxFloatBottom = 0;
+ int repaintLogicalTop = 0;
+ int repaintLogicalBottom = 0;
+ int maxFloatLogicalBottom = 0;
if (!firstChild() && !isAnonymousBlock())
setChildrenInline(true);
if (childrenInline())
- layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
+ layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
else
- layoutBlockChildren(relayoutChildren, maxFloatBottom);
+ layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
// Expand our intrinsic height to encompass floats.
- int toAdd = borderAfter() + paddingAfter() + horizontalScrollbarHeight(); // FIXME: https://bugs.webkit.org/show_bug.cgi?id=46645, overflow and block-flow.
- if (floatBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
- setLogicalHeight(floatBottom() + toAdd);
+ int toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+ if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
+ setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
if (layoutColumns(hasSpecifiedPageHeight, pageHeight, statePusher))
return;
@@ -1227,13 +1229,13 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
computeLogicalHeight();
int newHeight = logicalHeight();
if (oldHeight != newHeight) {
- if (oldHeight > newHeight && maxFloatBottom > newHeight && !childrenInline()) {
+ if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !childrenInline()) {
// One of our children's floats may have become an overhanging float for us. We need to look for it.
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
RenderBlock* block = toRenderBlock(child);
- if (block->floatBottom() + block->logicalTop() > newHeight)
- addOverhangingFloats(block, -block->x(), -block->y(), false);
+ if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
+ addOverhangingFloats(block, -block->logicalLeft(), -block->logicalTop(), false);
}
}
}
@@ -1273,10 +1275,15 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
// 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())) {
- int repaintLeft = min(leftVisualOverflow(), leftLayoutOverflow());
- int repaintRight = max(rightVisualOverflow(), rightLayoutOverflow());
- IntRect repaintRect(repaintLeft, repaintTop, repaintRight - repaintLeft, repaintBottom - repaintTop);
+ if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
+ int repaintLogicalLeft = min(logicalLeftVisualOverflow(), logicalLeftLayoutOverflow());
+ int repaintLogicalRight = max(logicalRightVisualOverflow(), logicalRightLayoutOverflow());
+
+ IntRect repaintRect;
+ if (style()->isHorizontalWritingMode())
+ repaintRect = IntRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
+ else
+ repaintRect = IntRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
// The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
adjustRectForColumns(repaintRect);
@@ -1318,7 +1325,7 @@ void RenderBlock::addOverflowFromFloats()
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()));
+ addOverflowFromChild(r->m_renderer, IntSize(r->left() + r->m_renderer->marginLeft(), r->top() + r->m_renderer->marginTop()));
}
return;
}
@@ -1326,13 +1333,13 @@ void RenderBlock::addOverflowFromFloats()
bool RenderBlock::expandsToEncloseOverhangingFloats() const
{
return isInlineBlockOrInlineTable() || isFloatingOrPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBox())
- || hasColumns() || isTableCell() || isFieldset() || isBlockFlowRoot();
+ || hasColumns() || isTableCell() || isFieldset() || isWritingModeRoot();
}
void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
{
if (child->style()->hasStaticX()) {
- if (style()->direction() == LTR)
+ if (style()->isLeftToRightDirection())
child->layer()->setStaticX(borderLeft() + paddingLeft());
else
child->layer()->setStaticX(borderRight() + paddingRight());
@@ -1343,8 +1350,8 @@ void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marg
if (!marginInfo.canCollapseWithMarginBefore()) {
child->computeBlockDirectionMargins(this);
int marginTop = child->marginTop();
- int collapsedTopPos = marginInfo.posMargin();
- int collapsedTopNeg = marginInfo.negMargin();
+ int collapsedTopPos = marginInfo.positiveMargin();
+ int collapsedTopNeg = marginInfo.negativeMargin();
if (marginTop > 0) {
if (marginTop > collapsedTopPos)
collapsedTopPos = marginTop;
@@ -1378,9 +1385,9 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
// http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
// an example of this scenario.
int marginOffset = marginInfo.canCollapseWithMarginBefore() ? 0 : marginInfo.margin();
- setLogicalHeight(height() + marginOffset);
+ setLogicalHeight(logicalHeight() + marginOffset);
positionNewFloats();
- setLogicalHeight(height() - marginOffset);
+ setLogicalHeight(logicalHeight() - marginOffset);
}
bool RenderBlock::handleSpecialChild(RenderBox* child, const MarginInfo& marginInfo)
@@ -1474,15 +1481,18 @@ bool RenderBlock::handleRunInChild(RenderBox* child)
int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
{
+ // Get the four margin values for the child and cache them.
+ const MarginValues childMargins = marginValuesForChild(child);
+
// Get our max pos and neg top margins.
- int posTop = child->maxMarginBefore(PositiveMargin);
- int negTop = child->maxMarginBefore(NegativeMargin);
+ int posTop = childMargins.positiveMarginBefore();
+ int negTop = childMargins.negativeMarginBefore();
// For self-collapsing blocks, collapse our bottom margins into our
// top to get new posTop and negTop values.
if (child->isSelfCollapsingBlock()) {
- posTop = max(posTop, child->maxMarginAfter(PositiveMargin));
- negTop = max(negTop, child->maxMarginAfter(NegativeMargin));
+ posTop = max(posTop, childMargins.positiveMarginAfter());
+ negTop = max(negTop, childMargins.negativeMarginAfter());
}
// See if the top margin is quirky. We only care if this child has
@@ -1494,18 +1504,18 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
// block. If it has larger margin values, then we need to update
// our own maximal values.
if (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
- setMaxMarginBeforeValues(max(posTop, maxPosMarginBefore()), max(negTop, maxNegMarginBefore()));
+ setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
// The minute any of the margins involved isn't a quirk, don't
// collapse it away, even if the margin is smaller (www.webreference.com
// has an example of this, a <dt> with 0.8em author-specified inside
// a <dl> inside a <td>.
- if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop-negTop)) {
+ if (!marginInfo.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
setMarginBeforeQuirk(false);
marginInfo.setDeterminedMarginBeforeQuirk(true);
}
- if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && marginTop() == 0)
+ if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
// We have no top margin and our top child has a quirky margin.
// We will pick up this quirky margin and pass it through.
// This deals with the <td><div><p> case.
@@ -1517,44 +1527,44 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
marginInfo.setMarginBeforeQuirk(topQuirk);
- int beforeCollapseY = height();
- int ypos = beforeCollapseY;
+ int beforeCollapseLogicalTop = logicalHeight();
+ int logicalTop = beforeCollapseLogicalTop;
if (child->isSelfCollapsingBlock()) {
// This child has no height. We need to compute our
// position before we collapse the child's margins together,
// so that we can get an accurate position for the zero-height block.
- int collapsedTopPos = max(marginInfo.posMargin(), child->maxMarginBefore(PositiveMargin));
- int collapsedTopNeg = max(marginInfo.negMargin(), child->maxMarginBefore(NegativeMargin));
- marginInfo.setMargin(collapsedTopPos, collapsedTopNeg);
+ int collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
+ int collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
+ marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
// Now collapse the child's margins together, which means examining our
// bottom margin values as well.
- marginInfo.setPosMarginIfLarger(child->maxMarginAfter(PositiveMargin));
- marginInfo.setNegMarginIfLarger(child->maxMarginAfter(NegativeMargin));
+ marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
+ marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
if (!marginInfo.canCollapseWithMarginBefore())
// We need to make sure that the position of the self-collapsing block
// is correct, since it could have overflowing content
// that needs to be positioned correctly (e.g., a block that
// had a specified height of 0 but that actually had subcontent).
- ypos = height() + collapsedTopPos - collapsedTopNeg;
+ logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
}
else {
if (child->style()->marginBeforeCollapse() == MSEPARATE) {
- setLogicalHeight(height() + marginInfo.margin() + child->marginTop());
- ypos = height();
+ setLogicalHeight(logicalHeight() + marginInfo.margin() + marginBeforeForChild(child));
+ logicalTop = logicalHeight();
}
else if (!marginInfo.atBeforeSideOfBlock() ||
(!marginInfo.canCollapseMarginBeforeWithChildren()
&& (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginBeforeQuirk()))) {
// We're collapsing with a previous sibling's margins and not
// with the top of the block.
- setLogicalHeight(height() + max(marginInfo.posMargin(), posTop) - max(marginInfo.negMargin(), negTop));
- ypos = height();
+ setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
+ logicalTop = logicalHeight();
}
- marginInfo.setPosMargin(child->maxMarginAfter(PositiveMargin));
- marginInfo.setNegMargin(child->maxMarginAfter(NegativeMargin));
+ marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
+ marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
if (marginInfo.margin())
marginInfo.setMarginAfterQuirk(child->isMarginAfterQuirk() || style()->marginAfterCollapse() == MDISCARD);
@@ -1563,12 +1573,12 @@ int RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
// If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
// collapsed into the page edge.
bool paginated = view()->layoutState()->isPaginated();
- if (paginated && ypos > beforeCollapseY) {
- int oldY = ypos;
- ypos = min(ypos, nextPageTop(beforeCollapseY));
- setLogicalHeight(height() + (ypos - oldY));
+ if (paginated && logicalTop > beforeCollapseLogicalTop) {
+ int oldLogicalTop = logicalTop;
+ logicalTop = min(logicalTop, nextPageTop(beforeCollapseLogicalTop));
+ setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
}
- return ypos;
+ return logicalTop;
}
int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin, int yPos)
@@ -1590,12 +1600,14 @@ int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, i
if (!curr->isFloatingOrPositioned())
atBottomOfBlock = false;
}
+
+ MarginValues childMargins = marginValuesForChild(child);
if (atBottomOfBlock) {
- marginInfo.setPosMargin(child->maxMarginAfter(PositiveMargin));
- marginInfo.setNegMargin(child->maxMarginAfter(NegativeMargin));
+ marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
+ marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
} else {
- marginInfo.setPosMargin(max(child->maxMarginBefore(PositiveMargin), child->maxMarginAfter(PositiveMargin)));
- marginInfo.setNegMargin(max(child->maxMarginBefore(NegativeMargin), child->maxMarginAfter(NegativeMargin)));
+ marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
+ marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
}
// Adjust our height such that we are ready to be collapsed with subsequent siblings (or the bottom
@@ -1618,89 +1630,68 @@ int RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, i
return yPos + heightIncrease;
}
-int RenderBlock::estimateVerticalPosition(RenderBox* child, const MarginInfo& marginInfo)
+int RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo)
{
// 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.
- int yPosEstimate = height();
+ int logicalTopEstimate = logicalHeight();
if (!marginInfo.canCollapseWithMarginBefore()) {
- int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginBefore();
- yPosEstimate += max(marginInfo.margin(), childMarginTop);
+ int childMarginBefore = child->selfNeedsLayout() ? marginBeforeForChild(child) : collapsedMarginBeforeForChild(child);
+ logicalTopEstimate += max(marginInfo.margin(), childMarginBefore);
}
bool paginated = view()->layoutState()->isPaginated();
- // Adjust yPosEstimate down to the next page if the margins are so large that we don't fit on the current
+ // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
// page.
- if (paginated && yPosEstimate > height())
- yPosEstimate = min(yPosEstimate, nextPageTop(height()));
+ if (paginated && logicalTopEstimate > logicalHeight())
+ logicalTopEstimate = min(logicalTopEstimate, nextPageTop(logicalHeight()));
- yPosEstimate += getClearDelta(child, yPosEstimate);
+ logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
if (paginated) {
// If the object has a page or column break value of "before", then we should shift to the top of the next page.
- yPosEstimate = applyBeforeBreak(child, yPosEstimate);
+ logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
// For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
- yPosEstimate = adjustForUnsplittableChild(child, yPosEstimate);
+ logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
if (!child->selfNeedsLayout() && child->isRenderBlock())
- yPosEstimate += toRenderBlock(child)->paginationStrut();
+ logicalTopEstimate += toRenderBlock(child)->paginationStrut();
}
- return yPosEstimate;
+ return logicalTopEstimate;
}
-void RenderBlock::determineHorizontalPosition(RenderBox* child)
+void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child)
{
- int xPos = borderLeft() + paddingLeft();
- if (style()->direction() == LTR) {
- // Add in our left margin.
- int chPos = xPos + child->marginLeft();
+ int startPosition = borderStart() + paddingStart();
+ int totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
+
+ // Add in our start margin.
+ int childMarginStart = marginStartForChild(child);
+ int newPosition = startPosition + childMarginStart;
- // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
- // to shift over as necessary to dodge any floats that might get in the way.
- if (child->avoidsFloats()) {
- int leftOff = logicalLeftOffsetForLine(height(), false);
- if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginLeft().type() != Auto) {
- if (child->marginLeft() < 0)
- leftOff += child->marginLeft();
- chPos = max(chPos, leftOff); // Let the float sit in the child's margin if it can fit.
- }
- else if (leftOff != xPos) {
- // The object is shifting right. The object might be centered, so we need to
- // recalculate our horizontal margins. Note that the containing block content
- // width computation will take into account the delta between |leftOff| and |xPos|
- // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection|
- // function.
- child->computeInlineDirectionMargins(this, availableLogicalWidthForLine(child->y(), false), child->width());
- chPos = leftOff + child->marginLeft();
- }
- }
- view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
- child->setLocation(chPos, child->y());
- } else {
- xPos += availableLogicalWidth();
- int chPos = xPos - (child->width() + child->marginRight());
- if (child->avoidsFloats()) {
- int rightOff = logicalRightOffsetForLine(height(), false);
- if (style()->textAlign() != WEBKIT_CENTER && child->style()->marginRight().type() != Auto) {
- if (child->marginRight() < 0)
- rightOff -= child->marginRight();
- chPos = min(chPos, rightOff - child->width()); // Let the float sit in the child's margin if it can fit.
- } else if (rightOff != xPos) {
- // The object is shifting left. The object might be centered, so we need to
- // recalculate our horizontal margins. Note that the containing block content
- // width computation will take into account the delta between |rightOff| and |xPos|
- // so that we can just pass the content width in directly to the |computeInlineDirectionMargins|
- // function.
- child->computeInlineDirectionMargins(this, availableLogicalWidthForLine(child->y(), false), child->width());
- chPos = rightOff - child->marginRight() - child->width();
- }
+ // Some objects (e.g., tables, horizontal rules, overflow:auto blocks) avoid floats. They need
+ // to shift over as necessary to dodge any floats that might get in the way.
+ if (child->avoidsFloats()) {
+ int startOff = style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(logicalHeight(), false) : totalAvailableLogicalWidth - logicalRightOffsetForLine(logicalHeight(), false);
+ if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
+ if (childMarginStart < 0)
+ startOff += childMarginStart;
+ newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
+ } else if (startOff != startPosition) {
+ // The object is shifting to the "end" side of the block. The object might be centered, so we need to
+ // recalculate our inline direction margins. Note that the containing block content
+ // width computation will take into account the delta between |startOff| and |startPosition|
+ // so that we can just pass the content width in directly to the |computeMarginsInContainingBlockInlineDirection|
+ // function.
+ child->computeInlineDirectionMargins(this, availableLogicalWidthForLine(logicalTopForChild(child), false), logicalWidthForChild(child));
+ newPosition = startOff + marginStartForChild(child);
}
- view()->addLayoutDelta(IntSize(child->x() - chPos, 0));
- child->setLocation(chPos, child->y());
}
+
+ setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), ApplyLayoutDelta);
}
void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
@@ -1708,12 +1699,12 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
// Update our max pos/neg bottom margins, since we collapsed our bottom margins
// with our children.
- setMaxMarginAfterValues(max(maxPosMarginAfter(), marginInfo.posMargin()), max(maxNegMarginAfter(), marginInfo.negMargin()));
+ setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
if (!marginInfo.marginAfterQuirk())
setMarginAfterQuirk(false);
- if (marginInfo.marginAfterQuirk() && marginBottom() == 0)
+ if (marginInfo.marginAfterQuirk() && marginAfter() == 0)
// We have no bottom margin and our last child has a quirky margin.
// We will pick up this quirky margin and pass it through.
// This deals with the <td><div><p> case.
@@ -1721,27 +1712,53 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
}
}
-void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
+void RenderBlock::handleAfterSideOfBlock(int beforeSide, int afterSide, MarginInfo& marginInfo)
{
marginInfo.setAtAfterSideOfBlock(true);
// If we can't collapse with children then go ahead and add in the bottom margin.
if (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
&& (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.marginAfterQuirk()))
- setLogicalHeight(height() + marginInfo.margin());
+ setLogicalHeight(logicalHeight() + marginInfo.margin());
// Now add in our bottom border/padding.
- setLogicalHeight(height() + bottom);
+ setLogicalHeight(logicalHeight() + afterSide);
// Negative margins can cause our height to shrink below our minimal height (border/padding).
// If this happens, ensure that the computed height is increased to the minimal height.
- setLogicalHeight(max(height(), top + bottom));
+ setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
// Update our bottom collapsed margin info.
setCollapsedBottomMargin(marginInfo);
}
-void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom)
+void RenderBlock::setLogicalLeftForChild(RenderBox* child, int logicalLeft, ApplyLayoutDeltaMode applyDelta)
+{
+ if (style()->isHorizontalWritingMode()) {
+ if (applyDelta == ApplyLayoutDelta)
+ view()->addLayoutDelta(IntSize(child->x() - logicalLeft, 0));
+ child->setX(logicalLeft);
+ } else {
+ if (applyDelta == ApplyLayoutDelta)
+ view()->addLayoutDelta(IntSize(0, child->y() - logicalLeft));
+ child->setY(logicalLeft);
+ }
+}
+
+void RenderBlock::setLogicalTopForChild(RenderBox* child, int logicalTop, ApplyLayoutDeltaMode applyDelta)
+{
+ if (style()->isHorizontalWritingMode()) {
+ if (applyDelta == ApplyLayoutDelta)
+ view()->addLayoutDelta(IntSize(0, child->y() - logicalTop));
+ child->setY(logicalTop);
+ } else {
+ if (applyDelta == ApplyLayoutDelta)
+ view()->addLayoutDelta(IntSize(child->x() - logicalTop, 0));
+ child->setX(logicalTop);
+ }
+}
+
+void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatLogicalBottom)
{
if (gPercentHeightDescendantsMap) {
if (HashSet<RenderBox*>* descendants = gPercentHeightDescendantsMap->get(this)) {
@@ -1761,20 +1778,22 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
}
}
- int top = borderTop() + paddingTop();
- int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+ int beforeEdge = borderBefore() + paddingBefore();
+ int afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
- setLogicalHeight(top);
+ setLogicalHeight(beforeEdge);
// The margin struct caches all our current margin collapsing state. The compact struct caches state when we encounter compacts,
- MarginInfo marginInfo(this, top, bottom);
+ MarginInfo marginInfo(this, beforeEdge, afterEdge);
// Fieldsets need to find their legend and position it inside the border of the object.
// The legend then gets skipped during normal layout.
+ // FIXME: Make fieldsets work with block-flow.
+ // https://bugs.webkit.org/show_bug.cgi?id=46785
RenderObject* legend = layoutLegend(relayoutChildren);
- int previousFloatBottom = 0;
- maxFloatBottom = 0;
+ int previousFloatLogicalBottom = 0;
+ maxFloatLogicalBottom = 0;
RenderBox* next = firstChildBox();
@@ -1788,11 +1807,11 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
// 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.
- if (relayoutChildren || ((child->style()->height().isPercent() || child->style()->minHeight().isPercent() || child->style()->maxHeight().isPercent()) && !isRenderView()))
+ if (relayoutChildren || ((child->style()->logicalHeight().isPercent() || child->style()->logicalMinHeight().isPercent() || child->style()->logicalMaxHeight().isPercent()) && !isRenderView()))
child->setChildNeedsLayout(true, false);
- // If relayoutChildren is set and we have percentage padding, we also need to invalidate the child's pref widths.
- if (relayoutChildren && (child->style()->paddingLeft().isPercent() || child->style()->paddingRight().isPercent()))
+ // If relayoutChildren is set and the child has percentage padding, we also need to invalidate the child's pref widths.
+ if (relayoutChildren && (child->style()->paddingStart().isPercent() || child->style()->paddingEnd().isPercent()))
child->setPreferredLogicalWidthsDirty(true, false);
// Handle the four types of special elements first. These include positioned content, floating content, compacts and
@@ -1801,63 +1820,64 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom
continue;
// Lay out the child.
- layoutBlockChild(child, marginInfo, previousFloatBottom, maxFloatBottom);
+ layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
}
// 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);
+ handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
}
-void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatBottom, int& maxFloatBottom)
+void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int& previousFloatLogicalBottom, int& maxFloatLogicalBottom)
{
- int oldTopPosMargin = maxPosMarginBefore();
- int oldTopNegMargin = maxNegMarginBefore();
+ int oldPosMarginBefore = maxPositiveMarginBefore();
+ int oldNegMarginBefore = maxNegativeMarginBefore();
- // The child is a normal flow object. Compute its vertical margins now.
+ // The child is a normal flow object. Compute the margins we will use for collapsing now.
child->computeBlockDirectionMargins(this);
- // Do not allow a collapse if the margin top collapse style is set to SEPARATE.
+ // Do not allow a collapse if the margin-before-collapse style is set to SEPARATE.
if (child->style()->marginBeforeCollapse() == MSEPARATE) {
marginInfo.setAtBeforeSideOfBlock(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)
+ // Try to guess our correct logical top position. In most cases this guess will
+ // be correct. Only if we're wrong (when we compute the real logical top position)
// will we have to potentially relayout.
- int yPosEstimate = estimateVerticalPosition(child, marginInfo);
+ int logicalTopEstimate = estimateLogicalTopPosition(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());
+ int oldLogicalTop = logicalTopForChild(child);
+
#ifndef NDEBUG
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);
+ setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
bool markDescendantsWithFloats = false;
- if (yPosEstimate != oldRect.y() && !child->avoidsFloats() && childRenderBlock && childRenderBlock->containsFloats())
+ if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->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)
+ int fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
+ if (fb > logicalTopEstimate)
markDescendantsWithFloats = true;
}
if (childRenderBlock) {
if (markDescendantsWithFloats)
childRenderBlock->markAllDescendantsWithFloatsForLayout();
- previousFloatBottom = max(previousFloatBottom, oldRect.y() + toRenderBlock(child)->floatBottom());
+ if (!child->isWritingModeRoot())
+ previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
}
- bool paginated = view()->layoutState()->isPaginated();
- if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight && childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
- childRenderBlock->markForPaginationRelayout();
+ if (!child->needsLayout())
+ child->markForPaginationRelayoutIfNeeded();
bool childHadLayout = child->m_everHadLayout;
bool childNeededLayout = child->needsLayout();
@@ -1869,23 +1889,24 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
// Now determine the correct ypos based off examination of collapsing margin
// values.
- int yBeforeClear = collapseMargins(child, marginInfo);
+ int logicalTopBeforeClear = collapseMargins(child, marginInfo);
// Now check for clear.
- int yAfterClear = clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin, yBeforeClear);
+ int logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
+ bool paginated = view()->layoutState()->isPaginated();
if (paginated) {
- int oldY = yAfterClear;
+ int oldTop = logicalTopAfterClear;
// If the object has a page or column break value of "before", then we should shift to the top of the next page.
- yAfterClear = applyBeforeBreak(child, yAfterClear);
+ logicalTopAfterClear = applyBeforeBreak(child, logicalTopAfterClear);
// For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
- int yBeforeUnsplittableAdjustment = yAfterClear;
- int yAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, yAfterClear);
+ int logicalTopBeforeUnsplittableAdjustment = logicalTopAfterClear;
+ int logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, logicalTopAfterClear);
int paginationStrut = 0;
- int unsplittableAdjustmentDelta = yAfterUnsplittableAdjustment - yBeforeUnsplittableAdjustment;
+ int unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment;
if (unsplittableAdjustmentDelta)
paginationStrut = unsplittableAdjustmentDelta;
else if (childRenderBlock && childRenderBlock->paginationStrut())
@@ -1894,26 +1915,25 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
if (paginationStrut) {
// We are willing to propagate out to our parent block as long as we were at the top of the block prior
// to collapsing our margins, and as long as we didn't clear or move as a result of other pagination.
- if (atBeforeSideOfBlock && oldY == yBeforeClear && !isPositioned() && !isTableCell()) {
+ if (atBeforeSideOfBlock && oldTop == logicalTopBeforeClear && !isPositioned() && !isTableCell()) {
// FIXME: Should really check if we're exceeding the page height before propagating the strut, but we don't
// have all the information to do so (the strut only has the remaining amount to push). Gecko gets this wrong too
// and pushes to the next page anyway, so not too concerned about it.
- setPaginationStrut(yAfterClear + paginationStrut);
+ setPaginationStrut(logicalTopAfterClear + paginationStrut);
if (childRenderBlock)
childRenderBlock->setPaginationStrut(0);
} else
- yAfterClear += paginationStrut;
+ logicalTopAfterClear += paginationStrut;
}
// Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child.
- setLogicalHeight(height() + (yAfterClear - oldY));
+ setLogicalHeight(logicalHeight() + (logicalTopAfterClear - oldTop));
}
- view()->addLayoutDelta(IntSize(0, yPosEstimate - yAfterClear));
- child->setLocation(child->x(), yAfterClear);
+ setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
- // Now we have a final y position. See if it really does end up being different from our estimate.
- if (yAfterClear != yPosEstimate) {
+ // Now we have a final top position. See if it really does end up being different from our estimate.
+ if (logicalTopAfterClear != logicalTopEstimate) {
if (child->shrinkToAvoidFloats()) {
// The child's width depends on the line width.
// When the child shifts to clear an item, its width can
@@ -1924,8 +1944,8 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
if (childRenderBlock) {
if (!child->avoidsFloats() && childRenderBlock->containsFloats())
childRenderBlock->markAllDescendantsWithFloatsForLayout();
- if (paginated && !child->needsLayout() && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
- childRenderBlock->markForPaginationRelayout();
+ if (!child->needsLayout())
+ child->markForPaginationRelayoutIfNeeded();
}
// Our guess was wrong. Make the child lay itself out again.
@@ -1937,19 +1957,19 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
if (marginInfo.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
marginInfo.setAtBeforeSideOfBlock(false);
- // Now place the child in the correct horizontal position
- determineHorizontalPosition(child);
+ // Now place the child in the correct left position
+ determineLogicalLeftPositionForChild(child);
// Update our height now that the child has been placed in the correct position.
- setLogicalHeight(height() + child->height());
+ setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
if (child->style()->marginAfterCollapse() == MSEPARATE) {
- setLogicalHeight(height() + child->marginBottom());
+ setLogicalHeight(logicalHeight() + marginAfterForChild(child));
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 (childRenderBlock && childRenderBlock->containsFloats())
- maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(toRenderBlock(child), -child->x(), -child->y(), !childNeededLayout));
+ maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), -child->logicalLeft(), -child->logicalTop(), !childNeededLayout));
IntSize childOffset(child->x() - oldRect.x(), child->y() - oldRect.y());
if (childOffset.width() || childOffset.height()) {
@@ -2014,8 +2034,6 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
if (hasColumns())
view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
- bool paginated = view()->layoutState()->isPaginated();
-
RenderBox* r;
Iterator end = m_positionedObjects->end();
for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
@@ -2031,11 +2049,8 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
//if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
r->setPreferredLogicalWidthsDirty(true, false);
- if (!r->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
- RenderBlock* childRenderBlock = r->isRenderBlock() ? toRenderBlock(r) : 0;
- if (childRenderBlock && view()->layoutState()->pageY(childRenderBlock->y()) != childRenderBlock->pageY())
- childRenderBlock->markForPaginationRelayout();
- }
+ if (!r->needsLayout())
+ r->markForPaginationRelayoutIfNeeded();
// 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.
@@ -2061,6 +2076,16 @@ void RenderBlock::markPositionedObjectsForLayout()
}
}
+void RenderBlock::markForPaginationRelayoutIfNeeded()
+{
+ ASSERT(!needsLayout());
+ if (needsLayout())
+ return;
+
+ if (view()->layoutState()->pageHeightChanged() || (view()->layoutState()->pageHeight() && view()->layoutState()->pageY(y()) != pageY()))
+ setChildNeedsLayout(true, false);
+}
+
void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
{
// Repaint any overhanging floats (if we know we're the one to paint them).
@@ -2081,7 +2106,7 @@ void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
// Only repaint the object if it is overhanging, is not in its own layer, and
// is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
// condition is replaced with being a descendant of us.
- if (r->m_bottom > height() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
+ if (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {
r->m_renderer->repaint();
r->m_renderer->repaintOverhangingFloats();
}
@@ -2134,14 +2159,14 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
// We need to do multiple passes, breaking up our child painting into strips.
ColumnInfo* colInfo = columnInfo();
unsigned colCount = columnCount(colInfo);
- int currXOffset = style()->direction() == LTR ? 0 : contentWidth();
+ int currXOffset = style()->isLeftToRightDirection() ? 0 : contentWidth();
int ruleAdd = borderLeft() + paddingLeft();
- int ruleX = style()->direction() == LTR ? 0 : contentWidth();
+ int ruleX = style()->isLeftToRightDirection() ? 0 : contentWidth();
for (unsigned i = 0; i < colCount; i++) {
IntRect colRect = columnRectAt(colInfo, i);
// Move to the next position.
- if (style()->direction() == LTR) {
+ if (style()->isLeftToRightDirection()) {
ruleX += colRect.width() + colGap / 2;
currXOffset += colRect.width() + colGap;
} else {
@@ -2156,7 +2181,7 @@ void RenderBlock::paintColumnRules(PaintInfo& paintInfo, int tx, int ty)
int ruleTop = ty + borderTop() + paddingTop();
int ruleBottom = ruleTop + contentHeight();
drawLineForBoxSide(paintInfo.context, ruleStart, ruleTop, ruleEnd, ruleBottom,
- style()->direction() == LTR ? BSLeft : BSRight, ruleColor, ruleStyle, 0, 0);
+ style()->isLeftToRightDirection() ? BSLeft : BSRight, ruleColor, ruleStyle, 0, 0);
}
ruleX = currXOffset;
@@ -2172,7 +2197,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool
unsigned colCount = columnCount(colInfo);
if (!colCount)
return;
- int currXOffset = style()->direction() == LTR ? 0 : contentWidth() - columnRectAt(colInfo, 0).width();
+ int currXOffset = style()->isLeftToRightDirection() ? 0 : contentWidth() - columnRectAt(colInfo, 0).width();
int currYOffset = 0;
for (unsigned i = 0; i < colCount; i++) {
// For each rect, we clip to the rect, and then we adjust our coords.
@@ -2200,7 +2225,7 @@ void RenderBlock::paintColumnContents(PaintInfo& paintInfo, int tx, int ty, bool
}
// Move to the next position.
- if (style()->direction() == LTR)
+ if (style()->isLeftToRightDirection())
currXOffset += colRect.width() + colGap;
else
currXOffset -= (colRect.width() + colGap);
@@ -2393,8 +2418,8 @@ void RenderBlock::paintFloats(PaintInfo& paintInfo, int tx, int ty, bool preserv
if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
PaintInfo currentPaintInfo(paintInfo);
currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
- int currentTX = tx + r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
- int currentTY = ty + r->m_top - r->m_renderer->y() + r->m_renderer->marginTop();
+ int currentTX = tx + r->left() - r->m_renderer->x() + r->m_renderer->marginLeft();
+ int currentTY = ty + r->top() - r->m_renderer->y() + r->m_renderer->marginTop();
r->m_renderer->paint(currentPaintInfo, currentTX, currentTY);
if (!preservePhase) {
currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
@@ -2603,8 +2628,8 @@ GapRects RenderBlock::fillSelectionGaps(RenderBlock* rootBlock, int blockX, int
if (m_floatingObjects) {
for (DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects); it.current(); ++it) {
FloatingObject* r = it.current();
- paintInfo->context->clipOut(IntRect(tx + r->m_left + r->m_renderer->marginLeft(),
- ty + r->m_top + r->m_renderer->marginTop(),
+ paintInfo->context->clipOut(IntRect(tx + r->left() + r->m_renderer->marginLeft(),
+ ty + r->top() + r->m_renderer->marginTop(),
r->m_renderer->width(), r->m_renderer->height()));
}
}
@@ -2815,7 +2840,7 @@ IntRect RenderBlock::fillRightSelectionGap(RenderObject* selObj, int xPos, int y
void RenderBlock::getHorizontalSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
{
- bool ltr = style()->direction() == LTR;
+ bool ltr = style()->isLeftToRightDirection();
leftGap = (state == RenderObject::SelectionInside) ||
(state == RenderObject::SelectionEnd && ltr) ||
(state == RenderObject::SelectionStart && !ltr);
@@ -2933,20 +2958,21 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
// Create the special object entry & append it to the list
FloatingObject* newObj = new FloatingObject(o->style()->floating() == FLEFT ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
-
- newObj->m_top = -1;
- newObj->m_bottom = -1;
// Our location is irrelevant if we're unsplittable or no pagination is in effect.
// Just go ahead and lay out the float.
- bool affectedByPagination = o->isRenderBlock() && view()->layoutState()->m_pageHeight;
- if (!affectedByPagination)
+ bool isChildRenderBlock = o->isRenderBlock();
+ if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageHeightChanged())
+ o->setChildNeedsLayout(true, false);
+
+ bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageHeight;
+ if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
o->layoutIfNeeded();
else {
o->computeLogicalWidth();
o->computeBlockDirectionMargins(this);
}
- newObj->m_width = o->width() + o->marginLeft() + o->marginRight();
+ setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself. Otherwise someone else will.
newObj->m_isDescendant = true;
@@ -2964,12 +2990,14 @@ void RenderBlock::removeFloatingObject(RenderBox* o)
while (it.current()) {
if (it.current()->m_renderer == o) {
if (childrenInline()) {
- int bottom = it.current()->m_bottom;
+ int logicalTop = logicalTopForFloat(it.current());
+ int logicalBottom = logicalBottomForFloat(it.current());
+
// Special-case zero- and less-than-zero-height floats: those don't touch
// the line that they're on, but it still needs to be dirtied. This is
// accomplished by pretending they have a height of 1.
- bottom = max(bottom, it.current()->m_top + 1);
- markLinesDirtyInVerticalRange(0, bottom);
+ logicalBottom = max(logicalBottom, logicalTop + 1);
+ markLinesDirtyInBlockRange(0, logicalBottom);
}
m_floatingObjects->removeRef(it.current());
}
@@ -2984,7 +3012,7 @@ void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int y)
return;
FloatingObject* curr = m_floatingObjects->last();
- while (curr != lastFloat && (curr->m_top == -1 || curr->m_top >= y)) {
+ while (curr != lastFloat && (!curr->isPlaced() || curr->top() >= y)) {
m_floatingObjects->removeLast();
curr = m_floatingObjects->last();
}
@@ -2995,111 +3023,118 @@ bool RenderBlock::positionNewFloats()
if (!m_floatingObjects)
return false;
- FloatingObject* f = m_floatingObjects->last();
+ FloatingObject* floatingObject = m_floatingObjects->last();
// If all floats have already been positioned, then we have no work to do.
- if (!f || f->m_top != -1)
+ if (!floatingObject || floatingObject->isPlaced())
return false;
// Move backwards through our floating object list until we find a float that has
// already been positioned. Then we'll be able to move forward, positioning all of
// the new floats that need it.
FloatingObject* lastFloat = m_floatingObjects->getPrev();
- while (lastFloat && lastFloat->m_top == -1) {
- f = m_floatingObjects->prev();
+ while (lastFloat && !lastFloat->isPlaced()) {
+ floatingObject = m_floatingObjects->prev();
lastFloat = m_floatingObjects->getPrev();
}
- int y = height();
+ int logicalTop = logicalHeight();
- // The float cannot start above the y position of the last positioned float.
+ // The float cannot start above the top position of the last positioned float.
if (lastFloat)
- y = max(lastFloat->m_top, y);
+ logicalTop = max(logicalTopForFloat(lastFloat), logicalTop);
// Now walk through the set of unpositioned floats and place them.
- while (f) {
+ while (floatingObject) {
// 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 (f->m_renderer->containingBlock() != this) {
- f = m_floatingObjects->next();
+ if (floatingObject->renderer()->containingBlock() != this) {
+ floatingObject = m_floatingObjects->next();
continue;
}
- RenderBox* o = f->m_renderer;
+ RenderBox* childBox = floatingObject->renderer();
+ int childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
- int ro = logicalRightOffsetForContent(); // Constant part of right offset.
- int lo = logicalLeftOffsetForContent(); // Constant part of left offset.
- int fwidth = f->m_width; // The width we look for.
- if (ro - lo < fwidth)
- fwidth = ro - lo; // Never look for more than what will be available.
+ int rightOffset = logicalRightOffsetForContent(); // Constant part of right offset.
+ int leftOffset = logicalLeftOffsetForContent(); // Constant part of left offset.
+ int floatLogicalWidth = logicalWidthForFloat(floatingObject); // The width we look for.
+ if (rightOffset - leftOffset < floatLogicalWidth)
+ floatLogicalWidth = rightOffset - leftOffset; // Never look for more than what will be available.
- IntRect oldRect(o->x(), o->y() , o->width(), o->height());
+ IntRect oldRect(childBox->x(), childBox->y() , childBox->width(), childBox->height());
- if (o->style()->clear() & CLEFT)
- y = max(leftBottom(), y);
- if (o->style()->clear() & CRIGHT)
- y = max(rightBottom(), y);
+ if (childBox->style()->clear() & CLEFT)
+ logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
+ if (childBox->style()->clear() & CRIGHT)
+ logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
- if (o->style()->floating() == FLEFT) {
+ int floatLogicalLeft;
+ if (childBox->style()->floating() == FLEFT) {
int heightRemainingLeft = 1;
int heightRemainingRight = 1;
- int fx = logicalLeftOffsetForLine(y, lo, false, &heightRemainingLeft);
- while (logicalRightOffsetForLine(y, ro, false, &heightRemainingRight)-fx < fwidth) {
- y += min(heightRemainingLeft, heightRemainingRight);
- fx = logicalLeftOffsetForLine(y, lo, false, &heightRemainingLeft);
+ floatLogicalLeft = logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft);
+ while (logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
+ logicalTop += min(heightRemainingLeft, heightRemainingRight);
+ floatLogicalLeft = logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft);
}
- fx = max(0, fx);
- f->m_left = fx;
- o->setLocation(fx + o->marginLeft(), y + o->marginTop());
+ floatLogicalLeft = max(0, floatLogicalLeft);
} else {
int heightRemainingLeft = 1;
int heightRemainingRight = 1;
- int fx = logicalRightOffsetForLine(y, ro, false, &heightRemainingRight);
- while (fx - logicalLeftOffsetForLine(y, lo, false, &heightRemainingLeft) < fwidth) {
- y += min(heightRemainingLeft, heightRemainingRight);
- fx = logicalRightOffsetForLine(y, ro, false, &heightRemainingRight);
+ floatLogicalLeft = logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight);
+ while (floatLogicalLeft - logicalLeftOffsetForLine(logicalTop, leftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
+ logicalTop += min(heightRemainingLeft, heightRemainingRight);
+ floatLogicalLeft = logicalRightOffsetForLine(logicalTop, rightOffset, false, &heightRemainingRight);
}
- f->m_left = fx - f->m_width;
- o->setLocation(fx - o->marginRight() - o->width(), y + o->marginTop());
+ floatLogicalLeft -= logicalWidthForFloat(floatingObject); // Use the original width of the float here, since the local variable
+ // |floatLogicalWidth| was capped to the available line width.
+ // See fast/block/float/clamped-right-float.html.
}
+
+ setLogicalLeftForFloat(floatingObject, floatLogicalLeft);
+ setLogicalLeftForChild(childBox, floatLogicalLeft + childLogicalLeftMargin);
+ setLogicalTopForChild(childBox, logicalTop + marginBeforeForChild(childBox));
if (view()->layoutState()->isPaginated()) {
- RenderBlock* childBlock = o->isRenderBlock() ? toRenderBlock(o) : 0;
+ RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
- if (childBlock && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(o->y()) != childBlock->pageY())
- childBlock->markForPaginationRelayout();
- o->layoutIfNeeded();
+ if (!childBox->needsLayout())
+ childBox->markForPaginationRelayoutIfNeeded();;
+ childBox->layoutIfNeeded();
// If we are unsplittable and don't fit, then we need to move down.
// We include our margins as part of the unsplittable area.
- int newY = adjustForUnsplittableChild(o, y, true);
+ int newLogicalTop = adjustForUnsplittableChild(childBox, logicalTop, true);
// See if we have a pagination strut that is making us move down further.
// Note that an unsplittable child can't also have a pagination strut, so this is
// exclusive with the case above.
if (childBlock && childBlock->paginationStrut()) {
- newY += childBlock->paginationStrut();
+ newLogicalTop += childBlock->paginationStrut();
childBlock->setPaginationStrut(0);
}
- if (newY != y) {
- f->m_paginationStrut = newY - y;
- y = newY;
- o->setY(y + o->marginTop());
+ if (newLogicalTop != logicalTop) {
+ floatingObject->m_paginationStrut = newLogicalTop - logicalTop;
+ logicalTop = newLogicalTop;
+ setLogicalTopForChild(childBox, logicalTop + marginBeforeForChild(childBox));
if (childBlock)
childBlock->setChildNeedsLayout(true, false);
- o->layoutIfNeeded();
+ childBox->layoutIfNeeded();
}
}
- f->m_top = y;
- f->m_bottom = f->m_top + o->marginTop() + o->height() + o->marginBottom();
-
+ setLogicalTopForFloat(floatingObject, logicalTop);
+ setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
+
+ floatingObject->setIsPlaced();
+
// If the child moved, we have to repaint it.
- if (o->checkForRepaintDuringLayout())
- o->repaintDuringLayoutIfMoved(oldRect);
+ if (childBox->checkForRepaintDuringLayout())
+ childBox->repaintDuringLayoutIfMoved(oldRect);
- f = m_floatingObjects->next();
+ floatingObject = m_floatingObjects->next();
}
return true;
}
@@ -3110,30 +3145,29 @@ bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObjec
if (!didPosition || !newFloat->m_paginationStrut)
return didPosition;
- int floatTop = newFloat->m_top;
+ int floatLogicalTop = logicalTopForFloat(newFloat);
int paginationStrut = newFloat->m_paginationStrut;
FloatingObject* f = m_floatingObjects->last();
ASSERT(f == newFloat);
- if (floatTop - paginationStrut != height())
+ if (floatLogicalTop - paginationStrut != logicalHeight())
return didPosition;
for (f = m_floatingObjects->prev(); f && f != lastFloatFromPreviousLine; f = m_floatingObjects->prev()) {
- if (f->m_top == height()) {
+ if (logicalTopForFloat(f) == logicalHeight()) {
ASSERT(!f->m_paginationStrut);
f->m_paginationStrut = paginationStrut;
RenderBox* o = f->m_renderer;
- o->setY(o->y() + o->marginTop() + paginationStrut);
+ setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
if (o->isRenderBlock())
toRenderBlock(o)->setChildNeedsLayout(true, false);
o->layoutIfNeeded();
- f->m_top += f->m_paginationStrut;
- f->m_bottom += f->m_paginationStrut;
+ setLogicalTopForFloat(f, logicalTopForFloat(f) + f->m_paginationStrut);
}
}
- setLogicalHeight(height() + paginationStrut);
+ setLogicalHeight(logicalHeight() + paginationStrut);
return didPosition;
}
@@ -3146,13 +3180,13 @@ void RenderBlock::newLine(EClear clear)
switch (clear)
{
case CLEFT:
- newY = leftBottom();
+ newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
break;
case CRIGHT:
- newY = rightBottom();
+ newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
break;
case CBOTH:
- newY = floatBottom();
+ newY = lowestFloatLogicalBottom();
default:
break;
}
@@ -3220,30 +3254,26 @@ HashSet<RenderBox*>* RenderBlock::percentHeightDescendants() const
return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
}
-int RenderBlock::logicalLeftOffsetForContent() const
-{
- return borderLeft() + paddingLeft();
-}
-
-int RenderBlock::logicalLeftOffsetForLine(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
+int RenderBlock::logicalLeftOffsetForLine(int logicalTop, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
{
int left = fixedOffset;
if (m_floatingObjects) {
- if ( heightRemaining ) *heightRemaining = 1;
+ if (heightRemaining)
+ *heightRemaining = 1;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- {
- if (r->m_top <= y && r->m_bottom > y &&
- r->type() == FloatingObject::FloatLeft &&
- r->m_left + r->m_width > left) {
- left = r->m_left + r->m_width;
- if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
+ for ( ; (r = it.current()); ++it) {
+ if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop
+ && r->type() == FloatingObject::FloatLeft
+ && logicalRightForFloat(r) > left) {
+ left = logicalRightForFloat(r);
+ if (heightRemaining)
+ *heightRemaining = logicalBottomForFloat(r) - logicalTop;
}
}
}
- if (applyTextIndent && style()->direction() == LTR) {
+ if (applyTextIndent && style()->isLeftToRightDirection()) {
int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableLogicalWidth();
@@ -3253,31 +3283,27 @@ int RenderBlock::logicalLeftOffsetForLine(int y, int fixedOffset, bool applyText
return left;
}
-int RenderBlock::logicalRightOffsetForContent() const
-{
- return borderLeft() + paddingLeft() + availableLogicalWidth();
-}
-
-int RenderBlock::logicalRightOffsetForLine(int y, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
+int RenderBlock::logicalRightOffsetForLine(int logicalTop, int fixedOffset, bool applyTextIndent, int* heightRemaining) const
{
int right = fixedOffset;
if (m_floatingObjects) {
- if (heightRemaining) *heightRemaining = 1;
+ if (heightRemaining)
+ *heightRemaining = 1;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- {
- if (r->m_top <= y && r->m_bottom > y &&
- r->type() == FloatingObject::FloatRight &&
- r->m_left < right) {
- right = r->m_left;
- if ( heightRemaining ) *heightRemaining = r->m_bottom - y;
+ for ( ; (r = it.current()); ++it) {
+ if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop
+ && r->type() == FloatingObject::FloatRight
+ && logicalLeftForFloat(r) < right) {
+ right = logicalLeftForFloat(r);
+ if (heightRemaining)
+ *heightRemaining = logicalBottomForFloat(r) - logicalTop;
}
}
}
- if (applyTextIndent && style()->direction() == RTL) {
+ if (applyTextIndent && !style()->isLeftToRightDirection()) {
int cw = 0;
if (style()->textIndent().isPercent())
cw = containingBlock()->availableLogicalWidth();
@@ -3294,7 +3320,7 @@ RenderBlock::availableLogicalWidthForLine(int position, bool firstLine) const
return (result < 0) ? 0 : result;
}
-int RenderBlock::nextFloatBottomBelow(int height) const
+int RenderBlock::nextFloatLogicalBottomBelow(int logicalHeight) const
{
if (!m_floatingObjects)
return 0;
@@ -3303,36 +3329,130 @@ int RenderBlock::nextFloatBottomBelow(int height) const
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it) {
- if (r->m_bottom > height)
- bottom = min(r->m_bottom, bottom);
+ int floatBottom = logicalBottomForFloat(r);
+ if (floatBottom > logicalHeight)
+ bottom = min(floatBottom, bottom);
}
return bottom == INT_MAX ? 0 : bottom;
}
-int
-RenderBlock::floatBottom() const
+int RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
{
- if (!m_floatingObjects) return 0;
- int bottom = 0;
+ if (!m_floatingObjects)
+ return 0;
+ int lowestFloatBottom = 0;
FloatingObject* r;
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->m_bottom>bottom)
- bottom = r->m_bottom;
- return bottom;
+ for ( ; (r = it.current()); ++it) {
+ if (r->isPlaced() && r->type() & floatType)
+ lowestFloatBottom = max(lowestFloatBottom, logicalBottomForFloat(r));
+ }
+ return lowestFloatBottom;
}
-int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
+int RenderBlock::topmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const
{
- int bottom = includeSelf && width() > 0 ? height() : 0;
-
+ IntRect transformedRect = transformedFrameRect();
+ int transformedTop = includeSelf && transformedRect.width() > 0 ? 0 : transformedRect.height();
+
if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return bottom;
+ return transformedTop;
- if (!firstChild() && (!width() || !height()))
- return bottom;
+ if (!firstChild() && (!transformedRect.width() || !transformedRect.height()))
+ return transformedTop;
+
+ int top = includeSelf && width() > 0 ? 0 : height();
+
+ 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
+ // a tiny rel div buried somewhere deep in our child tree. In this case we have to get to
+ // the abs div.
+ for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
+ if (!c->isFloatingOrPositioned() && c->isBox()) {
+ RenderBox* childBox = toRenderBox(c);
+ top = min(top, childBox->transformedFrameRect().y() + childBox->topmostPosition(false));
+ }
+ }
+ }
+
+ if (includeSelf && isRelPositioned())
+ top += relativePositionOffsetY();
+
+ if (!includeOverflowInterior && hasOverflowClip())
+ return top;
+ int relativeOffset = includeSelf && isRelPositioned() ? relativePositionOffsetY() : 0;
+
+ if (includeSelf)
+ top = min(top, topLayoutOverflow() + relativeOffset);
+
+ if (m_positionedObjects) {
+ RenderBox* r;
+ Iterator end = m_positionedObjects->end();
+ for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
+ r = *it;
+ // Fixed positioned objects do not scroll and thus should not constitute
+ // part of the topmost position.
+ if (r->style()->position() != FixedPosition) {
+ // FIXME: Should work for overflow sections too.
+ // If a positioned object lies completely to the left of the root it will be unreachable via scrolling.
+ // Therefore we should not allow it to contribute to the topmost position.
+ IntRect transformedR = r->transformedFrameRect();
+ if (!isRenderView() || transformedR.x() + transformedR.width() > 0 || transformedR.x() + r->rightmostPosition(false) > 0) {
+ int tp = transformedR.y() + r->topmostPosition(false);
+ top = min(top, tp + relativeOffset);
+ }
+ }
+ }
+ }
+
+ if (hasColumns()) {
+ ColumnInfo* colInfo = columnInfo();
+ for (unsigned i = 0; i < columnCount(colInfo); i++)
+ top = min(top, columnRectAt(colInfo, i).y() + relativeOffset);
+ return top;
+ }
+
+ if (m_floatingObjects) {
+ FloatingObject* r;
+ DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
+ for ( ; (r = it.current()); ++it) {
+ if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
+ int tp = r->top() + r->m_renderer->marginTop() + r->m_renderer->topmostPosition(false);
+ top = min(top, tp + relativeOffset);
+ }
+ }
+ }
+
+ if (!includeSelf && firstRootBox())
+ top = min(top, firstRootBox()->selectionTop() + relativeOffset);
+
+ if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) {
+ int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top));
+ return transformRect.y();
+ }
+
+ return top;
+}
+
+int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const
+{
+ IntRect transformedRect = transformedFrameRect();
+ int transformedBottom = includeSelf && transformedRect.width() > 0 ? transformedRect.height() : 0;
+
+ if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
+ return transformedBottom;
+
+ if (!firstChild() && (!transformedRect.width() || !transformedRect.height()))
+ return transformedBottom;
+
+ 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
@@ -3343,7 +3463,7 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
if (!c->isFloatingOrPositioned() && c->isBox()) {
RenderBox* childBox = toRenderBox(c);
- bottom = max(bottom, childBox->y() + childBox->lowestPosition(false));
+ bottom = max(bottom, childBox->transformedFrameRect().y() + childBox->lowestPosition(false));
}
}
}
@@ -3369,8 +3489,9 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely to the left of the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the lowest position.
- if (!isRenderView() || r->x() + r->width() > 0 || r->x() + r->rightmostPosition(false) > 0) {
- int lp = r->y() + r->lowestPosition(false);
+ IntRect transformedR = r->transformedFrameRect();
+ if (!isRenderView() || transformedR.x() + transformedR.width() > 0 || transformedR.x() + r->rightmostPosition(false) > 0) {
+ int lp = transformedR.y() + r->lowestPosition(false);
bottom = max(bottom, lp + relativeOffset);
}
}
@@ -3389,7 +3510,7 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
- int lp = r->m_top + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
+ int lp = r->top() + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
bottom = max(bottom, lp + relativeOffset);
}
}
@@ -3408,24 +3529,36 @@ int RenderBlock::lowestPosition(bool includeOverflowInterior, bool includeSelf)
while (currBox && currBox->isFloatingOrPositioned())
currBox = currBox->previousSiblingBox();
if (currBox) {
- int childBottomEdge = currBox->y() + currBox->height() + currBox->collapsedMarginAfter(); // FIXME: "after" is wrong here for lowestPosition.
+ IntRect transformedCurrBox = currBox->transformedFrameRect();
+ int childBottomEdge = transformedCurrBox.y() + transformedCurrBox.height() + currBox->collapsedMarginAfter(); // FIXME: "after" is wrong here for lowestPosition.
bottom = max(bottom, childBottomEdge + paddingBottom() + relativeOffset);
}
}
}
-
+
+ if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) {
+ int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top));
+ return transformRect.height();
+ }
+
return bottom;
}
-int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
+int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const
{
- int right = includeSelf && height() > 0 ? width() : 0;
+ IntRect transformedRect = transformedFrameRect();
+ int transformedRight = includeSelf && transformedRect.height() > 0 ? transformedRect.width() : 0;
if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return right;
+ return transformedRight;
- if (!firstChild() && (!width() || !height()))
- return right;
+ if (!firstChild() && (!transformedRect.width() || !transformedRect.height()))
+ return transformedRight;
+
+ int right = includeSelf && height() > 0 ? width() : 0;
if (!hasColumns()) {
// FIXME: Come up with a way to use the layer tree to avoid visiting all the kids.
@@ -3435,7 +3568,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
if (!c->isFloatingOrPositioned() && c->isBox()) {
RenderBox* childBox = toRenderBox(c);
- right = max(right, childBox->x() + childBox->rightmostPosition(false));
+ right = max(right, childBox->transformedFrameRect().x() + childBox->rightmostPosition(false));
}
}
}
@@ -3462,8 +3595,9 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely above the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the rightmost position.
- if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
- int rp = r->x() + r->rightmostPosition(false);
+ IntRect transformedR = r->transformedFrameRect();
+ if (!isRenderView() || transformedR.y() + transformedR.height() > 0 || transformedR.y() + r->lowestPosition(false) > 0) {
+ int rp = transformedR.x() + r->rightmostPosition(false);
right = max(right, rp + relativeOffset);
}
}
@@ -3472,12 +3606,19 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
if (hasColumns()) {
// This only matters for LTR
- if (style()->direction() == LTR) {
+ if (style()->isLeftToRightDirection()) {
ColumnInfo* colInfo = columnInfo();
unsigned count = columnCount(colInfo);
if (count)
right = max(columnRectAt(colInfo, count - 1).right() + relativeOffset, right);
}
+ if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) {
+ int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top));
+ return transformRect.width();
+ }
return right;
}
@@ -3486,7 +3627,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
- int rp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
+ int rp = r->left() + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
right = max(right, rp + relativeOffset);
}
}
@@ -3500,7 +3641,7 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
// If this node is a root editable element, then the rightmostPosition should account for a caret at the end.
// FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
- if (node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->direction() == LTR && !paddingRight())
+ if (node() && node()->isContentEditable() && node() == node()->rootEditableElement() && style()->isLeftToRightDirection() && !paddingRight())
childRightEdge += 1;
right = max(right, childRightEdge + paddingRight() + relativeOffset);
}
@@ -3509,24 +3650,36 @@ int RenderBlock::rightmostPosition(bool includeOverflowInterior, bool includeSel
for (RenderBox* currBox = firstChildBox(); currBox; currBox = currBox->nextSiblingBox()) {
if (currBox->isFloatingOrPositioned())
continue;
- int childRightEdge = currBox->x() + currBox->width() + currBox->marginRight();
+ IntRect transformedChild = currBox->transformedFrameRect();
+ int childRightEdge = transformedChild.x() + transformedChild.width() + currBox->marginRight();
right = max(right, childRightEdge + paddingRight() + relativeOffset);
}
}
}
+
+ if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) {
+ int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int left = leftmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top));
+ return transformRect.width();
+ }
return right;
}
-int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
+int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf, ApplyTransform applyTransform) const
{
- int left = includeSelf && height() > 0 ? 0 : width();
+ IntRect transformedRect = transformedFrameRect();
+ int transformedLeft = includeSelf && transformedRect.height() > 0 ? 0 : transformedRect.width();
if (!includeOverflowInterior && (hasOverflowClip() || hasControlClip()))
- return left;
+ return transformedLeft;
- if (!firstChild() && (!width() || !height()))
- return left;
+ if (!firstChild() && (!transformedRect.width() || !transformedRect.height()))
+ return transformedLeft;
+
+ 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.
@@ -3536,7 +3689,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
for (RenderObject* c = firstChild(); c; c = c->nextSibling()) {
if (!c->isFloatingOrPositioned() && c->isBox()) {
RenderBox* childBox = toRenderBox(c);
- left = min(left, childBox->x() + childBox->leftmostPosition(false));
+ left = min(left, childBox->transformedFrameRect().x() + childBox->leftmostPosition(false));
}
}
}
@@ -3563,8 +3716,9 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
// FIXME: Should work for overflow sections too.
// If a positioned object lies completely above the root it will be unreachable via scrolling.
// Therefore we should not allow it to contribute to the leftmost position.
- if (!isRenderView() || r->y() + r->height() > 0 || r->y() + r->lowestPosition(false) > 0) {
- int lp = r->x() + r->leftmostPosition(false);
+ IntRect transformedR = r->transformedFrameRect();
+ if (!isRenderView() || transformedR.y() + transformedR.height() > 0 || transformedR.y() + r->lowestPosition(false) > 0) {
+ int lp = transformedR.x() + r->leftmostPosition(false);
left = min(left, lp + relativeOffset);
}
}
@@ -3573,7 +3727,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
if (hasColumns()) {
// This only matters for RTL
- if (style()->direction() == RTL) {
+ if (!style()->isLeftToRightDirection()) {
ColumnInfo* colInfo = columnInfo();
unsigned count = columnCount(colInfo);
if (count)
@@ -3587,7 +3741,7 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for ( ; (r = it.current()); ++it ) {
if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
- int lp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
+ int lp = r->left() + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
left = min(left, lp + relativeOffset);
}
}
@@ -3597,51 +3751,31 @@ int RenderBlock::leftmostPosition(bool includeOverflowInterior, bool includeSelf
for (InlineFlowBox* currBox = firstLineBox(); currBox; currBox = currBox->nextLineBox())
left = min(left, (int)currBox->x() + relativeOffset);
}
+
+ if (applyTransform == IncludeTransform && includeSelf && layer() && layer()->hasTransform()) {
+ int top = topmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int bottom = lowestPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ int right = rightmostPosition(includeOverflowInterior, includeSelf, ExcludeTransform);
+ IntRect transformRect = applyLayerTransformToRect(IntRect(left, top, right - left, bottom - top));
+ return transformRect.x();
+ }
return left;
}
-int
-RenderBlock::leftBottom()
-{
- if (!m_floatingObjects) return 0;
- int bottom = 0;
- FloatingObject* r;
- DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->m_bottom > bottom && r->type() == FloatingObject::FloatLeft)
- bottom = r->m_bottom;
-
- return bottom;
-}
-
-int
-RenderBlock::rightBottom()
-{
- if (!m_floatingObjects) return 0;
- int bottom = 0;
- FloatingObject* r;
- DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- for ( ; (r = it.current()); ++it )
- if (r->m_bottom>bottom && r->type() == FloatingObject::FloatRight)
- bottom = r->m_bottom;
-
- return bottom;
-}
-
-void RenderBlock::markLinesDirtyInVerticalRange(int top, int bottom, RootInlineBox* highest)
+void RenderBlock::markLinesDirtyInBlockRange(int logicalTop, int logicalBottom, RootInlineBox* highest)
{
- if (top >= bottom)
+ if (logicalTop >= logicalBottom)
return;
RootInlineBox* lowestDirtyLine = lastRootBox();
RootInlineBox* afterLowest = lowestDirtyLine;
- while (lowestDirtyLine && lowestDirtyLine->blockHeight() >= bottom) {
+ while (lowestDirtyLine && lowestDirtyLine->blockLogicalHeight() >= logicalBottom) {
afterLowest = lowestDirtyLine;
lowestDirtyLine = lowestDirtyLine->prevRootBox();
}
- while (afterLowest && afterLowest != highest && afterLowest->blockHeight() >= top) {
+ while (afterLowest && afterLowest != highest && afterLowest->blockLogicalHeight() >= logicalTop) {
afterLowest->markDirty();
afterLowest = afterLowest->prevRootBox();
}
@@ -3678,6 +3812,7 @@ void RenderBlock::clearFloats()
// 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());
RenderObject* prev = previousSibling();
while (prev && (prev->isFloatingOrPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
if (prev->isFloating())
@@ -3686,18 +3821,16 @@ void RenderBlock::clearFloats()
}
// First add in floats from the parent.
- int offset = y();
- if (parentHasFloats) {
- RenderBlock* parentBlock = toRenderBlock(parent());
- addIntrudingFloats(parentBlock, parentBlock->borderLeft() + parentBlock->paddingLeft(), offset);
- }
+ int logicalTopOffset = logicalTop();
+ if (parentHasFloats)
+ addIntrudingFloats(parentBlock, parentBlock->logicalLeftOffsetForContent(), logicalTopOffset);
- int xoffset = 0;
+ int logicalLeftOffset = 0;
if (prev)
- offset -= toRenderBox(prev)->y();
- else if (parent()->isBox()) {
- prev = parent();
- xoffset += toRenderBox(prev)->borderLeft() + toRenderBox(prev)->paddingLeft();
+ logicalTopOffset -= toRenderBox(prev)->logicalTop();
+ else {
+ prev = parentBlock;
+ logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
}
// Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
@@ -3705,29 +3838,31 @@ void RenderBlock::clearFloats()
return;
RenderBlock* block = toRenderBlock(prev);
- if (block->m_floatingObjects && block->floatBottom() > offset)
- addIntrudingFloats(block, xoffset, offset);
+ if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
+ addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
if (childrenInline()) {
- int changeTop = numeric_limits<int>::max();
- int changeBottom = numeric_limits<int>::min();
+ int changeLogicalTop = numeric_limits<int>::max();
+ int changeLogicalBottom = numeric_limits<int>::min();
if (m_floatingObjects) {
for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
+ int logicalBottom = logicalBottomForFloat(f);
if (oldFloatingObject) {
- if (f->m_width != oldFloatingObject->m_width || f->m_left != oldFloatingObject->m_left) {
- changeTop = 0;
- changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
- } else if (f->m_bottom != oldFloatingObject->m_bottom) {
- changeTop = min(changeTop, min(f->m_bottom, oldFloatingObject->m_bottom));
- changeBottom = max(changeBottom, max(f->m_bottom, oldFloatingObject->m_bottom));
+ int oldLogicalBottom = logicalBottomForFloat(oldFloatingObject);
+ if (logicalWidthForFloat(f) != logicalWidthForFloat(oldFloatingObject) || logicalLeftForFloat(f) != logicalLeftForFloat(oldFloatingObject)) {
+ changeLogicalTop = 0;
+ changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
+ } else if (logicalBottom != oldLogicalBottom) {
+ changeLogicalTop = min(changeLogicalTop, min(logicalBottom, oldLogicalBottom));
+ changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
}
floatMap.remove(f->m_renderer);
delete oldFloatingObject;
} else {
- changeTop = 0;
- changeBottom = max(changeBottom, f->m_bottom);
+ changeLogicalTop = 0;
+ changeLogicalBottom = max(changeLogicalBottom, logicalBottom);
}
}
}
@@ -3736,39 +3871,37 @@ void RenderBlock::clearFloats()
for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
FloatingObject* floatingObject = (*it).second;
if (!floatingObject->m_isDescendant) {
- changeTop = 0;
- changeBottom = max(changeBottom, floatingObject->m_bottom);
+ changeLogicalTop = 0;
+ changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
}
}
deleteAllValues(floatMap);
- markLinesDirtyInVerticalRange(changeTop, changeBottom);
+ markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
}
}
-int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bool makeChildPaintOtherFloats)
+int RenderBlock::addOverhangingFloats(RenderBlock* child, int logicalLeftOffset, int logicalTopOffset, bool makeChildPaintOtherFloats)
{
// Prevent floats from being added to the canvas by the root element, e.g., <html>.
- if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isBlockFlowRoot())
+ if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
return 0;
- int lowestFloatBottom = 0;
+ int lowestFloatLogicalBottom = 0;
// 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;
- lowestFloatBottom = max(lowestFloatBottom, bottom);
+ int logicalBottom = child->logicalTop() + logicalBottomForFloat(r);
+ lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
- if (bottom > height()) {
+ if (logicalBottom > logicalHeight()) {
// If the object is not in the list, we add it now.
if (!containsFloat(r->m_renderer)) {
- FloatingObject *floatingObj = new FloatingObject(r->type());
- floatingObj->m_top = r->m_top - yoff;
- floatingObj->m_bottom = r->m_bottom - yoff;
- floatingObj->m_left = r->m_left - xoff;
- floatingObj->m_width = r->m_width;
+ int leftOffset = style()->isHorizontalWritingMode() ? logicalLeftOffset : logicalTopOffset;
+ int topOffset = style()->isHorizontalWritingMode() ? logicalTopOffset : logicalLeftOffset;
+ FloatingObject* floatingObj = new FloatingObject(r->type(), IntRect(r->left() - leftOffset, r->top() - topOffset, r->width(), r->height()));
floatingObj->m_renderer = r->m_renderer;
// The nearest enclosing layer always paints the float (so that zindex and stacking
@@ -3797,45 +3930,48 @@ int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff, bo
r->m_shouldPaint = true;
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->addOverflowFromChild(r->m_renderer, IntSize(r->left() + r->m_renderer->marginLeft(), r->top() + r->m_renderer->marginTop()));
}
- return lowestFloatBottom;
+ return lowestFloatLogicalBottom;
}
-void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
+void RenderBlock::addIntrudingFloats(RenderBlock* prev, int logicalLeftOffset, int logicalTopOffset)
{
// If the parent or previous sibling doesn't have any floats to add, don't bother.
if (!prev->m_floatingObjects)
return;
+ logicalLeftOffset += (style()->isHorizontalWritingMode() ? marginLeft() : marginTop());
+
DeprecatedPtrListIterator<FloatingObject> it(*prev->m_floatingObjects);
for (FloatingObject *r; (r = it.current()); ++it) {
- if (r->m_bottom > yoff) {
+ if (logicalBottomForFloat(r) > logicalTopOffset) {
// The object may already be in our list. Check for it up front to avoid
// creating duplicate entries.
FloatingObject* f = 0;
if (m_floatingObjects) {
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
while ((f = it.current())) {
- if (f->m_renderer == r->m_renderer) break;
+ if (f->m_renderer == r->m_renderer)
+ break;
++it;
}
}
if (!f) {
- FloatingObject *floatingObj = new FloatingObject(r->type());
- floatingObj->m_top = r->m_top - yoff;
- floatingObj->m_bottom = r->m_bottom - yoff;
- floatingObj->m_left = r->m_left - xoff;
+ int leftOffset = style()->isHorizontalWritingMode() ? logicalLeftOffset : logicalTopOffset;
+ int topOffset = style()->isHorizontalWritingMode() ? logicalTopOffset : logicalLeftOffset;
+
+ FloatingObject* floatingObj = new FloatingObject(r->type(), IntRect(r->left() - leftOffset, r->top() - topOffset, r->width(), r->height()));
+
// Applying the child's margin makes no sense in the case where the child was passed in.
- // since his own margin was added already through the subtraction of the |xoff| variable
- // above. |xoff| will equal -flow->marginLeft() in this case, so it's already been taken
- // into account. Only apply this code if |child| is false, since otherwise the left margin
+ // since this margin was added already through the modification of the |logicalLeftOffset| variable
+ // above. |logicalLeftOffset| will equal the margin in this case, so it's already been taken
+ // into account. Only apply this code if prev is the parent, since otherwise the left margin
// will get applied twice.
if (prev != parent())
- floatingObj->m_left += prev->marginLeft();
- floatingObj->m_left -= marginLeft();
+ floatingObj->setLeft(floatingObj->left() + (style()->isHorizontalWritingMode() ? prev->marginLeft() : prev->marginTop()));
+
floatingObj->m_shouldPaint = false; // We are not in the direct inheritance chain for this float. We will never paint it.
- floatingObj->m_width = r->m_width;
floatingObj->m_renderer = r->m_renderer;
// We create the floating object list lazily.
@@ -3890,41 +4026,6 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove
}
}
-void RenderBlock::markDescendantBlocksAndLinesForLayout(bool inLayout)
-{
- if (!m_everHadLayout)
- return;
-
- setChildNeedsLayout(true, !inLayout);
-
- // Iterate over our children and mark them as needed.
- if (!childrenInline()) {
- for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
- if (child->isFloatingOrPositioned())
- continue;
- child->markDescendantBlocksAndLinesForLayout(inLayout);
- }
- }
-
- // Walk our floating objects and mark them too.
- if (m_floatingObjects) {
- DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
- while (it.current()) {
- if (it.current()->m_renderer->isRenderBlock())
- it.current()->m_renderer->markDescendantBlocksAndLinesForLayout(inLayout);
- ++it;
- }
- }
-
- if (m_positionedObjects) {
- // FIXME: Technically we don't have to mark the positioned objects if we're the block
- // that established the columns, but we don't really have that information here.
- Iterator end = m_positionedObjects->end();
- for (Iterator it = m_positionedObjects->begin(); it != end; ++it)
- (*it)->markDescendantBlocksAndLinesForLayout();
- }
-}
-
int RenderBlock::getClearDelta(RenderBox* child, int yPos)
{
// There is no need to compute clearance if we have no floats.
@@ -3938,13 +4039,13 @@ int RenderBlock::getClearDelta(RenderBox* child, int yPos)
case CNONE:
break;
case CLEFT:
- bottom = leftBottom();
+ bottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
break;
case CRIGHT:
- bottom = rightBottom();
+ bottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
break;
case CBOTH:
- bottom = floatBottom();
+ bottom = lowestFloatLogicalBottom();
break;
}
@@ -3972,7 +4073,7 @@ int RenderBlock::getClearDelta(RenderBox* child, int yPos)
if (childWidthAtY <= widthAtY)
return y - yPos;
- y = nextFloatBottomBelow(y);
+ y = nextFloatLogicalBottomBelow(y);
ASSERT(y >= yPos);
if (y < yPos)
break;
@@ -3999,7 +4100,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Check if we need to do anything at all.
IntRect overflowBox = visibleOverflowRect();
overflowBox.move(tx, ty);
- if (!overflowBox.intersects(result.rectFromPoint(_x, _y)))
+ if (!overflowBox.intersects(result.rectForPoint(_x, _y)))
return false;
}
@@ -4013,7 +4114,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// If we have clipping, then we can't have any spillout.
bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
bool useClip = (hasControlClip() || useOverflowClip);
- IntRect hitTestArea(result.rectFromPoint(_x, _y));
+ IntRect hitTestArea(result.rectForPoint(_x, _y));
bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).intersects(hitTestArea) : overflowClipRect(tx, ty).intersects(hitTestArea));
if (checkChildren) {
// Hit test descendants first.
@@ -4042,7 +4143,7 @@ bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
// Now hit test our background
if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
IntRect boundsRect(tx, ty, width(), height());
- if (visibleToHitTesting() && boundsRect.intersects(result.rectFromPoint(_x, _y))) {
+ if (visibleToHitTesting() && boundsRect.intersects(result.rectForPoint(_x, _y))) {
updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
if (!result.addNodeToRectBasedTestResult(node(), _x, _y, boundsRect))
return true;
@@ -4066,8 +4167,8 @@ bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& re
DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
for (it.toLast(); (floatingObject = it.current()); --it) {
if (floatingObject->m_shouldPaint && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
- int xOffset = tx + floatingObject->m_left + floatingObject->m_renderer->marginLeft() - floatingObject->m_renderer->x();
- int yOffset = ty + floatingObject->m_top + floatingObject->m_renderer->marginTop() - floatingObject->m_renderer->y();
+ int xOffset = tx + floatingObject->left() + floatingObject->m_renderer->marginLeft() - floatingObject->m_renderer->x();
+ int yOffset = ty + floatingObject->top() + floatingObject->m_renderer->marginTop() - floatingObject->m_renderer->y();
if (floatingObject->m_renderer->hitTest(request, result, IntPoint(x, y), xOffset, yOffset)) {
updateHitTestResult(result, IntPoint(x - xOffset, y - yOffset));
return true;
@@ -4096,13 +4197,13 @@ bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& r
currYOffset += colRect.height();
colRect.move(tx, ty);
- if (colRect.intersects(result.rectFromPoint(x, y))) {
+ if (colRect.intersects(result.rectForPoint(x, y))) {
// The point is inside this column.
// Adjust tx and ty to change where we hit test.
int finalX = tx + currXOffset;
int finalY = ty + currYOffset;
- if (result.isRectBasedTest() && !colRect.contains(result.rectFromPoint(x, y)))
+ if (result.isRectBasedTest() && !colRect.contains(result.rectForPoint(x, y)))
hitTestContents(request, result, x, y, finalX, finalY, hitTestAction);
else
return hitTestContents(request, result, x, y, finalX, finalY, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, x, y, finalX, finalY));
@@ -4443,7 +4544,7 @@ IntRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
int colHeight = colInfo->columnHeight();
int colTop = borderTop() + paddingTop();
int colGap = columnGap();
- int colLeft = style()->direction() == LTR ?
+ int colLeft = style()->isLeftToRightDirection() ?
borderLeft() + paddingLeft() + (index * (colWidth + colGap))
: borderLeft() + paddingLeft() + contentWidth() - colWidth - (index * (colWidth + colGap));
return IntRect(colLeft, colTop, colWidth, colHeight);
@@ -4485,8 +4586,8 @@ bool RenderBlock::layoutColumns(bool hasSpecifiedPageHeight, int pageHeight, Lay
if (columnCount(colInfo)) {
IntRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
- int overflowLeft = style()->direction() == RTL ? min(0, lastRect.x()) : 0;
- int overflowRight = style()->direction() == LTR ? max(width(), lastRect.x() + lastRect.width()) : 0;
+ int overflowLeft = !style()->isLeftToRightDirection() ? min(0, lastRect.x()) : 0;
+ int overflowRight = style()->isLeftToRightDirection() ? max(width(), lastRect.x() + lastRect.width()) : 0;
int overflowHeight = borderTop() + paddingTop() + colInfo->columnHeight();
setLogicalHeight(overflowHeight + borderBottom() + paddingBottom() + horizontalScrollbarHeight());
@@ -4607,8 +4708,8 @@ void RenderBlock::computePreferredLogicalWidths()
updateFirstLetter();
- if (!isTableCell() && style()->width().isFixed() && style()->width().value() > 0)
- m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->width().value());
+ if (!isTableCell() && style()->logicalWidth().isFixed() && style()->logicalWidth().value() > 0)
+ m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeContentBoxLogicalWidth(style()->logicalWidth().value());
else {
m_minPreferredLogicalWidth = 0;
m_maxPreferredLogicalWidth = 0;
@@ -4635,18 +4736,18 @@ void RenderBlock::computePreferredLogicalWidths()
}
}
- if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
- m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->minWidth().value()));
+ if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMinWidth().value()));
+ m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMinWidth().value()));
}
- if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
- m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
- m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->maxWidth().value()));
+ if (style()->logicalMaxWidth().isFixed() && style()->logicalMaxWidth().value() != undefinedLength) {
+ m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value()));
+ m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, computeContentBoxLogicalWidth(style()->logicalMaxWidth().value()));
}
int toAdd = 0;
- toAdd = borderAndPaddingWidth();
+ toAdd = borderAndPaddingLogicalWidth();
if (hasOverflowClip() && style()->overflowY() == OSCROLL)
toAdd += verticalScrollbarWidth();
@@ -4732,7 +4833,7 @@ static int getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfI
{
RenderStyle* cstyle = child->style();
int result = 0;
- bool leftSide = (cstyle->direction() == LTR) ? !endOfInline : endOfInline;
+ bool leftSide = (cstyle->isLeftToRightDirection()) ? !endOfInline : endOfInline;
result += getBPMWidth((leftSide ? child->marginLeft() : child->marginRight()),
(leftSide ? cstyle->marginLeft() :
cstyle->marginRight()));
@@ -5135,15 +5236,15 @@ bool RenderBlock::hasLineIfEmpty() const
return false;
}
-int RenderBlock::lineHeight(bool firstLine, bool isRootLineBox) const
+int RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
{
// Inline blocks are replaced elements. Otherwise, just pass off to
// the base class. If we're being queried as though we're the root line
// box, then the fact that we're an inline-block is irrelevant, and we behave
// just like a block.
- if (isReplaced() && !isRootLineBox)
- return height() + marginTop() + marginBottom();
-
+ if (isReplaced() && linePositionMode == PositionOnContainingLine)
+ return RenderBox::lineHeight(firstLine, direction, linePositionMode);
+
if (firstLine && document()->usesFirstLineRules()) {
RenderStyle* s = style(firstLine);
if (s != style())
@@ -5156,16 +5257,17 @@ int RenderBlock::lineHeight(bool firstLine, bool isRootLineBox) const
return m_lineHeight;
}
-int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
+int RenderBlock::baselinePosition(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
{
// Inline blocks are replaced elements. Otherwise, just pass off to
// the base class. If we're being queried as though we're the root line
// box, then the fact that we're an inline-block is irrelevant, and we behave
// just like a block.
- if (isReplaced() && !isRootLineBox) {
+ if (isReplaced() && linePositionMode == PositionOnContainingLine) {
// For "leaf" theme objects, let the theme decide what the baseline position is.
// FIXME: Might be better to have a custom CSS property instead, so that if the theme
// is turned off, checkboxes/radios will still have decent baselines.
+ // FIXME: Need to patch form controls to deal with vertical lines.
if (style()->hasAppearance() && !theme()->isControlContainer(style()->appearance()))
return theme()->baselinePosition(this);
@@ -5175,22 +5277,29 @@ int RenderBlock::baselinePosition(bool b, bool isRootLineBox) const
// We also give up on finding a baseline if we have a vertical scrollbar, or if we are scrolled
// vertically (e.g., an overflow:hidden block that has had scrollTop moved) or if the baseline is outside
// of our content box.
- int baselinePos = (layer() && (layer()->marquee() || layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)) ? -1 : lastLineBoxBaseline();
- if (baselinePos != -1 && baselinePos <= borderTop() + paddingTop() + contentHeight())
- return marginTop() + baselinePos;
- return height() + marginTop() + marginBottom();
+ bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
+ : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || isWritingModeRoot();
+ int baselinePos = ignoreBaseline ? -1 : lastLineBoxBaseline();
+
+ int bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
+ if (baselinePos != -1 && baselinePos <= bottomOfContent)
+ return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
+
+ return RenderBox::baselinePosition(firstLine, direction, linePositionMode);
}
- return RenderBox::baselinePosition(b, isRootLineBox);
+
+ const Font& f = style(firstLine)->font();
+ return f.ascent() + (lineHeight(firstLine, direction, linePositionMode) - f.height()) / 2;
}
int RenderBlock::firstLineBoxBaseline() const
{
- if (!isBlockFlow())
+ if (!isBlockFlow() || isWritingModeRoot())
return -1;
if (childrenInline()) {
if (firstLineBox())
- return firstLineBox()->y() + style(true)->font().ascent();
+ return firstLineBox()->logicalTop() + style(true)->font().ascent();
else
return -1;
}
@@ -5199,7 +5308,7 @@ int RenderBlock::firstLineBoxBaseline() const
if (!curr->isFloatingOrPositioned()) {
int result = curr->firstLineBoxBaseline();
if (result != -1)
- return curr->y() + result; // Translate to our coordinate space.
+ return curr->logicalTop() + result; // Translate to our coordinate space.
}
}
}
@@ -5209,28 +5318,33 @@ int RenderBlock::firstLineBoxBaseline() const
int RenderBlock::lastLineBoxBaseline() const
{
- if (!isBlockFlow())
+ if (!isBlockFlow() || isWritingModeRoot())
return -1;
+ LineDirectionMode lineDirection = style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
+
if (childrenInline()) {
- if (!firstLineBox() && hasLineIfEmpty())
- return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
+ if (!firstLineBox() && hasLineIfEmpty()) {
+ const Font& f = firstLineStyle()->font();
+ return f.ascent() + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - f.height()) / 2 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
+ }
if (lastLineBox())
- return lastLineBox()->y() + style(lastLineBox() == firstLineBox())->font().ascent();
+ return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->font().ascent();
return -1;
- }
- else {
+ } else {
bool haveNormalFlowChild = false;
for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
if (!curr->isFloatingOrPositioned()) {
haveNormalFlowChild = true;
int result = curr->lastLineBoxBaseline();
if (result != -1)
- return curr->y() + result; // Translate to our coordinate space.
+ return curr->logicalTop() + result; // Translate to our coordinate space.
}
}
- if (!haveNormalFlowChild && hasLineIfEmpty())
- return RenderBox::baselinePosition(true, true) + borderTop() + paddingTop();
+ if (!haveNormalFlowChild && hasLineIfEmpty()) {
+ const Font& f = firstLineStyle()->font();
+ return f.ascent() + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - f.height()) / 2 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
+ }
}
return -1;
@@ -5279,6 +5393,24 @@ static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderOb
return pseudoStyle;
}
+// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
+// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
+// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
+static inline bool isPunctuationForFirstLetter(UChar c)
+{
+ CharCategory charCategory = category(c);
+ return charCategory == Punctuation_Open
+ || charCategory == Punctuation_Close
+ || charCategory == Punctuation_InitialQuote
+ || charCategory == Punctuation_FinalQuote
+ || charCategory == Punctuation_Other;
+}
+
+static inline bool shouldSkipForFirstLetter(UChar c)
+{
+ return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
+}
+
void RenderBlock::updateFirstLetter()
{
if (!document()->usesFirstLetterRules())
@@ -5403,15 +5535,27 @@ void RenderBlock::updateFirstLetter()
if (oldText && oldText->length() > 0) {
unsigned length = 0;
- // account for leading spaces and punctuation
- while (length < oldText->length() && (isSpaceOrNewline((*oldText)[length]) || Unicode::isPunct((*oldText)[length])))
+ // Account for leading spaces and punctuation.
+ while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length]))
length++;
- // account for first letter
+ // Account for first letter.
length++;
+
+ // Keep looking for whitespace and allowed punctuation, but avoid
+ // accumulating just whitespace into the :first-letter.
+ for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) {
+ UChar c = (*oldText)[scanLength];
+
+ if (!shouldSkipForFirstLetter(c))
+ break;
- // construct text fragment for the text after the first letter
- // NOTE: this might empty
+ if (isPunctuationForFirstLetter(c))
+ length = scanLength + 1;
+ }
+
+ // Construct a text fragment for the text after the first letter.
+ // This text fragment might be empty.
RenderTextFragment* remainingText =
new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
remainingText->setStyle(textObj->style());
@@ -5553,7 +5697,7 @@ void RenderBlock::adjustForBorderFit(int x, int& left, int& right) const
for (; (r = it.current()); ++it) {
// Only examine the object if our m_shouldPaint flag is set.
if (r->m_shouldPaint) {
- int floatLeft = r->m_left - r->m_renderer->x() + r->m_renderer->marginLeft();
+ int floatLeft = r->left() - r->m_renderer->x() + r->m_renderer->marginLeft();
int floatRight = floatLeft + r->m_renderer->width();
left = min(left, floatLeft);
right = max(right, floatRight);
@@ -5605,23 +5749,23 @@ void RenderBlock::clearTruncation()
void RenderBlock::setMaxMarginBeforeValues(int pos, int neg)
{
if (!m_rareData) {
- if (pos == RenderBlockRareData::beforePosDefault(this) && neg == RenderBlockRareData::beforeNegDefault(this))
+ if (pos == RenderBlockRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockRareData::negativeMarginBeforeDefault(this))
return;
m_rareData = new RenderBlockRareData(this);
}
- m_rareData->m_beforePos = pos;
- m_rareData->m_beforeNeg = neg;
+ m_rareData->m_margins.setPositiveMarginBefore(pos);
+ m_rareData->m_margins.setNegativeMarginBefore(neg);
}
void RenderBlock::setMaxMarginAfterValues(int pos, int neg)
{
if (!m_rareData) {
- if (pos == RenderBlockRareData::afterPosDefault(this) && neg == RenderBlockRareData::afterNegDefault(this))
+ if (pos == RenderBlockRareData::positiveMarginAfterDefault(this) && neg == RenderBlockRareData::negativeMarginAfterDefault(this))
return;
m_rareData = new RenderBlockRareData(this);
}
- m_rareData->m_afterPos = pos;
- m_rareData->m_afterNeg = neg;
+ m_rareData->m_margins.setPositiveMarginAfter(pos);
+ m_rareData->m_margins.setNegativeMarginAfter(neg);
}
void RenderBlock::setPaginationStrut(int strut)
@@ -5745,7 +5889,7 @@ IntRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, int*
// constructed and this kludge is not called any more. So only the caret size
// of an empty :first-line'd block is wrong. I think we can live with that.
RenderStyle* currentStyle = firstLineStyle();
- int height = lineHeight(true);
+ int height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine);
enum CaretAlignment { alignLeft, alignRight, alignCenter };
@@ -5754,7 +5898,7 @@ IntRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, int*
switch (currentStyle->textAlign()) {
case TAAUTO:
case JUSTIFY:
- if (currentStyle->direction() == RTL)
+ if (!currentStyle->isLeftToRightDirection())
alignment = alignRight;
break;
case LEFT:
@@ -6020,7 +6164,213 @@ void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, int& d
}
}
}
-
+
+int RenderBlock::collapsedMarginBeforeForChild(RenderBox* child) const
+{
+ // If the child has the same directionality as we do, then we can just return its
+ // collapsed margin.
+ if (!child->isWritingModeRoot())
+ return child->collapsedMarginBefore();
+
+ // The child has a different directionality. If the child is parallel, then it's just
+ // flipped relative to us. We can use the collapsed margin for the opposite edge.
+ if (child->style()->isHorizontalWritingMode() == style()->isHorizontalWritingMode())
+ return child->collapsedMarginAfter();
+
+ // The child is perpendicular to us, which means its margins don't collapse but are on the
+ // "logical left/right" sides of the child box. We can just return the raw margin in this case.
+ return marginBeforeForChild(child);
+}
+
+int RenderBlock::collapsedMarginAfterForChild(RenderBox* child) const
+{
+ // If the child has the same directionality as we do, then we can just return its
+ // collapsed margin.
+ if (!child->isWritingModeRoot())
+ return child->collapsedMarginAfter();
+
+ // The child has a different directionality. If the child is parallel, then it's just
+ // flipped relative to us. We can use the collapsed margin for the opposite edge.
+ if (child->style()->isHorizontalWritingMode() == style()->isHorizontalWritingMode())
+ return child->collapsedMarginBefore();
+
+ // The child is perpendicular to us, which means its margins don't collapse but are on the
+ // "logical left/right" side of the child box. We can just return the raw margin in this case.
+ return marginAfterForChild(child);
+}
+
+int RenderBlock::marginBeforeForChild(RenderBoxModelObject* child) const
+{
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ return child->marginTop();
+ case BottomToTopWritingMode:
+ return child->marginBottom();
+ case LeftToRightWritingMode:
+ return child->marginLeft();
+ case RightToLeftWritingMode:
+ return child->marginRight();
+ }
+ ASSERT_NOT_REACHED();
+ return child->marginTop();
+}
+
+int RenderBlock::marginAfterForChild(RenderBoxModelObject* child) const
+{
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ return child->marginBottom();
+ case BottomToTopWritingMode:
+ return child->marginTop();
+ case LeftToRightWritingMode:
+ return child->marginRight();
+ case RightToLeftWritingMode:
+ return child->marginLeft();
+ }
+ ASSERT_NOT_REACHED();
+ return child->marginBottom();
+}
+
+int RenderBlock::marginStartForChild(RenderBoxModelObject* child) const
+{
+ if (style()->isHorizontalWritingMode())
+ return style()->isLeftToRightDirection() ? child->marginLeft() : child->marginRight();
+ return style()->isLeftToRightDirection() ? child->marginTop() : child->marginBottom();
+}
+
+int RenderBlock::marginEndForChild(RenderBoxModelObject* child) const
+{
+ if (style()->isHorizontalWritingMode())
+ return style()->isLeftToRightDirection() ? child->marginRight() : child->marginLeft();
+ return style()->isLeftToRightDirection() ? child->marginBottom() : child->marginTop();
+}
+
+void RenderBlock::setMarginStartForChild(RenderBox* child, int margin)
+{
+ if (style()->isHorizontalWritingMode()) {
+ if (style()->isLeftToRightDirection())
+ child->setMarginLeft(margin);
+ else
+ child->setMarginRight(margin);
+ } else {
+ if (style()->isLeftToRightDirection())
+ child->setMarginTop(margin);
+ else
+ child->setMarginBottom(margin);
+ }
+}
+
+void RenderBlock::setMarginEndForChild(RenderBox* child, int margin)
+{
+ if (style()->isHorizontalWritingMode()) {
+ if (style()->isLeftToRightDirection())
+ child->setMarginRight(margin);
+ else
+ child->setMarginLeft(margin);
+ } else {
+ if (style()->isLeftToRightDirection())
+ child->setMarginBottom(margin);
+ else
+ child->setMarginTop(margin);
+ }
+}
+
+void RenderBlock::setMarginBeforeForChild(RenderBox* child, int margin)
+{
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ child->setMarginTop(margin);
+ break;
+ case BottomToTopWritingMode:
+ child->setMarginBottom(margin);
+ break;
+ case LeftToRightWritingMode:
+ child->setMarginLeft(margin);
+ break;
+ case RightToLeftWritingMode:
+ child->setMarginRight(margin);
+ break;
+ }
+}
+
+void RenderBlock::setMarginAfterForChild(RenderBox* child, int margin)
+{
+ switch (style()->writingMode()) {
+ case TopToBottomWritingMode:
+ child->setMarginBottom(margin);
+ break;
+ case BottomToTopWritingMode:
+ child->setMarginTop(margin);
+ break;
+ case LeftToRightWritingMode:
+ child->setMarginRight(margin);
+ break;
+ case RightToLeftWritingMode:
+ child->setMarginLeft(margin);
+ break;
+ }
+}
+
+RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
+{
+ int childBeforePositive = 0;
+ int childBeforeNegative = 0;
+ int childAfterPositive = 0;
+ int childAfterNegative = 0;
+
+ int beforeMargin = 0;
+ int afterMargin = 0;
+
+ RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
+
+ // If the child has the same directionality as we do, then we can just return its
+ // margins in the same direction.
+ if (!child->isWritingModeRoot()) {
+ if (childRenderBlock) {
+ childBeforePositive = childRenderBlock->maxPositiveMarginBefore();
+ childBeforeNegative = childRenderBlock->maxNegativeMarginBefore();
+ childAfterPositive = childRenderBlock->maxPositiveMarginAfter();
+ childAfterNegative = childRenderBlock->maxNegativeMarginAfter();
+ } else {
+ beforeMargin = child->marginBefore();
+ afterMargin = child->marginAfter();
+ }
+ } else if (child->style()->isHorizontalWritingMode() == style()->isHorizontalWritingMode()) {
+ // The child has a different directionality. If the child is parallel, then it's just
+ // flipped relative to us. We can use the margins for the opposite edges.
+ if (childRenderBlock) {
+ childBeforePositive = childRenderBlock->maxPositiveMarginAfter();
+ childBeforeNegative = childRenderBlock->maxNegativeMarginAfter();
+ childAfterPositive = childRenderBlock->maxPositiveMarginBefore();
+ childAfterNegative = childRenderBlock->maxNegativeMarginBefore();
+ } else {
+ beforeMargin = child->marginAfter();
+ afterMargin = child->marginBefore();
+ }
+ } else {
+ // The child is perpendicular to us, which means its margins don't collapse but are on the
+ // "logical left/right" sides of the child box. We can just return the raw margin in this case.
+ beforeMargin = marginBeforeForChild(child);
+ afterMargin = marginAfterForChild(child);
+ }
+
+ // Resolve uncollapsing margins into their positive/negative buckets.
+ if (beforeMargin) {
+ if (beforeMargin > 0)
+ childBeforePositive = beforeMargin;
+ else
+ childBeforeNegative = -beforeMargin;
+ }
+ if (afterMargin) {
+ if (afterMargin > 0)
+ childAfterPositive = afterMargin;
+ else
+ childAfterNegative = -afterMargin;
+ }
+
+ return MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
+}
+
const char* RenderBlock::renderName() const
{
if (isBody())