| Index: Source/core/rendering/RenderTableSection.cpp | 
| diff --git a/Source/core/rendering/RenderTableSection.cpp b/Source/core/rendering/RenderTableSection.cpp | 
| index 9bca8347a798ce6c39c6a9ee0f024e9ca4357f41..d8f632d00e89217501a10365948b4e98496c3d98 100644 | 
| --- a/Source/core/rendering/RenderTableSection.cpp | 
| +++ b/Source/core/rendering/RenderTableSection.cpp | 
| @@ -252,6 +252,123 @@ void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row) | 
| cell->setCol(table()->effColToCol(col)); | 
| } | 
|  | 
| +void RenderTableSection::populateSpanningRowsHeightFromCell(RenderTableCell* cell, struct SpanningRowsHeight& spanningRowsHeight) | 
| +{ | 
| +    const unsigned rowSpan = cell->rowSpan(); | 
| +    const unsigned rowIndex = cell->rowIndex(); | 
| + | 
| +    spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing = cell->logicalHeightForRowSizing(); | 
| + | 
| +    spanningRowsHeight.rowHeight.resize(rowSpan); | 
| +    spanningRowsHeight.totalRowsHeight = 0; | 
| +    for (unsigned row = 0; row < rowSpan; row++) { | 
| +        unsigned actualRow = row + rowIndex; | 
| +        spanningRowsHeight.rowHeight[row] = m_rowPos[actualRow + 1] - m_rowPos[actualRow] - borderSpacingForRow(actualRow); | 
| +        spanningRowsHeight.totalRowsHeight += spanningRowsHeight.rowHeight[row]; | 
| +        spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing -= borderSpacingForRow(actualRow); | 
| +    } | 
| +    // We don't span the following row so its border-spacing (if any) should be included. | 
| +    spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing += borderSpacingForRow(rowIndex + rowSpan - 1); | 
| +} | 
| + | 
| +void RenderTableSection::distributeExtraRowSpanHeightToPercentRows(RenderTableCell* cell, int totalPercent, int& extraRowSpanningHeight, Vector<int>& rowsHeight) | 
| +{ | 
| +    if (!extraRowSpanningHeight || !totalPercent) | 
| +        return; | 
| + | 
| +    const unsigned rowSpan = cell->rowSpan(); | 
| +    const unsigned rowIndex = cell->rowIndex(); | 
| +    int percent = min(totalPercent, 100); | 
| +    const int tableHeight = m_rowPos[m_grid.size()] + extraRowSpanningHeight; | 
| + | 
| +    // Our algorithm matches Firefox. Extra spanning height would be distributed Only in first percent height rows | 
| +    // those total percent is 100. Other percent rows would be uneffected even extra spanning height is remain. | 
| +    int accumulatedPositionIncrease = 0; | 
| +    for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 
| +        if (percent > 0 && extraRowSpanningHeight > 0) { | 
| +            if (m_grid[row].logicalHeight.isPercent()) { | 
| +                int toAdd = (tableHeight * m_grid[row].logicalHeight.percent() / 100) - rowsHeight[row - rowIndex]; | 
| +                // FIXME: Note that this is wrong if we have a percentage above 100% and may make us grow | 
| +                // above the available space. | 
| + | 
| +                toAdd = min(toAdd, extraRowSpanningHeight); | 
| +                accumulatedPositionIncrease += toAdd; | 
| +                extraRowSpanningHeight -= toAdd; | 
| +                percent -= m_grid[row].logicalHeight.percent(); | 
| +            } | 
| +        } | 
| +        m_rowPos[row + 1] += accumulatedPositionIncrease; | 
| +    } | 
| +} | 
| + | 
| +void RenderTableSection::distributeExtraRowSpanHeightToAutoRows(RenderTableCell* cell, int totalAutoRowsHeight, int& extraRowSpanningHeight, Vector<int>& rowsHeight) | 
| +{ | 
| +    if (!extraRowSpanningHeight || !totalAutoRowsHeight) | 
| +        return; | 
| + | 
| +    const unsigned rowSpan = cell->rowSpan(); | 
| +    const unsigned rowIndex = cell->rowIndex(); | 
| +    int accumulatedPositionIncrease = 0; | 
| +    int remainder = 0; | 
| + | 
| +    // Aspect ratios of auto rows should not change otherwise table may look different than user expected. | 
| +    // So extra height distributed in auto spanning rows based on their weight in spanning cell. | 
| +    for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 
| +        if (m_grid[row].logicalHeight.isAuto()) { | 
| +            accumulatedPositionIncrease += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) / totalAutoRowsHeight; | 
| +            remainder += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) % totalAutoRowsHeight; | 
| + | 
| +            // While whole extra spanning height is distributing in auto spanning rows, rational parts remains | 
| +            // in every integer division. So accumulating all remainder part in integer division and when total remainder | 
| +            // is equvalent to divisor then 1 unit increased in row position. | 
| +            // Note that this algorithm is biased towards adding more space towards the lower rows. | 
| +            if (remainder >= totalAutoRowsHeight) { | 
| +                remainder -= totalAutoRowsHeight; | 
| +                accumulatedPositionIncrease++; | 
| +            } | 
| +        } | 
| +        m_rowPos[row + 1] += accumulatedPositionIncrease; | 
| +    } | 
| + | 
| +    ASSERT(!remainder); | 
| + | 
| +    extraRowSpanningHeight -= accumulatedPositionIncrease; | 
| +} | 
| + | 
| +void RenderTableSection::distributeExtraRowSpanHeightToRemainingRows(RenderTableCell* cell, int totalRemainingRowsHeight, int& extraRowSpanningHeight, Vector<int>& rowsHeight) | 
| +{ | 
| +    if (!extraRowSpanningHeight || !totalRemainingRowsHeight) | 
| +        return; | 
| + | 
| +    const unsigned rowSpan = cell->rowSpan(); | 
| +    const unsigned rowIndex = cell->rowIndex(); | 
| +    int accumulatedPositionIncrease = 0; | 
| +    int remainder = 0; | 
| + | 
| +    // Aspect ratios of the rows should not change otherwise table may look different than user expected. | 
| +    // So extra height distribution in remaining spanning rows based on their weight in spanning cell. | 
| +    for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 
| +        if (!m_grid[row].logicalHeight.isPercent()) { | 
| +            accumulatedPositionIncrease += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) / totalRemainingRowsHeight; | 
| +            remainder += (extraRowSpanningHeight * rowsHeight[row - rowIndex]) % totalRemainingRowsHeight; | 
| + | 
| +            // While whole extra spanning height is distributing in remaining spanning rows, rational parts remains | 
| +            // in every integer division. So accumulating all remainder part in integer division and when total remainder | 
| +            // is equvalent to divisor then 1 unit increased in row position. | 
| +            // Note that this algorithm is biased towards adding more space towards the lower rows. | 
| +            if (remainder >= totalRemainingRowsHeight) { | 
| +                remainder -= totalRemainingRowsHeight; | 
| +                accumulatedPositionIncrease++; | 
| +            } | 
| +        } | 
| +        m_rowPos[row + 1] += accumulatedPositionIncrease; | 
| +    } | 
| + | 
| +    ASSERT(!remainder); | 
| + | 
| +    extraRowSpanningHeight -= accumulatedPositionIncrease; | 
| +} | 
| + | 
| // Distribute rowSpan cell height in rows those comes in rowSpan cell based on the ratio of row's height if | 
| // 1. RowSpan cell height is greater then the total height of rows in rowSpan cell | 
| void RenderTableSection::distributeRowSpanHeightToRows(SpanningRenderTableCells& rowSpanCells) | 
| @@ -262,38 +379,40 @@ void RenderTableSection::distributeRowSpanHeightToRows(SpanningRenderTableCells& | 
| RenderTableCell* cell = rowSpanCells[0]; | 
|  | 
| unsigned rowSpan = cell->rowSpan(); | 
| -    unsigned rowIndex = cell->rowIndex(); | 
| -    int initialPos = m_rowPos[rowIndex + rowSpan]; | 
|  | 
| -    int totalRowsHeight = 0; | 
| -    int rowSpanCellHeight = cell->logicalHeightForRowSizing(); | 
| -    Vector<int> rowsHeight(rowSpan); | 
| +    struct SpanningRowsHeight spanningRowsHeight; | 
|  | 
| -    // Getting height of rows in current rowSpan cell, getting total height of rows and adjusting rowSpan cell height with border spacing. | 
| -    for (unsigned row = 0; row < rowSpan; row++) { | 
| -        unsigned actualRow = row + rowIndex; | 
| -        rowsHeight[row] = m_rowPos[actualRow + 1] - m_rowPos[actualRow] - borderSpacingForRow(actualRow); | 
| -        totalRowsHeight += rowsHeight[row]; | 
| -        rowSpanCellHeight -= borderSpacingForRow(actualRow); | 
| -    } | 
| -    rowSpanCellHeight += borderSpacingForRow(rowIndex + rowSpan - 1); | 
| +    populateSpanningRowsHeightFromCell(cell, spanningRowsHeight); | 
|  | 
| -    if (!totalRowsHeight || rowSpanCellHeight <= totalRowsHeight) | 
| +    if (!spanningRowsHeight.totalRowsHeight || spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing <= spanningRowsHeight.totalRowsHeight) | 
| return; | 
|  | 
| -    // Recalculating the height of rows based on rowSpan cell height if rowSpan cell height is more than total height of rows. | 
| -    int remainingHeight = rowSpanCellHeight; | 
| +    unsigned rowIndex = cell->rowIndex(); | 
| +    int totalPercent = 0; | 
| +    int totalAutoRowsHeight = 0; | 
| +    int totalRemainingRowsHeight = spanningRowsHeight.totalRowsHeight; | 
|  | 
| +    // Calculate total percentage, total auto rows height and total rows height except percent rows. | 
| for (unsigned row = rowIndex; row < (rowIndex + rowSpan); row++) { | 
| -        int rowHeight = (rowSpanCellHeight * rowsHeight[row - rowIndex]) / totalRowsHeight; | 
| -        remainingHeight -= rowHeight; | 
| -        m_rowPos[row + 1] = m_rowPos[row] + rowHeight + borderSpacingForRow(row); | 
| +        if (m_grid[row].logicalHeight.isPercent()) { | 
| +            totalPercent += m_grid[row].logicalHeight.percent(); | 
| +            totalRemainingRowsHeight -= spanningRowsHeight.rowHeight[row - rowIndex]; | 
| +        } else if (m_grid[row].logicalHeight.isAuto()) { | 
| +            totalAutoRowsHeight += spanningRowsHeight.rowHeight[row - rowIndex]; | 
| +        } | 
| } | 
| -    // Remaining height added in the last row under rowSpan cell | 
| -    m_rowPos[rowIndex + rowSpan] += remainingHeight; | 
| + | 
| +    int initialPos = m_rowPos[rowIndex + rowSpan]; | 
| +    int extraRowSpanningHeight = spanningRowsHeight.spanningCellHeightIgnoringBorderSpacing - spanningRowsHeight.totalRowsHeight; | 
| + | 
| +    distributeExtraRowSpanHeightToPercentRows(cell, totalPercent, extraRowSpanningHeight, spanningRowsHeight.rowHeight); | 
| +    distributeExtraRowSpanHeightToAutoRows(cell, totalAutoRowsHeight, extraRowSpanningHeight, spanningRowsHeight.rowHeight); | 
| +    distributeExtraRowSpanHeightToRemainingRows(cell, totalRemainingRowsHeight, extraRowSpanningHeight, spanningRowsHeight.rowHeight); | 
| + | 
| +    ASSERT(!extraRowSpanningHeight); | 
|  | 
| // Getting total changed height in the table | 
| -    unsigned changedHeight = changedHeight = m_rowPos[rowIndex + rowSpan] - initialPos; | 
| +    unsigned changedHeight = m_rowPos[rowIndex + rowSpan] - initialPos; | 
|  | 
| if (changedHeight) { | 
| unsigned totalRows = m_grid.size(); | 
|  |