| Index: third_party/WebKit/Source/core/layout/LayoutGrid.cpp
|
| diff --git a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
|
| index 1ac1d2d35d3cc99dcec4971c84193397ebd0a8ea..5faa75f14c9db4936d05196eb92d2fbb88aeafb3 100644
|
| --- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
|
| +++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp
|
| @@ -251,7 +251,44 @@ public:
|
| LayoutUnit& freeSpaceForDirection(GridTrackSizingDirection direction) { return direction == ForColumns ? freeSpaceForColumns : freeSpaceForRows; }
|
|
|
| SizingOperation sizingOperation { TrackSizing };
|
| -
|
| + enum SizingState { ColumnSizingFirstIteration, RowSizingFirstIteration, ColumnSizingSecondIteration, RowSizingSecondIteration};
|
| + SizingState sizingState { ColumnSizingFirstIteration };
|
| + void nextState()
|
| + {
|
| + switch (sizingState) {
|
| + case ColumnSizingFirstIteration:
|
| + sizingState = RowSizingFirstIteration;
|
| + return;
|
| + case RowSizingFirstIteration:
|
| + sizingState = ColumnSizingSecondIteration;
|
| + return;
|
| + case ColumnSizingSecondIteration:
|
| + sizingState = RowSizingSecondIteration;
|
| + return;
|
| + case RowSizingSecondIteration:
|
| + sizingState = ColumnSizingFirstIteration;
|
| + return;
|
| + }
|
| + NOTREACHED();
|
| + sizingState = ColumnSizingFirstIteration;
|
| + }
|
| + bool isValidTransitionForDirection(GridTrackSizingDirection direction)
|
| + {
|
| + switch (sizingState) {
|
| + case ColumnSizingFirstIteration:
|
| + return direction == ForColumns ? true : false;
|
| + case RowSizingFirstIteration:
|
| + return direction == ForRows ? true : false;
|
| + case ColumnSizingSecondIteration:
|
| + if (direction == ForRows)
|
| + sizingState = RowSizingFirstIteration;
|
| + return true;
|
| + case RowSizingSecondIteration:
|
| + return direction == ForRows ? true : false;
|
| + }
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| private:
|
| LayoutUnit freeSpaceForColumns { };
|
| LayoutUnit freeSpaceForRows { };
|
| @@ -355,12 +392,32 @@ LayoutUnit LayoutGrid::computeTrackBasedLogicalHeight(const GridSizingData& sizi
|
|
|
| void LayoutGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit freeSpace)
|
| {
|
| + DCHECK(sizingData.isValidTransitionForDirection(direction));
|
| sizingData.freeSpaceForDirection(direction) = freeSpace - guttersSize(direction, direction == ForRows ? gridRowCount() : gridColumnCount());
|
| sizingData.sizingOperation = TrackSizing;
|
|
|
| LayoutUnit baseSizes, growthLimits;
|
| computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes, growthLimits);
|
| ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData));
|
| + sizingData.nextState();
|
| +}
|
| +
|
| +void LayoutGrid::repeatTracksSizingIfNeeded(GridSizingData& sizingData, LayoutUnit availableSpaceForColumns, LayoutUnit availableSpaceForRows)
|
| +{
|
| + DCHECK(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 LayoutGrid::layoutBlock(bool relayoutChildren)
|
| @@ -393,7 +450,8 @@ void LayoutGrid::layoutBlock(bool relayoutChildren)
|
| // 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);
|
|
|
| // 2- Next, the track sizing algorithm resolves the sizes of the grid rows, using the
|
| // grid column sizes calculated in the previous step.
|
| @@ -408,8 +466,14 @@ void LayoutGrid::layoutBlock(bool relayoutChildren)
|
|
|
| // 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 doesn't affect track sizing though.
|
| if (hasLineIfEmpty())
|
| @@ -687,7 +751,7 @@ double LayoutGrid::findFlexFactorUnitSize(const Vector<GridTrack>& tracks, const
|
|
|
| static bool hasOverrideContainingBlockContentSizeForChild(const LayoutBox& child, GridTrackSizingDirection direction)
|
| {
|
| - return direction == ForColumns ? child.hasOverrideContainingBlockLogicalWidth() : child.overrideContainingBlockContentLogicalHeight();
|
| + return direction == ForColumns ? child.hasOverrideContainingBlockLogicalWidth() : child.hasOverrideContainingBlockLogicalHeight();
|
| }
|
|
|
| static LayoutUnit overrideContainingBlockContentSizeForChild(const LayoutBox& child, GridTrackSizingDirection direction)
|
| @@ -752,6 +816,7 @@ GridTrackSize LayoutGrid::gridTrackSize(GridTrackSizingDirection direction, size
|
| if (minTrackBreadth.hasPercentage() || maxTrackBreadth.hasPercentage()) {
|
| // For the inline axis this only happens when we're computing the intrinsic sizes (AvailableSpaceIndefinite).
|
| // For the block axis we check that the percentage height is resolvable on the first in-flow child.
|
| + // TODO (lajava) This condition for determining whether a size is indefinite or not is not working correctly for orthogonal flows.
|
| if ((sizingOperation == IntrinsicSizeComputation) || (direction == ForRows && firstInFlowChildBox() && !firstInFlowChildBox()->percentageLogicalHeightIsResolvable())) {
|
| if (minTrackBreadth.hasPercentage())
|
| minTrackBreadth = Length(Auto);
|
| @@ -799,9 +864,6 @@ GridTrackSizingDirection LayoutGrid::flowAwareDirectionForChild(const LayoutBox&
|
|
|
| LayoutUnit LayoutGrid::minSizeForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData)
|
| {
|
| - // TODO(svillar): Properly support orthogonal writing mode.
|
| - if (isOrthogonalChild(child))
|
| - return LayoutUnit();
|
| GridTrackSizingDirection childInlineDirection = flowAwareDirectionForChild(child, ForColumns);
|
| bool isRowAxis = direction == childInlineDirection;
|
| const Length& childSize = isRowAxis ? child.styleRef().logicalWidth() : child.styleRef().logicalHeight();
|
| @@ -815,7 +877,7 @@ LayoutUnit LayoutGrid::minSizeForChild(LayoutBox& child, GridTrackSizingDirectio
|
| return child.computeLogicalWidthUsing(MinSize, childMinSize, overrideContainingBlockContentSizeForChild(child, childInlineDirection), this) + marginLogicalWidth;
|
| }
|
|
|
| - if (overrideSizeHasChanged)
|
| + if (overrideSizeHasChanged && (direction != ForColumns || sizingData.sizingOperation != IntrinsicSizeComputation))
|
| child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
|
| child.layoutIfNeeded();
|
| return child.computeLogicalHeightUsing(MinSize, childMinSize, child.intrinsicLogicalHeight()) + child.marginLogicalHeight() + child.scrollbarLogicalHeight();
|
| @@ -833,9 +895,6 @@ bool LayoutGrid::updateOverrideContainingBlockContentSizeForChild(LayoutBox& chi
|
|
|
| LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData)
|
| {
|
| - // FIXME: Properly support orthogonal writing mode.
|
| - if (isOrthogonalChild(child))
|
| - return LayoutUnit();
|
| 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
|
| @@ -848,6 +907,15 @@ LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child, GridTrackSizingDirec
|
| return child.minPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
|
| }
|
|
|
| + // 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) {
|
| + DCHECK(isOrthogonalChild(child));
|
| + return child.logicalHeight() + child.marginLogicalHeight();
|
| + }
|
| +
|
| SubtreeLayoutScope layouter(child);
|
| if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
|
| child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
|
| @@ -856,8 +924,6 @@ LayoutUnit LayoutGrid::minContentForChild(LayoutBox& child, GridTrackSizingDirec
|
|
|
| LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, GridTrackSizingDirection direction, GridSizingData& sizingData)
|
| {
|
| - if (isOrthogonalChild(child))
|
| - return LayoutUnit();
|
| 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
|
| @@ -870,6 +936,15 @@ LayoutUnit LayoutGrid::maxContentForChild(LayoutBox& child, GridTrackSizingDirec
|
| return child.maxPreferredLogicalWidth() + marginIntrinsicLogicalWidthForChild(child);
|
| }
|
|
|
| + // 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) {
|
| + DCHECK(isOrthogonalChild(child));
|
| + return child.logicalHeight() + child.marginLogicalHeight();
|
| + }
|
| +
|
| SubtreeLayoutScope layouter(child);
|
| if (updateOverrideContainingBlockContentSizeForChild(child, childInlineDirection, sizingData))
|
| child.setNeedsLayout(LayoutInvalidationReason::GridChanged);
|
| @@ -1324,10 +1399,13 @@ void LayoutGrid::placeItemsOnGrid()
|
|
|
| Vector<LayoutBox*> autoMajorAxisAutoGridItems;
|
| Vector<LayoutBox*> specifiedMajorAxisAutoGridItems;
|
| + m_hasAnyOrthogonalChild = false;
|
| for (LayoutBox* 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(abs(m_smallestRowStart));
|
| @@ -1611,7 +1689,7 @@ void LayoutGrid::layoutGridItems(GridSizingData& sizingData)
|
| LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChildIncludingAlignmentOffsets(*child, ForRows, sizingData);
|
|
|
| SubtreeLayoutScope layoutScope(*child);
|
| - if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight && child->hasRelativeLogicalHeight()))
|
| + if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || (oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight && (child->hasRelativeLogicalHeight() || isOrthogonalChild(*child))))
|
| layoutScope.setNeedsLayout(child, LayoutInvalidationReason::GridChanged);
|
|
|
| child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
|
| @@ -1779,8 +1857,34 @@ GridSpan LayoutGrid::cachedGridSpan(const LayoutBox& gridItem, GridTrackSizingDi
|
| return direction == ForColumns ? area.columns : area.rows;
|
| }
|
|
|
| +LayoutUnit LayoutGrid::assumedRowsSizeForOrthogonalChild(const LayoutBox& child, SizingOperation sizingOperation) const
|
| +{
|
| + DCHECK(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 LayoutGrid::gridAreaBreadthForChild(const LayoutBox& 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;
|
| @@ -2242,13 +2346,19 @@ LayoutUnit LayoutGrid::translateRTLCoordinate(LayoutUnit coordinate) const
|
|
|
| LayoutPoint LayoutGrid::findChildLogicalPosition(const LayoutBox& child, GridSizingData& sizingData) const
|
| {
|
| + LayoutUnit columnAxisOffset = columnAxisOffsetForChild(child, sizingData);
|
| LayoutUnit rowAxisOffset = rowAxisOffsetForChild(child, sizingData);
|
| // We stored m_columnPosition's data ignoring the direction, hence we might need now
|
| // to translate positions from RTL to LTR, as it's more convenient for painting.
|
| if (!style()->isLeftToRightDirection())
|
| rowAxisOffset = translateRTLCoordinate(rowAxisOffset) - child.logicalWidth();
|
|
|
| - return LayoutPoint(rowAxisOffset, columnAxisOffsetForChild(child, sizingData));
|
| + // "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 LayoutGrid::paintChildren(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
|
|
|