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

Side by Side Diff: third_party/WebKit/Source/core/layout/LayoutTableSection.cpp

Issue 2433473002: Move table row pagination strut insertion to the first layout pass. (Closed)
Patch Set: Rebaseline semi-manually thank you very much. Created 4 years, 2 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 | « third_party/WebKit/Source/core/layout/LayoutTableSection.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) 1997 Martin Jones (mjones@kde.org) 2 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org) 3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org) 4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org) 5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org) 6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc. 7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2013 Apple Inc.
8 * All rights reserved. 8 * All rights reserved.
9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) 9 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
10 * 10 *
(...skipping 842 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 853
854 SpanningLayoutTableCells rowSpanCells; 854 SpanningLayoutTableCells rowSpanCells;
855 #if ENABLE(ASSERT) 855 #if ENABLE(ASSERT)
856 HashSet<const LayoutTableCell*> uniqueCells; 856 HashSet<const LayoutTableCell*> uniqueCells;
857 #endif 857 #endif
858 858
859 for (unsigned r = 0; r < m_grid.size(); r++) { 859 for (unsigned r = 0; r < m_grid.size(); r++) {
860 m_grid[r].baseline = -1; 860 m_grid[r].baseline = -1;
861 int baselineDescent = 0; 861 int baselineDescent = 0;
862 862
863 if (state.isPaginated() && m_grid[r].rowLayoutObject)
864 m_rowPos[r] += m_grid[r].rowLayoutObject->paginationStrut().ceil();
865
863 if (m_grid[r].logicalHeight.isSpecified()) { 866 if (m_grid[r].logicalHeight.isSpecified()) {
864 // Our base size is the biggest logical height from our cells' styles 867 // Our base size is the biggest logical height from our cells' styles
865 // (excluding row spanning cells). 868 // (excluding row spanning cells).
866 m_rowPos[r + 1] = std::max( 869 m_rowPos[r + 1] = std::max(
867 m_rowPos[r] + 870 m_rowPos[r] +
868 minimumValueForLength(m_grid[r].logicalHeight, LayoutUnit()) 871 minimumValueForLength(m_grid[r].logicalHeight, LayoutUnit())
869 .round(), 872 .round(),
870 0); 873 0);
871 } else { 874 } else {
872 // Non-specified lengths are ignored because the row already accounts for 875 // Non-specified lengths are ignored because the row already accounts for
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
971 } 974 }
972 975
973 if (LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject) { 976 if (LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject) {
974 if (state.isPaginated()) { 977 if (state.isPaginated()) {
975 rowLayoutObject->setLogicalTop(rowLogicalTop); 978 rowLayoutObject->setLogicalTop(rowLogicalTop);
976 if (!rowLayoutObject->needsLayout()) 979 if (!rowLayoutObject->needsLayout())
977 markChildForPaginationRelayoutIfNeeded(*rowLayoutObject, layouter); 980 markChildForPaginationRelayoutIfNeeded(*rowLayoutObject, layouter);
978 } 981 }
979 rowLayoutObject->layoutIfNeeded(); 982 rowLayoutObject->layoutIfNeeded();
980 if (state.isPaginated()) { 983 if (state.isPaginated()) {
981 rowLayoutObject->setLogicalHeight( 984 adjustRowForPagination(*rowLayoutObject, layouter);
982 LayoutUnit(logicalHeightForRow(*rowLayoutObject)));
983 rowLogicalTop = rowLayoutObject->logicalBottom(); 985 rowLogicalTop = rowLayoutObject->logicalBottom();
984 rowLogicalTop += LayoutUnit(table()->vBorderSpacing()); 986 rowLogicalTop += LayoutUnit(table()->vBorderSpacing());
985 } 987 }
986 } 988 }
987 } 989 }
988 990
989 clearNeedsLayout(); 991 clearNeedsLayout();
990 } 992 }
991 993
992 void LayoutTableSection::distributeExtraLogicalHeightToPercentRows( 994 void LayoutTableSection::distributeExtraLogicalHeightToPercentRows(
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1111 // FIXME: Changing the height without a layout can change the overflow so it 1113 // FIXME: Changing the height without a layout can change the overflow so it
1112 // seems wrong. 1114 // seems wrong.
1113 1115
1114 unsigned totalRows = m_grid.size(); 1116 unsigned totalRows = m_grid.size();
1115 1117
1116 // Set the width of our section now. The rows will also be this width. 1118 // Set the width of our section now. The rows will also be this width.
1117 setLogicalWidth(table()->contentLogicalWidth()); 1119 setLogicalWidth(table()->contentLogicalWidth());
1118 1120
1119 int vspacing = table()->vBorderSpacing(); 1121 int vspacing = table()->vBorderSpacing();
1120 unsigned nEffCols = table()->numEffectiveColumns(); 1122 unsigned nEffCols = table()->numEffectiveColumns();
1121 bool isPaginated = view()->layoutState()->isPaginated();
1122
1123 if (isPaginated) {
1124 LayoutTableSection* header = table()->header();
1125 // If we're a table header nested inside a table cell then we want to repeat
1126 // on each page, but below the header we're nested inside. Note we don't try
1127 // to match the padding on the cell on each repeated header.
1128 if (header && header == this)
1129 setOffsetForRepeatingHeader(
1130 view()->layoutState()->heightOffsetForTableHeaders());
1131 }
1132
1133 LayoutState state(*this, locationOffset()); 1123 LayoutState state(*this, locationOffset());
1134 1124
1125 // Set the rows' location and size.
1135 for (unsigned r = 0; r < totalRows; r++) { 1126 for (unsigned r = 0; r < totalRows; r++) {
1136 // Set the row's x/y position and width/height.
1137 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject; 1127 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject;
1138 int paginationStrutOnRow = 0;
1139 if (rowLayoutObject) { 1128 if (rowLayoutObject) {
1140 rowLayoutObject->setLogicalLocation(LayoutPoint(0, m_rowPos[r])); 1129 rowLayoutObject->setLogicalLocation(LayoutPoint(0, m_rowPos[r]));
1141 rowLayoutObject->setLogicalWidth(logicalWidth()); 1130 rowLayoutObject->setLogicalWidth(logicalWidth());
1142 rowLayoutObject->setLogicalHeight( 1131 LayoutUnit rowLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
1143 LayoutUnit(m_rowPos[r + 1] - m_rowPos[r] - vspacing)); 1132 if (state.isPaginated() && r + 1 < totalRows) {
1133 // If the next row has a pagination strut, we need to subtract it. It
1134 // should not be included in this row's height.
1135 if (LayoutTableRow* nextRowObject = m_grid[r + 1].rowLayoutObject)
1136 rowLogicalHeight -= nextRowObject->paginationStrut();
1137 }
1138 rowLayoutObject->setLogicalHeight(rowLogicalHeight);
1144 rowLayoutObject->updateLayerTransformAfterLayout(); 1139 rowLayoutObject->updateLayerTransformAfterLayout();
1145 if (isPaginated) {
1146 paginationStrutOnRow =
1147 paginationStrutForRow(rowLayoutObject, LayoutUnit(m_rowPos[r]));
1148 rowLayoutObject->setPaginationStrut(LayoutUnit(paginationStrutOnRow));
1149 bool rowIsAtTopOfColumn =
1150 state.heightOffsetForTableHeaders() &&
1151 pageRemainingLogicalHeightForOffset(LayoutUnit(m_rowPos[r]),
1152 AssociateWithLatterPage) ==
1153 pageLogicalHeightForOffset(LayoutUnit(m_rowPos[r]));
1154 if (paginationStrutOnRow || rowIsAtTopOfColumn) {
1155 // If there isn't room for at least one content row on a page with a
1156 // header group, then we won't repeat the header on each page.
1157 if (!r && table()->header() &&
1158 table()->sectionAbove(this) == table()->header() &&
1159 table()->header()->getPaginationBreakability() != AllowAnyBreaks)
1160 state.setHeightOffsetForTableHeaders(
1161 state.heightOffsetForTableHeaders() -
1162 table()->header()->logicalHeight());
1163 // If we have a header group we will paint it at the top of each page,
1164 // move the rows down to accomodate it.
1165 paginationStrutOnRow += state.heightOffsetForTableHeaders().toInt();
1166 for (unsigned rowIndex = r; rowIndex <= totalRows; rowIndex++)
1167 m_rowPos[rowIndex] += paginationStrutOnRow;
1168 }
1169 }
1170 } 1140 }
1141 }
1171 1142
1143 // Vertically align and flex the cells in each row.
1144 for (unsigned r = 0; r < totalRows; r++) {
1145 LayoutTableRow* rowLayoutObject = m_grid[r].rowLayoutObject;
1172 int rowHeightIncreaseForPagination = INT_MIN; 1146 int rowHeightIncreaseForPagination = INT_MIN;
1173 1147
1174 for (unsigned c = 0; c < nEffCols; c++) { 1148 for (unsigned c = 0; c < nEffCols; c++) {
1175 CellStruct& cs = cellAt(r, c); 1149 CellStruct& cs = cellAt(r, c);
1176 LayoutTableCell* cell = cs.primaryCell(); 1150 LayoutTableCell* cell = cs.primaryCell();
1177 1151
1178 if (!cell || cs.inColSpan) 1152 if (!cell || cs.inColSpan)
1179 continue; 1153 continue;
1180 1154
1181 int rowIndex = cell->rowIndex(); 1155 if (cell->rowIndex() != r)
1182 int rHeight = 1156 continue; // Rowspanned cells are handled in the first row they occur.
1183 m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing; 1157
1158 int rHeight;
1159 int rowLogicalTop;
1160 unsigned rowSpan = std::max(1U, cell->rowSpan());
1161 unsigned endRowIndex = std::min(r + rowSpan, totalRows) - 1;
1162 LayoutTableRow* lastRowObject = m_grid[endRowIndex].rowLayoutObject;
1163 if (lastRowObject && rowLayoutObject) {
1164 rowLogicalTop = rowLayoutObject->logicalTop().toInt();
1165 rHeight = lastRowObject->logicalBottom().toInt() - rowLogicalTop;
1166 } else {
1167 rHeight = m_rowPos[endRowIndex + 1] - m_rowPos[r] - vspacing;
1168 rowLogicalTop = m_rowPos[r];
1169 }
1184 1170
1185 relayoutCellIfFlexed(*cell, r, rHeight); 1171 relayoutCellIfFlexed(*cell, r, rHeight);
1186 1172
1187 SubtreeLayoutScope layouter(*cell); 1173 SubtreeLayoutScope layouter(*cell);
1188 LayoutUnit rowLogicalTop(m_rowPos[rowIndex]);
1189 EVerticalAlign cellVerticalAlign; 1174 EVerticalAlign cellVerticalAlign;
1190 // If the cell crosses a fragmentainer boundary, just align it at the 1175 // If the cell crosses a fragmentainer boundary, just align it at the
1191 // top. That's how it was laid out initially, before we knew the final 1176 // top. That's how it was laid out initially, before we knew the final
1192 // row height, and re-aligning it now could result in the cell being 1177 // row height, and re-aligning it now could result in the cell being
1193 // fragmented differently, which could change its height and thus violate 1178 // fragmented differently, which could change its height and thus violate
1194 // the requested alignment. Give up instead of risking circular 1179 // the requested alignment. Give up instead of risking circular
1195 // dependencies and unstable layout. 1180 // dependencies and unstable layout.
1196 if (state.isPaginated() && 1181 if (state.isPaginated() &&
1197 crossesPageBoundary(rowLogicalTop, LayoutUnit(rHeight))) 1182 crossesPageBoundary(LayoutUnit(rowLogicalTop), LayoutUnit(rHeight)))
1198 cellVerticalAlign = VerticalAlignTop; 1183 cellVerticalAlign = VerticalAlignTop;
1199 else 1184 else
1200 cellVerticalAlign = cell->style()->verticalAlign(); 1185 cellVerticalAlign = cell->style()->verticalAlign();
1201 cell->computeIntrinsicPadding(rHeight, cellVerticalAlign, layouter); 1186 cell->computeIntrinsicPadding(rHeight, cellVerticalAlign, layouter);
1202 1187
1203 LayoutRect oldCellRect = cell->frameRect(); 1188 LayoutRect oldCellRect = cell->frameRect();
1204 1189
1205 setLogicalPositionForCell(cell, c); 1190 setLogicalPositionForCell(cell, c);
1206 1191
1207 if (!cell->needsLayout()) 1192 if (!cell->needsLayout())
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
1991 // TODO(mstensho): Rowspanned cells also need to contribute to row heights 1976 // TODO(mstensho): Rowspanned cells also need to contribute to row heights
1992 // during the first layout pass, in order to get fragmentation right. 1977 // during the first layout pass, in order to get fragmentation right.
1993 if (cell->rowSpan() == 1) { 1978 if (cell->rowSpan() == 1) {
1994 logicalHeight = 1979 logicalHeight =
1995 std::max(logicalHeight, cell->logicalHeightForRowSizing()); 1980 std::max(logicalHeight, cell->logicalHeightForRowSizing());
1996 } 1981 }
1997 } 1982 }
1998 return logicalHeight; 1983 return logicalHeight;
1999 } 1984 }
2000 1985
1986 void LayoutTableSection::adjustRowForPagination(LayoutTableRow& rowObject,
1987 SubtreeLayoutScope& layouter) {
1988 LayoutState& state = *view()->layoutState();
1989 rowObject.setPaginationStrut(LayoutUnit());
1990 rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject)));
1991 int paginationStrut =
1992 paginationStrutForRow(&rowObject, rowObject.logicalTop());
1993 if (!paginationStrut) {
1994 bool rowIsAtTopOfColumn =
1995 state.heightOffsetForTableHeaders() &&
1996 pageLogicalHeightForOffset(rowObject.logicalTop()) ==
1997 pageRemainingLogicalHeightForOffset(rowObject.logicalTop(),
1998 AssociateWithLatterPage);
1999 if (!rowIsAtTopOfColumn)
2000 return;
2001 }
2002 // We need to push this row to the next fragmentainer. If there are repeated
2003 // table headers, we need to make room for those at the top of the next
2004 // fragmentainer, above this row. Otherwise, this row will just go at the top
2005 // of the next fragmentainer.
2006
2007 // If there isn't room for at least one content row on a page with a
2008 // header group, then we won't repeat the header on each page.
2009 LayoutTableSection* header = table()->header();
2010 if (!rowObject.rowIndex() && header &&
2011 table()->sectionAbove(this) == header &&
2012 header->getPaginationBreakability() != AllowAnyBreaks) {
2013 state.setHeightOffsetForTableHeaders(state.heightOffsetForTableHeaders() -
2014 header->logicalHeight());
2015 }
2016 // If we have a header group we will paint it at the top of each page,
2017 // move the rows down to accomodate it.
2018 paginationStrut += state.heightOffsetForTableHeaders().toInt();
2019 rowObject.setPaginationStrut(LayoutUnit(paginationStrut));
2020
2021 // We have inserted a pagination strut before the row. Adjust the logical top
2022 // and re-lay out. We no longer want to break inside the row, but rather
2023 // *before* it. From the previous layout pass, there are most likely
2024 // pagination struts inside some cell in this row that we need to get rid of.
2025 rowObject.setLogicalTop(rowObject.logicalTop() + paginationStrut);
2026 layouter.setChildNeedsLayout(&rowObject);
2027 rowObject.layoutIfNeeded();
2028
2029 // It's very likely that re-laying out (and nuking pagination struts inside
2030 // cells) gave us a new height.
2031 rowObject.setLogicalHeight(LayoutUnit(logicalHeightForRow(rowObject)));
2032 }
2033
2001 bool LayoutTableSection::isRepeatingHeaderGroup() const { 2034 bool LayoutTableSection::isRepeatingHeaderGroup() const {
2002 if (getPaginationBreakability() == LayoutBox::AllowAnyBreaks) 2035 if (getPaginationBreakability() == LayoutBox::AllowAnyBreaks)
2003 return false; 2036 return false;
2004 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting? 2037 // TODO(rhogan): Should we paint a header repeatedly if it's self-painting?
2005 if (hasSelfPaintingLayer()) 2038 if (hasSelfPaintingLayer())
2006 return false; 2039 return false;
2007 LayoutUnit pageHeight = table()->pageLogicalHeightForOffset(LayoutUnit()); 2040 LayoutUnit pageHeight = table()->pageLogicalHeightForOffset(LayoutUnit());
2008 if (!pageHeight) 2041 if (!pageHeight)
2009 return false; 2042 return false;
2010 2043
(...skipping 23 matching lines...) Expand all
2034 // the header in all columns. 2067 // the header in all columns.
2035 // Note that this is in flow thread coordinates, not visual coordinates. The 2068 // Note that this is in flow thread coordinates, not visual coordinates. The
2036 // enclosing LayoutFlowThread will convert to visual coordinates. 2069 // enclosing LayoutFlowThread will convert to visual coordinates.
2037 if (table()->header() == this && isRepeatingHeaderGroup()) 2070 if (table()->header() == this && isRepeatingHeaderGroup())
2038 rect.setHeight(table()->logicalHeight()); 2071 rect.setHeight(table()->logicalHeight());
2039 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect, 2072 return LayoutTableBoxComponent::mapToVisualRectInAncestorSpace(ancestor, rect,
2040 flags); 2073 flags);
2041 } 2074 }
2042 2075
2043 } // namespace blink 2076 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/LayoutTableSection.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698