Bug 1907289 - Reflow table cell if collapsed borders have changed. r=dshin, a=dmeehan

A potentially better approach could be to call FrameNeedsReflow from
nsBCTableCellFrame::SetBorderWidth... But it seems that might
over-invalidate quite a lot when recalculating borders, since it seems
we reset the relevant ones and then accumulate directly on the frame.

If that seems like a better approach, happy to give that a try. This
should be less risky for performance changes in general tho.

Differential Revision: https://phabricator.services.mozilla.com/D216409
This commit is contained in:
Emilio Cobos Álvarez 2024-07-12 15:05:32 +00:00
parent fa75917866
commit e1d6dd14b9
5 changed files with 87 additions and 10 deletions

View file

@ -889,6 +889,14 @@ void nsTableCellFrame::Reflow(nsPresContext* aPresContext,
PushDirtyBitToAbsoluteFrames();
}
void nsBCTableCellFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus) {
nsTableCellFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
mLastUsedBorder = GetUsedBorder();
}
/* ----- global methods ----- */
NS_QUERYFRAME_HEAD(nsTableCellFrame)
@ -944,9 +952,7 @@ nsresult nsTableCellFrame::GetFrameName(nsAString& aResult) const {
nsBCTableCellFrame::nsBCTableCellFrame(ComputedStyle* aStyle,
nsTableFrame* aTableFrame)
: nsTableCellFrame(aStyle, aTableFrame, kClassID) {
mBStartBorder = mIEndBorder = mBEndBorder = mIStartBorder = 0;
}
: nsTableCellFrame(aStyle, aTableFrame, kClassID) {}
nsBCTableCellFrame::~nsBCTableCellFrame() = default;

View file

@ -216,6 +216,7 @@ class nsTableCellFrame : public nsContainerFrame,
}
virtual mozilla::LogicalMargin GetBorderWidth(mozilla::WritingMode aWM) const;
virtual bool BCBordersChanged() const { return false; }
void DecorateForSelection(DrawTarget* aDrawTarget, nsPoint aPt);
@ -265,10 +266,15 @@ class nsBCTableCellFrame final : public nsTableCellFrame {
NS_DECL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
nsBCTableCellFrame(ComputedStyle* aStyle, nsTableFrame* aTableFrame);
void Reflow(nsPresContext*, ReflowOutput&, const ReflowInput&,
nsReflowStatus&) override;
~nsBCTableCellFrame();
nsMargin GetUsedBorder() const override;
bool BCBordersChanged() const override {
return GetUsedBorder() != mLastUsedBorder;
}
// Get the *inner half of the border only*, in twips.
mozilla::LogicalMargin GetBorderWidth(
@ -289,10 +295,12 @@ class nsBCTableCellFrame final : public nsTableCellFrame {
private:
// These are the entire width of the border (the cell edge contains only
// the inner half).
nscoord mBStartBorder;
nscoord mIEndBorder;
nscoord mBEndBorder;
nscoord mIStartBorder;
nscoord mBStartBorder = 0;
nscoord mIEndBorder = 0;
nscoord mBEndBorder = 0;
nscoord mIStartBorder = 0;
nsMargin mLastUsedBorder;
};
// Implemented here because that's a sane-ish way to make the includes work out.

View file

@ -755,14 +755,14 @@ void nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
NS_ASSERTION(kidFrame->GetWritingMode() == wm,
"expected consistent writing-mode within table");
LogicalSize cellDesiredSize = kidFrame->GetDesiredSize();
if ((availCellISize != kidFrame->GetPriorAvailISize()) ||
(cellDesiredSize.ISize(wm) > kidFrame->GetPriorAvailISize()) ||
if (availCellISize != kidFrame->GetPriorAvailISize() ||
cellDesiredSize.ISize(wm) > kidFrame->GetPriorAvailISize() ||
HasAnyStateBits(NS_FRAME_IS_DIRTY) || isPaginated ||
kidFrame->IsSubtreeDirty() ||
// See if it needs a special reflow, or if it had one that we need to
// undo.
kidFrame->HasAnyStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE) ||
HasPctBSize()) {
kidFrame->BCBordersChanged() || HasPctBSize()) {
// Reflow the cell to fit the available isize, bsize
// XXX The old IR_ChildIsDirty code used availCellISize here.
LogicalSize kidAvailSize(wm, availCellISize,

View file

@ -0,0 +1,24 @@
<!doctype html>
<meta charset="utf-8">
<title>CSS test reference</title>
<style>
table {
border-collapse: collapse;
}
td {
border-bottom: 10px solid;
}
</style>
<table>
<thead>
<tr>
<td>Something</td>
</tr>
</thead>
<tbody>
<tr>
<td>Body</td>
</tr>
</tbody>
</table>

View file

@ -0,0 +1,39 @@
<!doctype html>
<meta charset="utf-8">
<title>collapsed border recalculation as a result of removal</title>
<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
<link rel="author" href="https://mozilla.org" title="Mozilla">
<link rel="help" href="https://drafts.csswg.org/css-tables/#border-collapse-property">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1907289">
<link rel="match" href="collapsed-border-remove-row-group-ref.html">
<style>
table {
border-collapse: collapse;
}
td {
border-bottom: 10px solid;
}
</style>
<table>
<thead>
<tr>
<td>Something</td>
</tr>
</thead>
<thead id="removeMe">
<tr>
<td style="border: 0">Something</td>
</tr>
</thead>
<tbody>
<tr>
<td>Body</td>
</tr>
</tbody>
</table>
<script>
onload = function () {
removeMe.getBoundingClientRect();
removeMe.remove();
};
</script>