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

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: 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
« no previous file with comments | « Source/core/rendering/RenderGrid.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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)
Julien - ping for review 2015/01/19 16:36:24 TBH this field doesn't seem to belong here. It's u
svillar 2015/01/20 08:23:24 It isn't because the previous approach was wrong,
Julien - ping for review 2015/01/20 13:47:14 We discussed this part of the change over IRC and
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 void setPlannedIncrease(const LayoutUnit& plannedIncrease)
105 {
106 ASSERT(plannedIncrease >= 0);
107 m_plannedIncrease = plannedIncrease;
108 }
109
110 void growPlannedIncrease(const LayoutUnit& plannedIncrease)
111 {
112 ASSERT(plannedIncrease >= 0);
113 m_plannedIncrease += plannedIncrease;
Julien - ping for review 2015/01/19 16:36:24 This concerns me because we don't enforce that we
114 }
115
102 private: 116 private:
103 bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite( ) || m_growthLimit >= m_baseSize; } 117 bool isGrowthLimitBiggerThanBaseSize() const { return growthLimitIsInfinite( ) || m_growthLimit >= m_baseSize; }
104 118
105 void ensureGrowthLimitIsBiggerThanBaseSize() 119 void ensureGrowthLimitIsBiggerThanBaseSize()
106 { 120 {
107 if (m_growthLimit != infinity && m_growthLimit < m_baseSize) 121 if (m_growthLimit != infinity && m_growthLimit < m_baseSize)
108 m_growthLimit = m_baseSize; 122 m_growthLimit = m_baseSize;
109 } 123 }
110 124
111 LayoutUnit m_baseSize; 125 LayoutUnit m_baseSize;
112 LayoutUnit m_growthLimit; 126 LayoutUnit m_growthLimit;
127 LayoutUnit m_plannedIncrease;
113 }; 128 };
114 129
115 struct GridTrackForNormalization { 130 struct GridTrackForNormalization {
116 GridTrackForNormalization(const GridTrack& track, double flex) 131 GridTrackForNormalization(const GridTrack& track, double flex)
117 : m_track(&track) 132 : m_track(&track)
118 , m_flex(flex) 133 , m_flex(flex)
119 , m_normalizedFlexValue(track.baseSize() / flex) 134 , m_normalizedFlexValue(track.baseSize() / flex)
120 { 135 {
121 } 136 }
122 137
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 : columnTracks(gridColumnCount) 236 : columnTracks(gridColumnCount)
222 , rowTracks(gridRowCount) 237 , rowTracks(gridRowCount)
223 { 238 {
224 } 239 }
225 240
226 Vector<GridTrack> columnTracks; 241 Vector<GridTrack> columnTracks;
227 Vector<GridTrack> rowTracks; 242 Vector<GridTrack> rowTracks;
228 Vector<size_t> contentSizedTracksIndex; 243 Vector<size_t> contentSizedTracksIndex;
229 244
230 // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free. 245 // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free.
231 Vector<LayoutUnit> distributeTrackVector;
232 Vector<GridTrack*> filteredTracks; 246 Vector<GridTrack*> filteredTracks;
233 WillBeHeapVector<GridItemWithSpan> itemsSortedByIncreasingSpan; 247 WillBeHeapVector<GridItemWithSpan> itemsSortedByIncreasingSpan;
234 Vector<size_t> growAboveMaxBreadthTrackIndexes; 248 Vector<GridTrack*> growBeyondGrowthLimitsTracks;
235 }; 249 };
236 250
237 RenderGrid::RenderGrid(Element* element) 251 RenderGrid::RenderGrid(Element* element)
238 : RenderBlock(element) 252 : RenderBlock(element)
239 , m_gridIsDirty(true) 253 , m_gridIsDirty(true)
240 , m_orderIterator(this) 254 , m_orderIterator(this)
241 { 255 {
242 ASSERT(!childrenInline()); 256 ASSERT(!childrenInline());
243 } 257 }
244 258
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 return; 445 return;
432 446
433 // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until 447 // 3. Grow all Grid tracks in GridTracks from their UsedBreadth up to their MaxBreadth value until
434 // availableLogicalSpace (RemainingSpace in the specs) is exhausted. 448 // availableLogicalSpace (RemainingSpace in the specs) is exhausted.
435 const size_t tracksSize = tracks.size(); 449 const size_t tracksSize = tracks.size();
436 if (!hasUndefinedRemainingSpace) { 450 if (!hasUndefinedRemainingSpace) {
437 Vector<GridTrack*> tracksForDistribution(tracksSize); 451 Vector<GridTrack*> tracksForDistribution(tracksSize);
438 for (size_t i = 0; i < tracksSize; ++i) 452 for (size_t i = 0; i < tracksSize; ++i)
439 tracksForDistribution[i] = tracks.data() + i; 453 tracksForDistribution[i] = tracks.data() + i;
440 454
441 distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::baseSize, &GridTrack::growBaseSize, sizingData, availableLogicalSpace); 455 distributeSpaceToTracks(tracksForDistribution, nullptr, &GridTrack::base Size, &GridTrack::growBaseSize, sizingData, availableLogicalSpace);
442 } else { 456 } else {
443 for (auto& track : tracks) 457 for (auto& track : tracks)
444 track.setBaseSize(track.growthLimit()); 458 track.setBaseSize(track.growthLimit());
445 } 459 }
446 460
447 if (flexibleSizedTracksIndex.isEmpty()) 461 if (flexibleSizedTracksIndex.isEmpty())
448 return; 462 return;
449 463
450 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction. 464 // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
451 double normalizedFractionBreadth = 0; 465 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))); 760 track.setGrowthLimit(std::max(track.growthLimit(), maxContentForChild(gr idItem, direction, columnTracks)));
747 } 761 }
748 762
749 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing Direction direction, GridSizingData& sizingData, GridItemWithSpan& gridItemWithS pan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGe tter trackGetter, AccumulatorGrowFunction trackGrowthFunction, FilterFunction gr owAboveMaxBreadthFilterFunction) 763 void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(GridTrackSizing Direction direction, GridSizingData& sizingData, GridItemWithSpan& gridItemWithS pan, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGe tter trackGetter, AccumulatorGrowFunction trackGrowthFunction, FilterFunction gr owAboveMaxBreadthFilterFunction)
750 { 764 {
751 ASSERT(gridItemWithSpan.span() > 1); 765 ASSERT(gridItemWithSpan.span() > 1);
752 const GridCoordinate coordinate = gridItemWithSpan.coordinate(); 766 const GridCoordinate coordinate = gridItemWithSpan.coordinate();
753 const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPo sition; 767 const GridResolvedPosition initialTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedInitialPosition : coordinate.rows.resolvedInitialPo sition;
754 const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition ; 768 const GridResolvedPosition finalTrackPosition = (direction == ForColumns) ? coordinate.columns.resolvedFinalPosition : coordinate.rows.resolvedFinalPosition ;
755 769
756 sizingData.growAboveMaxBreadthTrackIndexes.shrink(0); 770 sizingData.growBeyondGrowthLimitsTracks.shrink(0);
757 sizingData.filteredTracks.shrink(0); 771 sizingData.filteredTracks.shrink(0);
758 for (GridResolvedPosition trackPosition = initialTrackPosition; trackPositio n <= finalTrackPosition; ++trackPosition) { 772 for (GridResolvedPosition trackPosition = initialTrackPosition; trackPositio n <= finalTrackPosition; ++trackPosition) {
759 GridTrackSize trackSize = gridTrackSize(direction, trackPosition.toInt() ); 773 GridTrackSize trackSize = gridTrackSize(direction, trackPosition.toInt() );
760 if (!(trackSize.*filterFunction)()) 774 if (!(trackSize.*filterFunction)())
761 continue; 775 continue;
762 776
763 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()]; 777 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackPosition.toInt()] : sizingData.rowTracks[trackPosition.toInt()];
764 sizingData.filteredTracks.append(&track); 778 sizingData.filteredTracks.append(&track);
765 779
766 if (growAboveMaxBreadthFilterFunction && (trackSize.*growAboveMaxBreadth FilterFunction)()) 780 if (!growAboveMaxBreadthFilterFunction || (trackSize.*growAboveMaxBreadt hFilterFunction)())
767 sizingData.growAboveMaxBreadthTrackIndexes.append(sizingData.filtere dTracks.size() - 1); 781 sizingData.growBeyondGrowthLimitsTracks.append(&track);
768 } 782 }
769 783
770 if (sizingData.filteredTracks.isEmpty()) 784 if (sizingData.filteredTracks.isEmpty())
771 return; 785 return;
772 786
773 LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItemWithSpan .gridItem(), direction, sizingData.columnTracks); 787 LayoutUnit extraSpace = (this->*sizingFunction)(gridItemWithSpan.gridItem(), direction, sizingData.columnTracks);
774 for (GridResolvedPosition trackIndexForSpace = initialTrackPosition; trackIn dexForSpace <= finalTrackPosition; ++trackIndexForSpace) { 788 for (GridResolvedPosition trackIndexForSpace = initialTrackPosition; trackIn dexForSpace <= finalTrackPosition; ++trackIndexForSpace) {
775 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackIndexForSpace.toInt()] : sizingData.rowTracks[trackIndexForSpace.toInt()]; 789 GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[t rackIndexForSpace.toInt()] : sizingData.rowTracks[trackIndexForSpace.toInt()];
776 additionalBreadthSpace -= (track.*trackGetter)(); 790 extraSpace -= (track.*trackGetter)();
777 } 791 }
778 792
779 // Specs mandate to floor additionalBreadthSpace (extra-space in specs) to 0 . Instead we directly avoid the function 793 extraSpace = std::max<LayoutUnit>(0, extraSpace);
780 // call in those cases as it will be a noop in terms of track sizing. 794 Vector<GridTrack*>* tracksToGrowBeyondGrowthLimits = sizingData.growBeyondGr owthLimitsTracks.isEmpty() ? &sizingData.filteredTracks : &sizingData.growBeyond GrowthLimitsTracks;
781 if (additionalBreadthSpace > 0) 795 distributeSpaceToTracks(sizingData.filteredTracks, tracksToGrowBeyondGrowthL imits, trackGetter, trackGrowthFunction, sizingData, extraSpace);
782 distributeSpaceToTracks(sizingData.filteredTracks, &sizingData.growAbove MaxBreadthTrackIndexes, trackGetter, trackGrowthFunction, sizingData, additional BreadthSpace);
783 } 796 }
784 797
785 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr ack* track2) 798 static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr ack* track2)
786 { 799 {
787 // This check ensures that we respect the irreflexivity property of the stri ct weak ordering required by std::sort 800 // 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). 801 // (forall x: NOT x < x).
789 if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite()) 802 if (track1->growthLimitIsInfinite() && track2->growthLimitIsInfinite())
790 return false; 803 return false;
791 804
792 if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite()) 805 if (track1->growthLimitIsInfinite() || track2->growthLimitIsInfinite())
793 return track2->growthLimitIsInfinite(); 806 return track2->growthLimitIsInfinite();
794 807
795 return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize()); 808 return (track1->growthLimit() - track1->baseSize()) < (track2->growthLimit() - track2->baseSize());
796 } 809 }
797 810
798 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<size _t>* growAboveMaxBreadthTrackIndexes, AccumulatorGetter trackGetter, Accumulator GrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availa bleLogicalSpace) 811 void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, const Vecto r<GridTrack*>* growBeyondGrowthLimitsTracks, AccumulatorGetter trackGetter, Accu mulatorGrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
799 { 812 {
800 ASSERT(availableLogicalSpace > 0);
Julien - ping for review 2015/01/19 16:36:24 If you don't have any |availableLogicalSpace|, it
svillar 2015/01/20 08:23:24 Correct, I removed it by accident, it was part of
801 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential); 813 std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
802 814
803 size_t tracksSize = tracks.size(); 815 size_t tracksSize = tracks.size();
804 sizingData.distributeTrackVector.resize(tracksSize); 816 size_t i = 0;
805 817 for (auto* track : tracks) {
806 for (size_t i = 0; i < tracksSize; ++i) { 818 LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksS ize - i++);
807 GridTrack& track = *tracks[i]; 819 const LayoutUnit& trackBreadth = (track->*trackGetter)();
808 LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksS ize - i); 820 LayoutUnit growthShare = track->growthLimitIsInfinite() ? availableLogic alSpaceShare : std::min(availableLogicalSpaceShare, track->growthLimit() - track Breadth);
809 const LayoutUnit& trackBreadth = (tracks[i]->*trackGetter)(); 821 track->setPlannedIncrease(0);
810 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. 822 // 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) { 823 if (growthShare > 0) {
814 sizingData.distributeTrackVector[i] += growthShare; 824 track->growPlannedIncrease(growthShare);
815 availableLogicalSpace -= growthShare; 825 availableLogicalSpace -= growthShare;
816 } 826 }
817 } 827 }
818 828
819 if (availableLogicalSpace > 0 && growAboveMaxBreadthTrackIndexes) { 829 if (availableLogicalSpace > 0 && growBeyondGrowthLimitsTracks) {
820 size_t indexesSize = growAboveMaxBreadthTrackIndexes->size(); 830 size_t tracksGrowingAboveMaxBreadthSize = growBeyondGrowthLimitsTracks-> size();
821 size_t tracksGrowingAboveMaxBreadthSize = indexesSize ? indexesSize : tr acksSize; 831 size_t i = 0;
822 // If we have a non-null empty vector of track indexes to grow above max breadth means that we should grow all 832 for (auto* track : *growBeyondGrowthLimitsTracks) {
823 // affected tracks. 833 LayoutUnit growthShare = availableLogicalSpace / (tracksGrowingAbove MaxBreadthSize - i++);
Julien - ping for review 2015/01/19 16:36:24 The pattern with the auto-for loop + manual iterat
svillar 2015/01/20 08:23:24 Yeah, I don't have a strong opinion here, I can ro
824 for (size_t i = 0; i < tracksGrowingAboveMaxBreadthSize; ++i) { 834 track->growPlannedIncrease(growthShare);
825 LayoutUnit growthShare = availableLogicalSpace / (tracksGrowingAbove MaxBreadthSize - i);
826 size_t distributeTrackIndex = indexesSize ? growAboveMaxBreadthTrack Indexes->at(i) : i;
827 sizingData.distributeTrackVector[distributeTrackIndex] += growthShar e;
828 availableLogicalSpace -= growthShare; 835 availableLogicalSpace -= growthShare;
829 } 836 }
830 } 837 }
831 838
832 for (size_t i = 0; i < tracksSize; ++i) { 839 for (auto* track: tracks) {
833 LayoutUnit growth = sizingData.distributeTrackVector[i] - (tracks[i]->*t rackGetter)(); 840 if (auto plannedIncrease = track->plannedIncrease())
834 if (growth >= 0) 841 (track->*trackGrowthFunction)(plannedIncrease);
835 (tracks[i]->*trackGrowthFunction)(growth);
836 } 842 }
837 } 843 }
838 844
839 #if ENABLE(ASSERT) 845 #if ENABLE(ASSERT)
840 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire ction, const Vector<GridTrack>& tracks) 846 bool RenderGrid::tracksAreWiderThanMinTrackBreadth(GridTrackSizingDirection dire ction, const Vector<GridTrack>& tracks)
841 { 847 {
842 for (size_t i = 0; i < tracks.size(); ++i) { 848 for (size_t i = 0; i < tracks.size(); ++i) {
843 GridTrackSize trackSize = gridTrackSize(direction, i); 849 GridTrackSize trackSize = gridTrackSize(direction, i);
844 const GridLength& minTrackBreadth = trackSize.minTrackBreadth(); 850 const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
845 if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i ].baseSize()) 851 if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i ].baseSize())
(...skipping 813 matching lines...) Expand 10 before | Expand all | Expand 10 after
1659 if (isOutOfFlowPositioned()) 1665 if (isOutOfFlowPositioned())
1660 return "RenderGrid (positioned)"; 1666 return "RenderGrid (positioned)";
1661 if (isAnonymous()) 1667 if (isAnonymous())
1662 return "RenderGrid (generated)"; 1668 return "RenderGrid (generated)";
1663 if (isRelPositioned()) 1669 if (isRelPositioned())
1664 return "RenderGrid (relative positioned)"; 1670 return "RenderGrid (relative positioned)";
1665 return "RenderGrid"; 1671 return "RenderGrid";
1666 } 1672 }
1667 1673
1668 } // namespace blink 1674 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderGrid.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698