summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderTableRow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/rendering/RenderTableRow.cpp')
-rw-r--r--Source/WebCore/rendering/RenderTableRow.cpp156
1 files changed, 106 insertions, 50 deletions
diff --git a/Source/WebCore/rendering/RenderTableRow.cpp b/Source/WebCore/rendering/RenderTableRow.cpp
index 741aaac09..9ed1f6a85 100644
--- a/Source/WebCore/rendering/RenderTableRow.cpp
+++ b/Source/WebCore/rendering/RenderTableRow.cpp
@@ -38,15 +38,15 @@ namespace WebCore {
using namespace HTMLNames;
-RenderTableRow::RenderTableRow(Element& element, PassRef<RenderStyle> style)
- : RenderBox(element, std::move(style), 0)
+RenderTableRow::RenderTableRow(Element& element, RenderStyle&& style)
+ : RenderBox(element, WTFMove(style), 0)
, m_rowIndex(unsetRowIndex)
{
setInline(false);
}
-RenderTableRow::RenderTableRow(Document& document, PassRef<RenderStyle> style)
- : RenderBox(document, std::move(style), 0)
+RenderTableRow::RenderTableRow(Document& document, RenderStyle&& style)
+ : RenderBox(document, WTFMove(style), 0)
, m_rowIndex(unsetRowIndex)
{
setInline(false);
@@ -78,12 +78,11 @@ void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* old
section()->rowLogicalHeightChanged(rowIndex());
// If border was changed, notify table.
- if (parent()) {
- RenderTable* table = this->table();
- if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style().border())
+ if (RenderTable* table = this->table()) {
+ if (oldStyle && oldStyle->border() != style().border())
table->invalidateCollapsedBorders();
-
- if (table && oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, &style())) {
+
+ if (oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, &style())) {
// If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
// This only happens when borders are collapsed, since they end up affecting the border sides of the cell
// itself.
@@ -93,49 +92,59 @@ void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* old
}
}
-const BorderValue& RenderTableRow::borderAdjoiningStartCell(const RenderTableCell* cell) const
+const BorderValue& RenderTableRow::borderAdjoiningStartCell(const RenderTableCell& cell) const
{
- ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
+ ASSERT_UNUSED(cell, cell.isFirstOrLastCellInRow());
// FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
return style().borderStart();
}
-const BorderValue& RenderTableRow::borderAdjoiningEndCell(const RenderTableCell* cell) const
+const BorderValue& RenderTableRow::borderAdjoiningEndCell(const RenderTableCell& cell) const
{
- ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
+ ASSERT_UNUSED(cell, cell.isFirstOrLastCellInRow());
// FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
return style().borderEnd();
}
void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
{
- if (!child->isTableCell()) {
+ if (!is<RenderTableCell>(*child)) {
RenderObject* last = beforeChild;
if (!last)
last = lastCell();
- if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
- RenderTableCell* cell = toRenderTableCell(last);
- if (beforeChild == cell)
- beforeChild = cell->firstChild();
- cell->addChild(child, beforeChild);
+ if (last && last->isAnonymous() && is<RenderTableCell>(*last) && !last->isBeforeOrAfterContent()) {
+ RenderTableCell& cell = downcast<RenderTableCell>(*last);
+ if (beforeChild == &cell)
+ beforeChild = cell.firstChild();
+ cell.addChild(child, beforeChild);
return;
}
if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
RenderObject* cell = beforeChild->previousSibling();
- if (cell && cell->isTableCell() && cell->isAnonymous()) {
- toRenderTableCell(cell)->addChild(child);
+ if (is<RenderTableCell>(cell) && cell->isAnonymous()) {
+ downcast<RenderTableCell>(*cell).addChild(child);
return;
}
}
- // If beforeChild is inside an anonymous cell, insert into the cell.
- if (last && !last->isTableCell() && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
- last->parent()->addChild(child, beforeChild);
- return;
+ // Try to find an anonymous container for the child.
+ if (last && last->parent() && last->parent()->isAnonymous() && !last->parent()->isBeforeOrAfterContent()) {
+ // If beforeChild is inside an anonymous cell, insert into the cell.
+ if (!is<RenderTableCell>(*last)) {
+ last->parent()->addChild(child, beforeChild);
+ return;
+ }
+ // If beforeChild is inside an anonymous row, insert into the row.
+ auto& parent = *last->parent();
+ if (is<RenderTableRow>(parent)) {
+ auto* cell = RenderTableCell::createAnonymousWithParentRenderer(*this).release();
+ parent.addChild(cell, beforeChild);
+ cell->addChild(child);
+ return;
+ }
}
-
- RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
+ auto* cell = RenderTableCell::createAnonymousWithParentRenderer(*this).release();
addChild(cell, beforeChild);
cell->addChild(child);
return;
@@ -144,17 +153,19 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
if (beforeChild && beforeChild->parent() != this)
beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
- RenderTableCell* cell = toRenderTableCell(child);
+ RenderTableCell& cell = downcast<RenderTableCell>(*child);
// Generated content can result in us having a null section so make sure to null check our parent.
- if (parent())
- section()->addCell(cell, this);
+ if (RenderTableSection* section = this->section())
+ section->addCell(&cell, this);
- ASSERT(!beforeChild || beforeChild->isTableCell());
- RenderBox::addChild(cell, beforeChild);
+ ASSERT(!beforeChild || is<RenderTableCell>(*beforeChild));
+ RenderBox::addChild(&cell, beforeChild);
if (beforeChild || nextRow())
section()->setNeedsCellRecalc();
+ if (RenderTable* table = this->table())
+ table->invalidateCollapsedBorders();
}
void RenderTableRow::layout()
@@ -168,15 +179,17 @@ void RenderTableRow::layout()
bool paginated = view().layoutState()->isPaginated();
for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
- if (!cell->needsLayout() && paginated && view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
+ if (!cell->needsLayout() && paginated && (view().layoutState()->pageLogicalHeightChanged() || (view().layoutState()->pageLogicalHeight() && view().layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())))
cell->setChildNeedsLayout(MarkOnlyThis);
if (cell->needsLayout()) {
- cell->computeAndSetBlockDirectionMargins(table());
+ cell->computeAndSetBlockDirectionMargins(*table());
cell->layout();
}
}
+ clearOverflow();
+ addVisualEffectOverflow();
// We only ever need to repaint if our cells didn't, which menas that they didn't need
// layout, so we know that our bounds didn't change. This code is just making up for
// the fact that we did not repaint in setStyle() because we had a layout hint.
@@ -195,18 +208,16 @@ void RenderTableRow::layout()
LayoutRect RenderTableRow::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
{
ASSERT(parent());
-
- if (repaintContainer == this)
- return RenderBox::clippedOverflowRectForRepaint(repaintContainer);
-
- // For now, just repaint the whole table.
- // FIXME: Find a better way to do this, e.g., need to repaint all the cells that we
- // might have propagated a background color into.
- // FIXME: do repaintContainer checks here
- if (RenderTable* parentTable = table())
- return parentTable->clippedOverflowRectForRepaint(repaintContainer);
-
- return LayoutRect();
+ // Rows and cells are in the same coordinate space. We need to both compute our overflow rect (which
+ // will accommodate a row outline and any visual effects on the row itself), but we also need to add in
+ // the repaint rects of cells.
+ LayoutRect result = RenderBox::clippedOverflowRectForRepaint(repaintContainer);
+ for (RenderTableCell* cell = firstCell(); cell; cell = cell->nextCell()) {
+ // Even if a cell is a repaint container, it's the row that paints the background behind it.
+ // So we don't care if a cell is a repaintContainer here.
+ result.uniteIfNonZero(cell->clippedOverflowRectForRepaint(repaintContainer));
+ }
+ return result;
}
// Hit Testing
@@ -259,11 +270,56 @@ void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
repaint();
}
-RenderTableRow* RenderTableRow::createAnonymousWithParentRenderer(const RenderObject* parent)
+std::unique_ptr<RenderTableRow> RenderTableRow::createTableRowWithStyle(Document& document, const RenderStyle& style)
{
- auto newRow = new RenderTableRow(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), TABLE_ROW));
- newRow->initializeStyle();
- return newRow;
+ auto row = std::make_unique<RenderTableRow>(document, RenderStyle::createAnonymousStyleWithDisplay(style, TABLE_ROW));
+ row->initializeStyle();
+ return row;
+}
+
+std::unique_ptr<RenderTableRow> RenderTableRow::createAnonymousWithParentRenderer(const RenderTableSection& parent)
+{
+ return RenderTableRow::createTableRowWithStyle(parent.document(), parent.style());
+}
+
+void RenderTableRow::destroyAndCollapseAnonymousSiblingRows()
+{
+ auto collapseAnonymousSiblingRows = [&] {
+ auto* section = this->section();
+ if (!section)
+ return;
+
+ // All siblings generated?
+ for (auto* current = section->firstRow(); current; current = current->nextRow()) {
+ if (current == this)
+ continue;
+ if (!current->isAnonymous())
+ return;
+ }
+
+ RenderTableRow* rowToInsertInto = nullptr;
+ auto* currentRow = section->firstRow();
+ while (currentRow) {
+ if (currentRow == this) {
+ currentRow = currentRow->nextRow();
+ continue;
+ }
+ if (!rowToInsertInto) {
+ rowToInsertInto = currentRow;
+ currentRow = currentRow->nextRow();
+ continue;
+ }
+ currentRow->moveAllChildrenTo(rowToInsertInto);
+ auto* destroyThis = currentRow;
+ currentRow = currentRow->nextRow();
+ destroyThis->destroy();
+ }
+ if (rowToInsertInto)
+ rowToInsertInto->setNeedsLayout();
+ };
+
+ collapseAnonymousSiblingRows();
+ destroy();
}
} // namespace WebCore