Title: [295051] trunk/Source/WebCore/layout
- Revision
- 295051
- Author
- za...@apple.com
- Date
- 2022-05-31 06:41:03 -0700 (Tue, 31 May 2022)
Log Message
Add support for margin: auto
https://bugs.webkit.org/show_bug.cgi?id=241111
Reviewed by Antti Koivisto.
Auto margins take up all of the space that they can in their axis.
1. compute the space 'margin: auto' can take
2. distribute it among flex items with 'margin: auto'
3. adjust final top/left with the computed margin
* Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp:
(WebCore::Layout::FlexFormattingContext::computedAutoMarginValueForFlexItems):
(WebCore::Layout::FlexFormattingContext::convertFlexItemsToLogicalSpace):
(WebCore::Layout::FlexFormattingContext::setFlexItemsGeometry):
(WebCore::Layout::FlexFormattingContext::layoutInFlowContentForIntegration):
* Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.h:
Canonical link: https://commits.webkit.org/251146@main
Modified Paths
Diff
Modified: trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp (295050 => 295051)
--- trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp 2022-05-31 13:39:54 UTC (rev 295050)
+++ trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.cpp 2022-05-31 13:41:03 UTC (rev 295051)
@@ -119,8 +119,36 @@
}
}
-FlexLayout::LogicalFlexItems FlexFormattingContext::convertFlexItemsToLogicalSpace()
+std::optional<LayoutUnit> FlexFormattingContext::computedAutoMarginValueForFlexItems(const ConstraintsForFlexContent& constraints)
{
+ auto flexDirection = root().style().flexDirection();
+ auto flexDirectionIsInlineAxis = flexDirection == FlexDirection::Row || flexDirection == FlexDirection::RowReverse;
+ auto availableSpace = flexDirectionIsInlineAxis ? std::make_optional(constraints.horizontal().logicalWidth) : constraints.availableVerticalSpace();
+ if (!availableSpace)
+ return { };
+
+ size_t autoMarginCount = 0;
+ auto logicalWidth = LayoutUnit { };
+
+ for (auto* flexItem = root().firstInFlowChild(); flexItem; flexItem = flexItem->nextInFlowSibling()) {
+ auto& flexItemStyle = flexItem->style();
+ auto hasAutoMarginStart = flexDirectionIsInlineAxis ? flexItemStyle.marginStart().isAuto() : flexItemStyle.marginBefore().isAuto();
+ auto hasAutoMarginEnd = flexDirectionIsInlineAxis ? flexItemStyle.marginEnd().isAuto() : flexItemStyle.marginAfter().isAuto();
+ if (hasAutoMarginStart)
+ ++autoMarginCount;
+ if (hasAutoMarginEnd)
+ ++autoMarginCount;
+
+ auto& flexItemGeometry = formattingState().boxGeometry(*flexItem);
+ logicalWidth += flexDirectionIsInlineAxis ? flexItemGeometry.marginBoxWidth() : flexItemGeometry.marginBoxHeight();
+ }
+ if (autoMarginCount)
+ return std::max(0_lu, *availableSpace - logicalWidth) / autoMarginCount;
+ return { };
+}
+
+FlexLayout::LogicalFlexItems FlexFormattingContext::convertFlexItemsToLogicalSpace(const ConstraintsForFlexContent& constraints)
+{
struct FlexItem {
FlexRect marginRect;
int logicalOrder { 0 };
@@ -129,6 +157,7 @@
auto& formattingState = this->formattingState();
Vector<FlexItem> flexItemList;
auto flexItemsNeedReordering = false;
+ auto autoMarginValue = computedAutoMarginValueForFlexItems(constraints);
auto convertVisualToLogical = [&] {
auto direction = root().style().flexDirection();
@@ -136,22 +165,39 @@
for (auto* flexItem = root().firstInFlowChild(); flexItem; flexItem = flexItem->nextInFlowSibling()) {
auto& flexItemGeometry = formattingState.boxGeometry(*flexItem);
+ auto& flexItemStyle = flexItem->style();
auto logicalSize = LayoutSize { };
switch (direction) {
case FlexDirection::Row:
- case FlexDirection::RowReverse:
+ case FlexDirection::RowReverse: {
+ auto hasAutoMarginStart = flexItemStyle.marginStart().isAuto();
+ auto hasAutoMarginEnd = flexItemStyle.marginEnd().isAuto();
+ if (autoMarginValue && (hasAutoMarginStart || hasAutoMarginEnd)) {
+ auto horizontalMargin = flexItemGeometry.horizontalMargin();
+ horizontalMargin = { hasAutoMarginStart ? *autoMarginValue : horizontalMargin.start, hasAutoMarginEnd ? *autoMarginValue : horizontalMargin.end };
+ flexItemGeometry.setHorizontalMargin(horizontalMargin);
+ }
logicalSize = { flexItemGeometry.marginBoxWidth(), flexItemGeometry.marginBoxHeight() };
break;
+ }
case FlexDirection::Column:
- case FlexDirection::ColumnReverse:
+ case FlexDirection::ColumnReverse: {
+ auto hasAutoMarginBefore = flexItemStyle.marginBefore().isAuto();
+ auto hasAutoMarginAfter = flexItemStyle.marginAfter().isAuto();
+ if (autoMarginValue && (hasAutoMarginBefore || hasAutoMarginAfter)) {
+ auto verticalMargin = flexItemGeometry.verticalMargin();
+ verticalMargin = { hasAutoMarginBefore ? *autoMarginValue : verticalMargin.before, hasAutoMarginAfter ? *autoMarginValue : verticalMargin.after };
+ flexItemGeometry.setVerticalMargin(verticalMargin);
+ }
logicalSize = { flexItemGeometry.marginBoxHeight(), flexItemGeometry.marginBoxWidth() };
break;
+ }
default:
ASSERT_NOT_REACHED();
break;
}
- auto flexItemOrder = flexItem->style().order();
+ auto flexItemOrder = flexItemStyle.order();
flexItemsNeedReordering = flexItemsNeedReordering || flexItemOrder != previousLogicalOrder.value_or(0);
previousLogicalOrder = flexItemOrder;
@@ -186,28 +232,40 @@
auto direction = root().style().flexDirection();
for (auto& logicalFlexItem : logicalFlexItemList) {
auto& flexItemGeometry = formattingState.boxGeometry(*logicalFlexItem.layoutBox);
- auto topLeft = LayoutPoint { };
+ auto borderBoxTopLeft = LayoutPoint { };
switch (direction) {
case FlexDirection::Row:
- topLeft = { constraints.horizontal().logicalLeft + logicalFlexItem.marginRect.left(), constraints.logicalTop() + logicalFlexItem.marginRect.top() };
+ borderBoxTopLeft = {
+ constraints.horizontal().logicalLeft + logicalFlexItem.marginRect.left() + flexItemGeometry.marginStart(),
+ constraints.logicalTop() + logicalFlexItem.marginRect.top()
+ };
break;
case FlexDirection::RowReverse:
- topLeft = { constraints.horizontal().logicalRight() - logicalFlexItem.marginRect.right(), constraints.logicalTop() + logicalFlexItem.marginRect.top() };
+ borderBoxTopLeft = {
+ constraints.horizontal().logicalRight() - logicalFlexItem.marginRect.right() + flexItemGeometry.marginStart(),
+ constraints.logicalTop() + logicalFlexItem.marginRect.top()
+ };
break;
case FlexDirection::Column: {
auto flippedTopLeft = logicalFlexItem.marginRect.topLeft().transposedPoint();
- topLeft = { constraints.horizontal().logicalLeft + flippedTopLeft.x(), constraints.logicalTop() + flippedTopLeft.y() };
+ borderBoxTopLeft = {
+ constraints.horizontal().logicalLeft + flippedTopLeft.x(),
+ constraints.logicalTop() + flippedTopLeft.y() + flexItemGeometry.marginBefore()
+ };
break;
}
case FlexDirection::ColumnReverse:
- topLeft = { constraints.horizontal().logicalLeft + logicalFlexItem.marginRect.top(), constraints.logicalTop() + logicalWidth - logicalFlexItem.marginRect.right() };
+ borderBoxTopLeft = {
+ constraints.horizontal().logicalLeft + logicalFlexItem.marginRect.top(),
+ constraints.logicalTop() + logicalWidth - logicalFlexItem.marginRect.right() + flexItemGeometry.marginBefore()
+ };
break;
default:
ASSERT_NOT_REACHED();
break;
}
- flexItemGeometry.setLogicalTopLeft(topLeft);
+ flexItemGeometry.setLogicalTopLeft(borderBoxTopLeft);
if (direction == FlexDirection::Row || direction == FlexDirection::RowReverse) {
flexItemGeometry.setContentBoxWidth(logicalFlexItem.marginRect.width() - flexItemGeometry.horizontalMarginBorderAndPadding());
flexItemGeometry.setContentBoxHeight(logicalFlexItem.marginRect.height() - flexItemGeometry.verticalMarginBorderAndPadding());
@@ -221,7 +279,7 @@
void FlexFormattingContext::layoutInFlowContentForIntegration(const ConstraintsForInFlowContent& constraints)
{
auto flexConstraints = downcast<ConstraintsForFlexContent>(constraints);
- auto logicalFlexItems = convertFlexItemsToLogicalSpace();
+ auto logicalFlexItems = convertFlexItemsToLogicalSpace(flexConstraints);
auto flexLayout = FlexLayout { formattingState(), root().style() };
flexLayout.layout(flexConstraints, logicalFlexItems);
setFlexItemsGeometry(logicalFlexItems, flexConstraints);
Modified: trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.h (295050 => 295051)
--- trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.h 2022-05-31 13:39:54 UTC (rev 295050)
+++ trunk/Source/WebCore/layout/formattingContexts/flex/FlexFormattingContext.h 2022-05-31 13:41:03 UTC (rev 295051)
@@ -58,9 +58,11 @@
void sizeAndPlaceFlexItems(const ConstraintsForFlexContent&);
void computeIntrinsicWidthConstraintsForFlexItems();
- FlexLayout::LogicalFlexItems convertFlexItemsToLogicalSpace();
+ FlexLayout::LogicalFlexItems convertFlexItemsToLogicalSpace(const ConstraintsForFlexContent&);
void setFlexItemsGeometry(const FlexLayout::LogicalFlexItems&, const ConstraintsForFlexContent&);
+ std::optional<LayoutUnit> computedAutoMarginValueForFlexItems(const ConstraintsForFlexContent&);
+
const FlexFormattingState& formattingState() const { return downcast<FlexFormattingState>(FormattingContext::formattingState()); }
FlexFormattingState& formattingState() { return downcast<FlexFormattingState>(FormattingContext::formattingState()); }
Modified: trunk/Source/WebCore/layout/integration/flex/LayoutIntegrationFlexLayout.cpp (295050 => 295051)
--- trunk/Source/WebCore/layout/integration/flex/LayoutIntegrationFlexLayout.cpp 2022-05-31 13:39:54 UTC (rev 295050)
+++ trunk/Source/WebCore/layout/integration/flex/LayoutIntegrationFlexLayout.cpp 2022-05-31 13:41:03 UTC (rev 295051)
@@ -148,6 +148,11 @@
renderer.setLocation(borderBox.topLeft());
renderer.setWidth(borderBox.width());
renderer.setHeight(borderBox.height());
+
+ renderer.setMarginStart(flexItemGeometry.marginStart());
+ renderer.setMarginEnd(flexItemGeometry.marginEnd());
+ renderer.setMarginBefore(flexItemGeometry.marginBefore());
+ renderer.setMarginAfter(flexItemGeometry.marginAfter());
}
}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes