зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1865172 Part 1 - Always store a page name value when a breakpoint is first found during block reflow. r=dholbert
This happens in a similar location to where we find a breakpoint caused by a change in page name. However, if the breakpoint was caused by something else, we still need to compute this value so that the next page being constructed will have the correct page name. This also "fixes" the WPT /css/printing/page-name-007-print.html, which passed before this patch just because our previous logic would continue using the last page value in those cases, which coincidentally matched what was expected. Part 2 will include a test that specifically detects this discrepency. Differential Revision: https://phabricator.services.mozilla.com/D196895
This commit is contained in:
Родитель
ae3439337b
Коммит
2bf56c0358
|
@ -8042,6 +8042,20 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
|
|||
return newFrame;
|
||||
}
|
||||
|
||||
void nsCSSFrameConstructor::MaybeSetNextPageContentFramePageName(
|
||||
const nsIFrame* aFrame) {
|
||||
MOZ_ASSERT(aFrame, "Frame should not be null");
|
||||
// No parent means the root frame, which isn't what this funciton is for.
|
||||
MOZ_ASSERT(aFrame->GetParent(),
|
||||
"Frame should be the first child placed on a new page, not the "
|
||||
"root frame.");
|
||||
if (mNextPageContentFramePageName) {
|
||||
return;
|
||||
}
|
||||
const nsAtom* const autoValue = aFrame->GetParent()->GetAutoPageValue();
|
||||
mNextPageContentFramePageName = aFrame->ComputePageValue(autoValue);
|
||||
}
|
||||
|
||||
nsresult nsCSSFrameConstructor::ReplicateFixedFrames(
|
||||
nsPageContentFrame* aParentFrame) {
|
||||
// Now deal with fixed-pos things.... They should appear on all pages,
|
||||
|
|
|
@ -297,12 +297,39 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||
nsContainerFrame* aParentFrame,
|
||||
bool aIsFluid = true);
|
||||
|
||||
void SetNextPageContentFramePageName(const nsAtom* aAtom) {
|
||||
/**
|
||||
* Sets the page name when a page break is being generated due to a change
|
||||
* in page name.
|
||||
*
|
||||
* Should only be used during paginated reflow, to signal what page value
|
||||
* the next page content frame should have.
|
||||
*
|
||||
* It is an error to set this if a new page name has already been set, either
|
||||
* through SetNextPageContentFramePageName or
|
||||
* MaybeSetNextPageContentFramePageName.
|
||||
*/
|
||||
void SetNextPageContentFramePageName(const nsAtom* aPageName) {
|
||||
MOZ_ASSERT(aPageName, "New page name should never be null");
|
||||
MOZ_ASSERT(!mNextPageContentFramePageName,
|
||||
"PageContentFrame page name was already set");
|
||||
mNextPageContentFramePageName = aAtom;
|
||||
mNextPageContentFramePageName = aPageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a new page name has not been set for the next page, sets the value
|
||||
* using the given frame.
|
||||
*
|
||||
* |aFrame| should be a frame to be placed on the new page.
|
||||
*
|
||||
* This function handles the work of resolving an atom for the frame, and
|
||||
* avoids doing this extra work when not necessary.
|
||||
*
|
||||
* This is used during block reflow when a page break has occurred but it was
|
||||
* not caused by a change in page name. It should only be used during
|
||||
* paginated reflow.
|
||||
*/
|
||||
void MaybeSetNextPageContentFramePageName(const nsIFrame* aFrame);
|
||||
|
||||
// Copy over fixed frames from aParentFrame's prev-in-flow
|
||||
nsresult ReplicateFixedFrames(nsPageContentFrame* aParentFrame);
|
||||
|
||||
|
|
|
@ -3153,9 +3153,12 @@ bool nsBlockFrame::ReflowDirtyLines(BlockReflowState& aState) {
|
|||
// Immediately fragment for page-name. It is possible we could break
|
||||
// out of the loop right here, but this should make it more similar to
|
||||
// what happens when reflow causes fragmentation.
|
||||
PushTruncatedLine(aState, line, &keepGoing);
|
||||
// Set the page name, so that PushTruncatedLine does not need to
|
||||
// recalculate the new page name.
|
||||
PresShell()->FrameConstructor()->SetNextPageContentFramePageName(
|
||||
nextPageName ? nextPageName : GetAutoPageValue());
|
||||
PushTruncatedLine(aState, line, &keepGoing,
|
||||
ComputeNewPageNameIfNeeded::No);
|
||||
} else {
|
||||
// Reflow the dirty line. If it's an incremental reflow, then force
|
||||
// it to invalidate the dirty area if necessary
|
||||
|
@ -4730,11 +4733,25 @@ void nsBlockFrame::SetBreakBeforeStatusBeforeLine(BlockReflowState& aState,
|
|||
*aKeepReflowGoing = false;
|
||||
}
|
||||
|
||||
void nsBlockFrame::PushTruncatedLine(BlockReflowState& aState,
|
||||
LineIterator aLine,
|
||||
bool* aKeepReflowGoing) {
|
||||
void nsBlockFrame::PushTruncatedLine(
|
||||
BlockReflowState& aState, LineIterator aLine, bool* aKeepReflowGoing,
|
||||
ComputeNewPageNameIfNeeded aComputeNewPageName) {
|
||||
PushLines(aState, aLine.prev());
|
||||
*aKeepReflowGoing = false;
|
||||
|
||||
if (aComputeNewPageName == ComputeNewPageNameIfNeeded::Yes) {
|
||||
// mCanHaveClassABreakpoints can only be true during paginated reflow, and
|
||||
// we expect this function to only be called when the available bsize is
|
||||
// constrained.
|
||||
const WritingMode wm = GetWritingMode();
|
||||
const bool canBreakForPageNames =
|
||||
aState.mReflowInput.mFlags.mCanHaveClassABreakpoints &&
|
||||
!PresShell()->GetRootFrame()->GetWritingMode().IsOrthogonalTo(wm);
|
||||
if (canBreakForPageNames) {
|
||||
PresShell()->FrameConstructor()->MaybeSetNextPageContentFramePageName(
|
||||
aLine->mFirstChild);
|
||||
}
|
||||
}
|
||||
aState.mReflowStatus.SetIncomplete();
|
||||
}
|
||||
|
||||
|
|
|
@ -848,13 +848,24 @@ class nsBlockFrame : public nsContainerFrame {
|
|||
LineIterator aLine,
|
||||
bool* aKeepReflowGoing);
|
||||
|
||||
/**
|
||||
* Indicates if we need to compute a page name for the next page when pushing
|
||||
* a truncated line.
|
||||
*
|
||||
* Using a value of No saves work when a new page name has already been set
|
||||
* with nsCSSFrameConstructor::SetNextPageContentFramePageName.
|
||||
*/
|
||||
enum class ComputeNewPageNameIfNeeded : uint8_t { Yes, No };
|
||||
|
||||
/**
|
||||
* Push aLine (and any after it), since it cannot be placed on this
|
||||
* page/column. Set aKeepReflowGoing to false and set
|
||||
* flag aState.mReflowStatus as incomplete.
|
||||
*/
|
||||
void PushTruncatedLine(BlockReflowState& aState, LineIterator aLine,
|
||||
bool* aKeepReflowGoing);
|
||||
bool* aKeepReflowGoing,
|
||||
ComputeNewPageNameIfNeeded aComputeNewPageName =
|
||||
ComputeNewPageNameIfNeeded::Yes);
|
||||
|
||||
void SplitLine(BlockReflowState& aState, nsLineLayout& aLineLayout,
|
||||
LineIterator aLine, nsIFrame* aFrame,
|
||||
|
|
|
@ -2117,8 +2117,8 @@ nsIFrame::CaretBlockAxisMetrics nsIFrame::GetCaretBlockAxisMetrics(
|
|||
return CaretBlockAxisMetrics{.mOffset = baseline - ascent, .mExtent = height};
|
||||
}
|
||||
|
||||
const nsAtom* nsIFrame::ComputePageValue() const {
|
||||
const nsAtom* value = nsGkAtoms::_empty;
|
||||
const nsAtom* nsIFrame::ComputePageValue(const nsAtom* aAutoValue) const {
|
||||
const nsAtom* value = aAutoValue ? aAutoValue : nsGkAtoms::_empty;
|
||||
const nsIFrame* frame = this;
|
||||
// Find what CSS page name value this frame's subtree has, if any.
|
||||
// Starting with this frame, check if a page name other than auto is present,
|
||||
|
|
|
@ -1643,7 +1643,13 @@ class nsIFrame : public nsQueryFrame {
|
|||
// This is intended to be used either on the root frame to find the first
|
||||
// page's page-name, or on a newly created continuation to find what the new
|
||||
// page's page-name will be.
|
||||
const nsAtom* ComputePageValue() const MOZ_NONNULL_RETURN;
|
||||
//
|
||||
// The auto page value can be set by the caller. This is useful when trying
|
||||
// to compute a page value in the middle of a frame tree. In that case the
|
||||
// auto value can be found from the AutoPageValue frame property of the
|
||||
// parent frame. A null auto value is interpreted as the empty-string atom.
|
||||
const nsAtom* ComputePageValue(const nsAtom* aAutoValue = nullptr) const
|
||||
MOZ_NONNULL_RETURN;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// The public visibility API.
|
||||
|
|
Загрузка…
Ссылка в новой задаче