Crash in WebCore::RenderTableSection::addChild due to assert failure
[WebKit-https.git] / Source / WebCore / rendering / RenderTableSection.cpp
1 /*
2  * 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)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
8  * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  *
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
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "RenderTableSection.h"
28 #include "CachedImage.h"
29 #include "Document.h"
30 #include "HitTestResult.h"
31 #include "HTMLNames.h"
32 #include "PaintInfo.h"
33 #include "RenderTableCell.h"
34 #include "RenderTableCol.h"
35 #include "RenderTableRow.h"
36 #include "RenderView.h"
37 #include <limits>
38 #include <wtf/HashSet.h>
39 #include <wtf/Vector.h>
40
41 using namespace std;
42
43 namespace WebCore {
44
45 using namespace HTMLNames;
46
47 // Those 2 variables are used to balance the memory consumption vs the repaint time on big tables.
48 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75;
49 static float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f;
50
51 static inline void setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(RenderTableSection::RowStruct* row)
52 {
53     ASSERT(row && row->rowRenderer);
54     row->logicalHeight = row->rowRenderer->style()->logicalHeight();
55     if (row->logicalHeight.isRelative())
56         row->logicalHeight = Length();
57 }
58
59 RenderTableSection::RenderTableSection(Node* node)
60     : RenderBox(node)
61     , m_gridRows(0)
62     , m_cCol(0)
63     , m_cRow(-1)
64     , m_outerBorderStart(0)
65     , m_outerBorderEnd(0)
66     , m_outerBorderBefore(0)
67     , m_outerBorderAfter(0)
68     , m_needsCellRecalc(false)
69     , m_hasMultipleCellLevels(false)
70 {
71     // init RenderObject attributes
72     setInline(false); // our object is not Inline
73 }
74
75 RenderTableSection::~RenderTableSection()
76 {
77     clearGrid();
78 }
79
80 void RenderTableSection::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
81 {
82     RenderBox::styleDidChange(diff, oldStyle);
83     propagateStyleToAnonymousChildren();
84
85     // If border was changed, notify table.
86     RenderTable* table = this->table();
87     if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
88         table->invalidateCollapsedBorders();
89 }
90
91 void RenderTableSection::willBeDestroyed()
92 {
93     RenderTable* recalcTable = table();
94     
95     RenderBox::willBeDestroyed();
96     
97     // recalc cell info because RenderTable has unguarded pointers
98     // stored that point to this RenderTableSection.
99     if (recalcTable)
100         recalcTable->setNeedsSectionRecalc();
101 }
102
103 void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
104 {
105     // Make sure we don't append things after :after-generated content if we have it.
106     if (!beforeChild)
107         beforeChild = findAfterContentRenderer();
108
109     if (!child->isTableRow()) {
110         RenderObject* last = beforeChild;
111         if (!last)
112             last = lastChild();
113         if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
114             if (beforeChild == last)
115                 beforeChild = last->firstChild();
116             last->addChild(child, beforeChild);
117             return;
118         }
119
120         if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
121             RenderObject* row = beforeChild->previousSibling();
122             if (row && row->isTableRow() && row->isAnonymous()) {
123                 row->addChild(child);
124                 return;
125             }
126         }
127
128         // If beforeChild is inside an anonymous cell/row, insert into the cell or into
129         // the anonymous row containing it, if there is one.
130         RenderObject* lastBox = last;
131         while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
132             lastBox = lastBox->parent();
133         if (lastBox && lastBox->isAnonymous() && !lastBox->isBeforeOrAfterContent()) {
134             lastBox->addChild(child, beforeChild);
135             return;
136         }
137
138         RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table row */);
139         RefPtr<RenderStyle> newStyle = RenderStyle::create();
140         newStyle->inheritFrom(style());
141         newStyle->setDisplay(TABLE_ROW);
142         row->setStyle(newStyle.release());
143         addChild(row, beforeChild);
144         row->addChild(child);
145         return;
146     }
147
148     if (beforeChild)
149         setNeedsCellRecalc();
150
151     ++m_cRow;
152     m_cCol = 0;
153
154     // make sure we have enough rows
155     if (!ensureRows(m_cRow + 1))
156         return;
157
158     m_grid[m_cRow].rowRenderer = toRenderTableRow(child);
159
160     if (!beforeChild)
161         setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(&m_grid[m_cRow]);
162
163     // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
164     while (beforeChild && beforeChild->parent() != this)
165         beforeChild = beforeChild->parent();
166
167     ASSERT(!beforeChild || beforeChild->isTableRow());
168     RenderBox::addChild(child, beforeChild);
169     toRenderTableRow(child)->updateBeforeAndAfterContent();
170 }
171
172 void RenderTableSection::removeChild(RenderObject* oldChild)
173 {
174     setNeedsCellRecalc();
175     RenderBox::removeChild(oldChild);
176 }
177
178 bool RenderTableSection::ensureRows(int numRows)
179 {
180     int nRows = m_gridRows;
181     if (numRows > nRows) {
182         if (numRows > static_cast<int>(m_grid.size())) {
183             size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);
184             if (static_cast<size_t>(numRows) > maxSize)
185                 return false;
186             m_grid.grow(numRows);
187         }
188         m_gridRows = numRows;
189         int nCols = max(1, table()->numEffCols());
190         for (int r = nRows; r < numRows; r++) {
191             m_grid[r].row = new Row(nCols);
192             m_grid[r].rowRenderer = 0;
193             m_grid[r].baseline = 0;
194             m_grid[r].logicalHeight = Length();
195         }
196     }
197
198     return true;
199 }
200
201 void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
202 {
203     int rSpan = cell->rowSpan();
204     int cSpan = cell->colSpan();
205     Vector<RenderTable::ColumnStruct>& columns = table()->columns();
206     int nCols = columns.size();
207
208     // ### mozilla still seems to do the old HTML way, even for strict DTD
209     // (see the annotation on table cell layouting in the CSS specs and the testcase below:
210     // <TABLE border>
211     // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
212     // <TR><TD colspan="2">5
213     // </TABLE>
214     while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).hasCells() || cellAt(m_cRow, m_cCol).inColSpan))
215         m_cCol++;
216
217     if (rSpan == 1) {
218         // we ignore height settings on rowspan cells
219         Length logicalHeight = cell->style()->logicalHeight();
220         if (logicalHeight.isPositive() || (logicalHeight.isRelative() && logicalHeight.value() >= 0)) {
221             Length cRowLogicalHeight = m_grid[m_cRow].logicalHeight;
222             switch (logicalHeight.type()) {
223                 case Percent:
224                     if (!(cRowLogicalHeight.isPercent()) ||
225                         (cRowLogicalHeight.isPercent() && cRowLogicalHeight.percent() < logicalHeight.percent()))
226                         m_grid[m_cRow].logicalHeight = logicalHeight;
227                         break;
228                 case Fixed:
229                     if (cRowLogicalHeight.type() < Percent ||
230                         (cRowLogicalHeight.isFixed() && cRowLogicalHeight.value() < logicalHeight.value()))
231                         m_grid[m_cRow].logicalHeight = logicalHeight;
232                     break;
233                 case Relative:
234                 default:
235                     break;
236             }
237         }
238     }
239
240     // make sure we have enough rows
241     if (!ensureRows(m_cRow + rSpan))
242         return;
243
244     m_grid[m_cRow].rowRenderer = row;
245
246     int col = m_cCol;
247     // tell the cell where it is
248     bool inColSpan = false;
249     while (cSpan) {
250         int currentSpan;
251         if (m_cCol >= nCols) {
252             table()->appendColumn(cSpan);
253             currentSpan = cSpan;
254         } else {
255             if (cSpan < (int)columns[m_cCol].span)
256                 table()->splitColumn(m_cCol, cSpan);
257             currentSpan = columns[m_cCol].span;
258         }
259         for (int r = 0; r < rSpan; r++) {
260             CellStruct& c = cellAt(m_cRow + r, m_cCol);
261             ASSERT(cell);
262             c.cells.append(cell);
263             // If cells overlap then we take the slow path for painting.
264             if (c.cells.size() > 1)
265                 m_hasMultipleCellLevels = true;
266             if (inColSpan)
267                 c.inColSpan = true;
268         }
269         m_cCol++;
270         cSpan -= currentSpan;
271         inColSpan = true;
272     }
273     cell->setRow(m_cRow);
274     cell->setCol(table()->effColToCol(col));
275 }
276
277 void RenderTableSection::setCellLogicalWidths()
278 {
279     Vector<LayoutUnit>& columnPos = table()->columnPositions();
280
281     LayoutStateMaintainer statePusher(view());
282     
283     for (int i = 0; i < m_gridRows; i++) {
284         Row& row = *m_grid[i].row;
285         int cols = row.size();
286         for (int j = 0; j < cols; j++) {
287             CellStruct& current = row[j];
288             RenderTableCell* cell = current.primaryCell();
289             if (!cell || current.inColSpan)
290               continue;
291             int endCol = j;
292             int cspan = cell->colSpan();
293             while (cspan && endCol < cols) {
294                 ASSERT(endCol < (int)table()->columns().size());
295                 cspan -= table()->columns()[endCol].span;
296                 endCol++;
297             }
298             int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
299             int oldLogicalWidth = cell->logicalWidth();
300             if (w != oldLogicalWidth) {
301                 cell->setNeedsLayout(true);
302                 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
303                     if (!statePusher.didPush()) {
304                         // Technically, we should also push state for the row, but since
305                         // rows don't push a coordinate transform, that's not necessary.
306                         statePusher.push(this, IntSize(x(), y()));
307                     }
308                     cell->repaint();
309                 }
310                 cell->updateLogicalWidth(w);
311             }
312         }
313     }
314     
315     statePusher.pop(); // only pops if we pushed
316 }
317
318 LayoutUnit RenderTableSection::calcRowLogicalHeight()
319 {
320 #ifndef NDEBUG
321     setNeedsLayoutIsForbidden(true);
322 #endif
323
324     ASSERT(!needsLayout());
325
326     RenderTableCell* cell;
327
328     LayoutUnit spacing = table()->vBorderSpacing();
329
330     LayoutStateMaintainer statePusher(view());
331
332     m_rowPos.resize(m_gridRows + 1);
333     m_rowPos[0] = spacing;
334
335     for (int r = 0; r < m_gridRows; r++) {
336         m_rowPos[r + 1] = 0;
337         m_grid[r].baseline = 0;
338         LayoutUnit baseline = 0;
339         LayoutUnit bdesc = 0;
340         LayoutUnit ch = m_grid[r].logicalHeight.calcMinValue(0);
341         LayoutUnit pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);
342
343         m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
344
345         Row* row = m_grid[r].row;
346         int totalCols = row->size();
347
348         for (int c = 0; c < totalCols; c++) {
349             CellStruct& current = cellAt(r, c);
350             cell = current.primaryCell();
351
352             if (!cell || current.inColSpan)
353                 continue;
354
355             if ((cell->row() + cell->rowSpan() - 1) > r)
356                 continue;
357
358             int indx = max(r - cell->rowSpan() + 1, 0);
359
360             if (cell->hasOverrideHeight()) {
361                 if (!statePusher.didPush()) {
362                     // Technically, we should also push state for the row, but since
363                     // rows don't push a coordinate transform, that's not necessary.
364                     statePusher.push(this, locationOffset());
365                 }
366                 cell->clearIntrinsicPadding();
367                 cell->clearOverrideSize();
368                 cell->setChildNeedsLayout(true, false);
369                 cell->layoutIfNeeded();
370             }
371
372             LayoutUnit adjustedPaddingBefore = cell->paddingBefore() - cell->intrinsicPaddingBefore();
373             LayoutUnit adjustedPaddingAfter = cell->paddingAfter() - cell->intrinsicPaddingAfter();
374             LayoutUnit adjustedLogicalHeight = cell->logicalHeight() - (cell->intrinsicPaddingBefore() + cell->intrinsicPaddingAfter());
375
376             // Explicit heights use the border box in quirks mode.  In strict mode do the right
377             // thing and actually add in the border and padding.
378             ch = cell->style()->logicalHeight().calcValue(0) + 
379                 (document()->inQuirksMode() ? 0 : (adjustedPaddingBefore + adjustedPaddingAfter +
380                                                    cell->borderBefore() + cell->borderAfter()));
381             ch = max(ch, adjustedLogicalHeight);
382
383             pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);
384
385             m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
386
387             // find out the baseline
388             EVerticalAlign va = cell->style()->verticalAlign();
389             if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
390                 LayoutUnit b = cell->cellBaselinePosition();
391                 if (b > cell->borderBefore() + cell->paddingBefore()) {
392                     baseline = max(baseline, b - cell->intrinsicPaddingBefore());
393                     bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingBefore()));
394                 }
395             }
396         }
397
398         // do we have baseline aligned elements?
399         if (baseline) {
400             // increase rowheight if baseline requires
401             m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));
402             m_grid[r].baseline = baseline;
403         }
404
405         m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
406     }
407
408 #ifndef NDEBUG
409     setNeedsLayoutIsForbidden(false);
410 #endif
411
412     ASSERT(!needsLayout());
413
414     statePusher.pop();
415
416     return m_rowPos[m_gridRows];
417 }
418
419 void RenderTableSection::layout()
420 {
421     ASSERT(needsLayout());
422
423     LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
424     for (RenderObject* child = children()->firstChild(); child; child = child->nextSibling()) {
425         if (child->isTableRow()) {
426             child->layoutIfNeeded();
427             ASSERT(!child->needsLayout());
428         }
429     }
430     statePusher.pop();
431     setNeedsLayout(false);
432 }
433
434 LayoutUnit RenderTableSection::layoutRows(LayoutUnit toAdd)
435 {
436 #ifndef NDEBUG
437     setNeedsLayoutIsForbidden(true);
438 #endif
439
440     ASSERT(!needsLayout());
441
442     LayoutUnit rHeight;
443     int rindx;
444     int totalRows = m_gridRows;
445     
446     // Set the width of our section now.  The rows will also be this width.
447     setLogicalWidth(table()->contentLogicalWidth());
448     m_overflow.clear();
449     m_overflowingCells.clear();
450     m_forceSlowPaintPathWithOverflowingCell = false;
451
452     if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) {
453         LayoutUnit totalHeight = m_rowPos[totalRows] + toAdd;
454
455         LayoutUnit dh = toAdd;
456         int totalPercent = 0;
457         int numAuto = 0;
458         for (int r = 0; r < totalRows; r++) {
459             if (m_grid[r].logicalHeight.isAuto())
460                 numAuto++;
461             else if (m_grid[r].logicalHeight.isPercent())
462                 totalPercent += m_grid[r].logicalHeight.percent();
463         }
464         if (totalPercent) {
465             // try to satisfy percent
466             LayoutUnit add = 0;
467             totalPercent = min(totalPercent, 100);
468             int rh = m_rowPos[1] - m_rowPos[0];
469             for (int r = 0; r < totalRows; r++) {
470                 if (totalPercent > 0 && m_grid[r].logicalHeight.isPercent()) {
471                     LayoutUnit toAdd = min(dh, static_cast<LayoutUnit>((totalHeight * m_grid[r].logicalHeight.percent() / 100) - rh));
472                     // If toAdd is negative, then we don't want to shrink the row (this bug
473                     // affected Outlook Web Access).
474                     toAdd = max<LayoutUnit>(0, toAdd);
475                     add += toAdd;
476                     dh -= toAdd;
477                     totalPercent -= m_grid[r].logicalHeight.percent();
478                 }
479                 if (r < totalRows - 1)
480                     rh = m_rowPos[r + 2] - m_rowPos[r + 1];
481                 m_rowPos[r + 1] += add;
482             }
483         }
484         if (numAuto) {
485             // distribute over variable cols
486             LayoutUnit add = 0;
487             for (int r = 0; r < totalRows; r++) {
488                 if (numAuto > 0 && m_grid[r].logicalHeight.isAuto()) {
489                     LayoutUnit toAdd = dh / numAuto;
490                     add += toAdd;
491                     dh -= toAdd;
492                     numAuto--;
493                 }
494                 m_rowPos[r + 1] += add;
495             }
496         }
497         if (dh > 0 && m_rowPos[totalRows]) {
498             // if some left overs, distribute equally.
499             LayoutUnit tot = m_rowPos[totalRows];
500             LayoutUnit add = 0;
501             LayoutUnit prev = m_rowPos[0];
502             for (int r = 0; r < totalRows; r++) {
503                 // weight with the original height
504                 add += dh * (m_rowPos[r + 1] - prev) / tot;
505                 prev = m_rowPos[r + 1];
506                 m_rowPos[r + 1] += add;
507             }
508         }
509     }
510
511     LayoutUnit hspacing = table()->hBorderSpacing();
512     LayoutUnit vspacing = table()->vBorderSpacing();
513     LayoutUnit nEffCols = table()->numEffCols();
514
515     LayoutStateMaintainer statePusher(view(), this, LayoutSize(x(), y()), style()->isFlippedBlocksWritingMode());
516
517     for (int r = 0; r < totalRows; r++) {
518         // Set the row's x/y position and width/height.
519         if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
520             rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
521             rowRenderer->setLogicalWidth(logicalWidth());
522             rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
523             rowRenderer->updateLayerTransform();
524         }
525
526         for (int c = 0; c < nEffCols; c++) {
527             CellStruct& cs = cellAt(r, c);
528             RenderTableCell* cell = cs.primaryCell();
529
530             if (!cell || cs.inColSpan)
531                 continue;
532
533             rindx = cell->row();
534             rHeight = m_rowPos[rindx + cell->rowSpan()] - m_rowPos[rindx] - vspacing;
535             
536             // Force percent height children to lay themselves out again.
537             // This will cause these children to grow to fill the cell.
538             // FIXME: There is still more work to do here to fully match WinIE (should
539             // it become necessary to do so).  In quirks mode, WinIE behaves like we
540             // do, but it will clip the cells that spill out of the table section.  In
541             // strict mode, Mozilla and WinIE both regrow the table to accommodate the
542             // new height of the cell (thus letting the percentages cause growth one
543             // time only).  We may also not be handling row-spanning cells correctly.
544             //
545             // Note also the oddity where replaced elements always flex, and yet blocks/tables do
546             // not necessarily flex.  WinIE is crazy and inconsistent, and we can't hope to
547             // match the behavior perfectly, but we'll continue to refine it as we discover new
548             // bugs. :)
549             bool cellChildrenFlex = false;
550             bool flexAllChildren = cell->style()->logicalHeight().isFixed()
551                 || (!table()->style()->logicalHeight().isAuto() && rHeight != cell->logicalHeight());
552
553             for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
554                 if (!o->isText() && o->style()->logicalHeight().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
555                     // Tables with no sections do not flex.
556                     if (!o->isTable() || toRenderTable(o)->hasSections()) {
557                         o->setNeedsLayout(true, false);
558                         cellChildrenFlex = true;
559                     }
560                 }
561             }
562
563             if (HashSet<RenderBox*>* percentHeightDescendants = cell->percentHeightDescendants()) {
564                 HashSet<RenderBox*>::iterator end = percentHeightDescendants->end();
565                 for (HashSet<RenderBox*>::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
566                     RenderBox* box = *it;
567                     if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
568                         continue;
569
570                     while (box != cell) {
571                         if (box->normalChildNeedsLayout())
572                             break;
573                         box->setChildNeedsLayout(true, false);
574                         box = box->containingBlock();
575                         ASSERT(box);
576                         if (!box)
577                             break;
578                     }
579                     cellChildrenFlex = true;
580                 }
581             }
582
583             if (cellChildrenFlex) {
584                 cell->setChildNeedsLayout(true, false);
585                 // Alignment within a cell is based off the calculated
586                 // height, which becomes irrelevant once the cell has
587                 // been resized based off its percentage.
588                 cell->setOverrideHeightFromRowHeight(rHeight);
589                 cell->layoutIfNeeded();
590
591                 // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
592                 EVerticalAlign va = cell->style()->verticalAlign();
593                 if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
594                     LayoutUnit baseline = cell->cellBaselinePosition();
595                     if (baseline > cell->borderBefore() + cell->paddingBefore())
596                         m_grid[r].baseline = max(m_grid[r].baseline, baseline);
597                 }
598             }
599
600             LayoutUnit oldIntrinsicPaddingBefore = cell->intrinsicPaddingBefore();
601             LayoutUnit oldIntrinsicPaddingAfter = cell->intrinsicPaddingAfter();
602             LayoutUnit logicalHeightWithoutIntrinsicPadding = cell->logicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter;
603
604             LayoutUnit intrinsicPaddingBefore = 0;
605             switch (cell->style()->verticalAlign()) {
606                 case SUB:
607                 case SUPER:
608                 case TEXT_TOP:
609                 case TEXT_BOTTOM:
610                 case BASELINE: {
611                     LayoutUnit b = cell->cellBaselinePosition();
612                     if (b > cell->borderBefore() + cell->paddingBefore())
613                         intrinsicPaddingBefore = getBaseline(r) - (b - oldIntrinsicPaddingBefore);
614                     break;
615                 }
616                 case TOP:
617                     break;
618                 case MIDDLE:
619                     intrinsicPaddingBefore = (rHeight - logicalHeightWithoutIntrinsicPadding) / 2;
620                     break;
621                 case BOTTOM:
622                     intrinsicPaddingBefore = rHeight - logicalHeightWithoutIntrinsicPadding;
623                     break;
624                 default:
625                     break;
626             }
627             
628             LayoutUnit intrinsicPaddingAfter = rHeight - logicalHeightWithoutIntrinsicPadding - intrinsicPaddingBefore;
629             cell->setIntrinsicPaddingBefore(intrinsicPaddingBefore);
630             cell->setIntrinsicPaddingAfter(intrinsicPaddingAfter);
631
632             LayoutRect oldCellRect(cell->x(), cell->y() , cell->width(), cell->height());
633
634             LayoutPoint cellLocation(0, m_rowPos[rindx]);
635             if (!style()->isLeftToRightDirection())
636                 cellLocation.setX(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing);
637             else
638                 cellLocation.setX(table()->columnPositions()[c] + hspacing);
639             cell->setLogicalLocation(cellLocation);
640             view()->addLayoutDelta(oldCellRect.location() - cell->location());
641
642             if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter)
643                 cell->setNeedsLayout(true, false);
644
645             if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell->logicalTop()) != cell->pageLogicalOffset())
646                 cell->setChildNeedsLayout(true, false);
647
648             cell->layoutIfNeeded();
649
650             // FIXME: Make pagination work with vertical tables.
651             if (style()->isHorizontalWritingMode() && view()->layoutState()->pageLogicalHeight() && cell->height() != rHeight)
652                 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.
653
654             LayoutSize childOffset(cell->location() - oldCellRect.location());
655             if (childOffset.width() || childOffset.height()) {
656                 view()->addLayoutDelta(childOffset);
657
658                 // If the child moved, we have to repaint it as well as any floating/positioned
659                 // descendants.  An exception is if we need a layout.  In this case, we know we're going to
660                 // repaint ourselves (and the child) anyway.
661                 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
662                     cell->repaintDuringLayoutIfMoved(oldCellRect);
663             }
664         }
665     }
666
667 #ifndef NDEBUG
668     setNeedsLayoutIsForbidden(false);
669 #endif
670
671     ASSERT(!needsLayout());
672
673     setLogicalHeight(m_rowPos[totalRows]);
674
675     unsigned totalCellsCount = nEffCols * totalRows;
676     int maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
677
678 #ifndef NDEBUG
679     bool hasOverflowingCell = false;
680 #endif
681     // Now that our height has been determined, add in overflow from cells.
682     for (int r = 0; r < totalRows; r++) {
683         for (int c = 0; c < nEffCols; c++) {
684             CellStruct& cs = cellAt(r, c);
685             RenderTableCell* cell = cs.primaryCell();
686             if (!cell || cs.inColSpan)
687                 continue;
688             if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
689                 continue;
690             addOverflowFromChild(cell);
691 #ifndef NDEBUG
692             hasOverflowingCell |= cell->hasVisualOverflow();
693 #endif
694             if (cell->hasVisualOverflow() && !m_forceSlowPaintPathWithOverflowingCell) {
695                 m_overflowingCells.add(cell);
696                 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) {
697                     // We need to set m_forcesSlowPaintPath only if there is a least one overflowing cells as the hit testing code rely on this information.
698                     m_forceSlowPaintPathWithOverflowingCell = true;
699                     // The slow path does not make any use of the overflowing cells info, don't hold on to the memory.
700                     m_overflowingCells.clear();
701                 }
702             }
703         }
704     }
705
706     ASSERT(hasOverflowingCell == this->hasOverflowingCell());
707
708     statePusher.pop();
709     return height();
710 }
711
712 LayoutUnit RenderTableSection::calcOuterBorderBefore() const
713 {
714     int totalCols = table()->numEffCols();
715     if (!m_gridRows || !totalCols)
716         return 0;
717
718     unsigned borderWidth = 0;
719
720     const BorderValue& sb = style()->borderBefore();
721     if (sb.style() == BHIDDEN)
722         return -1;
723     if (sb.style() > BHIDDEN)
724         borderWidth = sb.width();
725
726     const BorderValue& rb = firstChild()->style()->borderBefore();
727     if (rb.style() == BHIDDEN)
728         return -1;
729     if (rb.style() > BHIDDEN && rb.width() > borderWidth)
730         borderWidth = rb.width();
731
732     bool allHidden = true;
733     for (int c = 0; c < totalCols; c++) {
734         const CellStruct& current = cellAt(0, c);
735         if (current.inColSpan || !current.hasCells())
736             continue;
737         const BorderValue& cb = current.primaryCell()->style()->borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
738         // FIXME: Don't repeat for the same col group
739         RenderTableCol* colGroup = table()->colElement(c);
740         if (colGroup) {
741             const BorderValue& gb = colGroup->style()->borderBefore();
742             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
743                 continue;
744             allHidden = false;
745             if (gb.style() > BHIDDEN && gb.width() > borderWidth)
746                 borderWidth = gb.width();
747             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
748                 borderWidth = cb.width();
749         } else {
750             if (cb.style() == BHIDDEN)
751                 continue;
752             allHidden = false;
753             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
754                 borderWidth = cb.width();
755         }
756     }
757     if (allHidden)
758         return -1;
759
760     return borderWidth / 2;
761 }
762
763 LayoutUnit RenderTableSection::calcOuterBorderAfter() const
764 {
765     int totalCols = table()->numEffCols();
766     if (!m_gridRows || !totalCols)
767         return 0;
768
769     unsigned borderWidth = 0;
770
771     const BorderValue& sb = style()->borderAfter();
772     if (sb.style() == BHIDDEN)
773         return -1;
774     if (sb.style() > BHIDDEN)
775         borderWidth = sb.width();
776
777     const BorderValue& rb = lastChild()->style()->borderAfter();
778     if (rb.style() == BHIDDEN)
779         return -1;
780     if (rb.style() > BHIDDEN && rb.width() > borderWidth)
781         borderWidth = rb.width();
782
783     bool allHidden = true;
784     for (int c = 0; c < totalCols; c++) {
785         const CellStruct& current = cellAt(m_gridRows - 1, c);
786         if (current.inColSpan || !current.hasCells())
787             continue;
788         const BorderValue& cb = current.primaryCell()->style()->borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
789         // FIXME: Don't repeat for the same col group
790         RenderTableCol* colGroup = table()->colElement(c);
791         if (colGroup) {
792             const BorderValue& gb = colGroup->style()->borderAfter();
793             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
794                 continue;
795             allHidden = false;
796             if (gb.style() > BHIDDEN && gb.width() > borderWidth)
797                 borderWidth = gb.width();
798             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
799                 borderWidth = cb.width();
800         } else {
801             if (cb.style() == BHIDDEN)
802                 continue;
803             allHidden = false;
804             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
805                 borderWidth = cb.width();
806         }
807     }
808     if (allHidden)
809         return -1;
810
811     return (borderWidth + 1) / 2;
812 }
813
814 LayoutUnit RenderTableSection::calcOuterBorderStart() const
815 {
816     int totalCols = table()->numEffCols();
817     if (!m_gridRows || !totalCols)
818         return 0;
819
820     unsigned borderWidth = 0;
821
822     const BorderValue& sb = style()->borderStart();
823     if (sb.style() == BHIDDEN)
824         return -1;
825     if (sb.style() > BHIDDEN)
826         borderWidth = sb.width();
827
828     if (RenderTableCol* colGroup = table()->colElement(0)) {
829         const BorderValue& gb = colGroup->style()->borderStart();
830         if (gb.style() == BHIDDEN)
831             return -1;
832         if (gb.style() > BHIDDEN && gb.width() > borderWidth)
833             borderWidth = gb.width();
834     }
835
836     bool allHidden = true;
837     for (int r = 0; r < m_gridRows; r++) {
838         const CellStruct& current = cellAt(r, 0);
839         if (!current.hasCells())
840             continue;
841         // FIXME: Don't repeat for the same cell
842         const BorderValue& cb = current.primaryCell()->style()->borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
843         const BorderValue& rb = current.primaryCell()->parent()->style()->borderStart();
844         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
845             continue;
846         allHidden = false;
847         if (cb.style() > BHIDDEN && cb.width() > borderWidth)
848             borderWidth = cb.width();
849         if (rb.style() > BHIDDEN && rb.width() > borderWidth)
850             borderWidth = rb.width();
851     }
852     if (allHidden)
853         return -1;
854
855     return (borderWidth + (table()->style()->isLeftToRightDirection() ? 0 : 1)) / 2;
856 }
857
858 LayoutUnit RenderTableSection::calcOuterBorderEnd() const
859 {
860     int totalCols = table()->numEffCols();
861     if (!m_gridRows || !totalCols)
862         return 0;
863
864     unsigned borderWidth = 0;
865
866     const BorderValue& sb = style()->borderEnd();
867     if (sb.style() == BHIDDEN)
868         return -1;
869     if (sb.style() > BHIDDEN)
870         borderWidth = sb.width();
871
872     if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
873         const BorderValue& gb = colGroup->style()->borderEnd();
874         if (gb.style() == BHIDDEN)
875             return -1;
876         if (gb.style() > BHIDDEN && gb.width() > borderWidth)
877             borderWidth = gb.width();
878     }
879
880     bool allHidden = true;
881     for (int r = 0; r < m_gridRows; r++) {
882         const CellStruct& current = cellAt(r, totalCols - 1);
883         if (!current.hasCells())
884             continue;
885         // FIXME: Don't repeat for the same cell
886         const BorderValue& cb = current.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
887         const BorderValue& rb = current.primaryCell()->parent()->style()->borderEnd();
888         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
889             continue;
890         allHidden = false;
891         if (cb.style() > BHIDDEN && cb.width() > borderWidth)
892             borderWidth = cb.width();
893         if (rb.style() > BHIDDEN && rb.width() > borderWidth)
894             borderWidth = rb.width();
895     }
896     if (allHidden)
897         return -1;
898
899     return (borderWidth + (table()->style()->isLeftToRightDirection() ? 1 : 0)) / 2;
900 }
901
902 void RenderTableSection::recalcOuterBorder()
903 {
904     m_outerBorderBefore = calcOuterBorderBefore();
905     m_outerBorderAfter = calcOuterBorderAfter();
906     m_outerBorderStart = calcOuterBorderStart();
907     m_outerBorderEnd = calcOuterBorderEnd();
908 }
909
910 LayoutUnit RenderTableSection::firstLineBoxBaseline() const
911 {
912     if (!m_gridRows)
913         return -1;
914
915     LayoutUnit firstLineBaseline = m_grid[0].baseline;
916     if (firstLineBaseline)
917         return firstLineBaseline + m_rowPos[0];
918
919     firstLineBaseline = -1;
920     Row* firstRow = m_grid[0].row;
921     for (size_t i = 0; i < firstRow->size(); ++i) {
922         CellStruct& cs = firstRow->at(i);
923         RenderTableCell* cell = cs.primaryCell();
924         if (cell)
925             firstLineBaseline = max(firstLineBaseline, cell->logicalTop() + cell->paddingBefore() + cell->borderBefore() + cell->contentLogicalHeight());
926     }
927
928     return firstLineBaseline;
929 }
930
931 void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
932 {
933     // put this back in when all layout tests can handle it
934     // ASSERT(!needsLayout());
935     // avoid crashing on bugs that cause us to paint with dirty layout
936     if (needsLayout())
937         return;
938     
939     unsigned totalRows = m_gridRows;
940     unsigned totalCols = table()->columns().size();
941
942     if (!totalRows || !totalCols)
943         return;
944
945     LayoutPoint adjustedPaintOffset = paintOffset + location();
946
947     PaintPhase phase = paintInfo.phase;
948     bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
949     paintObject(paintInfo, adjustedPaintOffset);
950     if (pushedClip)
951         popContentsClip(paintInfo, phase, adjustedPaintOffset);
952 }
953
954 static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
955 {
956     return elem1->row() < elem2->row();
957 }
958
959 // This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
960 // to sort both on rows and columns to properly repaint.
961 static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
962 {
963     if (elem1->row() != elem2->row())
964         return elem1->row() < elem2->row();
965
966     return elem1->col() < elem2->col();
967 }
968
969 void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
970 {
971     LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
972     PaintPhase paintPhase = paintInfo.phase;
973     RenderTableRow* row = toRenderTableRow(cell->parent());
974
975     if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
976         // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
977         // the column group, column, row group, row, and then the cell.
978         RenderObject* col = table()->colElement(cell->col());
979         RenderObject* colGroup = 0;
980         if (col && col->parent()->style()->display() == TABLE_COLUMN_GROUP)
981             colGroup = col->parent();
982
983         // Column groups and columns first.
984         // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
985         // the stack, since we have already opened a transparency layer (potentially) for the table row group.
986         // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
987         // cell.
988         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, colGroup);
989         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, col);
990
991         // Paint the row group next.
992         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, this);
993
994         // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
995         // painting the row background for the cell.
996         if (!row->hasSelfPaintingLayer())
997             cell->paintBackgroundsBehindCell(paintInfo, cellPoint, row);
998     }
999     if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
1000         cell->paint(paintInfo, cellPoint);
1001 }
1002
1003 void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1004 {
1005     // Check which rows and cols are visible and only paint these.
1006     unsigned totalRows = m_gridRows;
1007     unsigned totalCols = table()->columns().size();
1008
1009     PaintPhase paintPhase = paintInfo.phase;
1010
1011     LayoutUnit os = 2 * maximalOutlineSize(paintPhase);
1012     unsigned startrow = 0;
1013     unsigned endrow = totalRows;
1014
1015     LayoutRect localRepaintRect = paintInfo.rect;
1016     localRepaintRect.moveBy(-paintOffset);
1017     if (style()->isFlippedBlocksWritingMode()) {
1018         if (style()->isHorizontalWritingMode())
1019             localRepaintRect.setY(height() - localRepaintRect.maxY());
1020         else
1021             localRepaintRect.setX(width() - localRepaintRect.maxX());
1022     }
1023
1024     if (!m_forceSlowPaintPathWithOverflowingCell) {
1025         LayoutUnit before = (style()->isHorizontalWritingMode() ? localRepaintRect.y() : localRepaintRect.x()) - os;
1026         // binary search to find a row
1027         startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), before) - m_rowPos.begin();
1028
1029         // 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] >  before)))
1033           --startrow;
1034
1035         LayoutUnit after = (style()->isHorizontalWritingMode() ? localRepaintRect.maxY() : localRepaintRect.maxX()) + os;
1036         endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), after) - m_rowPos.begin();
1037         if (endrow == m_rowPos.size())
1038           --endrow;
1039
1040         if (!endrow && m_rowPos[0] - table()->outerBorderBefore() <= after)
1041             ++endrow;
1042     }
1043
1044     unsigned startcol = 0;
1045     unsigned endcol = totalCols;
1046     // FIXME: Implement RTL.
1047     if (!m_forceSlowPaintPathWithOverflowingCell && style()->isLeftToRightDirection()) {
1048         LayoutUnit start = (style()->isHorizontalWritingMode() ? localRepaintRect.x() : localRepaintRect.y()) - os;
1049         Vector<LayoutUnit>& columnPos = table()->columnPositions();
1050         startcol = std::lower_bound(columnPos.begin(), columnPos.end(), start) - columnPos.begin();
1051         if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > start)))
1052             --startcol;
1053
1054         LayoutUnit end = (style()->isHorizontalWritingMode() ? localRepaintRect.maxX() : localRepaintRect.maxY()) + os;
1055         endcol = std::lower_bound(columnPos.begin(), columnPos.end(), end) - columnPos.begin();
1056         if (endcol == columnPos.size())
1057             --endcol;
1058
1059         if (!endcol && columnPos[0] - table()->outerBorderStart() <= end)
1060             ++endcol;
1061     }
1062     if (startcol < endcol) {
1063         if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
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();
1069                     if (!cell || (r > startrow && primaryCellAt(r - 1, c) == cell) || (c > startcol && primaryCellAt(r, c - 1) == cell))
1070                         continue;
1071                     paintCell(cell, paintInfo, paintOffset);
1072                 }
1073             }
1074         } else {
1075             // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
1076             ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
1077
1078             // To make sure we properly repaint the section, we repaint all the overflowing cells that we collected.
1079             Vector<RenderTableCell*> cells;
1080             copyToVector(m_overflowingCells, cells);
1081
1082             HashSet<RenderTableCell*> spanningCells;
1083
1084             for (unsigned r = startrow; r < endrow; r++) {
1085                 for (unsigned c = startcol; c < endcol; c++) {
1086                     CellStruct& current = cellAt(r, c);
1087                     if (!current.hasCells())
1088                         continue;
1089                     for (unsigned i = 0; i < current.cells.size(); ++i) {
1090                         if (m_overflowingCells.contains(current.cells[i]))
1091                             continue;
1092
1093                         if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
1094                             if (spanningCells.contains(current.cells[i]))
1095                                 continue;
1096                             spanningCells.add(current.cells[i]);
1097                         }
1098
1099                         cells.append(current.cells[i]);
1100                     }
1101                 }
1102             }
1103
1104             // Sort the dirty cells by paint order.
1105             if (!m_overflowingCells.size())
1106                 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
1107             else
1108                 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
1109
1110             int size = cells.size();
1111             // Paint the cells.
1112             for (int i = 0; i < size; ++i)
1113                 paintCell(cells[i], paintInfo, paintOffset);
1114         }
1115     }
1116 }
1117
1118 void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
1119 {
1120     // FIXME: Examine cells and repaint only the rect the image paints in.
1121     repaint();
1122 }
1123
1124 void RenderTableSection::recalcCells()
1125 {
1126     m_cCol = 0;
1127     m_cRow = -1;
1128     clearGrid();
1129     m_gridRows = 0;
1130
1131     for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
1132         if (row->isTableRow()) {
1133             m_cRow++;
1134             m_cCol = 0;
1135             if (!ensureRows(m_cRow + 1))
1136                 break;
1137             
1138             RenderTableRow* tableRow = toRenderTableRow(row);
1139             m_grid[m_cRow].rowRenderer = tableRow;
1140             setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(&m_grid[m_cRow]);
1141
1142             for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
1143                 if (cell->isTableCell())
1144                     addCell(toRenderTableCell(cell), tableRow);
1145             }
1146         }
1147     }
1148     m_needsCellRecalc = false;
1149     setNeedsLayout(true);
1150 }
1151
1152 void RenderTableSection::setNeedsCellRecalc()
1153 {
1154     m_needsCellRecalc = true;
1155     if (RenderTable* t = table())
1156         t->setNeedsSectionRecalc();
1157 }
1158
1159 void RenderTableSection::clearGrid()
1160 {
1161     int rows = m_gridRows;
1162     while (rows--)
1163         delete m_grid[rows].row;
1164 }
1165
1166 int RenderTableSection::numColumns() const
1167 {
1168     int result = 0;
1169     
1170     for (int r = 0; r < m_gridRows; ++r) {
1171         for (int c = result; c < table()->numEffCols(); ++c) {
1172             const CellStruct& cell = cellAt(r, c);
1173             if (cell.hasCells() || cell.inColSpan)
1174                 result = c;
1175         }
1176     }
1177     
1178     return result + 1;
1179 }
1180
1181 void RenderTableSection::appendColumn(int pos)
1182 {
1183     for (int row = 0; row < m_gridRows; ++row)
1184         m_grid[row].row->resize(pos + 1);
1185 }
1186
1187 void RenderTableSection::splitColumn(int pos, int first)
1188 {
1189     ASSERT(!m_needsCellRecalc);
1190
1191     if (m_cCol > pos)
1192         m_cCol++;
1193     for (int row = 0; row < m_gridRows; ++row) {
1194         Row& r = *m_grid[row].row;
1195         r.insert(pos + 1, CellStruct());
1196         if (r[pos].hasCells()) {
1197             r[pos + 1].cells.append(r[pos].cells);
1198             RenderTableCell* cell = r[pos].primaryCell();
1199             ASSERT(cell);
1200             int colleft = cell->colSpan() - r[pos].inColSpan;
1201             if (first > colleft)
1202               r[pos + 1].inColSpan = 0;
1203             else
1204               r[pos + 1].inColSpan = first + r[pos].inColSpan;
1205         } else {
1206             r[pos + 1].inColSpan = 0;
1207         }
1208     }
1209 }
1210
1211 // Hit Testing
1212 bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1213 {
1214     // If we have no children then we have nothing to do.
1215     if (!firstChild())
1216         return false;
1217
1218     // Table sections cannot ever be hit tested.  Effectively they do not exist.
1219     // Just forward to our children always.
1220     LayoutPoint adjustedLocation = accumulatedOffset + location();
1221
1222     if (hasOverflowClip() && !overflowClipRect(adjustedLocation, result.region()).intersects(result.rectForPoint(pointInContainer)))
1223         return false;
1224
1225     if (hasOverflowingCell()) {
1226         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1227             // FIXME: We have to skip over inline flows, since they can show up inside table rows
1228             // at the moment (a demoted inline <form> for example). If we ever implement a
1229             // table-specific hit-test method (which we should do for performance reasons anyway),
1230             // then we can remove this check.
1231             if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer()) {
1232                 LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
1233                 if (child->nodeAtPoint(request, result, pointInContainer, childPoint, action)) {
1234                     updateHitTestResult(result, toLayoutPoint(pointInContainer - childPoint));
1235                     return true;
1236                 }
1237             }
1238         }
1239         return false;
1240     }
1241
1242     LayoutPoint location = pointInContainer - toLayoutSize(adjustedLocation);
1243     if (style()->isFlippedBlocksWritingMode()) {
1244         if (style()->isHorizontalWritingMode())
1245             location.setY(height() - location.y());
1246         else
1247             location.setX(width() - location.x());
1248     }
1249
1250     LayoutUnit offsetInColumnDirection = style()->isHorizontalWritingMode() ? location.y() : location.x();
1251     // Find the first row that starts after offsetInColumnDirection.
1252     unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), offsetInColumnDirection) - m_rowPos.begin();
1253     if (nextRow == m_rowPos.size())
1254         return false;
1255     // Now set hitRow to the index of the hit row, or 0.
1256     unsigned hitRow = nextRow > 0 ? nextRow - 1 : 0;
1257
1258     Vector<LayoutUnit>& columnPos = table()->columnPositions();
1259     LayoutUnit offsetInRowDirection = style()->isHorizontalWritingMode() ? location.x() : location.y();
1260     if (!style()->isLeftToRightDirection())
1261         offsetInRowDirection = columnPos[columnPos.size() - 1] - offsetInRowDirection;
1262
1263     unsigned nextColumn = std::lower_bound(columnPos.begin(), columnPos.end(), offsetInRowDirection) - columnPos.begin();
1264     if (nextColumn == columnPos.size())
1265         return false;
1266     unsigned hitColumn = nextColumn > 0 ? nextColumn - 1 : 0;
1267
1268     CellStruct& current = cellAt(hitRow, hitColumn);
1269
1270     // If the cell is empty, there's nothing to do
1271     if (!current.hasCells())
1272         return false;
1273
1274     for (int i = current.cells.size() - 1; i >= 0; --i) {
1275         RenderTableCell* cell = current.cells[i];
1276         LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
1277         if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, pointInContainer, cellPoint, action)) {
1278             updateHitTestResult(result, toLayoutPoint(pointInContainer - cellPoint));
1279             return true;
1280         }
1281     }
1282     return false;
1283
1284 }
1285
1286 } // namespace WebCore