Bug 1804794 - Do not allow CSS named page breaks except in specific subtrees. r=dholbert

This currently only includes block frames, grid containers, and flex
containers, and the document and pagination frames. It is possible more frames
will need to be added or more advanced checks in the future.

This adds some related tests to ignoring some subtrees, but are expected fails
until bug 1816570 is fixed.

Differential Revision: https://phabricator.services.mozilla.com/D169018
This commit is contained in:
Emily McDonough 2023-02-22 02:29:31 +00:00
parent 4f47e992e7
commit 75a6f4f11e
16 changed files with 158 additions and 3 deletions

View File

@ -140,6 +140,9 @@ ReflowInput::ReflowInput(nsPresContext* aPresContext, nsIFrame* aFrame,
if (!aFlags.contains(InitFlag::CallerWillInit)) {
Init(aPresContext);
}
// If we encounter a PageContent frame, this will be flipped on and the pref
// layout.css.named-pages.enabled will be checked.
mFlags.mCanHaveClassABreakpoints = false;
}
// Initialize a reflow input for a child frame's reflow. Some state
@ -199,6 +202,49 @@ ReflowInput::ReflowInput(nsPresContext* aPresContext,
mFlags.mStaticPosIsCBOrigin = aFlags.contains(InitFlag::StaticPosIsCBOrigin);
mFlags.mIOffsetsNeedCSSAlign = mFlags.mBOffsetsNeedCSSAlign = false;
// aPresContext->IsPaginated() and the named pages pref should have been
// checked when constructing the root ReflowInput.
if (aParentReflowInput.mFlags.mCanHaveClassABreakpoints) {
MOZ_ASSERT(aPresContext->IsPaginated(),
"mCanHaveClassABreakpoints set during non-paginated reflow.");
MOZ_ASSERT(StaticPrefs::layout_css_named_pages_enabled(),
"mCanHaveClassABreakpoints should not be set when "
"layout.css.named_pages.enabled is false");
}
{
using mozilla::LayoutFrameType;
switch (mFrame->Type()) {
case LayoutFrameType::PageContent:
// PageContent requires paginated reflow.
MOZ_ASSERT(aPresContext->IsPaginated(),
"nsPageContentFrame should not be in non-paginated reflow");
MOZ_ASSERT(!mFlags.mCanHaveClassABreakpoints,
"mFlags.mCanHaveClassABreakpoints should have been "
"initalized to false before we found nsPageContentFrame");
mFlags.mCanHaveClassABreakpoints =
StaticPrefs::layout_css_named_pages_enabled();
break;
case LayoutFrameType::Block: // FALLTHROUGH
case LayoutFrameType::Canvas: // FALLTHROUGH
case LayoutFrameType::FlexContainer: // FALLTHROUGH
case LayoutFrameType::GridContainer:
// This frame type can have class A breakpoints, inherit this flag
// from the parent (this is done for all flags during construction).
// This also includes Canvas frames, as each PageContent frame always
// has exactly one child which is a Canvas frame.
// Do NOT include the subclasses of BlockFrame here, as the ones for
// which this could be applicable (ColumnSetWrapper and the MathML
// frames) cannot have class A breakpoints.
MOZ_ASSERT(mFlags.mCanHaveClassABreakpoints ==
aParentReflowInput.mFlags.mCanHaveClassABreakpoints);
break;
default:
mFlags.mCanHaveClassABreakpoints = false;
break;
}
}
if (aFlags.contains(InitFlag::DummyParentReflowInput) ||
(mParentReflowInput->mFlags.mDummyParentReflowInput &&
mFrame->IsTableFrame())) {

View File

@ -562,6 +562,10 @@ struct ReflowInput : public SizeComputationInput {
// children's block-size (after reflowing them).
// https://drafts.csswg.org/css-sizing-4/#aspect-ratio-minimum
bool mIsBSizeSetByAspectRatio : 1;
// If true, then children of this frame can generate class A breakpoints
// for paginated reflow.
bool mCanHaveClassABreakpoints : 1;
};
Flags mFlags;

View File

@ -2647,11 +2647,23 @@ void nsBlockFrame::ReflowDirtyLines(BlockReflowState& aState) {
// See: https://www.w3.org/TR/css-break-3/#btw-blocks
const nsPresContext* const presCtx = aState.mPresContext;
const bool canBreakForPageNames =
aState.mReflowInput.mFlags.mCanHaveClassABreakpoints &&
aState.mReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE &&
presCtx->IsPaginated() && StaticPrefs::layout_css_named_pages_enabled() &&
presCtx->GetPresShell()->GetRootFrame()->GetWritingMode().IsVertical() ==
GetWritingMode().IsVertical();
// ReflowInput.mFlags.mCanHaveClassABreakpoints should respect the named
// pages pref and presCtx->IsPaginated, so we did not explicitly check these
// above when setting canBreakForPageNames.
if (canBreakForPageNames) {
MOZ_ASSERT(presCtx->IsPaginated(),
"canBreakForPageNames should not be set during non-paginated "
"reflow");
MOZ_ASSERT(StaticPrefs::layout_css_named_pages_enabled(),
"canBreakForPageNames should not be set when "
"layout.css.named_pages.enabled is false");
}
// Reflow the lines that are already ours
for (; line != line_end; ++line, aState.AdvanceToNextLine()) {
DumpLine(aState, line, deltaBCoord, 0);

View File

@ -0,0 +1,10 @@
<script>
window.onload = () => {
SpecialPowers.wrap(window).printPreview()?.close()
}
</script>
<style>
html { column-count: 5 }
</style>
<hr style="page: a">
<a>A</a>

View File

@ -9,3 +9,4 @@ load 1748277.html # Bug 1751260
load 1758199-1.html
pref(layout.css.named-pages.enabled,true) load 1804571.html
pref(layout.css.named-pages.enabled,true) load 1804798.html
pref(layout.css.named-pages.enabled,true) load 1804794.html

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div>a</div>
<div style="position: absolute; right: 0; top: 0;">b</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div>a</div>
<div style="page: b; position: absolute; right: 0; top: 0;">b</div>
</body>
</html>

View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="position: absolute; left: 0; top: 0;">
<div>a</div>
<div>b</div>
</div>
</body>
</html>

View File

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="position: absolute; left: 0; top: 0;">
<div style="page: a">a</div>
<div style="page: b">b</div>
</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="page: a">a</div>
<div style="page: b; position: absolute; left: 0; top: 0;">b</div>
<div style="page: c; break-before: page;">c</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="page: a">a</div>
<div style="page: b; position: absolute; left: 0; top: 0;">b</div>
<div style="page: c">c</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="float: left;">a</div>
<div>b</div>
</body>
</html>

View File

@ -0,0 +1,7 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="page: a; float: left;">a</div>
<div style="page: b">b</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div>a</div>
<div style="float: left;">b</div>
<div style="break-before: page;">c</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html class="reftest-paged">
<body>
<div style="page: a">a</div>
<div style="page: b; float: left;">b</div>
<div style="page: c">c</div>
</body>
</html>

View File

@ -1,11 +1,13 @@
defaults pref(layout.css.named-pages.enabled,true)
# https://bugzilla.mozilla.org/1764437
== page-name-display-none-child.html page-name-display-none-child-ref.html
== page-name-abspos-001.html page-name-abspos-001-ref.html
fails == page-name-abspos-002.html page-name-abspos-002-ref.html # bug 1816570
fails == page-name-abspos-003.html page-name-abspos-003-ref.html # bug 1816570
== page-name-canvas-001.html page-name-canvas-001-ref.html
== page-name-canvas-002.html page-name-canvas-002-ref.html
== page-name-canvas-003.html page-name-canvas-003-ref.html
== page-name-canvas-004.html page-name-canvas-004-ref.html
== page-name-display-none-child.html page-name-display-none-child-ref.html
== page-name-fixed-pos-001.html page-name-fixed-pos-001-ref.html
== page-name-flex-001.html page-name-flex-001-ref.html
== page-name-flex-002.html page-name-flex-002-ref.html
@ -13,6 +15,8 @@ defaults pref(layout.css.named-pages.enabled,true)
# This is affected by https://bugzilla.mozilla.org/1663079, however we can
# still expect this to behave the same with break-after and page name breaks.
== page-name-flex-004.html page-name-flex-004-ref.html
== page-name-float-001.html page-name-float-001-ref.html
fails == page-name-float-002.html page-name-float-002-ref.html # bug 1816570
== page-name-img-001.html page-name-img-001-ref.html
== page-name-img-002.html page-name-img-002-ref.html
== page-name-img-003.html page-name-img-003-ref.html