2009-01-23 David Hyatt <hyatt@apple.com>
[WebKit-https.git] / 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 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
29 #include "CachedImage.h"
30 #include "Document.h"
31 #include "HTMLNames.h"
32 #include "RenderTableCell.h"
33 #include "RenderTableCol.h"
34 #include "RenderTableRow.h"
35 #include "RenderView.h"
36 #include <limits>
37 #include <wtf/Vector.h>
38
39 using namespace std;
40
41 namespace WebCore {
42
43 using namespace HTMLNames;
44
45 RenderTableSection::RenderTableSection(Node* node)
46     : RenderContainer(node)
47     , m_gridRows(0)
48     , m_cCol(0)
49     , m_cRow(-1)
50     , m_needsCellRecalc(false)
51     , m_outerBorderLeft(0)
52     , m_outerBorderRight(0)
53     , m_outerBorderTop(0)
54     , m_outerBorderBottom(0)
55     , m_overflowLeft(0)
56     , m_overflowWidth(0)
57     , m_overflowTop(0)
58     , m_overflowHeight(0)
59     , m_hasOverflowingCell(false)
60 {
61     // init RenderObject attributes
62     setInline(false);   // our object is not Inline
63 }
64
65 RenderTableSection::~RenderTableSection()
66 {
67     clearGrid();
68 }
69
70 void RenderTableSection::destroy()
71 {
72     RenderTable* recalcTable = table();
73     
74     RenderContainer::destroy();
75     
76     // recalc cell info because RenderTable has unguarded pointers
77     // stored that point to this RenderTableSection.
78     if (recalcTable)
79         recalcTable->setNeedsSectionRecalc();
80 }
81
82 void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
83 {
84     // Make sure we don't append things after :after-generated content if we have it.
85     if (!beforeChild && isAfterContent(lastChild()))
86         beforeChild = lastChild();
87
88     bool isTableSection = element() && (element()->hasTagName(theadTag) || element()->hasTagName(tbodyTag) || element()->hasTagName(tfootTag));
89
90     if (!child->isTableRow()) {
91         if (isTableSection && child->element() && child->element()->hasTagName(formTag) && document()->isHTMLDocument()) {
92             RenderContainer::addChild(child, beforeChild);
93             return;
94         }
95
96         RenderObject* last = beforeChild;
97         if (!last)
98             last = lastChild();
99         if (last && last->isAnonymous()) {
100             last->addChild(child);
101             return;
102         }
103
104         // If beforeChild is inside an anonymous cell/row, insert into the cell or into
105         // the anonymous row containing it, if there is one.
106         RenderObject* lastBox = last;
107         while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
108             lastBox = lastBox->parent();
109         if (lastBox && lastBox->isAnonymous()) {
110             lastBox->addChild(child, beforeChild);
111             return;
112         }
113
114         RenderObject* row = new (renderArena()) RenderTableRow(document() /* anonymous table */);
115         RefPtr<RenderStyle> newStyle = RenderStyle::create();
116         newStyle->inheritFrom(style());
117         newStyle->setDisplay(TABLE_ROW);
118         row->setStyle(newStyle.release());
119         addChild(row, beforeChild);
120         row->addChild(child);
121         return;
122     }
123
124     if (beforeChild)
125         setNeedsCellRecalc();
126
127     ++m_cRow;
128     m_cCol = 0;
129
130     // make sure we have enough rows
131     if (!ensureRows(m_cRow + 1))
132         return;
133
134     m_grid[m_cRow].rowRenderer = static_cast<RenderTableRow*>(child);
135
136     if (!beforeChild) {
137         m_grid[m_cRow].height = child->style()->height();
138         if (m_grid[m_cRow].height.isRelative())
139             m_grid[m_cRow].height = Length();
140     }
141
142     // If the next renderer is actually wrapped in an anonymous table row, we need to go up and find that.
143     while (beforeChild && beforeChild->parent() != this)
144         beforeChild = beforeChild->parent();
145
146     ASSERT(!beforeChild || beforeChild->isTableRow() || isTableSection && beforeChild->element() && beforeChild->element()->hasTagName(formTag) && document()->isHTMLDocument());
147     RenderContainer::addChild(child, beforeChild);
148 }
149
150 bool RenderTableSection::ensureRows(int numRows)
151 {
152     int nRows = m_gridRows;
153     if (numRows > nRows) {
154         if (numRows > static_cast<int>(m_grid.size())) {
155             size_t maxSize = numeric_limits<size_t>::max() / sizeof(RowStruct);
156             if (static_cast<size_t>(numRows) > maxSize)
157                 return false;
158             m_grid.grow(numRows);
159         }
160         m_gridRows = numRows;
161         int nCols = max(1, table()->numEffCols());
162         CellStruct emptyCellStruct;
163         emptyCellStruct.cell = 0;
164         emptyCellStruct.inColSpan = false;
165         for (int r = nRows; r < numRows; r++) {
166             m_grid[r].row = new Row(nCols);
167             m_grid[r].row->fill(emptyCellStruct);
168             m_grid[r].rowRenderer = 0;
169             m_grid[r].baseline = 0;
170             m_grid[r].height = Length();
171         }
172     }
173
174     return true;
175 }
176
177 void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
178 {
179     int rSpan = cell->rowSpan();
180     int cSpan = cell->colSpan();
181     Vector<RenderTable::ColumnStruct>& columns = table()->columns();
182     int nCols = columns.size();
183
184     // ### mozilla still seems to do the old HTML way, even for strict DTD
185     // (see the annotation on table cell layouting in the CSS specs and the testcase below:
186     // <TABLE border>
187     // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
188     // <TR><TD colspan="2">5
189     // </TABLE>
190
191     while (m_cCol < nCols && (cellAt(m_cRow, m_cCol).cell || cellAt(m_cRow, m_cCol).inColSpan))
192         m_cCol++;
193
194     if (rSpan == 1) {
195         // we ignore height settings on rowspan cells
196         Length height = cell->style()->height();
197         if (height.isPositive() || (height.isRelative() && height.value() >= 0)) {
198             Length cRowHeight = m_grid[m_cRow].height;
199             switch (height.type()) {
200                 case Percent:
201                     if (!(cRowHeight.isPercent()) ||
202                         (cRowHeight.isPercent() && cRowHeight.rawValue() < height.rawValue()))
203                         m_grid[m_cRow].height = height;
204                         break;
205                 case Fixed:
206                     if (cRowHeight.type() < Percent ||
207                         (cRowHeight.isFixed() && cRowHeight.value() < height.value()))
208                         m_grid[m_cRow].height = height;
209                     break;
210                 case Relative:
211                 default:
212                     break;
213             }
214         }
215     }
216
217     // make sure we have enough rows
218     if (!ensureRows(m_cRow + rSpan))
219         return;
220
221     m_grid[m_cRow].rowRenderer = row;
222
223     int col = m_cCol;
224     // tell the cell where it is
225     CellStruct currentCell;
226     currentCell.cell = cell;
227     currentCell.inColSpan = false;
228     while (cSpan) {
229         int currentSpan;
230         if (m_cCol >= nCols) {
231             table()->appendColumn(cSpan);
232             currentSpan = cSpan;
233         } else {
234             if (cSpan < columns[m_cCol].span)
235                 table()->splitColumn(m_cCol, cSpan);
236             currentSpan = columns[m_cCol].span;
237         }
238
239         for (int r = 0; r < rSpan; r++) {
240             CellStruct& c = cellAt(m_cRow + r, m_cCol);
241             if (currentCell.cell && !c.cell)
242                 c.cell = currentCell.cell;
243             if (currentCell.inColSpan)
244                 c.inColSpan = true;
245         }
246         m_cCol++;
247         cSpan -= currentSpan;
248         currentCell.cell = 0;
249         currentCell.inColSpan = true;
250     }
251     if (cell) {
252         cell->setRow(m_cRow);
253         cell->setCol(table()->effColToCol(col));
254     }
255 }
256
257 void RenderTableSection::setCellWidths()
258 {
259     Vector<int>& columnPos = table()->columnPositions();
260
261     LayoutStateMaintainer statePusher(view());
262     
263     for (int i = 0; i < m_gridRows; i++) {
264         Row& row = *m_grid[i].row;
265         int cols = row.size();
266         for (int j = 0; j < cols; j++) {
267             CellStruct current = row[j];
268             RenderTableCell* cell = current.cell;
269
270             if (!cell)
271                 continue;
272             int endCol = j;
273             int cspan = cell->colSpan();
274             while (cspan && endCol < cols) {
275                 cspan -= table()->columns()[endCol].span;
276                 endCol++;
277             }
278             int w = columnPos[endCol] - columnPos[j] - table()->hBorderSpacing();
279             int oldWidth = cell->width();
280             if (w != oldWidth) {
281                 cell->setNeedsLayout(true);
282                 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout()) {
283                     if (!statePusher.didPush()) {
284                         // Technically, we should also push state for the row, but since
285                         // rows don't push a coordinate transform, that's not necessary.
286                         statePusher.push(this, IntSize(x(), y()));
287                     }
288                     cell->repaint();
289                 }
290                 cell->updateWidth(w);
291             }
292         }
293     }
294     
295     statePusher.pop();  // only pops if we pushed
296 }
297
298 int RenderTableSection::calcRowHeight()
299 {
300     RenderTableCell* cell;
301
302     int spacing = table()->vBorderSpacing();
303
304     LayoutStateMaintainer statePusher(view());
305
306     m_rowPos.resize(m_gridRows + 1);
307     m_rowPos[0] = spacing;
308
309     for (int r = 0; r < m_gridRows; r++) {
310         m_rowPos[r + 1] = 0;
311         m_grid[r].baseline = 0;
312         int baseline = 0;
313         int bdesc = 0;
314         int ch = m_grid[r].height.calcMinValue(0);
315         int pos = m_rowPos[r] + ch + (m_grid[r].rowRenderer ? spacing : 0);
316
317         m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
318
319         Row* row = m_grid[r].row;
320         int totalCols = row->size();
321
322         for (int c = 0; c < totalCols; c++) {
323             CellStruct current = cellAt(r, c);
324             cell = current.cell;
325             if (!cell || current.inColSpan)
326                 continue;
327             if (r < m_gridRows - 1 && cellAt(r + 1, c).cell == cell)
328                 continue;
329
330             int indx = max(r - cell->rowSpan() + 1, 0);
331
332             if (cell->overrideSize() != -1) {
333                 if (!statePusher.didPush()) {
334                     // Technically, we should also push state for the row, but since
335                     // rows don't push a coordinate transform, that's not necessary.
336                     statePusher.push(this, IntSize(x(), y()));
337                 }
338                 cell->setOverrideSize(-1);
339                 cell->setChildNeedsLayout(true, false);
340                 cell->layoutIfNeeded();
341             }
342             
343             int adjustedPaddingTop = cell->paddingTop() - cell->intrinsicPaddingTop();
344             int adjustedPaddingBottom = cell->paddingBottom() - cell->intrinsicPaddingBottom();
345             int adjustedHeight = cell->height() - (cell->intrinsicPaddingTop() + cell->intrinsicPaddingBottom());
346         
347             // Explicit heights use the border box in quirks mode.  In strict mode do the right
348             // thing and actually add in the border and padding.
349             ch = cell->style()->height().calcValue(0) + 
350                 (cell->style()->htmlHacks() ? 0 : (adjustedPaddingTop + adjustedPaddingBottom +
351                                                    cell->borderTop() + cell->borderBottom()));
352             ch = max(ch, adjustedHeight);
353
354             pos = m_rowPos[indx] + ch + (m_grid[r].rowRenderer ? spacing : 0);
355
356             m_rowPos[r + 1] = max(m_rowPos[r + 1], pos);
357
358             // find out the baseline
359             EVerticalAlign va = cell->style()->verticalAlign();
360             if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
361                 int b = cell->baselinePosition();
362                 if (b > cell->borderTop() + cell->paddingTop()) {
363                     baseline = max(baseline, b - cell->intrinsicPaddingTop());
364                     bdesc = max(bdesc, m_rowPos[indx] + ch - (b - cell->intrinsicPaddingTop()));
365                 }
366             }
367         }
368
369         //do we have baseline aligned elements?
370         if (baseline) {
371             // increase rowheight if baseline requires
372             m_rowPos[r + 1] = max(m_rowPos[r + 1], baseline + bdesc + (m_grid[r].rowRenderer ? spacing : 0));
373             m_grid[r].baseline = baseline;
374         }
375
376         m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
377     }
378
379     statePusher.pop();
380
381     return m_rowPos[m_gridRows];
382 }
383
384 int RenderTableSection::layoutRows(int toAdd)
385 {
386     int rHeight;
387     int rindx;
388     int totalRows = m_gridRows;
389     
390     // Set the width of our section now.  The rows will also be this width.
391     setWidth(table()->contentWidth());
392     m_overflowLeft = 0;
393     m_overflowWidth = width();
394     m_overflowTop = 0;
395     m_overflowHeight = 0;
396     m_hasOverflowingCell = false;
397
398     if (toAdd && totalRows && (m_rowPos[totalRows] || !nextSibling())) {
399         int totalHeight = m_rowPos[totalRows] + toAdd;
400
401         int dh = toAdd;
402         int totalPercent = 0;
403         int numAuto = 0;
404         for (int r = 0; r < totalRows; r++) {
405             if (m_grid[r].height.isAuto())
406                 numAuto++;
407             else if (m_grid[r].height.isPercent())
408                 totalPercent += m_grid[r].height.rawValue();
409         }
410         if (totalPercent) {
411             // try to satisfy percent
412             int add = 0;
413             totalPercent = min(totalPercent, 100 * percentScaleFactor);
414             int rh = m_rowPos[1] - m_rowPos[0];
415             for (int r = 0; r < totalRows; r++) {
416                 if (totalPercent > 0 && m_grid[r].height.isPercent()) {
417                     int toAdd = min(dh, (totalHeight * m_grid[r].height.rawValue() / (100 * percentScaleFactor)) - rh);
418                     // If toAdd is negative, then we don't want to shrink the row (this bug
419                     // affected Outlook Web Access).
420                     toAdd = max(0, toAdd);
421                     add += toAdd;
422                     dh -= toAdd;
423                     totalPercent -= m_grid[r].height.rawValue();
424                 }
425                 if (r < totalRows - 1)
426                     rh = m_rowPos[r + 2] - m_rowPos[r + 1];
427                 m_rowPos[r + 1] += add;
428             }
429         }
430         if (numAuto) {
431             // distribute over variable cols
432             int add = 0;
433             for (int r = 0; r < totalRows; r++) {
434                 if (numAuto > 0 && m_grid[r].height.isAuto()) {
435                     int toAdd = dh / numAuto;
436                     add += toAdd;
437                     dh -= toAdd;
438                     numAuto--;
439                 }
440                 m_rowPos[r + 1] += add;
441             }
442         }
443         if (dh > 0 && m_rowPos[totalRows]) {
444             // if some left overs, distribute equally.
445             int tot = m_rowPos[totalRows];
446             int add = 0;
447             int prev = m_rowPos[0];
448             for (int r = 0; r < totalRows; r++) {
449                 //weight with the original height
450                 add += dh * (m_rowPos[r + 1] - prev) / tot;
451                 prev = m_rowPos[r + 1];
452                 m_rowPos[r + 1] += add;
453             }
454         }
455     }
456
457     int hspacing = table()->hBorderSpacing();
458     int vspacing = table()->vBorderSpacing();
459     int nEffCols = table()->numEffCols();
460
461     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()));
462
463     for (int r = 0; r < totalRows; r++) {
464         // Set the row's x/y position and width/height.
465         if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
466             rowRenderer->setLocation(0, m_rowPos[r]);
467             rowRenderer->setWidth(width());
468             rowRenderer->setHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
469         }
470
471         for (int c = 0; c < nEffCols; c++) {
472             RenderTableCell* cell = cellAt(r, c).cell;
473             
474             if (!cell)
475                 continue;
476             if (r < totalRows - 1 && cell == cellAt(r + 1, c).cell)
477                 continue;
478
479             rindx = max(0, r - cell->rowSpan() + 1);
480
481             rHeight = m_rowPos[r + 1] - m_rowPos[rindx] - vspacing;
482             
483             // Force percent height children to lay themselves out again.
484             // This will cause these children to grow to fill the cell.
485             // FIXME: There is still more work to do here to fully match WinIE (should
486             // it become necessary to do so).  In quirks mode, WinIE behaves like we
487             // do, but it will clip the cells that spill out of the table section.  In
488             // strict mode, Mozilla and WinIE both regrow the table to accommodate the
489             // new height of the cell (thus letting the percentages cause growth one
490             // time only).  We may also not be handling row-spanning cells correctly.
491             //
492             // Note also the oddity where replaced elements always flex, and yet blocks/tables do
493             // not necessarily flex.  WinIE is crazy and inconsistent, and we can't hope to
494             // match the behavior perfectly, but we'll continue to refine it as we discover new
495             // bugs. :)
496             bool cellChildrenFlex = false;
497             bool flexAllChildren = cell->style()->height().isFixed() || 
498                 (!table()->style()->height().isAuto() && rHeight != cell->height());
499
500             for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
501                 if (!o->isText() && o->style()->height().isPercent() && (o->isReplaced() || (o->isBox() && RenderBox::toRenderBox(o)->scrollsOverflow()) || flexAllChildren)) {
502                     // Tables with no sections do not flex.
503                     if (!o->isTable() || static_cast<RenderTable*>(o)->hasSections()) {
504                         o->setNeedsLayout(true, false);
505                         cell->setChildNeedsLayout(true, false);
506                         cellChildrenFlex = true;
507                     }
508                 }
509             }
510             
511             if (cellChildrenFlex) {
512                 // Alignment within a cell is based off the calculated
513                 // height, which becomes irrelevant once the cell has
514                 // been resized based off its percentage.
515                 cell->setOverrideSize(max(0, 
516                                            rHeight - cell->borderTop() - cell->paddingTop() - 
517                                                      cell->borderBottom() - cell->paddingBottom()));
518                 cell->layoutIfNeeded();
519                 
520                 // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
521                 EVerticalAlign va = cell->style()->verticalAlign();
522                 if (va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB) {
523                     int b = cell->baselinePosition();
524                     if (b > cell->borderTop() + cell->paddingTop())
525                         m_grid[r].baseline = max(m_grid[r].baseline, b);
526                 }
527             }
528             
529             int oldTe = cell->intrinsicPaddingTop();
530             int oldBe = cell->intrinsicPaddingBottom();
531             int heightWithoutIntrinsicPadding = cell->height() - oldTe - oldBe;
532             
533             int te = 0;
534             switch (cell->style()->verticalAlign()) {
535                 case SUB:
536                 case SUPER:
537                 case TEXT_TOP:
538                 case TEXT_BOTTOM:
539                 case BASELINE: {
540                     int b = cell->baselinePosition();
541                     if (b > cell->borderTop() + cell->paddingTop())
542                         te = getBaseline(r) - (b - oldTe);
543                     break;
544                 }
545                 case TOP:
546                     te = 0;
547                     break;
548                 case MIDDLE:
549                     te = (rHeight - heightWithoutIntrinsicPadding) / 2;
550                     break;
551                 case BOTTOM:
552                     te = rHeight - heightWithoutIntrinsicPadding;
553                     break;
554                 default:
555                     break;
556             }
557             
558             int be = rHeight - heightWithoutIntrinsicPadding - te;
559             cell->setIntrinsicPaddingTop(te);
560             cell->setIntrinsicPaddingBottom(be);
561             if (te != oldTe || be != oldBe) {
562                 cell->setNeedsLayout(true, false);
563                 cell->layoutIfNeeded();
564             }
565
566             if ((te != oldTe || be > oldBe) && !table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
567                 cell->repaint();
568             
569             IntRect oldCellRect(cell->x(), cell->y() , cell->width(), cell->height());
570         
571             if (style()->direction() == RTL) {
572                 cell->setLocation(table()->columnPositions()[nEffCols] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + hspacing, m_rowPos[rindx]);
573             } else
574                 cell->setLocation(table()->columnPositions()[c] + hspacing, m_rowPos[rindx]);
575
576             m_overflowLeft = min(m_overflowLeft, cell->x() + cell->overflowLeft(false));
577             m_overflowWidth = max(m_overflowWidth, cell->x() + cell->overflowWidth(false));
578             m_overflowTop = min(m_overflowTop, cell->y() + cell->overflowTop(false));
579             m_overflowHeight = max(m_overflowHeight, cell->y() + cell->overflowHeight(false));
580             m_hasOverflowingCell |= cell->overflowLeft(false) || cell->overflowWidth(false) > cell->width() || cell->overflowTop(false) || cell->overflowHeight(false) > cell->height();
581
582             // If the cell moved, we have to repaint it as well as any floating/positioned
583             // descendants.  An exception is if we need a layout.  In this case, we know we're going to
584             // repaint ourselves (and the cell) anyway.
585             if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
586                 cell->repaintDuringLayoutIfMoved(oldCellRect);
587         }
588     }
589
590     statePusher.pop();
591
592     setHeight(m_rowPos[totalRows]);
593     m_overflowHeight = max(m_overflowHeight, height());
594     return height();
595 }
596
597 int RenderTableSection::lowestPosition(bool includeOverflowInterior, bool includeSelf) const
598 {
599     int bottom = RenderContainer::lowestPosition(includeOverflowInterior, includeSelf);
600     if (!includeOverflowInterior && hasOverflowClip())
601         return bottom;
602
603     for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
604         for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
605             if (cell->isTableCell())
606                 bottom = max(bottom, static_cast<RenderTableCell*>(cell)->y() + cell->lowestPosition(false));
607         }
608     }
609     
610     return bottom;
611 }
612
613 int RenderTableSection::rightmostPosition(bool includeOverflowInterior, bool includeSelf) const
614 {
615     int right = RenderContainer::rightmostPosition(includeOverflowInterior, includeSelf);
616     if (!includeOverflowInterior && hasOverflowClip())
617         return right;
618
619     for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
620         for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
621             if (cell->isTableCell())
622                 right = max(right, static_cast<RenderTableCell*>(cell)->x() + cell->rightmostPosition(false));
623         }
624     }
625     
626     return right;
627 }
628
629 int RenderTableSection::leftmostPosition(bool includeOverflowInterior, bool includeSelf) const
630 {
631     int left = RenderContainer::leftmostPosition(includeOverflowInterior, includeSelf);
632     if (!includeOverflowInterior && hasOverflowClip())
633         return left;
634     
635     for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
636         for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
637             if (cell->isTableCell())
638                 left = min(left, static_cast<RenderTableCell*>(cell)->x() + cell->leftmostPosition(false));
639         }
640     }
641     
642     return left;
643 }
644
645 int RenderTableSection::calcOuterBorderTop() const
646 {
647     int totalCols = table()->numEffCols();
648     if (!m_gridRows || !totalCols)
649         return 0;
650
651     unsigned borderWidth = 0;
652
653     const BorderValue& sb = style()->borderTop();
654     if (sb.style() == BHIDDEN)
655         return -1;
656     if (sb.style() > BHIDDEN)
657         borderWidth = sb.width;
658
659     const BorderValue& rb = firstChild()->style()->borderTop();
660     if (rb.style() == BHIDDEN)
661         return -1;
662     if (rb.style() > BHIDDEN && rb.width > borderWidth)
663         borderWidth = rb.width;
664
665     bool allHidden = true;
666     for (int c = 0; c < totalCols; c++) {
667         const CellStruct& current = cellAt(0, c);
668         if (current.inColSpan || !current.cell)
669             continue;
670         const BorderValue& cb = current.cell->style()->borderTop();
671         // FIXME: Don't repeat for the same col group
672         RenderTableCol* colGroup = table()->colElement(c);
673         if (colGroup) {
674             const BorderValue& gb = colGroup->style()->borderTop();
675             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
676                 continue;
677             else
678                 allHidden = false;
679             if (gb.style() > BHIDDEN && gb.width > borderWidth)
680                 borderWidth = gb.width;
681             if (cb.style() > BHIDDEN && cb.width > borderWidth)
682                 borderWidth = cb.width;
683         } else {
684             if (cb.style() == BHIDDEN)
685                 continue;
686             else
687                 allHidden = false;
688             if (cb.style() > BHIDDEN && cb.width > borderWidth)
689                 borderWidth = cb.width;
690         }
691     }
692     if (allHidden)
693         return -1;
694
695     return borderWidth / 2;
696 }
697
698 int RenderTableSection::calcOuterBorderBottom() const
699 {
700     int totalCols = table()->numEffCols();
701     if (!m_gridRows || !totalCols)
702         return 0;
703
704     unsigned borderWidth = 0;
705
706     const BorderValue& sb = style()->borderBottom();
707     if (sb.style() == BHIDDEN)
708         return -1;
709     if (sb.style() > BHIDDEN)
710         borderWidth = sb.width;
711
712     const BorderValue& rb = lastChild()->style()->borderBottom();
713     if (rb.style() == BHIDDEN)
714         return -1;
715     if (rb.style() > BHIDDEN && rb.width > borderWidth)
716         borderWidth = rb.width;
717
718     bool allHidden = true;
719     for (int c = 0; c < totalCols; c++) {
720         const CellStruct& current = cellAt(m_gridRows - 1, c);
721         if (current.inColSpan || !current.cell)
722             continue;
723         const BorderValue& cb = current.cell->style()->borderBottom();
724         // FIXME: Don't repeat for the same col group
725         RenderTableCol* colGroup = table()->colElement(c);
726         if (colGroup) {
727             const BorderValue& gb = colGroup->style()->borderBottom();
728             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
729                 continue;
730             else
731                 allHidden = false;
732             if (gb.style() > BHIDDEN && gb.width > borderWidth)
733                 borderWidth = gb.width;
734             if (cb.style() > BHIDDEN && cb.width > borderWidth)
735                 borderWidth = cb.width;
736         } else {
737             if (cb.style() == BHIDDEN)
738                 continue;
739             else
740                 allHidden = false;
741             if (cb.style() > BHIDDEN && cb.width > borderWidth)
742                 borderWidth = cb.width;
743         }
744     }
745     if (allHidden)
746         return -1;
747
748     return (borderWidth + 1) / 2;
749 }
750
751 int RenderTableSection::calcOuterBorderLeft(bool rtl) const
752 {
753     int totalCols = table()->numEffCols();
754     if (!m_gridRows || !totalCols)
755         return 0;
756
757     unsigned borderWidth = 0;
758
759     const BorderValue& sb = style()->borderLeft();
760     if (sb.style() == BHIDDEN)
761         return -1;
762     if (sb.style() > BHIDDEN)
763         borderWidth = sb.width;
764
765     int leftmostColumn = rtl ? totalCols - 1 : 0;
766     RenderTableCol* colGroup = table()->colElement(leftmostColumn);
767     if (colGroup) {
768         const BorderValue& gb = colGroup->style()->borderLeft();
769         if (gb.style() == BHIDDEN)
770             return -1;
771         if (gb.style() > BHIDDEN && gb.width > borderWidth)
772             borderWidth = gb.width;
773     }
774
775     bool allHidden = true;
776     for (int r = 0; r < m_gridRows; r++) {
777         const CellStruct& current = cellAt(r, leftmostColumn);
778         if (!current.cell)
779             continue;
780         // FIXME: Don't repeat for the same cell
781         const BorderValue& cb = current.cell->style()->borderLeft();
782         const BorderValue& rb = current.cell->parent()->style()->borderLeft();
783         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
784             continue;
785         else
786             allHidden = false;
787         if (cb.style() > BHIDDEN && cb.width > borderWidth)
788             borderWidth = cb.width;
789         if (rb.style() > BHIDDEN && rb.width > borderWidth)
790             borderWidth = rb.width;
791     }
792     if (allHidden)
793         return -1;
794
795     return borderWidth / 2;
796 }
797
798 int RenderTableSection::calcOuterBorderRight(bool rtl) const
799 {
800     int totalCols = table()->numEffCols();
801     if (!m_gridRows || !totalCols)
802         return 0;
803
804     unsigned borderWidth = 0;
805
806     const BorderValue& sb = style()->borderRight();
807     if (sb.style() == BHIDDEN)
808         return -1;
809     if (sb.style() > BHIDDEN)
810         borderWidth = sb.width;
811
812     int rightmostColumn = rtl ? 0 : totalCols - 1;
813     RenderTableCol* colGroup = table()->colElement(rightmostColumn);
814     if (colGroup) {
815         const BorderValue& gb = colGroup->style()->borderRight();
816         if (gb.style() == BHIDDEN)
817             return -1;
818         if (gb.style() > BHIDDEN && gb.width > borderWidth)
819             borderWidth = gb.width;
820     }
821
822     bool allHidden = true;
823     for (int r = 0; r < m_gridRows; r++) {
824         const CellStruct& current = cellAt(r, rightmostColumn);
825         if (!current.cell)
826             continue;
827         // FIXME: Don't repeat for the same cell
828         const BorderValue& cb = current.cell->style()->borderRight();
829         const BorderValue& rb = current.cell->parent()->style()->borderRight();
830         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
831             continue;
832         else
833             allHidden = false;
834         if (cb.style() > BHIDDEN && cb.width > borderWidth)
835             borderWidth = cb.width;
836         if (rb.style() > BHIDDEN && rb.width > borderWidth)
837             borderWidth = rb.width;
838     }
839     if (allHidden)
840         return -1;
841
842     return (borderWidth + 1) / 2;
843 }
844
845 void RenderTableSection::recalcOuterBorder()
846 {
847     bool rtl = table()->style()->direction() == RTL;
848     m_outerBorderTop = calcOuterBorderTop();
849     m_outerBorderBottom = calcOuterBorderBottom();
850     m_outerBorderLeft = calcOuterBorderLeft(rtl);
851     m_outerBorderRight = calcOuterBorderRight(rtl);
852 }
853
854 int RenderTableSection::getBaselineOfFirstLineBox() const
855 {
856     if (!m_gridRows)
857         return -1;
858
859     int firstLineBaseline = m_grid[0].baseline;
860     if (firstLineBaseline)
861         return firstLineBaseline + m_rowPos[0];
862
863     firstLineBaseline = -1;
864     Row* firstRow = m_grid[0].row;
865     for (size_t i = 0; i < firstRow->size(); ++i) {
866         RenderTableCell* cell = firstRow->at(i).cell;
867         if (cell)
868             firstLineBaseline = max(firstLineBaseline, cell->y() + cell->paddingTop() + cell->borderTop() + cell->contentHeight());
869     }
870
871     return firstLineBaseline;
872 }
873
874 void RenderTableSection::paint(PaintInfo& paintInfo, int tx, int ty)
875 {
876     // put this back in when all layout tests can handle it
877     // ASSERT(!needsLayout());
878     // avoid crashing on bugs that cause us to paint with dirty layout
879     if (needsLayout())
880         return;
881     
882     unsigned totalRows = m_gridRows;
883     unsigned totalCols = table()->columns().size();
884
885     if (!totalRows || !totalCols)
886         return;
887
888     tx += x();
889     ty += y();
890
891     // Check which rows and cols are visible and only paint these.
892     // FIXME: Could use a binary search here.
893     PaintPhase paintPhase = paintInfo.phase;
894     int x = paintInfo.rect.x();
895     int y = paintInfo.rect.y();
896     int w = paintInfo.rect.width();
897     int h = paintInfo.rect.height();
898
899     int os = 2 * maximalOutlineSize(paintPhase);
900     unsigned startrow = 0;
901     unsigned endrow = totalRows;
902     
903     // If some cell overflows, just paint all of them.
904     if (!m_hasOverflowingCell) {
905         for (; startrow < totalRows; startrow++) {
906             if (ty + m_rowPos[startrow + 1] >= y - os)
907                 break;
908         }
909         if (startrow == totalRows && ty + m_rowPos[totalRows] + table()->outerBorderBottom() >= y - os)
910             startrow--;
911
912         for (; endrow > 0; endrow--) {
913             if (ty + m_rowPos[endrow - 1] <= y + h + os)
914                 break;
915         }
916         if (!endrow && ty + m_rowPos[0] - table()->outerBorderTop() <= y + h + os)
917             endrow++;
918     }
919
920     unsigned startcol = 0;
921     unsigned endcol = totalCols;
922     // FIXME: Implement RTL.
923     if (!m_hasOverflowingCell && style()->direction() == LTR) {
924         for (; startcol < totalCols; startcol++) {
925             if (tx + table()->columnPositions()[startcol + 1] >= x - os)
926                 break;
927         }
928         if (startcol == totalCols && tx + table()->columnPositions()[totalCols] + table()->outerBorderRight() >= x - os)
929             startcol--;
930
931         for (; endcol > 0; endcol--) {
932             if (tx + table()->columnPositions()[endcol - 1] <= x + w + os)
933                 break;
934         }
935         if (!endcol && tx + table()->columnPositions()[0] - table()->outerBorderLeft() <= y + w + os)
936             endcol++;
937     }
938
939     if (startcol < endcol) {
940         // draw the cells
941         for (unsigned r = startrow; r < endrow; r++) {
942             unsigned c = startcol;
943             // since a cell can be -1 (indicating a colspan) we might have to search backwards to include it
944             while (c && cellAt(r, c).inColSpan)
945                 c--;
946             for (; c < endcol; c++) {
947                 CellStruct current = cellAt(r, c);
948                 RenderTableCell* cell = current.cell;
949                     
950                 // Cells must always paint in the order in which they appear taking into account
951                 // their upper left originating row/column.  For cells with rowspans, avoid repainting
952                 // if we've already seen the cell.
953                 if (!cell || (r > startrow && (cellAt(r - 1, c).cell == cell)))
954                     continue;
955
956                 RenderTableRow* row = static_cast<RenderTableRow*>(cell->parent());
957
958                 if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
959                     // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
960                     // the column group, column, row group, row, and then the cell.
961                     RenderObject* col = table()->colElement(c);
962                     RenderObject* colGroup = 0;
963                     if (col && col->parent()->style()->display() == TABLE_COLUMN_GROUP)
964                         colGroup = col->parent();
965
966                     // Column groups and columns first.
967                     // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
968                     // the stack, since we have already opened a transparency layer (potentially) for the table row group.
969                     // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
970                     // cell.
971                     cell->paintBackgroundsBehindCell(paintInfo, tx, ty, colGroup);
972                     cell->paintBackgroundsBehindCell(paintInfo, tx, ty, col);
973
974                     // Paint the row group next.
975                     cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
976
977                     // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
978                     // painting the row background for the cell.
979                     if (!row->hasLayer())
980                         cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
981                 }
982
983                 if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
984                     cell->paint(paintInfo, tx, ty);
985             }
986         }
987     }
988 }
989
990 void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
991 {
992     // FIXME: Examine cells and repaint only the rect the image paints in.
993     repaint();
994 }
995
996 void RenderTableSection::recalcCells()
997 {
998     m_cCol = 0;
999     m_cRow = -1;
1000     clearGrid();
1001     m_gridRows = 0;
1002
1003     for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
1004         if (row->isTableRow()) {
1005             m_cRow++;
1006             m_cCol = 0;
1007             if (!ensureRows(m_cRow + 1))
1008                 break;
1009             
1010             RenderTableRow* tableRow = static_cast<RenderTableRow*>(row);
1011             m_grid[m_cRow].rowRenderer = tableRow;
1012
1013             for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
1014                 if (cell->isTableCell())
1015                     addCell(static_cast<RenderTableCell*>(cell), tableRow);
1016             }
1017         }
1018     }
1019     m_needsCellRecalc = false;
1020     setNeedsLayout(true);
1021 }
1022
1023 void RenderTableSection::clearGrid()
1024 {
1025     int rows = m_gridRows;
1026     while (rows--)
1027         delete m_grid[rows].row;
1028 }
1029
1030 int RenderTableSection::numColumns() const
1031 {
1032     int result = 0;
1033     
1034     for (int r = 0; r < m_gridRows; ++r) {
1035         for (int c = result; c < table()->numEffCols(); ++c) {
1036             const CellStruct& cell = cellAt(r, c);
1037             if (cell.cell || cell.inColSpan)
1038                 result = c;
1039         }
1040     }
1041     
1042     return result + 1;
1043 }
1044
1045 void RenderTableSection::appendColumn(int pos)
1046 {
1047     for (int row = 0; row < m_gridRows; ++row) {
1048         m_grid[row].row->resize(pos + 1);
1049         CellStruct& c = cellAt(row, pos);
1050         c.cell = 0;
1051         c.inColSpan = false;
1052     }
1053 }
1054
1055 void RenderTableSection::splitColumn(int pos, int newSize)
1056 {
1057     if (m_cCol > pos)
1058         m_cCol++;
1059     for (int row = 0; row < m_gridRows; ++row) {
1060         m_grid[row].row->resize(newSize);
1061         Row& r = *m_grid[row].row;
1062         memmove(r.data() + pos + 1, r.data() + pos, (newSize - 1 - pos) * sizeof(CellStruct));
1063         r[pos + 1].cell = 0;
1064         r[pos + 1].inColSpan = r[pos].inColSpan || r[pos].cell;
1065     }
1066 }
1067
1068 RenderObject* RenderTableSection::removeChildNode(RenderObject* child, bool fullRemove)
1069 {
1070     setNeedsCellRecalc();
1071     return RenderContainer::removeChildNode(child, fullRemove);
1072 }
1073
1074 // Hit Testing
1075 bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
1076 {
1077     // Table sections cannot ever be hit tested.  Effectively they do not exist.
1078     // Just forward to our children always.
1079     tx += x();
1080     ty += y();
1081
1082     for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
1083         // FIXME: We have to skip over inline flows, since they can show up inside table rows
1084         // at the moment (a demoted inline <form> for example). If we ever implement a
1085         // table-specific hit-test method (which we should do for performance reasons anyway),
1086         // then we can remove this check.
1087         if (!child->hasLayer() && !child->isInlineFlow() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
1088             updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
1089             return true;
1090         }
1091     }
1092     
1093     return false;
1094 }
1095
1096 } // namespace WebCore