OSDN Git Service

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