blob: ed4f527c8879dcfdc9563b267a78ad5ae0d84491 [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)
darin@apple.com83833152008-01-14 17:51:10 +00007 * Copyright (C) 2003, 2004, 2005, 2006, 2008 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"
bdashb07ae8d2007-02-08 04:56:20 +000028#include "CachedImage.h"
darinb9481ed2006-03-20 02:57:59 +000029#include "Document.h"
tonikitoo@webkit.org81c027d2010-07-29 13:19:43 +000030#include "HitTestResult.h"
darin98fa8b82006-03-20 08:03:57 +000031#include "HTMLNames.h"
darin91298e52006-06-12 01:10:17 +000032#include "RenderTableCell.h"
33#include "RenderTableCol.h"
34#include "RenderTableRow.h"
weinigfef13632007-04-29 20:09:08 +000035#include "RenderView.h"
darin91298e52006-06-12 01:10:17 +000036#include <limits>
jamesr@google.com36623a32010-07-23 20:22:29 +000037#include <wtf/HashSet.h>
ddkilzer260f3d22007-01-05 05:56:31 +000038#include <wtf/Vector.h>
eseidela043f3d2006-01-20 19:24:53 +000039
darin7bd70952006-04-13 07:07:34 +000040using namespace std;
41
eseidela043f3d2006-01-20 19:24:53 +000042namespace WebCore {
43
44using namespace HTMLNames;
45
dbates@webkit.orge1131832009-11-19 00:05:57 +000046static inline void setRowHeightToRowStyleHeightIfNotRelative(RenderTableSection::RowStruct* row)
47{
48 ASSERT(row && row->rowRenderer);
49 row->height = row->rowRenderer->style()->height();
50 if (row->height.isRelative())
51 row->height = Length();
52}
53
darinb9481ed2006-03-20 02:57:59 +000054RenderTableSection::RenderTableSection(Node* node)
hyatt@apple.comf073d9b2009-02-05 00:53:38 +000055 : RenderBox(node)
ddkilzer260f3d22007-01-05 05:56:31 +000056 , m_gridRows(0)
57 , m_cCol(0)
58 , m_cRow(-1)
ddkilzer260f3d22007-01-05 05:56:31 +000059 , m_outerBorderLeft(0)
60 , m_outerBorderRight(0)
61 , m_outerBorderTop(0)
62 , m_outerBorderBottom(0)
simon.fraser@apple.com85362502009-05-08 01:23:32 +000063 , m_needsCellRecalc(false)
adeleddfe27f2007-01-05 23:03:50 +000064 , m_hasOverflowingCell(false)
jamesr@google.com36623a32010-07-23 20:22:29 +000065 , m_hasMultipleCellLevels(false)
eseidela043f3d2006-01-20 19:24:53 +000066{
67 // init RenderObject attributes
jamesr@google.com36623a32010-07-23 20:22:29 +000068 setInline(false); // our object is not Inline
eseidela043f3d2006-01-20 19:24:53 +000069}
70
71RenderTableSection::~RenderTableSection()
72{
73 clearGrid();
74}
75
76void RenderTableSection::destroy()
77{
antti078e87f2007-08-16 16:13:28 +000078 RenderTable* recalcTable = table();
79
hyatt@apple.comf073d9b2009-02-05 00:53:38 +000080 RenderBox::destroy();
antti078e87f2007-08-16 16:13:28 +000081
eseidela043f3d2006-01-20 19:24:53 +000082 // recalc cell info because RenderTable has unguarded pointers
83 // stored that point to this RenderTableSection.
antti078e87f2007-08-16 16:13:28 +000084 if (recalcTable)
85 recalcTable->setNeedsSectionRecalc();
eseidela043f3d2006-01-20 19:24:53 +000086}
87
darin316ed062006-01-23 05:29:14 +000088void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
eseidela043f3d2006-01-20 19:24:53 +000089{
hyatt58028f52007-05-01 04:57:01 +000090 // Make sure we don't append things after :after-generated content if we have it.
91 if (!beforeChild && isAfterContent(lastChild()))
92 beforeChild = lastChild();
93
eseidela043f3d2006-01-20 19:24:53 +000094 if (!child->isTableRow()) {
darin316ed062006-01-23 05:29:14 +000095 RenderObject* last = beforeChild;
96 if (!last)
97 last = lastChild();
98 if (last && last->isAnonymous()) {
99 last->addChild(child);
100 return;
101 }
102
darin10ab1352006-01-29 01:29:33 +0000103 // If beforeChild is inside an anonymous cell/row, insert into the cell or into
104 // the anonymous row containing it, if there is one.
darin316ed062006-01-23 05:29:14 +0000105 RenderObject* lastBox = last;
106 while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
107 lastBox = lastBox->parent();
108 if (lastBox && lastBox->isAnonymous()) {
109 lastBox->addChild(child, beforeChild);
110 return;
111 }
112
eric@webkit.org32963e32009-06-05 03:25:12 +0000113 RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table row */);
hyatt@apple.comdec0cbf22008-10-17 00:25:33 +0000114 RefPtr<RenderStyle> newStyle = RenderStyle::create();
darin316ed062006-01-23 05:29:14 +0000115 newStyle->inheritFrom(style());
116 newStyle->setDisplay(TABLE_ROW);
hyatt@apple.comdec0cbf22008-10-17 00:25:33 +0000117 row->setStyle(newStyle.release());
darin316ed062006-01-23 05:29:14 +0000118 addChild(row, beforeChild);
eseidela043f3d2006-01-20 19:24:53 +0000119 row->addChild(child);
eseidela043f3d2006-01-20 19:24:53 +0000120 return;
121 }
122
123 if (beforeChild)
ddkilzer260f3d22007-01-05 05:56:31 +0000124 setNeedsCellRecalc();
eseidela043f3d2006-01-20 19:24:53 +0000125
ddkilzer260f3d22007-01-05 05:56:31 +0000126 ++m_cRow;
127 m_cCol = 0;
eseidela043f3d2006-01-20 19:24:53 +0000128
larsb5288ad2007-01-13 18:48:29 +0000129 // make sure we have enough rows
130 if (!ensureRows(m_cRow + 1))
131 return;
132
darin@apple.com445c34f2009-08-01 00:40:58 +0000133 m_grid[m_cRow].rowRenderer = toRenderTableRow(child);
eseidela043f3d2006-01-20 19:24:53 +0000134
dbates@webkit.orge1131832009-11-19 00:05:57 +0000135 if (!beforeChild)
136 setRowHeightToRowStyleHeightIfNotRelative(&m_grid[m_cRow]);
eseidela043f3d2006-01-20 19:24:53 +0000137
ddkilzer260f3d22007-01-05 05:56:31 +0000138 // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
mitz@apple.comfdbd51e2008-01-18 21:52:57 +0000139 while (beforeChild && beforeChild->parent() != this)
mjs6666eee72006-07-14 07:45:13 +0000140 beforeChild = beforeChild->parent();
141
bdakin@apple.com40ae9be2009-04-16 20:48:19 +0000142 ASSERT(!beforeChild || beforeChild->isTableRow());
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000143 RenderBox::addChild(child, beforeChild);
eseidela043f3d2006-01-20 19:24:53 +0000144}
145
weinig@apple.com84974112009-02-03 06:45:48 +0000146void RenderTableSection::removeChild(RenderObject* oldChild)
147{
148 setNeedsCellRecalc();
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000149 RenderBox::removeChild(oldChild);
weinig@apple.com84974112009-02-03 06:45:48 +0000150}
151
eseidela043f3d2006-01-20 19:24:53 +0000152bool RenderTableSection::ensureRows(int numRows)
153{
ddkilzer260f3d22007-01-05 05:56:31 +0000154 int nRows = m_gridRows;
eseidela043f3d2006-01-20 19:24:53 +0000155 if (numRows > nRows) {
ddkilzer260f3d22007-01-05 05:56:31 +0000156 if (numRows > static_cast<int>(m_grid.size())) {
larsb5288ad2007-01-13 18:48:29 +0000157 size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);
158 if (static_cast<size_t>(numRows) > maxSize)
eseidela043f3d2006-01-20 19:24:53 +0000159 return false;
darin@apple.com83833152008-01-14 17:51:10 +0000160 m_grid.grow(numRows);
darin91298e52006-06-12 01:10:17 +0000161 }
ddkilzer260f3d22007-01-05 05:56:31 +0000162 m_gridRows = numRows;
bdakin@apple.com5b0a3b22008-09-19 23:02:03 +0000163 int nCols = max(1, table()->numEffCols());
ap50b58352006-01-22 20:32:36 +0000164 for (int r = nRows; r < numRows; r++) {
ddkilzer260f3d22007-01-05 05:56:31 +0000165 m_grid[r].row = new Row(nCols);
ddkilzer260f3d22007-01-05 05:56:31 +0000166 m_grid[r].rowRenderer = 0;
hyatt851433b2007-05-12 06:40:14 +0000167 m_grid[r].baseline = 0;
ddkilzer260f3d22007-01-05 05:56:31 +0000168 m_grid[r].height = Length();
ap50b58352006-01-22 20:32:36 +0000169 }
eseidela043f3d2006-01-20 19:24:53 +0000170 }
171
172 return true;
173}
174
hyatt@apple.comd885df72009-01-22 02:31:52 +0000175void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
eseidela043f3d2006-01-20 19:24:53 +0000176{
177 int rSpan = cell->rowSpan();
178 int cSpan = cell->colSpan();
ddkilzer260f3d22007-01-05 05:56:31 +0000179 Vector<RenderTable::ColumnStruct>& columns = table()->columns();
eseidela043f3d2006-01-20 19:24:53 +0000180 int nCols = columns.size();
181
182 // ### mozilla still seems to do the old HTML way, even for strict DTD
183 // (see the annotation on table cell layouting in the CSS specs and the testcase below:
184 // <TABLE border>
185 // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
186 // <TR><TD colspan="2">5
187 // </TABLE>
jamesr@google.com36623a32010-07-23 20:22:29 +0000188 while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).hasCells() || cellAt(m_cRow, m_cCol).inColSpan))
ddkilzer260f3d22007-01-05 05:56:31 +0000189 m_cCol++;
jamesr@google.comb4266232010-07-28 20:07:19 +0000190
eseidela043f3d2006-01-20 19:24:53 +0000191 if (rSpan == 1) {
ap50b58352006-01-22 20:32:36 +0000192 // we ignore height settings on rowspan cells
193 Length height = cell->style()->height();
ddkilzerd1687ca2007-01-04 05:28:35 +0000194 if (height.isPositive() || (height.isRelative() && height.value() >= 0)) {
ddkilzer260f3d22007-01-05 05:56:31 +0000195 Length cRowHeight = m_grid[m_cRow].height;
darin947a31b2006-02-24 03:08:41 +0000196 switch (height.type()) {
eseidela043f3d2006-01-20 19:24:53 +0000197 case Percent:
darin947a31b2006-02-24 03:08:41 +0000198 if (!(cRowHeight.isPercent()) ||
ddkilzerd1687ca2007-01-04 05:28:35 +0000199 (cRowHeight.isPercent() && cRowHeight.rawValue() < height.rawValue()))
ddkilzer260f3d22007-01-05 05:56:31 +0000200 m_grid[m_cRow].height = height;
eseidela043f3d2006-01-20 19:24:53 +0000201 break;
202 case Fixed:
darin947a31b2006-02-24 03:08:41 +0000203 if (cRowHeight.type() < Percent ||
204 (cRowHeight.isFixed() && cRowHeight.value() < height.value()))
ddkilzer260f3d22007-01-05 05:56:31 +0000205 m_grid[m_cRow].height = height;
eseidela043f3d2006-01-20 19:24:53 +0000206 break;
207 case Relative:
208 default:
209 break;
ap50b58352006-01-22 20:32:36 +0000210 }
211 }
eseidela043f3d2006-01-20 19:24:53 +0000212 }
213
214 // make sure we have enough rows
ddkilzer260f3d22007-01-05 05:56:31 +0000215 if (!ensureRows(m_cRow + rSpan))
eseidela043f3d2006-01-20 19:24:53 +0000216 return;
217
ddkilzer260f3d22007-01-05 05:56:31 +0000218 m_grid[m_cRow].rowRenderer = row;
hyattd866e592006-03-17 09:50:35 +0000219
ddkilzer260f3d22007-01-05 05:56:31 +0000220 int col = m_cCol;
eseidela043f3d2006-01-20 19:24:53 +0000221 // tell the cell where it is
jamesr@google.com36623a32010-07-23 20:22:29 +0000222 bool inColSpan = false;
eseidela043f3d2006-01-20 19:24:53 +0000223 while (cSpan) {
jamesr@google.comb4266232010-07-28 20:07:19 +0000224 int currentSpan;
225 if (m_cCol >= nCols) {
226 table()->appendColumn(cSpan);
227 currentSpan = cSpan;
228 } else {
229 if (cSpan < (int)columns[m_cCol].span)
230 table()->splitColumn(m_cCol, cSpan);
231 currentSpan = columns[m_cCol].span;
232 }
233 for (int r = 0; r < rSpan; r++) {
234 CellStruct& c = cellAt(m_cRow + r, m_cCol);
235 ASSERT(cell);
236 c.cells.append(cell);
237 // If cells overlap then we take the slow path for painting.
238 if (c.cells.size() > 1)
239 m_hasMultipleCellLevels = true;
240 if (inColSpan)
241 c.inColSpan = true;
242 }
243 m_cCol++;
244 cSpan -= currentSpan;
245 inColSpan = true;
eseidela043f3d2006-01-20 19:24:53 +0000246 }
eric@webkit.org5832ab72009-03-25 22:15:03 +0000247 cell->setRow(m_cRow);
248 cell->setCol(table()->effColToCol(col));
eseidela043f3d2006-01-20 19:24:53 +0000249}
250
eseidela043f3d2006-01-20 19:24:53 +0000251void RenderTableSection::setCellWidths()
252{
ddkilzer260f3d22007-01-05 05:56:31 +0000253 Vector<int>& columnPos = table()->columnPositions();
eseidela043f3d2006-01-20 19:24:53 +0000254
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000255 LayoutStateMaintainer statePusher(view());
256
ddkilzer260f3d22007-01-05 05:56:31 +0000257 for (int i = 0; i < m_gridRows; i++) {
258 Row& row = *m_grid[i].row;
ap50b58352006-01-22 20:32:36 +0000259 int cols = row.size();
260 for (int j = 0; j < cols; j++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000261 CellStruct& current = row[j];
262 RenderTableCell* cell = current.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +0000263 if (!cell || current.inColSpan)
jamesr@google.com36623a32010-07-23 20:22:29 +0000264 continue;
ap50b58352006-01-22 20:32:36 +0000265 int endCol = j;
266 int cspan = cell->colSpan();
267 while (cspan && endCol < cols) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000268 ASSERT(endCol < (int)table()->columns().size());
ddkilzer260f3d22007-01-05 05:56:31 +0000269 cspan -= table()->columns()[endCol].span;
ap50b58352006-01-22 20:32:36 +0000270 endCol++;
271 }
272 int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
273 int oldWidth = cell->width();
274 if (w != oldWidth) {
275 cell->setNeedsLayout(true);
weinigfef13632007-04-29 20:09:08 +0000276 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000277 if (!statePusher.didPush()) {
weinigfef13632007-04-29 20:09:08 +0000278 // Technically, we should also push state for the row, but since
279 // rows don't push a coordinate transform, that's not necessary.
hyatt@apple.coma97f4672009-01-23 03:55:34 +0000280 statePusher.push(this, IntSize(x(), y()));
weinigfef13632007-04-29 20:09:08 +0000281 }
hyattd72625b2007-04-26 19:51:11 +0000282 cell->repaint();
weinigfef13632007-04-29 20:09:08 +0000283 }
hyatt@apple.comd885df72009-01-22 02:31:52 +0000284 cell->updateWidth(w);
ap50b58352006-01-22 20:32:36 +0000285 }
286 }
eseidela043f3d2006-01-20 19:24:53 +0000287 }
weinigfef13632007-04-29 20:09:08 +0000288
jamesr@google.com36623a32010-07-23 20:22:29 +0000289 statePusher.pop(); // only pops if we pushed
eseidela043f3d2006-01-20 19:24:53 +0000290}
291
mitz@apple.com440ac8c2008-04-05 16:05:08 +0000292int RenderTableSection::calcRowHeight()
eseidela043f3d2006-01-20 19:24:53 +0000293{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000294#ifndef NDEBUG
295 setNeedsLayoutIsForbidden(true);
296#endif
297
298 ASSERT(!needsLayout());
299
ddkilzer260f3d22007-01-05 05:56:31 +0000300 RenderTableCell* cell;
eseidela043f3d2006-01-20 19:24:53 +0000301
eseidela043f3d2006-01-20 19:24:53 +0000302 int spacing = table()->vBorderSpacing();
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000303
304 LayoutStateMaintainer statePusher(view());
eseidela043f3d2006-01-20 19:24:53 +0000305
ddkilzer260f3d22007-01-05 05:56:31 +0000306 m_rowPos.resize(m_gridRows + 1);
307 m_rowPos[0] = spacing;
eseidela043f3d2006-01-20 19:24:53 +0000308
ddkilzer260f3d22007-01-05 05:56:31 +0000309 for (int r = 0; r < m_gridRows; r++) {
310 m_rowPos[r + 1] = 0;
hyatt777b31c2007-07-19 20:01:26 +0000311 m_grid[r].baseline = 0;
ap50b58352006-01-22 20:32:36 +0000312 int baseline = 0;
313 int bdesc = 0;
ddkilzer260f3d22007-01-05 05:56:31 +0000314 int ch = m_grid[r].height.calcMinValue(0);
315 int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);
eseidela043f3d2006-01-20 19:24:53 +0000316
ddkilzer260f3d22007-01-05 05:56:31 +0000317 m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
eseidela043f3d2006-01-20 19:24:53 +0000318
ddkilzer260f3d22007-01-05 05:56:31 +0000319 Row* row = m_grid[r].row;
ap50b58352006-01-22 20:32:36 +0000320 int totalCols = row->size();
eseidela043f3d2006-01-20 19:24:53 +0000321
ap50b58352006-01-22 20:32:36 +0000322 for (int c = 0; c < totalCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000323 CellStruct& current = cellAt(r, c);
324 cell = current.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +0000325
326 if (!cell || current.inColSpan)
ap50b58352006-01-22 20:32:36 +0000327 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000328
329 if ((cell->row() + cell->rowSpan() - 1) > r)
ap50b58352006-01-22 20:32:36 +0000330 continue;
eseidela043f3d2006-01-20 19:24:53 +0000331
ddkilzer260f3d22007-01-05 05:56:31 +0000332 int indx = max(r - cell->rowSpan() + 1, 0);
eseidela043f3d2006-01-20 19:24:53 +0000333
334 if (cell->overrideSize() != -1) {
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000335 if (!statePusher.didPush()) {
weinigfef13632007-04-29 20:09:08 +0000336 // Technically, we should also push state for the row, but since
337 // rows don't push a coordinate transform, that's not necessary.
hyatt@apple.coma97f4672009-01-23 03:55:34 +0000338 statePusher.push(this, IntSize(x(), y()));
weinigfef13632007-04-29 20:09:08 +0000339 }
eseidela043f3d2006-01-20 19:24:53 +0000340 cell->setOverrideSize(-1);
341 cell->setChildNeedsLayout(true, false);
342 cell->layoutIfNeeded();
343 }
344
hyatt@apple.comd76152f2010-09-21 07:45:08 +0000345 int adjustedPaddingTop = cell->paddingTop() - cell->intrinsicPaddingBefore();
346 int adjustedPaddingBottom = cell->paddingBottom() - cell->intrinsicPaddingAfter();
347 int adjustedHeight = cell->height() - (cell->intrinsicPaddingBefore() + cell->intrinsicPaddingAfter());
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000348
eseidela043f3d2006-01-20 19:24:53 +0000349 // Explicit heights use the border box in quirks mode. In strict mode do the right
350 // thing and actually add in the border and padding.
darin947a31b2006-02-24 03:08:41 +0000351 ch = cell->style()->height().calcValue(0) +
hyatt@apple.comce8ee2a2010-08-27 20:29:34 +0000352 (document()->inQuirksMode() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom +
eseidela043f3d2006-01-20 19:24:53 +0000353 cell->borderTop() + cell->borderBottom()));
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000354 ch = max(ch, adjustedHeight);
eseidela043f3d2006-01-20 19:24:53 +0000355
ddkilzer260f3d22007-01-05 05:56:31 +0000356 pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);
eseidela043f3d2006-01-20 19:24:53 +0000357
ddkilzer260f3d22007-01-05 05:56:31 +0000358 m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
eseidela043f3d2006-01-20 19:24:53 +0000359
ap50b58352006-01-22 20:32:36 +0000360 // find out the baseline
361 EVerticalAlign va = cell->style()->verticalAlign();
ddkilzer260f3d22007-01-05 05:56:31 +0000362 if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
ap50b58352006-01-22 20:32:36 +0000363 int b = cell->baselinePosition();
eseidela043f3d2006-01-20 19:24:53 +0000364 if (b > cell->borderTop() + cell->paddingTop()) {
hyatt@apple.comd76152f2010-09-21 07:45:08 +0000365 baseline = max(baseline, b - cell->intrinsicPaddingBefore());
366 bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingBefore()));
eseidela043f3d2006-01-20 19:24:53 +0000367 }
ap50b58352006-01-22 20:32:36 +0000368 }
369 }
eseidela043f3d2006-01-20 19:24:53 +0000370
jamesr@google.com36623a32010-07-23 20:22:29 +0000371 // do we have baseline aligned elements?
ap50b58352006-01-22 20:32:36 +0000372 if (baseline) {
373 // increase rowheight if baseline requires
ddkilzer260f3d22007-01-05 05:56:31 +0000374 m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));
hyatt851433b2007-05-12 06:40:14 +0000375 m_grid[r].baseline = baseline;
ap50b58352006-01-22 20:32:36 +0000376 }
eseidela043f3d2006-01-20 19:24:53 +0000377
ddkilzer260f3d22007-01-05 05:56:31 +0000378 m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
eseidela043f3d2006-01-20 19:24:53 +0000379 }
weinigfef13632007-04-29 20:09:08 +0000380
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000381#ifndef NDEBUG
382 setNeedsLayoutIsForbidden(false);
383#endif
384
385 ASSERT(!needsLayout());
386
simon.fraser@apple.comfeaef2e2008-11-07 19:17:08 +0000387 statePusher.pop();
mitz@apple.com440ac8c2008-04-05 16:05:08 +0000388
389 return m_rowPos[m_gridRows];
eseidela043f3d2006-01-20 19:24:53 +0000390}
391
hyatt@apple.combfda0e32009-01-31 21:20:17 +0000392void RenderTableSection::layout()
393{
394 ASSERT(needsLayout());
395
396 LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
397 for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) {
398 if (child->isTableRow()) {
399 child->layoutIfNeeded();
400 ASSERT(!child->needsLayout());
401 }
402 }
403 statePusher.pop();
404 setNeedsLayout(false);
405}
406
eseidela043f3d2006-01-20 19:24:53 +0000407int RenderTableSection::layoutRows(int toAdd)
408{
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000409#ifndef NDEBUG
410 setNeedsLayoutIsForbidden(true);
411#endif
412
413 ASSERT(!needsLayout());
414
eseidela043f3d2006-01-20 19:24:53 +0000415 int rHeight;
416 int rindx;
ddkilzer260f3d22007-01-05 05:56:31 +0000417 int totalRows = m_gridRows;
eseidela043f3d2006-01-20 19:24:53 +0000418
hyattd866e592006-03-17 09:50:35 +0000419 // Set the width of our section now. The rows will also be this width.
hyatt@apple.comd885df72009-01-22 02:31:52 +0000420 setWidth(table()->contentWidth());
hyatt@apple.com5dc5a312009-08-18 19:15:19 +0000421 m_overflow.clear();
adeleddfe27f2007-01-05 23:03:50 +0000422 m_hasOverflowingCell = false;
423
ddkilzer260f3d22007-01-05 05:56:31 +0000424 if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) {
425 int totalHeight = m_rowPos[totalRows] + toAdd;
eseidela043f3d2006-01-20 19:24:53 +0000426
427 int dh = toAdd;
ap50b58352006-01-22 20:32:36 +0000428 int totalPercent = 0;
429 int numAuto = 0;
430 for (int r = 0; r < totalRows; r++) {
ddkilzer260f3d22007-01-05 05:56:31 +0000431 if (m_grid[r].height.isAuto())
ap50b58352006-01-22 20:32:36 +0000432 numAuto++;
ddkilzer260f3d22007-01-05 05:56:31 +0000433 else if (m_grid[r].height.isPercent())
434 totalPercent += m_grid[r].height.rawValue();
ap50b58352006-01-22 20:32:36 +0000435 }
436 if (totalPercent) {
437 // try to satisfy percent
438 int add = 0;
ddkilzer260f3d22007-01-05 05:56:31 +0000439 totalPercent = min(totalPercent, 100 * percentScaleFactor);
440 int rh = m_rowPos[1] - m_rowPos[0];
ap50b58352006-01-22 20:32:36 +0000441 for (int r = 0; r < totalRows; r++) {
ddkilzer260f3d22007-01-05 05:56:31 +0000442 if (totalPercent > 0 && m_grid[r].height.isPercent()) {
443 int toAdd = min(dh, (totalHeight * m_grid[r].height.rawValue() / (100 * percentScaleFactor)) - rh);
eseidela043f3d2006-01-20 19:24:53 +0000444 // If toAdd is negative, then we don't want to shrink the row (this bug
445 // affected Outlook Web Access).
darin7bd70952006-04-13 07:07:34 +0000446 toAdd = max(0, toAdd);
ap50b58352006-01-22 20:32:36 +0000447 add += toAdd;
448 dh -= toAdd;
ddkilzer260f3d22007-01-05 05:56:31 +0000449 totalPercent -= m_grid[r].height.rawValue();
ap50b58352006-01-22 20:32:36 +0000450 }
451 if (r < totalRows - 1)
ddkilzer260f3d22007-01-05 05:56:31 +0000452 rh = m_rowPos[r + 2] - m_rowPos[r + 1];
453 m_rowPos[r + 1] += add;
ap50b58352006-01-22 20:32:36 +0000454 }
455 }
456 if (numAuto) {
457 // distribute over variable cols
458 int add = 0;
459 for (int r = 0; r < totalRows; r++) {
ddkilzer260f3d22007-01-05 05:56:31 +0000460 if (numAuto > 0 && m_grid[r].height.isAuto()) {
461 int toAdd = dh / numAuto;
ap50b58352006-01-22 20:32:36 +0000462 add += toAdd;
463 dh -= toAdd;
eseidela043f3d2006-01-20 19:24:53 +0000464 numAuto--;
ap50b58352006-01-22 20:32:36 +0000465 }
ddkilzer260f3d22007-01-05 05:56:31 +0000466 m_rowPos[r + 1] += add;
ap50b58352006-01-22 20:32:36 +0000467 }
468 }
ddkilzer260f3d22007-01-05 05:56:31 +0000469 if (dh > 0 && m_rowPos[totalRows]) {
ap50b58352006-01-22 20:32:36 +0000470 // if some left overs, distribute equally.
ddkilzer260f3d22007-01-05 05:56:31 +0000471 int tot = m_rowPos[totalRows];
eseidela043f3d2006-01-20 19:24:53 +0000472 int add = 0;
ddkilzer260f3d22007-01-05 05:56:31 +0000473 int prev = m_rowPos[0];
eseidela043f3d2006-01-20 19:24:53 +0000474 for (int r = 0; r < totalRows; r++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000475 // weight with the original height
ddkilzer260f3d22007-01-05 05:56:31 +0000476 add += dh * (m_rowPos[r + 1] - prev) / tot;
477 prev = m_rowPos[r + 1];
478 m_rowPos[r + 1] += add;
eseidela043f3d2006-01-20 19:24:53 +0000479 }
480 }
481 }
482
ddkilzer260f3d22007-01-05 05:56:31 +0000483 int hspacing = table()->hBorderSpacing();
484 int vspacing = table()->vBorderSpacing();
eseidela043f3d2006-01-20 19:24:53 +0000485 int nEffCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000486
hyatt@apple.coma97f4672009-01-23 03:55:34 +0000487 LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
weinigfef13632007-04-29 20:09:08 +0000488
eseidela043f3d2006-01-20 19:24:53 +0000489 for (int r = 0; r < totalRows; r++) {
hyattd866e592006-03-17 09:50:35 +0000490 // Set the row's x/y position and width/height.
hyatt@apple.comd885df72009-01-22 02:31:52 +0000491 if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
492 rowRenderer->setLocation(0, m_rowPos[r]);
493 rowRenderer->setWidth(width());
adeleddfe27f2007-01-05 23:03:50 +0000494 rowRenderer->setHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
hyattd866e592006-03-17 09:50:35 +0000495 }
496
eseidela043f3d2006-01-20 19:24:53 +0000497 for (int c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000498 CellStruct& cs = cellAt(r, c);
499 RenderTableCell* cell = cs.primaryCell();
500
jamesr@google.comb4266232010-07-28 20:07:19 +0000501 if (!cell || cs.inColSpan)
ap50b58352006-01-22 20:32:36 +0000502 continue;
eseidela043f3d2006-01-20 19:24:53 +0000503
jamesr@google.com36623a32010-07-23 20:22:29 +0000504 rindx = cell->row();
505 rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
eseidela043f3d2006-01-20 19:24:53 +0000506
507 // Force percent height children to lay themselves out again.
508 // This will cause these children to grow to fill the cell.
509 // FIXME: There is still more work to do here to fully match WinIE (should
510 // it become necessary to do so). In quirks mode, WinIE behaves like we
511 // do, but it will clip the cells that spill out of the table section. In
512 // strict mode, Mozilla and WinIE both regrow the table to accommodate the
513 // new height of the cell (thus letting the percentages cause growth one
514 // time only). We may also not be handling row-spanning cells correctly.
515 //
516 // Note also the oddity where replaced elements always flex, and yet blocks/tables do
517 // not necessarily flex. WinIE is crazy and inconsistent, and we can't hope to
518 // match the behavior perfectly, but we'll continue to refine it as we discover new
519 // bugs. :)
520 bool cellChildrenFlex = false;
jamesr@google.com36623a32010-07-23 20:22:29 +0000521 bool flexAllChildren = cell->style()->height().isFixed()
522 || (!table()->style()->height().isAuto() && rHeight != cell->height());
eseidela043f3d2006-01-20 19:24:53 +0000523
524 for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000525 if (!o->isText() && o->style()->height().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
eseidela043f3d2006-01-20 19:24:53 +0000526 // Tables with no sections do not flex.
darin@apple.com445c34f2009-08-01 00:40:58 +0000527 if (!o->isTable() || toRenderTable(o)->hasSections()) {
eseidela043f3d2006-01-20 19:24:53 +0000528 o->setNeedsLayout(true, false);
eseidela043f3d2006-01-20 19:24:53 +0000529 cellChildrenFlex = true;
530 }
531 }
532 }
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000533
534 if (HashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) {
535 HashSet<RenderBox*>::iterator end = percentHeightDescendants->end();
536 for (HashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
537 RenderBox* box = *it;
538 if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
539 continue;
540
541 while (box != cell) {
542 if (box->normalChildNeedsLayout())
543 break;
544 box->setChildNeedsLayout(true, false);
545 box = box->containingBlock();
546 ASSERT(box);
547 if (!box)
548 break;
549 }
550 cellChildrenFlex = true;
551 }
552 }
553
eseidela043f3d2006-01-20 19:24:53 +0000554 if (cellChildrenFlex) {
mitz@apple.com1547c6d2009-03-20 23:41:54 +0000555 cell->setChildNeedsLayout(true, false);
eseidela043f3d2006-01-20 19:24:53 +0000556 // Alignment within a cell is based off the calculated
557 // height, which becomes irrelevant once the cell has
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000558 // been resized based off its percentage.
ap7332aaa2006-04-28 16:02:45 +0000559 cell->setOverrideSize(max(0,
560 rHeight - cell->borderTop() - cell->paddingTop() -
561 cell->borderBottom() - cell->paddingBottom()));
562 cell->layoutIfNeeded();
hyatt851433b2007-05-12 06:40:14 +0000563
564 // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
565 EVerticalAlign va = cell->style()->verticalAlign();
566 if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
567 int b = cell->baselinePosition();
568 if (b > cell->borderTop() + cell->paddingTop())
569 m_grid[r].baseline = max(m_grid[r].baseline, b);
570 }
eseidela043f3d2006-01-20 19:24:53 +0000571 }
572
hyatt@apple.comd76152f2010-09-21 07:45:08 +0000573 int oldTe = cell->intrinsicPaddingBefore();
574 int oldBe = cell->intrinsicPaddingAfter();
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000575 int heightWithoutIntrinsicPadding = cell->height() - oldTe - oldBe;
576
bdakinf9936352007-04-19 19:58:20 +0000577 int te = 0;
578 switch (cell->style()->verticalAlign()) {
579 case SUB:
580 case SUPER:
581 case TEXT_TOP:
582 case TEXT_BOTTOM:
hyatt@apple.com5defbad2009-01-23 04:30:47 +0000583 case BASELINE: {
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000584 int b = cell->baselinePosition();
585 if (b > cell->borderTop() + cell->paddingTop())
586 te = getBaseline(r) - (b - oldTe);
bdakinf9936352007-04-19 19:58:20 +0000587 break;
hyatt@apple.com5defbad2009-01-23 04:30:47 +0000588 }
bdakinf9936352007-04-19 19:58:20 +0000589 case TOP:
590 te = 0;
591 break;
592 case MIDDLE:
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000593 te = (rHeight - heightWithoutIntrinsicPadding) / 2;
bdakinf9936352007-04-19 19:58:20 +0000594 break;
595 case BOTTOM:
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000596 te = rHeight - heightWithoutIntrinsicPadding;
bdakinf9936352007-04-19 19:58:20 +0000597 break;
598 default:
599 break;
600 }
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000601
602 int be = rHeight - heightWithoutIntrinsicPadding - te;
hyatt@apple.comd76152f2010-09-21 07:45:08 +0000603 cell->setIntrinsicPaddingBefore(te);
604 cell->setIntrinsicPaddingAfter(be);
bdakinf9936352007-04-19 19:58:20 +0000605
hyatt@apple.com0bf6c842009-01-23 03:42:12 +0000606 IntRect oldCellRect(cell->x(), cell->y() , cell->width(), cell->height());
hyatt@apple.comb297b492010-09-20 20:21:34 +0000607
hyatt@apple.comc0fa1632010-09-30 20:01:33 +0000608 if (!style()->isLeftToRightDirection())
hyatt@apple.comd885df72009-01-22 02:31:52 +0000609 cell->setLocation(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
jamesr@google.com36623a32010-07-23 20:22:29 +0000610 else
hyatt@apple.comd885df72009-01-22 02:31:52 +0000611 cell->setLocation(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);
hyatt@apple.comb297b492010-09-20 20:21:34 +0000612 view()->addLayoutDelta(IntSize(oldCellRect.x() - cell->x(), oldCellRect.y() - cell->y()));
eseidela043f3d2006-01-20 19:24:53 +0000613
hyatt@apple.com1259d732010-09-20 16:12:58 +0000614 if (te != oldTe || be != oldBe)
615 cell->setNeedsLayout(true, false);
616
617 if (!cell->needsLayout() && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(cell->y()) != cell->pageY())
618 cell->setChildNeedsLayout(true, false);
hyatt@apple.comb297b492010-09-20 20:21:34 +0000619
hyatt@apple.com1259d732010-09-20 16:12:58 +0000620 cell->layoutIfNeeded();
621
622 if (view()->layoutState()->m_pageHeight && cell->height() != rHeight)
623 cell->setHeight(rHeight); // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
hyatt@apple.comb297b492010-09-20 20:21:34 +0000624
625 IntSize childOffset(cell->x() - oldCellRect.x(), cell->y() - oldCellRect.y());
626 if (childOffset.width() || childOffset.height()) {
627 view()->addLayoutDelta(childOffset);
hyatt@apple.com1259d732010-09-20 16:12:58 +0000628
hyatt@apple.comb297b492010-09-20 20:21:34 +0000629 // If the child moved, we have to repaint it as well as any floating/positioned
630 // descendants. An exception is if we need a layout. In this case, we know we're going to
631 // repaint ourselves (and the child) anyway.
632 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
633 cell->repaintDuringLayoutIfMoved(oldCellRect);
634 }
eseidela043f3d2006-01-20 19:24:53 +0000635 }
636 }
637
hyatt@apple.comc93db9b2009-02-04 22:29:04 +0000638#ifndef NDEBUG
639 setNeedsLayoutIsForbidden(false);
640#endif
641
hyatt@apple.com8b2cd1f2009-01-26 03:38:55 +0000642 ASSERT(!needsLayout());
643
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000644 setHeight(m_rowPos[totalRows]);
645
646 // Now that our height has been determined, add in overflow from cells.
647 for (int r = 0; r < totalRows; r++) {
648 for (int c = 0; c < nEffCols; c++) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000649 CellStruct& cs = cellAt(r, c);
650 RenderTableCell* cell = cs.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +0000651 if (!cell || cs.inColSpan)
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000652 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000653 if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000654 continue;
655 addOverflowFromChild(cell);
mitz@apple.comeea52852009-12-31 18:41:23 +0000656 m_hasOverflowingCell |= cell->hasVisibleOverflow();
hyatt@apple.com7214c6a2009-08-19 16:28:51 +0000657 }
658 }
weinigfef13632007-04-29 20:09:08 +0000659
mitz@apple.comeea52852009-12-31 18:41:23 +0000660 statePusher.pop();
hyatt@apple.comd885df72009-01-22 02:31:52 +0000661 return height();
eseidela043f3d2006-01-20 19:24:53 +0000662}
663
adele04d4ce12006-02-11 20:11:05 +0000664int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
665{
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000666 int bottom = RenderBox::lowestPosition(includeOverflowInterior, includeSelf);
adele04d4ce12006-02-11 20:11:05 +0000667 if (!includeOverflowInterior && hasOverflowClip())
668 return bottom;
669
ddkilzer260f3d22007-01-05 05:56:31 +0000670 for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000671 for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
672 if (curr->isTableCell()) {
darin@apple.com445c34f2009-08-01 00:40:58 +0000673 RenderTableCell* cell = toRenderTableCell(curr);
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000674 bottom = max(bottom, cell->y() + cell->lowestPosition(false));
675 }
adele04d4ce12006-02-11 20:11:05 +0000676 }
677 }
678
679 return bottom;
680}
681
682int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
683{
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000684 int right = RenderBox::rightmostPosition(includeOverflowInterior, includeSelf);
adele04d4ce12006-02-11 20:11:05 +0000685 if (!includeOverflowInterior && hasOverflowClip())
686 return right;
687
ddkilzer260f3d22007-01-05 05:56:31 +0000688 for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000689 for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
690 if (curr->isTableCell()) {
darin@apple.com445c34f2009-08-01 00:40:58 +0000691 RenderTableCell* cell = toRenderTableCell(curr);
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000692 right = max(right, cell->x() + cell->rightmostPosition(false));
693 }
adele04d4ce12006-02-11 20:11:05 +0000694 }
695 }
696
697 return right;
698}
699
700int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
701{
hyatt@apple.comf073d9b2009-02-05 00:53:38 +0000702 int left = RenderBox::leftmostPosition(includeOverflowInterior, includeSelf);
adele04d4ce12006-02-11 20:11:05 +0000703 if (!includeOverflowInterior && hasOverflowClip())
704 return left;
705
ddkilzer260f3d22007-01-05 05:56:31 +0000706 for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000707 for (RenderObject* curr = row->firstChild(); curr; curr = curr->nextSibling()) {
708 if (curr->isTableCell()) {
darin@apple.com445c34f2009-08-01 00:40:58 +0000709 RenderTableCell* cell = toRenderTableCell(curr);
hyatt@apple.com2e6e0b62009-02-13 18:17:26 +0000710 left = min(left, cell->x() + cell->leftmostPosition(false));
711 }
adele04d4ce12006-02-11 20:11:05 +0000712 }
713 }
714
715 return left;
716}
eseidela043f3d2006-01-20 19:24:53 +0000717
darin32011102006-05-15 04:42:09 +0000718int RenderTableSection::calcOuterBorderTop() const
719{
720 int totalCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000721 if (!m_gridRows || !totalCols)
darin32011102006-05-15 04:42:09 +0000722 return 0;
723
724 unsigned borderWidth = 0;
725
726 const BorderValue& sb = style()->borderTop();
727 if (sb.style() == BHIDDEN)
728 return -1;
729 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000730 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000731
732 const BorderValue& rb = firstChild()->style()->borderTop();
733 if (rb.style() == BHIDDEN)
734 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000735 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
736 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000737
738 bool allHidden = true;
739 for (int c = 0; c < totalCols; c++) {
740 const CellStruct& current = cellAt(0, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000741 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000742 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000743 const BorderValue& cb = current.primaryCell()->style()->borderTop();
darin32011102006-05-15 04:42:09 +0000744 // FIXME: Don't repeat for the same col group
745 RenderTableCol* colGroup = table()->colElement(c);
746 if (colGroup) {
747 const BorderValue& gb = colGroup->style()->borderTop();
748 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
749 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000750 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000751 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
752 borderWidth = gb.width();
753 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
754 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000755 } else {
756 if (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 (cb.style() > BHIDDEN && cb.width() > borderWidth)
760 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000761 }
762 }
763 if (allHidden)
764 return -1;
765
766 return borderWidth / 2;
767}
768
769int RenderTableSection::calcOuterBorderBottom() const
770{
771 int totalCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000772 if (!m_gridRows || !totalCols)
darin32011102006-05-15 04:42:09 +0000773 return 0;
774
775 unsigned borderWidth = 0;
776
777 const BorderValue& sb = style()->borderBottom();
778 if (sb.style() == BHIDDEN)
779 return -1;
780 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000781 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000782
783 const BorderValue& rb = lastChild()->style()->borderBottom();
784 if (rb.style() == BHIDDEN)
785 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000786 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
787 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000788
789 bool allHidden = true;
790 for (int c = 0; c < totalCols; c++) {
ddkilzer260f3d22007-01-05 05:56:31 +0000791 const CellStruct& current = cellAt(m_gridRows - 1, c);
jamesr@google.com36623a32010-07-23 20:22:29 +0000792 if (current.inColSpan || !current.hasCells())
darin32011102006-05-15 04:42:09 +0000793 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000794 const BorderValue& cb = current.primaryCell()->style()->borderBottom();
darin32011102006-05-15 04:42:09 +0000795 // FIXME: Don't repeat for the same col group
796 RenderTableCol* colGroup = table()->colElement(c);
797 if (colGroup) {
798 const BorderValue& gb = colGroup->style()->borderBottom();
799 if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
800 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000801 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000802 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
803 borderWidth = gb.width();
804 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
805 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000806 } else {
807 if (cb.style() == BHIDDEN)
808 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000809 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000810 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
811 borderWidth = cb.width();
darin32011102006-05-15 04:42:09 +0000812 }
813 }
814 if (allHidden)
815 return -1;
816
817 return (borderWidth + 1) / 2;
818}
819
820int RenderTableSection::calcOuterBorderLeft(bool rtl) const
821{
822 int totalCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000823 if (!m_gridRows || !totalCols)
darin32011102006-05-15 04:42:09 +0000824 return 0;
825
826 unsigned borderWidth = 0;
827
828 const BorderValue& sb = style()->borderLeft();
829 if (sb.style() == BHIDDEN)
830 return -1;
831 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000832 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000833
834 int leftmostColumn = rtl ? totalCols - 1 : 0;
835 RenderTableCol* colGroup = table()->colElement(leftmostColumn);
836 if (colGroup) {
837 const BorderValue& gb = colGroup->style()->borderLeft();
838 if (gb.style() == BHIDDEN)
839 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000840 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
841 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000842 }
843
844 bool allHidden = true;
ddkilzer260f3d22007-01-05 05:56:31 +0000845 for (int r = 0; r < m_gridRows; r++) {
darin32011102006-05-15 04:42:09 +0000846 const CellStruct& current = cellAt(r, leftmostColumn);
jamesr@google.com36623a32010-07-23 20:22:29 +0000847 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000848 continue;
849 // FIXME: Don't repeat for the same cell
jamesr@google.com36623a32010-07-23 20:22:29 +0000850 const BorderValue& cb = current.primaryCell()->style()->borderLeft();
851 const BorderValue& rb = current.primaryCell()->parent()->style()->borderLeft();
darin32011102006-05-15 04:42:09 +0000852 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
853 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000854 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000855 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
856 borderWidth = cb.width();
857 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
858 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000859 }
860 if (allHidden)
861 return -1;
862
863 return borderWidth / 2;
864}
865
866int RenderTableSection::calcOuterBorderRight(bool rtl) const
867{
868 int totalCols = table()->numEffCols();
ddkilzer260f3d22007-01-05 05:56:31 +0000869 if (!m_gridRows || !totalCols)
darin32011102006-05-15 04:42:09 +0000870 return 0;
871
872 unsigned borderWidth = 0;
873
874 const BorderValue& sb = style()->borderRight();
875 if (sb.style() == BHIDDEN)
876 return -1;
877 if (sb.style() > BHIDDEN)
hyatt@apple.come607db72010-04-09 20:21:55 +0000878 borderWidth = sb.width();
darin32011102006-05-15 04:42:09 +0000879
880 int rightmostColumn = rtl ? 0 : totalCols - 1;
881 RenderTableCol* colGroup = table()->colElement(rightmostColumn);
882 if (colGroup) {
883 const BorderValue& gb = colGroup->style()->borderRight();
884 if (gb.style() == BHIDDEN)
885 return -1;
hyatt@apple.come607db72010-04-09 20:21:55 +0000886 if (gb.style() > BHIDDEN && gb.width() > borderWidth)
887 borderWidth = gb.width();
darin32011102006-05-15 04:42:09 +0000888 }
889
890 bool allHidden = true;
ddkilzer260f3d22007-01-05 05:56:31 +0000891 for (int r = 0; r < m_gridRows; r++) {
darin32011102006-05-15 04:42:09 +0000892 const CellStruct& current = cellAt(r, rightmostColumn);
jamesr@google.com36623a32010-07-23 20:22:29 +0000893 if (!current.hasCells())
darin32011102006-05-15 04:42:09 +0000894 continue;
895 // FIXME: Don't repeat for the same cell
jamesr@google.com36623a32010-07-23 20:22:29 +0000896 const BorderValue& cb = current.primaryCell()->style()->borderRight();
897 const BorderValue& rb = current.primaryCell()->parent()->style()->borderRight();
darin32011102006-05-15 04:42:09 +0000898 if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
899 continue;
jamesr@google.com36623a32010-07-23 20:22:29 +0000900 allHidden = false;
hyatt@apple.come607db72010-04-09 20:21:55 +0000901 if (cb.style() > BHIDDEN && cb.width() > borderWidth)
902 borderWidth = cb.width();
903 if (rb.style() > BHIDDEN && rb.width() > borderWidth)
904 borderWidth = rb.width();
darin32011102006-05-15 04:42:09 +0000905 }
906 if (allHidden)
907 return -1;
908
909 return (borderWidth + 1) / 2;
910}
911
912void RenderTableSection::recalcOuterBorder()
913{
hyatt@apple.comc0fa1632010-09-30 20:01:33 +0000914 bool rtl = !table()->style()->isLeftToRightDirection();
darin32011102006-05-15 04:42:09 +0000915 m_outerBorderTop = calcOuterBorderTop();
916 m_outerBorderBottom = calcOuterBorderBottom();
917 m_outerBorderLeft = calcOuterBorderLeft(rtl);
918 m_outerBorderRight = calcOuterBorderRight(rtl);
919}
920
hyatt@apple.com916f31f2009-02-11 19:02:12 +0000921int RenderTableSection::firstLineBoxBaseline() const
mitz@apple.com57a2f482008-08-23 07:16:41 +0000922{
923 if (!m_gridRows)
924 return -1;
925
926 int firstLineBaseline = m_grid[0].baseline;
927 if (firstLineBaseline)
928 return firstLineBaseline + m_rowPos[0];
929
930 firstLineBaseline = -1;
931 Row* firstRow = m_grid[0].row;
932 for (size_t i = 0; i < firstRow->size(); ++i) {
jamesr@google.com36623a32010-07-23 20:22:29 +0000933 CellStruct& cs = firstRow->at(i);
934 RenderTableCell* cell = cs.primaryCell();
mitz@apple.com57a2f482008-08-23 07:16:41 +0000935 if (cell)
hyatt@apple.comd885df72009-01-22 02:31:52 +0000936 firstLineBaseline = max(firstLineBaseline, cell->y() + cell->paddingTop() + cell->borderTop() + cell->contentHeight());
mitz@apple.com57a2f482008-08-23 07:16:41 +0000937 }
938
939 return firstLineBaseline;
940}
darin32011102006-05-15 04:42:09 +0000941
weinig0a635f02006-11-01 21:49:13 +0000942void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
eseidela043f3d2006-01-20 19:24:53 +0000943{
anttib3666072007-08-17 23:29:50 +0000944 // put this back in when all layout tests can handle it
945 // ASSERT(!needsLayout());
946 // avoid crashing on bugs that cause us to paint with dirty layout
947 if (needsLayout())
948 return;
949
ddkilzer260f3d22007-01-05 05:56:31 +0000950 unsigned totalRows = m_gridRows;
951 unsigned totalCols = table()->columns().size();
eseidela043f3d2006-01-20 19:24:53 +0000952
ddkilzer260f3d22007-01-05 05:56:31 +0000953 if (!totalRows || !totalCols)
ap0e708ba2006-05-20 08:47:37 +0000954 return;
955
hyatt@apple.comd885df72009-01-22 02:31:52 +0000956 tx += x();
hyatt@apple.coma97f4672009-01-23 03:55:34 +0000957 ty += y();
eseidela043f3d2006-01-20 19:24:53 +0000958
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +0000959 PaintPhase phase = paintInfo.phase;
960 bool pushedClip = pushContentsClip(paintInfo, tx, ty);
961 paintObject(paintInfo, tx, ty);
962 if (pushedClip)
963 popContentsClip(paintInfo, phase, tx, ty);
964}
965
jamesr@google.com36623a32010-07-23 20:22:29 +0000966static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
967{
968 return elem1->row() < elem2->row();
969}
970
971void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, int tx, int ty)
972{
973 PaintPhase paintPhase = paintInfo.phase;
974 RenderTableRow* row = toRenderTableRow(cell->parent());
975
976 if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
977 // We need to handle painting a stack of backgrounds. This stack (from bottom to top) consists of
978 // the column group, column, row group, row, and then the cell.
979 RenderObject* col = table()->colElement(cell->col());
980 RenderObject* colGroup = 0;
981 if (col && col->parent()->style()->display() == TABLE_COLUMN_GROUP)
982 colGroup = col->parent();
983
984 // Column groups and columns first.
985 // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
986 // the stack, since we have already opened a transparency layer (potentially) for the table row group.
987 // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
988 // cell.
989 cell->paintBackgroundsBehindCell(paintInfo, tx, ty, colGroup);
990 cell->paintBackgroundsBehindCell(paintInfo, tx, ty, col);
991
992 // Paint the row group next.
993 cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
994
995 // Paint the row next, but only if it doesn't have a layer. If a row has a layer, it will be responsible for
996 // painting the row background for the cell.
997 if (!row->hasSelfPaintingLayer())
998 cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
999 }
1000 if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
1001 cell->paint(paintInfo, tx, ty);
1002
1003}
1004
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001005void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty)
1006{
ddkilzer260f3d22007-01-05 05:56:31 +00001007 // Check which rows and cols are visible and only paint these.
1008 // FIXME: Could use a binary search here.
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001009 unsigned totalRows = m_gridRows;
1010 unsigned totalCols = table()->columns().size();
1011
weinig0a635f02006-11-01 21:49:13 +00001012 PaintPhase paintPhase = paintInfo.phase;
1013 int x = paintInfo.rect.x();
1014 int y = paintInfo.rect.y();
1015 int w = paintInfo.rect.width();
1016 int h = paintInfo.rect.height();
eseidela043f3d2006-01-20 19:24:53 +00001017
bdakinf061af72006-03-31 01:19:41 +00001018 int os = 2 * maximalOutlineSize(paintPhase);
ddkilzer260f3d22007-01-05 05:56:31 +00001019 unsigned startrow = 0;
1020 unsigned endrow = totalRows;
ap292f4df2007-02-18 16:15:07 +00001021
1022 // If some cell overflows, just paint all of them.
1023 if (!m_hasOverflowingCell) {
jamesr@google.comf88b2582010-08-17 20:57:15 +00001024 int relativeY = y - ty;
1025 int top = relativeY - os;
1026 // binary search to find a row
1027 startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), top) - m_rowPos.begin();
eseidela043f3d2006-01-20 19:24:53 +00001028
jamesr@google.comf88b2582010-08-17 20:57:15 +00001029 // The binary search above gives us the first row with
1030 // a y position >= the top of the paint rect. Thus, the previous
1031 // may need to be repainted as well.
1032 if (startrow == m_rowPos.size() || (startrow > 0 && (m_rowPos[startrow] > top)))
1033 --startrow;
1034
fsamuel@chromium.org179df3b2010-10-05 23:55:13 +00001035 int bottom = relativeY + h + os;
jamesr@google.comf88b2582010-08-17 20:57:15 +00001036 endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), bottom) - m_rowPos.begin();
fsamuel@chromium.org179df3b2010-10-05 23:55:13 +00001037 if (endrow == m_rowPos.size())
jamesr@google.comf88b2582010-08-17 20:57:15 +00001038 --endrow;
1039
ap292f4df2007-02-18 16:15:07 +00001040 if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os)
jamesr@google.comf88b2582010-08-17 20:57:15 +00001041 ++endrow;
weinig0a635f02006-11-01 21:49:13 +00001042 }
ddkilzer260f3d22007-01-05 05:56:31 +00001043 unsigned startcol = 0;
1044 unsigned endcol = totalCols;
adeleddfe27f2007-01-05 23:03:50 +00001045 // FIXME: Implement RTL.
hyatt@apple.comc0fa1632010-09-30 20:01:33 +00001046 if (!m_hasOverflowingCell && style()->isLeftToRightDirection()) {
jamesr@google.comf88b2582010-08-17 20:57:15 +00001047 int relativeX = x - tx;
1048 int left = relativeX - os;
1049 Vector<int>& columnPos = table()->columnPositions();
1050 startcol = std::lower_bound(columnPos.begin(), columnPos.end(), left) - columnPos.begin();
1051 if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > left)))
1052 --startcol;
weinig0a635f02006-11-01 21:49:13 +00001053
fsamuel@chromium.org179df3b2010-10-05 23:55:13 +00001054 int right = relativeX + w + os;
jamesr@google.comf88b2582010-08-17 20:57:15 +00001055 endcol = std::lower_bound(columnPos.begin(), columnPos.end(), right) - columnPos.begin();
fsamuel@chromium.org179df3b2010-10-05 23:55:13 +00001056 if (endcol == columnPos.size())
jamesr@google.comf88b2582010-08-17 20:57:15 +00001057 --endcol;
1058
ddkilzer260f3d22007-01-05 05:56:31 +00001059 if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os)
jamesr@google.comf88b2582010-08-17 20:57:15 +00001060 ++endcol;
eseidela043f3d2006-01-20 19:24:53 +00001061 }
eseidela043f3d2006-01-20 19:24:53 +00001062 if (startcol < endcol) {
jamesr@google.com36623a32010-07-23 20:22:29 +00001063 if (!m_hasMultipleCellLevels) {
1064 // Draw the dirty cells in the order that they appear.
1065 for (unsigned r = startrow; r < endrow; r++) {
1066 for (unsigned c = startcol; c < endcol; c++) {
1067 CellStruct& current = cellAt(r, c);
1068 RenderTableCell* cell = current.primaryCell();
jamesr@google.comb4266232010-07-28 20:07:19 +00001069 if (!cell || (r > startrow && primaryCellAt(r - 1, c) == cell) || (c > startcol && primaryCellAt(r, c - 1) == cell))
jamesr@google.com36623a32010-07-23 20:22:29 +00001070 continue;
1071 paintCell(cell, paintInfo, tx, ty);
hyatte031dd02006-03-18 01:01:06 +00001072 }
ap50b58352006-01-22 20:32:36 +00001073 }
jamesr@google.com36623a32010-07-23 20:22:29 +00001074 } else {
1075 // Draw the cells in the correct paint order.
1076 Vector<RenderTableCell*> cells;
1077 HashSet<RenderTableCell*> spanningCells;
1078 for (unsigned r = startrow; r < endrow; r++) {
1079 for (unsigned c = startcol; c < endcol; c++) {
1080 CellStruct& current = cellAt(r, c);
jamesr@google.comb4266232010-07-28 20:07:19 +00001081 if (!current.hasCells())
jamesr@google.com36623a32010-07-23 20:22:29 +00001082 continue;
1083 for (unsigned i = 0; i < current.cells.size(); ++i) {
1084 if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
1085 if (spanningCells.contains(current.cells[i]))
1086 continue;
1087 spanningCells.add(current.cells[i]);
1088 }
1089 cells.append(current.cells[i]);
1090 }
1091 }
1092 }
1093 // Sort the dirty cells by paint order.
1094 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
1095 int size = cells.size();
1096 // Paint the cells.
1097 for (int i = 0; i < size; ++i)
1098 paintCell(cells[i], paintInfo, tx, ty);
ap50b58352006-01-22 20:32:36 +00001099 }
eseidela043f3d2006-01-20 19:24:53 +00001100 }
1101}
1102
darin@apple.com98a7ac62009-01-05 17:26:53 +00001103void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
bdashb07ae8d2007-02-08 04:56:20 +00001104{
bdashb07ae8d2007-02-08 04:56:20 +00001105 // FIXME: Examine cells and repaint only the rect the image paints in.
1106 repaint();
1107}
1108
eseidela043f3d2006-01-20 19:24:53 +00001109void RenderTableSection::recalcCells()
1110{
ddkilzer260f3d22007-01-05 05:56:31 +00001111 m_cCol = 0;
1112 m_cRow = -1;
eseidela043f3d2006-01-20 19:24:53 +00001113 clearGrid();
ddkilzer260f3d22007-01-05 05:56:31 +00001114 m_gridRows = 0;
eseidela043f3d2006-01-20 19:24:53 +00001115
ddkilzer260f3d22007-01-05 05:56:31 +00001116 for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
hyattd866e592006-03-17 09:50:35 +00001117 if (row->isTableRow()) {
ddkilzer260f3d22007-01-05 05:56:31 +00001118 m_cRow++;
1119 m_cCol = 0;
larsb5288ad2007-01-13 18:48:29 +00001120 if (!ensureRows(m_cRow + 1))
1121 break;
hyatt@apple.comd885df72009-01-22 02:31:52 +00001122
darin@apple.com445c34f2009-08-01 00:40:58 +00001123 RenderTableRow* tableRow = toRenderTableRow(row);
hyatt@apple.comd885df72009-01-22 02:31:52 +00001124 m_grid[m_cRow].rowRenderer = tableRow;
dbates@webkit.orge1131832009-11-19 00:05:57 +00001125 setRowHeightToRowStyleHeightIfNotRelative(&m_grid[m_cRow]);
eseidel05ef0432006-05-25 22:11:36 +00001126
ddkilzer260f3d22007-01-05 05:56:31 +00001127 for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
hyattd866e592006-03-17 09:50:35 +00001128 if (cell->isTableCell())
darin@apple.com445c34f2009-08-01 00:40:58 +00001129 addCell(toRenderTableCell(cell), tableRow);
ddkilzer260f3d22007-01-05 05:56:31 +00001130 }
hyattd866e592006-03-17 09:50:35 +00001131 }
eseidela043f3d2006-01-20 19:24:53 +00001132 }
ddkilzer260f3d22007-01-05 05:56:31 +00001133 m_needsCellRecalc = false;
eseidela043f3d2006-01-20 19:24:53 +00001134 setNeedsLayout(true);
1135}
1136
1137void RenderTableSection::clearGrid()
1138{
ddkilzer260f3d22007-01-05 05:56:31 +00001139 int rows = m_gridRows;
eseidela043f3d2006-01-20 19:24:53 +00001140 while (rows--)
ddkilzer260f3d22007-01-05 05:56:31 +00001141 delete m_grid[rows].row;
ap50b58352006-01-22 20:32:36 +00001142}
1143
1144int RenderTableSection::numColumns() const
1145{
1146 int result = 0;
1147
ddkilzer260f3d22007-01-05 05:56:31 +00001148 for (int r = 0; r < m_gridRows; ++r) {
ap50b58352006-01-22 20:32:36 +00001149 for (int c = result; c < table()->numEffCols(); ++c) {
1150 const CellStruct& cell = cellAt(r, c);
jamesr@google.com36623a32010-07-23 20:22:29 +00001151 if (cell.hasCells() || cell.inColSpan)
ap50b58352006-01-22 20:32:36 +00001152 result = c;
1153 }
1154 }
1155
1156 return result + 1;
eseidela043f3d2006-01-20 19:24:53 +00001157}
1158
ddkilzer260f3d22007-01-05 05:56:31 +00001159void RenderTableSection::appendColumn(int pos)
1160{
jamesr@google.comb4266232010-07-28 20:07:19 +00001161 for (int row = 0; row < m_gridRows; ++row)
ddkilzer260f3d22007-01-05 05:56:31 +00001162 m_grid[row].row->resize(pos + 1);
ddkilzer260f3d22007-01-05 05:56:31 +00001163}
1164
jamesr@google.com36623a32010-07-23 20:22:29 +00001165void RenderTableSection::splitColumn(int pos, int first)
ddkilzer260f3d22007-01-05 05:56:31 +00001166{
1167 if (m_cCol > pos)
1168 m_cCol++;
1169 for (int row = 0; row < m_gridRows; ++row) {
ddkilzer260f3d22007-01-05 05:56:31 +00001170 Row& r = *m_grid[row].row;
jamesr@google.com36623a32010-07-23 20:22:29 +00001171 r.insert(pos + 1, CellStruct());
1172 if (r[pos].hasCells()) {
1173 r[pos + 1].cells.append(r[pos].cells);
1174 RenderTableCell* cell = r[pos].primaryCell();
1175 ASSERT(cell);
1176 int colleft = cell->colSpan() - r[pos].inColSpan;
1177 if (first > colleft)
1178 r[pos + 1].inColSpan = 0;
1179 else
1180 r[pos + 1].inColSpan = first + r[pos].inColSpan;
1181 } else {
1182 r[pos + 1].inColSpan = 0;
1183 }
ddkilzer260f3d22007-01-05 05:56:31 +00001184 }
1185}
1186
hyattd866e592006-03-17 09:50:35 +00001187// Hit Testing
hyatt@apple.comd885df72009-01-22 02:31:52 +00001188bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
hyattd866e592006-03-17 09:50:35 +00001189{
jamesr@google.comf88b2582010-08-17 20:57:15 +00001190 // If we have no children then we have nothing to do.
1191 if (!firstChild())
1192 return false;
1193
hyattd866e592006-03-17 09:50:35 +00001194 // Table sections cannot ever be hit tested. Effectively they do not exist.
1195 // Just forward to our children always.
hyatt@apple.comd885df72009-01-22 02:31:52 +00001196 tx += x();
hyatt@apple.coma97f4672009-01-23 03:55:34 +00001197 ty += y();
hyattd866e592006-03-17 09:50:35 +00001198
tonikitoo@webkit.org81c027d2010-07-29 13:19:43 +00001199 if (hasOverflowClip() && !overflowClipRect(tx, ty).intersects(result.rectFromPoint(xPos, yPos)))
hyatt@apple.comfe52f5b2009-02-25 01:21:03 +00001200 return false;
1201
jamesr@google.comf88b2582010-08-17 20:57:15 +00001202 if (m_hasOverflowingCell) {
1203 for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1204 // FIXME: We have to skip over inline flows, since they can show up inside table rows
1205 // at the moment (a demoted inline <form> for example). If we ever implement a
1206 // table-specific hit-test method (which we should do for performance reasons anyway),
1207 // then we can remove this check.
1208 if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
1209 updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
1210 return true;
1211 }
1212 }
1213 return false;
1214 }
1215
1216 int relativeY = yPos - ty;
1217 // leftrow corresponds to the first row that starts after the y mouse position
1218 unsigned leftrow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), relativeY) - m_rowPos.begin();
1219 if (leftrow == m_rowPos.size())
1220 return false;
1221 // Grab the last row that starts before the y mouse position.
1222 if (leftrow > 0)
1223 --leftrow;
1224
1225 Vector<int>& columnPos = table()->columnPositions();
hyatt@apple.comc0fa1632010-09-30 20:01:33 +00001226 bool rtl = !style()->isLeftToRightDirection();
jamesr@google.comf88b2582010-08-17 20:57:15 +00001227 int relativeX = xPos - tx;
1228 if (rtl)
1229 relativeX = columnPos[columnPos.size() - 1] - relativeX;
1230
1231 unsigned leftcol = std::lower_bound(columnPos.begin(), columnPos.end(), relativeX) - columnPos.begin();
1232 if (leftcol == columnPos.size())
1233 return false;
1234 if (leftcol > 0)
1235 --leftcol;
1236
1237 CellStruct& current = cellAt(leftrow, leftcol);
1238
1239 // If the cell is empty, there's nothing to do
1240 if (!current.hasCells())
1241 return false;
1242
1243 for (int i = current.cells.size() - 1; i >= 0; --i) {
1244 RenderTableCell* cell = current.cells[i];
1245 if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
hyatt@apple.comd885df72009-01-22 02:31:52 +00001246 updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
hyattd866e592006-03-17 09:50:35 +00001247 return true;
1248 }
1249 }
hyattd866e592006-03-17 09:50:35 +00001250 return false;
jamesr@google.comf88b2582010-08-17 20:57:15 +00001251
hyattd866e592006-03-17 09:50:35 +00001252}
1253
ddkilzer260f3d22007-01-05 05:56:31 +00001254} // namespace WebCore