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