Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: Source/core/rendering/RenderGrid.cpp

Issue 845313003: [CSS Grid Layout] Tracks growing beyond limits when they should not (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Bring old-style loops back. Ensure that planned increases are applied. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2011 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 25 matching lines...) Expand all
36 36
37 namespace blink { 37 namespace blink {
38 38
39 static const int infinity = -1; 39 static const int infinity = -1;
40 40
41 class GridTrack { 41 class GridTrack {
42 public: 42 public:
43 GridTrack() 43 GridTrack()
44 : m_baseSize(0) 44 : m_baseSize(0)
45 , m_growthLimit(0) 45 , m_growthLimit(0)
46 , m_plannedIncrease(0)
46 { 47 {
47 } 48 }
48 49
49 const LayoutUnit& baseSize() const 50 const LayoutUnit& baseSize() const
50 { 51 {
51 ASSERT(isGrowthLimitBiggerThanBaseSize()); 52 ASSERT(isGrowthLimitBiggerThanBaseSize());
52 return m_baseSize; 53 return m_baseSize;
53 } 54 }
54 55
55 const LayoutUnit& growthLimit() const 56 const LayoutUnit& growthLimit() const
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 { 93 {
93 return m_growthLimit == infinity; 94 return m_growthLimit == infinity;
94 } 95 }
95 96
96 const LayoutUnit& growthLimitIfNotInfinite() const 97 const LayoutUnit& growthLimitIfNotInfinite() const
97 { 98 {
98 ASSERT(isGrowthLimitBiggerThanBaseSize()); 99 ASSERT(isGrowthLimitBiggerThanBaseSize());
99 return (m_growthLimit == infinity) ? m_baseSize : m_growthLimit; 100 return (m_growthLimit == infinity) ? m_baseSize : m_growthLimit;
100 } 101 }
101 102
103 const LayoutUnit& plannedIncrease() const { return m_plannedIncrease; }
104
105 void growPlannedIncrease(const LayoutUnit& plannedIncrease)
106 {
107 ASSERT(plannedIncrease >= 0);
108 m_plannedIncrease += plannedIncrease;
109 }
110
111 void updateFromPlannedIncrease(RenderGrid::AccumulatorGrowFunction trackGrow thFunction)
112 {
113 if (m_plannedIncrease == 0)
114 return;
115
116 (this->*trackGrowthFunction)(m_plannedIncrease);
117 m_plannedIncrease = 0;
118 }
119
102 private: 120 private:
103 bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite( ) || m_growthLimit >= m_baseSize; } 121 bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite( ) || m_growthLimit >= m_baseSize; }
104 122
105 void ensureGrowthLimitIsBiggerThanBaseSize() 123 void ensureGrowthLimitIsBiggerThanBaseSize()
106 { 124 {
107 if (m_growthLimit != infinity && m_growthLimit < m_baseSize) 125 if (m_growthLimit != infinity && m_growthLimit < m_baseSize)
108 m_growthLimit = m_baseSize; 126 m_growthLimit = m_baseSize;
109 } 127 }
110 128
111 LayoutUnit m_baseSize; 129 LayoutUnit m_baseSize;
112 LayoutUnit m_growthLimit; 130 LayoutUnit m_growthLimit;
131 LayoutUnit m_plannedIncrease;
113 }; 132 };
114 133
115 struct GridTrackForNormalization { 134 struct GridTrackForNormalization {
116 GridTrackForNormalization(const GridTrack& track, double flex) 135 GridTrackForNormalization(const GridTrack& track, double flex)
117 : m_track(&track) 136 : m_track(&track)
118 , m_flex(flex) 137 , m_flex(flex)
119 , m_normalizedFlexValue(track.baseSize() / flex) 138 , m_normalizedFlexValue(track.baseSize() / flex)
120 { 139 {
121 } 140 }
122 141
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 : columnTracks(gridColumnCount) 240 : columnTracks(gridColumnCount)
222 , rowTracks(gridRowCount) 241 , rowTracks(gridRowCount)
223 { 242 {
224 } 243 }
225 244
226 Vector<GridTrack> columnTracks; 245 Vector<GridTrack> columnTracks;
227 Vector<GridTrack> rowTracks; 246 Vector<GridTrack> rowTracks;
228 Vector<size_t> contentSizedTracksIndex; 247 Vector<size_t> contentSizedTracksIndex;
229 248
230 // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free. 249 // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free.
231 Vector<LayoutUnit> distributeTrackVector;
232 Vector<GridTrack*> filteredTracks; 250 Vector<GridTrack*> filteredTracks;
233 WillBeHeapVector<GridItemWithSpan> itemsSortedByIncreasingSpan; 251 WillBeHeapVector<GridItemWithSpan> itemsSortedByIncreasingSpan;
234 Vector<size_t> growAboveMaxBreadthTrackIndexes; 252 Vector<GridTrack*> growBeyondGrowthLimitsTracks;
235 }; 253 };
236 254
237 RenderGrid::RenderGrid(Element* element) 255 RenderGrid::RenderGrid(Element* element)
238 : RenderBlock(element) 256 : RenderBlock(element)
239 , m_gridIsDirty(true) 257 , m_gridIsDirty(true)
240 , m_orderIterator(this) 258 , m_orderIterator(this)
241 { 259 {
242 ASSERT(!childrenInline()); 260 ASSERT(!childrenInline());
243 } 261 }
244 262
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 return; 449 return;
432 450
433 // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until 451 // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until
434 // availableLogicalSpace (RemainingSpace in the specs) is exhausted. 452 // availableLogicalSpace (RemainingSpace in the specs) is exhausted.
435 const size_t tracksSize = tracks.size(); 453 const size_t tracksSize = tracks.size();
436 if (!hasUndefinedRemainingSpace) { 454 if (!hasUndefinedRemainingSpace) {
437 Vector<GridTrack*> tracksForDistribution(tracksSize); 455 Vector<GridTrack*> tracksForDistribution(tracksSize);
438 for (size_t i = 0; i < tracksSize; ++i) 456 for (size_t i = 0; i < tracksSize; ++i)
439 tracksForDistribution[i] = tracks.data() + i; 457 tracksForDistribution[i] = tracks.data() + i;
440 458
441 distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::baseSize, &GridTrack::growBaseSize, sizingData, availableLogicalSpace); 459 distributeSpaceToTracks(tracksForDistribution, nullptr, &GridTrack::base Size, &GridTrack::growBaseSize, sizingData, availableLogicalSpace);
442 } else { 460 } else {
443 for (auto& track : tracks) 461 for (auto& track : tracks)
444 track.setBaseSize(track.growthLimit()); 462 track.setBaseSize(track.growthLimit());
445 } 463 }
446 464
447 if (flexibleSizedTracksIndex.isEmpty()) 465 if (flexibleSizedTracksIndex.isEmpty())
448 return; 466 return;
449 467
450 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction. 468 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
451 double normalizedFractionBreadth = 0; 469 double normalizedFractionBreadth = 0;
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 track.setGrowthLimit(std::max(track.growthLimit(), maxContentForChild(gr idItem, direction, columnTracks))); 764 track.setGrowthLimit(std::max(track.growthLimit(), maxContentForChild(gr idItem, direction, columnTracks)));
747 } 765 }
748 766
749 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing Direction direction, GridSizingData& sizingData, GridItemWithSpan& gridItemWithS pan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGe tter trackGetter, AccumulatorGrowFunction trackGrowthFunction, FilterFunction gr owAboveMaxBreadthFilterFunction) 767 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing Direction direction, GridSizingData& sizingData, GridItemWithSpan& gridItemWithS pan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGe tter trackGetter, AccumulatorGrowFunction trackGrowthFunction, FilterFunction gr owAboveMaxBreadthFilterFunction)
750 { 768 {
751 ASSERT(gridItemWithSpan.span() > 1); 769 ASSERT(gridItemWithSpan.span() > 1);
752 const GridCoordinate coordinate = gridItemWithSpan.coordinate(); 770 const GridCoordinate coordinate = gridItemWithSpan.coordinate();
753 const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPo sition; 771 const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPo sition;
754 const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition ; 772 const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition ;
755 773
756 sizingData.growAboveMaxBreadthTrackIndexes.shrink(0); 774 sizingData.growBeyondGrowthLimitsTracks.shrink(0);
757 sizingData.filteredTracks.shrink(0); 775 sizingData.filteredTracks.shrink(0);
758 for (GridResolvedPosition trackPosition = initialTrackPosition; trackPositio n <= finalTrackPosition; ++trackPosition) { 776 for (GridResolvedPosition trackPosition = initialTrackPosition; trackPositio n <= finalTrackPosition; ++trackPosition) {
759 GridTrackSize trackSize = gridTrackSize(direction, trackPosition.toInt() ); 777 GridTrackSize trackSize = gridTrackSize(direction, trackPosition.toInt() );
760 if (!(trackSize.*filterFunction)()) 778 if (!(trackSize.*filterFunction)())
761 continue; 779 continue;
762 780
763 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()]; 781 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()];
764 sizingData.filteredTracks.append(&track); 782 sizingData.filteredTracks.append(&track);
765 783
766 if (growAboveMaxBreadthFilterFunction && (trackSize.*growAboveMaxBreadth FilterFunction)()) 784 if (!growAboveMaxBreadthFilterFunction || (trackSize.*growAboveMaxBreadt hFilterFunction)())
767 sizingData.growAboveMaxBreadthTrackIndexes.append(sizingData.filtere dTracks.size() - 1); 785 sizingData.growBeyondGrowthLimitsTracks.append(&track);
768 } 786 }
769 787
770 if (sizingData.filteredTracks.isEmpty()) 788 if (sizingData.filteredTracks.isEmpty())
771 return; 789 return;
772 790
773 LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItemWithSpan .gridItem(), direction, sizingData.columnTracks); 791 LayoutUnit extraSpace = (this->*sizingFunction)(gridItemWithSpan.gridItem(), direction, sizingData.columnTracks);
774 for (GridResolvedPosition trackIndexForSpace = initialTrackPosition; trackIn dexForSpace <= finalTrackPosition; ++trackIndexForSpace) { 792 for (GridResolvedPosition trackIndexForSpace = initialTrackPosition; trackIn dexForSpace <= finalTrackPosition; ++trackIndexForSpace) {
775 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackIndexForSpace.toInt()] : sizingData.rowTracks[trackIndexForSpace.toInt()]; 793 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackIndexForSpace.toInt()] : sizingData.rowTracks[trackIndexForSpace.toInt()];
776 additionalBreadthSpace -= (track.*trackGetter)(); 794 extraSpace -= (track.*trackGetter)();
777 } 795 }
778 796
779 // Specs mandate to floor additionalBreadthSpace (extra-space in specs) to 0 . Instead we directly avoid the function 797 // Specs mandate to floor additionalBreadthSpace (extra-space in specs) to 0 . Instead we directly avoid the function
Julien - ping for review 2015/01/23 10:20:12 The comment still talks about |additionalBreadthSp
780 // call in those cases as it will be a noop in terms of track sizing. 798 // call in those cases as it will be a noop in terms of track sizing.
781 if (additionalBreadthSpace > 0) 799 if (extraSpace > 0) {
782 distributeSpaceToTracks(sizingData.filteredTracks, &sizingData.growAbove MaxBreadthTrackIndexes, trackGetter, trackGrowthFunction, sizingData, additional BreadthSpace); 800 Vector<GridTrack*>* tracksToGrowBeyondGrowthLimits = sizingData.growBeyo ndGrowthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBe yondGrowthLimitsTracks;
801 distributeSpaceToTracks(sizingData.filteredTracks, tracksToGrowBeyondGro wthLimits, trackGetter, trackGrowthFunction, sizingData, extraSpace);
802 }
783 } 803 }
784 804
785 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr ack* track2) 805 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr ack* track2)
786 { 806 {
787 // This check ensures that we respect the irreflexivity property of the stri ct weak ordering required by std::sort 807 // This check ensures that we respect the irreflexivity property of the stri ct weak ordering required by std::sort
788 // (forall x: NOT x < x). 808 // (forall x: NOT x < x).
789 if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite()) 809 if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite())
790 return false; 810 return false;
791 811
792 if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite()) 812 if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite())
793 return track2->growthLimitIsInfinite(); 813 return track2->growthLimitIsInfinite();
794 814
795 return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize()); 815 return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize());
796 } 816 }
797 817
798 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<size _t>* growAboveMaxBreadthTrackIndexes, AccumulatorGetter trackGetter, Accumulator GrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availa bleLogicalSpace) 818 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vecto r<GridTrack*>* growBeyondGrowthLimitsTracks, AccumulatorGetter trackGetter, Accu mulatorGrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
799 { 819 {
800 ASSERT(availableLogicalSpace > 0); 820 ASSERT(availableLogicalSpace > 0);
801 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential); 821 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
802 822
803 size_t tracksSize = tracks.size(); 823 size_t tracksSize = tracks.size();
804 sizingData.distributeTrackVector.resize(tracksSize);
805
806 for (size_t i = 0; i < tracksSize; ++i) { 824 for (size_t i = 0; i < tracksSize; ++i) {
Julien - ping for review 2015/01/23 10:20:12 How about we use a C++11 auto loop here too?
svillar 2015/01/23 13:44:10 I did it in the first patch but you said "The patt
807 GridTrack& track = *tracks[i]; 825 GridTrack& track = *tracks[i];
826 ASSERT(track.plannedIncrease() == 0);
808 LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksS ize - i); 827 LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksS ize - i);
809 const LayoutUnit& trackBreadth = (tracks[i]->*trackGetter)(); 828 const LayoutUnit& trackBreadth = (track.*trackGetter)();
810 LayoutUnit growthShare = track.growthLimitIsInfinite() ? availableLogica lSpaceShare : std::min(availableLogicalSpaceShare, track.growthLimit() - trackBr eadth); 829 LayoutUnit growthShare = track.growthLimitIsInfinite() ? availableLogica lSpaceShare : std::min(availableLogicalSpaceShare, track.growthLimit() - trackBr eadth);
811 sizingData.distributeTrackVector[i] = trackBreadth;
812 // We should never shrink any grid track or else we can't guarantee we a bide by our min-sizing function. 830 // We should never shrink any grid track or else we can't guarantee we a bide by our min-sizing function.
813 if (growthShare > 0) { 831 if (growthShare > 0) {
814 sizingData.distributeTrackVector[i] += growthShare; 832 track.growPlannedIncrease(growthShare);
815 availableLogicalSpace -= growthShare; 833 availableLogicalSpace -= growthShare;
816 } 834 }
817 } 835 }
818 836
819 if (availableLogicalSpace > 0 && growAboveMaxBreadthTrackIndexes) { 837 if (availableLogicalSpace > 0 && growBeyondGrowthLimitsTracks) {
820 size_t indexesSize = growAboveMaxBreadthTrackIndexes->size(); 838 size_t tracksGrowingAboveMaxBreadthSize = growBeyondGrowthLimitsTracks-> size();
821 size_t tracksGrowingAboveMaxBreadthSize = indexesSize ? indexesSize : tr acksSize;
822 // If we have a non-null empty vector of track indexes to grow above max breadth means that we should grow all
823 // affected tracks.
824 for (size_t i = 0; i < tracksGrowingAboveMaxBreadthSize; ++i) { 839 for (size_t i = 0; i < tracksGrowingAboveMaxBreadthSize; ++i) {
840 GridTrack* track = growBeyondGrowthLimitsTracks->at(i);
825 LayoutUnit growthShare = availableLogicalSpace / (tracksGrowingAbove MaxBreadthSize - i); 841 LayoutUnit growthShare = availableLogicalSpace / (tracksGrowingAbove MaxBreadthSize - i);
826 size_t distributeTrackIndex = indexesSize ? growAboveMaxBreadthTrack Indexes->at(i) : i; 842 track->growPlannedIncrease(growthShare);
827 sizingData.distributeTrackVector[distributeTrackIndex] += growthShar e;
828 availableLogicalSpace -= growthShare; 843 availableLogicalSpace -= growthShare;
829 } 844 }
830 } 845 }
831 846
832 for (size_t i = 0; i < tracksSize; ++i) { 847 for (auto* track: tracks) {
833 LayoutUnit growth = sizingData.distributeTrackVector[i] - (tracks[i]->*t rackGetter)(); 848 track->updateFromPlannedIncrease(trackGrowthFunction);
834 if (growth >= 0) 849 ASSERT(track->plannedIncrease() == 0);
835 (tracks[i]->*trackGrowthFunction)(growth);
836 } 850 }
837 } 851 }
838 852
839 #if ENABLE(ASSERT) 853 #if ENABLE(ASSERT)
840 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire ction, const Vector<GridTrack>& tracks) 854 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire ction, const Vector<GridTrack>& tracks)
841 { 855 {
842 for (size_t i = 0; i < tracks.size(); ++i) { 856 for (size_t i = 0; i < tracks.size(); ++i) {
843 GridTrackSize trackSize = gridTrackSize(direction, i); 857 GridTrackSize trackSize = gridTrackSize(direction, i);
844 const GridLength& minTrackBreadth = trackSize.minTrackBreadth(); 858 const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
845 if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i ].baseSize()) 859 if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i ].baseSize())
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 if (isOutOfFlowPositioned()) 1673 if (isOutOfFlowPositioned())
1660 return "RenderGrid (positioned)"; 1674 return "RenderGrid (positioned)";
1661 if (isAnonymous()) 1675 if (isAnonymous())
1662 return "RenderGrid (generated)"; 1676 return "RenderGrid (generated)";
1663 if (isRelPositioned()) 1677 if (isRelPositioned())
1664 return "RenderGrid (relative positioned)"; 1678 return "RenderGrid (relative positioned)";
1665 return "RenderGrid"; 1679 return "RenderGrid";
1666 } 1680 }
1667 1681
1668 } // namespace blink 1682 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698