Chromium Code Reviews| Index: Source/core/layout/LayoutGrid.cpp |
| diff --git a/Source/core/layout/LayoutGrid.cpp b/Source/core/layout/LayoutGrid.cpp |
| index 7c0a17bec7fc0ac127904c5dbffef9ea7bf2b4b0..eb0579f1f3250947f9f4633859f81352d8fa791d 100644 |
| --- a/Source/core/layout/LayoutGrid.cpp |
| +++ b/Source/core/layout/LayoutGrid.cpp |
| @@ -41,10 +41,11 @@ static const int infinity = -1; |
| class GridTrack { |
| public: |
| GridTrack() |
| - : m_plannedIncrease(0) |
| - , m_increaseDuringDistribution(0) |
| - , m_baseSize(0) |
| + : m_baseSize(0) |
| , m_growthLimit(0) |
| + , m_plannedSize(0) |
| + , m_sizeDuringDistribution(0) |
| + , m_infinitelyGrowable(false) |
| { |
| } |
| @@ -72,37 +73,46 @@ public: |
| ensureGrowthLimitIsBiggerThanBaseSize(); |
| } |
| - void growBaseSize(LayoutUnit growth) |
| + bool growthLimitIsInfinite() const |
| { |
| - ASSERT(growth >= 0); |
| - m_baseSize += growth; |
| - ensureGrowthLimitIsBiggerThanBaseSize(); |
| + return m_growthLimit == infinity; |
| } |
| - void growGrowthLimit(LayoutUnit growth) |
| + bool growthLimitIsInfiniteOrTrackIsInfinitelyGrowable() const |
| { |
| - ASSERT(growth >= 0); |
| - if (m_growthLimit == infinity) |
| - m_growthLimit = m_baseSize + growth; |
| - else |
| - m_growthLimit += growth; |
| + return growthLimitIsInfinite() || m_infinitelyGrowable; |
| + } |
| - ASSERT(m_growthLimit >= m_baseSize); |
| + const LayoutUnit& growthLimitIfNotInfinite() const |
| + { |
| + ASSERT(isGrowthLimitBiggerThanBaseSize()); |
| + return (m_growthLimit == infinity) ? m_baseSize : m_growthLimit; |
| } |
| - bool growthLimitIsInfinite() const |
| + const LayoutUnit& plannedSize() const { return m_plannedSize; } |
| + |
| + void setPlannedSize(const LayoutUnit& plannedSize) |
| { |
| - return m_growthLimit == infinity; |
| + ASSERT(plannedSize >= 0 || plannedSize == infinity); |
| + m_plannedSize = plannedSize; |
|
Julien - ping for review
2015/04/08 18:58:56
It seems weird to allow the plannedSize to be infi
svillar
2015/04/10 09:43:09
In theory that's true, although not possible with
|
| } |
| - const LayoutUnit& growthLimitIfNotInfinite() const |
| + const LayoutUnit& sizeDuringDistribution() { return m_sizeDuringDistribution; } |
| + |
| + void setSizeDuringDistribution(const LayoutUnit& sizeDuringDistribution) |
| { |
| - ASSERT(isGrowthLimitBiggerThanBaseSize()); |
| - return (m_growthLimit == infinity) ? m_baseSize : m_growthLimit; |
| + ASSERT(sizeDuringDistribution >= 0); |
| + m_sizeDuringDistribution = sizeDuringDistribution; |
| } |
| - LayoutUnit m_plannedIncrease; |
| - LayoutUnit m_increaseDuringDistribution; |
| + void growSizeDuringDistribution(const LayoutUnit& sizeDuringDistribution) |
| + { |
| + ASSERT(sizeDuringDistribution >= 0); |
| + m_sizeDuringDistribution += sizeDuringDistribution; |
| + } |
| + |
| + bool infinitelyGrowable() const { return m_infinitelyGrowable; } |
| + void setInfinitelyGrowable(bool infinitelyGrowable) { m_infinitelyGrowable = infinitelyGrowable; } |
| private: |
| bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite() || m_growthLimit >= m_baseSize; } |
| @@ -115,6 +125,9 @@ private: |
| LayoutUnit m_baseSize; |
| LayoutUnit m_growthLimit; |
| + LayoutUnit m_plannedSize; |
| + LayoutUnit m_sizeDuringDistribution; |
| + bool m_infinitelyGrowable; |
|
Julien - ping for review
2015/04/08 18:58:56
We are storing one extra member compared to the sp
svillar
2015/04/10 09:43:09
It does exist in the original algorithm, it's call
|
| }; |
| struct GridTrackForNormalization { |
| @@ -413,6 +426,7 @@ void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi |
| track.setBaseSize(computeUsedBreadthOfMinLength(direction, minTrackBreadth)); |
| track.setGrowthLimit(computeUsedBreadthOfMaxLength(direction, maxTrackBreadth, track.baseSize())); |
| + track.setInfinitelyGrowable(false); |
| if (trackSize.isContentSized()) |
| sizingData.contentSizedTracksIndex.append(i); |
| @@ -425,7 +439,7 @@ void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi |
| resolveContentBasedTrackSizingFunctions(direction, sizingData); |
| for (const auto& track: tracks) { |
| - ASSERT(!track.growthLimitIsInfinite()); |
| + ASSERT(!track.growthLimitIsInfinite() && !track.infinitelyGrowable()); |
|
Julien - ping for review
2015/04/08 18:58:56
This should be split in 2. Logical AND in ASSERT m
svillar
2015/04/10 09:43:09
Acknowledged.
|
| freeSpace -= track.baseSize(); |
| } |
| @@ -440,13 +454,13 @@ void LayoutGrid::computeUsedBreadthOfGridTracks(GridTrackSizingDirection directi |
| Vector<GridTrack*> tracksForDistribution(tracksSize); |
| for (size_t i = 0; i < tracksSize; ++i) { |
| tracksForDistribution[i] = tracks.data() + i; |
| - tracksForDistribution[i]->m_plannedIncrease = 0; |
| + tracksForDistribution[i]->setPlannedSize(tracksForDistribution[i]->baseSize()); |
| } |
| distributeSpaceToTracks(tracksForDistribution, nullptr, &GridTrack::baseSize, sizingData, freeSpace); |
| for (auto* track : tracksForDistribution) |
| - track->growBaseSize(track->m_plannedIncrease); |
| + track->setBaseSize(track->plannedSize()); |
| } else { |
| for (auto& track : tracks) |
| track.setBaseSize(track.growthLimit()); |
| @@ -743,10 +757,10 @@ void LayoutGrid::resolveContentBasedTrackSizingFunctions(GridTrackSizingDirectio |
| auto end = sizingData.itemsSortedByIncreasingSpan.end(); |
| while (it != end) { |
| GridItemsSpanGroupRange spanGroupRange = { it, std::upper_bound(it, end, *it) }; |
| - resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &LayoutGrid::minContentForChild, &GridTrack::baseSize, &GridTrack::growBaseSize, &GridTrackSize::hasMinContentMinTrackBreadthAndMinOrMaxContentMaxTrackBreadth); |
| - resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMaxContentMinTrackBreadth, &LayoutGrid::maxContentForChild, &GridTrack::baseSize, &GridTrack::growBaseSize, &GridTrackSize::hasMaxContentMinTrackBreadthAndMaxContentMaxTrackBreadth); |
| - resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &LayoutGrid::minContentForChild, &GridTrack::growthLimitIfNotInfinite, &GridTrack::growGrowthLimit); |
| - resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMaxContentMaxTrackBreadth, &LayoutGrid::maxContentForChild, &GridTrack::growthLimitIfNotInfinite, &GridTrack::growGrowthLimit); |
| + resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &LayoutGrid::minContentForChild, &GridTrack::baseSize, &GridTrack::baseSize, &GridTrack::setBaseSize, &GridTrackSize::hasMinContentMinTrackBreadthAndMinOrMaxContentMaxTrackBreadth); |
| + resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMaxContentMinTrackBreadth, &LayoutGrid::maxContentForChild, &GridTrack::baseSize, &GridTrack::baseSize, &GridTrack::setBaseSize, &GridTrackSize::hasMaxContentMinTrackBreadthAndMaxContentMaxTrackBreadth); |
| + resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &LayoutGrid::minContentForChild, &GridTrack::growthLimit, &GridTrack::growthLimitIfNotInfinite, &GridTrack::setGrowthLimit); |
| + resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, spanGroupRange, &GridTrackSize::hasMaxContentMaxTrackBreadth, &LayoutGrid::maxContentForChild, &GridTrack::growthLimit, &GridTrack::growthLimitIfNotInfinite, &GridTrack::setGrowthLimit); |
| it = spanGroupRange.rangeEnd; |
| } |
| @@ -773,11 +787,13 @@ void LayoutGrid::resolveContentBasedTrackSizingFunctionsForNonSpanningItems(Grid |
| track.setGrowthLimit(std::max(track.growthLimit(), maxContentForChild(gridItem, direction, columnTracks))); |
| } |
| -void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, FilterFunction growAboveMaxBreadthFilterFunction) |
| +void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizingDirection direction, GridSizingData& sizingData, const GridItemsSpanGroupRange& gridItemsWithSpan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGetter trackGetterIfNotInfinite, AccumulatorSetterFunction trackSetterFunction, FilterFunction growAboveMaxBreadthFilterFunction) |
| { |
| Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks; |
| - for (const auto& trackIndex : sizingData.contentSizedTracksIndex) |
| - tracks[trackIndex].m_plannedIncrease = 0; |
| + for (const auto& trackIndex : sizingData.contentSizedTracksIndex) { |
| + GridTrack& track = tracks[trackIndex]; |
| + track.setPlannedSize((track.*trackGetter)()); |
| + } |
| for (auto it = gridItemsWithSpan.rangeStart; it != gridItemsWithSpan.rangeEnd; ++it) { |
| GridItemWithSpan& gridItemWithSpan = *it; |
| @@ -791,7 +807,7 @@ void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing |
| for (const auto& trackPosition : itemSpan) { |
| GridTrackSize trackSize = gridTrackSize(direction, trackPosition.toInt()); |
| GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()]; |
| - spanningTracksSize += (track.*trackGetter)(); |
| + spanningTracksSize += (track.*trackGetterIfNotInfinite)(); |
| if (!(trackSize.*filterFunction)()) |
| continue; |
| @@ -804,19 +820,19 @@ void LayoutGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing |
| if (sizingData.filteredTracks.isEmpty()) |
| continue; |
| - // Specs mandate to floor extraSpace to 0. Instead we directly avoid the function call in those cases as it will be |
| - // a noop in terms of track sizing. |
| LayoutUnit extraSpace = (this->*sizingFunction)(gridItemWithSpan.gridItem(), direction, sizingData.columnTracks) - spanningTracksSize; |
| - if (extraSpace > 0) { |
| - Vector<GridTrack*>* tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGrowthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBeyondGrowthLimitsTracks; |
| - distributeSpaceToTracks(sizingData.filteredTracks, tracksToGrowBeyondGrowthLimits, trackGetter, sizingData, extraSpace); |
| - } |
| + Vector<GridTrack*>* tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGrowthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBeyondGrowthLimitsTracks; |
| + extraSpace = std::max<LayoutUnit>(extraSpace, 0); |
| + distributeSpaceToTracks(sizingData.filteredTracks, tracksToGrowBeyondGrowthLimits, trackGetterIfNotInfinite, sizingData, extraSpace); |
| } |
| for (const auto& trackIndex : sizingData.contentSizedTracksIndex) { |
| GridTrack& track = tracks[trackIndex]; |
| - if (track.m_plannedIncrease) |
| - (track.*trackGrowthFunction)(track.m_plannedIncrease); |
| + if ((track.*trackGetter)() == infinity && track.plannedSize() != infinity) |
| + track.setInfinitelyGrowable(true); |
| + else if (track.infinitelyGrowable()) |
| + track.setInfinitelyGrowable(false); |
| + (track.*trackSetterFunction)(track.plannedSize()); |
| } |
| } |
| @@ -824,29 +840,34 @@ static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr |
| { |
| // This check ensures that we respect the irreflexivity property of the strict weak ordering required by std::sort |
| // (forall x: NOT x < x). |
| - if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite()) |
| + if (track1->growthLimitIsInfiniteOrTrackIsInfinitelyGrowable() && track2->growthLimitIsInfiniteOrTrackIsInfinitelyGrowable()) |
| return false; |
| - if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite()) |
| - return track2->growthLimitIsInfinite(); |
| + if (track1->growthLimitIsInfiniteOrTrackIsInfinitelyGrowable() || track2->growthLimitIsInfiniteOrTrackIsInfinitelyGrowable()) |
| + return track2->growthLimitIsInfiniteOrTrackIsInfinitelyGrowable(); |
| return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize()); |
| } |
| -void LayoutGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, AccumulatorGetter trackGetter, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace) |
| +void LayoutGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vector<GridTrack*>* growBeyondGrowthLimitsTracks, AccumulatorGetter trackGetterIfNotInfinite, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace) |
| { |
| - ASSERT(availableLogicalSpace > 0); |
| - std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential); |
| + ASSERT(availableLogicalSpace >= 0); |
| + if (availableLogicalSpace > 0) { |
| + std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential); |
| - size_t tracksSize = tracks.size(); |
| - for (size_t i = 0; i < tracksSize; ++i) { |
| - GridTrack& track = *tracks[i]; |
| - LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i); |
| - const LayoutUnit& trackBreadth = (track.*trackGetter)(); |
| - LayoutUnit growthShare = track.growthLimitIsInfinite() ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, track.growthLimit() - trackBreadth); |
| - ASSERT_WITH_MESSAGE(growthShare >= 0, "We must never shrink any grid track or else we can't guarantee we abide by our min-sizing function."); |
| - track.m_increaseDuringDistribution = growthShare; |
| - availableLogicalSpace -= growthShare; |
| + size_t tracksSize = tracks.size(); |
| + for (size_t i = 0; i < tracksSize; ++i) { |
| + GridTrack& track = *tracks[i]; |
| + LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i); |
| + const LayoutUnit& trackBreadth = (track.*trackGetterIfNotInfinite)(); |
| + LayoutUnit growthShare = track.growthLimitIsInfiniteOrTrackIsInfinitelyGrowable() ? availableLogicalSpaceShare : std::min(availableLogicalSpaceShare, track.growthLimit() - trackBreadth); |
| + ASSERT_WITH_MESSAGE(growthShare >= 0, "We must never shrink any grid track or else we can't guarantee we abide by our min-sizing function."); |
| + track.setSizeDuringDistribution(trackBreadth + growthShare); |
| + availableLogicalSpace -= growthShare; |
| + } |
| + } else { |
| + for (auto* track : tracks) |
| + track->setSizeDuringDistribution((track->*trackGetterIfNotInfinite)()); |
| } |
| if (availableLogicalSpace > 0 && growBeyondGrowthLimitsTracks) { |
| @@ -854,13 +875,13 @@ void LayoutGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vecto |
| for (size_t i = 0; i < tracksGrowingAboveMaxBreadthSize; ++i) { |
| GridTrack* track = growBeyondGrowthLimitsTracks->at(i); |
| LayoutUnit growthShare = availableLogicalSpace / (tracksGrowingAboveMaxBreadthSize - i); |
| - track->m_increaseDuringDistribution += growthShare; |
| + track->growSizeDuringDistribution(growthShare); |
| availableLogicalSpace -= growthShare; |
| } |
| } |
| for (auto* track : tracks) |
| - track->m_plannedIncrease = std::max(track->m_plannedIncrease, track->m_increaseDuringDistribution); |
| + track->setPlannedSize(track->plannedSize() == infinity ? track->sizeDuringDistribution() : std::max(track->plannedSize(), track->sizeDuringDistribution())); |
| } |
| #if ENABLE(ASSERT) |