summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/rendering/RenderBox.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderBox.cpp')
-rw-r--r--Source/WebCore/rendering/RenderBox.cpp854
1 files changed, 465 insertions, 389 deletions
diff --git a/Source/WebCore/rendering/RenderBox.cpp b/Source/WebCore/rendering/RenderBox.cpp
index 39c80d4..6e7c0f2 100644
--- a/Source/WebCore/rendering/RenderBox.cpp
+++ b/Source/WebCore/rendering/RenderBox.cpp
@@ -236,8 +236,6 @@ void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
RenderBlock* currBlock = toRenderBlock(curr);
if (currBlock->containsFloat(this))
parentBlock = currBlock;
- else
- break;
}
}
@@ -576,14 +574,14 @@ IntRect RenderBox::reflectedRect(const IntRect& r) const
bool RenderBox::includeVerticalScrollbarSize() const
{
- return !ScrollbarTheme::nativeTheme()->usesOverlayScrollbars()
- && hasOverflowClip() && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO);
+ return hasOverflowClip() && !layer()->hasOverlayScrollbars()
+ && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO);
}
bool RenderBox::includeHorizontalScrollbarSize() const
{
- return !ScrollbarTheme::nativeTheme()->usesOverlayScrollbars()
- && hasOverflowClip() && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO);
+ return hasOverflowClip() && !layer()->hasOverlayScrollbars()
+ && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO);
}
int RenderBox::verticalScrollbarWidth() const
@@ -1288,7 +1286,7 @@ IntSize RenderBox::offsetFromContainer(RenderObject* o, const IntPoint& point) c
} else
offset += locationOffsetIncludingFlipping();
} else
- offset += locationOffset();
+ offset += locationOffsetIncludingFlipping();
}
if (o->hasOverflowClip())
@@ -1321,18 +1319,18 @@ void RenderBox::positionLineBox(InlineBox* box)
if (isPositioned()) {
// Cache the x position only if we were an INLINE type originally.
bool wasInline = style()->isOriginalDisplayInlineType();
- if (wasInline && style()->hasStaticX()) {
+ if (wasInline && style()->hasStaticInlinePosition(box->isHorizontal())) {
// The value is cached in the xPos of the box. We only need this value if
// our object was inline originally, since otherwise it would have ended up underneath
// the inlines.
- layer()->setStaticX(box->x());
+ layer()->setStaticInlinePosition(lroundf(box->logicalLeft()));
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
- } else if (!wasInline && style()->hasStaticY()) {
+ } else if (!wasInline && style()->hasStaticBlockPosition(box->isHorizontal())) {
// Our object was a block originally, so we make our normal flow position be
// just below the line box (as though all the inlines that came before us got
// wrapped in an anonymous block, which is what would have happened had we been
// in flow). This value was cached in the y() of the box.
- layer()->setStaticY(box->y());
+ layer()->setStaticBlockPosition(box->logicalTop());
setChildNeedsLayout(true, false); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
}
@@ -1340,7 +1338,7 @@ void RenderBox::positionLineBox(InlineBox* box)
box->remove();
box->destroy(renderArena());
} else if (isReplaced()) {
- setLocation(box->x(), box->y());
+ setLocation(lroundf(box->x()), lroundf(box->y()));
m_inlineBoxWrapper = box;
}
}
@@ -1994,7 +1992,7 @@ int RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) const
// FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
// containing block's block-flow.
// https://bugs.webkit.org/show_bug.cgi?id=46496
- const int cw = isPositioned() ? containingBlockWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
+ const int cw = isPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
if (cw > 0)
return computeContentBoxLogicalWidth(logicalWidth.calcMinValue(cw));
}
@@ -2041,7 +2039,7 @@ int RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) const
// FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
// containing block's block-flow.
// https://bugs.webkit.org/show_bug.cgi?id=46496
- int availableHeight = isPositioned() ? containingBlockHeightForPositioned(toRenderBoxModelObject(cb)) : toRenderBox(cb)->availableLogicalHeight();
+ int availableHeight = isPositioned() ? containingBlockLogicalHeightForPositioned(toRenderBoxModelObject(cb)) : toRenderBox(cb)->availableLogicalHeight();
// It is necessary to use the border-box to match WinIE's broken
// box model. This is essential for sizing inside
@@ -2117,7 +2115,7 @@ void RenderBox::computeBlockDirectionMargins(RenderBlock* containingBlock)
containingBlock->setMarginAfterForChild(this, style()->marginAfterUsing(containingBlockStyle).calcMinValue(cw));
}
-int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* containingBlock) const
+int RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
#if PLATFORM(ANDROID)
// Fixed element's position should be decided by the visible screen size.
@@ -2127,11 +2125,13 @@ int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* con
return PlatformBridge::screenWidthInDocCoord(view->frameView());
}
#endif
- if (containingBlock->isBox()) {
- const RenderBox* containingBlockBox = toRenderBox(containingBlock);
- return containingBlockBox->width() - containingBlockBox->borderLeft() - containingBlockBox->borderRight() - containingBlockBox->verticalScrollbarWidth();
- }
-
+
+ if (checkForPerpendicularWritingMode && containingBlock->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode())
+ return containingBlockLogicalHeightForPositioned(containingBlock, false);
+
+ if (containingBlock->isBox())
+ return toRenderBox(containingBlock)->clientLogicalWidth();
+
ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
const RenderInline* flow = toRenderInline(containingBlock);
@@ -2155,7 +2155,7 @@ int RenderBox::containingBlockWidthForPositioned(const RenderBoxModelObject* con
return max(0, (fromRight - fromLeft));
}
-int RenderBox::containingBlockHeightForPositioned(const RenderBoxModelObject* containingBlock) const
+int RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
{
#if PLATFORM(ANDROID)
// Fixed element's position should be decided by the visible screen size.
@@ -2165,14 +2165,57 @@ int RenderBox::containingBlockHeightForPositioned(const RenderBoxModelObject* co
return PlatformBridge::screenHeightInDocCoord(view->frameView());
}
#endif
- int heightResult = 0;
+
+ if (checkForPerpendicularWritingMode && containingBlock->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode())
+ return containingBlockLogicalWidthForPositioned(containingBlock, false);
+
if (containingBlock->isBox())
- heightResult = toRenderBox(containingBlock)->height();
- else if (containingBlock->isRenderInline()) {
- ASSERT(containingBlock->isRelPositioned());
- heightResult = toRenderInline(containingBlock)->linesBoundingBox().height();
+ return toRenderBox(containingBlock)->clientLogicalHeight();
+
+ ASSERT(containingBlock->isRenderInline() && containingBlock->isRelPositioned());
+
+ const RenderInline* flow = toRenderInline(containingBlock);
+ InlineFlowBox* first = flow->firstLineBox();
+ InlineFlowBox* last = flow->lastLineBox();
+
+ // If the containing block is empty, return a height of 0.
+ if (!first || !last)
+ return 0;
+
+ int heightResult;
+ IntRect boundingBox = flow->linesBoundingBox();
+ if (containingBlock->style()->isHorizontalWritingMode())
+ heightResult = boundingBox.height();
+ else
+ heightResult = boundingBox.width();
+ heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter());
+ return heightResult;
+}
+
+static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, int containerLogicalWidth,
+ TextDirection containerDirection)
+{
+ if (!logicalLeft.isAuto() || !logicalRight.isAuto())
+ return;
+
+ // FIXME: The static distance computation has not been patched for mixed writing modes yet.
+ if (containerDirection == LTR) {
+ int staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft();
+ for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->parent()) {
+ if (curr->isBox())
+ staticPosition += toRenderBox(curr)->logicalLeft();
+ }
+ logicalLeft.setValue(Fixed, staticPosition);
+ } else {
+ RenderBox* enclosingBox = child->parent()->enclosingBox();
+ int staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalRight();
+ staticPosition -= enclosingBox->logicalWidth();
+ for (RenderObject* curr = enclosingBox; curr && curr != containerBlock; curr = curr->parent()) {
+ if (curr->isBox())
+ staticPosition -= toRenderBox(curr)->logicalLeft();
+ }
+ logicalRight.setValue(Fixed, staticPosition);
}
- return heightResult - containingBlock->borderTop() - containingBlock->borderBottom();
}
void RenderBox::computePositionedLogicalWidth()
@@ -2211,17 +2254,21 @@ void RenderBox::computePositionedLogicalWidth()
// relative positioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const int containerWidth = containingBlockWidthForPositioned(containerBlock);
+ const int containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
// To match WinIE, in quirks mode use the parent's 'direction' property
// instead of the the container block's.
TextDirection containerDirection = (document()->inQuirksMode()) ? parent()->style()->direction() : containerBlock->style()->direction();
- const int bordersPlusPadding = borderAndPaddingWidth();
- const Length marginLeft = style()->marginLeft();
- const Length marginRight = style()->marginRight();
- Length left = style()->left();
- Length right = style()->right();
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ const int bordersPlusPadding = borderAndPaddingLogicalWidth();
+ const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
+ const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
+ int& marginLogicalLeftAlias = isHorizontal ? m_marginLeft : m_marginTop;
+ int& marginLogicalRightAlias = isHorizontal ? m_marginRight : m_marginBottom;
+
+ Length logicalLeft = style()->logicalLeft();
+ Length logicalRight = style()->logicalRight();
/*---------------------------------------------------------------------------*\
* For the purposes of this section and the next, the term "static position"
@@ -2249,107 +2296,98 @@ void RenderBox::computePositionedLogicalWidth()
// see FIXME 2
// Calculate the static distance if needed.
- if (left.isAuto() && right.isAuto()) {
- if (containerDirection == LTR) {
- // 'staticX' should already have been set through layout of the parent.
- int staticPosition = layer()->staticX() - containerBlock->borderLeft();
- for (RenderObject* curr = parent(); curr && curr != containerBlock; curr = curr->parent()) {
- if (curr->isBox())
- staticPosition += toRenderBox(curr)->x();
- }
- left.setValue(Fixed, staticPosition);
- } else {
- RenderBox* enclosingBox = parent()->enclosingBox();
- // 'staticX' should already have been set through layout of the parent.
- int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight();
- staticPosition -= enclosingBox->width();
- for (RenderObject* curr = enclosingBox; curr && curr != containerBlock; curr = curr->parent()) {
- if (curr->isBox())
- staticPosition -= toRenderBox(curr)->x();
- }
- right.setValue(Fixed, staticPosition);
- }
- }
-
+ computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, containerDirection);
+
// Calculate constraint equation values for 'width' case.
- int widthResult;
- int xResult;
- computePositionedLogicalWidthUsing(style()->width(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- widthResult, m_marginLeft, m_marginRight, xResult);
- setWidth(widthResult);
- setX(xResult);
+ int logicalWidthResult;
+ int logicalLeftResult;
+ computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
+ containerLogicalWidth, bordersPlusPadding,
+ logicalLeft, logicalRight, marginLogicalLeft, marginLogicalRight,
+ logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
+ setLogicalWidth(logicalWidthResult);
+ setLogicalLeft(logicalLeftResult);
// Calculate constraint equation values for 'max-width' case.
- if (!style()->maxWidth().isUndefined()) {
- int maxWidth;
- int maxMarginLeft;
- int maxMarginRight;
- int maxXPos;
-
- computePositionedLogicalWidthUsing(style()->maxWidth(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- maxWidth, maxMarginLeft, maxMarginRight, maxXPos);
-
- if (width() > maxWidth) {
- setWidth(maxWidth);
- m_marginLeft = maxMarginLeft;
- m_marginRight = maxMarginRight;
- m_frameRect.setX(maxXPos);
+ if (!style()->logicalMaxWidth().isUndefined()) {
+ int maxLogicalWidth;
+ int maxMarginLogicalLeft;
+ int maxMarginLogicalRight;
+ int maxLogicalLeftPos;
+
+ computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
+ containerLogicalWidth, bordersPlusPadding,
+ logicalLeft, logicalRight, marginLogicalLeft, marginLogicalRight,
+ maxLogicalWidth, maxMarginLogicalLeft, maxMarginLogicalRight, maxLogicalLeftPos);
+
+ if (logicalWidth() > maxLogicalWidth) {
+ setLogicalWidth(maxLogicalWidth);
+ marginLogicalLeftAlias = maxMarginLogicalLeft;
+ marginLogicalRightAlias = maxMarginLogicalRight;
+ setLogicalLeft(maxLogicalLeftPos);
}
}
// Calculate constraint equation values for 'min-width' case.
- if (!style()->minWidth().isZero()) {
- int minWidth;
- int minMarginLeft;
- int minMarginRight;
- int minXPos;
-
- computePositionedLogicalWidthUsing(style()->minWidth(), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- minWidth, minMarginLeft, minMarginRight, minXPos);
-
- if (width() < minWidth) {
- setWidth(minWidth);
- m_marginLeft = minMarginLeft;
- m_marginRight = minMarginRight;
- m_frameRect.setX(minXPos);
+ if (!style()->logicalMinWidth().isZero()) {
+ int minLogicalWidth;
+ int minMarginLogicalLeft;
+ int minMarginLogicalRight;
+ int minLogicalLeftPos;
+
+ computePositionedLogicalWidthUsing(style()->logicalMinWidth(), containerBlock, containerDirection,
+ containerLogicalWidth, bordersPlusPadding,
+ logicalLeft, logicalRight, marginLogicalLeft, marginLogicalRight,
+ minLogicalWidth, minMarginLogicalLeft, minMarginLogicalRight, minLogicalLeftPos);
+
+ if (logicalWidth() < minLogicalWidth) {
+ setLogicalWidth(minLogicalWidth);
+ marginLogicalLeftAlias = minMarginLogicalLeft;
+ marginLogicalRightAlias = minMarginLogicalRight;
+ setLogicalLeft(minLogicalLeftPos);
}
}
- if (stretchesToMinIntrinsicLogicalWidth() && width() < minPreferredLogicalWidth() - bordersPlusPadding) {
+ if (stretchesToMinIntrinsicLogicalWidth() && logicalWidth() < minPreferredLogicalWidth() - bordersPlusPadding) {
computePositionedLogicalWidthUsing(Length(minPreferredLogicalWidth() - bordersPlusPadding, Fixed), containerBlock, containerDirection,
- containerWidth, bordersPlusPadding,
- left, right, marginLeft, marginRight,
- widthResult, m_marginLeft, m_marginRight, xResult);
- setWidth(widthResult);
- setX(xResult);
+ containerLogicalWidth, bordersPlusPadding,
+ logicalLeft, logicalRight, marginLogicalLeft, marginLogicalRight,
+ logicalWidthResult, marginLogicalLeftAlias, marginLogicalRightAlias, logicalLeftResult);
+ setLogicalWidth(logicalWidthResult);
+ setLogicalLeft(logicalLeftResult);
}
- // Put width() into correct form.
- setWidth(width() + bordersPlusPadding);
+ // Put logicalWidth() into correct form.
+ setLogicalWidth(logicalWidth() + bordersPlusPadding);
+}
+
+static void computeLogicalLeftPositionedOffset(int& logicalLeftPos, const RenderBox* child, int logicalWidthValue, const RenderBoxModelObject* containerBlock, int containerLogicalWidth)
+{
+ // Deal with differing writing modes here. Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
+ // along this axis, then we need to flip the coordinate. This can only happen if the containing block is both a flipped mode and perpendicular to us.
+ if (containerBlock->style()->isHorizontalWritingMode() != child->style()->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
+ logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
+ logicalLeftPos += (child->style()->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
+ } else
+ logicalLeftPos += (child->style()->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
}
-void RenderBox::computePositionedLogicalWidthUsing(Length width, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
- const int containerWidth, const int bordersPlusPadding,
- const Length left, const Length right, const Length marginLeft, const Length marginRight,
- int& widthValue, int& marginLeftValue, int& marginRightValue, int& xPos)
+void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
+ int containerLogicalWidth, int bordersPlusPadding,
+ Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
+ int& logicalWidthValue, int& marginLogicalLeftValue, int& marginLogicalRightValue, int& logicalLeftPos)
{
// 'left' and 'right' cannot both be 'auto' because one would of been
// converted to the static position already
- ASSERT(!(left.isAuto() && right.isAuto()));
+ ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
- int leftValue = 0;
+ int logicalLeftValue = 0;
- bool widthIsAuto = width.isIntrinsicOrAuto();
- bool leftIsAuto = left.isAuto();
- bool rightIsAuto = right.isAuto();
+ bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
+ bool logicalLeftIsAuto = logicalLeft.isAuto();
+ bool logicalRightIsAuto = logicalRight.isAuto();
- if (!leftIsAuto && !widthIsAuto && !rightIsAuto) {
+ if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
/*-----------------------------------------------------------------------*\
* If none of the three is 'auto': If both 'margin-left' and 'margin-
* right' are 'auto', solve the equation under the extra constraint that
@@ -2365,43 +2403,43 @@ void RenderBox::computePositionedLogicalWidthUsing(Length width, const RenderBox
// NOTE: It is not necessary to solve for 'right' in the over constrained
// case because the value is not used for any further calculations.
- leftValue = left.calcValue(containerWidth);
- widthValue = computeContentBoxLogicalWidth(width.calcValue(containerWidth));
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
- const int availableSpace = containerWidth - (leftValue + widthValue + right.calcValue(containerWidth) + bordersPlusPadding);
+ const int availableSpace = containerLogicalWidth - (logicalLeftValue + logicalWidthValue + logicalRight.calcValue(containerLogicalWidth) + bordersPlusPadding);
// Margins are now the only unknown
- if (marginLeft.isAuto() && marginRight.isAuto()) {
+ if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
// Both margins auto, solve for equality
if (availableSpace >= 0) {
- marginLeftValue = availableSpace / 2; // split the difference
- marginRightValue = availableSpace - marginLeftValue; // account for odd valued differences
+ marginLogicalLeftValue = availableSpace / 2; // split the difference
+ marginLogicalRightValue = availableSpace - marginLogicalLeftValue; // account for odd valued differences
} else {
// see FIXME 1
if (containerDirection == LTR) {
- marginLeftValue = 0;
- marginRightValue = availableSpace; // will be negative
+ marginLogicalLeftValue = 0;
+ marginLogicalRightValue = availableSpace; // will be negative
} else {
- marginLeftValue = availableSpace; // will be negative
- marginRightValue = 0;
+ marginLogicalLeftValue = availableSpace; // will be negative
+ marginLogicalRightValue = 0;
}
}
- } else if (marginLeft.isAuto()) {
+ } else if (marginLogicalLeft.isAuto()) {
// Solve for left margin
- marginRightValue = marginRight.calcValue(containerWidth);
- marginLeftValue = availableSpace - marginRightValue;
- } else if (marginRight.isAuto()) {
+ marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
+ marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
+ } else if (marginLogicalRight.isAuto()) {
// Solve for right margin
- marginLeftValue = marginLeft.calcValue(containerWidth);
- marginRightValue = availableSpace - marginLeftValue;
+ marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
} else {
// Over-constrained, solve for left if direction is RTL
- marginLeftValue = marginLeft.calcValue(containerWidth);
- marginRightValue = marginRight.calcValue(containerWidth);
+ marginLogicalLeftValue = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalRightValue = marginLogicalRight.calcValue(containerLogicalWidth);
// see FIXME 1 -- used to be "this->style()->direction()"
if (containerDirection == RTL)
- leftValue = (availableSpace + leftValue) - marginLeftValue - marginRightValue;
+ logicalLeftValue = (availableSpace + logicalLeftValue) - marginLogicalLeftValue - marginLogicalRightValue;
}
} else {
/*--------------------------------------------------------------------*\
@@ -2446,51 +2484,51 @@ void RenderBox::computePositionedLogicalWidthUsing(Length width, const RenderBox
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginLeftValue = marginLeft.calcMinValue(containerWidth);
- marginRightValue = marginRight.calcMinValue(containerWidth);
+ marginLogicalLeftValue = marginLogicalLeft.calcMinValue(containerLogicalWidth);
+ marginLogicalRightValue = marginLogicalRight.calcMinValue(containerLogicalWidth);
- const int availableSpace = containerWidth - (marginLeftValue + marginRightValue + bordersPlusPadding);
+ const int availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
// FIXME: Is there a faster way to find the correct case?
// Use rule/case that applies.
- if (leftIsAuto && widthIsAuto && !rightIsAuto) {
+ if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 1: (use shrink-to-fit for width, and solve of left)
- int rightValue = right.calcValue(containerWidth);
+ int logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
// FIXME: would it be better to have shrink-to-fit in one step?
int preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
int preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
- int availableWidth = availableSpace - rightValue;
- widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
- leftValue = availableSpace - (widthValue + rightValue);
- } else if (!leftIsAuto && widthIsAuto && rightIsAuto) {
+ int availableWidth = availableSpace - logicalRightValue;
+ logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
+ logicalLeftValue = availableSpace - (logicalWidthValue + logicalRightValue);
+ } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 3: (use shrink-to-fit for width, and no need solve of right)
- leftValue = left.calcValue(containerWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
// FIXME: would it be better to have shrink-to-fit in one step?
int preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
int preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
- int availableWidth = availableSpace - leftValue;
- widthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
- } else if (leftIsAuto && !width.isAuto() && !rightIsAuto) {
+ int availableWidth = availableSpace - logicalLeftValue;
+ logicalWidthValue = min(max(preferredMinWidth, availableWidth), preferredWidth);
+ } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 4: (solve for left)
- widthValue = computeContentBoxLogicalWidth(width.calcValue(containerWidth));
- leftValue = availableSpace - (widthValue + right.calcValue(containerWidth));
- } else if (!leftIsAuto && widthIsAuto && !rightIsAuto) {
+ logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
+ logicalLeftValue = availableSpace - (logicalWidthValue + logicalRight.calcValue(containerLogicalWidth));
+ } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
// RULE 5: (solve for width)
- leftValue = left.calcValue(containerWidth);
- widthValue = availableSpace - (leftValue + right.calcValue(containerWidth));
- } else if (!leftIsAuto&& !widthIsAuto && rightIsAuto) {
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalWidthValue = availableSpace - (logicalLeftValue + logicalRight.calcValue(containerLogicalWidth));
+ } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
// RULE 6: (no need solve for right)
- leftValue = left.calcValue(containerWidth);
- widthValue = computeContentBoxLogicalWidth(width.calcValue(containerWidth));
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalWidthValue = computeContentBoxLogicalWidth(logicalWidth.calcValue(containerLogicalWidth));
}
}
// Use computed values to calculate the horizontal position.
- // FIXME: This hack is needed to calculate the xPos for a 'rtl' relatively
- // positioned, inline because right now, it is using the xPos
+ // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
+ // positioned, inline because right now, it is using the logical left position
// of the first line box when really it should use the last line box. When
// this is fixed elsewhere, this block should be removed.
if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
@@ -2498,12 +2536,27 @@ void RenderBox::computePositionedLogicalWidthUsing(Length width, const RenderBox
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- xPos = leftValue + marginLeftValue + lastLine->borderLogicalLeft() + (lastLine->x() - firstLine->x());
+ logicalLeftPos = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
return;
}
}
- xPos = leftValue + marginLeftValue + containerBlock->borderLeft();
+ logicalLeftPos = logicalLeftValue + marginLogicalLeftValue;
+ computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidthValue, containerBlock, containerLogicalWidth);
+}
+
+static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
+{
+ if (!logicalTop.isAuto() || !logicalBottom.isAuto())
+ return;
+
+ // FIXME: The static distance computation has not been patched for mixed writing modes.
+ int staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore();
+ for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->parent()) {
+ if (curr->isBox() && !curr->isTableRow())
+ staticLogicalTop += toRenderBox(curr)->logicalTop();
+ }
+ logicalTop.setValue(Fixed, staticLogicalTop);
}
void RenderBox::computePositionedLogicalHeight()
@@ -2523,14 +2576,19 @@ void RenderBox::computePositionedLogicalHeight()
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const int containerHeight = containingBlockHeightForPositioned(containerBlock);
+ const int containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
- const int bordersPlusPadding = borderAndPaddingHeight();
- const Length marginTop = style()->marginTop();
- const Length marginBottom = style()->marginBottom();
- Length top = style()->top();
- Length bottom = style()->bottom();
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ bool isFlipped = style()->isFlippedBlocksWritingMode();
+ const int bordersPlusPadding = borderAndPaddingLogicalHeight();
+ const Length marginBefore = style()->marginBefore();
+ const Length marginAfter = style()->marginAfter();
+ int& marginBeforeAlias = isHorizontal ? (isFlipped ? m_marginBottom : m_marginTop) : (isFlipped ? m_marginRight: m_marginLeft);
+ int& marginAfterAlias = isHorizontal ? (isFlipped ? m_marginTop : m_marginBottom) : (isFlipped ? m_marginLeft: m_marginRight);
+ Length logicalTop = style()->logicalTop();
+ Length logicalBottom = style()->logicalBottom();
+
/*---------------------------------------------------------------------------*\
* For the purposes of this section and the next, the term "static position"
* (of an element) refers, roughly, to the position an element would have had
@@ -2550,95 +2608,108 @@ void RenderBox::computePositionedLogicalHeight()
// see FIXME 2
// Calculate the static distance if needed.
- if (top.isAuto() && bottom.isAuto()) {
- // staticY should already have been set through layout of the parent()
- int staticTop = layer()->staticY() - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- if (po->isBox() && !po->isTableRow())
- staticTop += toRenderBox(po)->y();
- }
- top.setValue(Fixed, staticTop);
- }
-
+ computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
- int h; // Needed to compute overflow.
- int y;
+ int logicalHeightResult; // Needed to compute overflow.
+ int logicalTopPos;
// Calculate constraint equation values for 'height' case.
- computePositionedLogicalHeightUsing(style()->height(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- h, m_marginTop, m_marginBottom, y);
- setY(y);
+ computePositionedLogicalHeightUsing(style()->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
+ logicalTop, logicalBottom, marginBefore, marginAfter,
+ logicalHeightResult, marginBeforeAlias, marginAfterAlias, logicalTopPos);
+ setLogicalTop(logicalTopPos);
// Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
// see FIXME 3
// Calculate constraint equation values for 'max-height' case.
- if (!style()->maxHeight().isUndefined()) {
- int maxHeight;
- int maxMarginTop;
- int maxMarginBottom;
- int maxYPos;
-
- computePositionedLogicalHeightUsing(style()->maxHeight(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- maxHeight, maxMarginTop, maxMarginBottom, maxYPos);
-
- if (h > maxHeight) {
- h = maxHeight;
- m_marginTop = maxMarginTop;
- m_marginBottom = maxMarginBottom;
- m_frameRect.setY(maxYPos);
+ if (!style()->logicalMaxHeight().isUndefined()) {
+ int maxLogicalHeight;
+ int maxMarginBefore;
+ int maxMarginAfter;
+ int maxLogicalTopPos;
+
+ computePositionedLogicalHeightUsing(style()->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
+ logicalTop, logicalBottom, marginBefore, marginAfter,
+ maxLogicalHeight, maxMarginBefore, maxMarginAfter, maxLogicalTopPos);
+
+ if (logicalHeightResult > maxLogicalHeight) {
+ logicalHeightResult = maxLogicalHeight;
+ marginBeforeAlias = maxMarginBefore;
+ marginAfterAlias = maxMarginAfter;
+ setLogicalTop(maxLogicalTopPos);
}
}
// Calculate constraint equation values for 'min-height' case.
- if (!style()->minHeight().isZero()) {
- int minHeight;
- int minMarginTop;
- int minMarginBottom;
- int minYPos;
-
- computePositionedLogicalHeightUsing(style()->minHeight(), containerBlock, containerHeight, bordersPlusPadding,
- top, bottom, marginTop, marginBottom,
- minHeight, minMarginTop, minMarginBottom, minYPos);
-
- if (h < minHeight) {
- h = minHeight;
- m_marginTop = minMarginTop;
- m_marginBottom = minMarginBottom;
- m_frameRect.setY(minYPos);
+ if (!style()->logicalMinHeight().isZero()) {
+ int minLogicalHeight;
+ int minMarginBefore;
+ int minMarginAfter;
+ int minLogicalTopPos;
+
+ computePositionedLogicalHeightUsing(style()->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding,
+ logicalTop, logicalBottom, marginBefore, marginAfter,
+ minLogicalHeight, minMarginBefore, minMarginAfter, minLogicalTopPos);
+
+ if (logicalHeightResult < minLogicalHeight) {
+ logicalHeightResult = minLogicalHeight;
+ marginBeforeAlias = minMarginBefore;
+ marginAfterAlias = minMarginAfter;
+ setLogicalTop(minLogicalTopPos);
}
}
// Set final height value.
- setHeight(h + bordersPlusPadding);
+ setLogicalHeight(logicalHeightResult + bordersPlusPadding);
}
-void RenderBox::computePositionedLogicalHeightUsing(Length h, const RenderBoxModelObject* containerBlock,
- const int containerHeight, const int bordersPlusPadding,
- const Length top, const Length bottom, const Length marginTop, const Length marginBottom,
- int& heightValue, int& marginTopValue, int& marginBottomValue, int& yPos)
+static void computeLogicalTopPositionedOffset(int& logicalTopPos, const RenderBox* child, int logicalHeightValue, const RenderBoxModelObject* containerBlock, int containerLogicalHeight)
+{
+ // Deal with differing writing modes here. Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
+ // along this axis, then we need to flip the coordinate. This can only happen if the containing block is both a flipped mode and perpendicular to us.
+ if ((child->style()->isFlippedBlocksWritingMode() && child->style()->isHorizontalWritingMode() != containerBlock->style()->isHorizontalWritingMode())
+ || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->style()->isHorizontalWritingMode() == containerBlock->style()->isHorizontalWritingMode()))
+ logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos;
+
+ // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt.
+ if (containerBlock->style()->isFlippedBlocksWritingMode() && child->style()->isHorizontalWritingMode() == containerBlock->style()->isHorizontalWritingMode()) {
+ if (child->style()->isHorizontalWritingMode())
+ logicalTopPos += containerBlock->borderBottom();
+ else
+ logicalTopPos += containerBlock->borderRight();
+ } else {
+ if (child->style()->isHorizontalWritingMode())
+ logicalTopPos += containerBlock->borderTop();
+ else
+ logicalTopPos += containerBlock->borderLeft();
+ }
+}
+
+void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
+ int containerLogicalHeight, int bordersPlusPadding,
+ Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
+ int& logicalHeightValue, int& marginBeforeValue, int& marginAfterValue, int& logicalTopPos)
{
// 'top' and 'bottom' cannot both be 'auto' because 'top would of been
// converted to the static position in computePositionedLogicalHeight()
- ASSERT(!(top.isAuto() && bottom.isAuto()));
+ ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
- int contentHeight = height() - bordersPlusPadding;
+ int contentLogicalHeight = logicalHeight() - bordersPlusPadding;
- int topValue = 0;
+ int logicalTopValue = 0;
- bool heightIsAuto = h.isAuto();
- bool topIsAuto = top.isAuto();
- bool bottomIsAuto = bottom.isAuto();
+ bool logicalHeightIsAuto = logicalHeightLength.isAuto();
+ bool logicalTopIsAuto = logicalTop.isAuto();
+ bool logicalBottomIsAuto = logicalBottom.isAuto();
// Height is never unsolved for tables.
if (isTable()) {
- h.setValue(Fixed, contentHeight);
- heightIsAuto = false;
+ logicalHeightLength.setValue(Fixed, contentLogicalHeight);
+ logicalHeightIsAuto = false;
}
- if (!topIsAuto && !heightIsAuto && !bottomIsAuto) {
+ if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
/*-----------------------------------------------------------------------*\
* If none of the three are 'auto': If both 'margin-top' and 'margin-
* bottom' are 'auto', solve the equation under the extra constraint that
@@ -2650,29 +2721,29 @@ void RenderBox::computePositionedLogicalHeightUsing(Length h, const RenderBoxMod
// NOTE: It is not necessary to solve for 'bottom' in the over constrained
// case because the value is not used for any further calculations.
- heightValue = computeContentBoxLogicalHeight(h.calcValue(containerHeight));
- topValue = top.calcValue(containerHeight);
+ logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
- const int availableSpace = containerHeight - (topValue + heightValue + bottom.calcValue(containerHeight) + bordersPlusPadding);
+ const int availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight) + bordersPlusPadding);
// Margins are now the only unknown
- if (marginTop.isAuto() && marginBottom.isAuto()) {
+ if (marginBefore.isAuto() && marginAfter.isAuto()) {
// Both margins auto, solve for equality
// NOTE: This may result in negative values.
- marginTopValue = availableSpace / 2; // split the difference
- marginBottomValue = availableSpace - marginTopValue; // account for odd valued differences
- } else if (marginTop.isAuto()) {
+ marginBeforeValue = availableSpace / 2; // split the difference
+ marginAfterValue = availableSpace - marginBeforeValue; // account for odd valued differences
+ } else if (marginBefore.isAuto()) {
// Solve for top margin
- marginBottomValue = marginBottom.calcValue(containerHeight);
- marginTopValue = availableSpace - marginBottomValue;
- } else if (marginBottom.isAuto()) {
+ marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
+ marginBeforeValue = availableSpace - marginAfterValue;
+ } else if (marginAfter.isAuto()) {
// Solve for bottom margin
- marginTopValue = marginTop.calcValue(containerHeight);
- marginBottomValue = availableSpace - marginTopValue;
+ marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
+ marginAfterValue = availableSpace - marginBeforeValue;
} else {
// Over-constrained, (no need solve for bottom)
- marginTopValue = marginTop.calcValue(containerHeight);
- marginBottomValue = marginBottom.calcValue(containerHeight);
+ marginBeforeValue = marginBefore.calcValue(containerLogicalHeight);
+ marginAfterValue = marginAfter.calcValue(containerLogicalHeight);
}
} else {
/*--------------------------------------------------------------------*\
@@ -2701,37 +2772,38 @@ void RenderBox::computePositionedLogicalHeightUsing(Length h, const RenderBoxMod
// because the value is not used for any further calculations.
// Calculate margins, 'auto' margins are ignored.
- marginTopValue = marginTop.calcMinValue(containerHeight);
- marginBottomValue = marginBottom.calcMinValue(containerHeight);
+ marginBeforeValue = marginBefore.calcMinValue(containerLogicalHeight);
+ marginAfterValue = marginAfter.calcMinValue(containerLogicalHeight);
- const int availableSpace = containerHeight - (marginTopValue + marginBottomValue + bordersPlusPadding);
+ const int availableSpace = containerLogicalHeight - (marginBeforeValue + marginAfterValue + bordersPlusPadding);
// Use rule/case that applies.
- if (topIsAuto && heightIsAuto && !bottomIsAuto) {
+ if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 1: (height is content based, solve of top)
- heightValue = contentHeight;
- topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
- } else if (!topIsAuto && heightIsAuto && bottomIsAuto) {
+ logicalHeightValue = contentLogicalHeight;
+ logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
+ } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 3: (height is content based, no need solve of bottom)
- topValue = top.calcValue(containerHeight);
- heightValue = contentHeight;
- } else if (topIsAuto && !heightIsAuto && !bottomIsAuto) {
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalHeightValue = contentLogicalHeight;
+ } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 4: (solve of top)
- heightValue = computeContentBoxLogicalHeight(h.calcValue(containerHeight));
- topValue = availableSpace - (heightValue + bottom.calcValue(containerHeight));
- } else if (!topIsAuto && heightIsAuto && !bottomIsAuto) {
+ logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
+ logicalTopValue = availableSpace - (logicalHeightValue + logicalBottom.calcValue(containerLogicalHeight));
+ } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
// RULE 5: (solve of height)
- topValue = top.calcValue(containerHeight);
- heightValue = max(0, availableSpace - (topValue + bottom.calcValue(containerHeight)));
- } else if (!topIsAuto && !heightIsAuto && bottomIsAuto) {
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalHeightValue = max(0, availableSpace - (logicalTopValue + logicalBottom.calcValue(containerLogicalHeight)));
+ } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
// RULE 6: (no need solve of bottom)
- heightValue = computeContentBoxLogicalHeight(h.calcValue(containerHeight));
- topValue = top.calcValue(containerHeight);
+ logicalHeightValue = computeContentBoxLogicalHeight(logicalHeightLength.calcValue(containerLogicalHeight));
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
}
}
// Use computed values to calculate the vertical position.
- yPos = topValue + marginTopValue + containerBlock->borderTop();
+ logicalTopPos = logicalTopValue + marginBeforeValue;
+ computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeightValue, containerBlock, containerLogicalHeight);
}
void RenderBox::computePositionedLogicalWidthReplaced()
@@ -2746,18 +2818,20 @@ void RenderBox::computePositionedLogicalWidthReplaced()
// relative positioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const int containerWidth = containingBlockWidthForPositioned(containerBlock);
+ const int containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
// To match WinIE, in quirks mode use the parent's 'direction' property
// instead of the the container block's.
TextDirection containerDirection = (document()->inQuirksMode()) ? parent()->style()->direction() : containerBlock->style()->direction();
// Variables to solve.
- Length left = style()->left();
- Length right = style()->right();
- Length marginLeft = style()->marginLeft();
- Length marginRight = style()->marginRight();
-
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ Length logicalLeft = style()->logicalLeft();
+ Length logicalRight = style()->logicalRight();
+ Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
+ Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
+ int& marginLogicalLeftAlias = isHorizontal ? m_marginLeft : m_marginTop;
+ int& marginLogicalRightAlias = isHorizontal ? m_marginRight : m_marginBottom;
/*-----------------------------------------------------------------------*\
* 1. The used value of 'width' is determined as for inline replaced
@@ -2766,8 +2840,8 @@ void RenderBox::computePositionedLogicalWidthReplaced()
// NOTE: This value of width is FINAL in that the min/max width calculations
// are dealt with in computeReplacedWidth(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- setWidth(computeReplacedLogicalWidth() + borderAndPaddingWidth());
- const int availableSpace = containerWidth - width();
+ setLogicalWidth(computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth());
+ const int availableSpace = containerLogicalWidth - logicalWidth();
/*-----------------------------------------------------------------------*\
* 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
@@ -2775,37 +2849,17 @@ void RenderBox::computePositionedLogicalWidthReplaced()
* else if 'direction' is 'rtl', set 'right' to the static position.
\*-----------------------------------------------------------------------*/
// see FIXME 2
- if (left.isAuto() && right.isAuto()) {
- // see FIXME 1
- if (containerDirection == LTR) {
- // 'staticX' should already have been set through layout of the parent.
- int staticPosition = layer()->staticX() - containerBlock->borderLeft();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- if (po->isBox())
- staticPosition += toRenderBox(po)->x();
- }
- left.setValue(Fixed, staticPosition);
- } else {
- RenderObject* po = parent();
- // 'staticX' should already have been set through layout of the parent.
- int staticPosition = layer()->staticX() + containerWidth + containerBlock->borderRight();
- for ( ; po && po != containerBlock; po = po->parent()) {
- if (po->isBox())
- staticPosition += toRenderBox(po)->x();
- }
- right.setValue(Fixed, staticPosition);
- }
- }
+ computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, containerDirection);
/*-----------------------------------------------------------------------*\
* 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
* or 'margin-right' with '0'.
\*-----------------------------------------------------------------------*/
- if (left.isAuto() || right.isAuto()) {
- if (marginLeft.isAuto())
- marginLeft.setValue(Fixed, 0);
- if (marginRight.isAuto())
- marginRight.setValue(Fixed, 0);
+ if (logicalLeft.isAuto() || logicalRight.isAuto()) {
+ if (marginLogicalLeft.isAuto())
+ marginLogicalLeft.setValue(Fixed, 0);
+ if (marginLogicalRight.isAuto())
+ marginLogicalRight.setValue(Fixed, 0);
}
/*-----------------------------------------------------------------------*\
@@ -2816,28 +2870,28 @@ void RenderBox::computePositionedLogicalWidthReplaced()
* ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
* 'margin-right' ('margin-left').
\*-----------------------------------------------------------------------*/
- int leftValue = 0;
- int rightValue = 0;
+ int logicalLeftValue = 0;
+ int logicalRightValue = 0;
- if (marginLeft.isAuto() && marginRight.isAuto()) {
+ if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
// 'left' and 'right' cannot be 'auto' due to step 3
- ASSERT(!(left.isAuto() && right.isAuto()));
+ ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
- leftValue = left.calcValue(containerWidth);
- rightValue = right.calcValue(containerWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
- int difference = availableSpace - (leftValue + rightValue);
+ int difference = availableSpace - (logicalLeftValue + logicalRightValue);
if (difference > 0) {
- m_marginLeft = difference / 2; // split the difference
- m_marginRight = difference - m_marginLeft; // account for odd valued differences
+ marginLogicalLeftAlias = difference / 2; // split the difference
+ marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
} else {
// see FIXME 1
if (containerDirection == LTR) {
- m_marginLeft = 0;
- m_marginRight = difference; // will be negative
+ marginLogicalLeftAlias = 0;
+ marginLogicalRightAlias = difference; // will be negative
} else {
- m_marginLeft = difference; // will be negative
- m_marginRight = 0;
+ marginLogicalLeftAlias = difference; // will be negative
+ marginLogicalRightAlias = 0;
}
}
@@ -2845,40 +2899,40 @@ void RenderBox::computePositionedLogicalWidthReplaced()
* 5. If at this point there is an 'auto' left, solve the equation for
* that value.
\*-----------------------------------------------------------------------*/
- } else if (left.isAuto()) {
- m_marginLeft = marginLeft.calcValue(containerWidth);
- m_marginRight = marginRight.calcValue(containerWidth);
- rightValue = right.calcValue(containerWidth);
+ } else if (logicalLeft.isAuto()) {
+ marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
+ logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
// Solve for 'left'
- leftValue = availableSpace - (rightValue + m_marginLeft + m_marginRight);
- } else if (right.isAuto()) {
- m_marginLeft = marginLeft.calcValue(containerWidth);
- m_marginRight = marginRight.calcValue(containerWidth);
- leftValue = left.calcValue(containerWidth);
+ logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
+ } else if (logicalRight.isAuto()) {
+ marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
// Solve for 'right'
- rightValue = availableSpace - (leftValue + m_marginLeft + m_marginRight);
- } else if (marginLeft.isAuto()) {
- m_marginRight = marginRight.calcValue(containerWidth);
- leftValue = left.calcValue(containerWidth);
- rightValue = right.calcValue(containerWidth);
+ logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
+ } else if (marginLogicalLeft.isAuto()) {
+ marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
// Solve for 'margin-left'
- m_marginLeft = availableSpace - (leftValue + rightValue + m_marginRight);
- } else if (marginRight.isAuto()) {
- m_marginLeft = marginLeft.calcValue(containerWidth);
- leftValue = left.calcValue(containerWidth);
- rightValue = right.calcValue(containerWidth);
+ marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
+ } else if (marginLogicalRight.isAuto()) {
+ marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
+ logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
// Solve for 'margin-right'
- m_marginRight = availableSpace - (leftValue + rightValue + m_marginLeft);
+ marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
} else {
// Nothing is 'auto', just calculate the values.
- m_marginLeft = marginLeft.calcValue(containerWidth);
- m_marginRight = marginRight.calcValue(containerWidth);
- rightValue = right.calcValue(containerWidth);
- leftValue = left.calcValue(containerWidth);
+ marginLogicalLeftAlias = marginLogicalLeft.calcValue(containerLogicalWidth);
+ marginLogicalRightAlias = marginLogicalRight.calcValue(containerLogicalWidth);
+ logicalRightValue = logicalRight.calcValue(containerLogicalWidth);
+ logicalLeftValue = logicalLeft.calcValue(containerLogicalWidth);
}
/*-----------------------------------------------------------------------*\
@@ -2889,14 +2943,17 @@ void RenderBox::computePositionedLogicalWidthReplaced()
\*-----------------------------------------------------------------------*/
// NOTE: It is not necessary to solve for 'right' when the direction is
// LTR because the value is not used.
- int totalWidth = width() + leftValue + rightValue + m_marginLeft + m_marginRight;
- if (totalWidth > containerWidth && (containerDirection == RTL))
- leftValue = containerWidth - (totalWidth - leftValue);
+ int totalLogicalWidth = logicalWidth() + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
+ if (totalLogicalWidth > containerLogicalWidth && (containerDirection == RTL))
+ logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
+ // FIXME: Deal with differing writing modes here. Our offset needs to be in the containing block's coordinate space, so that
+ // can make the result here rather complicated to compute.
+
// Use computed values to calculate the horizontal position.
- // FIXME: This hack is needed to calculate the xPos for a 'rtl' relatively
- // positioned, inline containing block because right now, it is using the xPos
+ // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
+ // positioned, inline containing block because right now, it is using the logical left position
// of the first line box when really it should use the last line box. When
// this is fixed elsewhere, this block should be removed.
if (containerBlock->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
@@ -2904,12 +2961,14 @@ void RenderBox::computePositionedLogicalWidthReplaced()
InlineFlowBox* firstLine = flow->firstLineBox();
InlineFlowBox* lastLine = flow->lastLineBox();
if (firstLine && lastLine && firstLine != lastLine) {
- m_frameRect.setX(leftValue + m_marginLeft + lastLine->borderLogicalLeft() + (lastLine->x() - firstLine->x()));
+ setLogicalLeft(logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft()));
return;
}
}
- m_frameRect.setX(leftValue + m_marginLeft + containerBlock->borderLeft());
+ int logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
+ computeLogicalLeftPositionedOffset(logicalLeftPos, this, logicalWidth(), containerBlock, containerLogicalWidth);
+ setLogicalLeft(logicalLeftPos);
}
void RenderBox::computePositionedLogicalHeightReplaced()
@@ -2923,14 +2982,18 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
- const int containerHeight = containingBlockHeightForPositioned(containerBlock);
+ const int containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
// Variables to solve.
- Length top = style()->top();
- Length bottom = style()->bottom();
- Length marginTop = style()->marginTop();
- Length marginBottom = style()->marginBottom();
+ bool isHorizontal = style()->isHorizontalWritingMode();
+ bool isFlipped = style()->isFlippedBlocksWritingMode();
+ Length marginBefore = style()->marginBefore();
+ Length marginAfter = style()->marginAfter();
+ int& marginBeforeAlias = isHorizontal ? (isFlipped ? m_marginBottom : m_marginTop) : (isFlipped ? m_marginRight: m_marginLeft);
+ int& marginAfterAlias = isHorizontal ? (isFlipped ? m_marginTop : m_marginBottom) : (isFlipped ? m_marginLeft: m_marginRight);
+ Length logicalTop = style()->logicalTop();
+ Length logicalBottom = style()->logicalBottom();
/*-----------------------------------------------------------------------*\
* 1. The used value of 'height' is determined as for inline replaced
@@ -2939,23 +3002,15 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// NOTE: This value of height is FINAL in that the min/max height calculations
// are dealt with in computeReplacedHeight(). This means that the steps to produce
// correct max/min in the non-replaced version, are not necessary.
- setHeight(computeReplacedLogicalHeight() + borderAndPaddingHeight());
- const int availableSpace = containerHeight - height();
+ setLogicalHeight(computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight());
+ const int availableSpace = containerLogicalHeight - logicalHeight();
/*-----------------------------------------------------------------------*\
* 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
* with the element's static position.
\*-----------------------------------------------------------------------*/
// see FIXME 2
- if (top.isAuto() && bottom.isAuto()) {
- // staticY should already have been set through layout of the parent().
- int staticTop = layer()->staticY() - containerBlock->borderTop();
- for (RenderObject* po = parent(); po && po != containerBlock; po = po->parent()) {
- if (po->isBox() && !po->isTableRow())
- staticTop += toRenderBox(po)->y();
- }
- top.setValue(Fixed, staticTop);
- }
+ computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
/*-----------------------------------------------------------------------*\
* 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
@@ -2963,11 +3018,11 @@ void RenderBox::computePositionedLogicalHeightReplaced()
\*-----------------------------------------------------------------------*/
// FIXME: The spec. says that this step should only be taken when bottom is
// auto, but if only top is auto, this makes step 4 impossible.
- if (top.isAuto() || bottom.isAuto()) {
- if (marginTop.isAuto())
- marginTop.setValue(Fixed, 0);
- if (marginBottom.isAuto())
- marginBottom.setValue(Fixed, 0);
+ if (logicalTop.isAuto() || logicalBottom.isAuto()) {
+ if (marginBefore.isAuto())
+ marginBefore.setValue(Fixed, 0);
+ if (marginAfter.isAuto())
+ marginAfter.setValue(Fixed, 0);
}
/*-----------------------------------------------------------------------*\
@@ -2975,59 +3030,59 @@ void RenderBox::computePositionedLogicalHeightReplaced()
* 'auto', solve the equation under the extra constraint that the two
* margins must get equal values.
\*-----------------------------------------------------------------------*/
- int topValue = 0;
- int bottomValue = 0;
+ int logicalTopValue = 0;
+ int logicalBottomValue = 0;
- if (marginTop.isAuto() && marginBottom.isAuto()) {
+ if (marginBefore.isAuto() && marginAfter.isAuto()) {
// 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
- ASSERT(!(top.isAuto() || bottom.isAuto()));
+ ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
- topValue = top.calcValue(containerHeight);
- bottomValue = bottom.calcValue(containerHeight);
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
- int difference = availableSpace - (topValue + bottomValue);
+ int difference = availableSpace - (logicalTopValue + logicalBottomValue);
// NOTE: This may result in negative values.
- m_marginTop = difference / 2; // split the difference
- m_marginBottom = difference - m_marginTop; // account for odd valued differences
+ marginBeforeAlias = difference / 2; // split the difference
+ marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences
/*-----------------------------------------------------------------------*\
* 5. If at this point there is only one 'auto' left, solve the equation
* for that value.
\*-----------------------------------------------------------------------*/
- } else if (top.isAuto()) {
- m_marginTop = marginTop.calcValue(containerHeight);
- m_marginBottom = marginBottom.calcValue(containerHeight);
- bottomValue = bottom.calcValue(containerHeight);
+ } else if (logicalTop.isAuto()) {
+ marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
+ marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
+ logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
// Solve for 'top'
- topValue = availableSpace - (bottomValue + m_marginTop + m_marginBottom);
- } else if (bottom.isAuto()) {
- m_marginTop = marginTop.calcValue(containerHeight);
- m_marginBottom = marginBottom.calcValue(containerHeight);
- topValue = top.calcValue(containerHeight);
+ logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
+ } else if (logicalBottom.isAuto()) {
+ marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
+ marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
// Solve for 'bottom'
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
- } else if (marginTop.isAuto()) {
- m_marginBottom = marginBottom.calcValue(containerHeight);
- topValue = top.calcValue(containerHeight);
- bottomValue = bottom.calcValue(containerHeight);
+ } else if (marginBefore.isAuto()) {
+ marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
// Solve for 'margin-top'
- m_marginTop = availableSpace - (topValue + bottomValue + m_marginBottom);
- } else if (marginBottom.isAuto()) {
- m_marginTop = marginTop.calcValue(containerHeight);
- topValue = top.calcValue(containerHeight);
- bottomValue = bottom.calcValue(containerHeight);
+ marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
+ } else if (marginAfter.isAuto()) {
+ marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
+ logicalBottomValue = logicalBottom.calcValue(containerLogicalHeight);
// Solve for 'margin-bottom'
- m_marginBottom = availableSpace - (topValue + bottomValue + m_marginTop);
+ marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
} else {
// Nothing is 'auto', just calculate the values.
- m_marginTop = marginTop.calcValue(containerHeight);
- m_marginBottom = marginBottom.calcValue(containerHeight);
- topValue = top.calcValue(containerHeight);
+ marginBeforeAlias = marginBefore.calcValue(containerLogicalHeight);
+ marginAfterAlias = marginAfter.calcValue(containerLogicalHeight);
+ logicalTopValue = logicalTop.calcValue(containerLogicalHeight);
// NOTE: It is not necessary to solve for 'bottom' because we don't ever
// use the value.
}
@@ -3041,7 +3096,9 @@ void RenderBox::computePositionedLogicalHeightReplaced()
// or not.
// Use computed values to calculate the vertical position.
- m_frameRect.setY(topValue + m_marginTop + containerBlock->borderTop());
+ int logicalTopPos = logicalTopValue + marginBeforeAlias;
+ computeLogicalTopPositionedOffset(logicalTopPos, this, logicalHeight(), containerBlock, containerLogicalHeight);
+ setLogicalTop(logicalTopPos);
}
IntRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, int* extraWidthToEndOfLine)
@@ -3439,13 +3496,32 @@ IntSize RenderBox::flipForWritingMode(const IntSize& offset) const
return style()->isHorizontalWritingMode() ? IntSize(offset.width(), height() - offset.height()) : IntSize(width() - offset.width(), offset.height());
}
+FloatPoint RenderBox::flipForWritingMode(const FloatPoint& position) const
+{
+ if (!style()->isFlippedBlocksWritingMode())
+ return position;
+ return style()->isHorizontalWritingMode() ? FloatPoint(position.x(), height() - position.y()) : FloatPoint(width() - position.x(), position.y());
+}
+
+void RenderBox::flipForWritingMode(FloatRect& rect) const
+{
+ if (!style()->isFlippedBlocksWritingMode())
+ return;
+
+ if (style()->isHorizontalWritingMode())
+ rect.setY(height() - rect.maxY());
+ else
+ rect.setX(width() - rect.maxX());
+}
+
IntSize RenderBox::locationOffsetIncludingFlipping() const
{
- if (!parent() || !parent()->isBox())
+ RenderBlock* containerBlock = containingBlock();
+ if (!containerBlock || containerBlock == this)
return locationOffset();
IntRect rect(frameRect());
- parentBox()->flipForWritingMode(rect);
+ containerBlock->flipForWritingMode(rect); // FIXME: This is wrong if we are an absolutely positioned object enclosed by a relative-positioned inline.
return IntSize(rect.x(), rect.y());
}