OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |