Text decorations do not contribute to visual overflow
[WebKit-https.git] / Source / WebCore / rendering / RenderTableSection.cpp
1 /*
2  * Copyright (C) 1997 Martin Jones (mjones@kde.org)
3  *           (C) 1997 Torben Weis (weis@kde.org)
4  *           (C) 1998 Waldo Bastian (bastian@kde.org)
5  *           (C) 1999 Lars Knoll (knoll@kde.org)
6  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
7  * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
8  * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  * Boston, MA 02110-1301, USA.
24  */
25
26 #include "config.h"
27 #include "RenderTableSection.h"
28 #include "Document.h"
29 #include "HitTestResult.h"
30 #include "HTMLNames.h"
31 #include "PaintInfo.h"
32 #include "RenderNamedFlowFragment.h"
33 #include "RenderTableCell.h"
34 #include "RenderTableCol.h"
35 #include "RenderTableRow.h"
36 #include "RenderView.h"
37 #include "StyleInheritedData.h"
38 #include <limits>
39 #include <wtf/HashSet.h>
40 #include <wtf/StackStats.h>
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45
46 // Those 2 variables are used to balance the memory consumption vs the repaint time on big tables.
47 static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75;
48 static float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f;
49
50 static inline void setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(RenderTableSection::RowStruct& row)
51 {
52     ASSERT(row.rowRenderer);
53     row.logicalHeight = row.rowRenderer->style().logicalHeight();
54     if (row.logicalHeight.isRelative())
55         row.logicalHeight = Length();
56 }
57
58 static inline void updateLogicalHeightForCell(RenderTableSection::RowStruct& row, const RenderTableCell* cell)
59 {
60     // We ignore height settings on rowspan cells.
61     if (cell->rowSpan() != 1)
62         return;
63
64     Length logicalHeight = cell->style().logicalHeight();
65     if (logicalHeight.isPositive() || (logicalHeight.isRelative() && logicalHeight.value() >= 0)) {
66         Length cRowLogicalHeight = row.logicalHeight;
67         switch (logicalHeight.type()) {
68         case Percent:
69             if (!cRowLogicalHeight.isPercentNotCalculated() || cRowLogicalHeight.percent() < logicalHeight.percent())
70                 row.logicalHeight = logicalHeight;
71             break;
72         case Fixed:
73             if (cRowLogicalHeight.isAuto() || cRowLogicalHeight.isRelative()
74                 || (cRowLogicalHeight.isFixed() && cRowLogicalHeight.value() < logicalHeight.value()))
75                 row.logicalHeight = logicalHeight;
76             break;
77         case Relative:
78         default:
79             break;
80         }
81     }
82 }
83
84 RenderTableSection::RenderTableSection(Element& element, PassRef<RenderStyle> style)
85     : RenderBox(element, std::move(style), 0)
86     , m_cCol(0)
87     , m_cRow(0)
88     , m_outerBorderStart(0)
89     , m_outerBorderEnd(0)
90     , m_outerBorderBefore(0)
91     , m_outerBorderAfter(0)
92     , m_needsCellRecalc(false)
93     , m_hasMultipleCellLevels(false)
94 {
95     setInline(false);
96 }
97
98 RenderTableSection::RenderTableSection(Document& document, PassRef<RenderStyle> style)
99     : RenderBox(document, std::move(style), 0)
100     , m_cCol(0)
101     , m_cRow(0)
102     , m_outerBorderStart(0)
103     , m_outerBorderEnd(0)
104     , m_outerBorderBefore(0)
105     , m_outerBorderAfter(0)
106     , m_needsCellRecalc(false)
107     , m_hasMultipleCellLevels(false)
108 {
109     setInline(false);
110 }
111
112 RenderTableSection::~RenderTableSection()
113 {
114 }
115
116 void RenderTableSection::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
117 {
118     RenderBox::styleDidChange(diff, oldStyle);
119     propagateStyleToAnonymousChildren(PropagateToAllChildren);
120
121     // If border was changed, notify table.
122     RenderTable* table = this->table();
123     if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style().border())
124         table->invalidateCollapsedBorders();
125 }
126
127 void RenderTableSection::willBeRemovedFromTree()
128 {
129     RenderBox::willBeRemovedFromTree();
130
131     // Preventively invalidate our cells as we may be re-inserted into
132     // a new table which would require us to rebuild our structure.
133     setNeedsCellRecalc();
134 }
135
136 void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
137 {
138     if (!child->isTableRow()) {
139         RenderObject* last = beforeChild;
140         if (!last)
141             last = lastRow();
142         if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
143             RenderTableRow* row = toRenderTableRow(last);
144             if (beforeChild == row)
145                 beforeChild = row->firstCell();
146             row->addChild(child, beforeChild);
147             return;
148         }
149
150         if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
151             RenderObject* row = beforeChild->previousSibling();
152             if (row && row->isTableRow() && row->isAnonymous()) {
153                 toRenderTableRow(row)->addChild(child);
154                 return;
155             }
156         }
157
158         // If beforeChild is inside an anonymous cell/row, insert into the cell or into
159         // the anonymous row containing it, if there is one.
160         RenderObject* lastBox = last;
161         while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableRow())
162             lastBox = lastBox->parent();
163         if (lastBox && lastBox->isAnonymous() && !lastBox->isBeforeOrAfterContent()) {
164             toRenderTableRow(lastBox)->addChild(child, beforeChild);
165             return;
166         }
167
168         RenderTableRow* row = RenderTableRow::createAnonymousWithParentRenderer(this);
169         addChild(row, beforeChild);
170         row->addChild(child);
171         return;
172     }
173
174     if (beforeChild)
175         setNeedsCellRecalc();
176
177     unsigned insertionRow = m_cRow;
178     ++m_cRow;
179     m_cCol = 0;
180
181     ensureRows(m_cRow);
182
183     RenderTableRow* row = toRenderTableRow(child);
184     m_grid[insertionRow].rowRenderer = row;
185     row->setRowIndex(insertionRow);
186
187     if (!beforeChild)
188         setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
189
190     if (beforeChild && beforeChild->parent() != this)
191         beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
192
193     ASSERT(!beforeChild || beforeChild->isTableRow());
194     RenderBox::addChild(child, beforeChild);
195 }
196
197 void RenderTableSection::ensureRows(unsigned numRows)
198 {
199     if (numRows <= m_grid.size())
200         return;
201
202     unsigned oldSize = m_grid.size();
203     m_grid.grow(numRows);
204
205     unsigned effectiveColumnCount = std::max(1u, table()->numEffCols());
206     for (unsigned row = oldSize; row < m_grid.size(); ++row)
207         m_grid[row].row.resizeToFit(effectiveColumnCount);
208 }
209
210 void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
211 {
212     // We don't insert the cell if we need cell recalc as our internal columns' representation
213     // will have drifted from the table's representation. Also recalcCells will call addCell
214     // at a later time after sync'ing our columns' with the table's.
215     if (needsCellRecalc())
216         return;
217
218     unsigned rSpan = cell->rowSpan();
219     unsigned cSpan = cell->colSpan();
220     const Vector<RenderTable::ColumnStruct>& columns = table()->columns();
221     unsigned nCols = columns.size();
222     unsigned insertionRow = row->rowIndex();
223
224     // ### mozilla still seems to do the old HTML way, even for strict DTD
225     // (see the annotation on table cell layouting in the CSS specs and the testcase below:
226     // <TABLE border>
227     // <TR><TD>1 <TD rowspan="2">2 <TD>3 <TD>4
228     // <TR><TD colspan="2">5
229     // </TABLE>
230     while (m_cCol < nCols && (cellAt(insertionRow, m_cCol).hasCells() || cellAt(insertionRow, m_cCol).inColSpan))
231         m_cCol++;
232
233     updateLogicalHeightForCell(m_grid[insertionRow], cell);
234
235     ensureRows(insertionRow + rSpan);
236
237     m_grid[insertionRow].rowRenderer = row;
238
239     unsigned col = m_cCol;
240     // tell the cell where it is
241     bool inColSpan = false;
242     while (cSpan) {
243         unsigned currentSpan;
244         if (m_cCol >= nCols) {
245             table()->appendColumn(cSpan);
246             currentSpan = cSpan;
247         } else {
248             if (cSpan < columns[m_cCol].span)
249                 table()->splitColumn(m_cCol, cSpan);
250             currentSpan = columns[m_cCol].span;
251         }
252         for (unsigned r = 0; r < rSpan; r++) {
253             CellStruct& c = cellAt(insertionRow + r, m_cCol);
254             ASSERT(cell);
255             c.cells.append(cell);
256             // If cells overlap then we take the slow path for painting.
257             if (c.cells.size() > 1)
258                 m_hasMultipleCellLevels = true;
259             if (inColSpan)
260                 c.inColSpan = true;
261         }
262         m_cCol++;
263         cSpan -= currentSpan;
264         inColSpan = true;
265     }
266     cell->setCol(table()->effColToCol(col));
267 }
268
269 int RenderTableSection::calcRowLogicalHeight()
270 {
271 #ifndef NDEBUG
272     SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
273 #endif
274
275     ASSERT(!needsLayout());
276
277     RenderTableCell* cell;
278
279     // We ignore the border-spacing on any non-top section as it is already included in the previous section's last row position.
280     int spacing = 0;
281     if (this == table()->topSection())
282         spacing = table()->vBorderSpacing();
283
284     LayoutStateMaintainer statePusher(view());
285
286     m_rowPos.resize(m_grid.size() + 1);
287     m_rowPos[0] = spacing;
288
289     unsigned totalRows = m_grid.size();
290
291     for (unsigned r = 0; r < totalRows; r++) {
292         m_grid[r].baseline = 0;
293         LayoutUnit baselineDescent = 0;
294
295         // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
296         m_rowPos[r + 1] = std::max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0).round(), 0);
297
298         Row& row = m_grid[r].row;
299         unsigned totalCols = row.size();
300
301         for (unsigned c = 0; c < totalCols; c++) {
302             CellStruct& current = cellAt(r, c);
303             for (unsigned i = 0; i < current.cells.size(); i++) {
304                 cell = current.cells[i];
305                 if (current.inColSpan && cell->rowSpan() == 1)
306                     continue;
307
308                 // FIXME: We are always adding the height of a rowspan to the last rows which doesn't match
309                 // other browsers. See webkit.org/b/52185 for example.
310                 if ((cell->rowIndex() + cell->rowSpan() - 1) != r) {
311                     // We will apply the height of the rowspan to the current row if next row is not valid.
312                     if ((r + 1) < totalRows) {
313                         unsigned col = 0;
314                         CellStruct nextRowCell = cellAt(r + 1, col);
315
316                         // We are trying to find that next row is valid or not.
317                         while (nextRowCell.cells.size() && nextRowCell.cells[0]->rowSpan() > 1 && nextRowCell.cells[0]->rowIndex() < (r + 1)) {
318                             col++;
319                             if (col < totalCols)
320                                 nextRowCell = cellAt(r + 1, col);
321                             else
322                                 break;
323                         }
324
325                         // We are adding the height of the rowspan to the current row if next row is not valid.
326                         if (col < totalCols && nextRowCell.cells.size())
327                             continue;
328                     }
329                 }
330
331                 // For row spanning cells, |r| is the last row in the span.
332                 unsigned cellStartRow = cell->rowIndex();
333
334                 if (cell->hasOverrideHeight()) {
335                     if (!statePusher.didPush()) {
336                         // Technically, we should also push state for the row, but since
337                         // rows don't push a coordinate transform, that's not necessary.
338                         statePusher.push(*this, locationOffset());
339                     }
340                     cell->clearIntrinsicPadding();
341                     cell->clearOverrideSize();
342                     cell->setChildNeedsLayout(MarkOnlyThis);
343                     cell->layoutIfNeeded();
344                 }
345
346                 int cellLogicalHeight = cell->logicalHeightForRowSizing();
347                 m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cellLogicalHeight);
348
349                 // Find out the baseline. The baseline is set on the first row in a rowspan.
350                 if (cell->isBaselineAligned()) {
351                     LayoutUnit baselinePosition = cell->cellBaselinePosition();
352                     if (baselinePosition > cell->borderAndPaddingBefore()) {
353                         m_grid[cellStartRow].baseline = std::max(m_grid[cellStartRow].baseline, baselinePosition);
354                         // The descent of a cell that spans multiple rows does not affect the height of the first row it spans, so don't let it
355                         // become the baseline descent applied to the rest of the row. Also we don't account for the baseline descent of
356                         // non-spanning cells when computing a spanning cell's extent.
357                         int cellStartRowBaselineDescent = 0;
358                         if (cell->rowSpan() == 1) {
359                             baselineDescent = std::max(baselineDescent, cellLogicalHeight - (baselinePosition - cell->intrinsicPaddingBefore()));
360                             cellStartRowBaselineDescent = baselineDescent;
361                         }
362                         m_rowPos[cellStartRow + 1] = std::max<int>(m_rowPos[cellStartRow + 1], m_rowPos[cellStartRow] + m_grid[cellStartRow].baseline + cellStartRowBaselineDescent);
363                     }
364                 }
365             }
366         }
367
368         // Add the border-spacing to our final position.
369         // Use table border-spacing even in non-top sections
370         spacing = table()->vBorderSpacing();
371         m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : 0;
372         m_rowPos[r + 1] = std::max(m_rowPos[r + 1], m_rowPos[r]);
373     }
374
375     ASSERT(!needsLayout());
376
377     statePusher.pop();
378
379     return m_rowPos[m_grid.size()];
380 }
381
382 void RenderTableSection::layout()
383 {
384     StackStats::LayoutCheckPoint layoutCheckPoint;
385     ASSERT(needsLayout());
386     ASSERT(!needsCellRecalc());
387     ASSERT(!table()->needsSectionRecalc());
388
389     // addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
390     // can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
391     m_grid.shrinkToFit();
392
393     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
394
395     const Vector<int>& columnPos = table()->columnPositions();
396
397     for (unsigned r = 0; r < m_grid.size(); ++r) {
398         Row& row = m_grid[r].row;
399         unsigned cols = row.size();
400         // First, propagate our table layout's information to the cells. This will mark the row as needing layout
401         // if there was a column logical width change.
402         for (unsigned startColumn = 0; startColumn < cols; ++startColumn) {
403             CellStruct& current = row[startColumn];
404             RenderTableCell* cell = current.primaryCell();
405             if (!cell || current.inColSpan)
406                 continue;
407
408             unsigned endCol = startColumn;
409             unsigned cspan = cell->colSpan();
410             while (cspan && endCol < cols) {
411                 ASSERT(endCol < table()->columns().size());
412                 cspan -= table()->columns()[endCol].span;
413                 endCol++;
414             }
415             int tableLayoutLogicalWidth = columnPos[endCol] - columnPos[startColumn] - table()->hBorderSpacing();
416             cell->setCellLogicalWidth(tableLayoutLogicalWidth);
417         }
418
419         if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer)
420             rowRenderer->layoutIfNeeded();
421     }
422
423     statePusher.pop();
424     clearNeedsLayout();
425 }
426
427 void RenderTableSection::distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent)
428 {
429     if (!totalPercent)
430         return;
431
432     unsigned totalRows = m_grid.size();
433     int totalHeight = m_rowPos[totalRows] + extraLogicalHeight;
434     int totalLogicalHeightAdded = 0;
435     totalPercent = std::min(totalPercent, 100);
436     int rowHeight = m_rowPos[1] - m_rowPos[0];
437     for (unsigned r = 0; r < totalRows; ++r) {
438         if (totalPercent > 0 && m_grid[r].logicalHeight.isPercentNotCalculated()) {
439             int toAdd = std::min<int>(extraLogicalHeight, (totalHeight * m_grid[r].logicalHeight.percent() / 100) - rowHeight);
440             // If toAdd is negative, then we don't want to shrink the row (this bug
441             // affected Outlook Web Access).
442             toAdd = std::max(0, toAdd);
443             totalLogicalHeightAdded += toAdd;
444             extraLogicalHeight -= toAdd;
445             totalPercent -= m_grid[r].logicalHeight.percent();
446         }
447         ASSERT(totalRows >= 1);
448         if (r < totalRows - 1)
449             rowHeight = m_rowPos[r + 2] - m_rowPos[r + 1];
450         m_rowPos[r + 1] += totalLogicalHeightAdded;
451     }
452 }
453
454 void RenderTableSection::distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount)
455 {
456     if (!autoRowsCount)
457         return;
458
459     int totalLogicalHeightAdded = 0;
460     for (unsigned r = 0; r < m_grid.size(); ++r) {
461         if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) {
462             // Recomputing |extraLogicalHeightForRow| guarantees that we properly ditribute round |extraLogicalHeight|.
463             int extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount;
464             totalLogicalHeightAdded += extraLogicalHeightForRow;
465             extraLogicalHeight -= extraLogicalHeightForRow;
466             --autoRowsCount;
467         }
468         m_rowPos[r + 1] += totalLogicalHeightAdded;
469     }
470 }
471
472 void RenderTableSection::distributeRemainingExtraLogicalHeight(int& extraLogicalHeight)
473 {
474     unsigned totalRows = m_grid.size();
475
476     if (extraLogicalHeight <= 0 || !m_rowPos[totalRows])
477         return;
478
479     // FIXME: m_rowPos[totalRows] - m_rowPos[0] is the total rows' size.
480     int totalRowSize = m_rowPos[totalRows];
481     int totalLogicalHeightAdded = 0;
482     int previousRowPosition = m_rowPos[0];
483     for (unsigned r = 0; r < totalRows; r++) {
484         // weight with the original height
485         totalLogicalHeightAdded += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
486         previousRowPosition = m_rowPos[r + 1];
487         m_rowPos[r + 1] += totalLogicalHeightAdded;
488     }
489
490     extraLogicalHeight -= totalLogicalHeightAdded;
491 }
492
493 int RenderTableSection::distributeExtraLogicalHeightToRows(int extraLogicalHeight)
494 {
495     if (!extraLogicalHeight)
496         return extraLogicalHeight;
497
498     unsigned totalRows = m_grid.size();
499     if (!totalRows)
500         return extraLogicalHeight;
501
502     if (!m_rowPos[totalRows] && nextSibling())
503         return extraLogicalHeight;
504
505     unsigned autoRowsCount = 0;
506     int totalPercent = 0;
507     for (unsigned r = 0; r < totalRows; r++) {
508         if (m_grid[r].logicalHeight.isAuto())
509             ++autoRowsCount;
510         else if (m_grid[r].logicalHeight.isPercentNotCalculated())
511             totalPercent += m_grid[r].logicalHeight.percent();
512     }
513
514     int remainingExtraLogicalHeight = extraLogicalHeight;
515     distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
516     distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
517     distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
518     return extraLogicalHeight - remainingExtraLogicalHeight;
519 }
520
521 void RenderTableSection::layoutRows()
522 {
523 #ifndef NDEBUG
524     SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
525 #endif
526
527     ASSERT(!needsLayout());
528
529     unsigned totalRows = m_grid.size();
530
531     // Set the width of our section now.  The rows will also be this width.
532     setLogicalWidth(table()->contentLogicalWidth());
533     m_forceSlowPaintPathWithOverflowingCell = false;
534
535     int vspacing = table()->vBorderSpacing();
536     unsigned nEffCols = table()->numEffCols();
537
538     LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || style().isFlippedBlocksWritingMode());
539
540     for (unsigned r = 0; r < totalRows; r++) {
541         // Set the row's x/y position and width/height.
542         if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
543             // FIXME: the x() position of the row should be table()->hBorderSpacing() so that it can 
544             // report the correct offsetLeft. However, that will require a lot of rebaselining of test results.
545             rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
546             rowRenderer->setLogicalWidth(logicalWidth());
547             rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
548             rowRenderer->updateLayerTransform();
549         }
550
551         int rowHeightIncreaseForPagination = 0;
552
553         for (unsigned c = 0; c < nEffCols; c++) {
554             CellStruct& cs = cellAt(r, c);
555             RenderTableCell* cell = cs.primaryCell();
556
557             if (!cell || cs.inColSpan)
558                 continue;
559
560             int rowIndex = cell->rowIndex();
561             int rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - vspacing;
562
563             // Force percent height children to lay themselves out again.
564             // This will cause these children to grow to fill the cell.
565             // FIXME: There is still more work to do here to fully match WinIE (should
566             // it become necessary to do so).  In quirks mode, WinIE behaves like we
567             // do, but it will clip the cells that spill out of the table section.  In
568             // strict mode, Mozilla and WinIE both regrow the table to accommodate the
569             // new height of the cell (thus letting the percentages cause growth one
570             // time only).  We may also not be handling row-spanning cells correctly.
571             //
572             // Note also the oddity where replaced elements always flex, and yet blocks/tables do
573             // not necessarily flex.  WinIE is crazy and inconsistent, and we can't hope to
574             // match the behavior perfectly, but we'll continue to refine it as we discover new
575             // bugs. :)
576             bool cellChildrenFlex = false;
577             bool flexAllChildren = cell->style().logicalHeight().isFixed()
578                 || (!table()->style().logicalHeight().isAuto() && rHeight != cell->logicalHeight());
579
580             for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
581                 if (!o->isText() && o->style().logicalHeight().isPercent() && (flexAllChildren || ((o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow())) && !o->isTextControl()))) {
582                     // Tables with no sections do not flex.
583                     if (!o->isTable() || toRenderTable(o)->hasSections()) {
584                         o->setNeedsLayout(MarkOnlyThis);
585                         cellChildrenFlex = true;
586                     }
587                 }
588             }
589
590             if (TrackedRendererListHashSet* percentHeightDescendants = cell->percentHeightDescendants()) {
591                 TrackedRendererListHashSet::iterator end = percentHeightDescendants->end();
592                 for (TrackedRendererListHashSet::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
593                     RenderBox* box = *it;
594                     if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
595                         continue;
596
597                     while (box != cell) {
598                         if (box->normalChildNeedsLayout())
599                             break;
600                         box->setChildNeedsLayout(MarkOnlyThis);
601                         box = box->containingBlock();
602                         ASSERT(box);
603                         if (!box)
604                             break;
605                     }
606                     cellChildrenFlex = true;
607                 }
608             }
609
610             if (cellChildrenFlex) {
611                 cell->setChildNeedsLayout(MarkOnlyThis);
612                 // Alignment within a cell is based off the calculated
613                 // height, which becomes irrelevant once the cell has
614                 // been resized based off its percentage.
615                 cell->setOverrideLogicalContentHeightFromRowHeight(rHeight);
616                 cell->layoutIfNeeded();
617
618                 // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
619                 if (cell->isBaselineAligned()) {
620                     LayoutUnit baseline = cell->cellBaselinePosition();
621                     if (baseline > cell->borderAndPaddingBefore())
622                         m_grid[r].baseline = std::max(m_grid[r].baseline, baseline);
623                 }
624             }
625
626             cell->computeIntrinsicPadding(rHeight);
627
628             LayoutRect oldCellRect = cell->frameRect();
629
630             setLogicalPositionForCell(cell, c);
631
632             if (!cell->needsLayout() && view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
633                 cell->setChildNeedsLayout(MarkOnlyThis);
634
635             cell->layoutIfNeeded();
636
637             // FIXME: Make pagination work with vertical tables.
638             if (view().layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
639                 // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
640                 // We'll also do a basic increase of the row height to accommodate the cell if it's bigger, but this isn't quite right
641                 // either. It's at least stable though and won't result in an infinite # of relayouts that may never stabilize.
642                 if (cell->logicalHeight() > rHeight)
643                     rowHeightIncreaseForPagination = std::max<int>(rowHeightIncreaseForPagination, cell->logicalHeight() - rHeight);
644                 cell->setLogicalHeight(rHeight);
645             }
646
647             LayoutSize childOffset(cell->location() - oldCellRect.location());
648             if (childOffset.width() || childOffset.height()) {
649                 view().addLayoutDelta(childOffset);
650
651                 // If the child moved, we have to repaint it as well as any floating/positioned
652                 // descendants.  An exception is if we need a layout.  In this case, we know we're going to
653                 // repaint ourselves (and the child) anyway.
654                 if (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
655                     cell->repaintDuringLayoutIfMoved(oldCellRect);
656             }
657         }
658         if (rowHeightIncreaseForPagination) {
659             for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++)
660                 m_rowPos[rowIndex] += rowHeightIncreaseForPagination;
661             for (unsigned c = 0; c < nEffCols; ++c) {
662                 Vector<RenderTableCell*, 1>& cells = cellAt(r, c).cells;
663                 for (size_t i = 0; i < cells.size(); ++i)
664                     cells[i]->setLogicalHeight(cells[i]->logicalHeight() + rowHeightIncreaseForPagination);
665             }
666         }
667     }
668
669     ASSERT(!needsLayout());
670
671     setLogicalHeight(m_rowPos[totalRows]);
672
673     computeOverflowFromCells(totalRows, nEffCols);
674
675     statePusher.pop();
676 }
677
678 void RenderTableSection::computeOverflowFromCells()
679 {
680     unsigned totalRows = m_grid.size();
681     unsigned nEffCols = table()->numEffCols();
682     computeOverflowFromCells(totalRows, nEffCols);
683 }
684
685 void RenderTableSection::computeOverflowFromCells(unsigned totalRows, unsigned nEffCols)
686 {
687     clearOverflow();
688     m_overflowingCells.clear();
689     unsigned totalCellsCount = nEffCols * totalRows;
690     int maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
691
692 #ifndef NDEBUG
693     bool hasOverflowingCell = false;
694 #endif
695     // Now that our height has been determined, add in overflow from cells.
696     for (unsigned r = 0; r < totalRows; r++) {
697         for (unsigned c = 0; c < nEffCols; c++) {
698             CellStruct& cs = cellAt(r, c);
699             RenderTableCell* cell = cs.primaryCell();
700             if (!cell || cs.inColSpan)
701                 continue;
702             if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
703                 continue;
704             addOverflowFromChild(cell);
705 #ifndef NDEBUG
706             hasOverflowingCell |= cell->hasVisualOverflow();
707 #endif
708             if (cell->hasVisualOverflow() && !m_forceSlowPaintPathWithOverflowingCell) {
709                 m_overflowingCells.add(cell);
710                 if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) {
711                     // We need to set m_forcesSlowPaintPath only if there is a least one overflowing cells as the hit testing code rely on this information.
712                     m_forceSlowPaintPathWithOverflowingCell = true;
713                     // The slow path does not make any use of the overflowing cells info, don't hold on to the memory.
714                     m_overflowingCells.clear();
715                 }
716             }
717         }
718     }
719
720     ASSERT(hasOverflowingCell == this->hasOverflowingCell());
721 }
722
723 int RenderTableSection::calcOuterBorderBefore() const
724 {
725     unsigned totalCols = table()->numEffCols();
726     if (!m_grid.size() || !totalCols)
727         return 0;
728
729     unsigned borderWidth = 0;
730
731     const BorderValue& sb = style().borderBefore();
732     if (sb.style() == BHIDDEN)
733         return -1;
734     if (sb.style() > BHIDDEN)
735         borderWidth = sb.width();
736
737     const BorderValue& rb = firstRow()->style().borderBefore();
738     if (rb.style() == BHIDDEN)
739         return -1;
740     if (rb.style() > BHIDDEN && rb.width() > borderWidth)
741         borderWidth = rb.width();
742
743     bool allHidden = true;
744     for (unsigned c = 0; c < totalCols; c++) {
745         const CellStruct& current = cellAt(0, c);
746         if (current.inColSpan || !current.hasCells())
747             continue;
748         const BorderValue& cb = current.primaryCell()->style().borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
749         // FIXME: Don't repeat for the same col group
750         RenderTableCol* colGroup = table()->colElement(c);
751         if (colGroup) {
752             const BorderValue& gb = colGroup->style().borderBefore();
753             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
754                 continue;
755             allHidden = false;
756             if (gb.style() > BHIDDEN && gb.width() > borderWidth)
757                 borderWidth = gb.width();
758             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
759                 borderWidth = cb.width();
760         } else {
761             if (cb.style() == BHIDDEN)
762                 continue;
763             allHidden = false;
764             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
765                 borderWidth = cb.width();
766         }
767     }
768     if (allHidden)
769         return -1;
770
771     return borderWidth / 2;
772 }
773
774 int RenderTableSection::calcOuterBorderAfter() const
775 {
776     unsigned totalCols = table()->numEffCols();
777     if (!m_grid.size() || !totalCols)
778         return 0;
779
780     unsigned borderWidth = 0;
781
782     const BorderValue& sb = style().borderAfter();
783     if (sb.style() == BHIDDEN)
784         return -1;
785     if (sb.style() > BHIDDEN)
786         borderWidth = sb.width();
787
788     const BorderValue& rb = lastRow()->style().borderAfter();
789     if (rb.style() == BHIDDEN)
790         return -1;
791     if (rb.style() > BHIDDEN && rb.width() > borderWidth)
792         borderWidth = rb.width();
793
794     bool allHidden = true;
795     for (unsigned c = 0; c < totalCols; c++) {
796         const CellStruct& current = cellAt(m_grid.size() - 1, c);
797         if (current.inColSpan || !current.hasCells())
798             continue;
799         const BorderValue& cb = current.primaryCell()->style().borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
800         // FIXME: Don't repeat for the same col group
801         RenderTableCol* colGroup = table()->colElement(c);
802         if (colGroup) {
803             const BorderValue& gb = colGroup->style().borderAfter();
804             if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
805                 continue;
806             allHidden = false;
807             if (gb.style() > BHIDDEN && gb.width() > borderWidth)
808                 borderWidth = gb.width();
809             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
810                 borderWidth = cb.width();
811         } else {
812             if (cb.style() == BHIDDEN)
813                 continue;
814             allHidden = false;
815             if (cb.style() > BHIDDEN && cb.width() > borderWidth)
816                 borderWidth = cb.width();
817         }
818     }
819     if (allHidden)
820         return -1;
821
822     return (borderWidth + 1) / 2;
823 }
824
825 int RenderTableSection::calcOuterBorderStart() const
826 {
827     unsigned totalCols = table()->numEffCols();
828     if (!m_grid.size() || !totalCols)
829         return 0;
830
831     unsigned borderWidth = 0;
832
833     const BorderValue& sb = style().borderStart();
834     if (sb.style() == BHIDDEN)
835         return -1;
836     if (sb.style() > BHIDDEN)
837         borderWidth = sb.width();
838
839     if (RenderTableCol* colGroup = table()->colElement(0)) {
840         const BorderValue& gb = colGroup->style().borderStart();
841         if (gb.style() == BHIDDEN)
842             return -1;
843         if (gb.style() > BHIDDEN && gb.width() > borderWidth)
844             borderWidth = gb.width();
845     }
846
847     bool allHidden = true;
848     for (unsigned r = 0; r < m_grid.size(); r++) {
849         const CellStruct& current = cellAt(r, 0);
850         if (!current.hasCells())
851             continue;
852         // FIXME: Don't repeat for the same cell
853         const BorderValue& cb = current.primaryCell()->style().borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
854         const BorderValue& rb = current.primaryCell()->parent()->style().borderStart();
855         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
856             continue;
857         allHidden = false;
858         if (cb.style() > BHIDDEN && cb.width() > borderWidth)
859             borderWidth = cb.width();
860         if (rb.style() > BHIDDEN && rb.width() > borderWidth)
861             borderWidth = rb.width();
862     }
863     if (allHidden)
864         return -1;
865
866     return (borderWidth + (table()->style().isLeftToRightDirection() ? 0 : 1)) / 2;
867 }
868
869 int RenderTableSection::calcOuterBorderEnd() const
870 {
871     unsigned totalCols = table()->numEffCols();
872     if (!m_grid.size() || !totalCols)
873         return 0;
874
875     unsigned borderWidth = 0;
876
877     const BorderValue& sb = style().borderEnd();
878     if (sb.style() == BHIDDEN)
879         return -1;
880     if (sb.style() > BHIDDEN)
881         borderWidth = sb.width();
882
883     if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
884         const BorderValue& gb = colGroup->style().borderEnd();
885         if (gb.style() == BHIDDEN)
886             return -1;
887         if (gb.style() > BHIDDEN && gb.width() > borderWidth)
888             borderWidth = gb.width();
889     }
890
891     bool allHidden = true;
892     for (unsigned r = 0; r < m_grid.size(); r++) {
893         const CellStruct& current = cellAt(r, totalCols - 1);
894         if (!current.hasCells())
895             continue;
896         // FIXME: Don't repeat for the same cell
897         const BorderValue& cb = current.primaryCell()->style().borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
898         const BorderValue& rb = current.primaryCell()->parent()->style().borderEnd();
899         if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
900             continue;
901         allHidden = false;
902         if (cb.style() > BHIDDEN && cb.width() > borderWidth)
903             borderWidth = cb.width();
904         if (rb.style() > BHIDDEN && rb.width() > borderWidth)
905             borderWidth = rb.width();
906     }
907     if (allHidden)
908         return -1;
909
910     return (borderWidth + (table()->style().isLeftToRightDirection() ? 1 : 0)) / 2;
911 }
912
913 void RenderTableSection::recalcOuterBorder()
914 {
915     m_outerBorderBefore = calcOuterBorderBefore();
916     m_outerBorderAfter = calcOuterBorderAfter();
917     m_outerBorderStart = calcOuterBorderStart();
918     m_outerBorderEnd = calcOuterBorderEnd();
919 }
920
921 int RenderTableSection::firstLineBaseline() const
922 {
923     if (!m_grid.size())
924         return -1;
925
926     int firstLineBaseline = m_grid[0].baseline;
927     if (firstLineBaseline)
928         return firstLineBaseline + m_rowPos[0];
929
930     firstLineBaseline = -1;
931     const Row& firstRow = m_grid[0].row;
932     for (size_t i = 0; i < firstRow.size(); ++i) {
933         const CellStruct& cs = firstRow.at(i);
934         const RenderTableCell* cell = cs.primaryCell();
935         // Only cells with content have a baseline
936         if (cell && cell->contentLogicalHeight())
937             firstLineBaseline = std::max<int>(firstLineBaseline, cell->logicalTop() + cell->borderAndPaddingBefore() + cell->contentLogicalHeight());
938     }
939
940     return firstLineBaseline;
941 }
942
943 void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
944 {
945     // put this back in when all layout tests can handle it
946     // ASSERT(!needsLayout());
947     // avoid crashing on bugs that cause us to paint with dirty layout
948     if (needsLayout())
949         return;
950     
951     unsigned totalRows = m_grid.size();
952     unsigned totalCols = table()->columns().size();
953
954     if (!totalRows || !totalCols)
955         return;
956
957     LayoutPoint adjustedPaintOffset = paintOffset + location();
958
959     PaintPhase phase = paintInfo.phase;
960     bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
961     paintObject(paintInfo, adjustedPaintOffset);
962     if (pushedClip)
963         popContentsClip(paintInfo, phase, adjustedPaintOffset);
964
965     if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style().visibility() == VISIBLE)
966         paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
967 }
968
969 static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
970 {
971     return elem1->rowIndex() < elem2->rowIndex();
972 }
973
974 // This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
975 // to sort both on rows and columns to properly repaint.
976 static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
977 {
978     if (elem1->rowIndex() != elem2->rowIndex())
979         return elem1->rowIndex() < elem2->rowIndex();
980
981     return elem1->col() < elem2->col();
982 }
983
984 void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
985 {
986     LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
987     PaintPhase paintPhase = paintInfo.phase;
988     RenderTableRow* row = toRenderTableRow(cell->parent());
989
990     if (paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) {
991         // We need to handle painting a stack of backgrounds.  This stack (from bottom to top) consists of
992         // the column group, column, row group, row, and then the cell.
993         RenderTableCol* column = table()->colElement(cell->col());
994         RenderTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0;
995
996         // Column groups and columns first.
997         // FIXME: Columns and column groups do not currently support opacity, and they are being painted "too late" in
998         // the stack, since we have already opened a transparency layer (potentially) for the table row group.
999         // Note that we deliberately ignore whether or not the cell has a layer, since these backgrounds paint "behind" the
1000         // cell.
1001         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, columnGroup);
1002         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, column);
1003
1004         // Paint the row group next.
1005         cell->paintBackgroundsBehindCell(paintInfo, cellPoint, this);
1006
1007         // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
1008         // painting the row background for the cell.
1009         if (!row->hasSelfPaintingLayer())
1010             cell->paintBackgroundsBehindCell(paintInfo, cellPoint, row);
1011     }
1012     if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()))
1013         cell->paint(paintInfo, cellPoint);
1014 }
1015
1016 LayoutRect RenderTableSection::logicalRectForWritingModeAndDirection(const LayoutRect& rect) const
1017 {
1018     LayoutRect tableAlignedRect(rect);
1019
1020     flipForWritingMode(tableAlignedRect);
1021
1022     if (!style().isHorizontalWritingMode())
1023         tableAlignedRect = tableAlignedRect.transposedRect();
1024
1025     const Vector<int>& columnPos = table()->columnPositions();
1026     // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
1027     if (!style().isLeftToRightDirection())
1028         tableAlignedRect.setX(columnPos[columnPos.size() - 1] - tableAlignedRect.maxX());
1029
1030     return tableAlignedRect;
1031 }
1032
1033 CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const
1034 {
1035     if (m_forceSlowPaintPathWithOverflowingCell) 
1036         return fullTableRowSpan();
1037
1038     CellSpan coveredRows = spannedRows(damageRect, IncludeAllIntersectingCells);
1039
1040     // To repaint the border we might need to repaint first or last row even if they are not spanned themselves.
1041     if (coveredRows.start() >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= damageRect.y())
1042         --coveredRows.start();
1043
1044     if (!coveredRows.end() && m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY())
1045         ++coveredRows.end();
1046
1047     return coveredRows;
1048 }
1049
1050 CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const
1051 {
1052     if (m_forceSlowPaintPathWithOverflowingCell) 
1053         return fullTableColumnSpan();
1054
1055     CellSpan coveredColumns = spannedColumns(damageRect, IncludeAllIntersectingCells);
1056
1057     const Vector<int>& columnPos = table()->columnPositions();
1058     // To repaint the border we might need to repaint first or last column even if they are not spanned themselves.
1059     if (coveredColumns.start() >= columnPos.size() - 1 && columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= damageRect.x())
1060         --coveredColumns.start();
1061
1062     if (!coveredColumns.end() && columnPos[0] - table()->outerBorderStart() <= damageRect.maxX())
1063         ++coveredColumns.end();
1064
1065     return coveredColumns;
1066 }
1067
1068 CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
1069 {
1070     // Find the first row that starts after rect top.
1071     unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - m_rowPos.begin();
1072     if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextRow && m_rowPos[nextRow - 1] == flippedRect.y())
1073         --nextRow;
1074
1075     if (nextRow == m_rowPos.size())
1076         return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); // After all rows.
1077
1078     unsigned startRow = nextRow > 0 ? nextRow - 1 : 0;
1079
1080     // Find the first row that starts after rect bottom.
1081     unsigned endRow;
1082     if (m_rowPos[nextRow] >= flippedRect.maxY())
1083         endRow = nextRow;
1084     else {
1085         endRow = std::upper_bound(m_rowPos.begin() + nextRow, m_rowPos.end(), flippedRect.maxY()) - m_rowPos.begin();
1086         if (endRow == m_rowPos.size())
1087             endRow = m_rowPos.size() - 1;
1088     }
1089
1090     return CellSpan(startRow, endRow);
1091 }
1092
1093 CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect, ShouldIncludeAllIntersectingCells shouldIncludeAllIntersectionCells) const
1094 {
1095     const Vector<int>& columnPos = table()->columnPositions();
1096
1097     // Find the first column that starts after rect left.
1098     // lower_bound doesn't handle the edge between two cells properly as it would wrongly return the
1099     // cell on the logical top/left.
1100     // upper_bound on the other hand properly returns the cell on the logical bottom/right, which also
1101     // matches the behavior of other browsers.
1102     unsigned nextColumn = std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - columnPos.begin();
1103     if (shouldIncludeAllIntersectionCells == IncludeAllIntersectingCells && nextColumn && columnPos[nextColumn - 1] == flippedRect.x())
1104         --nextColumn;
1105
1106     if (nextColumn == columnPos.size())
1107         return CellSpan(columnPos.size() - 1, columnPos.size() - 1); // After all columns.
1108
1109     unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0;
1110
1111     // Find the first column that starts after rect right.
1112     unsigned endColumn;
1113     if (columnPos[nextColumn] >= flippedRect.maxX())
1114         endColumn = nextColumn;
1115     else {
1116         endColumn = std::upper_bound(columnPos.begin() + nextColumn, columnPos.end(), flippedRect.maxX()) - columnPos.begin();
1117         if (endColumn == columnPos.size())
1118             endColumn = columnPos.size() - 1;
1119     }
1120
1121     return CellSpan(startColumn, endColumn);
1122 }
1123
1124 void RenderTableSection::paintRowGroupBorder(const PaintInfo& paintInfo, bool antialias, LayoutRect rect, BoxSide side, CSSPropertyID borderColor, EBorderStyle borderStyle, EBorderStyle tableBorderStyle)
1125 {
1126     if (tableBorderStyle == BHIDDEN)
1127         return;
1128     rect.intersect(paintInfo.rect);
1129     if (rect.isEmpty())
1130         return;
1131     drawLineForBoxSide(paintInfo.context, rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height(), side, style().visitedDependentColor(borderColor), borderStyle, 0, 0, antialias);
1132 }
1133
1134 int RenderTableSection::offsetLeftForRowGroupBorder(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
1135 {
1136     if (style().isHorizontalWritingMode()) {
1137         if (style().isLeftToRightDirection())
1138             return cell ? cell->x().toInt() + cell->width().toInt() : 0; 
1139         return -outerBorderLeft(&style());
1140     }
1141     bool isLastRow = row + 1 == m_grid.size();
1142     return rowGroupRect.width().toInt() - m_rowPos[row + 1] + (isLastRow ? -outerBorderLeft(&style()) : 0);
1143 }
1144
1145 int RenderTableSection::offsetTopForRowGroupBorder(RenderTableCell* cell, BoxSide borderSide, unsigned row)
1146 {
1147     bool isLastRow = row + 1 == m_grid.size();
1148     if (style().isHorizontalWritingMode())
1149         return m_rowPos[row] + (!row && borderSide == BSRight ? -outerBorderTop(&style()) : isLastRow && borderSide == BSLeft ? outerBorderTop(&style()) : 0);
1150     if (style().isLeftToRightDirection())
1151         return (cell ? cell->y().toInt() + cell->height().toInt() : 0) + (borderSide == BSLeft ? outerBorderTop(&style()) : 0);
1152     return borderSide == BSRight ? -outerBorderTop(&style()) : 0;
1153 }
1154
1155 int RenderTableSection::verticalRowGroupBorderHeight(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row)
1156 {
1157     bool isLastRow = row + 1 == m_grid.size();
1158     if (style().isHorizontalWritingMode())
1159         return m_rowPos[row + 1] - m_rowPos[row] + (!row ? outerBorderTop(&style()) : isLastRow ? outerBorderBottom(&style()) : 0);
1160     if (style().isLeftToRightDirection())
1161         return rowGroupRect.height().toInt() - (cell ? cell->y().toInt() + cell->height().toInt() : 0) + outerBorderBottom(&style());
1162     return cell ? rowGroupRect.height().toInt() - (cell->y().toInt() - cell->height().toInt()) : 0;
1163 }
1164
1165 int RenderTableSection::horizontalRowGroupBorderWidth(RenderTableCell* cell, const LayoutRect& rowGroupRect, unsigned row, unsigned column)
1166 {
1167     if (style().isHorizontalWritingMode()) {
1168         if (style().isLeftToRightDirection())
1169             return rowGroupRect.width().toInt() - (cell ? cell->x().toInt() + cell->width().toInt() : 0) + (!column ? outerBorderLeft(&style()) : column == table()->numEffCols() ? outerBorderRight(&style()) : 0);
1170         return cell ? rowGroupRect.width().toInt() - (cell->x().toInt() - cell->width().toInt()) : 0;
1171     }
1172     bool isLastRow = row + 1 == m_grid.size();
1173     return m_rowPos[row + 1] - m_rowPos[row] + (isLastRow ? outerBorderLeft(&style()) : !row ? outerBorderRight(&style()) : 0);
1174 }
1175
1176 void RenderTableSection::paintRowGroupBorderIfRequired(const PaintInfo& paintInfo, const LayoutPoint& paintOffset, unsigned row, unsigned column, BoxSide borderSide, RenderTableCell* cell)
1177 {
1178     if (table()->currentBorderValue()->precedence() > BROWGROUP)
1179         return;
1180     if (paintInfo.context->paintingDisabled())
1181         return;
1182
1183     const RenderStyle& style = this->style();
1184     bool antialias = shouldAntialiasLines(paintInfo.context);
1185     LayoutRect rowGroupRect = LayoutRect(paintOffset, size());
1186     rowGroupRect.moveBy(-LayoutPoint(outerBorderLeft(&style), (borderSide == BSRight) ? 0 : outerBorderTop(&style)));
1187
1188     switch (borderSide) {
1189     case BSTop:
1190         paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y(), 
1191             horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderTop().width()), BSTop, CSSPropertyBorderTopColor, style.borderTopStyle(), table()->style().borderTopStyle());
1192         break;
1193     case BSBottom:
1194         paintRowGroupBorder(paintInfo, antialias, LayoutRect(paintOffset.x() + offsetLeftForRowGroupBorder(cell, rowGroupRect, row), rowGroupRect.y() + rowGroupRect.height(), 
1195             horizontalRowGroupBorderWidth(cell, rowGroupRect, row, column), style.borderBottom().width()), BSBottom, CSSPropertyBorderBottomColor, style.borderBottomStyle(), table()->style().borderBottomStyle());
1196         break;
1197     case BSLeft:
1198         paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderLeft().width(),
1199             verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSLeft, CSSPropertyBorderLeftColor, style.borderLeftStyle(), table()->style().borderLeftStyle());
1200         break;
1201     case BSRight:
1202         paintRowGroupBorder(paintInfo, antialias, LayoutRect(rowGroupRect.x() + rowGroupRect.width(), rowGroupRect.y() + offsetTopForRowGroupBorder(cell, borderSide, row), style.borderRight().width(),
1203             verticalRowGroupBorderHeight(cell, rowGroupRect, row)), BSRight, CSSPropertyBorderRightColor, style.borderRightStyle(), table()->style().borderRightStyle());
1204         break;
1205     default:
1206         break;
1207     }
1208
1209 }
1210
1211 static BoxSide physicalBorderForDirection(RenderStyle* styleForCellFlow, CollapsedBorderSide side)
1212 {
1213
1214     switch (side) {
1215     case CBSStart:
1216         if (styleForCellFlow->isHorizontalWritingMode())
1217             return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1218         return styleForCellFlow->isLeftToRightDirection() ? BSTop : BSBottom;
1219     case CBSEnd:
1220         if (styleForCellFlow->isHorizontalWritingMode())
1221             return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1222         return styleForCellFlow->isLeftToRightDirection() ? BSBottom : BSTop;
1223     case CBSBefore:
1224         if (styleForCellFlow->isHorizontalWritingMode())
1225             return BSTop;
1226         return styleForCellFlow->isLeftToRightDirection() ? BSRight : BSLeft;
1227     case CBSAfter:
1228         if (styleForCellFlow->isHorizontalWritingMode())
1229             return BSBottom;
1230         return styleForCellFlow->isLeftToRightDirection() ? BSLeft : BSRight;
1231     default:
1232         ASSERT_NOT_REACHED();
1233         return BSLeft;
1234     }
1235 }
1236
1237 void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1238 {
1239     PaintPhase paintPhase = paintInfo.phase;
1240
1241     LayoutRect localRepaintRect = paintInfo.rect;
1242     localRepaintRect.moveBy(-paintOffset);
1243     localRepaintRect.inflate(maximalOutlineSize(paintPhase));
1244
1245     LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect);
1246
1247     CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect);
1248     CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect);
1249
1250     if (dirtiedColumns.start() < dirtiedColumns.end()) {
1251         if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
1252             if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1253                 // Collapsed borders are painted from the bottom right to the top left so that precedence
1254                 // due to cell position is respected. We need to paint one row beyond the topmost dirtied
1255                 // row to calculate its collapsed border value.
1256                 unsigned startRow = dirtiedRows.start() ? dirtiedRows.start() - 1 : 0;
1257                 for (unsigned r = dirtiedRows.end(); r > startRow; r--) {
1258                     unsigned row = r - 1;
1259                     bool shouldPaintRowGroupBorder = false;
1260                     for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.start(); c--) {
1261                         unsigned col = c - 1;
1262                         CellStruct& current = cellAt(row, col);
1263                         RenderTableCell* cell = current.primaryCell();
1264                         if (!cell) {
1265                             if (!c)
1266                                 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSStart));
1267                             else if (c == table()->numEffCols())
1268                                 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSEnd));
1269                             shouldPaintRowGroupBorder = true;
1270                             continue;
1271                         }
1272                         if ((row > dirtiedRows.start() && primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && primaryCellAt(row, col - 1) == cell))
1273                             continue;
1274                         
1275                         // If we had a run of null cells paint their corresponding section of the row group's border if necessary. Note that
1276                         // this will only happen once within a row as the null cells will always be clustered together on one end of the row.
1277                         if (shouldPaintRowGroupBorder) {
1278                             if (r == m_grid.size())
1279                                 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSAfter), cell);
1280                             else if (!row && !table()->sectionAbove(this))
1281                                 paintRowGroupBorderIfRequired(paintInfo, paintOffset, row, col, physicalBorderForDirection(&style(), CBSBefore), cell);
1282                             shouldPaintRowGroupBorder = false;
1283                         }
1284
1285                         LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
1286                         cell->paintCollapsedBorders(paintInfo, cellPoint);
1287                     }
1288                 }
1289             } else {
1290                 // Draw the dirty cells in the order that they appear.
1291                 for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
1292                     RenderTableRow* row = m_grid[r].rowRenderer;
1293                     if (row && !row->hasSelfPaintingLayer())
1294                         row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
1295                     for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
1296                         CellStruct& current = cellAt(r, c);
1297                         RenderTableCell* cell = current.primaryCell();
1298                         if (!cell || (r > dirtiedRows.start() && primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && primaryCellAt(r, c - 1) == cell))
1299                             continue;
1300                         paintCell(cell, paintInfo, paintOffset);
1301                     }
1302                 }
1303             }
1304         } else {
1305             // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
1306 #ifndef NDEBUG
1307             unsigned totalRows = m_grid.size();
1308             unsigned totalCols = table()->columns().size();
1309             ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
1310 #endif
1311
1312             // To make sure we properly repaint the section, we repaint all the overflowing cells that we collected.
1313             Vector<RenderTableCell*> cells;
1314             copyToVector(m_overflowingCells, cells);
1315
1316             HashSet<RenderTableCell*> spanningCells;
1317
1318             for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
1319                 RenderTableRow* row = m_grid[r].rowRenderer;
1320                 if (row && !row->hasSelfPaintingLayer())
1321                     row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
1322                 for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
1323                     CellStruct& current = cellAt(r, c);
1324                     if (!current.hasCells())
1325                         continue;
1326                     for (unsigned i = 0; i < current.cells.size(); ++i) {
1327                         if (m_overflowingCells.contains(current.cells[i]))
1328                             continue;
1329
1330                         if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
1331                             if (!spanningCells.add(current.cells[i]).isNewEntry)
1332                                 continue;
1333                         }
1334
1335                         cells.append(current.cells[i]);
1336                     }
1337                 }
1338             }
1339
1340             // Sort the dirty cells by paint order.
1341             if (!m_overflowingCells.size())
1342                 std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
1343             else
1344                 std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
1345
1346             if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
1347                 for (unsigned i = cells.size(); i > 0; --i) {
1348                     LayoutPoint cellPoint = flipForWritingModeForChild(cells[i - 1], paintOffset);
1349                     cells[i - 1]->paintCollapsedBorders(paintInfo, cellPoint);
1350                 }
1351             } else {
1352                 for (unsigned i = 0; i < cells.size(); ++i)
1353                     paintCell(cells[i], paintInfo, paintOffset);
1354             }
1355         }
1356     }
1357 }
1358
1359 void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
1360 {
1361     // FIXME: Examine cells and repaint only the rect the image paints in.
1362     repaint();
1363 }
1364
1365 void RenderTableSection::recalcCells()
1366 {
1367     ASSERT(m_needsCellRecalc);
1368     // We reset the flag here to ensure that addCell() works. This is safe to do because we clear the grid
1369     // and update its dimensions to be consistent with the table's column representation before we rebuild
1370     // the grid using addCell().
1371     m_needsCellRecalc = false;
1372
1373     m_cCol = 0;
1374     m_cRow = 0;
1375     m_grid.clear();
1376
1377     for (RenderTableRow* row = firstRow(); row; row = row->nextRow()) {
1378         unsigned insertionRow = m_cRow;
1379         m_cRow++;
1380         m_cCol = 0;
1381         ensureRows(m_cRow);
1382
1383         m_grid[insertionRow].rowRenderer = row;
1384         row->setRowIndex(insertionRow);
1385         setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
1386
1387         for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell())
1388             addCell(cell, row);
1389     }
1390
1391     m_grid.shrinkToFit();
1392     setNeedsLayout();
1393 }
1394
1395 // FIXME: This function could be made O(1) in certain cases (like for the non-most-constrainive cells' case).
1396 void RenderTableSection::rowLogicalHeightChanged(unsigned rowIndex)
1397 {
1398     if (needsCellRecalc())
1399         return;
1400
1401     setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[rowIndex]);
1402
1403     for (RenderTableCell* cell = m_grid[rowIndex].rowRenderer->firstCell(); cell; cell = cell->nextCell())
1404         updateLogicalHeightForCell(m_grid[rowIndex], cell);
1405 }
1406
1407 void RenderTableSection::setNeedsCellRecalc()
1408 {
1409     m_needsCellRecalc = true;
1410
1411     // Clear the grid now to ensure that we don't hold onto any stale pointers (e.g. a cell renderer that is being removed).
1412     m_grid.clear();
1413
1414     if (RenderTable* t = table())
1415         t->setNeedsSectionRecalc();
1416 }
1417
1418 unsigned RenderTableSection::numColumns() const
1419 {
1420     ASSERT(!m_needsCellRecalc);
1421     unsigned result = 0;
1422     
1423     for (unsigned r = 0; r < m_grid.size(); ++r) {
1424         for (unsigned c = result; c < table()->numEffCols(); ++c) {
1425             const CellStruct& cell = cellAt(r, c);
1426             if (cell.hasCells() || cell.inColSpan)
1427                 result = c;
1428         }
1429     }
1430     
1431     return result + 1;
1432 }
1433
1434 const BorderValue& RenderTableSection::borderAdjoiningStartCell(const RenderTableCell* cell) const
1435 {
1436     ASSERT(cell->isFirstOrLastCellInRow());
1437     return hasSameDirectionAs(cell) ? style().borderStart() : style().borderEnd();
1438 }
1439
1440 const BorderValue& RenderTableSection::borderAdjoiningEndCell(const RenderTableCell* cell) const
1441 {
1442     ASSERT(cell->isFirstOrLastCellInRow());
1443     return hasSameDirectionAs(cell) ? style().borderEnd() : style().borderStart();
1444 }
1445
1446 const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableStart() const
1447 {
1448     unsigned adjoiningStartCellColumnIndex = hasSameDirectionAs(table()) ? 0 : table()->lastColumnIndex();
1449     return cellAt(0, adjoiningStartCellColumnIndex).primaryCell();
1450 }
1451
1452 const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableEnd() const
1453 {
1454     unsigned adjoiningEndCellColumnIndex = hasSameDirectionAs(table()) ? table()->lastColumnIndex() : 0;
1455     return cellAt(0, adjoiningEndCellColumnIndex).primaryCell();
1456 }
1457
1458 void RenderTableSection::appendColumn(unsigned pos)
1459 {
1460     ASSERT(!m_needsCellRecalc);
1461
1462     for (unsigned row = 0; row < m_grid.size(); ++row)
1463         m_grid[row].row.resize(pos + 1);
1464 }
1465
1466 void RenderTableSection::splitColumn(unsigned pos, unsigned first)
1467 {
1468     ASSERT(!m_needsCellRecalc);
1469
1470     if (m_cCol > pos)
1471         m_cCol++;
1472     for (unsigned row = 0; row < m_grid.size(); ++row) {
1473         Row& r = m_grid[row].row;
1474         r.insert(pos + 1, CellStruct());
1475         if (r[pos].hasCells()) {
1476             r[pos + 1].cells.appendVector(r[pos].cells);
1477             RenderTableCell* cell = r[pos].primaryCell();
1478             ASSERT(cell);
1479             ASSERT(cell->colSpan() >= (r[pos].inColSpan ? 1u : 0));
1480             unsigned colleft = cell->colSpan() - r[pos].inColSpan;
1481             if (first > colleft)
1482               r[pos + 1].inColSpan = 0;
1483             else
1484               r[pos + 1].inColSpan = first + r[pos].inColSpan;
1485         } else {
1486             r[pos + 1].inColSpan = 0;
1487         }
1488     }
1489 }
1490
1491 // Hit Testing
1492 bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
1493 {
1494     // If we have no children then we have nothing to do.
1495     if (!firstRow())
1496         return false;
1497
1498     // Table sections cannot ever be hit tested.  Effectively they do not exist.
1499     // Just forward to our children always.
1500     LayoutPoint adjustedLocation = accumulatedOffset + location();
1501
1502     if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment())))
1503         return false;
1504
1505     if (hasOverflowingCell()) {
1506         for (RenderTableRow* row = lastRow(); row; row = row->previousRow()) {
1507             // FIXME: We have to skip over inline flows, since they can show up inside table rows
1508             // at the moment (a demoted inline <form> for example). If we ever implement a
1509             // table-specific hit-test method (which we should do for performance reasons anyway),
1510             // then we can remove this check.
1511             if (!row->hasSelfPaintingLayer()) {
1512                 LayoutPoint childPoint = flipForWritingModeForChild(row, adjustedLocation);
1513                 if (row->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
1514                     updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
1515                     return true;
1516                 }
1517             }
1518         }
1519         return false;
1520     }
1521
1522     recalcCellsIfNeeded();
1523
1524     LayoutRect hitTestRect = locationInContainer.boundingBox();
1525     hitTestRect.moveBy(-adjustedLocation);
1526
1527     LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect);
1528     CellSpan rowSpan = spannedRows(tableAlignedRect, DoNotIncludeAllIntersectingCells);
1529     CellSpan columnSpan = spannedColumns(tableAlignedRect, DoNotIncludeAllIntersectingCells);
1530
1531     // Now iterate over the spanned rows and columns.
1532     for (unsigned hitRow = rowSpan.start(); hitRow < rowSpan.end(); ++hitRow) {
1533         for (unsigned hitColumn = columnSpan.start(); hitColumn < columnSpan.end(); ++hitColumn) {
1534             CellStruct& current = cellAt(hitRow, hitColumn);
1535
1536             // If the cell is empty, there's nothing to do
1537             if (!current.hasCells())
1538                 continue;
1539
1540             for (unsigned i = current.cells.size() ; i; ) {
1541                 --i;
1542                 RenderTableCell* cell = current.cells[i];
1543                 LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
1544                 if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
1545                     updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
1546                     return true;
1547                 }
1548             }
1549             if (!result.isRectBasedTest())
1550                 break;
1551         }
1552         if (!result.isRectBasedTest())
1553             break;
1554     }
1555
1556     return false;
1557 }
1558
1559 void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell* cell)
1560 {
1561     if (!table()->collapseBorders())
1562         return;
1563     
1564     for (int side = CBSBefore; side <= CBSEnd; ++side)
1565         m_cellsCollapsedBorders.remove(std::make_pair(cell, side));
1566 }
1567
1568 void RenderTableSection::setCachedCollapsedBorder(const RenderTableCell* cell, CollapsedBorderSide side, CollapsedBorderValue border)
1569 {
1570     ASSERT(table()->collapseBorders());
1571     m_cellsCollapsedBorders.set(std::make_pair(cell, side), border);
1572 }
1573
1574 CollapsedBorderValue& RenderTableSection::cachedCollapsedBorder(const RenderTableCell* cell, CollapsedBorderSide side)
1575 {
1576     ASSERT(table()->collapseBorders());
1577     HashMap<std::pair<const RenderTableCell*, int>, CollapsedBorderValue>::iterator it = m_cellsCollapsedBorders.find(std::make_pair(cell, side));
1578     ASSERT(it != m_cellsCollapsedBorders.end());
1579     return it->value;
1580 }
1581
1582 RenderTableSection* RenderTableSection::createAnonymousWithParentRenderer(const RenderObject* parent)
1583 {
1584     auto section = new RenderTableSection(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), TABLE_ROW_GROUP));
1585     section->initializeStyle();
1586     return section;
1587 }
1588
1589 void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsigned effectiveColumn) const
1590 {
1591     LayoutPoint oldCellLocation = cell->location();
1592
1593     LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]);
1594     int horizontalBorderSpacing = table()->hBorderSpacing();
1595
1596     // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
1597     if (!style().isLeftToRightDirection())
1598         cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + horizontalBorderSpacing);
1599     else
1600         cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
1601
1602     cell->setLogicalLocation(cellLocation);
1603     view().addLayoutDelta(oldCellLocation - cell->location());
1604 }
1605
1606 } // namespace WebCore