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

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

Issue 196943026: [CSS Grid Layout] Support span in auto-placement algorithm (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: New rebased version including review comments Created 6 years, 7 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 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 } 197 }
198 198
199 RenderBox* newChildBox = toRenderBox(newChild); 199 RenderBox* newChildBox = toRenderBox(newChild);
200 OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFr omStyle(*style(), *newChildBox, ForRows); 200 OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositionsFr omStyle(*style(), *newChildBox, ForRows);
201 OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPosition sFromStyle(*style(), *newChildBox, ForColumns); 201 OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPosition sFromStyle(*style(), *newChildBox, ForColumns);
202 if (!rowPositions || !columnPositions) { 202 if (!rowPositions || !columnPositions) {
203 // The new child requires the auto-placement algorithm to run so we need to recompute the grid fully. 203 // The new child requires the auto-placement algorithm to run so we need to recompute the grid fully.
204 dirtyGrid(); 204 dirtyGrid();
205 return; 205 return;
206 } else { 206 } else {
207 // Ensure that the grid is big enough to contain new grid item.
208 if (gridRowCount() <= rowPositions->resolvedFinalPosition.toInt())
209 growGrid(ForRows, rowPositions->resolvedFinalPosition.toInt());
210 if (gridColumnCount() <= columnPositions->resolvedFinalPosition.toInt())
211 growGrid(ForColumns, columnPositions->resolvedFinalPosition.toInt()) ;
212
213 insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPos itions)); 207 insertItemIntoGrid(newChildBox, GridCoordinate(*rowPositions, *columnPos itions));
214 addChildToIndexesMap(newChildBox); 208 addChildToIndexesMap(newChildBox);
215 } 209 }
216 } 210 }
217 211
218 void RenderGrid::addChildToIndexesMap(RenderBox* child) 212 void RenderGrid::addChildToIndexesMap(RenderBox* child)
219 { 213 {
220 ASSERT(!m_gridItemsIndexesMap.contains(child)); 214 ASSERT(!m_gridItemsIndexesMap.contains(child));
221 RenderBox* sibling = child->nextSiblingBox(); 215 RenderBox* sibling = child->nextSiblingBox();
222 bool lastSibling = !sibling; 216 bool lastSibling = !sibling;
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 ASSERT(maximumPositionIndex >= gridRowCount()); 738 ASSERT(maximumPositionIndex >= gridRowCount());
745 const size_t oldRowSize = gridRowCount(); 739 const size_t oldRowSize = gridRowCount();
746 m_grid.grow(maximumPositionIndex + 1); 740 m_grid.grow(maximumPositionIndex + 1);
747 for (size_t row = oldRowSize; row < gridRowCount(); ++row) 741 for (size_t row = oldRowSize; row < gridRowCount(); ++row)
748 m_grid[row].grow(gridColumnCount()); 742 m_grid[row].grow(gridColumnCount());
749 } 743 }
750 } 744 }
751 745
752 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coor dinate) 746 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coor dinate)
753 { 747 {
748 // Ensure that the grid is big enough to contain new grid item.
749 if (gridRowCount() <= coordinate.rows.resolvedFinalPosition.toInt())
750 growGrid(ForRows, coordinate.rows.resolvedFinalPosition.toInt());
751 if (gridColumnCount() <= coordinate.columns.resolvedFinalPosition.toInt())
752 growGrid(ForColumns, coordinate.columns.resolvedFinalPosition.toInt());
Julien - ping for review 2014/05/29 21:07:00 I think we should just unconditionally ensure enou
753
754 for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.row s.end(); ++row) { 754 for (GridSpan::iterator row = coordinate.rows.begin(); row != coordinate.row s.end(); ++row) {
755 for (GridSpan::iterator column = coordinate.columns.begin(); column != c oordinate.columns.end(); ++column) 755 for (GridSpan::iterator column = coordinate.columns.begin(); column != c oordinate.columns.end(); ++column)
756 m_grid[row.toInt()][column.toInt()].append(child); 756 m_grid[row.toInt()][column.toInt()].append(child);
757 } 757 }
758 758
759 m_gridItemCoordinate.set(child, coordinate); 759 m_gridItemCoordinate.set(child, coordinate);
760 } 760 }
761 761
762 void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridResolvedPosition & rowTrack, const GridResolvedPosition& columnTrack)
763 {
764 const GridSpan& rowSpan = GridResolvedPosition::resolveGridPositionsFromAuto PlacementPosition(*child, ForRows, rowTrack);
765 const GridSpan& columnSpan = GridResolvedPosition::resolveGridPositionsFromA utoPlacementPosition(*child, ForColumns, columnTrack);
766 insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
767 }
768
769 void RenderGrid::placeItemsOnGrid() 762 void RenderGrid::placeItemsOnGrid()
770 { 763 {
771 if (!gridIsDirty()) 764 if (!gridIsDirty())
772 return; 765 return;
773 766
774 ASSERT(m_gridItemCoordinate.isEmpty()); 767 ASSERT(m_gridItemCoordinate.isEmpty());
775 768
776 populateExplicitGridAndOrderIterator(); 769 populateExplicitGridAndOrderIterator();
777 770
778 // We clear the dirty bit here as the grid sizes have been updated, this mea ns 771 // We clear the dirty bit here as the grid sizes have been updated, this mea ns
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
824 ASSERT(m_gridItemsIndexesMap.isEmpty()); 817 ASSERT(m_gridItemsIndexesMap.isEmpty());
825 size_t childIndex = 0; 818 size_t childIndex = 0;
826 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBo x()) { 819 for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBo x()) {
827 populator.collectChild(child); 820 populator.collectChild(child);
828 m_gridItemsIndexesMap.set(child, childIndex++); 821 m_gridItemsIndexesMap.set(child, childIndex++);
829 822
830 // This function bypasses the cache (cachedGridCoordinate()) as it is us ed to build it. 823 // This function bypasses the cache (cachedGridCoordinate()) as it is us ed to build it.
831 OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositio nsFromStyle(*style(), *child, ForRows); 824 OwnPtr<GridSpan> rowPositions = GridResolvedPosition::resolveGridPositio nsFromStyle(*style(), *child, ForRows);
832 OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPosi tionsFromStyle(*style(), *child, ForColumns); 825 OwnPtr<GridSpan> columnPositions = GridResolvedPosition::resolveGridPosi tionsFromStyle(*style(), *child, ForColumns);
833 826
834 // |positions| is 0 if we need to run the auto-placement algorithm. Our estimation ignores 827 // |positions| is 0 if we need to run the auto-placement algorithm.
835 // this case as the auto-placement algorithm will grow the grid as neede d. 828 if (rowPositions) {
836 if (rowPositions)
837 maximumRowIndex = std::max<size_t>(maximumRowIndex, rowPositions->re solvedFinalPosition.next().toInt()); 829 maximumRowIndex = std::max<size_t>(maximumRowIndex, rowPositions->re solvedFinalPosition.next().toInt());
838 if (columnPositions) 830 } else if (autoPlacementMinorAxisDirection() == ForRows) {
831 // Grow the grid for items with a definite row span, getting the lar gest such span.
832 OwnPtr<GridSpan> positions = GridResolvedPosition::resolveGridPositi onsFromAutoPlacementPosition(*style(), *child, ForRows, GridResolvedPosition(0)) ;
833 maximumRowIndex = std::max<size_t>(maximumRowIndex, positions->resol vedFinalPosition.next().toInt());
834 }
835
836 if (columnPositions) {
839 maximumColumnIndex = std::max<size_t>(maximumColumnIndex, columnPosi tions->resolvedFinalPosition.next().toInt()); 837 maximumColumnIndex = std::max<size_t>(maximumColumnIndex, columnPosi tions->resolvedFinalPosition.next().toInt());
838 } else if (autoPlacementMinorAxisDirection() == ForColumns) {
Julien - ping for review 2014/05/29 21:07:00 I still don't agree with being conditional here.
839 // Grow the grid for items with a definite column span, getting the largest such span.
840 OwnPtr<GridSpan> positions = GridResolvedPosition::resolveGridPositi onsFromAutoPlacementPosition(*style(), *child, ForColumns, GridResolvedPosition( 0));
841 maximumColumnIndex = std::max<size_t>(maximumColumnIndex, positions- >resolvedFinalPosition.next().toInt());
842 }
840 } 843 }
841 844
842 m_grid.grow(maximumRowIndex); 845 m_grid.grow(maximumRowIndex);
843 for (size_t i = 0; i < m_grid.size(); ++i) 846 for (size_t i = 0; i < m_grid.size(); ++i)
844 m_grid[i].grow(maximumColumnIndex); 847 m_grid[i].grow(maximumColumnIndex);
845 } 848 }
846 849
850 bool RenderGrid::checkEmptyCells(const GridCoordinate& coordinate) const
851 {
852 // Ignore cells outside current grid as we will grow it later if needed.
853 size_t maxRows = std::min(coordinate.rows.resolvedFinalPosition.next().toInt (), gridRowCount());
854 size_t maxColumns = std::min(coordinate.columns.resolvedFinalPosition.next() .toInt(), gridColumnCount());
855
856 // This adds a O(N^2) behavior that shouldn't be a big deal as we expect spa nning areas to be small.
857 for (size_t row = coordinate.rows.resolvedInitialPosition.toInt(); row < max Rows; ++row) {
858 for (size_t column = coordinate.columns.resolvedInitialPosition.toInt(); column < maxColumns; ++column) {
859 const GridCell& children = m_grid[row][column];
860 if (!children.isEmpty())
861 return false;
862 }
863 }
864
865 return true;
866 }
867
868 PassOwnPtr<GridCoordinate> RenderGrid::createEmptyGridAreaAtSpecifiedPositionsOu tsideGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection , const GridSpan& specifiedPositions) const
869 {
870 GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
871 const size_t endOfCrossDirection = crossDirection == ForColumns ? gridColumn Count() : gridRowCount();
872 OwnPtr<GridSpan> crossDirectionPositions = GridResolvedPosition::resolveGrid PositionsFromAutoPlacementPosition(*style(), *gridItem, crossDirection, GridReso lvedPosition(endOfCrossDirection));
873 return adoptPtr(new GridCoordinate(specifiedDirection == ForColumns ? *cross DirectionPositions : specifiedPositions, specifiedDirection == ForColumns ? spec ifiedPositions : *crossDirectionPositions));
874 }
875
876 PassOwnPtr<GridCoordinate> RenderGrid::findEmptyGridAreaAtSpecifiedPositionsInsi deGrid(const RenderBox* gridItem, GridTrackSizingDirection specifiedDirection, c onst GridSpan& specifiedPositions) const
877 {
878 GridTrackSizingDirection crossDirection = specifiedDirection == ForColumns ? ForRows : ForColumns;
879
880 GridIterator iterator(m_grid, specifiedDirection, specifiedPositions.resolve dInitialPosition.toInt());
881 OwnPtr<GridCoordinate> emptyGridArea;
882 for (emptyGridArea = iterator.nextEmptyGridArea(); emptyGridArea; emptyGridA rea = iterator.nextEmptyGridArea()) {
883 GridResolvedPosition crossDirectionInitialPositionIndex = crossDirection == ForColumns ? emptyGridArea->columns.resolvedInitialPosition : emptyGridArea- >rows.resolvedInitialPosition;
884 OwnPtr<GridSpan> crossDirectionPositions = GridResolvedPosition::resolve GridPositionsFromAutoPlacementPosition(*style(), *gridItem, crossDirection, cros sDirectionInitialPositionIndex);
885
886 emptyGridArea->rows = specifiedDirection == ForColumns ? *crossDirection Positions : specifiedPositions;
887 emptyGridArea->columns = specifiedDirection == ForColumns ? specifiedPos itions : *crossDirectionPositions;
888 if (checkEmptyCells(*emptyGridArea))
889 break;
890 }
891
892 return emptyGridArea.release();
893 }
894
847 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& au toGridItems) 895 void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(const Vector<RenderBox*>& au toGridItems)
848 { 896 {
849 for (size_t i = 0; i < autoGridItems.size(); ++i) { 897 for (size_t i = 0; i < autoGridItems.size(); ++i) {
850 OwnPtr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveGridP ositionsFromStyle(*style(), *autoGridItems[i], autoPlacementMajorAxisDirection() ); 898 OwnPtr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveGridP ositionsFromStyle(*style(), *autoGridItems[i], autoPlacementMajorAxisDirection() );
851 GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAx isPositions->resolvedInitialPosition.toInt()); 899 OwnPtr<GridCoordinate> emptyGridArea = findEmptyGridAreaAtSpecifiedPosit ionsInsideGrid(autoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPo sitions);
852 if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) { 900 if (!emptyGridArea)
853 insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.resolvedIni tialPosition, emptyGridArea->columns.resolvedInitialPosition); 901 emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(a utoGridItems[i], autoPlacementMajorAxisDirection(), *majorAxisPositions);
854 continue; 902 insertItemIntoGrid(autoGridItems[i], *emptyGridArea);
855 }
856
857 growGrid(autoPlacementMinorAxisDirection(), autoPlacementMinorAxisDirect ion() == ForColumns ? gridColumnCount() : gridRowCount());
858 OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
859 ASSERT(emptyGridArea);
860 insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.resolvedInitial Position, emptyGridArea->columns.resolvedInitialPosition);
861 } 903 }
862 } 904 }
863 905
864 void RenderGrid::placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGri dItems) 906 void RenderGrid::placeAutoMajorAxisItemsOnGrid(const Vector<RenderBox*>& autoGri dItems)
865 { 907 {
866 for (size_t i = 0; i < autoGridItems.size(); ++i) 908 for (size_t i = 0; i < autoGridItems.size(); ++i)
867 placeAutoMajorAxisItemOnGrid(autoGridItems[i]); 909 placeAutoMajorAxisItemOnGrid(autoGridItems[i]);
868 } 910 }
869 911
870 void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem) 912 void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
871 { 913 {
872 OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPosit ionsFromStyle(*style(), *gridItem, autoPlacementMinorAxisDirection()); 914 OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveGridPosit ionsFromStyle(*style(), *gridItem, autoPlacementMinorAxisDirection());
873 ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridI tem, autoPlacementMajorAxisDirection())); 915 ASSERT(!GridResolvedPosition::resolveGridPositionsFromStyle(*style(), *gridI tem, autoPlacementMajorAxisDirection()));
874 size_t minorAxisIndex = 0; 916 OwnPtr<GridCoordinate> emptyGridArea;
875 if (minorAxisPositions) { 917 if (minorAxisPositions) {
876 minorAxisIndex = minorAxisPositions->resolvedInitialPosition.toInt(); 918 emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(gridItem , autoPlacementMinorAxisDirection(), *minorAxisPositions);
877 GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAx isIndex); 919 if (!emptyGridArea)
878 if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) { 920 emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(g ridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions);
879 insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitialPosi tion, emptyGridArea->columns.resolvedInitialPosition);
880 return;
881 }
882 } else { 921 } else {
883 const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForC olumns) ? gridColumnCount() : gridRowCount(); 922 const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForC olumns) ? gridColumnCount() : gridRowCount();
884 for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++major AxisIndex) { 923 for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++major AxisIndex) {
885 GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), maj orAxisIndex); 924 // We need to resolve the position for every different index as the number of cells might vary depending on it.
886 if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridAre a()) { 925 // This will happen when we have "span <custom-indent>", which has a different resolution based on the position.
887 insertItemIntoGrid(gridItem, emptyGridArea->rows.resolvedInitial Position, emptyGridArea->columns.resolvedInitialPosition); 926 OwnPtr<GridSpan> majorAxisPositions = GridResolvedPosition::resolveG ridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMajorAxi sDirection(), majorAxisIndex);
888 return; 927 emptyGridArea = findEmptyGridAreaAtSpecifiedPositionsInsideGrid(grid Item, autoPlacementMajorAxisDirection(), *majorAxisPositions);
928
929 if (emptyGridArea) {
930 // Check that it fits in the minor axis direction, as we shouldn 't grow in that direction here (it was already managed in populateExplicitGridAn dOrderIterator()).
931 GridResolvedPosition minorAxisFinalPositionIndex = autoPlacement MinorAxisDirection() == ForColumns ? emptyGridArea->columns.resolvedFinalPositio n : emptyGridArea->rows.resolvedFinalPosition;
932 const size_t endOfMinorAxis = autoPlacementMinorAxisDirection() == ForColumns ? gridColumnCount() : gridRowCount();
933 if (minorAxisFinalPositionIndex.toInt() < endOfMinorAxis)
934 break;
889 } 935 }
890 } 936 }
937
938 if (!emptyGridArea) {
939 OwnPtr<GridSpan> minorAxisPositions = GridResolvedPosition::resolveG ridPositionsFromAutoPlacementPosition(*style(), *gridItem, autoPlacementMinorAxi sDirection(), GridResolvedPosition(0));
940 emptyGridArea = createEmptyGridAreaAtSpecifiedPositionsOutsideGrid(g ridItem, autoPlacementMinorAxisDirection(), *minorAxisPositions);
941 }
891 } 942 }
892 943
893 // We didn't find an empty grid area so we need to create an extra major axi s line and insert our gridItem in it. 944 insertItemIntoGrid(gridItem, *emptyGridArea);
894 const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : minorAxisIndex;
895 const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : gridRowCount();
896 growGrid(autoPlacementMajorAxisDirection(), autoPlacementMajorAxisDirection( ) == ForColumns ? gridColumnCount() : gridRowCount());
897 insertItemIntoGrid(gridItem, rowIndex, columnIndex);
898 } 945 }
899 946
900 GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const 947 GridTrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
901 { 948 {
902 GridAutoFlow flow = style()->gridAutoFlow(); 949 GridAutoFlow flow = style()->gridAutoFlow();
903 ASSERT(flow != AutoFlowNone); 950 ASSERT(flow != AutoFlowNone);
904 return (flow == AutoFlowColumn) ? ForColumns : ForRows; 951 return (flow == AutoFlowColumn) ? ForColumns : ForRows;
905 } 952 }
906 953
907 GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const 954 GridTrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
1212 if (isOutOfFlowPositioned()) 1259 if (isOutOfFlowPositioned())
1213 return "RenderGrid (positioned)"; 1260 return "RenderGrid (positioned)";
1214 if (isAnonymous()) 1261 if (isAnonymous())
1215 return "RenderGrid (generated)"; 1262 return "RenderGrid (generated)";
1216 if (isRelPositioned()) 1263 if (isRelPositioned())
1217 return "RenderGrid (relative positioned)"; 1264 return "RenderGrid (relative positioned)";
1218 return "RenderGrid"; 1265 return "RenderGrid";
1219 } 1266 }
1220 1267
1221 } // namespace WebCore 1268 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698