blob: d885e8e2c625c6dc0b5f2dff1579343ee5ee510f [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.come10a9b12016-08-26 23:25:29 +0000255static LayoutUnit resolveLogicalHeightForRow(const Length& rowLogicalHeight)
256{
257 if (rowLogicalHeight.isFixed())
258 return rowLogicalHeight.value();
259 if (rowLogicalHeight.isCalculated())
260 return rowLogicalHeight.nonNanCalculatedValue(0);
261 return 0;
262}
263
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000264LayoutUnit RenderTableSection::calcRowLogicalHeight()
eseidela043f3d2006-01-20 19:24:53 +0000265{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000266#ifndef NDEBUG
ojan@chromium.orgccdc4292013-02-07 00:55:10 +0000267 SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000268#endif
269
270 ASSERT(!needsLayout());
271
ddkilzer260f3d22007-01-05 05:56:31 +0000272 RenderTableCell* cell;
eseidela043f3d2006-01-20 19:24:53 +0000273
ossy@webkit.orgcf6bebb2013-11-25 14:57:38 +0000274 // 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 +0000275 LayoutUnit spacing = 0;
ossy@webkit.orgcf6bebb2013-11-25 14:57:38 +0000276 if (this == table()->topSection())
277 spacing = table()->vBorderSpacing();
akling@apple.com691cf5c2013-08-24 16:33:15 +0000278
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000279 LayoutStateMaintainer statePusher(view());
eseidela043f3d2006-01-20 19:24:53 +0000280
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000281 m_rowPos.resize(m_grid.size() + 1);
ddkilzer260f3d22007-01-05 05:56:31 +0000282 m_rowPos[0] = spacing;
eseidela043f3d2006-01-20 19:24:53 +0000283
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000284 unsigned totalRows = m_grid.size();
285
286 for (unsigned r = 0; r < totalRows; r++) {
zimmermann@webkit.org14b310a2012-02-25 09:27:25 +0000287 m_grid[r].baseline = 0;
leviw@chromium.org2650e382012-04-04 10:37:36 +0000288 LayoutUnit baselineDescent = 0;
eseidela043f3d2006-01-20 19:24:53 +0000289
jchaffraix@webkit.orgaddd65e2012-02-26 00:19:22 +0000290 // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
zalan@apple.come10a9b12016-08-26 23:25:29 +0000291 m_rowPos[r + 1] = std::max(m_rowPos[r] + resolveLogicalHeightForRow(m_grid[r].logicalHeight), LayoutUnit::fromPixel(0));
eseidela043f3d2006-01-20 19:24:53 +0000292
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +0000293 Row& row = m_grid[r].row;
294 unsigned totalCols = row.size();
eseidela043f3d2006-01-20 19:24:53 +0000295
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000296 for (unsigned c = 0; c < totalCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000297 CellStruct& current = cellAt(r, c);
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000298 for (unsigned i = 0; i < current.cells.size(); i++) {
299 cell = current.cells[i];
300 if (current.inColSpan && cell->rowSpan() == 1)
301 continue;
jamesr@google.comb4266232010-07-28 20:07:19 +0000302
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000303 // FIXME: We are always adding the height of a rowspan to the last rows which doesn't match
304 // other browsers. See webkit.org/b/52185 for example.
305 if ((cell->rowIndex() + cell->rowSpan() - 1) != r) {
306 // We will apply the height of the rowspan to the current row if next row is not valid.
307 if ((r + 1) < totalRows) {
308 unsigned col = 0;
309 CellStruct nextRowCell = cellAt(r + 1, col);
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000310
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000311 // We are trying to find that next row is valid or not.
312 while (nextRowCell.cells.size() && nextRowCell.cells[0]->rowSpan() > 1 && nextRowCell.cells[0]->rowIndex() < (r + 1)) {
313 col++;
314 if (col < totalCols)
315 nextRowCell = cellAt(r + 1, col);
316 else
317 break;
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000318 }
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000319
320 // We are adding the height of the rowspan to the current row if next row is not valid.
321 if (col < totalCols && nextRowCell.cells.size())
322 continue;
commit-queue@webkit.org1fdc04c2013-04-23 06:36:45 +0000323 }
324 }
jamesr@google.com36623a32010-07-23 20:22:29 +0000325
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000326 // For row spanning cells, |r| is the last row in the span.
327 unsigned cellStartRow = cell->rowIndex();
328
rego@igalia.comf7d624c2015-04-22 10:31:24 +0000329 if (cell->hasOverrideLogicalContentHeight()) {
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000330 if (!statePusher.didPush()) {
331 // Technically, we should also push state for the row, but since
332 // rows don't push a coordinate transform, that's not necessary.
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000333 statePusher.push(*this, locationOffset());
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000334 }
335 cell->clearIntrinsicPadding();
336 cell->clearOverrideSize();
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000337 cell->setChildNeedsLayout(MarkOnlyThis);
commit-queue@webkit.org5ec57ca2012-07-12 22:33:36 +0000338 cell->layoutIfNeeded();
weinigfef13632007-04-29 20:09:08 +0000339 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000340
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000341 LayoutUnit cellLogicalHeight = cell->logicalHeightForRowSizing();
andersca@apple.com86298632013-11-10 19:32:33 +0000342 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cellLogicalHeight);
eseidela043f3d2006-01-20 19:24:53 +0000343
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000344 // Find out the baseline. The baseline is set on the first row in a rowspan.
robert@webkit.org292be542013-03-09 06:40:13 +0000345 if (cell->isBaselineAligned()) {
zalan@apple.comdf6351f2016-01-11 22:03:03 +0000346 LayoutUnit baselinePosition = cell->cellBaselinePosition() - cell->intrinsicPaddingBefore();
347 LayoutUnit borderAndComputedPaddingBefore = cell->borderAndPaddingBefore() - cell->intrinsicPaddingBefore();
348 if (baselinePosition > borderAndComputedPaddingBefore) {
andersca@apple.com86298632013-11-10 19:32:33 +0000349 m_grid[cellStartRow].baseline = std::max(m_grid[cellStartRow].baseline, baselinePosition);
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000350 // 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
351 // become the baseline descent applied to the rest of the row. Also we don't account for the baseline descent of
352 // non-spanning cells when computing a spanning cell's extent.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000353 LayoutUnit cellStartRowBaselineDescent = 0;
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000354 if (cell->rowSpan() == 1) {
zalan@apple.comdf6351f2016-01-11 22:03:03 +0000355 baselineDescent = std::max(baselineDescent, cellLogicalHeight - baselinePosition);
commit-queue@webkit.orgbb454812013-05-14 19:57:51 +0000356 cellStartRowBaselineDescent = baselineDescent;
357 }
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000358 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 +0000359 }
eseidela043f3d2006-01-20 19:24:53 +0000360 }
ap50b58352006-01-22 20:32:36 +0000361 }
362 }
eseidela043f3d2006-01-20 19:24:53 +0000363
jchaffraix@webkit.orgaddd65e2012-02-26 00:19:22 +0000364 // Add the border-spacing to our final position.
ossy@webkit.org6d30aa72013-11-28 17:40:59 +0000365 // Use table border-spacing even in non-top sections
366 spacing = table()->vBorderSpacing();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000367 m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : LayoutUnit::fromPixel(0);
andersca@apple.com86298632013-11-10 19:32:33 +0000368 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[r]);
eseidela043f3d2006-01-20 19:24:53 +0000369 }
weinigfef13632007-04-29 20:09:08 +0000370
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000371 ASSERT(!needsLayout());
372
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000373 statePusher.pop();
mitz@apple.com440ac8c2008-04-05 16:05:08 +0000374
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000375 return m_rowPos[m_grid.size()];
eseidela043f3d2006-01-20 19:24:53 +0000376}
377
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000378void RenderTableSection::layout()
379{
mark.lam@apple.com6df1a802012-10-19 20:09:36 +0000380 StackStats::LayoutCheckPoint layoutCheckPoint;
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000381 ASSERT(needsLayout());
inferno@chromium.org7081f502012-05-26 00:28:23 +0000382 ASSERT(!needsCellRecalc());
383 ASSERT(!table()->needsSectionRecalc());
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000384
zalan@apple.coma2c50dc2016-08-23 21:47:20 +0000385 m_forceSlowPaintPathWithOverflowingCell = false;
jchaffraix@webkit.orga9ddfc12012-06-18 17:11:12 +0000386 // addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
387 // can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
388 m_grid.shrinkToFit();
389
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000390 LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
hyatt@apple.comccad3742015-02-04 21:39:00 +0000391 bool paginated = view().layoutState()->isPaginated();
392
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000393 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
hyatt@apple.comccad3742015-02-04 21:39:00 +0000394
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000395 for (unsigned r = 0; r < m_grid.size(); ++r) {
396 Row& row = m_grid[r].row;
397 unsigned cols = row.size();
398 // First, propagate our table layout's information to the cells. This will mark the row as needing layout
399 // if there was a column logical width change.
400 for (unsigned startColumn = 0; startColumn < cols; ++startColumn) {
401 CellStruct& current = row[startColumn];
402 RenderTableCell* cell = current.primaryCell();
403 if (!cell || current.inColSpan)
404 continue;
405
406 unsigned endCol = startColumn;
407 unsigned cspan = cell->colSpan();
408 while (cspan && endCol < cols) {
409 ASSERT(endCol < table()->columns().size());
410 cspan -= table()->columns()[endCol].span;
411 endCol++;
412 }
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000413 LayoutUnit tableLayoutLogicalWidth = columnPos[endCol] - columnPos[startColumn] - table()->hBorderSpacing();
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000414 cell->setCellLogicalWidth(tableLayoutLogicalWidth);
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000415 }
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000416
hyatt@apple.comccad3742015-02-04 21:39:00 +0000417 if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
418 if (!rowRenderer->needsLayout() && paginated && view().layoutState()->pageLogicalHeightChanged())
419 rowRenderer->setChildNeedsLayout(MarkOnlyThis);
420
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000421 rowRenderer->layoutIfNeeded();
hyatt@apple.comccad3742015-02-04 21:39:00 +0000422 }
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000423 }
jchaffraix@webkit.orga66f1082012-10-16 16:42:02 +0000424
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000425 statePusher.pop();
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000426 clearNeedsLayout();
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000427}
428
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000429void RenderTableSection::distributeExtraLogicalHeightToPercentRows(LayoutUnit& extraLogicalHeight, int totalPercent)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000430{
431 if (!totalPercent)
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000432 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000433
434 unsigned totalRows = m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000435 LayoutUnit totalHeight = m_rowPos[totalRows] + extraLogicalHeight;
436 LayoutUnit totalLogicalHeightAdded = 0;
andersca@apple.com86298632013-11-10 19:32:33 +0000437 totalPercent = std::min(totalPercent, 100);
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000438 LayoutUnit rowHeight = m_rowPos[1] - m_rowPos[0];
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000439 for (unsigned r = 0; r < totalRows; ++r) {
commit-queue@webkit.org2a67f682015-05-10 21:43:26 +0000440 if (totalPercent > 0 && m_grid[r].logicalHeight.isPercent()) {
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000441 LayoutUnit toAdd = std::min<LayoutUnit>(extraLogicalHeight, (totalHeight * m_grid[r].logicalHeight.percent() / 100) - rowHeight);
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000442 // If toAdd is negative, then we don't want to shrink the row (this bug
443 // affected Outlook Web Access).
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000444 toAdd = std::max(LayoutUnit::fromPixel(0), toAdd);
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000445 totalLogicalHeightAdded += toAdd;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000446 extraLogicalHeight -= toAdd;
447 totalPercent -= m_grid[r].logicalHeight.percent();
448 }
449 ASSERT(totalRows >= 1);
450 if (r < totalRows - 1)
451 rowHeight = m_rowPos[r + 2] - m_rowPos[r + 1];
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000452 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000453 }
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000454}
455
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000456void RenderTableSection::distributeExtraLogicalHeightToAutoRows(LayoutUnit& extraLogicalHeight, unsigned autoRowsCount)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000457{
458 if (!autoRowsCount)
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000459 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000460
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000461 LayoutUnit totalLogicalHeightAdded = 0;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000462 for (unsigned r = 0; r < m_grid.size(); ++r) {
463 if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) {
464 // Recomputing |extraLogicalHeightForRow| guarantees that we properly ditribute round |extraLogicalHeight|.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000465 LayoutUnit extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount;
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000466 totalLogicalHeightAdded += extraLogicalHeightForRow;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000467 extraLogicalHeight -= extraLogicalHeightForRow;
468 --autoRowsCount;
469 }
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000470 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000471 }
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000472}
473
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000474void RenderTableSection::distributeRemainingExtraLogicalHeight(LayoutUnit& extraLogicalHeight)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000475{
476 unsigned totalRows = m_grid.size();
477
478 if (extraLogicalHeight <= 0 || !m_rowPos[totalRows])
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000479 return;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000480
481 // FIXME: m_rowPos[totalRows] - m_rowPos[0] is the total rows' size.
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000482 LayoutUnit totalRowSize = m_rowPos[totalRows];
483 LayoutUnit totalLogicalHeightAdded = 0;
484 LayoutUnit previousRowPosition = m_rowPos[0];
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000485 for (unsigned r = 0; r < totalRows; r++) {
486 // weight with the original height
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000487 totalLogicalHeightAdded += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000488 previousRowPosition = m_rowPos[r + 1];
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000489 m_rowPos[r + 1] += totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000490 }
491
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000492 extraLogicalHeight -= totalLogicalHeightAdded;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000493}
494
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000495LayoutUnit RenderTableSection::distributeExtraLogicalHeightToRows(LayoutUnit extraLogicalHeight)
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000496{
497 if (!extraLogicalHeight)
498 return extraLogicalHeight;
499
500 unsigned totalRows = m_grid.size();
501 if (!totalRows)
502 return extraLogicalHeight;
503
504 if (!m_rowPos[totalRows] && nextSibling())
505 return extraLogicalHeight;
506
507 unsigned autoRowsCount = 0;
508 int totalPercent = 0;
509 for (unsigned r = 0; r < totalRows; r++) {
510 if (m_grid[r].logicalHeight.isAuto())
511 ++autoRowsCount;
commit-queue@webkit.org2a67f682015-05-10 21:43:26 +0000512 else if (m_grid[r].logicalHeight.isPercent())
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000513 totalPercent += m_grid[r].logicalHeight.percent();
514 }
515
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000516 LayoutUnit remainingExtraLogicalHeight = extraLogicalHeight;
jchaffraix@webkit.orgc2788982012-03-20 21:02:34 +0000517 distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
518 distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
519 distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
520 return extraLogicalHeight - remainingExtraLogicalHeight;
jchaffraix@webkit.org3395b972012-03-09 22:58:05 +0000521}
522
jchaffraix@webkit.org94f150f2012-03-20 04:53:14 +0000523void RenderTableSection::layoutRows()
eseidela043f3d2006-01-20 19:24:53 +0000524{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000525#ifndef NDEBUG
ojan@chromium.orgccdc4292013-02-07 00:55:10 +0000526 SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000527#endif
528
529 ASSERT(!needsLayout());
530
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000531 unsigned totalRows = m_grid.size();
532
hyattd866e592006-03-17 09:50:35 +0000533 // Set the width of our section now. The rows will also be this width.
mitz@apple.com8010bba2010-11-05 02:43:17 +0000534 setLogicalWidth(table()->contentLogicalWidth());
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000535 m_forceSlowPaintPathWithOverflowingCell = false;
adeleddfe27f2007-01-05 23:03:50 +0000536
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000537 LayoutUnit vspacing = table()->vBorderSpacing();
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000538 unsigned nEffCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000539
weinig@apple.comf8d77f32013-11-18 01:12:17 +0000540 LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || style().isFlippedBlocksWritingMode());
weinigfef13632007-04-29 20:09:08 +0000541
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000542 for (unsigned r = 0; r < totalRows; r++) {
hyattd866e592006-03-17 09:50:35 +0000543 // Set the row's x/y position and width/height.
hyatt@apple.comd885df72009-01-22 02:31:52 +0000544 if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
robert@webkit.orgf9766b12013-08-27 19:21:00 +0000545 // FIXME: the x() position of the row should be table()->hBorderSpacing() so that it can
546 // report the correct offsetLeft. However, that will require a lot of rebaselining of test results.
leviw@chromium.org7353dfd2011-08-12 21:01:45 +0000547 rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
mitz@apple.com8010bba2010-11-05 02:43:17 +0000548 rowRenderer->setLogicalWidth(logicalWidth());
549 rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
simon.fraser@apple.com78e3bdb2010-11-30 00:53:05 +0000550 rowRenderer->updateLayerTransform();
zalan@apple.comd423bcc2016-02-06 23:07:54 +0000551 rowRenderer->clearOverflow();
552 rowRenderer->addVisualEffectOverflow();
hyattd866e592006-03-17 09:50:35 +0000553 }
554
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000555 LayoutUnit rowHeightIncreaseForPagination = 0;
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000556
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000557 for (unsigned c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000558 CellStruct& cs = cellAt(r, c);
559 RenderTableCell* cell = cs.primaryCell();
560
jamesr@google.comb4266232010-07-28 20:07:19 +0000561 if (!cell || cs.inColSpan)
ap50b58352006-01-22 20:32:36 +0000562 continue;
eseidela043f3d2006-01-20 19:24:53 +0000563
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000564 int rowIndex = cell->rowIndex();
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000565 LayoutUnit rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing;
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000566
eseidela043f3d2006-01-20 19:24:53 +0000567 // Force percent height children to lay themselves out again.
568 // This will cause these children to grow to fill the cell.
569 // FIXME: There is still more work to do here to fully match WinIE (should
570 // it become necessary to do so). In quirks mode, WinIE behaves like we
571 // do, but it will clip the cells that spill out of the table section. In
572 // strict mode, Mozilla and WinIE both regrow the table to accommodate the
573 // new height of the cell (thus letting the percentages cause growth one
574 // time only). We may also not be handling row-spanning cells correctly.
575 //
576 // Note also the oddity where replaced elements always flex, and yet blocks/tables do
577 // not necessarily flex. WinIE is crazy and inconsistent, and we can't hope to
578 // match the behavior perfectly, but we'll continue to refine it as we discover new
579 // bugs. :)
580 bool cellChildrenFlex = false;
akling@apple.com827be9c2013-10-29 02:58:43 +0000581 bool flexAllChildren = cell->style().logicalHeight().isFixed()
582 || (!table()->style().logicalHeight().isAuto() && rHeight != cell->logicalHeight());
eseidela043f3d2006-01-20 19:24:53 +0000583
cdumez@apple.com69626952016-05-17 22:39:00 +0000584 for (auto& renderer : childrenOfType<RenderObject>(*cell)) {
585 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 +0000586 // Tables with no sections do not flex.
cdumez@apple.com69626952016-05-17 22:39:00 +0000587 if (!is<RenderTable>(renderer) || downcast<RenderTable>(renderer).hasSections()) {
588 renderer.setNeedsLayout(MarkOnlyThis);
eseidela043f3d2006-01-20 19:24:53 +0000589 cellChildrenFlex = true;
590 }
591 }
592 }
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000593
tony@chromium.org05b9d2c2012-09-05 01:31:38 +0000594 if (TrackedRendererListHashSet* percentHeightDescendants = cell->percentHeightDescendants()) {
595 TrackedRendererListHashSet::iterator end = percentHeightDescendants->end();
596 for (TrackedRendererListHashSet::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000597 RenderBox* box = *it;
598 if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
599 continue;
600
601 while (box != cell) {
602 if (box->normalChildNeedsLayout())
603 break;
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000604 box->setChildNeedsLayout(MarkOnlyThis);
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000605 box = box->containingBlock();
606 ASSERT(box);
607 if (!box)
608 break;
609 }
610 cellChildrenFlex = true;
611 }
612 }
613
eseidela043f3d2006-01-20 19:24:53 +0000614 if (cellChildrenFlex) {
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000615 cell->setChildNeedsLayout(MarkOnlyThis);
eseidela043f3d2006-01-20 19:24:53 +0000616 // Alignment within a cell is based off the calculated
617 // height, which becomes irrelevant once the cell has
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000618 // been resized based off its percentage.
ojan@chromium.org7a1ce8b2012-06-05 18:32:10 +0000619 cell->setOverrideLogicalContentHeightFromRowHeight(rHeight);
ap7332aaa2006-04-28 16:02:45 +0000620 cell->layoutIfNeeded();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000621
hyatt851433b2007-05-12 06:40:14 +0000622 // 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 +0000623 if (cell->isBaselineAligned()) {
leviw@chromium.org2650e382012-04-04 10:37:36 +0000624 LayoutUnit baseline = cell->cellBaselinePosition();
zoltan@webkit.org8e79cc22013-06-14 00:39:36 +0000625 if (baseline > cell->borderAndPaddingBefore())
andersca@apple.com86298632013-11-10 19:32:33 +0000626 m_grid[r].baseline = std::max(m_grid[r].baseline, baseline);
hyatt851433b2007-05-12 06:40:14 +0000627 }
eseidela043f3d2006-01-20 19:24:53 +0000628 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000629
jchaffraix@webkit.org83cb3912012-10-05 03:56:17 +0000630 cell->computeIntrinsicPadding(rHeight);
mitz@apple.com8010bba2010-11-05 02:43:17 +0000631
eae@chromium.org1146f212012-07-18 22:06:34 +0000632 LayoutRect oldCellRect = cell->frameRect();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000633
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +0000634 setLogicalPositionForCell(cell, c);
eseidela043f3d2006-01-20 19:24:53 +0000635
akling@apple.com691cf5c2013-08-24 16:33:15 +0000636 if (!cell->needsLayout() && view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
antti@apple.comca2a8ff2013-10-04 04:04:35 +0000637 cell->setChildNeedsLayout(MarkOnlyThis);
mitz@apple.com8010bba2010-11-05 02:43:17 +0000638
hyatt@apple.com1259d732010-09-20 16:12:58 +0000639 cell->layoutIfNeeded();
mitz@apple.com8010bba2010-11-05 02:43:17 +0000640
641 // FIXME: Make pagination work with vertical tables.
akling@apple.com691cf5c2013-08-24 16:33:15 +0000642 if (view().layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
hyatt@apple.com8403ad22012-04-10 18:14:20 +0000643 // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
644 // 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
645 // 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 +0000646 if (cell->logicalHeight() > rHeight)
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000647 rowHeightIncreaseForPagination = std::max(rowHeightIncreaseForPagination, cell->logicalHeight() - rHeight);
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000648 cell->setLogicalHeight(rHeight);
hyatt@apple.com8403ad22012-04-10 18:14:20 +0000649 }
mitz@apple.com8010bba2010-11-05 02:43:17 +0000650
leviw@chromium.org7353dfd2011-08-12 21:01:45 +0000651 LayoutSize childOffset(cell->location() - oldCellRect.location());
hyatt@apple.comb297b492010-09-20 20:21:34 +0000652 if (childOffset.width() || childOffset.height()) {
akling@apple.com691cf5c2013-08-24 16:33:15 +0000653 view().addLayoutDelta(childOffset);
hyatt@apple.com1259d732010-09-20 16:12:58 +0000654
hyatt@apple.comb297b492010-09-20 20:21:34 +0000655 // If the child moved, we have to repaint it as well as any floating/positioned
656 // descendants. An exception is if we need a layout. In this case, we know we're going to
657 // repaint ourselves (and the child) anyway.
658 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
659 cell->repaintDuringLayoutIfMoved(oldCellRect);
660 }
eseidela043f3d2006-01-20 19:24:53 +0000661 }
mitz@apple.com48b3ee82012-07-12 02:38:38 +0000662 if (rowHeightIncreaseForPagination) {
663 for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++)
664 m_rowPos[rowIndex] += rowHeightIncreaseForPagination;
665 for (unsigned c = 0; c < nEffCols; ++c) {
666 Vector<RenderTableCell*, 1>& cells = cellAt(r, c).cells;
667 for (size_t i = 0; i < cells.size(); ++i)
668 cells[i]->setLogicalHeight(cells[i]->logicalHeight() + rowHeightIncreaseForPagination);
669 }
670 }
eseidela043f3d2006-01-20 19:24:53 +0000671 }
672
hyatt@apple.com8b2cd1f2009-01-26 03:38:55 +0000673 ASSERT(!needsLayout());
674
mitz@apple.com8010bba2010-11-05 02:43:17 +0000675 setLogicalHeight(m_rowPos[totalRows]);
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000676
robert@webkit.org4c91cc92013-03-27 23:49:48 +0000677 computeOverflowFromCells(totalRows, nEffCols);
678
679 statePusher.pop();
680}
681
682void RenderTableSection::computeOverflowFromCells()
683{
684 unsigned totalRows = m_grid.size();
685 unsigned nEffCols = table()->numEffCols();
686 computeOverflowFromCells(totalRows, nEffCols);
687}
688
689void RenderTableSection::computeOverflowFromCells(unsigned totalRows, unsigned nEffCols)
690{
abucur@adobe.com6585d012013-09-04 08:26:41 +0000691 clearOverflow();
robert@webkit.orge4314c42013-08-08 18:13:22 +0000692 m_overflowingCells.clear();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000693 unsigned totalCellsCount = nEffCols * totalRows;
commit-queue@webkit.org877bfc32015-03-10 21:54:21 +0000694 unsigned maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000695
696#ifndef NDEBUG
697 bool hasOverflowingCell = false;
698#endif
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000699 // Now that our height has been determined, add in overflow from cells.
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +0000700 for (unsigned r = 0; r < totalRows; r++) {
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000701 for (unsigned c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000702 CellStruct& cs = cellAt(r, c);
703 RenderTableCell* cell = cs.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +0000704 if (!cell || cs.inColSpan)
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000705 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000706 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000707 continue;
708 addOverflowFromChild(cell);
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000709#ifndef NDEBUG
710 hasOverflowingCell |= cell->hasVisualOverflow();
711#endif
712 if (cell->hasVisualOverflow() && !m_forceSlowPaintPathWithOverflowingCell) {
713 m_overflowingCells.add(cell);
714 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) {
715 // We need to set m_forcesSlowPaintPath only if there is a least one overflowing cells as the hit testing code rely on this information.
716 m_forceSlowPaintPathWithOverflowingCell = true;
717 // The slow path does not make any use of the overflowing cells info, don't hold on to the memory.
718 m_overflowingCells.clear();
719 }
720 }
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000721 }
722 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000723 ASSERT(hasOverflowingCell == this->hasOverflowingCell());
eseidela043f3d2006-01-20 19:24:53 +0000724}
725
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000726LayoutUnit RenderTableSection::calcOuterBorderBefore() const
darin32011102006-05-15 04:42:09 +0000727{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000728 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000729 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000730 return 0;
731
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000732 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000733
akling@apple.com827be9c2013-10-29 02:58:43 +0000734 const BorderValue& sb = style().borderBefore();
darin32011102006-05-15 04:42:09 +0000735 if (sb.style() == BHIDDEN)
736 return -1;
737 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000738 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000739
akling@apple.com827be9c2013-10-29 02:58:43 +0000740 const BorderValue& rb = firstRow()->style().borderBefore();
darin32011102006-05-15 04:42:09 +0000741 if (rb.style() == BHIDDEN)
742 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000743 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
744 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000745
746 bool allHidden = true;
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000747 for (unsigned c = 0; c < totalCols; c++) {
darin32011102006-05-15 04:42:09 +0000748 const CellStruct& current = cellAt(0, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000749 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000750 continue;
akling@apple.com827be9c2013-10-29 02:58:43 +0000751 const BorderValue& cb = current.primaryCell()->style().borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
darin32011102006-05-15 04:42:09 +0000752 // FIXME: Don't repeat for the same col group
753 RenderTableCol* colGroup = table()->colElement(c);
754 if (colGroup) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000755 const BorderValue& gb = colGroup->style().borderBefore();
darin32011102006-05-15 04:42:09 +0000756 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
757 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000758 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000759 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
760 borderWidth = gb.width();
761 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
762 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000763 } else {
764 if (cb.style() == BHIDDEN)
765 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000766 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000767 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
768 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000769 }
770 }
771 if (allHidden)
772 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000773 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), false);
darin32011102006-05-15 04:42:09 +0000774}
775
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000776LayoutUnit RenderTableSection::calcOuterBorderAfter() const
darin32011102006-05-15 04:42:09 +0000777{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000778 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000779 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000780 return 0;
781
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000782 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000783
akling@apple.com827be9c2013-10-29 02:58:43 +0000784 const BorderValue& sb = style().borderAfter();
darin32011102006-05-15 04:42:09 +0000785 if (sb.style() == BHIDDEN)
786 return -1;
787 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000788 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000789
akling@apple.com827be9c2013-10-29 02:58:43 +0000790 const BorderValue& rb = lastRow()->style().borderAfter();
darin32011102006-05-15 04:42:09 +0000791 if (rb.style() == BHIDDEN)
792 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000793 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
794 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000795
796 bool allHidden = true;
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000797 for (unsigned c = 0; c < totalCols; c++) {
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000798 const CellStruct& current = cellAt(m_grid.size() - 1, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000799 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000800 continue;
akling@apple.com827be9c2013-10-29 02:58:43 +0000801 const BorderValue& cb = current.primaryCell()->style().borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
darin32011102006-05-15 04:42:09 +0000802 // FIXME: Don't repeat for the same col group
803 RenderTableCol* colGroup = table()->colElement(c);
804 if (colGroup) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000805 const BorderValue& gb = colGroup->style().borderAfter();
darin32011102006-05-15 04:42:09 +0000806 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
807 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000808 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000809 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
810 borderWidth = gb.width();
811 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
812 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000813 } else {
814 if (cb.style() == BHIDDEN)
815 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000816 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000817 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
818 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000819 }
820 }
821 if (allHidden)
822 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000823 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), true);
darin32011102006-05-15 04:42:09 +0000824}
825
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000826LayoutUnit RenderTableSection::calcOuterBorderStart() const
darin32011102006-05-15 04:42:09 +0000827{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000828 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000829 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000830 return 0;
831
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000832 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000833
akling@apple.com827be9c2013-10-29 02:58:43 +0000834 const BorderValue& sb = style().borderStart();
darin32011102006-05-15 04:42:09 +0000835 if (sb.style() == BHIDDEN)
836 return -1;
837 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000838 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000839
mitz@apple.com8010bba2010-11-05 02:43:17 +0000840 if (RenderTableCol* colGroup = table()->colElement(0)) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000841 const BorderValue& gb = colGroup->style().borderStart();
darin32011102006-05-15 04:42:09 +0000842 if (gb.style() == BHIDDEN)
843 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000844 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
845 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000846 }
847
848 bool allHidden = true;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000849 for (unsigned r = 0; r < m_grid.size(); r++) {
mitz@apple.com8010bba2010-11-05 02:43:17 +0000850 const CellStruct& current = cellAt(r, 0);
jamesr@google.com36623a32010-07-23 20:22:29 +0000851 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000852 continue;
853 // FIXME: Don't repeat for the same cell
akling@apple.com827be9c2013-10-29 02:58:43 +0000854 const BorderValue& cb = current.primaryCell()->style().borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
855 const BorderValue& rb = current.primaryCell()->parent()->style().borderStart();
darin32011102006-05-15 04:42:09 +0000856 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
857 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000858 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000859 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
860 borderWidth = cb.width();
861 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
862 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000863 }
864 if (allHidden)
865 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000866 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), !table()->style().isLeftToRightDirection());
darin32011102006-05-15 04:42:09 +0000867}
868
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000869LayoutUnit RenderTableSection::calcOuterBorderEnd() const
darin32011102006-05-15 04:42:09 +0000870{
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +0000871 unsigned totalCols = table()->numEffCols();
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000872 if (!m_grid.size() || !totalCols)
darin32011102006-05-15 04:42:09 +0000873 return 0;
874
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000875 LayoutUnit borderWidth = 0;
darin32011102006-05-15 04:42:09 +0000876
akling@apple.com827be9c2013-10-29 02:58:43 +0000877 const BorderValue& sb = style().borderEnd();
darin32011102006-05-15 04:42:09 +0000878 if (sb.style() == BHIDDEN)
879 return -1;
880 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000881 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000882
mitz@apple.com8010bba2010-11-05 02:43:17 +0000883 if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
akling@apple.com827be9c2013-10-29 02:58:43 +0000884 const BorderValue& gb = colGroup->style().borderEnd();
darin32011102006-05-15 04:42:09 +0000885 if (gb.style() == BHIDDEN)
886 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000887 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
888 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000889 }
890
891 bool allHidden = true;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000892 for (unsigned r = 0; r < m_grid.size(); r++) {
mitz@apple.com8010bba2010-11-05 02:43:17 +0000893 const CellStruct& current = cellAt(r, totalCols - 1);
jamesr@google.com36623a32010-07-23 20:22:29 +0000894 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000895 continue;
896 // FIXME: Don't repeat for the same cell
akling@apple.com827be9c2013-10-29 02:58:43 +0000897 const BorderValue& cb = current.primaryCell()->style().borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
898 const BorderValue& rb = current.primaryCell()->parent()->style().borderEnd();
darin32011102006-05-15 04:42:09 +0000899 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
900 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000901 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000902 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
903 borderWidth = cb.width();
904 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
905 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000906 }
907 if (allHidden)
908 return -1;
zalan@apple.com6a1fae4a2016-03-06 03:10:21 +0000909 return CollapsedBorderValue::adjustedCollapsedBorderWidth(borderWidth, document().deviceScaleFactor(), table()->style().isLeftToRightDirection());
darin32011102006-05-15 04:42:09 +0000910}
911
912void RenderTableSection::recalcOuterBorder()
913{
mitz@apple.com8010bba2010-11-05 02:43:17 +0000914 m_outerBorderBefore = calcOuterBorderBefore();
915 m_outerBorderAfter = calcOuterBorderAfter();
916 m_outerBorderStart = calcOuterBorderStart();
917 m_outerBorderEnd = calcOuterBorderEnd();
darin32011102006-05-15 04:42:09 +0000918}
919
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000920Optional<int> RenderTableSection::firstLineBaseline() const
mitz@apple.com57a2f482008-08-23 07:16:41 +0000921{
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000922 if (!m_grid.size())
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000923 return Optional<int>();
mitz@apple.com57a2f482008-08-23 07:16:41 +0000924
eae@chromium.org82b94982012-10-22 18:38:29 +0000925 int firstLineBaseline = m_grid[0].baseline;
mitz@apple.com57a2f482008-08-23 07:16:41 +0000926 if (firstLineBaseline)
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000927 return firstLineBaseline + roundToInt(m_rowPos[0]);
mitz@apple.com57a2f482008-08-23 07:16:41 +0000928
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000929 Optional<int> result;
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +0000930 const Row& firstRow = m_grid[0].row;
931 for (size_t i = 0; i < firstRow.size(); ++i) {
932 const CellStruct& cs = firstRow.at(i);
933 const RenderTableCell* cell = cs.primaryCell();
robert@webkit.org3b67b1f2012-05-16 21:06:10 +0000934 // Only cells with content have a baseline
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000935 if (cell && cell->contentLogicalHeight()) {
zalan@apple.com5471a8d2015-10-27 16:38:10 +0000936 int candidate = roundToInt(cell->logicalTop() + cell->borderAndPaddingBefore() + cell->contentLogicalHeight());
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000937 result = std::max(result.valueOr(candidate), candidate);
938 }
mitz@apple.com57a2f482008-08-23 07:16:41 +0000939 }
940
mmaxfield@apple.com5f907742015-03-11 18:22:06 +0000941 return result;
mitz@apple.com57a2f482008-08-23 07:16:41 +0000942}
darin32011102006-05-15 04:42:09 +0000943
leviw@chromium.orgb3757502011-06-29 21:33:11 +0000944void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
eseidela043f3d2006-01-20 19:24:53 +0000945{
zalan@apple.com5097b112016-10-06 21:40:38 +0000946 ASSERT(!needsLayout());
inferno@chromium.org64a831b2012-08-03 19:47:08 +0000947 // avoid crashing on bugs that cause us to paint with dirty layout
eric@webkit.org5d226dc2012-08-02 21:06:06 +0000948 if (needsLayout())
949 return;
inferno@chromium.org64a831b2012-08-03 19:47:08 +0000950
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +0000951 unsigned totalRows = m_grid.size();
ddkilzer260f3d22007-01-05 05:56:31 +0000952 unsigned totalCols = table()->columns().size();
eseidela043f3d2006-01-20 19:24:53 +0000953
ddkilzer260f3d22007-01-05 05:56:31 +0000954 if (!totalRows || !totalCols)
ap0e708ba2006-05-20 08:47:37 +0000955 return;
956
leviw@chromium.orgb3757502011-06-29 21:33:11 +0000957 LayoutPoint adjustedPaintOffset = paintOffset + location();
eseidela043f3d2006-01-20 19:24:53 +0000958
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000959 PaintPhase phase = paintInfo.phase;
leviw@chromium.org61ca1372011-06-07 18:56:41 +0000960 bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
961 paintObject(paintInfo, adjustedPaintOffset);
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000962 if (pushedClip)
leviw@chromium.org61ca1372011-06-07 18:56:41 +0000963 popContentsClip(paintInfo, phase, adjustedPaintOffset);
robert@webkit.org87e8d0c2012-01-14 19:13:35 +0000964
akling@apple.com827be9c2013-10-29 02:58:43 +0000965 if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style().visibility() == VISIBLE)
wangxianzhu@chromium.org64f38292013-02-28 20:38:23 +0000966 paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000967}
968
jamesr@google.com36623a32010-07-23 20:22:29 +0000969static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
970{
jchaffraix@webkit.orga0177fd2012-05-01 03:13:06 +0000971 return elem1->rowIndex() < elem2->rowIndex();
jamesr@google.com36623a32010-07-23 20:22:29 +0000972}
973
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000974// This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
975// to sort both on rows and columns to properly repaint.
976static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
977{
jchaffraix@webkit.orga0177fd2012-05-01 03:13:06 +0000978 if (elem1->rowIndex() != elem2->rowIndex())
979 return elem1->rowIndex() < elem2->rowIndex();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +0000980
981 return elem1->col() < elem2->col();
982}
983
leviw@chromium.org890e9b02011-07-07 23:17:55 +0000984void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
jamesr@google.com36623a32010-07-23 20:22:29 +0000985{
ojan@chromium.org035c88ca2011-10-03 22:00:25 +0000986 LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
jamesr@google.com36623a32010-07-23 20:22:29 +0000987 PaintPhase paintPhase = paintInfo.phase;
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000988 RenderTableRow& row = downcast<RenderTableRow>(*cell->parent());
jamesr@google.com36623a32010-07-23 20:22:29 +0000989
990 if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
991 // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
992 // the column group, column, row group, row, and then the cell.
jchaffraix@webkit.org1ddd9fa2012-05-31 16:00:20 +0000993 RenderTableCol* column = table()->colElement(cell->col());
cdumez@apple.com8faf7722014-10-13 18:21:11 +0000994 RenderTableCol* columnGroup = column ? column->enclosingColumnGroup() : nullptr;
jamesr@google.com36623a32010-07-23 20:22:29 +0000995
996 // Column groups and columns first.
997 // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
998 // the stack, since we have already opened a transparency layer (potentially) for the table row group.
999 // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
1000 // cell.
jchaffraix@webkit.org1ddd9fa2012-05-31 16:00:20 +00001001 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup);
1002 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, column);
jamesr@google.com36623a32010-07-23 20:22:29 +00001003
1004 // Paint the row group next.
leviw@chromium.org719a45b2011-06-03 20:59:40 +00001005 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, this);
jamesr@google.com36623a32010-07-23 20:22:29 +00001006
1007 // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
1008 // painting the row background for the cell.
cdumez@apple.com8faf7722014-10-13 18:21:11 +00001009 if (!row.hasSelfPaintingLayer())
1010 cell->paintBackgroundsBehindCell(paintInfo, cellPoint, &row);
jamesr@google.com36623a32010-07-23 20:22:29 +00001011 }
cdumez@apple.com8faf7722014-10-13 18:21:11 +00001012 if ((!cell->hasSelfPaintingLayer() && !row.hasSelfPaintingLayer()))
leviw@chromium.org61ca1372011-06-07 18:56:41 +00001013 cell->paint(paintInfo, cellPoint);
jamesr@google.com36623a32010-07-23 20:22:29 +00001014}
1015
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001016LayoutRect RenderTableSection::logicalRectForWritingModeAndDirection(const LayoutRect& rect) const
1017{
1018 LayoutRect tableAlignedRect(rect);
1019
1020 flipForWritingMode(tableAlignedRect);
1021
akling@apple.com827be9c2013-10-29 02:58:43 +00001022 if (!style().isHorizontalWritingMode())
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001023 tableAlignedRect = tableAlignedRect.transposedRect();
1024
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001025 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
jchaffraix@webkit.org6d6c3052012-11-05 07:55:28 +00001026 // 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 +00001027 if (!style().isLeftToRightDirection())
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001028 tableAlignedRect.setX(columnPos[columnPos.size() - 1] - tableAlignedRect.maxX());
1029
1030 return tableAlignedRect;
1031}
1032
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001033CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const
1034{
1035 if (m_forceSlowPaintPathWithOverflowingCell)
1036 return fullTableRowSpan();
1037
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001038 CellSpan coveredRows = spannedRows(damageRect, IncludeAllIntersectingCells);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001039
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001040 // 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 +00001041 if (coveredRows.start >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= damageRect.y())
1042 --coveredRows.start;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001043
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001044 if (!coveredRows.end && m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY())
1045 ++coveredRows.end;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001046
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001047 return coveredRows;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001048}
1049
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001050CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const
1051{
1052 if (m_forceSlowPaintPathWithOverflowingCell)
1053 return fullTableColumnSpan();
1054
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001055 CellSpan coveredColumns = spannedColumns(damageRect, IncludeAllIntersectingCells);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001056
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001057 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001058 // 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 +00001059 if (coveredColumns.start >= columnPos.size() - 1 && columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= damageRect.x())
1060 --coveredColumns.start;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001061
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001062 if (!coveredColumns.end && columnPos[0] - table()->outerBorderStart() <= damageRect.maxX())
1063 ++coveredColumns.end;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001064
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001065 return coveredColumns;
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001066}
1067
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001068CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001069{
1070 // Find the first row that starts after rect top.
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001071 unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - m_rowPos.begin();
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001072 if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextRow && m_rowPos[nextRow - 1] == flippedRect.y())
1073 --nextRow;
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001074
1075 if (nextRow == m_rowPos.size())
1076 return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); // After all rows.
1077
1078 unsigned startRow = nextRow > 0 ? nextRow - 1 : 0;
1079
1080 // Find the first row that starts after rect bottom.
1081 unsigned endRow;
1082 if (m_rowPos[nextRow] >= flippedRect.maxY())
1083 endRow = nextRow;
1084 else {
andersca@apple.com16123952014-12-06 21:04:35 +00001085 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 +00001086 if (endRow == m_rowPos.size())
1087 endRow = m_rowPos.size() - 1;
1088 }
1089
1090 return CellSpan(startRow, endRow);
1091}
1092
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001093CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001094{
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001095 const Vector<LayoutUnit>& columnPos = table()->columnPositions();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001096
commit-queue@webkit.org01f61412012-08-15 18:01:05 +00001097 // Find the first column that starts after rect left.
1098 // lower_bound doesn't handle the edge between two cells properly as it would wrongly return the
1099 // cell on the logical top/left.
1100 // upper_bound on the other hand properly returns the cell on the logical bottom/right, which also
1101 // matches the behavior of other browsers.
1102 unsigned nextColumn = std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - columnPos.begin();
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001103 if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextColumn && columnPos[nextColumn - 1] == flippedRect.x())
1104 --nextColumn;
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001105
1106 if (nextColumn == columnPos.size())
1107 return CellSpan(columnPos.size() - 1, columnPos.size() - 1); // After all columns.
1108
1109 unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0;
1110
commit-queue@webkit.org01f61412012-08-15 18:01:05 +00001111 // Find the first column that starts after rect right.
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001112 unsigned endColumn;
1113 if (columnPos[nextColumn] >= flippedRect.maxX())
1114 endColumn = nextColumn;
1115 else {
andersca@apple.com16123952014-12-06 21:04:35 +00001116 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 +00001117 if (endColumn == columnPos.size())
1118 endColumn = columnPos.size() - 1;
1119 }
1120
1121 return CellSpan(startColumn, endColumn);
1122}
1123
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001124void RenderTableSection::paintRowGroupBorder(const PaintInfo& paintInfo, bool antialias, LayoutRect rect, BoxSide side, CSSPropertyID borderColor, EBorderStyle borderStyle, EBorderStyle tableBorderStyle)
1125{
1126 if (tableBorderStyle == BHIDDEN)
1127 return;
1128 rect.intersect(paintInfo.rect);
1129 if (rect.isEmpty())
1130 return;
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001131 drawLineForBoxSide(paintInfo.context(), rect, side, style().visitedDependentColor(borderColor), borderStyle, 0, 0, antialias);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001132}
1133
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001134LayoutUnit RenderTableSection::offsetLeftForRowGroupBorder(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001135{
akling@apple.com827be9c2013-10-29 02:58:43 +00001136 if (style().isHorizontalWritingMode()) {
1137 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001138 return cell ? cell->x() + cell->width() : LayoutUnit::fromPixel(0);
akling@apple.com827be9c2013-10-29 02:58:43 +00001139 return -outerBorderLeft(&style());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001140 }
1141 bool isLastRow = row + 1 == m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001142 return rowGroupRect.width() - m_rowPos[row + 1] + (isLastRow ? -outerBorderLeft(&style()) : LayoutUnit::fromPixel(0));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001143}
1144
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001145LayoutUnit RenderTableSection::offsetTopForRowGroupBorder(RenderTableCell* cell, BoxSide borderSide, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001146{
1147 bool isLastRow = row + 1 == m_grid.size();
akling@apple.com827be9c2013-10-29 02:58:43 +00001148 if (style().isHorizontalWritingMode())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001149 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 +00001150 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001151 return (cell ? cell->y() + cell->height() : LayoutUnit::fromPixel(0)) + (borderSide == BSLeft ? outerBorderTop(&style()) : LayoutUnit::fromPixel(0));
1152 return borderSide == BSRight ? -outerBorderTop(&style()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001153}
1154
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001155LayoutUnit RenderTableSection::verticalRowGroupBorderHeight(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001156{
1157 bool isLastRow = row + 1 == m_grid.size();
akling@apple.com827be9c2013-10-29 02:58:43 +00001158 if (style().isHorizontalWritingMode())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001159 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 +00001160 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001161 return rowGroupRect.height() - (cell ? cell->y() + cell->height() : LayoutUnit::fromPixel(0)) + outerBorderBottom(&style());
1162 return cell ? rowGroupRect.height() - (cell->y() - cell->height()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001163}
1164
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001165LayoutUnit RenderTableSection::horizontalRowGroupBorderWidth(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row, unsigned column)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001166{
akling@apple.com827be9c2013-10-29 02:58:43 +00001167 if (style().isHorizontalWritingMode()) {
1168 if (style().isLeftToRightDirection())
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001169 return rowGroupRect.width() - (cell ? cell->x() + cell->width() : LayoutUnit::fromPixel(0)) + (!column ? outerBorderLeft(&style()) : column == table()->numEffCols() ? outerBorderRight(&style()) : LayoutUnit::fromPixel(0));
1170 return cell ? rowGroupRect.width() - (cell->x() - cell->width()) : LayoutUnit::fromPixel(0);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001171 }
1172 bool isLastRow = row + 1 == m_grid.size();
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001173 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 +00001174}
1175
1176void RenderTableSection::paintRowGroupBorderIfRequired(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, unsigned row, unsigned column, BoxSide borderSide, RenderTableCell* cell)
1177{
1178 if (table()->currentBorderValue()->precedence() > BROWGROUP)
1179 return;
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001180 if (paintInfo.context().paintingDisabled())
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001181 return;
1182
akling@apple.com827be9c2013-10-29 02:58:43 +00001183 const RenderStyle& style = this->style();
mmaxfield@apple.coma93d7ef2015-08-29 06:15:28 +00001184 bool antialias = shouldAntialiasLines(paintInfo.context());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001185 LayoutRect rowGroupRect = LayoutRect(paintOffset, size());
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001186 rowGroupRect.moveBy(-LayoutPoint(outerBorderLeft(&style), (borderSide == BSRight) ? LayoutUnit::fromPixel(0) : outerBorderTop(&style)));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001187
1188 switch (borderSide) {
1189 case BSTop:
1190 paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y(),
akling@apple.com827be9c2013-10-29 02:58:43 +00001191 horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderTop().width()), BSTop, CSSPropertyBorderTopColor, style.borderTopStyle(), table()->style().borderTopStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001192 break;
1193 case BSBottom:
1194 paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y() + rowGroupRect.height(),
akling@apple.com827be9c2013-10-29 02:58:43 +00001195 horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderBottom().width()), BSBottom, CSSPropertyBorderBottomColor, style.borderBottomStyle(), table()->style().borderBottomStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001196 break;
1197 case BSLeft:
akling@apple.com827be9c2013-10-29 02:58:43 +00001198 paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderLeft().width(),
1199 verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSLeft, CSSPropertyBorderLeftColor, style.borderLeftStyle(), table()->style().borderLeftStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001200 break;
1201 case BSRight:
akling@apple.com827be9c2013-10-29 02:58:43 +00001202 paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x() + rowGroupRect.width(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderRight().width(),
1203 verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSRight, CSSPropertyBorderRightColor, style.borderRightStyle(), table()->style().borderRightStyle());
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001204 break;
1205 default:
1206 break;
1207 }
1208
1209}
1210
antti@apple.com5c4302b2016-04-26 18:20:09 +00001211static BoxSide physicalBorderForDirection(const RenderStyle* styleForCellFlow, CollapsedBorderSide side)
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001212{
1213
1214 switch (side) {
1215 case CBSStart:
1216 if (styleForCellFlow->isHorizontalWritingMode())
1217 return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1218 return styleForCellFlow->isLeftToRightDirection() ? BSTop : BSBottom;
1219 case CBSEnd:
1220 if (styleForCellFlow->isHorizontalWritingMode())
1221 return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1222 return styleForCellFlow->isLeftToRightDirection() ? BSBottom : BSTop;
1223 case CBSBefore:
1224 if (styleForCellFlow->isHorizontalWritingMode())
1225 return BSTop;
1226 return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1227 case CBSAfter:
1228 if (styleForCellFlow->isHorizontalWritingMode())
1229 return BSBottom;
1230 return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1231 default:
1232 ASSERT_NOT_REACHED();
1233 return BSLeft;
1234 }
1235}
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001236
leviw@chromium.orgc4918082011-06-29 01:06:00 +00001237void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001238{
leviw@chromium.orgc4918082011-06-29 01:06:00 +00001239 LayoutRect localRepaintRect = paintInfo.rect;
leviw@chromium.org43d0c4d2011-06-04 02:25:54 +00001240 localRepaintRect.moveBy(-paintOffset);
eseidela043f3d2006-01-20 19:24:53 +00001241
commit-queue@webkit.org9fa1a352012-06-19 16:07:00 +00001242 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect);
1243
1244 CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect);
1245 CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001246
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001247 if (dirtiedColumns.start < dirtiedColumns.end) {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001248 if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001249 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1250 // Collapsed borders are painted from the bottom right to the top left so that precedence
robert@webkit.orgc75e7672013-06-11 18:11:31 +00001251 // due to cell position is respected. We need to paint one row beyond the topmost dirtied
1252 // row to calculate its collapsed border value.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001253 unsigned startRow = dirtiedRows.start ? dirtiedRows.start - 1 : 0;
1254 for (unsigned r = dirtiedRows.end; r > startRow; r--) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001255 unsigned row = r - 1;
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001256 bool shouldPaintRowGroupBorder = false;
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001257 for (unsigned c = dirtiedColumns.end; c > dirtiedColumns.start; c--) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001258 unsigned col = c - 1;
1259 CellStruct& current = cellAt(row, col);
1260 RenderTableCell* cell = current.primaryCell();
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001261 if (!cell) {
1262 if (!c)
akling@apple.com827be9c2013-10-29 02:58:43 +00001263 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSStart));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001264 else if (c == table()->numEffCols())
akling@apple.com827be9c2013-10-29 02:58:43 +00001265 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSEnd));
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001266 shouldPaintRowGroupBorder = true;
robert@webkit.org2d408272011-12-19 19:49:27 +00001267 continue;
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001268 }
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001269 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 +00001270 continue;
1271
1272 // If we had a run of null cells paint their corresponding section of the row group's border if necessary. Note that
1273 // this will only happen once within a row as the null cells will always be clustered together on one end of the row.
1274 if (shouldPaintRowGroupBorder) {
1275 if (r == m_grid.size())
akling@apple.com827be9c2013-10-29 02:58:43 +00001276 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSAfter), cell);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001277 else if (!row && !table()->sectionAbove(this))
akling@apple.com827be9c2013-10-29 02:58:43 +00001278 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSBefore), cell);
robert@webkit.org2d9d64b2013-10-17 17:44:20 +00001279 shouldPaintRowGroupBorder = false;
1280 }
1281
robert@webkit.org2d408272011-12-19 19:49:27 +00001282 LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
1283 cell->paintCollapsedBorders(paintInfo, cellPoint);
1284 }
1285 }
1286 } else {
1287 // Draw the dirty cells in the order that they appear.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001288 for (unsigned r = dirtiedRows.start; r < dirtiedRows.end; r++) {
robert@webkit.org87e8d0c2012-01-14 19:13:35 +00001289 RenderTableRow* row = m_grid[r].rowRenderer;
1290 if (row && !row->hasSelfPaintingLayer())
1291 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001292 for (unsigned c = dirtiedColumns.start; c < dirtiedColumns.end; c++) {
robert@webkit.org2d408272011-12-19 19:49:27 +00001293 CellStruct& current = cellAt(r, c);
1294 RenderTableCell* cell = current.primaryCell();
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001295 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 +00001296 continue;
1297 paintCell(cell, paintInfo, paintOffset);
1298 }
hyatte031dd02006-03-18 01:01:06 +00001299 }
ap50b58352006-01-22 20:32:36 +00001300 }
jamesr@google.com36623a32010-07-23 20:22:29 +00001301 } else {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001302 // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001303#ifndef NDEBUG
1304 unsigned totalRows = m_grid.size();
1305 unsigned totalCols = table()->columns().size();
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001306 ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
jchaffraix@webkit.org7e3f5d42012-02-28 01:05:10 +00001307#endif
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001308
1309 // 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 +00001310 Vector<RenderTableCell*> cells;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001311 copyToVector(m_overflowingCells, cells);
1312
jamesr@google.com36623a32010-07-23 20:22:29 +00001313 HashSet<RenderTableCell*> spanningCells;
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001314
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001315 for (unsigned r = dirtiedRows.start; r < dirtiedRows.end; r++) {
robert@webkit.org87e8d0c2012-01-14 19:13:35 +00001316 RenderTableRow* row = m_grid[r].rowRenderer;
1317 if (row && !row->hasSelfPaintingLayer())
1318 row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001319 for (unsigned c = dirtiedColumns.start; c < dirtiedColumns.end; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +00001320 CellStruct& current = cellAt(r, c);
jamesr@google.comb4266232010-07-28 20:07:19 +00001321 if (!current.hasCells())
jamesr@google.com36623a32010-07-23 20:22:29 +00001322 continue;
1323 for (unsigned i = 0; i < current.cells.size(); ++i) {
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001324 if (m_overflowingCells.contains(current.cells[i]))
1325 continue;
1326
jamesr@google.com36623a32010-07-23 20:22:29 +00001327 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
rafael.lobo@openbossa.org61c47ed2013-05-31 00:53:31 +00001328 if (!spanningCells.add(current.cells[i]).isNewEntry)
jamesr@google.com36623a32010-07-23 20:22:29 +00001329 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +00001330 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001331
jamesr@google.com36623a32010-07-23 20:22:29 +00001332 cells.append(current.cells[i]);
1333 }
1334 }
1335 }
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001336
jamesr@google.com36623a32010-07-23 20:22:29 +00001337 // Sort the dirty cells by paint order.
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001338 if (!m_overflowingCells.size())
1339 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
1340 else
1341 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
1342
robert@webkit.org2d408272011-12-19 19:49:27 +00001343 if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1344 for (unsigned i = cells.size(); i > 0; --i) {
1345 LayoutPoint cellPoint = flipForWritingModeForChild(cells[i - 1], paintOffset);
1346 cells[i - 1]->paintCollapsedBorders(paintInfo, cellPoint);
1347 }
1348 } else {
1349 for (unsigned i = 0; i < cells.size(); ++i)
1350 paintCell(cells[i], paintInfo, paintOffset);
1351 }
ap50b58352006-01-22 20:32:36 +00001352 }
eseidela043f3d2006-01-20 19:24:53 +00001353 }
1354}
1355
darin@apple.com98a7ac62009-01-05 17:26:53 +00001356void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
bdashb07ae8d2007-02-08 04:56:20 +00001357{
bdashb07ae8d2007-02-08 04:56:20 +00001358 // FIXME: Examine cells and repaint only the rect the image paints in.
1359 repaint();
1360}
1361
eseidela043f3d2006-01-20 19:24:53 +00001362void RenderTableSection::recalcCells()
1363{
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001364 ASSERT(m_needsCellRecalc);
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001365 // We reset the flag here to ensure that addCell() works. This is safe to do because we clear the grid
1366 // and update its dimensions to be consistent with the table's column representation before we rebuild
1367 // the grid using addCell().
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001368 m_needsCellRecalc = false;
1369
ddkilzer260f3d22007-01-05 05:56:31 +00001370 m_cCol = 0;
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001371 m_cRow = 0;
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001372 m_grid.clear();
eseidela043f3d2006-01-20 19:24:53 +00001373
antti@apple.com7f9196b2013-09-24 20:47:01 +00001374 for (RenderTableRow* row = firstRow(); row; row = row->nextRow()) {
1375 unsigned insertionRow = m_cRow;
1376 m_cRow++;
1377 m_cCol = 0;
1378 ensureRows(m_cRow);
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001379
antti@apple.com7f9196b2013-09-24 20:47:01 +00001380 m_grid[insertionRow].rowRenderer = row;
1381 row->setRowIndex(insertionRow);
1382 setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
eseidel05ef0432006-05-25 22:11:36 +00001383
antti@apple.com7f9196b2013-09-24 20:47:01 +00001384 for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
1385 addCell(cell, row);
eseidela043f3d2006-01-20 19:24:53 +00001386 }
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001387
jchaffraix@webkit.orge98e3e52011-11-11 01:41:26 +00001388 m_grid.shrinkToFit();
antti@apple.comca2a8ff2013-10-04 04:04:35 +00001389 setNeedsLayout();
eseidela043f3d2006-01-20 19:24:53 +00001390}
1391
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +00001392// 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 +00001393void RenderTableSection::rowLogicalHeightChanged(unsigned rowIndex)
1394{
jchaffraix@webkit.orgdd34df42012-01-24 04:15:06 +00001395 if (needsCellRecalc())
1396 return;
1397
jchaffraix@webkit.org19bbb722011-11-03 17:20:01 +00001398 setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[rowIndex]);
jchaffraix@webkit.org74857b42011-12-20 14:08:52 +00001399
antti@apple.com7f9196b2013-09-24 20:47:01 +00001400 for (RenderTableCell* cell = m_grid[rowIndex].rowRenderer->firstCell(); cell; cell = cell->nextCell())
1401 updateLogicalHeightForCell(m_grid[rowIndex], cell);
jchaffraix@webkit.org19bbb722011-11-03 17:20:01 +00001402}
1403
jamesr@google.com5ddfb042011-01-20 21:34:34 +00001404void RenderTableSection::setNeedsCellRecalc()
1405{
1406 m_needsCellRecalc = true;
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001407
1408 // Clear the grid now to ensure that we don't hold onto any stale pointers (e.g. a cell renderer that is being removed).
1409 m_grid.clear();
1410
jamesr@google.com5ddfb042011-01-20 21:34:34 +00001411 if (RenderTable* t = table())
1412 t->setNeedsSectionRecalc();
1413}
1414
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001415unsigned RenderTableSection::numColumns() const
ap50b58352006-01-22 20:32:36 +00001416{
dbates@webkit.orgf04ec0f2014-03-18 20:00:47 +00001417 ASSERT(!m_needsCellRecalc);
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001418 unsigned result = 0;
ap50b58352006-01-22 20:32:36 +00001419
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001420 for (unsigned r = 0; r < m_grid.size(); ++r) {
jchaffraix@webkit.org369c5d32011-10-28 01:28:58 +00001421 for (unsigned c = result; c < table()->numEffCols(); ++c) {
ap50b58352006-01-22 20:32:36 +00001422 const CellStruct& cell = cellAt(r, c);
jamesr@google.com36623a32010-07-23 20:22:29 +00001423 if (cell.hasCells() || cell.inColSpan)
ap50b58352006-01-22 20:32:36 +00001424 result = c;
1425 }
1426 }
1427
1428 return result + 1;
eseidela043f3d2006-01-20 19:24:53 +00001429}
1430
zalan@apple.com1731e362016-07-24 01:39:13 +00001431const BorderValue& RenderTableSection::borderAdjoiningStartCell(const RenderTableCell& cell) const
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001432{
zalan@apple.com1731e362016-07-24 01:39:13 +00001433 ASSERT(cell.isFirstOrLastCellInRow());
zalan@apple.comb2e52722016-07-26 02:15:56 +00001434 return isDirectionSame(this, &cell) ? style().borderStart() : style().borderEnd();
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001435}
1436
zalan@apple.com1731e362016-07-24 01:39:13 +00001437const BorderValue& RenderTableSection::borderAdjoiningEndCell(const RenderTableCell& cell) const
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001438{
zalan@apple.com1731e362016-07-24 01:39:13 +00001439 ASSERT(cell.isFirstOrLastCellInRow());
zalan@apple.comb2e52722016-07-26 02:15:56 +00001440 return isDirectionSame(this, &cell) ? style().borderEnd() : style().borderStart();
jchaffraix@webkit.orgec614042012-09-20 00:58:58 +00001441}
1442
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001443const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableStart() const
1444{
zalan@apple.comb2e52722016-07-26 02:15:56 +00001445 unsigned adjoiningStartCellColumnIndex = isDirectionSame(this, table()) ? 0 : table()->lastColumnIndex();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001446 return cellAt(0, adjoiningStartCellColumnIndex).primaryCell();
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001447}
1448
1449const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableEnd() const
1450{
zalan@apple.comb2e52722016-07-26 02:15:56 +00001451 unsigned adjoiningEndCellColumnIndex = isDirectionSame(this, table()) ? table()->lastColumnIndex() : 0;
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001452 return cellAt(0, adjoiningEndCellColumnIndex).primaryCell();
jchaffraix@webkit.orgceaacec2012-06-01 20:15:01 +00001453}
1454
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001455void RenderTableSection::appendColumn(unsigned pos)
ddkilzer260f3d22007-01-05 05:56:31 +00001456{
jchaffraix@webkit.orgb86b64e2011-11-14 21:21:43 +00001457 ASSERT(!m_needsCellRecalc);
1458
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001459 for (unsigned row = 0; row < m_grid.size(); ++row)
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001460 m_grid[row].row.resize(pos + 1);
ddkilzer260f3d22007-01-05 05:56:31 +00001461}
1462
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001463void RenderTableSection::splitColumn(unsigned pos, unsigned first)
ddkilzer260f3d22007-01-05 05:56:31 +00001464{
inferno@chromium.orgb1ffad72011-10-10 18:58:12 +00001465 ASSERT(!m_needsCellRecalc);
1466
ddkilzer260f3d22007-01-05 05:56:31 +00001467 if (m_cCol > pos)
1468 m_cCol++;
jchaffraix@webkit.org68d3b572011-10-27 19:12:39 +00001469 for (unsigned row = 0; row < m_grid.size(); ++row) {
jchaffraix@webkit.org9fb80752011-10-28 18:04:14 +00001470 Row& r = m_grid[row].row;
jamesr@google.com36623a32010-07-23 20:22:29 +00001471 r.insert(pos + 1, CellStruct());
1472 if (r[pos].hasCells()) {
andersca@apple.com92012992013-05-05 19:03:49 +00001473 r[pos + 1].cells.appendVector(r[pos].cells);
jamesr@google.com36623a32010-07-23 20:22:29 +00001474 RenderTableCell* cell = r[pos].primaryCell();
1475 ASSERT(cell);
commit-queue@webkit.org1ee5b342012-05-08 05:14:07 +00001476 ASSERT(cell->colSpan() >= (r[pos].inColSpan ? 1u : 0));
jchaffraix@webkit.orgfb2a8602011-11-16 02:03:54 +00001477 unsigned colleft = cell->colSpan() - r[pos].inColSpan;
jamesr@google.com36623a32010-07-23 20:22:29 +00001478 if (first > colleft)
1479 r[pos + 1].inColSpan = 0;
1480 else
1481 r[pos + 1].inColSpan = first + r[pos].inColSpan;
1482 } else {
1483 r[pos + 1].inColSpan = 0;
1484 }
ddkilzer260f3d22007-01-05 05:56:31 +00001485 }
1486}
1487
hyattd866e592006-03-17 09:50:35 +00001488// Hit Testing
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001489bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
hyattd866e592006-03-17 09:50:35 +00001490{
jamesr@google.comf88b2582010-08-17 20:57:15 +00001491 // If we have no children then we have nothing to do.
antti@apple.com7f9196b2013-09-24 20:47:01 +00001492 if (!firstRow())
jamesr@google.comf88b2582010-08-17 20:57:15 +00001493 return false;
1494
hyattd866e592006-03-17 09:50:35 +00001495 // Table sections cannot ever be hit tested. Effectively they do not exist.
1496 // Just forward to our children always.
eae@chromium.orge14cd1a2011-07-06 23:38:32 +00001497 LayoutPoint adjustedLocation = accumulatedOffset + location();
hyattd866e592006-03-17 09:50:35 +00001498
abucur@adobe.com7f9668a2014-05-16 13:22:00 +00001499 if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment())))
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001500 return false;
1501
jchaffraix@webkit.orgf4ce0502011-08-18 20:20:57 +00001502 if (hasOverflowingCell()) {
antti@apple.com7f9196b2013-09-24 20:47:01 +00001503 for (RenderTableRow* row = lastRow(); row; row = row->previousRow()) {
jamesr@google.comf88b2582010-08-17 20:57:15 +00001504 // FIXME: We have to skip over inline flows, since they can show up inside table rows
1505 // at the moment (a demoted inline <form> for example). If we ever implement a
1506 // table-specific hit-test method (which we should do for performance reasons anyway),
1507 // then we can remove this check.
antti@apple.comd04c0812013-09-25 17:45:59 +00001508 if (!row->hasSelfPaintingLayer()) {
antti@apple.com7f9196b2013-09-24 20:47:01 +00001509 LayoutPoint childPoint = flipForWritingModeForChild(row, adjustedLocation);
1510 if (row->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001511 updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
mitz@apple.com39fb3ae2010-11-09 20:46:15 +00001512 return true;
1513 }
jamesr@google.comf88b2582010-08-17 20:57:15 +00001514 }
1515 }
1516 return false;
1517 }
1518
inferno@chromium.org9c8b2302012-02-21 19:10:05 +00001519 recalcCellsIfNeeded();
1520
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001521 LayoutRect hitTestRect = locationInContainer.boundingBox();
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001522 hitTestRect.moveBy(-adjustedLocation);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001523
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001524 LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect);
mmaxfield@apple.comf28245e2014-05-20 00:45:52 +00001525 CellSpan rowSpan = spannedRows(tableAlignedRect, DoNotIncludeAllIntersectingCells);
1526 CellSpan columnSpan = spannedColumns(tableAlignedRect, DoNotIncludeAllIntersectingCells);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001527
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001528 // Now iterate over the spanned rows and columns.
zalan@apple.comec6c110a2015-02-17 22:41:25 +00001529 for (unsigned hitRow = rowSpan.start; hitRow < rowSpan.end; ++hitRow) {
1530 for (unsigned hitColumn = columnSpan.start; hitColumn < columnSpan.end; ++hitColumn) {
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001531 CellStruct& current = cellAt(hitRow, hitColumn);
jamesr@google.comf88b2582010-08-17 20:57:15 +00001532
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001533 // If the cell is empty, there's nothing to do
1534 if (!current.hasCells())
1535 continue;
jamesr@google.comf88b2582010-08-17 20:57:15 +00001536
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001537 for (unsigned i = current.cells.size() ; i; ) {
1538 --i;
1539 RenderTableCell* cell = current.cells[i];
1540 LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
allan.jensen@nokia.com9a9045b2012-08-28 09:41:54 +00001541 if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
1542 updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001543 return true;
1544 }
1545 }
1546 if (!result.isRectBasedTest())
1547 break;
hyattd866e592006-03-17 09:50:35 +00001548 }
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001549 if (!result.isRectBasedTest())
1550 break;
hyattd866e592006-03-17 09:50:35 +00001551 }
jamesr@google.comf88b2582010-08-17 20:57:15 +00001552
commit-queue@webkit.orgbe3795c2012-06-11 09:38:48 +00001553 return false;
hyattd866e592006-03-17 09:50:35 +00001554}
1555
zalan@apple.com42146622015-04-01 15:56:34 +00001556void RenderTableSection::clearCachedCollapsedBorders()
1557{
1558 if (!table()->collapseBorders())
1559 return;
1560 m_cellsCollapsedBorders.clear();
1561}
1562
1563void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell& cell)
robert@webkit.org76a76102012-01-15 13:48:45 +00001564{
1565 if (!table()->collapseBorders())
1566 return;
1567
1568 for (int side = CBSBefore; side <= CBSEnd; ++side)
zalan@apple.com42146622015-04-01 15:56:34 +00001569 m_cellsCollapsedBorders.remove(std::make_pair(&cell, side));
robert@webkit.org76a76102012-01-15 13:48:45 +00001570}
1571
zalan@apple.com42146622015-04-01 15:56:34 +00001572void RenderTableSection::setCachedCollapsedBorder(const RenderTableCell& cell, CollapsedBorderSide side, CollapsedBorderValue border)
robert@webkit.org76a76102012-01-15 13:48:45 +00001573{
1574 ASSERT(table()->collapseBorders());
zalan@apple.com42146622015-04-01 15:56:34 +00001575 ASSERT(border.width());
1576 m_cellsCollapsedBorders.set(std::make_pair(&cell, side), border);
robert@webkit.org76a76102012-01-15 13:48:45 +00001577}
1578
zalan@apple.com42146622015-04-01 15:56:34 +00001579CollapsedBorderValue RenderTableSection::cachedCollapsedBorder(const RenderTableCell& cell, CollapsedBorderSide side)
robert@webkit.org76a76102012-01-15 13:48:45 +00001580{
zalan@apple.com42146622015-04-01 15:56:34 +00001581 ASSERT(table()->collapseBorders() && table()->collapsedBordersAreValid());
1582 auto it = m_cellsCollapsedBorders.find(std::make_pair(&cell, side));
1583 // Only non-empty collapsed borders are in the hashmap.
1584 if (it == m_cellsCollapsedBorders.end())
1585 return CollapsedBorderValue(BorderValue(), Color(), BCELL);
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001586 return it->value;
robert@webkit.org76a76102012-01-15 13:48:45 +00001587}
1588
zalan@apple.comcda46e42016-07-26 02:40:04 +00001589std::unique_ptr<RenderTableSection> RenderTableSection::createTableSectionWithStyle(Document& document, const RenderStyle& style)
inferno@chromium.org2164c612012-04-04 22:41:56 +00001590{
zalan@apple.comcda46e42016-07-26 02:40:04 +00001591 auto section = std::make_unique<RenderTableSection>(document, RenderStyle::createAnonymousStyleWithDisplay(style, TABLE_ROW_GROUP));
akling@apple.com8f40c5b2013-10-27 22:54:07 +00001592 section->initializeStyle();
1593 return section;
inferno@chromium.org2164c612012-04-04 22:41:56 +00001594}
1595
zalan@apple.comcda46e42016-07-26 02:40:04 +00001596std::unique_ptr<RenderTableSection> RenderTableSection::createAnonymousWithParentRenderer(const RenderTable& parent)
1597{
1598 return RenderTableSection::createTableSectionWithStyle(parent.document(), parent.style());
1599}
1600
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001601void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsigned effectiveColumn) const
1602{
eae@chromium.org1146f212012-07-18 22:06:34 +00001603 LayoutPoint oldCellLocation = cell->location();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001604
1605 LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]);
zalan@apple.com5471a8d2015-10-27 16:38:10 +00001606 LayoutUnit horizontalBorderSpacing = table()->hBorderSpacing();
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001607
jchaffraix@webkit.org6d6c3052012-11-05 07:55:28 +00001608 // 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 +00001609 if (!style().isLeftToRightDirection())
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001610 cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + horizontalBorderSpacing);
1611 else
1612 cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
1613
1614 cell->setLogicalLocation(cellLocation);
akling@apple.com691cf5c2013-08-24 16:33:15 +00001615 view().addLayoutDelta(oldCellLocation - cell->location());
jchaffraix@webkit.org4b5292a2012-06-06 16:07:16 +00001616}
1617
ddkilzer260f3d22007-01-05 05:56:31 +00001618} // namespace WebCore