WebKit Bugzilla
Attachment 342395 Details for
Bug 186474
: [LFC] Merge left, right, width and horizontal margin computation for out-of-flow non-replaced elements
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186474-20180610153334.patch (text/plain), 20.73 KB, created by
zalan
on 2018-06-10 15:33:35 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2018-06-10 15:33:35 PDT
Size:
20.73 KB
patch
obsolete
>Subversion Revision: 232661 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index e744f9b27e8f6051078c157cef823c5b8bfe23fa..74a05abe55b03363382ca9d847dd28d307da1e97 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,26 @@ >+2018-06-10 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC] Merge left, right, width and horizontal margin computation for out-of-flow non-replaced elements >+ https://bugs.webkit.org/show_bug.cgi?id=186474 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implement https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-width >+ (10.3.7 Absolutely positioned, non-replaced elements) >+ >+ * layout/FormattingContext.cpp: >+ (WebCore::Layout::FormattingContext::computeOutOfFlowHorizontalGeometry const): >+ (WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const): >+ (WebCore::Layout::FormattingContext::computeOutOfFlowWidthAndMargin const): Deleted. >+ * layout/FormattingContext.h: >+ * layout/FormattingContextGeometry.cpp: >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry): >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedHorizontalGeometry): >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowHorizontalGeometry): >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedWidthAndMargin): Deleted. >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedWidthAndMargin): Deleted. >+ (WebCore::Layout::FormattingContext::Geometry::outOfFlowWidthAndMargin): Deleted. >+ > 2018-06-09 Zalan Bujtas <zalan@apple.com> > > [LFC] MarginCollapse functions should be able to resolve non-fixed margin values >diff --git a/Source/WebCore/layout/FormattingContext.cpp b/Source/WebCore/layout/FormattingContext.cpp >index 51c2623b3c6c930f7c5c6f58805970eafb403960..b946dcd4afbdcfd5c419cae22a2eae2d6bdcb6c8 100644 >--- a/Source/WebCore/layout/FormattingContext.cpp >+++ b/Source/WebCore/layout/FormattingContext.cpp >@@ -68,11 +68,13 @@ void FormattingContext::computeFloatingWidthAndMargin(LayoutContext& layoutConte > displayBox.setHorizontalMargin(widthAndMargin.margin); > } > >-void FormattingContext::computeOutOfFlowWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const >+void FormattingContext::computeOutOfFlowHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const > { >- auto widthAndMargin = Geometry::outOfFlowWidthAndMargin(layoutContext, layoutBox); >- displayBox.setWidth(widthAndMargin.width); >- displayBox.setHorizontalMargin(widthAndMargin.margin); >+ auto horizontalGeometry = Geometry::outOfFlowHorizontalGeometry(layoutContext, layoutBox); >+ displayBox.setLeft(horizontalGeometry.left); >+ displayBox.setWidth(horizontalGeometry.width); >+ ASSERT(horizontalGeometry.left + horizontalGeometry.width == horizontalGeometry.right); >+ displayBox.setHorizontalMargin(horizontalGeometry.margin); > } > > void FormattingContext::computeOutOfFlowHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const >@@ -115,7 +117,7 @@ void FormattingContext::layoutOutOfFlowDescendants(LayoutContext& layoutContext) > // of a hypothetical box that would have been the first box of the element if its specified 'position' value had been 'static' and > // its specified 'float' had been 'none' and its specified 'clear' had been 'none'. > computeStaticPosition(layoutContext, layoutBox, displayBox); >- computeOutOfFlowWidthAndMargin(layoutContext, layoutBox, displayBox); >+ computeOutOfFlowHorizontalGeometry(layoutContext, layoutBox, displayBox); > > ASSERT(layoutBox.establishesFormattingContext()); > auto formattingContext = layoutContext.formattingContext(layoutBox); >diff --git a/Source/WebCore/layout/FormattingContext.h b/Source/WebCore/layout/FormattingContext.h >index 9d230f21888d0b65aa4520e3ea1f6c7a3da5e03b..1c06045e639c4a98d5710f9a2085b6b9906ab2f0 100644 >--- a/Source/WebCore/layout/FormattingContext.h >+++ b/Source/WebCore/layout/FormattingContext.h >@@ -91,8 +91,15 @@ protected: > Display::Box::VerticalEdges margin; > }; > >+ struct HorizontalGeometry { >+ LayoutUnit left; >+ LayoutUnit right; >+ LayoutUnit width; >+ Display::Box::HorizontalEdges margin; >+ }; >+ > static HeightAndMargin outOfFlowHeightAndMargin(LayoutContext&, const Box&); >- static WidthAndMargin outOfFlowWidthAndMargin(LayoutContext&, const Box&); >+ static HorizontalGeometry outOfFlowHorizontalGeometry(LayoutContext&, const Box&); > > static HeightAndMargin floatingHeightAndMargin(LayoutContext&, const Box&); > static WidthAndMargin floatingWidthAndMargin(LayoutContext&, const Box&); >@@ -111,10 +118,10 @@ protected: > > private: > static HeightAndMargin outOfFlowReplacedHeightAndMargin(LayoutContext&, const Box&); >- static WidthAndMargin outOfFlowReplacedWidthAndMargin(LayoutContext&, const Box&); >+ static HorizontalGeometry outOfFlowReplacedHorizontalGeometry(LayoutContext&, const Box&); > > static HeightAndMargin outOfFlowNonReplacedHeightAndMargin(LayoutContext&, const Box&); >- static WidthAndMargin outOfFlowNonReplacedWidthAndMargin(LayoutContext&, const Box&); >+ static HorizontalGeometry outOfFlowNonReplacedHorizontalGeometry(LayoutContext&, const Box&); > > static HeightAndMargin floatingReplacedHeightAndMargin(LayoutContext&, const Box&); > static WidthAndMargin floatingReplacedWidthAndMargin(LayoutContext&, const Box&); >@@ -126,7 +133,7 @@ protected: > private: > void computeOutOfFlowPosition(LayoutContext&, const Box&, Display::Box&) const; > void computeOutOfFlowHeight(LayoutContext&, const Box&, Display::Box&) const; >- void computeOutOfFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const; >+ void computeOutOfFlowHorizontalGeometry(LayoutContext&, const Box&, Display::Box&) const; > > WeakPtr<Box> m_root; > }; >diff --git a/Source/WebCore/layout/FormattingContextGeometry.cpp b/Source/WebCore/layout/FormattingContextGeometry.cpp >index a40c43d07b23aeadd755079fc1ac022c2f63efd0..be770452b1f91685c023bc38d7ef2a9b228fe39a 100644 >--- a/Source/WebCore/layout/FormattingContextGeometry.cpp >+++ b/Source/WebCore/layout/FormattingContextGeometry.cpp >@@ -128,7 +128,7 @@ FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfF > return { computedHeightValue, { } }; > } > >-FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowNonReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox) >+FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowNonReplacedHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox) > { > ASSERT(layoutBox.isOutOfFlowPositioned() && !layoutBox.replaced()); > >@@ -140,7 +140,15 @@ FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFl > // If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. > // Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static > // position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below. >- >+ // >+ // If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values, >+ // unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and >+ // solve for 'margin-right' ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto', solve the equation for that value. >+ // If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' >+ // (in case 'direction' is 'ltr') and solve for that value. >+ // >+ // Otherwise, set 'auto' values for 'margin-left' and 'margin-right' to 0, and pick the one of the following six rules that applies. >+ // > // 1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left' > // 2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if the 'direction' property of the element establishing the static-position > // containing block is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position. >@@ -149,41 +157,144 @@ FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFl > // 4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left' > // 5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width' > // 6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right' >- auto& style = layoutBox.style(); >- auto left = style.logicalLeft(); >- auto right = style.logicalRight(); >- auto width = style.logicalWidth(); >- >- auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->width(); >- LayoutUnit computedWidthValue; >- >- if (!width.isAuto()) >- computedWidthValue = valueForLength(width, containingBlockWidth); >- else if ((left.isAuto() && right.isAuto()) >- || (left.isAuto() && !right.isAuto()) >- || (!left.isAuto() && right.isAuto())) { >- // All auto (#1), #1 and #3 >- computedWidthValue = shrinkToFitWidth(layoutContext, layoutBox); >- } else if (!left.isAuto() && !right.isAuto()) { >- // #5 >- auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox); > >- auto marginLeft = displayBox.marginLeft(); >- auto marginRight = displayBox.marginRight(); >+ auto& style = layoutBox.style(); >+ auto leftLength = style.logicalLeft(); >+ auto rightLength = style.logicalRight(); >+ auto widthLength = style.logicalWidth(); >+ auto marginLeftLength = style.marginLeft(); >+ auto marginRightLength = style.marginRight(); >+ auto horizontalNonCollapsedMarginValue = computedNonCollapsedHorizontalMarginValue(layoutContext, layoutBox); >+ >+ auto& containingBlock = *layoutBox.containingBlock(); >+ auto isLeftToRightDirection = containingBlock.style().isLeftToRightDirection(); >+ auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(containingBlock)->width(); > >- auto paddingLeft = displayBox.paddingLeft(); >- auto paddingRight = displayBox.paddingRight(); >+ auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox); >+ auto paddingLeft = displayBox.paddingLeft(); >+ auto paddingRight = displayBox.paddingRight(); >+ auto borderLeft = displayBox.borderLeft(); >+ auto borderRight = displayBox.borderRight(); >+ >+ std::optional<LayoutUnit> left; >+ std::optional<LayoutUnit> right; >+ std::optional<LayoutUnit> width; >+ std::optional<LayoutUnit> marginLeft; >+ std::optional<LayoutUnit> marginRight; >+ >+ if (leftLength.isAuto() && widthLength.isAuto() && rightLength.isAuto()) { >+ // If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. >+ // Then, if the 'direction' property of the element establishing the static-position containing block is 'ltr' set 'left' to the static >+ // position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below. >+ marginLeft = horizontalNonCollapsedMarginValue.left; >+ marginRight = horizontalNonCollapsedMarginValue.right; >+ >+ if (isLeftToRightDirection) >+ left = displayBox.left(); >+ else >+ right = displayBox.right(); >+ } else if (!leftLength.isAuto() && !widthLength.isAuto() && !rightLength.isAuto()) { >+ // If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values, >+ // unless this would make them negative, in which case when direction of the containing block is 'ltr' ('rtl'), set 'margin-left' ('margin-right') to zero and >+ // solve for 'margin-right' ('margin-left'). If one of 'margin-left' or 'margin-right' is 'auto', solve the equation for that value. >+ // If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is 'rtl') or 'right' >+ // (in case 'direction' is 'ltr') and solve for that value. >+ left = LayoutUnit { leftLength.value() }; >+ right = LayoutUnit { rightLength.value() }; >+ width = LayoutUnit { widthLength.value() }; >+ >+ if (marginLeftLength.isAuto() && marginRightLength.isAuto()) { >+ auto marginLeftAndRight = containingBlockWidth - (*left + borderLeft + paddingLeft + *width + paddingRight + borderRight + *right); >+ if (marginLeftAndRight >= 0) >+ marginLeft = marginRight = marginLeftAndRight / 2; >+ else { >+ if (isLeftToRightDirection) { >+ marginLeft = LayoutUnit { 0 }; >+ marginRight = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *right); >+ } else { >+ marginRight = LayoutUnit { 0 }; >+ marginLeft = containingBlockWidth - (*left + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ } >+ } >+ } else if (marginLeftLength.isAuto()) { >+ marginRight = horizontalNonCollapsedMarginValue.right; >+ marginLeft = containingBlockWidth - (*left + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ // Overconstrained? Ignore right (left). >+ if (*marginLeft < 0) { >+ if (isLeftToRightDirection) >+ marginLeft = containingBlockWidth - (*left + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight); >+ else >+ marginLeft = containingBlockWidth - (borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ } >+ } else if (marginRightLength.isAuto()) { >+ marginLeft = horizontalNonCollapsedMarginValue.left; >+ marginRight = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *right); >+ // Overconstrained? Ignore right (left). >+ if (*marginRight < 0) { >+ if (isLeftToRightDirection) >+ marginRight = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight); >+ else >+ marginRight = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *right); >+ } >+ } >+ } else { >+ // Otherwise, set 'auto' values for 'margin-left' and 'margin-right' to 0, and pick the one of the following six rules that applies. >+ marginLeft = horizontalNonCollapsedMarginValue.left; >+ marginRight = horizontalNonCollapsedMarginValue.right; >+ } > >- auto borderLeft = displayBox.borderLeft(); >- auto borderRight = displayBox.borderRight(); >+ ASSERT(marginLeft); >+ ASSERT(marginRight); > >- computedWidthValue = containingBlockWidth - (left.value() + marginLeft + borderLeft + paddingLeft + paddingRight + borderRight + marginRight + right.value()); >- } else { >- // #2 #4 #6 have width != auto >- ASSERT_NOT_REACHED(); >+ if (leftLength.isAuto() && widthLength.isAuto() && (!rightLength.isAuto() || right)) { >+ // #1 >+ if (!rightLength.isAuto()) { >+ ASSERT(!right); >+ right = LayoutUnit { rightLength.value() }; >+ } >+ width = shrinkToFitWidth(layoutContext, layoutBox); >+ left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ } else if (leftLength.isAuto() && rightLength.isAuto() && !widthLength.isAuto()) { >+ // #2 >+ width = LayoutUnit { widthLength.value() }; >+ if (isLeftToRightDirection) { >+ left = displayBox.left(); >+ right = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight); >+ } else { >+ right = displayBox.right(); >+ left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ } >+ } else if (widthLength.isAuto() && rightLength.isAuto() && (!leftLength.isAuto() || left)) { >+ // #3 >+ if (!leftLength.isAuto()) { >+ ASSERT(!left); >+ left = LayoutUnit { leftLength.value() }; >+ } >+ width = shrinkToFitWidth(layoutContext, layoutBox); >+ right = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight); >+ } else if (leftLength.isAuto() && !widthLength.isAuto() && !rightLength.isAuto()) { >+ // #4 >+ right = LayoutUnit { rightLength.value() }; >+ width = LayoutUnit { widthLength.value() }; >+ left = containingBlockWidth - (*marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight + *right); >+ } else if (widthLength.isAuto() && !leftLength.isAuto() && !rightLength.isAuto()) { >+ // #5 >+ left = LayoutUnit { leftLength.value() }; >+ right = LayoutUnit { rightLength.value() }; >+ width = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + paddingRight + borderRight + *marginRight + *right); >+ } else if (rightLength.isAuto() && !leftLength.isAuto() && !widthLength.isAuto()) { >+ // #6 >+ left = LayoutUnit { leftLength.value() }; >+ width = LayoutUnit { widthLength.value() }; >+ right = containingBlockWidth - (*left + *marginLeft + borderLeft + paddingLeft + *width + paddingRight + borderRight + *marginRight); > } > >- return WidthAndMargin { computedWidthValue, { } }; >+ ASSERT(left); >+ ASSERT(right); >+ ASSERT(width); >+ ASSERT(marginLeft); >+ ASSERT(marginRight); >+ return HorizontalGeometry { *left, *right, *width, { *marginLeft, *marginRight } }; > } > > FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfFlowReplacedHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox) >@@ -195,13 +306,14 @@ FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfF > return inlineReplacedHeightAndMargin(layoutContext, layoutBox); > } > >-FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox) >+FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowReplacedHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox) > { > ASSERT(layoutBox.isOutOfFlowPositioned() && layoutBox.replaced()); > // 10.3.8 Absolutely positioned, replaced elements > // > // The used value of 'width' is determined as for inline replaced elements. >- return inlineReplacedWidthAndMargin(layoutContext, layoutBox); >+ auto widthAndMargin = inlineReplacedWidthAndMargin(layoutContext, layoutBox); >+ return { { }, { }, widthAndMargin.width, widthAndMargin.margin }; > } > > FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::floatingNonReplacedHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox) >@@ -449,13 +561,13 @@ FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfF > return outOfFlowReplacedHeightAndMargin(layoutContext, layoutBox); > } > >-FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox) >+FormattingContext::Geometry::HorizontalGeometry FormattingContext::Geometry::outOfFlowHorizontalGeometry(LayoutContext& layoutContext, const Box& layoutBox) > { > ASSERT(layoutBox.isOutOfFlowPositioned()); > > if (!layoutBox.replaced()) >- return outOfFlowNonReplacedWidthAndMargin(layoutContext, layoutBox); >- return outOfFlowReplacedWidthAndMargin(layoutContext, layoutBox); >+ return outOfFlowNonReplacedHorizontalGeometry(layoutContext, layoutBox); >+ return outOfFlowReplacedHorizontalGeometry(layoutContext, layoutBox); > } > > FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::floatingHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186474
:
342395
|
342406