Skip to content
Permalink
Browse files
Extract the logic for computing the dirty rows / columns out of Rende…
…rTableSection::paintObject

https://bugs.webkit.org/show_bug.cgi?id=79580

Reviewed by Eric Seidel.

Refactoring only.

* rendering/RenderTableSection.h:
(CellSpan):
(WebCore::CellSpan::CellSpan):
(WebCore::CellSpan::start):
(WebCore::CellSpan::end):
Added this class to hold the span information.

(WebCore::RenderTableSection::fullTableRowSpan):
(WebCore::RenderTableSection::fullTableColumnSpan):
Those functions return the span corresponding to the full table.

* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::dirtiedRows):
(WebCore::RenderTableSection::dirtiedColumns):
Those functions compute the rows / columns impacted by a |damageRect|. On the slow painting path, they
return the full table span.

(WebCore::RenderTableSection::paintObject):
Updated this function to call the new ones. Also we now inflate the local rectangle with the outlineSize.
This wasn't done previously and we had to manually patch some size comparison to account for the outline.


Canonical link: https://commits.webkit.org/96806@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@109042 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
Julien Chaffraix committed Feb 28, 2012
1 parent 39f9cf3 commit 0a1be385da1f5714b784dfdc7b5c7a5ee1c98b38
Showing with 125 additions and 53 deletions.
  1. +30 −0 Source/WebCore/ChangeLog
  2. +72 −53 Source/WebCore/rendering/RenderTableSection.cpp
  3. +23 −0 Source/WebCore/rendering/RenderTableSection.h
@@ -1,3 +1,33 @@
2012-02-27 Julien Chaffraix <jchaffraix@webkit.org>

Extract the logic for computing the dirty rows / columns out of RenderTableSection::paintObject
https://bugs.webkit.org/show_bug.cgi?id=79580

Reviewed by Eric Seidel.

Refactoring only.

* rendering/RenderTableSection.h:
(CellSpan):
(WebCore::CellSpan::CellSpan):
(WebCore::CellSpan::start):
(WebCore::CellSpan::end):
Added this class to hold the span information.

(WebCore::RenderTableSection::fullTableRowSpan):
(WebCore::RenderTableSection::fullTableColumnSpan):
Those functions return the span corresponding to the full table.

* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::dirtiedRows):
(WebCore::RenderTableSection::dirtiedColumns):
Those functions compute the rows / columns impacted by a |damageRect|. On the slow painting path, they
return the full table span.

(WebCore::RenderTableSection::paintObject):
Updated this function to call the new ones. Also we now inflate the local rectangle with the outlineSize.
This wasn't done previously and we had to manually patch some size comparison to account for the outline.

2012-02-27 Kentaro Hara <haraken@chromium.org>

Rename resolve-supplemental.pl to preprocess-idls.pl
@@ -993,17 +993,63 @@ void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo,
cell->paint(paintInfo, cellPoint);
}

void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const
{
// Check which rows and cols are visible and only paint these.
unsigned totalRows = m_grid.size();
unsigned totalCols = table()->columns().size();
if (m_forceSlowPaintPathWithOverflowingCell)
return fullTableRowSpan();

PaintPhase paintPhase = paintInfo.phase;
LayoutUnit before = style()->isHorizontalWritingMode() ? damageRect.y() : damageRect.x();

// binary search to find a row
unsigned startRow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), before) - m_rowPos.begin();

// The binary search above gives us the first row with
// a y position >= the top of the paint rect. Thus, the previous
// may need to be repainted as well.
if (startRow == m_rowPos.size() || (startRow > 0 && (m_rowPos[startRow] > before)))
--startRow;

LayoutUnit after = (style()->isHorizontalWritingMode() ? damageRect.maxY() : damageRect.maxX());
unsigned endRow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), after) - m_rowPos.begin();
if (endRow == m_rowPos.size())
--endRow;

if (!endRow && m_rowPos[0] - table()->outerBorderBefore() <= after)
++endRow;

return CellSpan(startRow, endRow);
}


CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const
{
if (m_forceSlowPaintPathWithOverflowingCell)
return fullTableColumnSpan();

// FIXME: Implement RTL.
if (!style()->isLeftToRightDirection())
return fullTableColumnSpan();

LayoutUnit os = 2 * maximalOutlineSize(paintPhase);
unsigned startrow = 0;
unsigned endrow = totalRows;
LayoutUnit start = style()->isHorizontalWritingMode() ? damageRect.x() : damageRect.y();
Vector<int>& columnPos = table()->columnPositions();
unsigned startCol = std::lower_bound(columnPos.begin(), columnPos.end(), start) - columnPos.begin();
if ((startCol == columnPos.size()) || (startCol > 0 && (columnPos[startCol] > start)))
--startCol;

LayoutUnit end = (style()->isHorizontalWritingMode() ? damageRect.maxX() : damageRect.maxY());
unsigned endCol = std::lower_bound(columnPos.begin(), columnPos.end(), end) - columnPos.begin();
if (endCol == columnPos.size())
--endCol;

if (!endCol && columnPos[0] - table()->outerBorderStart() <= end)
++endCol;

return CellSpan(startCol, endCol);
}

void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
PaintPhase paintPhase = paintInfo.phase;

LayoutRect localRepaintRect = paintInfo.rect;
localRepaintRect.moveBy(-paintOffset);
@@ -1014,91 +1060,64 @@ void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& pa
localRepaintRect.setX(width() - localRepaintRect.maxX());
}

if (!m_forceSlowPaintPathWithOverflowingCell) {
LayoutUnit before = (style()->isHorizontalWritingMode() ? localRepaintRect.y() : localRepaintRect.x()) - os;
// binary search to find a row
startrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), before) - m_rowPos.begin();

// The binary search above gives us the first row with
// a y position >= the top of the paint rect. Thus, the previous
// may need to be repainted as well.
if (startrow == m_rowPos.size() || (startrow > 0 && (m_rowPos[startrow] > before)))
--startrow;
// FIXME: Why do we double the outline size?
LayoutUnit outlineSize = 2 * maximalOutlineSize(paintPhase);
localRepaintRect.inflate(outlineSize);

LayoutUnit after = (style()->isHorizontalWritingMode() ? localRepaintRect.maxY() : localRepaintRect.maxX()) + os;
endrow = std::lower_bound(m_rowPos.begin(), m_rowPos.end(), after) - m_rowPos.begin();
if (endrow == m_rowPos.size())
--endrow;

if (!endrow && m_rowPos[0] - table()->outerBorderBefore() <= after)
++endrow;
}
CellSpan dirtiedRows = this->dirtiedRows(localRepaintRect);
CellSpan dirtiedColumns = this->dirtiedColumns(localRepaintRect);

unsigned startcol = 0;
unsigned endcol = totalCols;
// FIXME: Implement RTL.
if (!m_forceSlowPaintPathWithOverflowingCell && style()->isLeftToRightDirection()) {
LayoutUnit start = (style()->isHorizontalWritingMode() ? localRepaintRect.x() : localRepaintRect.y()) - os;
Vector<int>& columnPos = table()->columnPositions();
startcol = std::lower_bound(columnPos.begin(), columnPos.end(), start) - columnPos.begin();
if ((startcol == columnPos.size()) || (startcol > 0 && (columnPos[startcol] > start)))
--startcol;

LayoutUnit end = (style()->isHorizontalWritingMode() ? localRepaintRect.maxX() : localRepaintRect.maxY()) + os;
endcol = std::lower_bound(columnPos.begin(), columnPos.end(), end) - columnPos.begin();
if (endcol == columnPos.size())
--endcol;

if (!endcol && columnPos[0] - table()->outerBorderStart() <= end)
++endcol;
}
if (startcol < endcol) {
if (dirtiedColumns.start() < dirtiedColumns.end()) {
if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
// Collapsed borders are painted from the bottom right to the top left so that precedence
// due to cell position is respected.
for (unsigned r = endrow; r > startrow; r--) {
for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r--) {
unsigned row = r - 1;
for (unsigned c = endcol; c > startcol; c--) {
for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.start(); c--) {
unsigned col = c - 1;
CellStruct& current = cellAt(row, col);
RenderTableCell* cell = current.primaryCell();
if (!cell || (row > startrow && primaryCellAt(row - 1, col) == cell) || (col > startcol && primaryCellAt(row, col - 1) == cell))
if (!cell || (row > dirtiedRows.start() && primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && primaryCellAt(row, col - 1) == cell))
continue;
LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
cell->paintCollapsedBorders(paintInfo, cellPoint);
}
}
} else {
// Draw the dirty cells in the order that they appear.
for (unsigned r = startrow; r < endrow; r++) {
for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
RenderTableRow* row = m_grid[r].rowRenderer;
if (row && !row->hasSelfPaintingLayer())
row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
for (unsigned c = startcol; c < endcol; c++) {
for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
CellStruct& current = cellAt(r, c);
RenderTableCell* cell = current.primaryCell();
if (!cell || (r > startrow && primaryCellAt(r - 1, c) == cell) || (c > startcol && primaryCellAt(r, c - 1) == cell))
if (!cell || (r > dirtiedRows.start() && primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && primaryCellAt(r, c - 1) == cell))
continue;
paintCell(cell, paintInfo, paintOffset);
}
}
}
} else {
// The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
#ifndef NDEBUG
unsigned totalRows = m_grid.size();
unsigned totalCols = table()->columns().size();
ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
#endif

// To make sure we properly repaint the section, we repaint all the overflowing cells that we collected.
Vector<RenderTableCell*> cells;
copyToVector(m_overflowingCells, cells);

HashSet<RenderTableCell*> spanningCells;

for (unsigned r = startrow; r < endrow; r++) {
for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
RenderTableRow* row = m_grid[r].rowRenderer;
if (row && !row->hasSelfPaintingLayer())
row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
for (unsigned c = startcol; c < endcol; c++) {
for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
CellStruct& current = cellAt(r, c);
if (!current.hasCells())
continue;
@@ -37,6 +37,23 @@ enum CollapsedBorderSide {
CBSEnd
};

// Helper class for paintObject.
class CellSpan {
public:
CellSpan(unsigned start, unsigned end)
: m_start(start)
, m_end(end)
{
}

unsigned start() const { return m_start; }
unsigned end() const { return m_end; }

private:
unsigned m_start;
unsigned m_end;
};

class RenderTableCell;
class RenderTableRow;

@@ -170,6 +187,12 @@ class RenderTableSection : public RenderBox {

bool hasOverflowingCell() const { return m_overflowingCells.size() || m_forceSlowPaintPathWithOverflowingCell; }

CellSpan fullTableRowSpan() const { return CellSpan(0, m_grid.size()); }
CellSpan fullTableColumnSpan() const { return CellSpan(0, table()->columns().size()); }

CellSpan dirtiedRows(const LayoutRect& repaintRect) const;
CellSpan dirtiedColumns(const LayoutRect& repaintRect) const;

RenderObjectChildList m_children;

Vector<RowStruct> m_grid;

0 comments on commit 0a1be38

Please sign in to comment.