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 559ff539950feba2497a8a70f9deafaf72a786b3..25183d3f099a07a386920b5d5c01ed574d4be4e4 100644 |
--- a/third_party/WebKit/Source/core/layout/LayoutGrid.cpp |
+++ b/third_party/WebKit/Source/core/layout/LayoutGrid.cpp |
@@ -249,7 +249,46 @@ public: |
enum SizingOperation { TrackSizing, IntrinsicSizeComputation }; |
SizingOperation sizingOperation { TrackSizing }; |
- |
+ enum SizingState { ColumnSizingFirstIteration, RowSizingFirstIteration, ColumnSizingSecondIteration, RowSizingSecondIteration}; |
+ SizingState sizingState { ColumnSizingFirstIteration }; |
+ void stateTransition() |
svillar
2016/06/02 14:39:40
Nit: what about nextState() ?
jfernandez
2016/06/02 21:39:25
Done.
|
+ { |
+ 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; |
+ } |
+#if DCHECK_IS_ON() |
+ 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; |
+ } |
+#endif |
private: |
LayoutUnit freeSpaceForColumns { }; |
LayoutUnit freeSpaceForRows { }; |
@@ -337,12 +376,32 @@ LayoutUnit LayoutGrid::computeTrackBasedLogicalHeight(const GridSizingData& sizi |
void LayoutGrid::computeTrackSizesForDirection(GridTrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit freeSpace) |
{ |
ASSERT(freeSpace >= 0); |
+ DCHECK(sizingData.isValidTransitionForDirection(direction)); |
sizingData.freeSpaceForDirection(direction) = freeSpace - guttersSize(direction, direction == ForRows ? gridRowCount() : gridColumnCount()); |
sizingData.sizingOperation = GridSizingData::TrackSizing; |
LayoutUnit baseSizes, growthLimits; |
computeUsedBreadthOfGridTracks(direction, sizingData, baseSizes, growthLimits, AvailableSpaceDefinite); |
ASSERT(tracksAreWiderThanMinTrackBreadth(direction, sizingData)); |
+ sizingData.stateTransition(); |
+} |
+ |
+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); |
+ } |
svillar
2016/06/02 14:39:40
I think we don't need this, see my comment bellow.
jfernandez
2016/06/02 21:39:25
I disagree, I think the function adds value, see m
|
} |
void LayoutGrid::layoutBlock(bool relayoutChildren) |
@@ -375,7 +434,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. |
@@ -390,8 +450,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()) |
@@ -674,7 +740,7 @@ bool LayoutGrid::hasDefiniteLogicalSize(GridTrackSizingDirection direction) cons |
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) |
@@ -784,9 +850,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(); |
@@ -818,9 +881,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 |
@@ -841,8 +901,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 |
@@ -1307,10 +1365,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); |
svillar
2016/06/02 14:39:40
That is not enough. Note that you could dynamicall
jfernandez
2016/06/02 21:39:25
I see, I'll change how I identify orthogonality.
|
+ |
GridArea area = cachedGridArea(*child); |
if (!area.rows.isIndefinite()) |
area.rows.translate(abs(m_smallestRowStart)); |
@@ -1593,7 +1654,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); |
@@ -1763,8 +1824,34 @@ GridSpan LayoutGrid::cachedGridSpan(const LayoutBox& gridItem, GridTrackSizingDi |
return direction == ForColumns ? area.columns : area.rows; |
} |
+LayoutUnit LayoutGrid::assumedRowsSizeForOrthogonalChild(const LayoutBox& child) 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).maxTrackBreadth(); |
+ if (maxTrackSize.isContentSized() || maxTrackSize.isFlex()) |
svillar
2016/06/02 14:39:40
I think this is still not correct for percentages
jfernandez
2016/06/02 21:39:25
I don't understand what you mean; as far as I know
svillar
2016/06/10 08:08:35
Yes you're right, sorry for the noise.
|
+ 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); |
svillar
2016/06/02 14:39:40
So assumedRowsSizeForOrthogonalChild() has an asse
jfernandez
2016/06/02 21:39:25
If we are determining column track's size in the F
svillar
2016/06/10 08:08:35
OK. In any case as we depend on the value of an st
jfernandez
2016/06/21 21:50:03
Done.
|
+ |
const Vector<GridTrack>& tracks = direction == ForColumns ? sizingData.columnTracks : sizingData.rowTracks; |
const GridSpan& span = cachedGridSpan(child, direction); |
LayoutUnit gridAreaBreadth; |
@@ -2232,13 +2319,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 |