blob: 182ec8658eddc53a302a8a72b71ad37b71ee5ae5 [file] [log] [blame]
darin@apple.com83833152008-01-14 17:51:10 +00001/*
eseidela043f3d2006-01-20 19:24:53 +00002 * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3 * (C) 1997 Torben Weis (weis@kde.org)
4 * (C) 1998 Waldo Bastian (bastian@kde.org)
5 * (C) 1999 Lars Knoll (knoll@kde.org)
6 * (C) 1999 Antti Koivisto (koivisto@kde.org)
mitz@apple.com8010bba2010-11-05 02:43:17 +00007 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
ap50b58352006-01-22 20:32:36 +00008 * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
eseidela043f3d2006-01-20 19:24:53 +00009 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
ddkilzerc8eccec2007-09-26 02:29:57 +000022 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
eseidela043f3d2006-01-20 19:24:53 +000024 */
25
26#include "config.h"
27#include "RenderTableSection.h"
darinb9481ed2006-03-20 02:57:59 +000028#include "Document.h"
tonikitoo@webkit.org81c027d2010-07-29 13:19:43 +000029#include "HitTestResult.h"
darin98fa8b82006-03-20 08:03:57 +000030#include "HTMLNames.h"
tonyg@chromium.orgb138b1e2011-01-15 00:27:07 +000031#include "PaintInfo.h"
cdumez@apple.com69626952016-05-17 22:39:00 +000032#include "RenderChildIterator.h"
abucur@adobe.com7f9668a2014-05-16 13:22:00 +000033#include "RenderNamedFlowFragment.h"
darin91298e52006-06-12 01:10:17 +000034#include "RenderTableCell.h"
35#include "RenderTableCol.h"
36#include "RenderTableRow.h"
cdumez@apple.com8faf7722014-10-13 18:21:11 +000037#include "RenderTextControl.h"
weinigfef13632007-04-29 20:09:08 +000038#include "RenderView.h"
commit-queue@webkit.orgd0c076d2012-08-22 22:25:59 +000039#include "StyleInheritedData.h"
darin91298e52006-06-12 01:10:17 +000040#include <limits>
jamesr@google.com36623a32010-07-23 20:22:29 +000041#include <wtf/HashSet.h>
andersca@apple.coma5fb7da2013-04-16 19:57:36 +000042#include <wtf/StackStats.h>
eseidela043f3d2006-01-20 19:24:53 +000043
44namespace WebCore {
45
46using namespace HTMLNames;
47
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +000048// Those 2 variables are used to balance the memory consumption vs the repaint time on big tables.
cdumez@apple.com4bf983a2015-05-19 07:22:36 +000049static const unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75;
50static const float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +000051
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +000052static inline void setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(RenderTableSection::RowStruct& row)
dbates@webkit.orge1131832009-11-19 00:05:57 +000053{
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +000054 ASSERT(row.rowRenderer);
akling@apple.com827be9c2013-10-29 02:58:43 +000055 row.logicalHeight = row.rowRenderer->style().logicalHeight();
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +000056 if (row.logicalHeight.isRelative())
57 row.logicalHeight = Length();
dbates@webkit.orge1131832009-11-19 00:05:57 +000058}
59
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +000060static inline void updateLogicalHeightForCell(RenderTableSection::RowStruct& row, const RenderTableCell* cell)
61{
62 // We ignore height settings on rowspan cells.
63 if (cell->rowSpan() != 1)
64 return;
65
akling@apple.com827be9c2013-10-29 02:58:43 +000066 Length logicalHeight = cell->style().logicalHeight();
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +000067 if (logicalHeight.isPositive() || (logicalHeight.isRelative() && logicalHeight.value() >= 0)) {
68 Length cRowLogicalHeight = row.logicalHeight;
69 switch (logicalHeight.type()) {
70 case Percent:
commit-queue@webkit.org2a67f682015-05-10 21:43:26 +000071 if (!cRowLogicalHeight.isPercent() || cRowLogicalHeight.percent() < logicalHeight.percent())
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +000072 row.logicalHeight = logicalHeight;
73 break;
74 case Fixed:
darin@apple.comb4326082014-04-08 08:58:43 +000075 if (cRowLogicalHeight.isAuto() || cRowLogicalHeight.isRelative()
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +000076 || (cRowLogicalHeight.isFixed() && cRowLogicalHeight.value() < logicalHeight.value()))
77 row.logicalHeight = logicalHeight;
78 break;
79 case Relative:
80 default:
81 break;
82 }
83 }
84}
85
antti@apple.com454418f2016-04-25 19:49:23 +000086RenderTableSection::RenderTableSection(Element& element, RenderStyle&& style)
aestes@apple.com13aae082016-01-02 08:03:08 +000087 : RenderBox(element, WTFMove(style), 0)
eseidela043f3d2006-01-20 19:24:53 +000088{
akling@apple.com42e10632013-10-14 17:55:52 +000089 setInline(false);
90}
91
antti@apple.com454418f2016-04-25 19:49:23 +000092RenderTableSection::RenderTableSection(Document& document, RenderStyle&& style)
aestes@apple.com13aae082016-01-02 08:03:08 +000093 : RenderBox(document, WTFMove(style), 0)
akling@apple.com42e10632013-10-14 17:55:52 +000094{
95 setInline(false);
eseidela043f3d2006-01-20 19:24:53 +000096}
97
98RenderTableSection::~RenderTableSection()
99{
eseidela043f3d2006-01-20 19:24:53 +0000100}
101
inferno@chromium.orga7f719f2011-09-06 01:45:39 +0000102void RenderTableSection::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
103{
104 RenderBox::styleDidChange(diff, oldStyle);
antti@apple.comcf4adae2013-09-24 00:55:44 +0000105 propagateStyleToAnonymousChildren(PropagateToAllChildren);
jchaffraix@webkit.org38e74af2011-09-23 19:56:21 +0000106
107 // If border was changed, notify table.
108 RenderTable* table = this->table();
zalan@apple.com42146622015-04-01 15:56:34 +0000109 if (table && oldStyle && oldStyle->border() != style().border())
jchaffraix@webkit.org38e74af2011-09-23 19:56:21 +0000110 table->invalidateCollapsedBorders();
inferno@chromium.orga7f719f2011-09-06 01:45:39 +0000111}
112
jchaffraix@webkit.org54b0e092012-08-22 02:16:02 +0000113void RenderTableSection::willBeRemovedFromTree()
eseidela043f3d2006-01-20 19:24:53 +0000114{
jchaffraix@webkit.org54b0e092012-08-22 02:16:02 +0000115 RenderBox::willBeRemovedFromTree();
116
117 // Preventively invalidate our cells as we may be re-inserted into
118 // a new table which would require us to rebuild our structure.
119 setNeedsCellRecalc();
eseidela043f3d2006-01-20 19:24:53 +0000120}
121
darin316ed062006-01-23 05:29:14 +0000122void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
eseidela043f3d2006-01-20 19:24:53 +0000123{
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000124 if (!is<RenderTableRow>(*child)) {
darin316ed062006-01-23 05:29:14 +0000125 RenderObject* last = beforeChild;
126 if (!last)
antti@apple.com7f9196b2013-09-24 20:47:01 +0000127 last = lastRow();
inferno@chromium.orga7f719f2011-09-06 01:45:39 +0000128 if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000129 RenderTableRow& row = downcast<RenderTableRow>(*last);
130 if (beforeChild == &row)
131 beforeChild = row.firstCell();
132 row.addChild(child, beforeChild);
darin316ed062006-01-23 05:29:14 +0000133 return;
134 }
135
inferno@chromium.orgb1ffad72011-10-10 18:58:12 +0000136 if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
137 RenderObject* row = beforeChild->previousSibling();
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000138 if (is<RenderTableRow>(row) && row->isAnonymous()) {
139 downcast<RenderTableRow>(*row).addChild(child);
inferno@chromium.orgb1ffad72011-10-10 18:58:12 +0000140 return;
141 }
142 }
143
darin10ab1352006-01-29 01:29:33 +0000144 // If beforeChild is inside an anonymous cell/row, insert into the cell or into
145 // the anonymous row containing it, if there is one.
darin316ed062006-01-23 05:29:14 +0000146 RenderObject* lastBox = last;
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000147 while (lastBox && lastBox->parent()->isAnonymous() && !is<RenderTableRow>(*lastBox))
darin316ed062006-01-23 05:29:14 +0000148 lastBox = lastBox->parent();
inferno@chromium.orga7f719f2011-09-06 01:45:39 +0000149 if (lastBox && lastBox->isAnonymous() && !lastBox->isBeforeOrAfterContent()) {
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000150 downcast<RenderTableRow>(*lastBox).addChild(child, beforeChild);
darin316ed062006-01-23 05:29:14 +0000151 return;
152 }
153
zalan@apple.comcda46e42016-07-26 02:40:04 +0000154 auto* row = RenderTableRow::createAnonymousWithParentRenderer(*this).release();
darin316ed062006-01-23 05:29:14 +0000155 addChild(row, beforeChild);
eseidela043f3d2006-01-20 19:24:53 +0000156 row->addChild(child);
eseidela043f3d2006-01-20 19:24:53 +0000157 return;
158 }
159
160 if (beforeChild)
ddkilzer260f3d22007-01-05 05:56:31 +0000161 setNeedsCellRecalc();
eseidela043f3d2006-01-20 19:24:53 +0000162
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000163 unsigned insertionRow = m_cRow;
ddkilzer260f3d22007-01-05 05:56:31 +0000164 ++m_cRow;
165 m_cCol = 0;
eseidela043f3d2006-01-20 19:24:53 +0000166
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000167 ensureRows(m_cRow);
larsb5288ad2007-01-13 18:48:29 +0000168
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000169 RenderTableRow& row = downcast<RenderTableRow>(*child);
170 m_grid[insertionRow].rowRenderer = &row;
171 row.setRowIndex(insertionRow);
eseidela043f3d2006-01-20 19:24:53 +0000172
dbates@webkit.orge1131832009-11-19 00:05:57 +0000173 if (!beforeChild)
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +0000174 setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
eseidela043f3d2006-01-20 19:24:53 +0000175
inferno@chromium.orga8d71922012-04-09 16:03:46 +0000176 if (beforeChild && beforeChild->parent() != this)
177 beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
mjs6666eee72006-07-14 07:45:13 +0000178
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000179 ASSERT(!beforeChild || is<RenderTableRow>(*beforeChild));
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000180 RenderBox::addChild(child, beforeChild);
eseidela043f3d2006-01-20 19:24:53 +0000181}
182
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000183void RenderTableSection::ensureRows(unsigned numRows)
eseidela043f3d2006-01-20 19:24:53 +0000184{
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000185 if (numRows <= m_grid.size())
186 return;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000187
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000188 unsigned oldSize = m_grid.size();
189 m_grid.grow(numRows);
eseidela043f3d2006-01-20 19:24:53 +0000190
andersca@apple.com86298632013-11-10 19:32:33 +0000191 unsigned effectiveColumnCount = std::max(1u, table()->numEffCols());
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000192 for (unsigned row = oldSize; row < m_grid.size(); ++row)
akling@apple.com194ce1d2013-11-13 11:46:51 +0000193 m_grid[row].row.resizeToFit(effectiveColumnCount);
eseidela043f3d2006-01-20 19:24:53 +0000194}
195
hyatt@apple.comd885df72009-01-22 02:31:52 +0000196void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
eseidela043f3d2006-01-20 19:24:53 +0000197{
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +0000198 // We don't insert the cell if we need cell recalc as our internal columns' representation
199 // will have drifted from the table's representation. Also recalcCells will call addCell
200 // at a later time after sync'ing our columns' with the table's.
201 if (needsCellRecalc())
202 return;
203
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000204 unsigned rSpan = cell->rowSpan();
205 unsigned cSpan = cell->colSpan();
jchaffraix@webkit.orgb87ce752012-10-15 21:52:22 +0000206 const Vector<RenderTable::ColumnStruct>& columns = table()->columns();
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000207 unsigned nCols = columns.size();
jchaffraix@webkit.orga0177fd2012-05-01 03:13:06 +0000208 unsigned insertionRow = row->rowIndex();
eseidela043f3d2006-01-20 19:24:53 +0000209
210 // ### mozilla still seems to do the old HTML way, even for strict DTD
211 // (see the annotation on table cell layouting in the CSS specs and the testcase below:
212 // <TABLE border>
213 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
214 // <TR><TD colspan="2">5
215 // </TABLE>
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000216 while (m_cCol < nCols && (cellAt(insertionRow, m_cCol).hasCells() || cellAt(insertionRow, m_cCol).inColSpan))
ddkilzer260f3d22007-01-05 05:56:31 +0000217 m_cCol++;
jamesr@google.comb4266232010-07-28 20:07:19 +0000218
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +0000219 updateLogicalHeightForCell(m_grid[insertionRow], cell);
eseidela043f3d2006-01-20 19:24:53 +0000220
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +0000221 ensureRows(insertionRow + rSpan);
eseidela043f3d2006-01-20 19:24:53 +0000222
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000223 m_grid[insertionRow].rowRenderer = row;
hyattd866e592006-03-17 09:50:35 +0000224
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000225 unsigned col = m_cCol;
eseidela043f3d2006-01-20 19:24:53 +0000226 // tell the cell where it is
jamesr@google.com36623a32010-07-23 20:22:29 +0000227 bool inColSpan = false;
eseidela043f3d2006-01-20 19:24:53 +0000228 while (cSpan) {
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000229 unsigned currentSpan;
jamesr@google.comb4266232010-07-28 20:07:19 +0000230 if (m_cCol >= nCols) {
231 table()->appendColumn(cSpan);
232 currentSpan = cSpan;
233 } else {
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000234 if (cSpan < columns[m_cCol].span)
jamesr@google.comb4266232010-07-28 20:07:19 +0000235 table()->splitColumn(m_cCol, cSpan);
236 currentSpan = columns[m_cCol].span;
237 }
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000238 for (unsigned r = 0; r < rSpan; r++) {
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000239 CellStruct& c = cellAt(insertionRow + r, m_cCol);
jamesr@google.comb4266232010-07-28 20:07:19 +0000240 ASSERT(cell);
241 c.cells.append(cell);
242 // If cells overlap then we take the slow path for painting.
243 if (c.cells.size() > 1)
244 m_hasMultipleCellLevels = true;
245 if (inColSpan)
246 c.inColSpan = true;
247 }
248 m_cCol++;
249 cSpan -= currentSpan;
250 inColSpan = true;
eseidela043f3d2006-01-20 19:24:53 +0000251 }
eric@webkit.org5832ab72009-03-25 22:15:03 +0000252 cell->setCol(table()->effColToCol(col));
eseidela043f3d2006-01-20 19:24:53 +0000253}
254
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000255LayoutUnit RenderTableSection::calcRowLogicalHeight()
eseidela043f3d2006-01-20 19:24:53 +0000256{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000257#ifndef NDEBUG
ojan@chromium.orgccdc4292013-02-07 00:55:10 +0000258 SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000259#endif
260
261 ASSERT(!needsLayout());
262
ddkilzer260f3d22007-01-05 05:56:31 +0000263 RenderTableCell* cell;
eseidela043f3d2006-01-20 19:24:53 +0000264
ossy@webkit.orgcf6bebb2013-11-25 14:57:38 +0000265 // We ignore the border-spacing on any non-top section as it is already included in the previous section's last row position.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000266 LayoutUnit spacing = 0;
ossy@webkit.orgcf6bebb2013-11-25 14:57:38 +0000267 if (this == table()->topSection())
268 spacing = table()->vBorderSpacing();
akling@apple.com691cf5c2013-08-24 16:33:15 +0000269
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000270 LayoutStateMaintainer statePusher(view());
eseidela043f3d2006-01-20 19:24:53 +0000271
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000272 m_rowPos.resize(m_grid.size() + 1);
ddkilzer260f3d22007-01-05 05:56:31 +0000273 m_rowPos[0] = spacing;
eseidela043f3d2006-01-20 19:24:53 +0000274
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000275 unsigned totalRows = m_grid.size();
276
277 for (unsigned r = 0; r < totalRows; r++) {
zimmermann@webkit.org14b310a2012-02-25 09:27:25 +0000278 m_grid[r].baseline = 0;
leviw@chromium.org2650e382012-04-04 10:37:36 +0000279 LayoutUnit baselineDescent = 0;
eseidela043f3d2006-01-20 19:24:53 +0000280
jchaffraix@webkit.orgaddd65e2012-02-26 00:19:22 +0000281 // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000282 m_rowPos[r + 1] = std::max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0), LayoutUnit::fromPixel(0));
eseidela043f3d2006-01-20 19:24:53 +0000283
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +0000284 Row& row = m_grid[r].row;
285 unsigned totalCols = row.size();
eseidela043f3d2006-01-20 19:24:53 +0000286
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000287 for (unsigned c = 0; c < totalCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000288 CellStruct& current = cellAt(r, c);
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000289 for (unsigned i = 0; i < current.cells.size(); i++) {
290 cell = current.cells[i];
291 if (current.inColSpan && cell->rowSpan() == 1)
292 continue;
jamesr@google.comb4266232010-07-28 20:07:19 +0000293
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000294 // FIXME: We are always adding the height of a rowspan to the last rows which doesn't match
295 // other browsers. See webkit.org/b/52185 for example.
296 if ((cell->rowIndex() + cell->rowSpan() - 1) != r) {
297 // We will apply the height of the rowspan to the current row if next row is not valid.
298 if ((r + 1) < totalRows) {
299 unsigned col = 0;
300 CellStruct nextRowCell = cellAt(r + 1, col);
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000301
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000302 // We are trying to find that next row is valid or not.
303 while (nextRowCell.cells.size() && nextRowCell.cells[0]->rowSpan() > 1 && nextRowCell.cells[0]->rowIndex() < (r + 1)) {
304 col++;
305 if (col < totalCols)
306 nextRowCell = cellAt(r + 1, col);
307 else
308 break;
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000309 }
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000310
311 // We are adding the height of the rowspan to the current row if next row is not valid.
312 if (col < totalCols && nextRowCell.cells.size())
313 continue;
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000314 }
315 }
jamesr@google.com36623a32010-07-23 20:22:29 +0000316
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000317 // For row spanning cells, |r| is the last row in the span.
318 unsigned cellStartRow = cell->rowIndex();
319
rego@igalia.comf7d624c2015-04-22 10:31:24 +0000320 if (cell->hasOverrideLogicalContentHeight()) {
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000321 if (!statePusher.didPush()) {
322 // Technically, we should also push state for the row, but since
323 // rows don't push a coordinate transform, that's not necessary.
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000324 statePusher.push(*this, locationOffset());
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000325 }
326 cell->clearIntrinsicPadding();
327 cell->clearOverrideSize();
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000328 cell->setChildNeedsLayout(MarkOnlyThis);
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000329 cell->layoutIfNeeded();
weinigfef13632007-04-29 20:09:08 +0000330 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000331
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000332 LayoutUnit cellLogicalHeight = cell->logicalHeightForRowSizing();
andersca@apple.com86298632013-11-10 19:32:33 +0000333 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cellLogicalHeight);
eseidela043f3d2006-01-20 19:24:53 +0000334
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000335 // Find out the baseline. The baseline is set on the first row in a rowspan.
robert@webkit.org292be542013-03-09 06:40:13 +0000336 if (cell->isBaselineAligned()) {
zalan@apple.comdf6351f2016-01-11 22:03:03 +0000337 LayoutUnit baselinePosition = cell->cellBaselinePosition() - cell->intrinsicPaddingBefore();
338 LayoutUnit borderAndComputedPaddingBefore = cell->borderAndPaddingBefore() - cell->intrinsicPaddingBefore();
339 if (baselinePosition > borderAndComputedPaddingBefore) {
andersca@apple.com86298632013-11-10 19:32:33 +0000340 m_grid[cellStartRow].baseline = std::max(m_grid[cellStartRow].baseline, baselinePosition);
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000341 // The descent of a cell that spans multiple rows does not affect the height of the first row it spans, so don't let it
342 // become the baseline descent applied to the rest of the row. Also we don't account for the baseline descent of
343 // non-spanning cells when computing a spanning cell's extent.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000344 LayoutUnit cellStartRowBaselineDescent = 0;
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000345 if (cell->rowSpan() == 1) {
zalan@apple.comdf6351f2016-01-11 22:03:03 +0000346 baselineDescent = std::max(baselineDescent, cellLogicalHeight - baselinePosition);
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000347 cellStartRowBaselineDescent = baselineDescent;
348 }
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000349 m_rowPos[cellStartRow + 1] = std::max(m_rowPos[cellStartRow + 1], m_rowPos[cellStartRow] + m_grid[cellStartRow].baseline + cellStartRowBaselineDescent);
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000350 }
eseidela043f3d2006-01-20 19:24:53 +0000351 }
ap50b58352006-01-22 20:32:36 +0000352 }
353 }
eseidela043f3d2006-01-20 19:24:53 +0000354
jchaffraix@webkit.orgaddd65e2012-02-26 00:19:22 +0000355 // Add the border-spacing to our final position.
ossy@webkit.org6d30aa72013-11-28 17:40:59 +0000356 // Use table border-spacing even in non-top sections
357 spacing = table()->vBorderSpacing();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000358 m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : LayoutUnit::fromPixel(0);
andersca@apple.com86298632013-11-10 19:32:33 +0000359 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[r]);
eseidela043f3d2006-01-20 19:24:53 +0000360 }
weinigfef13632007-04-29 20:09:08 +0000361
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000362 ASSERT(!needsLayout());
363
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000364 statePusher.pop();
mitz@apple.com440ac8c2008-04-05 16:05:08 +0000365
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000366 return m_rowPos[m_grid.size()];
eseidela043f3d2006-01-20 19:24:53 +0000367}
368
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000369void RenderTableSection::layout()
370{
mark.lam@apple.com6df1a802012-10-19 20:09:36 +0000371 StackStats::LayoutCheckPoint layoutCheckPoint;
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000372 ASSERT(needsLayout());
inferno@chromium.org7081f502012-05-26 00:28:23 +0000373 ASSERT(!needsCellRecalc());
374 ASSERT(!table()->needsSectionRecalc());
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000375
jchaffraix@webkit.orga9ddfc12012-06-18 17:11:12 +0000376 // addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
377 // can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
378 m_grid.shrinkToFit();
379
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000380 LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
hyatt@apple.comccad3742015-02-04 21:39:00 +0000381 bool paginated = view().layoutState()->isPaginated();
382
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000383 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
hyatt@apple.comccad3742015-02-04 21:39:00 +0000384
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000385 for (unsigned r = 0; r < m_grid.size(); ++r) {
386 Row& row = m_grid[r].row;
387 unsigned cols = row.size();
388 // First, propagate our table layout's information to the cells. This will mark the row as needing layout
389 // if there was a column logical width change.
390 for (unsigned startColumn = 0; startColumn < cols; ++startColumn) {
391 CellStruct& current = row[startColumn];
392 RenderTableCell* cell = current.primaryCell();
393 if (!cell || current.inColSpan)
394 continue;
395
396 unsigned endCol = startColumn;
397 unsigned cspan = cell->colSpan();
398 while (cspan && endCol < cols) {
399 ASSERT(endCol < table()->columns().size());
400 cspan -= table()->columns()[endCol].span;
401 endCol++;
402 }
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000403 LayoutUnit tableLayoutLogicalWidth = columnPos[endCol] - columnPos[startColumn] - table()->hBorderSpacing();
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000404 cell->setCellLogicalWidth(tableLayoutLogicalWidth);
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000405 }
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000406
hyatt@apple.comccad3742015-02-04 21:39:00 +0000407 if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
408 if (!rowRenderer->needsLayout() && paginated && view().layoutState()->pageLogicalHeightChanged())
409 rowRenderer->setChildNeedsLayout(MarkOnlyThis);
410
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000411 rowRenderer->layoutIfNeeded();
hyatt@apple.comccad3742015-02-04 21:39:00 +0000412 }
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000413 }
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000414
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000415 statePusher.pop();
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000416 clearNeedsLayout();
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000417}
418
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000419void RenderTableSection::distributeExtraLogicalHeightToPercentRows(LayoutUnit& extraLogicalHeight, int totalPercent)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000420{
421 if (!totalPercent)
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000422 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000423
424 unsigned totalRows = m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000425 LayoutUnit totalHeight = m_rowPos[totalRows] + extraLogicalHeight;
426 LayoutUnit totalLogicalHeightAdded = 0;
andersca@apple.com86298632013-11-10 19:32:33 +0000427 totalPercent = std::min(totalPercent, 100);
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000428 LayoutUnit rowHeight = m_rowPos[1] - m_rowPos[0];
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000429 for (unsigned r = 0; r < totalRows; ++r) {
commit-queue@webkit.org2a67f682015-05-10 21:43:26 +0000430 if (totalPercent > 0 && m_grid[r].logicalHeight.isPercent()) {
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000431 LayoutUnit toAdd = std::min<LayoutUnit>(extraLogicalHeight, (totalHeight * m_grid[r].logicalHeight.percent() / 100) - rowHeight);
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000432 // If toAdd is negative, then we don't want to shrink the row (this bug
433 // affected Outlook Web Access).
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000434 toAdd = std::max(LayoutUnit::fromPixel(0), toAdd);
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000435 totalLogicalHeightAdded += toAdd;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000436 extraLogicalHeight -= toAdd;
437 totalPercent -= m_grid[r].logicalHeight.percent();
438 }
439 ASSERT(totalRows >= 1);
440 if (r < totalRows - 1)
441 rowHeight = m_rowPos[r + 2] - m_rowPos[r + 1];
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000442 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000443 }
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000444}
445
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000446void RenderTableSection::distributeExtraLogicalHeightToAutoRows(LayoutUnit& extraLogicalHeight, unsigned autoRowsCount)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000447{
448 if (!autoRowsCount)
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000449 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000450
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000451 LayoutUnit totalLogicalHeightAdded = 0;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000452 for (unsigned r = 0; r < m_grid.size(); ++r) {
453 if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) {
454 // Recomputing |extraLogicalHeightForRow| guarantees that we properly ditribute round |extraLogicalHeight|.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000455 LayoutUnit extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount;
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000456 totalLogicalHeightAdded += extraLogicalHeightForRow;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000457 extraLogicalHeight -= extraLogicalHeightForRow;
458 --autoRowsCount;
459 }
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000460 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000461 }
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000462}
463
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000464void RenderTableSection::distributeRemainingExtraLogicalHeight(LayoutUnit& extraLogicalHeight)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000465{
466 unsigned totalRows = m_grid.size();
467
468 if (extraLogicalHeight <= 0 || !m_rowPos[totalRows])
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000469 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000470
471 // FIXME: m_rowPos[totalRows] - m_rowPos[0] is the total rows' size.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000472 LayoutUnit totalRowSize = m_rowPos[totalRows];
473 LayoutUnit totalLogicalHeightAdded = 0;
474 LayoutUnit previousRowPosition = m_rowPos[0];
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000475 for (unsigned r = 0; r < totalRows; r++) {
476 // weight with the original height
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000477 totalLogicalHeightAdded += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000478 previousRowPosition = m_rowPos[r + 1];
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000479 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000480 }
481
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000482 extraLogicalHeight -= totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000483}
484
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000485LayoutUnit RenderTableSection::distributeExtraLogicalHeightToRows(LayoutUnit extraLogicalHeight)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000486{
487 if (!extraLogicalHeight)
488 return extraLogicalHeight;
489
490 unsigned totalRows = m_grid.size();
491 if (!totalRows)
492 return extraLogicalHeight;
493
494 if (!m_rowPos[totalRows] && nextSibling())
495 return extraLogicalHeight;
496
497 unsigned autoRowsCount = 0;
498 int totalPercent = 0;
499 for (unsigned r = 0; r < totalRows; r++) {
500 if (m_grid[r].logicalHeight.isAuto())
501 ++autoRowsCount;
commit-queue@webkit.org2a67f682015-05-10 21:43:26 +0000502 else if (m_grid[r].logicalHeight.isPercent())
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000503 totalPercent += m_grid[r].logicalHeight.percent();
504 }
505
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000506 LayoutUnit remainingExtraLogicalHeight = extraLogicalHeight;
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000507 distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
508 distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
509 distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
510 return extraLogicalHeight - remainingExtraLogicalHeight;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000511}
512
jchaffraix@webkit.org94f150f2012-03-20 04:53:14 +0000513void RenderTableSection::layoutRows()
eseidela043f3d2006-01-20 19:24:53 +0000514{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000515#ifndef NDEBUG
ojan@chromium.orgccdc4292013-02-07 00:55:10 +0000516 SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000517#endif
518
519 ASSERT(!needsLayout());
520
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000521 unsigned totalRows = m_grid.size();
522
hyattd866e592006-03-17 09:50:35 +0000523 // Set the width of our section now. The rows will also be this width.
mitz@apple.com8010bba2010-11-05 02:43:17 +0000524 setLogicalWidth(table()->contentLogicalWidth());
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000525 m_forceSlowPaintPathWithOverflowingCell = false;
adeleddfe27f2007-01-05 23:03:50 +0000526
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000527 LayoutUnit vspacing = table()->vBorderSpacing();
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000528 unsigned nEffCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000529
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000530 LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || style().isFlippedBlocksWritingMode());
weinigfef13632007-04-29 20:09:08 +0000531
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000532 for (unsigned r = 0; r < totalRows; r++) {
hyattd866e592006-03-17 09:50:35 +0000533 // Set the row's x/y position and width/height.
hyatt@apple.comd885df72009-01-22 02:31:52 +0000534 if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
robert@webkit.orgf9766b12013-08-27 19:21:00 +0000535 // FIXME: the x() position of the row should be table()->hBorderSpacing() so that it can
536 // report the correct offsetLeft. However, that will require a lot of rebaselining of test results.
leviw@chromium.org7353dfd2011-08-12 21:01:45 +0000537 rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
mitz@apple.com8010bba2010-11-05 02:43:17 +0000538 rowRenderer->setLogicalWidth(logicalWidth());
539 rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
simon.fraser@apple.com78e3bdb2010-11-30 00:53:05 +0000540 rowRenderer->updateLayerTransform();
zalan@apple.comd423bcc2016-02-06 23:07:54 +0000541 rowRenderer->clearOverflow();
542 rowRenderer->addVisualEffectOverflow();
hyattd866e592006-03-17 09:50:35 +0000543 }
544
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000545 LayoutUnit rowHeightIncreaseForPagination = 0;
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000546
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000547 for (unsigned c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000548 CellStruct& cs = cellAt(r, c);
549 RenderTableCell* cell = cs.primaryCell();
550
jamesr@google.comb4266232010-07-28 20:07:19 +0000551 if (!cell || cs.inColSpan)
ap50b58352006-01-22 20:32:36 +0000552 continue;
eseidela043f3d2006-01-20 19:24:53 +0000553
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000554 int rowIndex = cell->rowIndex();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000555 LayoutUnit rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing;
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000556
eseidela043f3d2006-01-20 19:24:53 +0000557 // Force percent height children to lay themselves out again.
558 // This will cause these children to grow to fill the cell.
559 // FIXME: There is still more work to do here to fully match WinIE (should
560 // it become necessary to do so). In quirks mode, WinIE behaves like we
561 // do, but it will clip the cells that spill out of the table section. In
562 // strict mode, Mozilla and WinIE both regrow the table to accommodate the
563 // new height of the cell (thus letting the percentages cause growth one
564 // time only). We may also not be handling row-spanning cells correctly.
565 //
566 // Note also the oddity where replaced elements always flex, and yet blocks/tables do
567 // not necessarily flex. WinIE is crazy and inconsistent, and we can't hope to
568 // match the behavior perfectly, but we'll continue to refine it as we discover new
569 // bugs. :)
570 bool cellChildrenFlex = false;
akling@apple.com827be9c2013-10-29 02:58:43 +0000571 bool flexAllChildren = cell->style().logicalHeight().isFixed()
572 || (!table()->style().logicalHeight().isAuto() && rHeight != cell->logicalHeight());
eseidela043f3d2006-01-20 19:24:53 +0000573
cdumez@apple.com69626952016-05-17 22:39:00 +0000574 for (auto& renderer : childrenOfType<RenderObject>(*cell)) {
575 if (!is<RenderText>(renderer) && renderer.style().logicalHeight().isPercentOrCalculated() && (flexAllChildren || ((renderer.isReplaced() || (is<RenderBox>(renderer) && downcast<RenderBox>(renderer).scrollsOverflow())) && !is<RenderTextControl>(renderer)))) {
eseidela043f3d2006-01-20 19:24:53 +0000576 // Tables with no sections do not flex.
cdumez@apple.com69626952016-05-17 22:39:00 +0000577 if (!is<RenderTable>(renderer) || downcast<RenderTable>(renderer).hasSections()) {
578 renderer.setNeedsLayout(MarkOnlyThis);
eseidela043f3d2006-01-20 19:24:53 +0000579 cellChildrenFlex = true;
580 }
581 }
582 }
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000583
tony@chromium.org05b9d2c2012-09-05 01:31:38 +0000584 if (TrackedRendererListHashSet* percentHeightDescendants = cell->percentHeightDescendants()) {
585 TrackedRendererListHashSet::iterator end = percentHeightDescendants->end();
586 for (TrackedRendererListHashSet::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000587 RenderBox* box = *it;
588 if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
589 continue;
590
591 while (box != cell) {
592 if (box->normalChildNeedsLayout())
593 break;
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000594 box->setChildNeedsLayout(MarkOnlyThis);
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000595 box = box->containingBlock();
596 ASSERT(box);
597 if (!box)
598 break;
599 }
600 cellChildrenFlex = true;
601 }
602 }
603
eseidela043f3d2006-01-20 19:24:53 +0000604 if (cellChildrenFlex) {
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000605 cell->setChildNeedsLayout(MarkOnlyThis);
eseidela043f3d2006-01-20 19:24:53 +0000606 // Alignment within a cell is based off the calculated
607 // height, which becomes irrelevant once the cell has
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000608 // been resized based off its percentage.
ojan@chromium.org7a1ce8b2012-06-05 18:32:10 +0000609 cell->setOverrideLogicalContentHeightFromRowHeight(rHeight);
ap7332aaa2006-04-28 16:02:45 +0000610 cell->layoutIfNeeded();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000611
hyatt851433b2007-05-12 06:40:14 +0000612 // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
robert@webkit.org292be542013-03-09 06:40:13 +0000613 if (cell->isBaselineAligned()) {
leviw@chromium.org2650e382012-04-04 10:37:36 +0000614 LayoutUnit baseline = cell->cellBaselinePosition();
zoltan@webkit.org8e79cc22013-06-14 00:39:36 +0000615 if (baseline > cell->borderAndPaddingBefore())
andersca@apple.com86298632013-11-10 19:32:33 +0000616 m_grid[r].baseline = std::max(m_grid[r].baseline, baseline);
hyatt851433b2007-05-12 06:40:14 +0000617 }
eseidela043f3d2006-01-20 19:24:53 +0000618 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000619
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000620 cell->computeIntrinsicPadding(rHeight);
mitz@apple.com8010bba2010-11-05 02:43:17 +0000621
eae@chromium.org1146f212012-07-18 22:06:34 +0000622 LayoutRect oldCellRect = cell->frameRect();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000623
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +0000624 setLogicalPositionForCell(cell, c);
eseidela043f3d2006-01-20 19:24:53 +0000625
akling@apple.com691cf5c2013-08-24 16:33:15 +0000626 if (!cell->needsLayout() && view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000627 cell->setChildNeedsLayout(MarkOnlyThis);
mitz@apple.com8010bba2010-11-05 02:43:17 +0000628
hyatt@apple.com1259d732010-09-20 16:12:58 +0000629 cell->layoutIfNeeded();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000630
631 // FIXME: Make pagination work with vertical tables.
akling@apple.com691cf5c2013-08-24 16:33:15 +0000632 if (view().layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
hyatt@apple.com8403ad22012-04-10 18:14:20 +0000633 // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
634 // We'll also do a basic increase of the row height to accommodate the cell if it's bigger, but this isn't quite right
635 // either. It's at least stable though and won't result in an infinite # of relayouts that may never stabilize.
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000636 if (cell->logicalHeight() > rHeight)
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000637 rowHeightIncreaseForPagination = std::max(rowHeightIncreaseForPagination, cell->logicalHeight() - rHeight);
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000638 cell->setLogicalHeight(rHeight);
hyatt@apple.com8403ad22012-04-10 18:14:20 +0000639 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000640
leviw@chromium.org7353dfd2011-08-12 21:01:45 +0000641 LayoutSize childOffset(cell->location() - oldCellRect.location());
hyatt@apple.comb297b492010-09-20 20:21:34 +0000642 if (childOffset.width() || childOffset.height()) {
akling@apple.com691cf5c2013-08-24 16:33:15 +0000643 view().addLayoutDelta(childOffset);
hyatt@apple.com1259d732010-09-20 16:12:58 +0000644
hyatt@apple.comb297b492010-09-20 20:21:34 +0000645 // If the child moved, we have to repaint it as well as any floating/positioned
646 // descendants. An exception is if we need a layout. In this case, we know we're going to
647 // repaint ourselves (and the child) anyway.
648 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
649 cell->repaintDuringLayoutIfMoved(oldCellRect);
650 }
eseidela043f3d2006-01-20 19:24:53 +0000651 }
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000652 if (rowHeightIncreaseForPagination) {
653 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++)
654 m_rowPos[rowIndex] += rowHeightIncreaseForPagination;
655 for (unsigned c = 0; c < nEffCols; ++c) {
656 Vector<RenderTableCell*, 1>& cells = cellAt(r, c).cells;
657 for (size_t i = 0; i < cells.size(); ++i)
658 cells[i]->setLogicalHeight(cells[i]->logicalHeight() + rowHeightIncreaseForPagination);
659 }
660 }
eseidela043f3d2006-01-20 19:24:53 +0000661 }
662
hyatt@apple.com8b2cd1f2009-01-26 03:38:55 +0000663 ASSERT(!needsLayout());
664
mitz@apple.com8010bba2010-11-05 02:43:17 +0000665 setLogicalHeight(m_rowPos[totalRows]);
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000666
robert@webkit.org4c91cc92013-03-27 23:49:48 +0000667 computeOverflowFromCells(totalRows, nEffCols);
668
669 statePusher.pop();
670}
671
672void RenderTableSection::computeOverflowFromCells()
673{
674 unsigned totalRows = m_grid.size();
675 unsigned nEffCols = table()->numEffCols();
676 computeOverflowFromCells(totalRows, nEffCols);
677}
678
679void RenderTableSection::computeOverflowFromCells(unsigned totalRows, unsigned nEffCols)
680{
abucur@adobe.com6585d012013-09-04 08:26:41 +0000681 clearOverflow();
robert@webkit.orge4314c42013-08-08 18:13:22 +0000682 m_overflowingCells.clear();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000683 unsigned totalCellsCount = nEffCols * totalRows;
commit-queue@webkit.org877bfc32015-03-10 21:54:21 +0000684 unsigned maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000685
686#ifndef NDEBUG
687 bool hasOverflowingCell = false;
688#endif
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000689 // Now that our height has been determined, add in overflow from cells.
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000690 for (unsigned r = 0; r < totalRows; r++) {
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000691 for (unsigned c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000692 CellStruct& cs = cellAt(r, c);
693 RenderTableCell* cell = cs.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +0000694 if (!cell || cs.inColSpan)
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000695 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000696 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000697 continue;
698 addOverflowFromChild(cell);
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000699#ifndef NDEBUG
700 hasOverflowingCell |= cell->hasVisualOverflow();
701#endif
702 if (cell->hasVisualOverflow() && !m_forceSlowPaintPathWithOverflowingCell) {
703 m_overflowingCells.add(cell);
704 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) {
705 // We need to set m_forcesSlowPaintPath only if there is a least one overflowing cells as the hit testing code rely on this information.
706 m_forceSlowPaintPathWithOverflowingCell = true;
707 // The slow path does not make any use of the overflowing cells info, don't hold on to the memory.
708 m_overflowingCells.clear();
709 }
710 }
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000711 }
712 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000713 ASSERT(hasOverflowingCell == this->hasOverflowingCell());
eseidela043f3d2006-01-20 19:24:53 +0000714}
715
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000716LayoutUnit RenderTableSection::calcOuterBorderBefore() const
darin32011102006-05-15 04:42:09 +0000717{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000718 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000719 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000720 return 0;
721
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000722 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000723
akling@apple.com827be9c2013-10-29 02:58:43 +0000724 const BorderValue& sb = style().borderBefore();
darin32011102006-05-15 04:42:09 +0000725 if (sb.style() == BHIDDEN)
726 return -1;
727 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000728 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000729
akling@apple.com827be9c2013-10-29 02:58:43 +0000730 const BorderValue& rb = firstRow()->style().borderBefore();
darin32011102006-05-15 04:42:09 +0000731 if (rb.style() == BHIDDEN)
732 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000733 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
734 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000735
736 bool allHidden = true;
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000737 for (unsigned c = 0; c < totalCols; c++) {
darin32011102006-05-15 04:42:09 +0000738 const CellStruct& current = cellAt(0, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000739 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000740 continue;
akling@apple.com827be9c2013-10-29 02:58:43 +0000741 const BorderValue& cb = current.primaryCell()->style().borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
darin32011102006-05-15 04:42:09 +0000742 // FIXME: Don't repeat for the same col group
743 RenderTableCol* colGroup = table()->colElement(c);
744 if (colGroup) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000745 const BorderValue& gb = colGroup->style().borderBefore();
darin32011102006-05-15 04:42:09 +0000746 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
747 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000748 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000749 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
750 borderWidth = gb.width();
751 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
752 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000753 } else {
754 if (cb.style() == BHIDDEN)
755 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000756 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000757 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
758 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000759 }
760 }
761 if (allHidden)
762 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000763 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), false);
darin32011102006-05-15 04:42:09 +0000764}
765
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000766LayoutUnit RenderTableSection::calcOuterBorderAfter() const
darin32011102006-05-15 04:42:09 +0000767{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000768 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000769 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000770 return 0;
771
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000772 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000773
akling@apple.com827be9c2013-10-29 02:58:43 +0000774 const BorderValue& sb = style().borderAfter();
darin32011102006-05-15 04:42:09 +0000775 if (sb.style() == BHIDDEN)
776 return -1;
777 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000778 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000779
akling@apple.com827be9c2013-10-29 02:58:43 +0000780 const BorderValue& rb = lastRow()->style().borderAfter();
darin32011102006-05-15 04:42:09 +0000781 if (rb.style() == BHIDDEN)
782 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000783 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
784 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000785
786 bool allHidden = true;
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000787 for (unsigned c = 0; c < totalCols; c++) {
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000788 const CellStruct& current = cellAt(m_grid.size() - 1, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000789 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000790 continue;
akling@apple.com827be9c2013-10-29 02:58:43 +0000791 const BorderValue& cb = current.primaryCell()->style().borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
darin32011102006-05-15 04:42:09 +0000792 // FIXME: Don't repeat for the same col group
793 RenderTableCol* colGroup = table()->colElement(c);
794 if (colGroup) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000795 const BorderValue& gb = colGroup->style().borderAfter();
darin32011102006-05-15 04:42:09 +0000796 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
797 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000798 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000799 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
800 borderWidth = gb.width();
801 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
802 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000803 } else {
804 if (cb.style() == BHIDDEN)
805 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000806 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000807 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
808 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000809 }
810 }
811 if (allHidden)
812 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000813 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), true);
darin32011102006-05-15 04:42:09 +0000814}
815
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000816LayoutUnit RenderTableSection::calcOuterBorderStart() const
darin32011102006-05-15 04:42:09 +0000817{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000818 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000819 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000820 return 0;
821
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000822 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000823
akling@apple.com827be9c2013-10-29 02:58:43 +0000824 const BorderValue& sb = style().borderStart();
darin32011102006-05-15 04:42:09 +0000825 if (sb.style() == BHIDDEN)
826 return -1;
827 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000828 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000829
mitz@apple.com8010bba2010-11-05 02:43:17 +0000830 if (RenderTableCol* colGroup = table()->colElement(0)) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000831 const BorderValue& gb = colGroup->style().borderStart();
darin32011102006-05-15 04:42:09 +0000832 if (gb.style() == BHIDDEN)
833 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000834 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
835 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000836 }
837
838 bool allHidden = true;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000839 for (unsigned r = 0; r < m_grid.size(); r++) {
mitz@apple.com8010bba2010-11-05 02:43:17 +0000840 const CellStruct& current = cellAt(r, 0);
jamesr@google.com36623a32010-07-23 20:22:29 +0000841 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000842 continue;
843 // FIXME: Don't repeat for the same cell
akling@apple.com827be9c2013-10-29 02:58:43 +0000844 const BorderValue& cb = current.primaryCell()->style().borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
845 const BorderValue& rb = current.primaryCell()->parent()->style().borderStart();
darin32011102006-05-15 04:42:09 +0000846 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
847 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000848 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000849 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
850 borderWidth = cb.width();
851 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
852 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000853 }
854 if (allHidden)
855 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000856 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), !table()->style().isLeftToRightDirection());
darin32011102006-05-15 04:42:09 +0000857}
858
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000859LayoutUnit RenderTableSection::calcOuterBorderEnd() const
darin32011102006-05-15 04:42:09 +0000860{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000861 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000862 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000863 return 0;
864
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000865 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000866
akling@apple.com827be9c2013-10-29 02:58:43 +0000867 const BorderValue& sb = style().borderEnd();
darin32011102006-05-15 04:42:09 +0000868 if (sb.style() == BHIDDEN)
869 return -1;
870 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000871 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000872
mitz@apple.com8010bba2010-11-05 02:43:17 +0000873 if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000874 const BorderValue& gb = colGroup->style().borderEnd();
darin32011102006-05-15 04:42:09 +0000875 if (gb.style() == BHIDDEN)
876 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000877 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
878 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000879 }
880
881 bool allHidden = true;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000882 for (unsigned r = 0; r < m_grid.size(); r++) {
mitz@apple.com8010bba2010-11-05 02:43:17 +0000883 const CellStruct& current = cellAt(r, totalCols - 1);
jamesr@google.com36623a32010-07-23 20:22:29 +0000884 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000885 continue;
886 // FIXME: Don't repeat for the same cell
akling@apple.com827be9c2013-10-29 02:58:43 +0000887 const BorderValue& cb = current.primaryCell()->style().borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
888 const BorderValue& rb = current.primaryCell()->parent()->style().borderEnd();
darin32011102006-05-15 04:42:09 +0000889 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
890 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000891 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000892 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
893 borderWidth = cb.width();
894 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
895 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000896 }
897 if (allHidden)
898 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000899 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), table()->style().isLeftToRightDirection());
darin32011102006-05-15 04:42:09 +0000900}
901
902void RenderTableSection::recalcOuterBorder()
903{
mitz@apple.com8010bba2010-11-05 02:43:17 +0000904 m_outerBorderBefore = calcOuterBorderBefore();
905 m_outerBorderAfter = calcOuterBorderAfter();
906 m_outerBorderStart = calcOuterBorderStart();
907 m_outerBorderEnd = calcOuterBorderEnd();
darin32011102006-05-15 04:42:09 +0000908}
909
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000910Optional<int> RenderTableSection::firstLineBaseline() const
mitz@apple.com57a2f482008-08-23 07:16:41 +0000911{
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000912 if (!m_grid.size())
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000913 return Optional<int>();
mitz@apple.com57a2f482008-08-23 07:16:41 +0000914
eae@chromium.org82b94982012-10-22 18:38:29 +0000915 int firstLineBaseline = m_grid[0].baseline;
mitz@apple.com57a2f482008-08-23 07:16:41 +0000916 if (firstLineBaseline)
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000917 return firstLineBaseline + roundToInt(m_rowPos[0]);
mitz@apple.com57a2f482008-08-23 07:16:41 +0000918
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000919 Optional<int> result;
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +0000920 const Row& firstRow = m_grid[0].row;
921 for (size_t i = 0; i < firstRow.size(); ++i) {
922 const CellStruct& cs = firstRow.at(i);
923 const RenderTableCell* cell = cs.primaryCell();
robert@webkit.org3b67b1f2012-05-16 21:06:10 +0000924 // Only cells with content have a baseline
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000925 if (cell && cell->contentLogicalHeight()) {
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000926 int candidate = roundToInt(cell->logicalTop() + cell->borderAndPaddingBefore() + cell->contentLogicalHeight());
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000927 result = std::max(result.valueOr(candidate), candidate);
928 }
mitz@apple.com57a2f482008-08-23 07:16:41 +0000929 }
930
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000931 return result;
mitz@apple.com57a2f482008-08-23 07:16:41 +0000932}
darin32011102006-05-15 04:42:09 +0000933
leviw@chromium.orgb3757502011-06-29 21:33:11 +0000934void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
eseidela043f3d2006-01-20 19:24:53 +0000935{
inferno@chromium.org64a831b2012-08-03 19:47:08 +0000936 // put this back in when all layout tests can handle it
937 // ASSERT(!needsLayout());
938 // avoid crashing on bugs that cause us to paint with dirty layout
eric@webkit.org5d226dc2012-08-02 21:06:06 +0000939 if (needsLayout())
940 return;
inferno@chromium.org64a831b2012-08-03 19:47:08 +0000941
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000942 unsigned totalRows = m_grid.size();
ddkilzer260f3d22007-01-05 05:56:31 +0000943 unsigned totalCols = table()->columns().size();
eseidela043f3d2006-01-20 19:24:53 +0000944
ddkilzer260f3d22007-01-05 05:56:31 +0000945 if (!totalRows || !totalCols)
ap0e708ba2006-05-20 08:47:37 +0000946 return;
947
leviw@chromium.orgb3757502011-06-29 21:33:11 +0000948 LayoutPoint adjustedPaintOffset = paintOffset + location();
eseidela043f3d2006-01-20 19:24:53 +0000949
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000950 PaintPhase phase = paintInfo.phase;
leviw@chromium.org61ca1372011-06-07 18:56:41 +0000951 bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
952 paintObject(paintInfo, adjustedPaintOffset);
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000953 if (pushedClip)
leviw@chromium.org61ca1372011-06-07 18:56:41 +0000954 popContentsClip(paintInfo, phase, adjustedPaintOffset);
robert@webkit.org87e8d0c2012-01-14 19:13:35 +0000955
akling@apple.com827be9c2013-10-29 02:58:43 +0000956 if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style().visibility() == VISIBLE)
wangxianzhu@chromium.org64f38292013-02-28 20:38:23 +0000957 paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000958}
959
jamesr@google.com36623a32010-07-23 20:22:29 +0000960static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
961{
jchaffraix@webkit.orga0177fd2012-05-01 03:13:06 +0000962 return elem1->rowIndex() < elem2->rowIndex();
jamesr@google.com36623a32010-07-23 20:22:29 +0000963}
964
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000965// This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
966// to sort both on rows and columns to properly repaint.
967static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
968{
jchaffraix@webkit.orga0177fd2012-05-01 03:13:06 +0000969 if (elem1->rowIndex() != elem2->rowIndex())
970 return elem1->rowIndex() < elem2->rowIndex();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000971
972 return elem1->col() < elem2->col();
973}
974
leviw@chromium.org890e9b02011-07-07 23:17:55 +0000975void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
jamesr@google.com36623a32010-07-23 20:22:29 +0000976{
ojan@chromium.org035c88ca2011-10-03 22:00:25 +0000977 LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
jamesr@google.com36623a32010-07-23 20:22:29 +0000978 PaintPhase paintPhase = paintInfo.phase;
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000979 RenderTableRow& row = downcast<RenderTableRow>(*cell->parent());
jamesr@google.com36623a32010-07-23 20:22:29 +0000980
981 if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
982 // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
983 // the column group, column, row group, row, and then the cell.
jchaffraix@webkit.org1ddd9fa2012-05-31 16:00:20 +0000984 RenderTableCol* column = table()->colElement(cell->col());
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000985 RenderTableCol* columnGroup = column ? column->enclosingColumnGroup() : nullptr;
jamesr@google.com36623a32010-07-23 20:22:29 +0000986
987 // Column groups and columns first.
988 // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
989 // the stack, since we have already opened a transparency layer (potentially) for the table row group.
990 // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
991 // cell.
jchaffraix@webkit.org1ddd9fa2012-05-31 16:00:20 +0000992 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup);
993 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, column);
jamesr@google.com36623a32010-07-23 20:22:29 +0000994
995 // Paint the row group next.
leviw@chromium.org719a45b2011-06-03 20:59:40 +0000996 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, this);
jamesr@google.com36623a32010-07-23 20:22:29 +0000997
998 // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
999 // painting the row background for the cell.
cdumez@apple.com8faf7722014-10-13 18:21:11 +00001000 if (!row.hasSelfPaintingLayer())
1001 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, &row);
jamesr@google.com36623a32010-07-23 20:22:29 +00001002 }
cdumez@apple.com8faf7722014-10-13 18:21:11 +00001003 if ((!cell->hasSelfPaintingLayer() && !row.hasSelfPaintingLayer()))
leviw@chromium.org61ca1372011-06-07 18:56:41 +00001004 cell->paint(paintInfo, cellPoint);
jamesr@google.com36623a32010-07-23 20:22:29 +00001005}
1006
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001007LayoutRect RenderTableSection::logicalRectForWritingModeAndDirection(const LayoutRect& rect) const
1008{
1009 LayoutRect tableAlignedRect(rect);
1010
1011 flipForWritingMode(tableAlignedRect);
1012
akling@apple.com827be9c2013-10-29 02:58:43 +00001013 if (!style().isHorizontalWritingMode())
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001014 tableAlignedRect = tableAlignedRect.transposedRect();
1015
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001016 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
jchaffraix@webkit.org6d6c3052012-11-05 07:55:28 +00001017 // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
akling@apple.com827be9c2013-10-29 02:58:43 +00001018 if (!style().isLeftToRightDirection())
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001019 tableAlignedRect.setX(columnPos[columnPos.size() - 1] - tableAlignedRect.maxX());
1020
1021 return tableAlignedRect;
1022}
1023
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001024CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const
1025{
1026 if (m_forceSlowPaintPathWithOverflowingCell)
1027 return fullTableRowSpan();
1028
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001029 CellSpan coveredRows = spannedRows(damageRect, IncludeAllIntersectingCells);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001030
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001031 // To repaint the border we might need to repaint first or last row even if they are not spanned themselves.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001032 if (coveredRows.start >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= damageRect.y())
1033 --coveredRows.start;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001034
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001035 if (!coveredRows.end && m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY())
1036 ++coveredRows.end;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001037
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001038 return coveredRows;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001039}
1040
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001041CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const
1042{
1043 if (m_forceSlowPaintPathWithOverflowingCell)
1044 return fullTableColumnSpan();
1045
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001046 CellSpan coveredColumns = spannedColumns(damageRect, IncludeAllIntersectingCells);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001047
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001048 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001049 // To repaint the border we might need to repaint first or last column even if they are not spanned themselves.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001050 if (coveredColumns.start >= columnPos.size() - 1 && columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= damageRect.x())
1051 --coveredColumns.start;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001052
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001053 if (!coveredColumns.end && columnPos[0] - table()->outerBorderStart() <= damageRect.maxX())
1054 ++coveredColumns.end;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001055
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001056 return coveredColumns;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001057}
1058
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001059CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001060{
1061 // Find the first row that starts after rect top.
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001062 unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - m_rowPos.begin();
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001063 if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextRow && m_rowPos[nextRow - 1] == flippedRect.y())
1064 --nextRow;
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001065
1066 if (nextRow == m_rowPos.size())
1067 return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); // After all rows.
1068
1069 unsigned startRow = nextRow > 0 ? nextRow - 1 : 0;
1070
1071 // Find the first row that starts after rect bottom.
1072 unsigned endRow;
1073 if (m_rowPos[nextRow] >= flippedRect.maxY())
1074 endRow = nextRow;
1075 else {
andersca@apple.com16123952014-12-06 21:04:35 +00001076 endRow = std::upper_bound(m_rowPos.begin() + static_cast<int32_t>(nextRow), m_rowPos.end(), flippedRect.maxY()) - m_rowPos.begin();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001077 if (endRow == m_rowPos.size())
1078 endRow = m_rowPos.size() - 1;
1079 }
1080
1081 return CellSpan(startRow, endRow);
1082}
1083
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001084CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001085{
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001086 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001087
commit-queue@webkit.org01f61412012-08-15 18:01:05 +00001088 // Find the first column that starts after rect left.
1089 // lower_bound doesn't handle the edge between two cells properly as it would wrongly return the
1090 // cell on the logical top/left.
1091 // upper_bound on the other hand properly returns the cell on the logical bottom/right, which also
1092 // matches the behavior of other browsers.
1093 unsigned nextColumn = std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - columnPos.begin();
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001094 if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextColumn && columnPos[nextColumn - 1] == flippedRect.x())
1095 --nextColumn;
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001096
1097 if (nextColumn == columnPos.size())
1098 return CellSpan(columnPos.size() - 1, columnPos.size() - 1); // After all columns.
1099
1100 unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0;
1101
commit-queue@webkit.org01f61412012-08-15 18:01:05 +00001102 // Find the first column that starts after rect right.
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001103 unsigned endColumn;
1104 if (columnPos[nextColumn] >= flippedRect.maxX())
1105 endColumn = nextColumn;
1106 else {
andersca@apple.com16123952014-12-06 21:04:35 +00001107 endColumn = std::upper_bound(columnPos.begin() + static_cast<int32_t>(nextColumn), columnPos.end(), flippedRect.maxX()) - columnPos.begin();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001108 if (endColumn == columnPos.size())
1109 endColumn = columnPos.size() - 1;
1110 }
1111
1112 return CellSpan(startColumn, endColumn);
1113}
1114
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001115void RenderTableSection::paintRowGroupBorder(const PaintInfo& paintInfo, bool antialias, LayoutRect rect, BoxSide side, CSSPropertyID borderColor, EBorderStyle borderStyle, EBorderStyle tableBorderStyle)
1116{
1117 if (tableBorderStyle == BHIDDEN)
1118 return;
1119 rect.intersect(paintInfo.rect);
1120 if (rect.isEmpty())
1121 return;
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001122 drawLineForBoxSide(paintInfo.context(), rect, side, style().visitedDependentColor(borderColor), borderStyle, 0, 0, antialias);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001123}
1124
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001125LayoutUnit RenderTableSection::offsetLeftForRowGroupBorder(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001126{
akling@apple.com827be9c2013-10-29 02:58:43 +00001127 if (style().isHorizontalWritingMode()) {
1128 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001129 return cell ? cell->x() + cell->width() : LayoutUnit::fromPixel(0);
akling@apple.com827be9c2013-10-29 02:58:43 +00001130 return -outerBorderLeft(&style());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001131 }
1132 bool isLastRow = row + 1 == m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001133 return rowGroupRect.width() - m_rowPos[row + 1] + (isLastRow ? -outerBorderLeft(&style()) : LayoutUnit::fromPixel(0));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001134}
1135
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001136LayoutUnit RenderTableSection::offsetTopForRowGroupBorder(RenderTableCell* cell, BoxSide borderSide, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001137{
1138 bool isLastRow = row + 1 == m_grid.size();
akling@apple.com827be9c2013-10-29 02:58:43 +00001139 if (style().isHorizontalWritingMode())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001140 return m_rowPos[row] + (!row && borderSide == BSRight ? -outerBorderTop(&style()) : isLastRow && borderSide == BSLeft ? outerBorderTop(&style()) : LayoutUnit::fromPixel(0));
akling@apple.com827be9c2013-10-29 02:58:43 +00001141 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001142 return (cell ? cell->y() + cell->height() : LayoutUnit::fromPixel(0)) + (borderSide == BSLeft ? outerBorderTop(&style()) : LayoutUnit::fromPixel(0));
1143 return borderSide == BSRight ? -outerBorderTop(&style()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001144}
1145
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001146LayoutUnit RenderTableSection::verticalRowGroupBorderHeight(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001147{
1148 bool isLastRow = row + 1 == m_grid.size();
akling@apple.com827be9c2013-10-29 02:58:43 +00001149 if (style().isHorizontalWritingMode())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001150 return m_rowPos[row + 1] - m_rowPos[row] + (!row ? outerBorderTop(&style()) : isLastRow ? outerBorderBottom(&style()) : LayoutUnit::fromPixel(0));
akling@apple.com827be9c2013-10-29 02:58:43 +00001151 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001152 return rowGroupRect.height() - (cell ? cell->y() + cell->height() : LayoutUnit::fromPixel(0)) + outerBorderBottom(&style());
1153 return cell ? rowGroupRect.height() - (cell->y() - cell->height()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001154}
1155
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001156LayoutUnit RenderTableSection::horizontalRowGroupBorderWidth(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row, unsigned column)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001157{
akling@apple.com827be9c2013-10-29 02:58:43 +00001158 if (style().isHorizontalWritingMode()) {
1159 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001160 return rowGroupRect.width() - (cell ? cell->x() + cell->width() : LayoutUnit::fromPixel(0)) + (!column ? outerBorderLeft(&style()) : column == table()->numEffCols() ? outerBorderRight(&style()) : LayoutUnit::fromPixel(0));
1161 return cell ? rowGroupRect.width() - (cell->x() - cell->width()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001162 }
1163 bool isLastRow = row + 1 == m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001164 return m_rowPos[row + 1] - m_rowPos[row] + (isLastRow ? outerBorderLeft(&style()) : !row ? outerBorderRight(&style()) : LayoutUnit::fromPixel(0));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001165}
1166
1167void RenderTableSection::paintRowGroupBorderIfRequired(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, unsigned row, unsigned column, BoxSide borderSide, RenderTableCell* cell)
1168{
1169 if (table()->currentBorderValue()->precedence() > BROWGROUP)
1170 return;
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001171 if (paintInfo.context().paintingDisabled())
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001172 return;
1173
akling@apple.com827be9c2013-10-29 02:58:43 +00001174 const RenderStyle& style = this->style();
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001175 bool antialias = shouldAntialiasLines(paintInfo.context());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001176 LayoutRect rowGroupRect = LayoutRect(paintOffset, size());
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001177 rowGroupRect.moveBy(-LayoutPoint(outerBorderLeft(&style), (borderSide == BSRight) ? LayoutUnit::fromPixel(0) : outerBorderTop(&style)));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001178
1179 switch (borderSide) {
1180 case BSTop:
1181 paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y(),
akling@apple.com827be9c2013-10-29 02:58:43 +00001182 horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderTop().width()), BSTop, CSSPropertyBorderTopColor, style.borderTopStyle(), table()->style().borderTopStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001183 break;
1184 case BSBottom:
1185 paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y() + rowGroupRect.height(),
akling@apple.com827be9c2013-10-29 02:58:43 +00001186 horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderBottom().width()), BSBottom, CSSPropertyBorderBottomColor, style.borderBottomStyle(), table()->style().borderBottomStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001187 break;
1188 case BSLeft:
akling@apple.com827be9c2013-10-29 02:58:43 +00001189 paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderLeft().width(),
1190 verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSLeft, CSSPropertyBorderLeftColor, style.borderLeftStyle(), table()->style().borderLeftStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001191 break;
1192 case BSRight:
akling@apple.com827be9c2013-10-29 02:58:43 +00001193 paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x() + rowGroupRect.width(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderRight().width(),
1194 verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSRight, CSSPropertyBorderRightColor, style.borderRightStyle(), table()->style().borderRightStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001195 break;
1196 default:
1197 break;
1198 }
1199
1200}
1201
antti@apple.com5c4302b2016-04-26 18:20:09 +00001202static BoxSide physicalBorderForDirection(const RenderStyle* styleForCellFlow, CollapsedBorderSide side)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001203{
1204
1205 switch (side) {
1206 case CBSStart:
1207 if (styleForCellFlow->isHorizontalWritingMode())
1208 return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1209 return styleForCellFlow->isLeftToRightDirection() ? BSTop : BSBottom;
1210 case CBSEnd:
1211 if (styleForCellFlow->isHorizontalWritingMode())
1212 return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1213 return styleForCellFlow->isLeftToRightDirection() ? BSBottom : BSTop;
1214 case CBSBefore:
1215 if (styleForCellFlow->isHorizontalWritingMode())
1216 return BSTop;
1217 return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1218 case CBSAfter:
1219 if (styleForCellFlow->isHorizontalWritingMode())
1220 return BSBottom;
1221 return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1222 default:
1223 ASSERT_NOT_REACHED();
1224 return BSLeft;
1225 }
1226}
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001227
leviw@chromium.orgc4918082011-06-29 01:06:00 +00001228void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001229{
leviw@chromium.orgc4918082011-06-29 01:06:00 +00001230 LayoutRect localRepaintRect = paintInfo.rect;
leviw@chromium.org43d0c4d2011-06-04 02:25:54 +00001231 localRepaintRect.moveBy(-paintOffset);
eseidela043f3d2006-01-20 19:24:53 +00001232
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001233 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect);
1234
1235 CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect);
1236 CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001237
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001238 if (dirtiedColumns.start < dirtiedColumns.end) {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001239 if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001240 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1241 // Collapsed borders are painted from the bottom right to the top left so that precedence
robert@webkit.orgc75e7672013-06-11 18:11:31 +00001242 // due to cell position is respected. We need to paint one row beyond the topmost dirtied
1243 // row to calculate its collapsed border value.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001244 unsigned startRow = dirtiedRows.start ? dirtiedRows.start - 1 : 0;
1245 for (unsigned r = dirtiedRows.end; r > startRow; r--) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001246 unsigned row = r - 1;
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001247 bool shouldPaintRowGroupBorder = false;
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001248 for (unsigned c = dirtiedColumns.end; c > dirtiedColumns.start; c--) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001249 unsigned col = c - 1;
1250 CellStruct& current = cellAt(row, col);
1251 RenderTableCell* cell = current.primaryCell();
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001252 if (!cell) {
1253 if (!c)
akling@apple.com827be9c2013-10-29 02:58:43 +00001254 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSStart));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001255 else if (c == table()->numEffCols())
akling@apple.com827be9c2013-10-29 02:58:43 +00001256 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSEnd));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001257 shouldPaintRowGroupBorder = true;
robert@webkit.org2d408272011-12-19 19:49:27 +00001258 continue;
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001259 }
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001260 if ((row > dirtiedRows.start && primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start && primaryCellAt(row, col - 1) == cell))
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001261 continue;
1262
1263 // If we had a run of null cells paint their corresponding section of the row group's border if necessary. Note that
1264 // this will only happen once within a row as the null cells will always be clustered together on one end of the row.
1265 if (shouldPaintRowGroupBorder) {
1266 if (r == m_grid.size())
akling@apple.com827be9c2013-10-29 02:58:43 +00001267 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSAfter), cell);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001268 else if (!row && !table()->sectionAbove(this))
akling@apple.com827be9c2013-10-29 02:58:43 +00001269 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSBefore), cell);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001270 shouldPaintRowGroupBorder = false;
1271 }
1272
robert@webkit.org2d408272011-12-19 19:49:27 +00001273 LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
1274 cell->paintCollapsedBorders(paintInfo, cellPoint);
1275 }
1276 }
1277 } else {
1278 // Draw the dirty cells in the order that they appear.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001279 for (unsigned r = dirtiedRows.start; r < dirtiedRows.end; r++) {
robert@webkit.org87e8d0c2012-01-14 19:13:35 +00001280 RenderTableRow* row = m_grid[r].rowRenderer;
1281 if (row && !row->hasSelfPaintingLayer())
1282 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001283 for (unsigned c = dirtiedColumns.start; c < dirtiedColumns.end; c++) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001284 CellStruct& current = cellAt(r, c);
1285 RenderTableCell* cell = current.primaryCell();
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001286 if (!cell || (r > dirtiedRows.start && primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start && primaryCellAt(r, c - 1) == cell))
robert@webkit.org2d408272011-12-19 19:49:27 +00001287 continue;
1288 paintCell(cell, paintInfo, paintOffset);
1289 }
hyatte031dd02006-03-18 01:01:06 +00001290 }
ap50b58352006-01-22 20:32:36 +00001291 }
jamesr@google.com36623a32010-07-23 20:22:29 +00001292 } else {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001293 // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001294#ifndef NDEBUG
1295 unsigned totalRows = m_grid.size();
1296 unsigned totalCols = table()->columns().size();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001297 ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001298#endif
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001299
1300 // To make sure we properly repaint the section, we repaint all the overflowing cells that we collected.
jamesr@google.com36623a32010-07-23 20:22:29 +00001301 Vector<RenderTableCell*> cells;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001302 copyToVector(m_overflowingCells, cells);
1303
jamesr@google.com36623a32010-07-23 20:22:29 +00001304 HashSet<RenderTableCell*> spanningCells;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001305
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001306 for (unsigned r = dirtiedRows.start; r < dirtiedRows.end; r++) {
robert@webkit.org87e8d0c2012-01-14 19:13:35 +00001307 RenderTableRow* row = m_grid[r].rowRenderer;
1308 if (row && !row->hasSelfPaintingLayer())
1309 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001310 for (unsigned c = dirtiedColumns.start; c < dirtiedColumns.end; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +00001311 CellStruct& current = cellAt(r, c);
jamesr@google.comb4266232010-07-28 20:07:19 +00001312 if (!current.hasCells())
jamesr@google.com36623a32010-07-23 20:22:29 +00001313 continue;
1314 for (unsigned i = 0; i < current.cells.size(); ++i) {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001315 if (m_overflowingCells.contains(current.cells[i]))
1316 continue;
1317
jamesr@google.com36623a32010-07-23 20:22:29 +00001318 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
rafael.lobo@openbossa.org61c47ed2013-05-31 00:53:31 +00001319 if (!spanningCells.add(current.cells[i]).isNewEntry)
jamesr@google.com36623a32010-07-23 20:22:29 +00001320 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +00001321 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001322
jamesr@google.com36623a32010-07-23 20:22:29 +00001323 cells.append(current.cells[i]);
1324 }
1325 }
1326 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001327
jamesr@google.com36623a32010-07-23 20:22:29 +00001328 // Sort the dirty cells by paint order.
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001329 if (!m_overflowingCells.size())
1330 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
1331 else
1332 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
1333
robert@webkit.org2d408272011-12-19 19:49:27 +00001334 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1335 for (unsigned i = cells.size(); i > 0; --i) {
1336 LayoutPoint cellPoint = flipForWritingModeForChild(cells[i - 1], paintOffset);
1337 cells[i - 1]->paintCollapsedBorders(paintInfo, cellPoint);
1338 }
1339 } else {
1340 for (unsigned i = 0; i < cells.size(); ++i)
1341 paintCell(cells[i], paintInfo, paintOffset);
1342 }
ap50b58352006-01-22 20:32:36 +00001343 }
eseidela043f3d2006-01-20 19:24:53 +00001344 }
1345}
1346
darin@apple.com98a7ac62009-01-05 17:26:53 +00001347void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
bdashb07ae8d2007-02-08 04:56:20 +00001348{
bdashb07ae8d2007-02-08 04:56:20 +00001349 // FIXME: Examine cells and repaint only the rect the image paints in.
1350 repaint();
1351}
1352
eseidela043f3d2006-01-20 19:24:53 +00001353void RenderTableSection::recalcCells()
1354{
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001355 ASSERT(m_needsCellRecalc);
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001356 // We reset the flag here to ensure that addCell() works. This is safe to do because we clear the grid
1357 // and update its dimensions to be consistent with the table's column representation before we rebuild
1358 // the grid using addCell().
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001359 m_needsCellRecalc = false;
1360
ddkilzer260f3d22007-01-05 05:56:31 +00001361 m_cCol = 0;
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001362 m_cRow = 0;
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001363 m_grid.clear();
eseidela043f3d2006-01-20 19:24:53 +00001364
antti@apple.com7f9196b2013-09-24 20:47:01 +00001365 for (RenderTableRow* row = firstRow(); row; row = row->nextRow()) {
1366 unsigned insertionRow = m_cRow;
1367 m_cRow++;
1368 m_cCol = 0;
1369 ensureRows(m_cRow);
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001370
antti@apple.com7f9196b2013-09-24 20:47:01 +00001371 m_grid[insertionRow].rowRenderer = row;
1372 row->setRowIndex(insertionRow);
1373 setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
eseidel05ef0432006-05-25 22:11:36 +00001374
antti@apple.com7f9196b2013-09-24 20:47:01 +00001375 for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
1376 addCell(cell, row);
eseidela043f3d2006-01-20 19:24:53 +00001377 }
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001378
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001379 m_grid.shrinkToFit();
antti@apple.comca2a8ff2013-10-04 04:04:35 +00001380 setNeedsLayout();
eseidela043f3d2006-01-20 19:24:53 +00001381}
1382
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +00001383// FIXME: This function could be made O(1) in certain cases (like for the non-most-constrainive cells' case).
jchaffraix@webkit.org19bbb722011-11-03 17:20:01 +00001384void RenderTableSection::rowLogicalHeightChanged(unsigned rowIndex)
1385{
jchaffraix@webkit.orgdd34df42012-01-24 04:15:06 +00001386 if (needsCellRecalc())
1387 return;
1388
jchaffraix@webkit.org19bbb722011-11-03 17:20:01 +00001389 setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[rowIndex]);
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +00001390
antti@apple.com7f9196b2013-09-24 20:47:01 +00001391 for (RenderTableCell* cell = m_grid[rowIndex].rowRenderer->firstCell(); cell; cell = cell->nextCell())
1392 updateLogicalHeightForCell(m_grid[rowIndex], cell);
jchaffraix@webkit.org19bbb722011-11-03 17:20:01 +00001393}
1394
jamesr@google.com5ddfb042011-01-20 21:34:34 +00001395void RenderTableSection::setNeedsCellRecalc()
1396{
1397 m_needsCellRecalc = true;
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001398
1399 // Clear the grid now to ensure that we don't hold onto any stale pointers (e.g. a cell renderer that is being removed).
1400 m_grid.clear();
1401
jamesr@google.com5ddfb042011-01-20 21:34:34 +00001402 if (RenderTable* t = table())
1403 t->setNeedsSectionRecalc();
1404}
1405
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001406unsigned RenderTableSection::numColumns() const
ap50b58352006-01-22 20:32:36 +00001407{
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001408 ASSERT(!m_needsCellRecalc);
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001409 unsigned result = 0;
ap50b58352006-01-22 20:32:36 +00001410
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001411 for (unsigned r = 0; r < m_grid.size(); ++r) {
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001412 for (unsigned c = result; c < table()->numEffCols(); ++c) {
ap50b58352006-01-22 20:32:36 +00001413 const CellStruct& cell = cellAt(r, c);
jamesr@google.com36623a32010-07-23 20:22:29 +00001414 if (cell.hasCells() || cell.inColSpan)
ap50b58352006-01-22 20:32:36 +00001415 result = c;
1416 }
1417 }
1418
1419 return result + 1;
eseidela043f3d2006-01-20 19:24:53 +00001420}
1421
zalan@apple.com1731e362016-07-24 01:39:13 +00001422const BorderValue& RenderTableSection::borderAdjoiningStartCell(const RenderTableCell& cell) const
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001423{
zalan@apple.com1731e362016-07-24 01:39:13 +00001424 ASSERT(cell.isFirstOrLastCellInRow());
zalan@apple.comb2e52722016-07-26 02:15:56 +00001425 return isDirectionSame(this, &cell) ? style().borderStart() : style().borderEnd();
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001426}
1427
zalan@apple.com1731e362016-07-24 01:39:13 +00001428const BorderValue& RenderTableSection::borderAdjoiningEndCell(const RenderTableCell& cell) const
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001429{
zalan@apple.com1731e362016-07-24 01:39:13 +00001430 ASSERT(cell.isFirstOrLastCellInRow());
zalan@apple.comb2e52722016-07-26 02:15:56 +00001431 return isDirectionSame(this, &cell) ? style().borderEnd() : style().borderStart();
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001432}
1433
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001434const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableStart() const
1435{
zalan@apple.comb2e52722016-07-26 02:15:56 +00001436 unsigned adjoiningStartCellColumnIndex = isDirectionSame(this, table()) ? 0 : table()->lastColumnIndex();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001437 return cellAt(0, adjoiningStartCellColumnIndex).primaryCell();
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001438}
1439
1440const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableEnd() const
1441{
zalan@apple.comb2e52722016-07-26 02:15:56 +00001442 unsigned adjoiningEndCellColumnIndex = isDirectionSame(this, table()) ? table()->lastColumnIndex() : 0;
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001443 return cellAt(0, adjoiningEndCellColumnIndex).primaryCell();
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001444}
1445
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001446void RenderTableSection::appendColumn(unsigned pos)
ddkilzer260f3d22007-01-05 05:56:31 +00001447{
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001448 ASSERT(!m_needsCellRecalc);
1449
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001450 for (unsigned row = 0; row < m_grid.size(); ++row)
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001451 m_grid[row].row.resize(pos + 1);
ddkilzer260f3d22007-01-05 05:56:31 +00001452}
1453
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001454void RenderTableSection::splitColumn(unsigned pos, unsigned first)
ddkilzer260f3d22007-01-05 05:56:31 +00001455{
inferno@chromium.orgb1ffad72011-10-10 18:58:12 +00001456 ASSERT(!m_needsCellRecalc);
1457
ddkilzer260f3d22007-01-05 05:56:31 +00001458 if (m_cCol > pos)
1459 m_cCol++;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001460 for (unsigned row = 0; row < m_grid.size(); ++row) {
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001461 Row& r = m_grid[row].row;
jamesr@google.com36623a32010-07-23 20:22:29 +00001462 r.insert(pos + 1, CellStruct());
1463 if (r[pos].hasCells()) {
andersca@apple.com92012992013-05-05 19:03:49 +00001464 r[pos + 1].cells.appendVector(r[pos].cells);
jamesr@google.com36623a32010-07-23 20:22:29 +00001465 RenderTableCell* cell = r[pos].primaryCell();
1466 ASSERT(cell);
commit-queue@webkit.org1ee5b342012-05-08 05:14:07 +00001467 ASSERT(cell->colSpan() >= (r[pos].inColSpan ? 1u : 0));
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001468 unsigned colleft = cell->colSpan() - r[pos].inColSpan;
jamesr@google.com36623a32010-07-23 20:22:29 +00001469 if (first > colleft)
1470 r[pos + 1].inColSpan = 0;
1471 else
1472 r[pos + 1].inColSpan = first + r[pos].inColSpan;
1473 } else {
1474 r[pos + 1].inColSpan = 0;
1475 }
ddkilzer260f3d22007-01-05 05:56:31 +00001476 }
1477}
1478
hyattd866e592006-03-17 09:50:35 +00001479// Hit Testing
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001480bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
hyattd866e592006-03-17 09:50:35 +00001481{
jamesr@google.comf88b2582010-08-17 20:57:15 +00001482 // If we have no children then we have nothing to do.
antti@apple.com7f9196b2013-09-24 20:47:01 +00001483 if (!firstRow())
jamesr@google.comf88b2582010-08-17 20:57:15 +00001484 return false;
1485
hyattd866e592006-03-17 09:50:35 +00001486 // Table sections cannot ever be hit tested. Effectively they do not exist.
1487 // Just forward to our children always.
eae@chromium.orge14cd1a2011-07-06 23:38:32 +00001488 LayoutPoint adjustedLocation = accumulatedOffset + location();
hyattd866e592006-03-17 09:50:35 +00001489
abucur@adobe.com7f9668a2014-05-16 13:22:00 +00001490 if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment())))
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001491 return false;
1492
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001493 if (hasOverflowingCell()) {
antti@apple.com7f9196b2013-09-24 20:47:01 +00001494 for (RenderTableRow* row = lastRow(); row; row = row->previousRow()) {
jamesr@google.comf88b2582010-08-17 20:57:15 +00001495 // FIXME: We have to skip over inline flows, since they can show up inside table rows
1496 // at the moment (a demoted inline <form> for example). If we ever implement a
1497 // table-specific hit-test method (which we should do for performance reasons anyway),
1498 // then we can remove this check.
antti@apple.comd04c0812013-09-25 17:45:59 +00001499 if (!row->hasSelfPaintingLayer()) {
antti@apple.com7f9196b2013-09-24 20:47:01 +00001500 LayoutPoint childPoint = flipForWritingModeForChild(row, adjustedLocation);
1501 if (row->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001502 updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
mitz@apple.com39fb3ae2010-11-09 20:46:15 +00001503 return true;
1504 }
jamesr@google.comf88b2582010-08-17 20:57:15 +00001505 }
1506 }
1507 return false;
1508 }
1509
inferno@chromium.org9c8b2302012-02-21 19:10:05 +00001510 recalcCellsIfNeeded();
1511
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001512 LayoutRect hitTestRect = locationInContainer.boundingBox();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001513 hitTestRect.moveBy(-adjustedLocation);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001514
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001515 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect);
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001516 CellSpan rowSpan = spannedRows(tableAlignedRect, DoNotIncludeAllIntersectingCells);
1517 CellSpan columnSpan = spannedColumns(tableAlignedRect, DoNotIncludeAllIntersectingCells);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001518
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001519 // Now iterate over the spanned rows and columns.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001520 for (unsigned hitRow = rowSpan.start; hitRow < rowSpan.end; ++hitRow) {
1521 for (unsigned hitColumn = columnSpan.start; hitColumn < columnSpan.end; ++hitColumn) {
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001522 CellStruct& current = cellAt(hitRow, hitColumn);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001523
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001524 // If the cell is empty, there's nothing to do
1525 if (!current.hasCells())
1526 continue;
jamesr@google.comf88b2582010-08-17 20:57:15 +00001527
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001528 for (unsigned i = current.cells.size() ; i; ) {
1529 --i;
1530 RenderTableCell* cell = current.cells[i];
1531 LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001532 if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
1533 updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001534 return true;
1535 }
1536 }
1537 if (!result.isRectBasedTest())
1538 break;
hyattd866e592006-03-17 09:50:35 +00001539 }
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001540 if (!result.isRectBasedTest())
1541 break;
hyattd866e592006-03-17 09:50:35 +00001542 }
jamesr@google.comf88b2582010-08-17 20:57:15 +00001543
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001544 return false;
hyattd866e592006-03-17 09:50:35 +00001545}
1546
zalan@apple.com42146622015-04-01 15:56:34 +00001547void RenderTableSection::clearCachedCollapsedBorders()
1548{
1549 if (!table()->collapseBorders())
1550 return;
1551 m_cellsCollapsedBorders.clear();
1552}
1553
1554void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell& cell)
robert@webkit.org76a76102012-01-15 13:48:45 +00001555{
1556 if (!table()->collapseBorders())
1557 return;
1558
1559 for (int side = CBSBefore; side <= CBSEnd; ++side)
zalan@apple.com42146622015-04-01 15:56:34 +00001560 m_cellsCollapsedBorders.remove(std::make_pair(&cell, side));
robert@webkit.org76a76102012-01-15 13:48:45 +00001561}
1562
zalan@apple.com42146622015-04-01 15:56:34 +00001563void RenderTableSection::setCachedCollapsedBorder(const RenderTableCell& cell, CollapsedBorderSide side, CollapsedBorderValue border)
robert@webkit.org76a76102012-01-15 13:48:45 +00001564{
1565 ASSERT(table()->collapseBorders());
zalan@apple.com42146622015-04-01 15:56:34 +00001566 ASSERT(border.width());
1567 m_cellsCollapsedBorders.set(std::make_pair(&cell, side), border);
robert@webkit.org76a76102012-01-15 13:48:45 +00001568}
1569
zalan@apple.com42146622015-04-01 15:56:34 +00001570CollapsedBorderValue RenderTableSection::cachedCollapsedBorder(const RenderTableCell& cell, CollapsedBorderSide side)
robert@webkit.org76a76102012-01-15 13:48:45 +00001571{
zalan@apple.com42146622015-04-01 15:56:34 +00001572 ASSERT(table()->collapseBorders() && table()->collapsedBordersAreValid());
1573 auto it = m_cellsCollapsedBorders.find(std::make_pair(&cell, side));
1574 // Only non-empty collapsed borders are in the hashmap.
1575 if (it == m_cellsCollapsedBorders.end())
1576 return CollapsedBorderValue(BorderValue(), Color(), BCELL);
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001577 return it->value;
robert@webkit.org76a76102012-01-15 13:48:45 +00001578}
1579
zalan@apple.comcda46e42016-07-26 02:40:04 +00001580std::unique_ptr<RenderTableSection> RenderTableSection::createTableSectionWithStyle(Document& document, const RenderStyle& style)
inferno@chromium.org2164c612012-04-04 22:41:56 +00001581{
zalan@apple.comcda46e42016-07-26 02:40:04 +00001582 auto section = std::make_unique<RenderTableSection>(document, RenderStyle::createAnonymousStyleWithDisplay(style, TABLE_ROW_GROUP));
akling@apple.com8f40c5b2013-10-27 22:54:07 +00001583 section->initializeStyle();
1584 return section;
inferno@chromium.org2164c612012-04-04 22:41:56 +00001585}
1586
zalan@apple.comcda46e42016-07-26 02:40:04 +00001587std::unique_ptr<RenderTableSection> RenderTableSection::createAnonymousWithParentRenderer(const RenderTable& parent)
1588{
1589 return RenderTableSection::createTableSectionWithStyle(parent.document(), parent.style());
1590}
1591
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001592void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsigned effectiveColumn) const
1593{
eae@chromium.org1146f212012-07-18 22:06:34 +00001594 LayoutPoint oldCellLocation = cell->location();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001595
1596 LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]);
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001597 LayoutUnit horizontalBorderSpacing = table()->hBorderSpacing();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001598
jchaffraix@webkit.org6d6c3052012-11-05 07:55:28 +00001599 // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
akling@apple.com827be9c2013-10-29 02:58:43 +00001600 if (!style().isLeftToRightDirection())
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001601 cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + horizontalBorderSpacing);
1602 else
1603 cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
1604
1605 cell->setLogicalLocation(cellLocation);
akling@apple.com691cf5c2013-08-24 16:33:15 +00001606 view().addLayoutDelta(oldCellLocation - cell->location());
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001607}
1608
ddkilzer260f3d22007-01-05 05:56:31 +00001609} // namespace WebCore