Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(278)

Unified Diff: third_party/WebKit/Source/core/layout/LayoutReplaced.cpp

Issue 1603603002: Move specialized computePositionedLogicalWidth to LayoutReplaced. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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();

Powered by Google App Engine
This is Rietveld 408576698