summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/RenderTable.cpp
diff options
context:
space:
mode:
authorKonstantin Tokarev <annulen@yandex.ru>2016-08-25 19:20:41 +0300
committerKonstantin Tokarev <annulen@yandex.ru>2017-02-02 12:30:55 +0000
commit6882a04fb36642862b11efe514251d32070c3d65 (patch)
treeb7959826000b061fd5ccc7512035c7478742f7b0 /Source/WebCore/rendering/RenderTable.cpp
parentab6df191029eeeb0b0f16f127d553265659f739e (diff)
downloadqtwebkit-6882a04fb36642862b11efe514251d32070c3d65.tar.gz
Imported QtWebKit TP3 (git b57bc6801f1876c3220d5a4bfea33d620d477443)
Change-Id: I3b1d8a2808782c9f34d50240000e20cb38d3680f Reviewed-by: Konstantin Tokarev <annulen@yandex.ru>
Diffstat (limited to 'Source/WebCore/rendering/RenderTable.cpp')
-rw-r--r--Source/WebCore/rendering/RenderTable.cpp721
1 files changed, 432 insertions, 289 deletions
diff --git a/Source/WebCore/rendering/RenderTable.cpp b/Source/WebCore/rendering/RenderTable.cpp
index 336b6c995..05325314a 100644
--- a/Source/WebCore/rendering/RenderTable.cpp
+++ b/Source/WebCore/rendering/RenderTable.cpp
@@ -4,7 +4,7 @@
* (C) 1998 Waldo Bastian (bastian@kde.org)
* (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2014 Apple Inc. All rights reserved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
*
* This library is free software; you can redistribute it and/or
@@ -35,7 +35,9 @@
#include "HTMLNames.h"
#include "HTMLTableElement.h"
#include "LayoutRepainter.h"
+#include "RenderIterator.h"
#include "RenderLayer.h"
+#include "RenderNamedFlowFragment.h"
#include "RenderTableCaption.h"
#include "RenderTableCell.h"
#include "RenderTableCol.h"
@@ -44,23 +46,47 @@
#include "StyleInheritedData.h"
#include <wtf/StackStats.h>
-using namespace std;
-
namespace WebCore {
using namespace HTMLNames;
-RenderTable::RenderTable(Element* element)
- : RenderBlock(element)
- , m_head(0)
- , m_foot(0)
- , m_firstBody(0)
- , m_currentBorder(0)
+RenderTable::RenderTable(Element& element, Ref<RenderStyle>&& style)
+ : RenderBlock(element, WTFMove(style), 0)
+ , m_head(nullptr)
+ , m_foot(nullptr)
+ , m_firstBody(nullptr)
+ , m_currentBorder(nullptr)
, m_collapsedBordersValid(false)
+ , m_collapsedEmptyBorderIsPresent(false)
, m_hasColElements(false)
, m_needsSectionRecalc(false)
, m_columnLogicalWidthChanged(false)
, m_columnRenderersValid(false)
+ , m_hasCellColspanThatDeterminesTableWidth(false)
+ , m_hSpacing(0)
+ , m_vSpacing(0)
+ , m_borderStart(0)
+ , m_borderEnd(0)
+ , m_columnOffsetTop(-1)
+ , m_columnOffsetHeight(-1)
+{
+ setChildrenInline(false);
+ m_columnPos.fill(0, 1);
+}
+
+RenderTable::RenderTable(Document& document, Ref<RenderStyle>&& style)
+ : RenderBlock(document, WTFMove(style), 0)
+ , m_head(nullptr)
+ , m_foot(nullptr)
+ , m_firstBody(nullptr)
+ , m_currentBorder(nullptr)
+ , m_collapsedBordersValid(false)
+ , m_collapsedEmptyBorderIsPresent(false)
+ , m_hasColElements(false)
+ , m_needsSectionRecalc(false)
+ , m_columnLogicalWidthChanged(false)
+ , m_columnRenderersValid(false)
+ , m_hasCellColspanThatDeterminesTableWidth(false)
, m_hSpacing(0)
, m_vSpacing(0)
, m_borderStart(0)
@@ -68,7 +94,6 @@ RenderTable::RenderTable(Element* element)
{
setChildrenInline(false);
m_columnPos.fill(0, 1);
-
}
RenderTable::~RenderTable()
@@ -78,26 +103,26 @@ RenderTable::~RenderTable()
void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
RenderBlock::styleDidChange(diff, oldStyle);
- propagateStyleToAnonymousChildren();
+ propagateStyleToAnonymousChildren(PropagateToAllChildren);
ETableLayout oldTableLayout = oldStyle ? oldStyle->tableLayout() : TAUTO;
// In the collapsed border model, there is no cell spacing.
- m_hSpacing = collapseBorders() ? 0 : style()->horizontalBorderSpacing();
- m_vSpacing = collapseBorders() ? 0 : style()->verticalBorderSpacing();
+ m_hSpacing = collapseBorders() ? 0 : style().horizontalBorderSpacing();
+ m_vSpacing = collapseBorders() ? 0 : style().verticalBorderSpacing();
m_columnPos[0] = m_hSpacing;
- if (!m_tableLayout || style()->tableLayout() != oldTableLayout) {
+ if (!m_tableLayout || style().tableLayout() != oldTableLayout) {
// According to the CSS2 spec, you only use fixed table layout if an
// explicit width is specified on the table. Auto width implies auto table layout.
- if (style()->tableLayout() == TFIXED && !style()->logicalWidth().isAuto())
- m_tableLayout = adoptPtr(new FixedTableLayout(this));
+ if (style().tableLayout() == TFIXED && !style().logicalWidth().isAuto())
+ m_tableLayout = std::make_unique<FixedTableLayout>(this);
else
- m_tableLayout = adoptPtr(new AutoTableLayout(this));
+ m_tableLayout = std::make_unique<AutoTableLayout>(this);
}
// If border was changed, invalidate collapsed borders cache.
- if (!needsLayout() && oldStyle && oldStyle->border() != style()->border())
+ if (oldStyle && oldStyle->border() != style().border())
invalidateCollapsedBorders();
}
@@ -116,47 +141,47 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
{
bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
- if (child->isTableCaption())
+ if (is<RenderTableCaption>(*child))
wrapInAnonymousSection = false;
- else if (child->isRenderTableCol()) {
+ else if (is<RenderTableCol>(*child)) {
m_hasColElements = true;
wrapInAnonymousSection = false;
- } else if (child->isTableSection()) {
- switch (child->style()->display()) {
+ } else if (is<RenderTableSection>(*child)) {
+ switch (child->style().display()) {
case TABLE_HEADER_GROUP:
resetSectionPointerIfNotBefore(m_head, beforeChild);
if (!m_head) {
- m_head = toRenderTableSection(child);
+ m_head = downcast<RenderTableSection>(child);
} else {
resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
if (!m_firstBody)
- m_firstBody = toRenderTableSection(child);
+ m_firstBody = downcast<RenderTableSection>(child);
}
wrapInAnonymousSection = false;
break;
case TABLE_FOOTER_GROUP:
resetSectionPointerIfNotBefore(m_foot, beforeChild);
if (!m_foot) {
- m_foot = toRenderTableSection(child);
+ m_foot = downcast<RenderTableSection>(child);
wrapInAnonymousSection = false;
break;
}
- // Fall through.
+ FALLTHROUGH;
case TABLE_ROW_GROUP:
resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
if (!m_firstBody)
- m_firstBody = toRenderTableSection(child);
+ m_firstBody = downcast<RenderTableSection>(child);
wrapInAnonymousSection = false;
break;
default:
ASSERT_NOT_REACHED();
}
- } else if (child->isTableCell() || child->isTableRow())
+ } else if (is<RenderTableCell>(*child) || is<RenderTableRow>(*child))
wrapInAnonymousSection = true;
else
wrapInAnonymousSection = true;
- if (child->isTableSection())
+ if (is<RenderTableSection>(*child))
setNeedsSectionRecalc();
if (!wrapInAnonymousSection) {
@@ -167,31 +192,32 @@ void RenderTable::addChild(RenderObject* child, RenderObject* beforeChild)
return;
}
- if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
- lastChild()->addChild(child);
+ if (!beforeChild && is<RenderTableSection>(lastChild()) && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
+ downcast<RenderTableSection>(*lastChild()).addChild(child);
return;
}
if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
RenderObject* section = beforeChild->previousSibling();
- if (section && section->isTableSection() && section->isAnonymous()) {
- section->addChild(child);
+ if (is<RenderTableSection>(section) && section->isAnonymous()) {
+ downcast<RenderTableSection>(*section).addChild(child);
return;
}
}
RenderObject* lastBox = beforeChild;
- while (lastBox && lastBox->parent()->isAnonymous() && !lastBox->isTableSection() && lastBox->style()->display() != TABLE_CAPTION && lastBox->style()->display() != TABLE_COLUMN_GROUP)
+ while (lastBox && lastBox->parent()->isAnonymous() && !is<RenderTableSection>(*lastBox) && lastBox->style().display() != TABLE_CAPTION && lastBox->style().display() != TABLE_COLUMN_GROUP)
lastBox = lastBox->parent();
- if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox)) {
- if (beforeChild == lastBox)
- beforeChild = lastBox->firstChild();
- lastBox->addChild(child, beforeChild);
+ if (lastBox && lastBox->isAnonymous() && !isAfterContent(lastBox) && lastBox->isTableSection()) {
+ RenderTableSection& section = downcast<RenderTableSection>(*lastBox);
+ if (beforeChild == &section)
+ beforeChild = section.firstRow();
+ section.addChild(child, beforeChild);
return;
}
- if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
- beforeChild = 0;
+ if (beforeChild && !is<RenderTableSection>(*beforeChild) && beforeChild->style().display() != TABLE_CAPTION && beforeChild->style().display() != TABLE_COLUMN_GROUP)
+ beforeChild = nullptr;
RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
addChild(section, beforeChild);
@@ -206,18 +232,21 @@ void RenderTable::addCaption(const RenderTableCaption* caption)
void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
{
- size_t index = m_captions.find(oldCaption);
- ASSERT(index != notFound);
- if (index == notFound)
- return;
-
- m_captions.remove(index);
+ bool removed = m_captions.removeFirst(oldCaption);
+ ASSERT_UNUSED(removed, removed);
}
void RenderTable::invalidateCachedColumns()
{
m_columnRenderersValid = false;
m_columnRenderers.resize(0);
+ m_effectiveColumnIndexMap.clear();
+}
+
+void RenderTable::invalidateCachedColumnOffsets()
+{
+ m_columnOffsetTop = -1;
+ m_columnOffsetHeight = -1;
}
void RenderTable::addColumn(const RenderTableCol*)
@@ -248,48 +277,47 @@ void RenderTable::updateLogicalWidth()
}
RenderBlock* cb = containingBlock();
- RenderView* renderView = view();
LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
- bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
+ bool hasPerpendicularContainingBlock = cb->style().isHorizontalWritingMode() != style().isHorizontalWritingMode();
LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
- Length styleLogicalWidth = style()->logicalWidth();
+ Length styleLogicalWidth = style().logicalWidth();
if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
else {
// Subtract out any fixed margins from our available width for auto width tables.
- LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
- LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+ LayoutUnit marginStart = minimumValueForLength(style().marginStart(), availableLogicalWidth);
+ LayoutUnit marginEnd = minimumValueForLength(style().marginEnd(), availableLogicalWidth);
LayoutUnit marginTotal = marginStart + marginEnd;
// Subtract out our margins to get the available content width.
- LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
+ LayoutUnit availableContentLogicalWidth = std::max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
// FIXME: Work with regions someday.
availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0);
}
// Ensure we aren't bigger than our available width.
- setLogicalWidth(min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
+ setLogicalWidth(std::min(availableContentLogicalWidth, maxPreferredLogicalWidth()));
}
// Ensure we aren't smaller than our min preferred width.
- setLogicalWidth(max<int>(logicalWidth(), minPreferredLogicalWidth()));
+ setLogicalWidth(std::max(logicalWidth(), minPreferredLogicalWidth()));
// Ensure we aren't bigger than our max-width style.
- Length styleMaxLogicalWidth = style()->logicalMaxWidth();
+ Length styleMaxLogicalWidth = style().logicalMaxWidth();
if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
- setLogicalWidth(min<int>(logicalWidth(), computedMaxLogicalWidth));
+ setLogicalWidth(std::min(logicalWidth(), computedMaxLogicalWidth));
}
// Ensure we aren't smaller than our min-width style.
- Length styleMinLogicalWidth = style()->logicalMinWidth();
+ Length styleMinLogicalWidth = style().logicalMinWidth();
if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
- setLogicalWidth(max<int>(logicalWidth(), computedMinLogicalWidth));
+ setLogicalWidth(std::max(logicalWidth(), computedMinLogicalWidth));
}
// Finally, with our true width determined, compute our margins for real.
@@ -300,15 +328,15 @@ void RenderTable::updateLogicalWidth()
if (avoidsFloats() && cb->containsFloats())
containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0); // FIXME: Work with regions someday.
ComputedMarginValues marginValues;
- bool hasInvertedDirection = cb->style()->isLeftToRightDirection() == style()->isLeftToRightDirection();
+ bool hasInvertedDirection = cb->style().isLeftToRightDirection() == style().isLeftToRightDirection();
computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
hasInvertedDirection ? marginValues.m_start : marginValues.m_end,
hasInvertedDirection ? marginValues.m_end : marginValues.m_start);
setMarginStart(marginValues.m_start);
setMarginEnd(marginValues.m_end);
} else {
- setMarginStart(minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView));
- setMarginEnd(minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView));
+ setMarginStart(minimumValueForLength(style().marginStart(), availableLogicalWidth));
+ setMarginEnd(minimumValueForLength(style().marginEnd(), availableLogicalWidth));
}
}
@@ -320,33 +348,33 @@ LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& st
// HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
LayoutUnit borders = 0;
- bool isCSSTable = !node() || !isHTMLTableElement(node());
- if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
+ bool isCSSTable = !is<HTMLTableElement>(element());
+ if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style().boxSizing() == CONTENT_BOX)
borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
- return minimumValueForLength(styleLogicalWidth, availableWidth, view()) + borders;
+ return minimumValueForLength(styleLogicalWidth, availableWidth) + borders;
}
LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
{
- LayoutUnit computedLogicalHeight = 0;
+ LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
+ LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
+ LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter;
if (styleLogicalHeight.isFixed()) {
// HTML tables size as though CSS height includes border/padding, CSS tables do not.
LayoutUnit borders = LayoutUnit();
// FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
- if ((node() && isHTMLTableElement(node())) || style()->boxSizing() == BORDER_BOX) {
- LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
- LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
- borders = borderAndPaddingBefore + borderAndPaddingAfter;
+ if (is<HTMLTableElement>(element()) || style().boxSizing() == BORDER_BOX) {
+ borders = borderAndPadding;
}
- computedLogicalHeight = styleLogicalHeight.value() - borders;
- } else if (styleLogicalHeight.isPercent())
- computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
- else if (styleLogicalHeight.isViewportPercentage())
- computedLogicalHeight = minimumValueForLength(styleLogicalHeight, 0, view());
+ return styleLogicalHeight.value() - borders;
+ } else if (styleLogicalHeight.isPercentOrCalculated())
+ return computePercentageLogicalHeight(styleLogicalHeight).valueOr(0);
+ else if (styleLogicalHeight.isIntrinsic())
+ return computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding).valueOr(0);
else
ASSERT_NOT_REACHED();
- return max<LayoutUnit>(0, computedLogicalHeight);
+ return LayoutUnit();
}
void RenderTable::layoutCaption(RenderTableCaption* caption)
@@ -369,7 +397,7 @@ void RenderTable::layoutCaption(RenderTableCaption* caption)
setLogicalHeight(logicalHeight() + caption->logicalHeight() + caption->marginBefore() + caption->marginAfter());
}
-void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
+void RenderTable::distributeExtraLogicalHeight(LayoutUnit extraLogicalHeight)
{
if (extraLogicalHeight <= 0)
return;
@@ -403,20 +431,18 @@ void RenderTable::layout()
// FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
// to call this before we call borderStart/borderEnd to avoid getting a stale value.
recalcBordersInRowDirection();
-
- LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
- LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
- setLogicalHeight(0);
+ LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+ LayoutStateMaintainer statePusher(view(), *this, locationOffset(), hasTransform() || hasReflection() || style().isFlippedBlocksWritingMode());
- initMaxMarginValues();
-
LayoutUnit oldLogicalWidth = logicalWidth();
+ LayoutUnit oldLogicalHeight = logicalHeight();
+ setLogicalHeight(0);
updateLogicalWidth();
if (logicalWidth() != oldLogicalWidth) {
for (unsigned i = 0; i < m_captions.size(); i++)
- m_captions[i]->setNeedsLayout(true, MarkOnlyThis);
+ m_captions[i]->setNeedsLayout(MarkOnlyThis);
}
// FIXME: The optimisation below doesn't work since the internal table
// layout could have changed. we need to add a flag to the table
@@ -432,19 +458,19 @@ void RenderTable::layout()
bool collapsing = collapseBorders();
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
+ for (auto& child : childrenOfType<RenderElement>(*this)) {
+ if (is<RenderTableSection>(child)) {
+ RenderTableSection& section = downcast<RenderTableSection>(child);
if (m_columnLogicalWidthChanged)
- section->setChildNeedsLayout(true, MarkOnlyThis);
- section->layoutIfNeeded();
- totalSectionLogicalHeight += section->calcRowLogicalHeight();
+ section.setChildNeedsLayout(MarkOnlyThis);
+ section.layoutIfNeeded();
+ totalSectionLogicalHeight += section.calcRowLogicalHeight();
if (collapsing)
- section->recalcOuterBorder();
- ASSERT(!section->needsLayout());
- } else if (child->isRenderTableCol()) {
- child->layoutIfNeeded();
- ASSERT(!child->needsLayout());
+ section.recalcOuterBorder();
+ ASSERT(!section.needsLayout());
+ } else if (is<RenderTableCol>(child)) {
+ downcast<RenderTableCol>(child).layoutIfNeeded();
+ ASSERT(!child.needsLayout());
}
}
@@ -457,13 +483,13 @@ void RenderTable::layout()
// FIXME: Collapse caption margin.
if (!m_captions.isEmpty()) {
for (unsigned i = 0; i < m_captions.size(); i++) {
- if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
+ if (m_captions[i]->style().captionSide() == CAPBOTTOM)
continue;
layoutCaption(m_captions[i]);
}
if (logicalHeight() != oldTableLogicalTop) {
sectionMoved = true;
- movedSectionLogicalTop = min(logicalHeight(), oldTableLogicalTop);
+ movedSectionLogicalTop = std::min(logicalHeight(), oldTableLogicalTop);
}
}
@@ -477,43 +503,43 @@ void RenderTable::layout()
LayoutUnit computedLogicalHeight = 0;
- Length logicalHeightLength = style()->logicalHeight();
- if (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive())
+ Length logicalHeightLength = style().logicalHeight();
+ if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
- Length logicalMaxHeightLength = style()->logicalMaxHeight();
- if (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative()) {
+ Length logicalMaxHeightLength = style().logicalMaxHeight();
+ if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
- computedLogicalHeight = min(computedLogicalHeight, computedMaxLogicalHeight);
+ computedLogicalHeight = std::min(computedLogicalHeight, computedMaxLogicalHeight);
}
- Length logicalMinHeightLength = style()->logicalMinHeight();
- if (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative()) {
+ Length logicalMinHeightLength = style().logicalMinHeight();
+ if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
- computedLogicalHeight = max(computedLogicalHeight, computedMinLogicalHeight);
+ computedLogicalHeight = std::max(computedLogicalHeight, computedMinLogicalHeight);
}
- distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
+ distributeExtraLogicalHeight(computedLogicalHeight - totalSectionLogicalHeight);
for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
section->layoutRows();
- if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
+ if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document().inQuirksMode()) {
// Completely empty tables (with no sections or anything) should at least honor specified height
// in strict mode.
setLogicalHeight(logicalHeight() + computedLogicalHeight);
}
- LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
+ LayoutUnit sectionLogicalLeft = style().isLeftToRightDirection() ? borderStart() : borderEnd();
if (!collapsing)
- sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
+ sectionLogicalLeft += style().isLeftToRightDirection() ? paddingStart() : paddingEnd();
// position the table sections
RenderTableSection* section = topSection();
while (section) {
if (!sectionMoved && section->logicalTop() != logicalHeight()) {
sectionMoved = true;
- movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
+ movedSectionLogicalTop = std::min(logicalHeight(), section->logicalTop()) + (style().isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
}
section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
@@ -524,7 +550,7 @@ void RenderTable::layout()
setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
for (unsigned i = 0; i < m_captions.size(); i++) {
- if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
+ if (m_captions[i]->style().captionSide() != CAPBOTTOM)
continue;
layoutCaption(m_captions[i]);
}
@@ -533,32 +559,71 @@ void RenderTable::layout()
updateLogicalHeight();
// table can be containing block of positioned elements.
- // FIXME: Only pass true if width or height changed.
- layoutPositionedObjects(true);
+ bool dimensionChanged = oldLogicalWidth != logicalWidth() || oldLogicalHeight != logicalHeight();
+ layoutPositionedObjects(dimensionChanged);
updateLayerTransform();
// Layout was changed, so probably borders too.
invalidateCollapsedBorders();
+ // The location or height of one or more sections may have changed.
+ invalidateCachedColumnOffsets();
+
computeOverflow(clientLogicalBottom());
statePusher.pop();
- if (view()->layoutState()->pageLogicalHeight())
- setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
+ if (view().layoutState()->pageLogicalHeight())
+ setPageLogicalOffset(view().layoutState()->pageLogicalOffset(this, logicalTop()));
bool didFullRepaint = repainter.repaintAfterLayout();
// Repaint with our new bounds if they are different from our old bounds.
if (!didFullRepaint && sectionMoved) {
- if (style()->isHorizontalWritingMode())
+ if (style().isHorizontalWritingMode())
repaintRectangle(LayoutRect(visualOverflowRect().x(), movedSectionLogicalTop, visualOverflowRect().width(), visualOverflowRect().maxY() - movedSectionLogicalTop));
else
repaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
}
m_columnLogicalWidthChanged = false;
- setNeedsLayout(false);
+ clearNeedsLayout();
+}
+
+void RenderTable::invalidateCollapsedBorders(RenderTableCell* cellWithStyleChange)
+{
+ m_collapsedBordersValid = false;
+ m_collapsedBorders.clear();
+
+ for (auto& section : childrenOfType<RenderTableSection>(*this))
+ section.clearCachedCollapsedBorders();
+
+ if (!m_collapsedEmptyBorderIsPresent)
+ return;
+
+ if (cellWithStyleChange) {
+ // It is enough to invalidate just the surrounding cells when cell border style changes.
+ cellWithStyleChange->invalidateHasEmptyCollapsedBorders();
+ if (auto* below = cellBelow(cellWithStyleChange))
+ below->invalidateHasEmptyCollapsedBorders();
+ if (auto* above = cellAbove(cellWithStyleChange))
+ above->invalidateHasEmptyCollapsedBorders();
+ if (auto* before = cellBefore(cellWithStyleChange))
+ before->invalidateHasEmptyCollapsedBorders();
+ if (auto* after = cellAfter(cellWithStyleChange))
+ after->invalidateHasEmptyCollapsedBorders();
+ return;
+ }
+
+ for (auto& section : childrenOfType<RenderTableSection>(*this)) {
+ for (auto* row = section.firstRow(); row; row = row->nextRow()) {
+ for (auto* cell = row->firstCell(); cell; cell = cell->nextCell()) {
+ ASSERT(cell->table() == this);
+ cell->invalidateHasEmptyCollapsedBorders();
+ }
+ }
+ }
+ m_collapsedEmptyBorderIsPresent = false;
}
// Collect all the unique border values that we want to paint in a sorted list.
@@ -566,38 +631,31 @@ void RenderTable::recalcCollapsedBorders()
{
if (m_collapsedBordersValid)
return;
- m_collapsedBordersValid = true;
m_collapsedBorders.clear();
- for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
- if (!section->isTableSection())
- continue;
- for (RenderObject* row = section->firstChild(); row; row = row->nextSibling()) {
- if (!row->isTableRow())
- continue;
- for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
- if (!cell->isTableCell())
- continue;
- ASSERT(toRenderTableCell(cell)->table() == this);
- toRenderTableCell(cell)->collectBorderValues(m_collapsedBorders);
+ for (auto& section : childrenOfType<RenderTableSection>(*this)) {
+ for (RenderTableRow* row = section.firstRow(); row; row = row->nextRow()) {
+ for (RenderTableCell* cell = row->firstCell(); cell; cell = cell->nextCell()) {
+ ASSERT(cell->table() == this);
+ cell->collectBorderValues(m_collapsedBorders);
}
}
}
RenderTableCell::sortBorderValues(m_collapsedBorders);
+ m_collapsedBordersValid = true;
}
-
void RenderTable::addOverflowFromChildren()
{
// Add overflow from borders.
// Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
// descendant objects, but since tables don't support overflow:auto, this works out fine.
if (collapseBorders()) {
- int rightBorderOverflow = width() + outerBorderRight() - borderRight();
- int leftBorderOverflow = borderLeft() - outerBorderLeft();
- int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
- int topBorderOverflow = borderTop() - outerBorderTop();
- IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
- if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
+ LayoutUnit rightBorderOverflow = width() + outerBorderRight() - borderRight();
+ LayoutUnit leftBorderOverflow = borderLeft() - outerBorderLeft();
+ LayoutUnit bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
+ LayoutUnit topBorderOverflow = borderTop() - outerBorderTop();
+ LayoutRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
+ if (borderOverflowRect != borderBoxRect()) {
addLayoutOverflow(borderOverflowRect);
addVisualOverflow(borderOverflowRect);
}
@@ -618,10 +676,9 @@ void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
PaintPhase paintPhase = paintInfo.phase;
- if (!isRoot()) {
+ if (!isDocumentElementRenderer()) {
LayoutRect overflowBox = visualOverflowRect();
flipForWritingMode(overflowBox);
- overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
overflowBox.moveBy(adjustedPaintOffset);
if (!overflowBox.intersects(paintInfo.rect))
return;
@@ -636,7 +693,7 @@ void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
PaintPhase paintPhase = paintInfo.phase;
- if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
+ if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style().visibility() == VISIBLE)
paintBoxDecorations(paintInfo, paintOffset);
if (paintPhase == PaintPhaseMask) {
@@ -656,14 +713,14 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
info.phase = paintPhase;
info.updateSubtreePaintRootForChildren(this);
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
- LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), paintOffset);
- child->paint(info, childPoint);
+ for (auto& box : childrenOfType<RenderBox>(*this)) {
+ if (!box.hasSelfPaintingLayer() && (box.isTableSection() || box.isTableCaption())) {
+ LayoutPoint childPoint = flipForWritingModeForChild(&box, paintOffset);
+ box.paint(info, childPoint);
}
}
- if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
+ if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style().visibility() == VISIBLE) {
recalcCollapsedBorders();
// Using our cached sorted styles, we then do individual passes,
// painting each style of border from lowest precedence to highest precedence.
@@ -680,7 +737,7 @@ void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
}
// Paint outline.
- if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
+ if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style().visibility() == VISIBLE)
paintOutline(paintInfo, LayoutRect(paintOffset, size()));
}
@@ -688,8 +745,8 @@ void RenderTable::subtractCaptionRect(LayoutRect& rect) const
{
for (unsigned i = 0; i < m_captions.size(); i++) {
LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
- bool captionIsBefore = (m_captions[i]->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
- if (style()->isHorizontalWritingMode()) {
+ bool captionIsBefore = (m_captions[i]->style().captionSide() != CAPBOTTOM) ^ style().isFlippedBlocksWritingMode();
+ if (style().isHorizontalWritingMode()) {
rect.setHeight(rect.height() - captionLogicalHeight);
if (captionIsBefore)
rect.move(0, captionLogicalHeight);
@@ -703,25 +760,25 @@ void RenderTable::subtractCaptionRect(LayoutRect& rect) const
void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (!paintInfo.shouldPaintWithinRoot(this))
+ if (!paintInfo.shouldPaintWithinRoot(*this))
return;
LayoutRect rect(paintOffset, size());
subtractCaptionRect(rect);
- BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
- if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+ BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context());
+ if (!boxShadowShouldBeAppliedToBackground(rect.location(), bleedAvoidance))
paintBoxShadow(paintInfo, rect, style(), Normal);
paintBackground(paintInfo, rect, bleedAvoidance);
paintBoxShadow(paintInfo, rect, style(), Inset);
- if (style()->hasBorder() && !collapseBorders())
+ if (style().hasBorderDecoration() && !collapseBorders())
paintBorder(paintInfo, rect, style());
}
void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{
- if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+ if (style().visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
return;
LayoutRect rect(paintOffset, size());
@@ -749,26 +806,26 @@ void RenderTable::computePreferredLogicalWidths()
computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
- int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
+ LayoutUnit bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
for (unsigned i = 0; i < m_captions.size(); i++)
- m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
+ m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
- RenderStyle* styleToUse = style();
- // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
- if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
- m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
- m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+ RenderStyle& styleToUse = style();
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for min-width.
+ if (styleToUse.logicalMinWidth().isFixed() && styleToUse.logicalMinWidth().value() > 0) {
+ m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
+ m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMinWidth().value()));
}
- // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
- if (styleToUse->logicalMaxWidth().isFixed()) {
- m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
- m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+ // FIXME: This should probably be checking for isSpecified since you should be able to use percentage or calc values for maxWidth.
+ if (styleToUse.logicalMaxWidth().isFixed()) {
+ m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
+ m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse.logicalMaxWidth().value()));
}
// FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
@@ -793,19 +850,14 @@ void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
// Propagate the change in our columns representation to the sections that don't need
// cell recalc. If they do, they will be synced up directly with m_columns later.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->isTableSection())
- continue;
-
- RenderTableSection* section = toRenderTableSection(child);
- if (section->needsCellRecalc())
+ for (auto& section : childrenOfType<RenderTableSection>(*this)) {
+ if (section.needsCellRecalc())
continue;
- section->splitColumn(position, firstSpan);
+ section.splitColumn(position, firstSpan);
}
m_columnPos.grow(numEffCols() + 1);
- m_columnPos[numEffCols()] = m_columnPos[numEffCols() - 1];
}
void RenderTable::appendColumn(unsigned span)
@@ -813,51 +865,135 @@ void RenderTable::appendColumn(unsigned span)
unsigned newColumnIndex = m_columns.size();
m_columns.append(ColumnStruct(span));
+ // Unless the table has cell(s) with colspan that exceed the number of columns afforded
+ // by the other rows in the table we can use the fast path when mapping columns to effective columns.
+ m_hasCellColspanThatDeterminesTableWidth = m_hasCellColspanThatDeterminesTableWidth || span > 1;
+
// Propagate the change in our columns representation to the sections that don't need
// cell recalc. If they do, they will be synced up directly with m_columns later.
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (!child->isTableSection())
+ for (auto& section : childrenOfType<RenderTableSection>(*this)) {
+ if (section.needsCellRecalc())
continue;
- RenderTableSection* section = toRenderTableSection(child);
- if (section->needsCellRecalc())
- continue;
-
- section->appendColumn(newColumnIndex);
+ section.appendColumn(newColumnIndex);
}
m_columnPos.grow(numEffCols() + 1);
- m_columnPos[numEffCols()] = m_columnPos[numEffCols() - 1];
}
RenderTableCol* RenderTable::firstColumn() const
{
for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isRenderTableCol())
- return toRenderTableCol(child);
+ if (is<RenderTableCol>(*child))
+ return downcast<RenderTableCol>(child);
// We allow only table-captions before columns or column-groups.
- if (!child->isTableCaption())
- return 0;
+ if (!is<RenderTableCaption>(*child))
+ return nullptr;
}
- return 0;
+ return nullptr;
}
void RenderTable::updateColumnCache() const
{
ASSERT(m_hasColElements);
ASSERT(m_columnRenderers.isEmpty());
+ ASSERT(m_effectiveColumnIndexMap.isEmpty());
ASSERT(!m_columnRenderersValid);
+ unsigned columnIndex = 0;
for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
if (columnRenderer->isTableColumnGroupWithColumnChildren())
continue;
m_columnRenderers.append(columnRenderer);
+ // FIXME: We should look to compute the effective column index successively from previous values instead of
+ // calling colToEffCol(), which is in O(numEffCols()). Although it's unlikely that this is a hot function.
+ m_effectiveColumnIndexMap.add(columnRenderer, colToEffCol(columnIndex));
+ columnIndex += columnRenderer->span();
}
m_columnRenderersValid = true;
}
+unsigned RenderTable::effectiveIndexOfColumn(const RenderTableCol& column) const
+{
+ if (!m_columnRenderersValid)
+ updateColumnCache();
+ const RenderTableCol* columnToUse = &column;
+ if (columnToUse->isTableColumnGroupWithColumnChildren())
+ columnToUse = columnToUse->nextColumn(); // First column in column-group
+ auto it = m_effectiveColumnIndexMap.find(columnToUse);
+ ASSERT(it != m_effectiveColumnIndexMap.end());
+ if (it == m_effectiveColumnIndexMap.end())
+ return std::numeric_limits<unsigned>::max();
+ return it->value;
+}
+
+LayoutUnit RenderTable::offsetTopForColumn(const RenderTableCol& column) const
+{
+ if (effectiveIndexOfColumn(column) >= numEffCols())
+ return 0;
+ if (m_columnOffsetTop >= 0) {
+ ASSERT(!needsLayout());
+ return m_columnOffsetTop;
+ }
+ RenderTableSection* section = topNonEmptySection();
+ return m_columnOffsetTop = section ? section->offsetTop() : LayoutUnit(0);
+}
+
+LayoutUnit RenderTable::offsetLeftForColumn(const RenderTableCol& column) const
+{
+ unsigned columnIndex = effectiveIndexOfColumn(column);
+ if (columnIndex >= numEffCols())
+ return 0;
+ return m_columnPos[columnIndex] + LayoutUnit(m_hSpacing) + borderLeft();
+}
+
+LayoutUnit RenderTable::offsetWidthForColumn(const RenderTableCol& column) const
+{
+ const RenderTableCol* currentColumn = &column;
+ bool hasColumnChildren;
+ if ((hasColumnChildren = currentColumn->isTableColumnGroupWithColumnChildren()))
+ currentColumn = currentColumn->nextColumn(); // First column in column-group
+ unsigned numberOfEffectiveColumns = numEffCols();
+ ASSERT_WITH_SECURITY_IMPLICATION(m_columnPos.size() >= numberOfEffectiveColumns + 1);
+ LayoutUnit width = 0;
+ LayoutUnit spacing = m_hSpacing;
+ while (currentColumn) {
+ unsigned columnIndex = effectiveIndexOfColumn(*currentColumn);
+ unsigned span = currentColumn->span();
+ while (span && columnIndex < numberOfEffectiveColumns) {
+ width += m_columnPos[columnIndex + 1] - m_columnPos[columnIndex] - spacing;
+ span -= m_columns[columnIndex].span;
+ ++columnIndex;
+ if (span)
+ width += spacing;
+ }
+ if (!hasColumnChildren)
+ break;
+ currentColumn = currentColumn->nextColumn();
+ if (!currentColumn || currentColumn->isTableColumnGroup())
+ break;
+ width += spacing;
+ }
+ return width;
+}
+
+LayoutUnit RenderTable::offsetHeightForColumn(const RenderTableCol& column) const
+{
+ if (effectiveIndexOfColumn(column) >= numEffCols())
+ return 0;
+ if (m_columnOffsetHeight >= 0) {
+ ASSERT(!needsLayout());
+ return m_columnOffsetHeight;
+ }
+ LayoutUnit height = 0;
+ for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
+ height += section->offsetHeight();
+ m_columnOffsetHeight = height;
+ return m_columnOffsetHeight;
+}
+
RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
{
ASSERT(m_hasColElements);
@@ -892,42 +1028,43 @@ void RenderTable::recalcSections() const
m_foot = 0;
m_firstBody = 0;
m_hasColElements = false;
+ m_hasCellColspanThatDeterminesTableWidth = hasCellColspanThatDeterminesTableWidth();
// We need to get valid pointers to caption, head, foot and first body again
RenderObject* nextSibling;
for (RenderObject* child = firstChild(); child; child = nextSibling) {
nextSibling = child->nextSibling();
- switch (child->style()->display()) {
+ switch (child->style().display()) {
case TABLE_COLUMN:
case TABLE_COLUMN_GROUP:
m_hasColElements = true;
break;
case TABLE_HEADER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
+ if (is<RenderTableSection>(*child)) {
+ RenderTableSection& section = downcast<RenderTableSection>(*child);
if (!m_head)
- m_head = section;
+ m_head = &section;
else if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
+ m_firstBody = &section;
+ section.recalcCellsIfNeeded();
}
break;
case TABLE_FOOTER_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
+ if (is<RenderTableSection>(*child)) {
+ RenderTableSection& section = downcast<RenderTableSection>(*child);
if (!m_foot)
- m_foot = section;
+ m_foot = &section;
else if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
+ m_firstBody = &section;
+ section.recalcCellsIfNeeded();
}
break;
case TABLE_ROW_GROUP:
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
+ if (is<RenderTableSection>(*child)) {
+ RenderTableSection& section = downcast<RenderTableSection>(*child);
if (!m_firstBody)
- m_firstBody = section;
- section->recalcCellsIfNeeded();
+ m_firstBody = &section;
+ section.recalcCellsIfNeeded();
}
break;
default:
@@ -937,13 +1074,10 @@ void RenderTable::recalcSections() const
// repair column count (addChild can grow it too much, because it always adds elements to the last row of a section)
unsigned maxCols = 0;
- for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
- if (child->isTableSection()) {
- RenderTableSection* section = toRenderTableSection(child);
- unsigned sectionCols = section->numColumns();
- if (sectionCols > maxCols)
- maxCols = sectionCols;
- }
+ for (auto& section : childrenOfType<RenderTableSection>(*this)) {
+ unsigned sectionCols = section.numColumns();
+ if (sectionCols > maxCols)
+ maxCols = sectionCols;
}
m_columns.resize(maxCols);
@@ -954,7 +1088,7 @@ void RenderTable::recalcSections() const
m_needsSectionRecalc = false;
}
-int RenderTable::calcBorderStart() const
+LayoutUnit RenderTable::calcBorderStart() const
{
if (!collapseBorders())
return RenderBlock::borderStart();
@@ -963,9 +1097,9 @@ int RenderTable::calcBorderStart() const
if (!numEffCols())
return 0;
- unsigned borderWidth = 0;
+ float borderWidth = 0;
- const BorderValue& tableStartBorder = style()->borderStart();
+ const BorderValue& tableStartBorder = style().borderStart();
if (tableStartBorder.style() == BHIDDEN)
return 0;
if (tableStartBorder.style() > BHIDDEN)
@@ -973,11 +1107,11 @@ int RenderTable::calcBorderStart() const
if (RenderTableCol* column = colElement(0)) {
// FIXME: We don't account for direction on columns and column groups.
- const BorderValue& columnAdjoiningBorder = column->style()->borderStart();
+ const BorderValue& columnAdjoiningBorder = column->style().borderStart();
if (columnAdjoiningBorder.style() == BHIDDEN)
return 0;
if (columnAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, columnAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
// FIXME: This logic doesn't properly account for the first column in the first column-group case.
}
@@ -987,7 +1121,7 @@ int RenderTable::calcBorderStart() const
return 0;
if (sectionAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, sectionAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
// FIXME: Make this work with perpendicular and flipped cells.
@@ -1000,15 +1134,15 @@ int RenderTable::calcBorderStart() const
return 0;
if (startCellAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, startCellAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, startCellAdjoiningBorder.width());
if (firstRowAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, firstRowAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
}
}
- return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
+ return floorToInt((borderWidth + (style().isLeftToRightDirection() ? 0 : 1)) / 2);
}
-int RenderTable::calcBorderEnd() const
+LayoutUnit RenderTable::calcBorderEnd() const
{
if (!collapseBorders())
return RenderBlock::borderEnd();
@@ -1017,9 +1151,9 @@ int RenderTable::calcBorderEnd() const
if (!numEffCols())
return 0;
- unsigned borderWidth = 0;
+ float borderWidth = 0;
- const BorderValue& tableEndBorder = style()->borderEnd();
+ const BorderValue& tableEndBorder = style().borderEnd();
if (tableEndBorder.style() == BHIDDEN)
return 0;
if (tableEndBorder.style() > BHIDDEN)
@@ -1028,11 +1162,11 @@ int RenderTable::calcBorderEnd() const
unsigned endColumn = numEffCols() - 1;
if (RenderTableCol* column = colElement(endColumn)) {
// FIXME: We don't account for direction on columns and column groups.
- const BorderValue& columnAdjoiningBorder = column->style()->borderEnd();
+ const BorderValue& columnAdjoiningBorder = column->style().borderEnd();
if (columnAdjoiningBorder.style() == BHIDDEN)
return 0;
if (columnAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, columnAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, columnAdjoiningBorder.width());
// FIXME: This logic doesn't properly account for the last column in the last column-group case.
}
@@ -1042,7 +1176,7 @@ int RenderTable::calcBorderEnd() const
return 0;
if (sectionAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, sectionAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, sectionAdjoiningBorder.width());
if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
// FIXME: Make this work with perpendicular and flipped cells.
@@ -1055,12 +1189,12 @@ int RenderTable::calcBorderEnd() const
return 0;
if (endCellAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, endCellAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, endCellAdjoiningBorder.width());
if (firstRowAdjoiningBorder.style() > BHIDDEN)
- borderWidth = max(borderWidth, firstRowAdjoiningBorder.width());
+ borderWidth = std::max(borderWidth, firstRowAdjoiningBorder.width());
}
}
- return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+ return floorToInt((borderWidth + (style().isLeftToRightDirection() ? 1 : 0)) / 2);
}
void RenderTable::recalcBordersInRowDirection()
@@ -1070,7 +1204,7 @@ void RenderTable::recalcBordersInRowDirection()
m_borderEnd = calcBorderEnd();
}
-int RenderTable::borderBefore() const
+LayoutUnit RenderTable::borderBefore() const
{
if (collapseBorders()) {
recalcSectionsIfNeeded();
@@ -1079,7 +1213,7 @@ int RenderTable::borderBefore() const
return RenderBlock::borderBefore();
}
-int RenderTable::borderAfter() const
+LayoutUnit RenderTable::borderAfter() const
{
if (collapseBorders()) {
recalcSectionsIfNeeded();
@@ -1088,63 +1222,63 @@ int RenderTable::borderAfter() const
return RenderBlock::borderAfter();
}
-int RenderTable::outerBorderBefore() const
+LayoutUnit RenderTable::outerBorderBefore() const
{
if (!collapseBorders())
return 0;
- int borderWidth = 0;
+ LayoutUnit borderWidth = 0;
if (RenderTableSection* topSection = this->topSection()) {
borderWidth = topSection->outerBorderBefore();
if (borderWidth < 0)
return 0; // Overridden by hidden
}
- const BorderValue& tb = style()->borderBefore();
+ const BorderValue& tb = style().borderBefore();
if (tb.style() == BHIDDEN)
return 0;
if (tb.style() > BHIDDEN)
- borderWidth = max<int>(borderWidth, tb.width() / 2);
+ borderWidth = floorToInt(std::max<LayoutUnit>(borderWidth, tb.width() / 2));
return borderWidth;
}
-int RenderTable::outerBorderAfter() const
+LayoutUnit RenderTable::outerBorderAfter() const
{
if (!collapseBorders())
return 0;
- int borderWidth = 0;
+ LayoutUnit borderWidth = 0;
if (RenderTableSection* section = bottomSection()) {
borderWidth = section->outerBorderAfter();
if (borderWidth < 0)
return 0; // Overridden by hidden
}
- const BorderValue& tb = style()->borderAfter();
+ const BorderValue& tb = style().borderAfter();
if (tb.style() == BHIDDEN)
return 0;
if (tb.style() > BHIDDEN)
- borderWidth = max<int>(borderWidth, (tb.width() + 1) / 2);
+ borderWidth = floorToInt(std::max<LayoutUnit>(borderWidth, (tb.width() + 1) / 2));
return borderWidth;
}
-int RenderTable::outerBorderStart() const
+LayoutUnit RenderTable::outerBorderStart() const
{
if (!collapseBorders())
return 0;
- int borderWidth = 0;
+ LayoutUnit borderWidth = 0;
- const BorderValue& tb = style()->borderStart();
+ const BorderValue& tb = style().borderStart();
if (tb.style() == BHIDDEN)
return 0;
if (tb.style() > BHIDDEN)
- borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
+ borderWidth = floorToInt((tb.width() + (style().isLeftToRightDirection() ? 0 : 1)) / 2);
bool allHidden = true;
for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
- int sw = section->outerBorderStart();
+ LayoutUnit sw = section->outerBorderStart();
if (sw < 0)
continue;
allHidden = false;
- borderWidth = max(borderWidth, sw);
+ borderWidth = std::max(borderWidth, sw);
}
if (allHidden)
return 0;
@@ -1152,26 +1286,26 @@ int RenderTable::outerBorderStart() const
return borderWidth;
}
-int RenderTable::outerBorderEnd() const
+LayoutUnit RenderTable::outerBorderEnd() const
{
if (!collapseBorders())
return 0;
- int borderWidth = 0;
+ LayoutUnit borderWidth = 0;
- const BorderValue& tb = style()->borderEnd();
+ const BorderValue& tb = style().borderEnd();
if (tb.style() == BHIDDEN)
return 0;
if (tb.style() > BHIDDEN)
- borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+ borderWidth = floorToInt((tb.width() + (style().isLeftToRightDirection() ? 1 : 0)) / 2);
bool allHidden = true;
for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
- int sw = section->outerBorderEnd();
+ LayoutUnit sw = section->outerBorderEnd();
if (sw < 0)
continue;
allHidden = false;
- borderWidth = max(borderWidth, sw);
+ borderWidth = std::max(borderWidth, sw);
}
if (allHidden)
return 0;
@@ -1184,17 +1318,17 @@ RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section,
recalcSectionsIfNeeded();
if (section == m_head)
- return 0;
+ return nullptr;
RenderObject* prevSection = section == m_foot ? lastChild() : section->previousSibling();
while (prevSection) {
- if (prevSection->isTableSection() && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toRenderTableSection(prevSection)->numRows()))
+ if (is<RenderTableSection>(*prevSection) && prevSection != m_head && prevSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || downcast<RenderTableSection>(*prevSection).numRows()))
break;
prevSection = prevSection->previousSibling();
}
if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
prevSection = m_head;
- return toRenderTableSection(prevSection);
+ return downcast<RenderTableSection>(prevSection);
}
RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, SkipEmptySectionsValue skipEmptySections) const
@@ -1202,17 +1336,17 @@ RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section,
recalcSectionsIfNeeded();
if (section == m_foot)
- return 0;
+ return nullptr;
RenderObject* nextSection = section == m_head ? firstChild() : section->nextSibling();
while (nextSection) {
- if (nextSection->isTableSection() && nextSection != m_head && nextSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || toRenderTableSection(nextSection)->numRows()))
+ if (is<RenderTableSection>(*nextSection) && nextSection != m_head && nextSection != m_foot && (skipEmptySections == DoNotSkipEmptySections || downcast<RenderTableSection>(*nextSection).numRows()))
break;
nextSection = nextSection->nextSibling();
}
if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
nextSection = m_foot;
- return toRenderTableSection(nextSection);
+ return downcast<RenderTableSection>(nextSection);
}
RenderTableSection* RenderTable::bottomSection() const
@@ -1223,11 +1357,11 @@ RenderTableSection* RenderTable::bottomSection() const
return m_foot;
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (child->isTableSection())
- return toRenderTableSection(child);
+ if (is<RenderTableSection>(*child))
+ return downcast<RenderTableSection>(child);
}
- return 0;
+ return nullptr;
}
RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
@@ -1236,7 +1370,7 @@ RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
// Find the section and row to look in
unsigned r = cell->rowIndex();
- RenderTableSection* section = 0;
+ RenderTableSection* section = nullptr;
unsigned rAbove = 0;
if (r > 0) {
// cell is not in the first row, so use the above row in its own section
@@ -1256,7 +1390,7 @@ RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
return aboveCell.primaryCell();
} else
- return 0;
+ return nullptr;
}
RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
@@ -1265,7 +1399,7 @@ RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
// Find the section and row to look in
unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
- RenderTableSection* section = 0;
+ RenderTableSection* section = nullptr;
unsigned rBelow = 0;
if (r < cell->section()->numRows() - 1) {
// The cell is not in the last row, so use the next row in the section.
@@ -1283,7 +1417,7 @@ RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
return belowCell.primaryCell();
} else
- return 0;
+ return nullptr;
}
RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
@@ -1293,7 +1427,7 @@ RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
RenderTableSection* section = cell->section();
unsigned effCol = colToEffCol(cell->col());
if (!effCol)
- return 0;
+ return nullptr;
// If we hit a colspan back up to a real cell.
RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
@@ -1306,13 +1440,13 @@ RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
if (effCol >= numEffCols())
- return 0;
+ return nullptr;
return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
}
RenderBlock* RenderTable::firstLineBlock() const
{
- return 0;
+ return nullptr;
}
void RenderTable::updateFirstLetter()
@@ -1321,40 +1455,37 @@ void RenderTable::updateFirstLetter()
int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
{
- LayoutUnit baseline = firstLineBoxBaseline();
- if (baseline != -1)
- return baseline;
-
- return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+ return firstLineBaseline().valueOrCompute([&] {
+ return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+ });
}
-int RenderTable::inlineBlockBaseline(LineDirectionMode) const
+Optional<int> RenderTable::inlineBlockBaseline(LineDirectionMode) const
{
// Tables are skipped when computing an inline-block's baseline.
- return -1;
+ return Optional<int>();
}
-int RenderTable::firstLineBoxBaseline() const
+Optional<int> RenderTable::firstLineBaseline() const
{
// The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
// doesn't define the baseline of a 'table' only an 'inline-table').
// This is also needed to properly determine the baseline of a cell if it has a table child.
if (isWritingModeRoot())
- return -1;
+ return Optional<int>();
recalcSectionsIfNeeded();
const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
if (!topNonEmptySection)
- return -1;
+ return Optional<int>();
- int baseline = topNonEmptySection->firstLineBoxBaseline();
- if (baseline > 0)
- return topNonEmptySection->logicalTop() + baseline;
+ if (Optional<int> baseline = topNonEmptySection->firstLineBaseline())
+ return Optional<int>(topNonEmptySection->logicalTop() + baseline.value());
// FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value?
- return -1;
+ return Optional<int>();
}
LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy, PaintPhase phase)
@@ -1375,7 +1506,7 @@ LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegi
// supported. When we actually support left/right and stop mapping them to top/bottom,
// we might have to hack this code first (depending on what order we do these bug fixes in).
if (!m_captions.isEmpty()) {
- if (style()->isHorizontalWritingMode()) {
+ if (style().isHorizontalWritingMode()) {
rect.setHeight(height());
rect.setY(location.y());
} else {
@@ -1392,10 +1523,10 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
LayoutPoint adjustedLocation = accumulatedOffset + location();
// Check kids first.
- if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region()))) {
+ if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, currentRenderNamedFlowFragment()))) {
for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
- if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
- LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
+ if (is<RenderBox>(*child) && !downcast<RenderBox>(*child).hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
+ LayoutPoint childPoint = flipForWritingModeForChild(downcast<RenderBox>(child), adjustedLocation);
if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
return true;
@@ -1408,7 +1539,7 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
LayoutRect boundsRect(adjustedLocation, size());
if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
- if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
+ if (!result.addNodeToRectBasedTestResult(element(), request, locationInContainer, boundsRect))
return true;
}
@@ -1417,29 +1548,41 @@ bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu
RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
{
- RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE);
- RenderTable* newTable = new (parent->renderArena()) RenderTable(0);
- newTable->setDocumentForAnonymous(parent->document());
- newTable->setStyle(newStyle.release());
- return newTable;
+ auto table = new RenderTable(parent->document(), RenderStyle::createAnonymousStyleWithDisplay(&parent->style(), parent->style().display() == INLINE ? INLINE_TABLE : TABLE));
+ table->initializeStyle();
+ return table;
}
const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const
{
ASSERT(cell->isFirstOrLastCellInRow());
if (hasSameDirectionAs(cell->row()))
- return style()->borderStart();
+ return style().borderStart();
- return style()->borderEnd();
+ return style().borderEnd();
}
const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const
{
ASSERT(cell->isFirstOrLastCellInRow());
if (hasSameDirectionAs(cell->row()))
- return style()->borderEnd();
+ return style().borderEnd();
- return style()->borderStart();
+ return style().borderStart();
+}
+
+void RenderTable::markForPaginationRelayoutIfNeeded()
+{
+ if (!view().layoutState()->isPaginated() || (!view().layoutState()->pageLogicalHeightChanged() && (!view().layoutState()->pageLogicalHeight() || view().layoutState()->pageLogicalOffset(this, logicalTop()) == pageLogicalOffset())))
+ return;
+
+ // When a table moves, we have to dirty all of the sections too.
+ if (!needsLayout())
+ setChildNeedsLayout(MarkOnlyThis);
+ for (auto& child : childrenOfType<RenderTableSection>(*this)) {
+ if (!child.needsLayout())
+ child.setChildNeedsLayout(MarkOnlyThis);
+ }
}
}