Title: [203252] trunk/Source/WebCore
Revision
203252
Author
jfernan...@igalia.com
Date
2016-07-14 16:33:13 -0700 (Thu, 14 Jul 2016)

Log Message

[css-grid] Handle min-content/max-content with orthogonal flows
https://bugs.webkit.org/show_bug.cgi?id=159294

Reviewed by Darin Adler.

Currently there is no support for orthogonal flows in many aspects of the
Grid Layout logic.

The Grid sizing algorithm should be adapted to this scenario, hence this
patch focus on the min-content and max-content functions, used to resolve
content based track sizes.

There are still issues related to alignment and sizes using percentages,
but they will be addressed in different patches.

Tests: fast/css-grid-layout/grid-item-positioning-with-orthogonal-flows.html
       fast/css-grid-layout/grid-item-sizing-with-orthogonal-flows.html
       fast/css-grid-layout/grid-item-spanning-and-orthogonal-flows.html
       fast/css-grid-layout/grid-track-sizing-with-orthogonal-flows.html
       fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::computeLogicalWidthInRegion):
* rendering/RenderGrid.cpp:
(WebCore::RenderGrid::GridSizingData::advanceNextState):
(WebCore::RenderGrid::GridSizingData::isValidTransitionForDirection):
(WebCore::RenderGrid::computeTrackSizesForDirection):
(WebCore::RenderGrid::repeatTracksSizingIfNeeded): Added.
(WebCore::RenderGrid::layoutBlock):
(WebCore::RenderGrid::computeIntrinsicLogicalWidths):
(WebCore::RenderGrid::computeIntrinsicLogicalHeight):
(WebCore::hasOverrideContainingBlockContentSizeForChild):
(WebCore::overrideContainingBlockContentSizeForChild):
(WebCore::setOverrideContainingBlockContentSizeForChild):
(WebCore::shouldClearOverrideContainingBlockContentSizeForChild):
(WebCore::RenderGrid::gridTrackSize):
(WebCore::RenderGrid::isOrthogonalChild): Added.
(WebCore::RenderGrid::logicalHeightForChild):
(WebCore::RenderGrid::flowAwareDirectionForChild): Added.
(WebCore::RenderGrid::minSizeForChild):
(WebCore::RenderGrid::updateOverrideContainingBlockContentSizeForChild):
(WebCore::RenderGrid::minContentForChild):
(WebCore::RenderGrid::maxContentForChild):
(WebCore::RenderGrid::placeItemsOnGrid):
(WebCore::RenderGrid::layoutPositionedObject):
(WebCore::RenderGrid::offsetAndBreadthForPositionedChild):
(WebCore::RenderGrid::assumedRowsSizeForOrthogonalChild): Added.
(WebCore::RenderGrid::gridAreaBreadthForChild):
(WebCore::RenderGrid::columnAxisPositionForChild):
(WebCore::RenderGrid::rowAxisPositionForChild):
(WebCore::RenderGrid::findChildLogicalPosition):
* rendering/RenderGrid.h:
(WebCore::RenderGrid::SizingOperation): This enum has been moved to the header file.
(WebCore::RenderGrid::m_hasAnyOrthogonalChild): New class attribute to know if there are any orthogonal grid items.
(WebCore::RenderGrid::updateOverrideContainingBlockContentSizeForChild):
(WebCore::RenderGrid::logicalHeightForChild):
(WebCore::RenderGrid::gridAreaBreadthForChild):
(WebCore::RenderGrid::assumedRowsSizeForOrthogonalChild):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (203251 => 203252)


--- trunk/Source/WebCore/ChangeLog	2016-07-14 23:21:34 UTC (rev 203251)
+++ trunk/Source/WebCore/ChangeLog	2016-07-14 23:33:13 UTC (rev 203252)
@@ -1,3 +1,66 @@
+2016-07-14  Javier Fernandez  <jfernan...@igalia.com>
+
+        [css-grid] Handle min-content/max-content with orthogonal flows
+        https://bugs.webkit.org/show_bug.cgi?id=159294
+
+        Reviewed by Darin Adler.
+
+        Currently there is no support for orthogonal flows in many aspects of the
+        Grid Layout logic.
+
+        The Grid sizing algorithm should be adapted to this scenario, hence this
+        patch focus on the min-content and max-content functions, used to resolve
+        content based track sizes.
+
+        There are still issues related to alignment and sizes using percentages,
+        but they will be addressed in different patches.
+
+        Tests: fast/css-grid-layout/grid-item-positioning-with-orthogonal-flows.html
+               fast/css-grid-layout/grid-item-sizing-with-orthogonal-flows.html
+               fast/css-grid-layout/grid-item-spanning-and-orthogonal-flows.html
+               fast/css-grid-layout/grid-track-sizing-with-orthogonal-flows.html
+               fast/css-grid-layout/grid-track-sizing-with-percentages-and-orthogonal-flows.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::computeLogicalWidthInRegion):
+        * rendering/RenderGrid.cpp:
+        (WebCore::RenderGrid::GridSizingData::advanceNextState):
+        (WebCore::RenderGrid::GridSizingData::isValidTransitionForDirection):
+        (WebCore::RenderGrid::computeTrackSizesForDirection):
+        (WebCore::RenderGrid::repeatTracksSizingIfNeeded): Added.
+        (WebCore::RenderGrid::layoutBlock):
+        (WebCore::RenderGrid::computeIntrinsicLogicalWidths):
+        (WebCore::RenderGrid::computeIntrinsicLogicalHeight):
+        (WebCore::hasOverrideContainingBlockContentSizeForChild):
+        (WebCore::overrideContainingBlockContentSizeForChild):
+        (WebCore::setOverrideContainingBlockContentSizeForChild):
+        (WebCore::shouldClearOverrideContainingBlockContentSizeForChild):
+        (WebCore::RenderGrid::gridTrackSize):
+        (WebCore::RenderGrid::isOrthogonalChild): Added.
+        (WebCore::RenderGrid::logicalHeightForChild):
+        (WebCore::RenderGrid::flowAwareDirectionForChild): Added.
+        (WebCore::RenderGrid::minSizeForChild):
+        (WebCore::RenderGrid::updateOverrideContainingBlockContentSizeForChild):
+        (WebCore::RenderGrid::minContentForChild):
+        (WebCore::RenderGrid::maxContentForChild):
+        (WebCore::RenderGrid::placeItemsOnGrid):
+        (WebCore::RenderGrid::layoutPositionedObject):
+        (WebCore::RenderGrid::offsetAndBreadthForPositionedChild):
+        (WebCore::RenderGrid::assumedRowsSizeForOrthogonalChild): Added.
+        (WebCore::RenderGrid::gridAreaBreadthForChild):
+        (WebCore::RenderGrid::columnAxisPositionForChild):
+        (WebCore::RenderGrid::rowAxisPositionForChild):
+        (WebCore::RenderGrid::findChildLogicalPosition):
+        * rendering/RenderGrid.h:
+        (WebCore::RenderGrid::SizingOperation): This enum has been moved to the header file.
+        (WebCore::RenderGrid::m_hasAnyOrthogonalChild): New class attribute to know if there are any orthogonal grid items.
+        (WebCore::RenderGrid::updateOverrideContainingBlockContentSizeForChild):
+        (WebCore::RenderGrid::logicalHeightForChild):
+        (WebCore::RenderGrid::gridAreaBreadthForChild):
+        (WebCore::RenderGrid::assumedRowsSizeForOrthogonalChild):
+
+
+
 2016-07-14  Chris Dumez  <cdu...@apple.com>
 
         Use emptyString() instead of "" when possible

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (203251 => 203252)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2016-07-14 23:21:34 UTC (rev 203251)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2016-07-14 23:33:13 UTC (rev 203252)
@@ -2408,19 +2408,20 @@
         return;
     }
 
+    LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
+    if (hasPerpendicularContainingBlock)
+        containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
+
     // Width calculations
     if (treatAsReplaced) {
         computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth();
 #if ENABLE(CSS_GRID_LAYOUT)
-    } else if (parent()->isRenderGrid() && style().logicalWidth().isAuto() && style().logicalMinWidth().isAuto() && style().overflowX() == OVISIBLE && containerLogicalWidth < minPreferredLogicalWidth()) {
+    } else if (parent()->isRenderGrid() && style().logicalWidth().isAuto() && style().logicalMinWidth().isAuto() && style().overflowX() == OVISIBLE && containerWidthInInlineDirection < minPreferredLogicalWidth()) {
         // TODO (lajava) Move this logic to the LayoutGrid class.
         // Implied minimum size of Grid items.
-        computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(minPreferredLogicalWidth(), containerLogicalWidth, cb);
+        computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(minPreferredLogicalWidth(), containerWidthInInlineDirection, cb);
 #endif
     } else {
-        LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
-        if (hasPerpendicularContainingBlock)
-            containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
         LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse.logicalWidth(), containerWidthInInlineDirection, cb, region);
         computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region);
     }

Modified: trunk/Source/WebCore/rendering/RenderGrid.cpp (203251 => 203252)


--- trunk/Source/WebCore/rendering/RenderGrid.cpp	2016-07-14 23:21:34 UTC (rev 203251)
+++ trunk/Source/WebCore/rendering/RenderGrid.cpp	2016-07-14 23:33:13 UTC (rev 203252)
@@ -240,6 +240,45 @@
 
     SizingOperation sizingOperation { TrackSizing };
 
+    enum SizingState { ColumnSizingFirstIteration, RowSizingFirstIteration, ColumnSizingSecondIteration, RowSizingSecondIteration};
+    SizingState sizingState { ColumnSizingFirstIteration };
+    void advanceNextState()
+    {
+        switch (sizingState) {
+        case ColumnSizingFirstIteration:
+            sizingState = RowSizingFirstIteration;
+            return;
+        case RowSizingFirstIteration:
+            sizingState = ColumnSizingSecondIteration;
+            return;
+        case ColumnSizingSecondIteration:
+            sizingState = RowSizingSecondIteration;
+            return;
+        case RowSizingSecondIteration:
+            sizingState = ColumnSizingFirstIteration;
+            return;
+        }
+        ASSERT_NOT_REACHED();
+        sizingState = ColumnSizingFirstIteration;
+    }
+    bool isValidTransition(GridTrackSizingDirection direction)
+    {
+        switch (sizingState) {
+        case ColumnSizingFirstIteration:
+            return direction == ForColumns;
+        case RowSizingFirstIteration:
+            return direction == ForRows;
+        case ColumnSizingSecondIteration:
+            if (direction == ForRows)
+                sizingState = RowSizingFirstIteration;
+            return true;
+        case RowSizingSecondIteration:
+            return direction == ForRows;
+        }
+        ASSERT_NOT_REACHED();
+        return false;
+    }
+
 private:
     Optional<LayoutUnit> freeSpaceForColumns;
     Optional<LayoutUnit> freeSpaceForRows;
@@ -357,6 +396,7 @@
 
 void RenderGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit freeSpace)
 {
+    ASSERT(sizingData.isValidTransition(direction));
     LayoutUnit totalGuttersSize = guttersSize(direction, direction == ForRows ? gridRowCount() : gridColumnCount());
     sizingData.setFreeSpaceForDirection(direction, freeSpace - totalGuttersSize);
     sizingData.sizingOperation = TrackSizing;
@@ -364,8 +404,28 @@
     LayoutUnit baseSizes, growthLimits;
     computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes, growthLimits);
     ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData));
+    sizingData.advanceNextState();
 }
 
+void RenderGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows)
+{
+    ASSERT(!m_gridIsDirty);
+    ASSERT(sizingData.sizingState > GridSizingData::RowSizingFirstIteration);
+
+    // In orthogonal flow cases column track's size is determined by using the computed
+    // row track's size, which it was estimated during the first cycle of the sizing
+    // algorithm. Hence we need to repeat computeUsedBreadthOfGridTracks for both,
+    // columns and rows, to determine the final values.
+    // TODO (lajava): orthogonal flows is just one of the cases which may require
+    // a new cycle of the sizing algorithm; there may be more. In addition, not all the
+    // cases with orthogonal flows require this extra cycle; we need a more specific
+    // condition to detect whether child's min-content contribution has changed or not.
+    if (m_hasAnyOrthogonalChild) {
+        computeTrackSizesForDirection(ForColumns, sizingData, availableSpaceForColumns);
+        computeTrackSizesForDirection(ForRows, sizingData, availableSpaceForRows);
+    }
+}
+
 void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
 {
     ASSERT(needsLayout());
@@ -392,7 +452,8 @@
     // properly resolves intrinsic sizes. We cannot do the same for heights though because many code
     // paths inside updateLogicalHeight() require a previous call to setLogicalHeight() to resolve
     // heights properly (like for positioned items for example).
-    computeTrackSizesForDirection(ForColumns, sizingData, availableLogicalWidth());
+    LayoutUnit availableSpaceForColumns = availableLogicalWidth();
+    computeTrackSizesForDirection(ForColumns, sizingData, availableSpaceForColumns);
 
     if (logicalHeightWasIndefinite)
         computeIntrinsicLogicalHeight(sizingData);
@@ -405,9 +466,15 @@
 
     // The above call might have changed the grid's logical height depending on min|max height restrictions.
     // Update the sizes of the rows whose size depends on the logical height (also on definite|indefinite sizes).
+    LayoutUnit availableSpaceForRows = contentLogicalHeight();
     if (logicalHeightWasIndefinite)
-        computeTrackSizesForDirection(ForRows, sizingData, contentLogicalHeight());
+        computeTrackSizesForDirection(ForRows, sizingData, availableSpaceForRows);
 
+    // 3- If the min-content contribution of any grid items have changed based on the row
+    // sizes calculated in step 2, steps 1 and 2 are repeated with the new min-content
+    // contribution (once only).
+    repeatTracksSizingIfNeeded(sizingData, availableSpaceForColumns, availableSpaceForRows);
+
     // Grid container should have the minimum height of a line if it's editable. That does not affect track sizing though.
     if (hasLineIfEmpty()) {
         LayoutUnit minHeightForEmptyLine = borderAndPaddingLogicalHeight()
@@ -720,6 +787,31 @@
     return computeFlexFactorUnitSize(tracks, direction, sizingOperation, flexFactorSum, leftOverSpace, flexibleTracksIndexes);
 }
 
+static bool hasOverrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
+{
+    return direction == ForColumns ? child.hasOverrideContainingBlockLogicalWidth() : child.hasOverrideContainingBlockLogicalHeight();
+}
+
+static Optional<LayoutUnit> overrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
+{
+    return direction == ForColumns ? child.overrideContainingBlockContentLogicalWidth() : child.overrideContainingBlockContentLogicalHeight();
+}
+
+static void setOverrideContainingBlockContentSizeForChild(RenderBox& child, GridTrackSizingDirection direction, Optional<LayoutUnit> size)
+{
+    if (direction == ForColumns)
+        child.setOverrideContainingBlockContentLogicalWidth(size);
+    else
+        child.setOverrideContainingBlockContentLogicalHeight(size);
+}
+
+static bool shouldClearOverrideContainingBlockContentSizeForChild(const RenderBox& child, GridTrackSizingDirection direction)
+{
+    if (direction == ForColumns)
+        return child.hasRelativeLogicalWidth() || child.style().logicalWidth().isIntrinsicOrAuto();
+    return child.hasRelativeLogicalHeight() || child.style().logicalHeight().isIntrinsicOrAuto();
+}
+
 const GridTrackSize& RenderGrid::rawGridTrackSize(GridTrackSizingDirection direction, unsigned translatedIndex) const
 {
     bool isRowAxis = direction == ForColumns;
@@ -758,6 +850,7 @@
     GridLength minTrackBreadth = trackSize.minTrackBreadth();
     GridLength maxTrackBreadth = trackSize.maxTrackBreadth();
 
+    // FIXME: Ensure this condition for determining whether a size is indefinite or not is working correctly for orthogonal flows.
     if (minTrackBreadth.isPercentage() || maxTrackBreadth.isPercentage()) {
         // If the logical width/height of the grid container is indefinite, percentage values are treated as <auto>.
         // For the inline axis this only happens when we're computing the intrinsic sizes (IntrinsicSizeComputation).
@@ -777,22 +870,30 @@
     return GridTrackSize(minTrackBreadth, maxTrackBreadth);
 }
 
-LayoutUnit RenderGrid::logicalHeightForChild(RenderBox& child, GridSizingData& sizingData) const
+bool RenderGrid::isOrthogonalChild(const RenderBox& child) const
 {
-    Optional<LayoutUnit> oldOverrideContainingBlockContentLogicalWidth = child.hasOverrideContainingBlockLogicalWidth() ? child.overrideContainingBlockContentLogicalWidth() : LayoutUnit();
-    LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, sizingData.columnTracks);
-    if (child.hasOverrideLogicalContentHeight() || child.hasRelativeLogicalHeight() || !oldOverrideContainingBlockContentLogicalWidth || oldOverrideContainingBlockContentLogicalWidth.value() != overrideContainingBlockContentLogicalWidth)
+    return child.isHorizontalWritingMode() != isHorizontalWritingMode();
+}
+
+GridTrackSizingDirection RenderGrid::flowAwareDirectionForChild(const RenderBox& child, GridTrackSizingDirection direction) const
+{
+    return !isOrthogonalChild(child) ? direction : (direction == ForColumns ? ForRows : ForColumns);
+}
+
+LayoutUnit RenderGrid::logicalHeightForChild(RenderBox& child) const
+{
+    GridTrackSizingDirection childBlockDirection = flowAwareDirectionForChild(child, ForRows);
+    // If |child| has a relative logical height, we shouldn't let it override its intrinsic height, which is
+    // what we are interested in here. Thus we need to set the block-axis override size to -1 (no possible resolution).
+    if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForRows)) {
+        setOverrideContainingBlockContentSizeForChild(child, childBlockDirection, Nullopt);
         child.setNeedsLayout(MarkOnlyThis);
+    }
 
     // We need to clear the stretched height to properly compute logical height during layout.
     if (child.needsLayout())
         child.clearOverrideLogicalContentHeight();
 
-    // If |child| has a relative logical height, we shouldn't let it override its intrinsic height, which is
-    // what we are interested in here. Thus we need to set the override logical height to Nullopt (no possible resolution).
-    if (child.hasRelativeLogicalHeight())
-        child.setOverrideContainingBlockContentLogicalHeight(Nullopt);
-
     child.layoutIfNeeded();
     return child.logicalHeight() + child.marginLogicalHeight();
 }
@@ -799,51 +900,43 @@
 
 LayoutUnit RenderGrid::minSizeForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
-    // FIXME: Properly support orthogonal writing mode.
-    if (hasOrthogonalWritingMode)
-        return { };
-
-    bool isRowAxis = direction == ForColumns;
+    GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
+    bool isRowAxis = direction == childInlineDirection;
     const Length& childMinSize = isRowAxis ? child.style().logicalMinWidth() : child.style().logicalMinHeight();
     const Length& childSize = isRowAxis ? child.style().logicalWidth() : child.style().logicalHeight();
     if (!childSize.isAuto() || childMinSize.isAuto())
         return minContentForChild(child, direction, sizingData);
 
-    bool overrideLogicalWidthHasChanged = updateOverrideContainingBlockContentLogicalWidthForChild(child, sizingData);
+    bool overrideSizeHasChanged = updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData);
     if (isRowAxis) {
-        LayoutUnit marginLogicalWidth = sizingData.sizingOperation == TrackSizing ? computeMarginLogicalSizeForChild(ForColumns, child) : marginIntrinsicLogicalWidthForChild(child);
-        return child.computeLogicalWidthInRegionUsing(MinSize, childMinSize, child.overrideContainingBlockContentLogicalWidth().valueOr(0), *this, nullptr) + marginLogicalWidth;
+        LayoutUnit marginLogicalWidth = sizingData.sizingOperation == TrackSizing ? computeMarginLogicalSizeForChild(childInlineDirection, child) : marginIntrinsicLogicalWidthForChild(child);
+        return child.computeLogicalWidthInRegionUsing(MinSize, childMinSize, overrideContainingBlockContentSizeForChild(child, childInlineDirection).valueOr(0), *this, nullptr) + marginLogicalWidth;
     }
 
-    if (overrideLogicalWidthHasChanged)
+    if (overrideSizeHasChanged && (direction != ForColumns || sizingData.sizingOperation != IntrinsicSizeComputation))
         child.setNeedsLayout(MarkOnlyThis);
     child.layoutIfNeeded();
     return child.computeLogicalHeightUsing(MinSize, childMinSize, Nullopt).valueOr(0) + child.marginLogicalHeight() + child.scrollbarLogicalHeight();
 }
 
-bool RenderGrid::updateOverrideContainingBlockContentLogicalWidthForChild(RenderBox& child, GridSizingData& sizingData) const
+bool RenderGrid::updateOverrideContainingBlockContentSizeForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
 {
-    LayoutUnit overrideWidth = gridAreaBreadthForChild(child, ForColumns, sizingData.columnTracks);
-    if (child.hasOverrideContainingBlockLogicalWidth() && child.overrideContainingBlockContentLogicalWidth() == overrideWidth)
+    LayoutUnit overrideSize = gridAreaBreadthForChild(child, direction, sizingData);
+    if (hasOverrideContainingBlockContentSizeForChild(child, direction) && overrideContainingBlockContentSizeForChild(child, direction) == overrideSize)
         return false;
 
-    child.setOverrideContainingBlockContentLogicalWidth(overrideWidth);
+    setOverrideContainingBlockContentSizeForChild(child, direction, overrideSize);
     return true;
 }
 
 LayoutUnit RenderGrid::minContentForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
-    // FIXME: Properly support orthogonal writing mode.
-    if (hasOrthogonalWritingMode)
-        return 0;
-
-    if (direction == ForColumns) {
+    GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
+    if (direction == childInlineDirection) {
         // If |child| has a relative logical width, we shouldn't let it override its intrinsic width, which is
         // what we are interested in here. Thus we need to set the override logical width to Nullopt (no possible resolution).
-        if (child.hasRelativeLogicalWidth())
-            child.setOverrideContainingBlockContentLogicalWidth(Nullopt);
+        if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForColumns))
+            setOverrideContainingBlockContentSizeForChild(child, childInlineDirection, Nullopt);
 
         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
@@ -850,23 +943,28 @@
         return child.minPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
     }
 
-    if (updateOverrideContainingBlockContentLogicalWidthForChild(child, sizingData))
+    // All orthogonal flow boxes were already laid out during an early layout phase performed in FrameView::performLayout.
+    // It's true that grid track sizing was not completed at that time and it may afffect the final height of a
+    // grid item, but since it's forbidden to perform a layout during intrinsic width computation, we have to use
+    // that computed height for now.
+    if (direction == ForColumns && sizingData.sizingOperation == IntrinsicSizeComputation) {
+        ASSERT(isOrthogonalChild(child));
+        return child.logicalHeight() + child.marginLogicalHeight();
+    }
+
+    if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
         child.setNeedsLayout(MarkOnlyThis);
-    return logicalHeightForChild(child, sizingData);
+    return logicalHeightForChild(child);
 }
 
 LayoutUnit RenderGrid::maxContentForChild(RenderBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData) const
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
-    // FIXME: Properly support orthogonal writing mode.
-    if (hasOrthogonalWritingMode)
-        return LayoutUnit();
-
-    if (direction == ForColumns) {
+    GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
+    if (direction == childInlineDirection) {
         // If |child| has a relative logical width, we shouldn't let it override its intrinsic width, which is
-        // what we are interested in here. Thus we need to set the override logical width to Nullopt (no possible resolution).
-        if (child.hasRelativeLogicalWidth())
-            child.setOverrideContainingBlockContentLogicalWidth(Nullopt);
+        // what we are interested in here. Thus we need to set the inline-axis override size to -1 (no possible resolution).
+        if (shouldClearOverrideContainingBlockContentSizeForChild(child, ForColumns))
+            setOverrideContainingBlockContentSizeForChild(child, childInlineDirection, Nullopt);
 
         // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
         // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
@@ -873,9 +971,18 @@
         return child.maxPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
     }
 
-    if (updateOverrideContainingBlockContentLogicalWidthForChild(child, sizingData))
+    // All orthogonal flow boxes were already laid out during an early layout phase performed in FrameView::performLayout.
+    // It's true that grid track sizing was not completed at that time and it may afffect the final height of a
+    // grid item, but since it's forbidden to perform a layout during intrinsic width computation, we have to use
+    // that computed height for now.
+    if (direction == ForColumns && sizingData.sizingOperation == IntrinsicSizeComputation) {
+        ASSERT(isOrthogonalChild(child));
+        return child.logicalHeight() + child.marginLogicalHeight();
+    }
+
+    if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
         child.setNeedsLayout(MarkOnlyThis);
-    return logicalHeightForChild(child, sizingData);
+    return logicalHeightForChild(child);
 }
 
 class GridItemWithSpan {
@@ -1329,10 +1436,13 @@
 
     Vector<RenderBox*> autoMajorAxisAutoGridItems;
     Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
+    m_hasAnyOrthogonalChild = false;
     for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
         if (child->isOutOfFlowPositioned())
             continue;
 
+        m_hasAnyOrthogonalChild = m_hasAnyOrthogonalChild || isOrthogonalChild(*child);
+
         GridArea area = cachedGridArea(*child);
         if (!area.rows.isIndefinite())
             area.rows.translate(std::abs(m_smallestRowStart));
@@ -1634,9 +1744,8 @@
 
 void RenderGrid::layoutPositionedObject(RenderBox& child, bool relayoutChildren, bool fixedPositionObjectsOnly)
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
     // FIXME: Properly support orthogonal writing mode.
-    if (!hasOrthogonalWritingMode) {
+    if (!isOrthogonalChild(child)) {
         LayoutUnit columnOffset = LayoutUnit();
         LayoutUnit columnBreadth = LayoutUnit();
         offsetAndBreadthForPositionedChild(child, ForColumns, columnOffset, columnBreadth);
@@ -1661,7 +1770,7 @@
 
 void RenderGrid::offsetAndBreadthForPositionedChild(const RenderBox& child, GridTrackSizingDirection direction, LayoutUnit& offset, LayoutUnit& breadth)
 {
-    ASSERT(child.isHorizontalWritingMode() == isHorizontalWritingMode());
+    ASSERT(!isOrthogonalChild(child));
     bool isRowAxis = direction == ForColumns;
 
     unsigned autoRepeatCount = autoRepeatCountForDirection(direction);
@@ -1750,8 +1859,35 @@
     return direction == ForColumns ? area.columns : area.rows;
 }
 
-LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox& child, GridTrackSizingDirection direction, const Vector<GridTrack>& tracks) const
+LayoutUnit RenderGrid::assumedRowsSizeForOrthogonalChild(const RenderBox& child, SizingOperation sizingOperation) const
 {
+    ASSERT(isOrthogonalChild(child));
+    const GridSpan& span = cachedGridSpan(child, ForRows);
+    LayoutUnit gridAreaSize;
+    bool gridAreaIsIndefinite = false;
+    LayoutUnit containingBlockAvailableSize = containingBlockLogicalHeightForContent(ExcludeMarginBorderPadding);
+    for (auto trackPosition : span) {
+        const GridLength& maxTrackSize = gridTrackSize(ForRows, trackPosition, sizingOperation).maxTrackBreadth();
+        if (maxTrackSize.isContentSized() || maxTrackSize.isFlex())
+            gridAreaIsIndefinite = true;
+        else
+            gridAreaSize += valueForLength(maxTrackSize.length(), containingBlockAvailableSize);
+    }
+
+    gridAreaSize += guttersSize(ForRows, span.integerSpan());
+
+    return gridAreaIsIndefinite ? std::max(child.maxPreferredLogicalWidth(), gridAreaSize) : gridAreaSize;
+}
+
+LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox& child, GridTrackSizingDirection direction, const GridSizingData& sizingData) const
+{
+    // To determine the column track's size based on an orthogonal grid item we need it's logical height, which
+    // may depend on the row track's size. It's possible that the row tracks sizing logic has not been performed yet,
+    // so we will need to do an estimation.
+    if (direction == ForRows && sizingData.sizingState == GridSizingData::ColumnSizingFirstIteration)
+        return assumedRowsSizeForOrthogonalChild(child, sizingData.sizingOperation);
+
+    const Vector<GridTrack>& tracks = direction == ForColumns ? sizingData.columnTracks : sizingData.rowTracks;
     const GridSpan& span = cachedGridSpan(child, direction);
     LayoutUnit gridAreaBreadth = 0;
     for (auto trackPosition : span)
@@ -1958,7 +2094,6 @@
 
 GridAxisPosition RenderGrid::columnAxisPositionForChild(const RenderBox& child) const
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
     bool hasSameWritingMode = child.style().writingMode() == style().writingMode();
 
     switch (child.style().resolvedAlignSelf(style(), selfAlignmentNormalBehavior).position()) {
@@ -1966,12 +2101,12 @@
         // If orthogonal writing-modes, this computes to 'start'.
         // FIXME: grid track sizing and positioning do not support orthogonal modes yet.
         // self-start is based on the child's block axis direction. That's why we need to check against the grid container's block flow.
-        return (hasOrthogonalWritingMode || hasSameWritingMode) ? GridAxisStart : GridAxisEnd;
+        return (isOrthogonalChild(child) || hasSameWritingMode) ? GridAxisStart : GridAxisEnd;
     case ItemPositionSelfEnd:
         // If orthogonal writing-modes, this computes to 'end'.
         // FIXME: grid track sizing and positioning do not support orthogonal modes yet.
         // self-end is based on the child's block axis direction. That's why we need to check against the grid container's block flow.
-        return (hasOrthogonalWritingMode || hasSameWritingMode) ? GridAxisEnd : GridAxisStart;
+        return (isOrthogonalChild(child) || hasSameWritingMode) ? GridAxisEnd : GridAxisStart;
     case ItemPositionLeft:
         // The alignment axis (column axis) and the inline axis are parallell in
         // orthogonal writing mode. Otherwise this this is equivalent to 'start'.
@@ -1981,7 +2116,7 @@
         // The alignment axis (column axis) and the inline axis are parallell in
         // orthogonal writing mode. Otherwise this this is equivalent to 'start'.
         // FIXME: grid track sizing and positioning do not support orthogonal modes yet.
-        return hasOrthogonalWritingMode ? GridAxisEnd : GridAxisStart;
+        return isOrthogonalChild(child) ? GridAxisEnd : GridAxisStart;
     case ItemPositionCenter:
         return GridAxisCenter;
     case ItemPositionFlexStart: // Only used in flex layout, otherwise equivalent to 'start'.
@@ -2007,7 +2142,6 @@
 
 GridAxisPosition RenderGrid::rowAxisPositionForChild(const RenderBox& child) const
 {
-    bool hasOrthogonalWritingMode = child.isHorizontalWritingMode() != isHorizontalWritingMode();
     bool hasSameDirection = child.style().direction() == style().direction();
     bool isLTR = style().isLeftToRightDirection();
 
@@ -2016,11 +2150,11 @@
         // For orthogonal writing-modes, this computes to 'start'
         // FIXME: grid track sizing and positioning do not support orthogonal modes yet.
         // self-start is based on the child's direction. That's why we need to check against the grid container's direction.
-        return (hasOrthogonalWritingMode || hasSameDirection) ? GridAxisStart : GridAxisEnd;
+        return (isOrthogonalChild(child) || hasSameDirection) ? GridAxisStart : GridAxisEnd;
     case ItemPositionSelfEnd:
         // For orthogonal writing-modes, this computes to 'start'
         // FIXME: grid track sizing and positioning do not support orthogonal modes yet.
-        return (hasOrthogonalWritingMode || hasSameDirection) ? GridAxisEnd : GridAxisStart;
+        return (isOrthogonalChild(child) || hasSameDirection) ? GridAxisEnd : GridAxisStart;
     case ItemPositionLeft:
         return isLTR ? GridAxisStart : GridAxisEnd;
     case ItemPositionRight:
@@ -2225,6 +2359,7 @@
 
 LayoutPoint RenderGrid::findChildLogicalPosition(const RenderBox& child) const
 {
+    LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child);
     LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child);
     // We stored m_columnPositions's data ignoring the direction, hence we might need now
     // to translate positions from RTL to LTR, as it's more convenient for painting.
@@ -2231,7 +2366,12 @@
     if (!style().isLeftToRightDirection())
         rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - child.logicalWidth();
 
-    return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child));
+    // "In the positioning phase [...] calculations are performed according to the writing mode
+    // of the containing block of the box establishing the orthogonal flow." However, the
+    // resulting LayoutPoint will be used in 'setLogicalPosition' in order to set the child's
+    // logical position, which will only take into account the child's writing-mode.
+    LayoutPoint childLocation(rowAxisOffset, columnAxisOffset);
+    return isOrthogonalChild(child) ? childLocation.transposedPoint() : childLocation;
 }
 
 void RenderGrid::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& forChild, bool usePrintRect)

Modified: trunk/Source/WebCore/rendering/RenderGrid.h (203251 => 203252)


--- trunk/Source/WebCore/rendering/RenderGrid.h	2016-07-14 23:21:34 UTC (rev 203251)
+++ trunk/Source/WebCore/rendering/RenderGrid.h	2016-07-14 23:33:13 UTC (rev 203252)
@@ -103,6 +103,8 @@
     LayoutUnit computeTrackBasedLogicalHeight(const GridSizingData&) const;
     void computeTrackSizesForDirection(GridTrackSizingDirection, GridSizingData&, LayoutUnit freeSpace);
 
+    void repeatTracksSizingIfNeeded(GridSizingData&, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows);
+
     void layoutGridItems(GridSizingData&);
     void populateGridPositionsForDirection(GridSizingData&, GridTrackSizingDirection);
     void clearGrid();
@@ -138,8 +140,8 @@
     const GridTrackSize& rawGridTrackSize(GridTrackSizingDirection, unsigned) const;
     GridTrackSize gridTrackSize(GridTrackSizingDirection, unsigned, SizingOperation) const;
 
-    bool updateOverrideContainingBlockContentLogicalWidthForChild(RenderBox&, GridSizingData&) const;
-    LayoutUnit logicalHeightForChild(RenderBox&, GridSizingData&) const;
+    bool updateOverrideContainingBlockContentSizeForChild(RenderBox&, GridTrackSizingDirection, GridSizingData&) const;
+    LayoutUnit logicalHeightForChild(RenderBox&) const;
     LayoutUnit minSizeForChild(RenderBox&, GridTrackSizingDirection, GridSizingData&) const;
     LayoutUnit minContentForChild(RenderBox&, GridTrackSizingDirection, GridSizingData&) const;
     LayoutUnit maxContentForChild(RenderBox&, GridTrackSizingDirection, GridSizingData&) const;
@@ -153,8 +155,9 @@
     GridSpan cachedGridSpan(const RenderBox&, GridTrackSizingDirection) const;
 
 
-    LayoutUnit gridAreaBreadthForChild(const RenderBox& child, GridTrackSizingDirection, const Vector<GridTrack>&) const;
+    LayoutUnit gridAreaBreadthForChild(const RenderBox& child, GridTrackSizingDirection, const GridSizingData&) const;
     LayoutUnit gridAreaBreadthForChildIncludingAlignmentOffsets(const RenderBox&, GridTrackSizingDirection, const GridSizingData&) const;
+    LayoutUnit assumedRowsSizeForOrthogonalChild(const RenderBox&, SizingOperation) const;
 
     void applyStretchAlignmentToTracksIfNeeded(GridTrackSizingDirection, GridSizingData&);
 
@@ -181,6 +184,9 @@
 
     LayoutUnit translateRTLCoordinate(LayoutUnit) const;
 
+    bool isOrthogonalChild(const RenderBox&) const;
+    GridTrackSizingDirection flowAwareDirectionForChild(const RenderBox&, GridTrackSizingDirection) const;
+
     Vector<Vector<Vector<RenderBox*, 1>>> m_grid;
     Vector<LayoutUnit> m_columnPositions;
     Vector<LayoutUnit> m_rowPositions;
@@ -198,6 +204,8 @@
     unsigned m_autoRepeatColumns { 0 };
     unsigned m_autoRepeatRows { 0 };
 
+    bool m_hasAnyOrthogonalChild;
+
     bool m_gridIsDirty { true };
 };
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to