| Index: third_party/WebKit/Source/core/layout/LayoutReplaced.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp b/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp
|
| index 7621248b5e277c8cbf02522cb478a92fcb16eab5..6bb54e15e914b155eab4f15610e83bcf929e3a09 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutReplaced.cpp
|
| @@ -27,6 +27,7 @@
|
| #include "core/layout/LayoutAnalyzer.h"
|
| #include "core/layout/LayoutBlock.h"
|
| #include "core/layout/LayoutImage.h"
|
| +#include "core/layout/LayoutInline.h"
|
| #include "core/layout/LayoutView.h"
|
| #include "core/paint/PaintInfo.h"
|
| #include "core/paint/PaintLayer.h"
|
| @@ -210,6 +211,304 @@ void LayoutReplaced::computeAspectRatioInformationForLayoutBox(LayoutBox* conten
|
| }
|
| }
|
|
|
| +void LayoutReplaced::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues) const
|
| +{
|
| + // The following is based off of the W3C Working Draft from April 11, 2006 of
|
| + // CSS 2.1: Section 10.3.8 "Absolutely positioned, replaced elements"
|
| + // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-width>
|
| + // (block-style-comments in this function correspond to text from the spec and
|
| + // the numbers correspond to numbers in spec)
|
| +
|
| + // We don't use containingBlock(), since we may be positioned by an enclosing
|
| + // relative positioned inline.
|
| + const LayoutBoxModelObject* containerBlock = toLayoutBoxModelObject(container());
|
| +
|
| + const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
|
| + const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
|
| +
|
| + // To match WinIE, in quirks mode use the parent's 'direction' property
|
| + // instead of the the container block's.
|
| + TextDirection containerDirection = containerBlock->style()->direction();
|
| +
|
| + // Variables to solve.
|
| + bool isHorizontal = isHorizontalWritingMode();
|
| + Length logicalLeft = style()->logicalLeft();
|
| + Length logicalRight = style()->logicalRight();
|
| + Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
|
| + Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
|
| + LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
|
| + LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 1. The used value of 'width' is determined as for inline replaced
|
| + * elements.
|
| + \*-----------------------------------------------------------------------*/
|
| + // 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.
|
| + computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();
|
| +
|
| + const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent;
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 2. If both 'left' and 'right' have the value 'auto', then if 'direction'
|
| + * of the containing block is 'ltr', set 'left' to the static position;
|
| + * else if 'direction' is 'rtl', set 'right' to the static position.
|
| + \*-----------------------------------------------------------------------*/
|
| + // see FIXME 1
|
| + computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth);
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
|
| + * or 'margin-right' with '0'.
|
| + \*-----------------------------------------------------------------------*/
|
| + if (logicalLeft.isAuto() || logicalRight.isAuto()) {
|
| + if (marginLogicalLeft.isAuto())
|
| + marginLogicalLeft.setValue(Fixed, 0);
|
| + if (marginLogicalRight.isAuto())
|
| + marginLogicalRight.setValue(Fixed, 0);
|
| + }
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 4. If at this point both 'margin-left' and 'margin-right' are still
|
| + * 'auto', solve the equation under the extra constraint that the two
|
| + * margins must get equal values, unless this would make them negative,
|
| + * in which case when the direction of the containing block is 'ltr'
|
| + * ('rtl'), set 'margin-left' ('margin-right') to zero and solve for
|
| + * 'margin-right' ('margin-left').
|
| + \*-----------------------------------------------------------------------*/
|
| + LayoutUnit logicalLeftValue = 0;
|
| + LayoutUnit logicalRightValue = 0;
|
| +
|
| + if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
|
| + // 'left' and 'right' cannot be 'auto' due to step 3
|
| + ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
|
| +
|
| + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
|
| + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
|
| +
|
| + LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
|
| + if (difference > 0) {
|
| + marginLogicalLeftAlias = difference / 2; // split the difference
|
| + marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
|
| + } else {
|
| + // Use the containing block's direction rather than the parent block's
|
| + // per CSS 2.1 reference test abspos-replaced-width-margin-000.
|
| + if (containerDirection == LTR) {
|
| + marginLogicalLeftAlias = 0;
|
| + marginLogicalRightAlias = difference; // will be negative
|
| + } else {
|
| + marginLogicalLeftAlias = difference; // will be negative
|
| + marginLogicalRightAlias = 0;
|
| + }
|
| + }
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 5. If at this point there is an 'auto' left, solve the equation for
|
| + * that value.
|
| + \*-----------------------------------------------------------------------*/
|
| + } else if (logicalLeft.isAuto()) {
|
| + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
|
| + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
|
| + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
|
| +
|
| + // Solve for 'left'
|
| + logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
|
| + } else if (logicalRight.isAuto()) {
|
| + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
|
| + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
|
| + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
|
| +
|
| + // Solve for 'right'
|
| + logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
|
| + } else if (marginLogicalLeft.isAuto()) {
|
| + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
|
| + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
|
| + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
|
| +
|
| + // Solve for 'margin-left'
|
| + marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
|
| + } else if (marginLogicalRight.isAuto()) {
|
| + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
|
| + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
|
| + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
|
| +
|
| + // Solve for 'margin-right'
|
| + marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
|
| + } else {
|
| + // Nothing is 'auto', just calculate the values.
|
| + marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth);
|
| + marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth);
|
| + logicalRightValue = valueForLength(logicalRight, containerLogicalWidth);
|
| + logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth);
|
| + // If the containing block is right-to-left, then push the left position as far to the right as possible
|
| + if (containerDirection == RTL) {
|
| + int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias;
|
| + logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
|
| + }
|
| + }
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 6. If at this point the values are over-constrained, ignore the value
|
| + * for either 'left' (in case the 'direction' property of the
|
| + * containing block is 'rtl') or 'right' (in case 'direction' is
|
| + * 'ltr') and solve for that value.
|
| + \*-----------------------------------------------------------------------*/
|
| + // NOTE: Constraints imposed by the width of the containing block and its content have already been accounted for above.
|
| +
|
| + // 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 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->isLayoutInline() && !containerBlock->style()->isLeftToRightDirection()) {
|
| + const LayoutInline* flow = toLayoutInline(containerBlock);
|
| + InlineFlowBox* firstLine = flow->firstLineBox();
|
| + InlineFlowBox* lastLine = flow->lastLineBox();
|
| + if (firstLine && lastLine && firstLine != lastLine) {
|
| + computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
|
| + return;
|
| + }
|
| + }
|
| +
|
| + LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
|
| + computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
|
| + computedValues.m_position = logicalLeftPos;
|
| +}
|
| +
|
| +void LayoutReplaced::computePositionedLogicalHeight(LogicalExtentComputedValues& computedValues) const
|
| +{
|
| + // The following is based off of the W3C Working Draft from April 11, 2006 of
|
| + // CSS 2.1: Section 10.6.5 "Absolutely positioned, replaced elements"
|
| + // <http://www.w3.org/TR/2005/WD-CSS21-20050613/visudet.html#abs-replaced-height>
|
| + // (block-style-comments in this function correspond to text from the spec and
|
| + // the numbers correspond to numbers in spec)
|
| +
|
| + // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
|
| + const LayoutBoxModelObject* containerBlock = toLayoutBoxModelObject(container());
|
| +
|
| + const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
|
| + const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, false);
|
| +
|
| + // Variables to solve.
|
| + Length marginBefore = style()->marginBefore();
|
| + Length marginAfter = style()->marginAfter();
|
| + LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before;
|
| + LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after;
|
| +
|
| + Length logicalTop = style()->logicalTop();
|
| + Length logicalBottom = style()->logicalBottom();
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 1. The used value of 'height' is determined as for inline replaced
|
| + * elements.
|
| + \*-----------------------------------------------------------------------*/
|
| + // 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.
|
| + computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight();
|
| + const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent;
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
|
| + * with the element's static position.
|
| + \*-----------------------------------------------------------------------*/
|
| + // see FIXME 1
|
| + computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 3. If 'bottom' is 'auto', replace any 'auto' on 'margin-top' or
|
| + * 'margin-bottom' with '0'.
|
| + \*-----------------------------------------------------------------------*/
|
| + // 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 (logicalTop.isAuto() || logicalBottom.isAuto()) {
|
| + if (marginBefore.isAuto())
|
| + marginBefore.setValue(Fixed, 0);
|
| + if (marginAfter.isAuto())
|
| + marginAfter.setValue(Fixed, 0);
|
| + }
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 4. If at this point both 'margin-top' and 'margin-bottom' are still
|
| + * 'auto', solve the equation under the extra constraint that the two
|
| + * margins must get equal values.
|
| + \*-----------------------------------------------------------------------*/
|
| + LayoutUnit logicalTopValue = 0;
|
| + LayoutUnit logicalBottomValue = 0;
|
| +
|
| + if (marginBefore.isAuto() && marginAfter.isAuto()) {
|
| + // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
|
| + ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
|
| +
|
| + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
|
| + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
|
| +
|
| + LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
|
| + // NOTE: This may result in negative values.
|
| + 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 (logicalTop.isAuto()) {
|
| + marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
|
| + marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
|
| + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
|
| +
|
| + // Solve for 'top'
|
| + logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
|
| + } else if (logicalBottom.isAuto()) {
|
| + marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
|
| + marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
|
| + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
|
| +
|
| + // Solve for 'bottom'
|
| + // NOTE: It is not necessary to solve for 'bottom' because we don't ever
|
| + // use the value.
|
| + } else if (marginBefore.isAuto()) {
|
| + marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
|
| + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
|
| + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
|
| +
|
| + // Solve for 'margin-top'
|
| + marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
|
| + } else if (marginAfter.isAuto()) {
|
| + marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
|
| + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
|
| + logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight);
|
| +
|
| + // Solve for 'margin-bottom'
|
| + marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
|
| + } else {
|
| + // Nothing is 'auto', just calculate the values.
|
| + marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth);
|
| + marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth);
|
| + logicalTopValue = valueForLength(logicalTop, containerLogicalHeight);
|
| + // NOTE: It is not necessary to solve for 'bottom' because we don't ever
|
| + // use the value.
|
| + }
|
| +
|
| + /*-----------------------------------------------------------------------*\
|
| + * 6. If at this point the values are over-constrained, ignore the value
|
| + * for 'bottom' and solve for that value.
|
| + \*-----------------------------------------------------------------------*/
|
| + // NOTE: It is not necessary to do this step because we don't end up using
|
| + // the value of 'bottom' regardless of whether the values are over-constrained
|
| + // or not.
|
| +
|
| + // Use computed values to calculate the vertical position.
|
| + LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
|
| + computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight);
|
| + computedValues.m_position = logicalTopPos;
|
| +}
|
| +
|
| LayoutRect LayoutReplaced::replacedContentRect(const LayoutSize* overriddenIntrinsicSize) const
|
| {
|
| LayoutRect contentRect = contentBoxRect();
|
|
|