Skip to content

Commit

Permalink
Extract the logic for computing the dirty rows / columns out of Rende…
Browse files Browse the repository at this point in the history
…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 0a1be38
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 53 deletions.
30 changes: 30 additions & 0 deletions Source/WebCore/ChangeLog
@@ -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
Expand Down
125 changes: 72 additions & 53 deletions Source/WebCore/rendering/RenderTableSection.cpp
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
23 changes: 23 additions & 0 deletions Source/WebCore/rendering/RenderTableSection.h
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 0a1be38

Please sign in to comment.