summaryrefslogtreecommitdiffstats
path: root/layout/tables
diff options
context:
space:
mode:
Diffstat (limited to 'layout/tables')
-rw-r--r--layout/tables/crashtests/1555757-1.html16
-rw-r--r--layout/tables/crashtests/1555757-2.html27
-rw-r--r--layout/tables/crashtests/1881157.html26
-rw-r--r--layout/tables/crashtests/347506-1.xhtml23
-rw-r--r--layout/tables/crashtests/crashtests.list6
-rw-r--r--layout/tables/nsCellMap.cpp6
-rw-r--r--layout/tables/nsTableCellFrame.cpp19
-rw-r--r--layout/tables/nsTableFrame.cpp245
-rw-r--r--layout/tables/nsTableFrame.h3
-rw-r--r--layout/tables/nsTableRowFrame.cpp72
10 files changed, 236 insertions, 207 deletions
diff --git a/layout/tables/crashtests/1555757-1.html b/layout/tables/crashtests/1555757-1.html
deleted file mode 100644
index 04f2b27a60..0000000000
--- a/layout/tables/crashtests/1555757-1.html
+++ /dev/null
@@ -1,16 +0,0 @@
-<html>
-<head>
- <style>
- .class_1 {
- transition-delay: 2129ms;
- contain: strict;
- }
- </style>
-</head>
-<math>
- <mover>
- <ms></ms>
- <mtable class="class_1"></mtable>
- </mover>
-</math>
-</html>
diff --git a/layout/tables/crashtests/1555757-2.html b/layout/tables/crashtests/1555757-2.html
deleted file mode 100644
index eff048784a..0000000000
--- a/layout/tables/crashtests/1555757-2.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
- <style>
- #testElem {
- border: 1px solid black;
- background: yellow;
- contain: layout size;
- width: 300px;
- }
- </style>
- <script>
- function go() {
- /* trigger an incremental reflow.
- * Note: elem.style is undefined for MathML elements, so we have
- * to use setAttribute().
- */
- testElem.setAttribute("style", "width:150px");
- }
- </script>
-</head>
-<body onload="go()">
- <math>
- <mtable id="testElem">Change my size</mtable>
- </math>
-</body>
-</html>
diff --git a/layout/tables/crashtests/1881157.html b/layout/tables/crashtests/1881157.html
new file mode 100644
index 0000000000..d9beb64429
--- /dev/null
+++ b/layout/tables/crashtests/1881157.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<style>
+#a {
+ min-height: 1vw;
+ line-height: 0vw;
+}
+#b {
+ scale: 0.67976 1 1;
+}
+:root {
+ column-width: 1em;
+}
+</style>
+<script>
+document.addEventListener("DOMContentLoaded", () => {
+ b.appendChild(a)
+ document.execCommand("fontSize", false, 5)
+ b.style.setProperty("border-top-style", "dotted")
+})
+function func_0() {
+ b.rules = "cols"
+}
+</script>
+<dialog id="a" open="true">,&#x27;/,_J</dialog>
+<table id="b">
+<details open="true" ontoggle="func_0()">
diff --git a/layout/tables/crashtests/347506-1.xhtml b/layout/tables/crashtests/347506-1.xhtml
deleted file mode 100644
index 4119389a56..0000000000
--- a/layout/tables/crashtests/347506-1.xhtml
+++ /dev/null
@@ -1,23 +0,0 @@
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-<body>
-
-<div><math xmlns="http://www.w3.org/1998/Math/MathML" display="block">
-
- <mtable>
- <mtr>
- <mtd><mi>x</mi></mtd>
- <mtd rowspan="4" columnspan="4"><mi>y</mi></mtd>
- </mtr>
- <mtr>
- <mtd rowspan="0" columnspan="0"><mi>z</mi></mtd>
- <mtd><mi>w</mi></mtd>
- </mtr>
- </mtable>
-
-
-</math></div>
-
-</body>
-
-</html> \ No newline at end of file
diff --git a/layout/tables/crashtests/crashtests.list b/layout/tables/crashtests/crashtests.list
index 92bca235e3..58bdad5c78 100644
--- a/layout/tables/crashtests/crashtests.list
+++ b/layout/tables/crashtests/crashtests.list
@@ -45,7 +45,6 @@ load 343087-1.html
load 343588-1.xhtml
load 344000-1.html
load 347367.html
-load 347506-1.xhtml
load 347506-2.xhtml
load 347725-1.xhtml
load 348977-1.xhtml
@@ -140,7 +139,7 @@ load 580481-1.xhtml
asserts(1) load 595758-1.xhtml # Bug 714667
load 595758-2.xhtml
load 678447-1.html
-skip-if(Android&&browserIsRemote) load 691824-1.xhtml # bug 1507207
+skip-if(Android) load 691824-1.xhtml # bug 1507207
load 695430-1.html
load 696640-1.html
load 696640-2.html
@@ -167,8 +166,6 @@ load 1232881-1.html
load 1243623-1.html
load 1335552-1.html
load 1335552-2.html
-load 1555757-1.html
-load 1555757-2.html
load 1555757-3.html
load 1555757-4.html
load 1607045.html
@@ -180,3 +177,4 @@ load 1767364-4.html
load 1795030.html
load 1795051.html
load 1821177.html
+asserts(0-2) load 1881157.html # bug 1884058
diff --git a/layout/tables/nsCellMap.cpp b/layout/tables/nsCellMap.cpp
index a13a6a1c3a..7c29baa5b0 100644
--- a/layout/tables/nsCellMap.cpp
+++ b/layout/tables/nsCellMap.cpp
@@ -981,13 +981,13 @@ void nsTableCellMap::SetBCBorderCorner(LogicalCorner aCorner,
int32_t yPos = aRowIndex;
int32_t rgYPos = aRowIndex - aCellMapStart;
- if (eLogicalCornerBStartIEnd == aCorner) {
+ if (LogicalCorner::BStartIEnd == aCorner) {
xPos++;
- } else if (eLogicalCornerBEndIEnd == aCorner) {
+ } else if (LogicalCorner::BEndIEnd == aCorner) {
xPos++;
rgYPos++;
yPos++;
- } else if (eLogicalCornerBEndIStart == aCorner) {
+ } else if (LogicalCorner::BEndIStart == aCorner) {
rgYPos++;
yPos++;
}
diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp
index 70556d5e28..6eb1c3146a 100644
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -456,7 +456,7 @@ void nsTableCellFrame::BlockDirAlignChild(WritingMode aWM, nscoord aMaxAscent) {
ReflowOutput desiredSize(aWM);
desiredSize.SetSize(aWM, GetLogicalSize(aWM));
- nsRect overflow(nsPoint(0, 0), GetSize());
+ nsRect overflow(nsPoint(), GetSize());
overflow.Inflate(GetBorderOverflow());
desiredSize.mOverflowAreas.SetAllTo(overflow);
ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
@@ -761,24 +761,21 @@ void nsTableCellFrame::Reflow(nsPresContext* aPresContext,
kidReflowInput.Init(aPresContext, Nothing(), Nothing(), Some(padding));
if (firstKid->IsScrollFrame()) {
// Propagate explicit block sizes to our inner frame, if it's a scroll
- // frame.
+ // frame. Note that in table layout, explicit heights act as a minimum
+ // height, see nsTableRowFrame::CalcCellActualBSize.
+ //
// Table cells don't respect box-sizing, so we need to remove the
// padding, so that the scroll-frame sizes properly (since the
// scrollbars also add to the padding area).
auto ToScrolledBSize = [&](const nscoord aBSize) {
return std::max(0, aBSize - padding.BStartEnd(kidWM));
};
+ nscoord minBSize = aReflowInput.ComputedMinBSize();
if (aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE) {
- kidReflowInput.SetComputedBSize(
- ToScrolledBSize(aReflowInput.ComputedBSize()));
+ minBSize = std::max(minBSize, aReflowInput.ComputedBSize());
}
- if (aReflowInput.ComputedMinBSize() > 0) {
- kidReflowInput.SetComputedMinBSize(
- ToScrolledBSize(aReflowInput.ComputedMinBSize()));
- }
- if (aReflowInput.ComputedMaxBSize() != NS_UNCONSTRAINEDSIZE) {
- kidReflowInput.SetComputedMaxBSize(
- ToScrolledBSize(aReflowInput.ComputedMaxBSize()));
+ if (minBSize > 0) {
+ kidReflowInput.SetComputedMinBSize(ToScrolledBSize(minBSize));
}
}
}
diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp
index 9a359192c0..e7fd7340bf 100644
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -82,13 +82,19 @@ struct TableReflowInput final {
std::max(0, mReflowInput.ComputedISize() - table->GetColSpacing(-1) -
table->GetColSpacing(table->GetColCount()));
- // Bug 1863421 will fix border-spacing issue in the block-axis in printing.
mAvailSize.BSize(mWM) = aMode == TableReflowMode::Measuring
? NS_UNCONSTRAINEDSIZE
: mReflowInput.AvailableBSize();
- AdvanceBCoord(aBorderPadding.BStart(mWM));
- ReduceAvailableBSizeBy(aBorderPadding.BEnd(mWM) + table->GetRowSpacing(-1) +
- table->GetRowSpacing(table->GetRowCount()));
+ AdvanceBCoord(aBorderPadding.BStart(mWM) +
+ (!table->GetPrevInFlow() ? table->GetRowSpacing(-1) : 0));
+ if (aReflowInput.mStyleBorder->mBoxDecorationBreak ==
+ StyleBoxDecorationBreak::Clone) {
+ // At this point, we're assuming we won't be the last fragment, so we only
+ // reserve space for block-end border-padding if we're cloning it on each
+ // fragment; and we don't need to reserve any row-spacing for this
+ // hypothetical fragmentation, either.
+ ReduceAvailableBSizeBy(aBorderPadding.BEnd(mWM));
+ }
}
// Advance to the next block-offset and reduce the available block-size.
@@ -1633,12 +1639,15 @@ void nsTableFrame::Reflow(nsPresContext* aPresContext,
// Check for an overflow list, and append any row group frames being pushed
MoveOverflowToChildList();
- bool haveDesiredBSize = false;
+ bool haveCalledCalcDesiredBSize = false;
SetHaveReflowedColGroups(false);
- // Bug 1863421: We need to call ApplySkipSides() for borderPadding so that it
- // is correct in a table continuation.
- LogicalMargin borderPadding = aReflowInput.ComputedLogicalBorderPadding(wm);
+ LogicalMargin borderPadding =
+ aReflowInput.ComputedLogicalBorderPadding(wm).ApplySkipSides(
+ PreReflowBlockLevelLogicalSkipSides());
+ nsIFrame* lastChildReflowed = nullptr;
+ const nsSize containerSize =
+ aReflowInput.ComputedSizeAsContainerIfConstrained();
// The tentative width is the width we assumed for the table when the child
// frames were positioned (which only matters in vertical-rl mode, because
@@ -1691,7 +1700,6 @@ void nsTableFrame::Reflow(nsPresContext* aPresContext,
needToInitiateSpecialReflow =
HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
}
- nsIFrame* lastChildReflowed = nullptr;
NS_ASSERTION(!aReflowInput.mFlags.mSpecialBSizeReflow,
"Shouldn't be in special bsize reflow here!");
@@ -1717,8 +1725,6 @@ void nsTableFrame::Reflow(nsPresContext* aPresContext,
// Note that vertical-lr, unlike vertical-rl, doesn't need to take special
// care of this situation, because they're positioned relative to the
// left-hand edge.
- const nsSize containerSize =
- aReflowInput.ComputedSizeAsContainerIfConstrained();
if (wm.IsVerticalRL()) {
tentativeContainerWidth = containerSize.width;
mayAdjustXForAllChildren = true;
@@ -1736,29 +1742,36 @@ void nsTableFrame::Reflow(nsPresContext* aPresContext,
ReflowInput& mutable_rs = const_cast<ReflowInput&>(aReflowInput);
// distribute extra block-direction space to rows
- aDesiredSize.BSize(wm) = CalcDesiredBSize(aReflowInput, borderPadding);
+ aDesiredSize.BSize(wm) =
+ CalcDesiredBSize(aReflowInput, borderPadding, aStatus);
+ haveCalledCalcDesiredBSize = true;
+
mutable_rs.mFlags.mSpecialBSizeReflow = true;
ReflowTable(aDesiredSize, aReflowInput, borderPadding,
TableReflowMode::Final, lastChildReflowed, aStatus);
- if (lastChildReflowed && aStatus.IsIncomplete()) {
- // if there is an incomplete child, then set the desired bsize
- // to include it but not the next one
- aDesiredSize.BSize(wm) =
- borderPadding.BEnd(wm) + GetRowSpacing(GetRowCount()) +
- lastChildReflowed->GetLogicalNormalRect(wm, containerSize).BEnd(wm);
- }
- haveDesiredBSize = true;
-
mutable_rs.mFlags.mSpecialBSizeReflow = false;
}
}
+ if (aStatus.IsIncomplete() &&
+ aReflowInput.mStyleBorder->mBoxDecorationBreak ==
+ StyleBoxDecorationBreak::Slice) {
+ borderPadding.BEnd(wm) = 0;
+ }
+
aDesiredSize.ISize(wm) =
aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm);
- if (!haveDesiredBSize) {
- aDesiredSize.BSize(wm) = CalcDesiredBSize(aReflowInput, borderPadding);
+ if (!haveCalledCalcDesiredBSize) {
+ aDesiredSize.BSize(wm) =
+ CalcDesiredBSize(aReflowInput, borderPadding, aStatus);
+ } else if (lastChildReflowed && aStatus.IsIncomplete()) {
+ // If there is an incomplete child, then set the desired block-size to
+ // include it but not the next one.
+ aDesiredSize.BSize(wm) =
+ borderPadding.BEnd(wm) +
+ lastChildReflowed->GetLogicalNormalRect(wm, containerSize).BEnd(wm);
}
if (IsRowInserted()) {
ProcessRowInserted(aDesiredSize.BSize(wm));
@@ -2380,16 +2393,15 @@ nsMargin nsTableFrame::GetUsedMargin() const {
return nsMargin(0, 0, 0, 0);
}
-// This property is only set on the first-in-flow of nsTableFrame.
+// TODO(TYLin): Should this property only be set on the first-in-flow of
+// nsTableFrame?
NS_DECLARE_FRAME_PROPERTY_DELETABLE(TableBCDataProperty, TableBCData)
TableBCData* nsTableFrame::GetTableBCData() const {
- return FirstInFlow()->GetProperty(TableBCDataProperty());
+ return GetProperty(TableBCDataProperty());
}
TableBCData* nsTableFrame::GetOrCreateTableBCData() {
- MOZ_ASSERT(!GetPrevInFlow(),
- "TableBCProperty should only be set on the first-in-flow!");
TableBCData* value = GetProperty(TableBCDataProperty());
if (!value) {
value = new TableBCData();
@@ -2609,7 +2621,6 @@ void nsTableFrame::PlaceRepeatedFooter(TableReflowInput& aReflowInput,
kidAvailSize, Nothing(),
ReflowInput::InitFlag::CallerWillInit);
InitChildReflowInput(footerReflowInput);
- aReflowInput.AdvanceBCoord(GetRowSpacing(GetRowCount()));
nsRect origTfootRect = aTfoot->GetRect();
nsRect origTfootInkOverflow = aTfoot->InkOverflowRect();
@@ -2727,6 +2738,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
PushChildrenToOverflow(rowGroups, childX);
aStatus.Reset();
aStatus.SetIncomplete();
+ aLastChildReflowed = allowRepeatedFooter ? tfoot : prevKidFrame;
break;
}
@@ -2769,7 +2781,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
.BEnd(wm) > 0)) {
kidReflowInput.mFlags.mIsTopOfPage = false;
}
- aReflowInput.AdvanceBCoord(rowSpacing);
+
// record the presence of a next in flow, it might get destroyed so we
// need to reorder the row group array
const bool reorder = kidFrame->GetNextInFlow();
@@ -2813,7 +2825,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
aStatus.Reset();
aStatus.SetIncomplete();
PushChildrenToOverflow(rowGroups, childX + 1);
- aLastChildReflowed = kidFrame;
+ aLastChildReflowed = allowRepeatedFooter ? tfoot : kidFrame;
break;
}
} else { // we are not on top, push this rowgroup onto the next page
@@ -2822,7 +2834,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
aStatus.Reset();
aStatus.SetIncomplete();
PushChildrenToOverflow(rowGroups, childX);
- aLastChildReflowed = prevKidFrame;
+ aLastChildReflowed = allowRepeatedFooter ? tfoot : prevKidFrame;
break;
} else { // we can't push so lets make clear how much space we need
PlaceChild(aReflowInput, kidFrame, kidReflowInput, kidPosition,
@@ -2850,6 +2862,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
// Place the child
PlaceChild(aReflowInput, kidFrame, kidReflowInput, kidPosition,
containerSize, desiredSize, oldKidRect, oldKidInkOverflow);
+ aReflowInput.AdvanceBCoord(rowSpacing);
// Remember where we just were in case we end up pushing children
prevKidFrame = kidFrame;
@@ -2887,6 +2900,7 @@ void nsTableFrame::ReflowChildren(TableReflowInput& aReflowInput,
if (kidFrame->GetNextSibling()) {
PushChildrenToOverflow(rowGroups, childX + 1);
}
+ aLastChildReflowed = allowRepeatedFooter ? tfoot : kidFrame;
break;
}
} else { // it isn't being reflowed
@@ -2970,10 +2984,10 @@ void nsTableFrame::ReflowColGroups(gfxContext* aRenderingContext) {
}
nscoord nsTableFrame::CalcDesiredBSize(const ReflowInput& aReflowInput,
- const LogicalMargin& aBorderPadding) {
+ const LogicalMargin& aBorderPadding,
+ const nsReflowStatus& aStatus) {
WritingMode wm = aReflowInput.GetWritingMode();
- // get the natural bsize based on the last child's (row group) rect
RowGroupArray rowGroups = OrderedRowGroups();
if (rowGroups.IsEmpty()) {
if (eCompatibility_NavQuirks == PresContext()->CompatibilityMode()) {
@@ -2990,11 +3004,20 @@ nscoord nsTableFrame::CalcDesiredBSize(const ReflowInput& aReflowInput,
int32_t colCount = cellMap->GetColCount();
nscoord desiredBSize = aBorderPadding.BStartEnd(wm);
if (rowCount > 0 && colCount > 0) {
- desiredBSize += GetRowSpacing(-1);
- for (uint32_t rgIdx = 0; rgIdx < rowGroups.Length(); rgIdx++) {
- desiredBSize += rowGroups[rgIdx]->BSize(wm) +
- GetRowSpacing(rowGroups[rgIdx]->GetRowCount() +
- rowGroups[rgIdx]->GetStartRowIndex());
+ if (!GetPrevInFlow()) {
+ desiredBSize += GetRowSpacing(-1);
+ }
+ const nsTableRowGroupFrame* lastRG = rowGroups.LastElement();
+ for (nsTableRowGroupFrame* rg : rowGroups) {
+ desiredBSize += rg->BSize(wm);
+ if (rg != lastRG || aStatus.IsFullyComplete()) {
+ desiredBSize +=
+ GetRowSpacing(rg->GetStartRowIndex() + rg->GetRowCount());
+ }
+ }
+ if (aReflowInput.ComputedBSize() == NS_UNCONSTRAINEDSIZE &&
+ aStatus.IsIncomplete()) {
+ desiredBSize = std::max(desiredBSize, aReflowInput.AvailableBSize());
}
}
@@ -3903,16 +3926,19 @@ class BCMapCellIterator {
public:
BCMapCellIterator(nsTableFrame* aTableFrame, const TableArea& aDamageArea);
- void First(BCMapCellInfo& aMapCellInfo);
+ void First(BCMapCellInfo& aMapInfo);
- void Next(BCMapCellInfo& aMapCellInfo);
+ void Next(BCMapCellInfo& aMapInfo);
- void PeekIEnd(BCMapCellInfo& aRefInfo, uint32_t aRowIndex,
+ void PeekIEnd(const BCMapCellInfo& aRefInfo, int32_t aRowIndex,
BCMapCellInfo& aAjaInfo);
- void PeekBEnd(BCMapCellInfo& aRefInfo, uint32_t aColIndex,
+ void PeekBEnd(const BCMapCellInfo& aRefInfo, int32_t aColIndex,
BCMapCellInfo& aAjaInfo);
+ void PeekIStart(const BCMapCellInfo& aRefInfo, int32_t aRowIndex,
+ BCMapCellInfo& aAjaInfo);
+
bool IsNewRow() { return mIsNewRow; }
nsTableRowFrame* GetPrevRow() const { return mPrevRow; }
@@ -3927,6 +3953,8 @@ class BCMapCellIterator {
private:
bool SetNewRow(nsTableRowFrame* row = nullptr);
bool SetNewRowGroup(bool aFindFirstDamagedRow);
+ void PeekIAt(const BCMapCellInfo& aRefInfo, int32_t aRowIndex,
+ int32_t aColIndex, BCMapCellInfo& aAjaInfo);
nsTableFrame* mTableFrame;
nsTableCellMap* mTableCellMap;
@@ -4184,35 +4212,14 @@ void BCMapCellIterator::Next(BCMapCellInfo& aMapInfo) {
mAtEnd = true;
}
-void BCMapCellIterator::PeekIEnd(BCMapCellInfo& aRefInfo, uint32_t aRowIndex,
- BCMapCellInfo& aAjaInfo) {
- aAjaInfo.ResetCellInfo();
- int32_t colIndex = aRefInfo.mColIndex + aRefInfo.mColSpan;
- uint32_t rgRowIndex = aRowIndex - mRowGroupStart;
-
- BCCellData* cellData =
- static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, colIndex));
- if (!cellData) { // add a dead cell data
- NS_ASSERTION(colIndex < mTableCellMap->GetColCount(), "program error");
- TableArea damageArea;
- cellData = static_cast<BCCellData*>(mCellMap->AppendCell(
- *mTableCellMap, nullptr, rgRowIndex, false, 0, damageArea));
- if (!cellData) ABORT0();
- }
- nsTableRowFrame* row = nullptr;
- if (cellData->IsRowSpan()) {
- rgRowIndex -= cellData->GetRowSpanOffset();
- cellData =
- static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, colIndex));
- if (!cellData) ABORT0();
- } else {
- row = mRow;
- }
- aAjaInfo.SetInfo(row, colIndex, cellData, this);
+void BCMapCellIterator::PeekIEnd(const BCMapCellInfo& aRefInfo,
+ int32_t aRowIndex, BCMapCellInfo& aAjaInfo) {
+ PeekIAt(aRefInfo, aRowIndex, aRefInfo.mColIndex + aRefInfo.mColSpan,
+ aAjaInfo);
}
-void BCMapCellIterator::PeekBEnd(BCMapCellInfo& aRefInfo, uint32_t aColIndex,
- BCMapCellInfo& aAjaInfo) {
+void BCMapCellIterator::PeekBEnd(const BCMapCellInfo& aRefInfo,
+ int32_t aColIndex, BCMapCellInfo& aAjaInfo) {
aAjaInfo.ResetCellInfo();
int32_t rowIndex = aRefInfo.mRowIndex + aRefInfo.mRowSpan;
int32_t rgRowIndex = rowIndex - mRowGroupStart;
@@ -4227,6 +4234,7 @@ void BCMapCellIterator::PeekBEnd(BCMapCellInfo& aRefInfo, uint32_t aColIndex,
if (rg) {
cellMap = mTableCellMap->GetMapFor(rg, cellMap);
if (!cellMap) ABORT0();
+ // First row of the next row group
rgRowIndex = 0;
nextRow = rg->GetFirstRow();
}
@@ -4251,13 +4259,46 @@ void BCMapCellIterator::PeekBEnd(BCMapCellInfo& aRefInfo, uint32_t aColIndex,
if (!cellData) ABORT0();
}
if (cellData->IsColSpan()) {
- aColIndex -= cellData->GetColSpanOffset();
+ aColIndex -= static_cast<int32_t>(cellData->GetColSpanOffset());
cellData =
static_cast<BCCellData*>(cellMap->GetDataAt(rgRowIndex, aColIndex));
}
aAjaInfo.SetInfo(nextRow, aColIndex, cellData, this, cellMap);
}
+void BCMapCellIterator::PeekIStart(const BCMapCellInfo& aRefInfo,
+ int32_t aRowIndex, BCMapCellInfo& aAjaInfo) {
+ NS_ASSERTION(aRefInfo.mColIndex != 0, "program error");
+ PeekIAt(aRefInfo, aRowIndex, aRefInfo.mColIndex - 1, aAjaInfo);
+}
+
+void BCMapCellIterator::PeekIAt(const BCMapCellInfo& aRefInfo,
+ int32_t aRowIndex, int32_t aColIndex,
+ BCMapCellInfo& aAjaInfo) {
+ aAjaInfo.ResetCellInfo();
+ int32_t rgRowIndex = aRowIndex - mRowGroupStart;
+
+ auto* cellData =
+ static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, aColIndex));
+ if (!cellData) { // add a dead cell data
+ NS_ASSERTION(aColIndex < mTableCellMap->GetColCount(), "program error");
+ TableArea damageArea;
+ cellData = static_cast<BCCellData*>(mCellMap->AppendCell(
+ *mTableCellMap, nullptr, rgRowIndex, false, 0, damageArea));
+ if (!cellData) ABORT0();
+ }
+ nsTableRowFrame* row = nullptr;
+ if (cellData->IsRowSpan()) {
+ rgRowIndex -= static_cast<int32_t>(cellData->GetRowSpanOffset());
+ cellData =
+ static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, aColIndex));
+ if (!cellData) ABORT0();
+ } else {
+ row = mRow;
+ }
+ aAjaInfo.SetInfo(row, aColIndex, cellData, this);
+}
+
#define CELL_CORNER true
/** return the border style, border color and optionally the width in
@@ -5043,6 +5084,24 @@ void nsTableFrame::CalcBCBorders() {
BCCellBorders lastBlockDirBorders(damageArea.ColCount() + 1,
damageArea.StartCol());
if (!lastBlockDirBorders.borders) ABORT0();
+ if (damageArea.StartRow() != 0) {
+ // Ok, we've filled with information about the previous row's borders with
+ // the default state, which is "no borders." This is incorrect, and leaving
+ // it will result in an erroneous behaviour if the previous row did have
+ // borders, and the dirty rows don't, as we will not mark the beginning of
+ // the no border segment.
+ TableArea prevRowArea(damageArea.StartCol(), damageArea.StartRow() - 1,
+ damageArea.ColCount(), 1);
+ BCMapCellIterator iter(this, prevRowArea);
+ BCMapCellInfo info(this);
+ for (iter.First(info); !iter.mAtEnd; iter.Next(info)) {
+ if (info.mColIndex == prevRowArea.StartCol()) {
+ lastBlockDirBorders.borders[0] = info.GetIStartEdgeBorder();
+ }
+ lastBlockDirBorders.borders[info.mColIndex - prevRowArea.StartCol() + 1] =
+ info.GetIEndEdgeBorder();
+ }
+ }
// Inline direction border at block start of the table, computed by the
// previous cell. Unused afterwards.
Maybe<BCCellBorder> firstRowBStartEdgeBorder;
@@ -5072,12 +5131,27 @@ void nsTableFrame::CalcBCBorders() {
if (iter.IsNewRow()) {
if (info.mRowIndex == 0) {
BCCellBorder border;
- border.Reset(info.mRowIndex, info.mRowSpan);
+ if (info.mColIndex == 0) {
+ border.Reset(info.mRowIndex, info.mRowSpan);
+ } else {
+ // Similar to lastBlockDirBorders, the previous block-start border
+ // is filled by actually quering the adjacent cell.
+ BCMapCellInfo ajaInfo(this);
+ iter.PeekIStart(info, info.mRowIndex, ajaInfo);
+ border = ajaInfo.GetBStartEdgeBorder();
+ }
firstRowBStartEdgeBorder = Some(border);
} else {
firstRowBStartEdgeBorder = Nothing{};
}
- lastBEndBorder.Reset(info.GetCellEndRowIndex() + 1, info.mRowSpan);
+ if (info.mColIndex == 0) {
+ lastBEndBorder.Reset(info.GetCellEndRowIndex() + 1, info.mRowSpan);
+ } else {
+ // Same as above, but for block-end border.
+ BCMapCellInfo ajaInfo(this);
+ iter.PeekIStart(info, info.mRowIndex, ajaInfo);
+ lastBEndBorder = ajaInfo.GetBEndEdgeBorder();
+ }
} else if (info.mColIndex > damageArea.StartCol()) {
lastBEndBorder = lastBEndBorders[info.mColIndex - 1];
if (lastBEndBorder.rowIndex > (info.GetCellEndRowIndex() + 1)) {
@@ -5105,7 +5179,7 @@ void nsTableFrame::CalcBCBorders() {
} else {
bStartIStartCorner.Update(eLogicalSideIEnd, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBStartIStart, *iter.mCellMap, 0, 0, colIdx,
+ LogicalCorner::BStartIStart, *iter.mCellMap, 0, 0, colIdx,
LogicalSide(bStartIStartCorner.ownerSide),
bStartIStartCorner.subWidth, bStartIStartCorner.bevel);
}
@@ -5164,7 +5238,7 @@ void nsTableFrame::CalcBCBorders() {
(0 == rowB) ? bStartCorners[0] : bEndCorners[0];
bStartIStartCorner.Update(eLogicalSideBEnd, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBStartIStart, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BStartIStart, *iter.mCellMap, iter.mRowGroupStart,
rowB, 0, LogicalSide(bStartIStartCorner.ownerSide),
bStartIStartCorner.subWidth, bStartIStartCorner.bevel);
bEndCorners[0].Set(eLogicalSideBStart, currentBorder);
@@ -5203,14 +5277,15 @@ void nsTableFrame::CalcBCBorders() {
: bEndCorners[info.GetCellEndColIndex() + 1];
bStartIEndCorner.Update(eLogicalSideBEnd, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBStartIEnd, *iter.mCellMap, iter.mRowGroupStart, rowB,
- info.GetCellEndColIndex(), LogicalSide(bStartIEndCorner.ownerSide),
- bStartIEndCorner.subWidth, bStartIEndCorner.bevel);
+ LogicalCorner::BStartIEnd, *iter.mCellMap, iter.mRowGroupStart,
+ rowB, info.GetCellEndColIndex(),
+ LogicalSide(bStartIEndCorner.ownerSide), bStartIEndCorner.subWidth,
+ bStartIEndCorner.bevel);
BCCornerInfo& bEndIEndCorner =
bEndCorners[info.GetCellEndColIndex() + 1];
bEndIEndCorner.Set(eLogicalSideBStart, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIEnd, *iter.mCellMap, iter.mRowGroupStart, rowB,
+ LogicalCorner::BEndIEnd, *iter.mCellMap, iter.mRowGroupStart, rowB,
info.GetCellEndColIndex(), LogicalSide(bEndIEndCorner.ownerSide),
bEndIEndCorner.subWidth, bEndIEndCorner.bevel);
// update lastBlockDirBorders and see if a new segment starts
@@ -5293,7 +5368,7 @@ void nsTableFrame::CalcBCBorders() {
if (0 != rowB) {
// Ok, actually store the information
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBStartIEnd, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BStartIEnd, *iter.mCellMap, iter.mRowGroupStart,
rowB, info.GetCellEndColIndex(),
LogicalSide(bStartIEndCorner->ownerSide),
bStartIEndCorner->subWidth, bStartIEndCorner->bevel);
@@ -5301,8 +5376,8 @@ void nsTableFrame::CalcBCBorders() {
// Propagate this segment down the rowspan
for (int32_t rX = rowB + 1; rX < rowB + segLength; rX++) {
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIEnd, *iter.mCellMap, iter.mRowGroupStart, rX,
- info.GetCellEndColIndex(),
+ LogicalCorner::BEndIEnd, *iter.mCellMap, iter.mRowGroupStart,
+ rX, info.GetCellEndColIndex(),
LogicalSide(bStartIEndCorner->ownerSide),
bStartIEndCorner->subWidth, false);
}
@@ -5336,7 +5411,7 @@ void nsTableFrame::CalcBCBorders() {
BCCornerInfo& bEndIStartCorner = bEndCorners[colIdx];
bEndIStartCorner.Update(eLogicalSideIEnd, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIStart, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BEndIStart, *iter.mCellMap, iter.mRowGroupStart,
info.GetCellEndRowIndex(), colIdx,
LogicalSide(bEndIStartCorner.ownerSide), bEndIStartCorner.subWidth,
bEndIStartCorner.bevel);
@@ -5346,7 +5421,7 @@ void nsTableFrame::CalcBCBorders() {
// inline-end of the overall table.
if (info.mNumTableCols == colIdx + 1) {
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIEnd, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BEndIEnd, *iter.mCellMap, iter.mRowGroupStart,
info.GetCellEndRowIndex(), colIdx,
LogicalSide(bEndIEndCorner.ownerSide), bEndIEndCorner.subWidth,
bEndIEndCorner.bevel, true);
@@ -5423,7 +5498,7 @@ void nsTableFrame::CalcBCBorders() {
colIdx >= damageArea.StartCol()) {
if (hitsSpanBelow) {
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIStart, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BEndIStart, *iter.mCellMap, iter.mRowGroupStart,
info.GetCellEndRowIndex(), colIdx,
LogicalSide(bEndIStartCorner.ownerSide),
bEndIStartCorner.subWidth, bEndIStartCorner.bevel);
@@ -5433,7 +5508,7 @@ void nsTableFrame::CalcBCBorders() {
BCCornerInfo& corner = bEndCorners[c];
corner.Set(eLogicalSideIEnd, currentBorder);
tableCellMap->SetBCBorderCorner(
- eLogicalCornerBEndIStart, *iter.mCellMap, iter.mRowGroupStart,
+ LogicalCorner::BEndIStart, *iter.mCellMap, iter.mRowGroupStart,
info.GetCellEndRowIndex(), c, LogicalSide(corner.ownerSide),
corner.subWidth, false);
}
diff --git a/layout/tables/nsTableFrame.h b/layout/tables/nsTableFrame.h
index 0204af9834..d6105308c6 100644
--- a/layout/tables/nsTableFrame.h
+++ b/layout/tables/nsTableFrame.h
@@ -634,7 +634,8 @@ class nsTableFrame : public nsContainerFrame {
// distribute extra block-size to table rows if the table has a specified
// block-size larger than the intrinsic block-size.
nscoord CalcDesiredBSize(const ReflowInput& aReflowInput,
- const LogicalMargin& aBorderPadding);
+ const LogicalMargin& aBorderPadding,
+ const nsReflowStatus& aStatus);
// The following is a helper for CalcDesiredBSize
void DistributeBSizeToRows(const ReflowInput& aReflowInput, nscoord aAmount);
diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp
index 5d8119522f..1190561ee8 100644
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -13,7 +13,6 @@
#include "mozilla/ComputedStyle.h"
#include "mozilla/StaticPrefs_layout.h"
#include "nsStyleConsts.h"
-#include "nsGkAtoms.h"
#include "nsIContent.h"
#include "nsIFrame.h"
#include "nsIFrameInlines.h"
@@ -23,9 +22,7 @@
#include "nsHTMLParts.h"
#include "nsTableColGroupFrame.h"
#include "nsTableColFrame.h"
-#include "nsCOMPtr.h"
#include "nsDisplayList.h"
-#include "nsIFrameInlines.h"
#include <algorithm>
#ifdef ACCESSIBILITY
@@ -443,35 +440,36 @@ void nsTableRowFrame::UpdateBSize(nscoord aBSize, nscoord aAscent,
return;
}
- if (aBSize != NS_UNCONSTRAINEDSIZE) {
- if (!(aCellFrame->HasVerticalAlignBaseline())) { // only the cell's height
- // matters
- if (GetInitialBSize() < aBSize) {
- int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
- if (rowSpan == 1) {
- SetContentBSize(aBSize);
- }
- }
- } else { // the alignment on the baseline can change the bsize
- NS_ASSERTION((aAscent != NS_UNCONSTRAINEDSIZE) &&
- (aDescent != NS_UNCONSTRAINEDSIZE),
- "invalid call");
- // see if this is a long ascender
- if (mMaxCellAscent < aAscent) {
- mMaxCellAscent = aAscent;
- }
- // see if this is a long descender and without rowspan
- if (mMaxCellDescent < aDescent) {
- int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
- if (rowSpan == 1) {
- mMaxCellDescent = aDescent;
- }
+ if (aBSize == NS_UNCONSTRAINEDSIZE) {
+ return;
+ }
+ if (!aCellFrame->HasVerticalAlignBaseline()) {
+ // only the cell's height matters
+ if (GetInitialBSize() < aBSize) {
+ int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
+ if (rowSpan == 1) {
+ SetContentBSize(aBSize);
}
- // keep the tallest bsize in sync
- if (GetInitialBSize() < mMaxCellAscent + mMaxCellDescent) {
- SetContentBSize(mMaxCellAscent + mMaxCellDescent);
+ }
+ } else { // the alignment on the baseline can change the bsize
+ NS_ASSERTION(
+ aAscent != NS_UNCONSTRAINEDSIZE && aDescent != NS_UNCONSTRAINEDSIZE,
+ "invalid call");
+ // see if this is a long ascender
+ if (mMaxCellAscent < aAscent) {
+ mMaxCellAscent = aAscent;
+ }
+ // see if this is a long descender and without rowspan
+ if (mMaxCellDescent < aDescent) {
+ int32_t rowSpan = aTableFrame->GetEffectiveRowSpan(*aCellFrame);
+ if (rowSpan == 1) {
+ mMaxCellDescent = aDescent;
}
}
+ // keep the tallest bsize in sync
+ if (GetInitialBSize() < mMaxCellAscent + mMaxCellDescent) {
+ SetContentBSize(mMaxCellAscent + mMaxCellDescent);
+ }
}
}
@@ -497,7 +495,7 @@ nscoord nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput) {
kidFrame = kidFrame->GetNextCell()) {
MOZ_ASSERT(kidFrame->GetWritingMode() == wm);
LogicalSize desSize = kidFrame->GetDesiredSize();
- if ((NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) &&
+ if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize() &&
!GetPrevInFlow()) {
desSize.BSize(wm) = CalcCellActualBSize(kidFrame, desSize.BSize(wm), wm);
}
@@ -706,19 +704,19 @@ void nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
bool doReflowChild = true;
if (!aReflowInput.ShouldReflowAllKids() && !aTableFrame.IsGeometryDirty() &&
!kidFrame->IsSubtreeDirty()) {
- if (!aReflowInput.mFlags.mSpecialBSizeReflow) doReflowChild = false;
- } else if ((NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableBSize())) {
+ if (!aReflowInput.mFlags.mSpecialBSizeReflow) {
+ doReflowChild = false;
+ }
+ } else if (NS_UNCONSTRAINEDSIZE != aReflowInput.AvailableBSize()) {
// We don't reflow a rowspan >1 cell here with a constrained bsize.
// That happens in nsTableRowGroupFrame::SplitSpanningCells.
if (aTableFrame.GetEffectiveRowSpan(*kidFrame) > 1) {
doReflowChild = false;
}
}
- if (aReflowInput.mFlags.mSpecialBSizeReflow) {
- if (!isPaginated &&
- !kidFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
- continue;
- }
+ if (aReflowInput.mFlags.mSpecialBSizeReflow && !isPaginated &&
+ !kidFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE)) {
+ continue;
}
uint32_t cellColIndex = kidFrame->ColIndex();