mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 00:32:11 +00:00
Bug 1652278 part 2: Flesh out PrintedSheetFrame implementation so that it serves as the container for nsPageFrame. r=TYLin
This patch: - Creates an anon-box pseudo-style for PrintedSheetFrame, in part so that it can co-opt the styles that we formerly gave to page-frames in ua.css, to draw the sheet of paper and the shadow in Print Preview. - Adjusts nsCSSFrameConstructor to create a PrintedSheetFrame as the parent of nsPageFrame (inserting between it and its nsPageSequenceFrame container, in the frame tree). - Fleshes out out a simple BuildDisplayList() implementation for PrintedSheetFrame (taking the responsibility for "paper"-drawing from nsPageFrame). - Fleshes out a simple Reflow implementation for PrintedSheetFrame, just placing the child page (assuming there's only one for now) at the origin. - Adjusts nsPageFrame and nsPageSequenceFrame to account for the fact that there's another layer between them now. Note that PrintedSheetFrame needs to implement AppendDirectlyOwnedAnonBoxes() (just as nsSimplePageSequence and nsPageFrame do), since it owns anonymous nsPageFrame instances. This implementation only needs to append the first child, as explained in the code-comment and in https://bugzilla.mozilla.org/show_bug.cgi?id=1374761#c9 (and of course, for now, PrintedSheetFrame only has one child at a time anyway.) Differential Revision: https://phabricator.services.mozilla.com/D83457
This commit is contained in:
parent
41ce298d55
commit
96d67c6eb3
@ -29,6 +29,7 @@
|
|||||||
#include "mozilla/MemoryReporting.h"
|
#include "mozilla/MemoryReporting.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/PresShellInlines.h"
|
#include "mozilla/PresShellInlines.h"
|
||||||
|
#include "mozilla/PrintedSheetFrame.h"
|
||||||
#include "mozilla/ServoBindings.h"
|
#include "mozilla/ServoBindings.h"
|
||||||
#include "mozilla/ServoStyleSetInlines.h"
|
#include "mozilla/ServoStyleSetInlines.h"
|
||||||
#include "mozilla/StaticPrefs_layout.h"
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
@ -2467,22 +2468,24 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
|
|
||||||
ViewportFrame
|
ViewportFrame
|
||||||
nsPageSequenceFrame
|
nsPageSequenceFrame
|
||||||
nsPageFrame
|
PrintedSheetFrame
|
||||||
nsPageContentFrame [fixed-cb]
|
nsPageFrame
|
||||||
nsCanvasFrame [abs-cb]
|
nsPageContentFrame [fixed-cb]
|
||||||
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
nsCanvasFrame [abs-cb]
|
||||||
nsTableWrapperFrame, nsPlaceholderFrame)
|
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
||||||
|
nsTableWrapperFrame, nsPlaceholderFrame)
|
||||||
|
|
||||||
Print-preview presentation, non-XUL
|
Print-preview presentation, non-XUL
|
||||||
|
|
||||||
ViewportFrame
|
ViewportFrame
|
||||||
nsHTMLScrollFrame
|
nsHTMLScrollFrame
|
||||||
nsPageSequenceFrame
|
nsPageSequenceFrame
|
||||||
nsPageFrame
|
PrintedSheetFrame
|
||||||
nsPageContentFrame [fixed-cb]
|
nsPageFrame
|
||||||
nsCanvasFrame [abs-cb]
|
nsPageContentFrame [fixed-cb]
|
||||||
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
nsCanvasFrame [abs-cb]
|
||||||
nsTableWrapperFrame, nsPlaceholderFrame)
|
root element frame (nsBlockFrame, SVGOuterSVGFrame,
|
||||||
|
nsTableWrapperFrame, nsPlaceholderFrame)
|
||||||
|
|
||||||
Print/print preview of XUL is not supported.
|
Print/print preview of XUL is not supported.
|
||||||
[fixed-cb]: the default containing block for fixed-pos content
|
[fixed-cb]: the default containing block for fixed-pos content
|
||||||
@ -2628,13 +2631,20 @@ void nsCSSFrameConstructor::SetUpDocElementContainingBlock(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isPaginated) {
|
if (isPaginated) {
|
||||||
// Create the first page
|
// Create the first printed sheet frame, as the sole child (for now) of our
|
||||||
// Set the initial child lists
|
// page sequence frame (rootFrame).
|
||||||
|
auto* printedSheetFrame =
|
||||||
|
ConstructPrintedSheetFrame(mPresShell, rootFrame, nullptr);
|
||||||
|
printedSheetFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
||||||
|
SetInitialSingleChild(rootFrame, printedSheetFrame);
|
||||||
|
|
||||||
|
// Create the first page, as the sole child (for now) of the printed sheet
|
||||||
|
// frame that we just created.
|
||||||
nsContainerFrame* canvasFrame;
|
nsContainerFrame* canvasFrame;
|
||||||
nsContainerFrame* pageFrame =
|
nsContainerFrame* pageFrame =
|
||||||
ConstructPageFrame(mPresShell, rootFrame, nullptr, canvasFrame);
|
ConstructPageFrame(mPresShell, printedSheetFrame, nullptr, canvasFrame);
|
||||||
pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
pageFrame->AddStateBits(NS_FRAME_OWNS_ANON_BOXES);
|
||||||
SetInitialSingleChild(rootFrame, pageFrame);
|
SetInitialSingleChild(printedSheetFrame, pageFrame);
|
||||||
|
|
||||||
// The eventual parent of the document element frame.
|
// The eventual parent of the document element frame.
|
||||||
// XXX should this be set for every new page (in ConstructPageFrame)?
|
// XXX should this be set for every new page (in ConstructPageFrame)?
|
||||||
@ -2671,15 +2681,33 @@ void nsCSSFrameConstructor::ConstructAnonymousContentForCanvas(
|
|||||||
aFrameList);
|
aFrameList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrintedSheetFrame* nsCSSFrameConstructor::ConstructPrintedSheetFrame(
|
||||||
|
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
||||||
|
nsIFrame* aPrevSheetFrame) {
|
||||||
|
ComputedStyle* parentComputedStyle = aParentFrame->Style();
|
||||||
|
ServoStyleSet* styleSet = aPresShell->StyleSet();
|
||||||
|
|
||||||
|
RefPtr<ComputedStyle> printedSheetPseudoStyle =
|
||||||
|
styleSet->ResolveInheritingAnonymousBoxStyle(
|
||||||
|
PseudoStyleType::printedSheet, parentComputedStyle);
|
||||||
|
|
||||||
|
auto* printedSheetFrame =
|
||||||
|
NS_NewPrintedSheetFrame(aPresShell, printedSheetPseudoStyle);
|
||||||
|
|
||||||
|
printedSheetFrame->Init(nullptr, aParentFrame, aPrevSheetFrame);
|
||||||
|
|
||||||
|
return printedSheetFrame;
|
||||||
|
}
|
||||||
|
|
||||||
nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
|
nsContainerFrame* nsCSSFrameConstructor::ConstructPageFrame(
|
||||||
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
||||||
nsIFrame* aPrevPageFrame, nsContainerFrame*& aCanvasFrame) {
|
nsIFrame* aPrevPageFrame, nsContainerFrame*& aCanvasFrame) {
|
||||||
ComputedStyle* parentComputedStyle = aParentFrame->Style();
|
ComputedStyle* parentComputedStyle = aParentFrame->Style();
|
||||||
ServoStyleSet* styleSet = aPresShell->StyleSet();
|
ServoStyleSet* styleSet = aPresShell->StyleSet();
|
||||||
|
|
||||||
RefPtr<ComputedStyle> pagePseudoStyle;
|
RefPtr<ComputedStyle> pagePseudoStyle =
|
||||||
pagePseudoStyle = styleSet->ResolveInheritingAnonymousBoxStyle(
|
styleSet->ResolveInheritingAnonymousBoxStyle(PseudoStyleType::page,
|
||||||
PseudoStyleType::page, parentComputedStyle);
|
parentComputedStyle);
|
||||||
|
|
||||||
nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
|
nsContainerFrame* pageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
|
||||||
|
|
||||||
@ -7931,8 +7959,10 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
|
|||||||
"no support for fragmenting table captions yet");
|
"no support for fragmenting table captions yet");
|
||||||
newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
|
newFrame = NS_NewColumnSetFrame(mPresShell, computedStyle, nsFrameState(0));
|
||||||
newFrame->Init(content, aParentFrame, aFrame);
|
newFrame->Init(content, aParentFrame, aFrame);
|
||||||
|
} else if (LayoutFrameType::PrintedSheet == frameType) {
|
||||||
|
newFrame = ConstructPrintedSheetFrame(mPresShell, aParentFrame, aFrame);
|
||||||
} else if (LayoutFrameType::Page == frameType) {
|
} else if (LayoutFrameType::Page == frameType) {
|
||||||
nsContainerFrame* canvasFrame;
|
nsContainerFrame* canvasFrame; // (unused outparam for ConstructPageFrame)
|
||||||
newFrame =
|
newFrame =
|
||||||
ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
|
ConstructPageFrame(mPresShell, aParentFrame, aFrame, canvasFrame);
|
||||||
} else if (LayoutFrameType::TableWrapper == frameType) {
|
} else if (LayoutFrameType::TableWrapper == frameType) {
|
||||||
|
@ -44,6 +44,7 @@ namespace mozilla {
|
|||||||
|
|
||||||
class ComputedStyle;
|
class ComputedStyle;
|
||||||
class PresShell;
|
class PresShell;
|
||||||
|
class PrintedSheetFrame;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
|
||||||
@ -348,6 +349,10 @@ class nsCSSFrameConstructor final : public nsFrameManager {
|
|||||||
nsContainerFrame* aRootElementFrame, nsFrameConstructorState&,
|
nsContainerFrame* aRootElementFrame, nsFrameConstructorState&,
|
||||||
nsFrameList&);
|
nsFrameList&);
|
||||||
|
|
||||||
|
mozilla::PrintedSheetFrame* ConstructPrintedSheetFrame(
|
||||||
|
PresShell* aPresShell, nsContainerFrame* aParentFrame,
|
||||||
|
nsIFrame* aPrevSheetFrame);
|
||||||
|
|
||||||
nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
|
nsContainerFrame* ConstructPageFrame(PresShell* aPresShell,
|
||||||
nsContainerFrame* aParentFrame,
|
nsContainerFrame* aParentFrame,
|
||||||
nsIFrame* aPrevPageFrame,
|
nsIFrame* aPrevPageFrame,
|
||||||
|
@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
#include "PrintedSheetFrame.h"
|
#include "PrintedSheetFrame.h"
|
||||||
|
|
||||||
|
#include "nsCSSFrameConstructor.h"
|
||||||
|
#include "nsPageFrame.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
PrintedSheetFrame* NS_NewPrintedSheetFrame(PresShell* aPresShell,
|
PrintedSheetFrame* NS_NewPrintedSheetFrame(PresShell* aPresShell,
|
||||||
@ -26,14 +29,116 @@ NS_IMPL_FRAMEARENA_HELPERS(PrintedSheetFrame)
|
|||||||
|
|
||||||
void PrintedSheetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
void PrintedSheetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists) {
|
const nsDisplayListSet& aLists) {
|
||||||
// TODO: Implement me
|
if (PresContext()->IsScreen()) {
|
||||||
|
// Draw the background/shadow/etc. of a blank sheet of paper, for
|
||||||
|
// print-preview.
|
||||||
|
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let each of our children (pages) draw itself:
|
||||||
|
for (auto* frame : mFrames) {
|
||||||
|
BuildDisplayListForChild(aBuilder, frame, aLists);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
void PrintedSheetFrame::Reflow(nsPresContext* aPresContext,
|
||||||
ReflowOutput& aReflowOutput,
|
ReflowOutput& aReflowOutput,
|
||||||
const ReflowInput& aReflowInput,
|
const ReflowInput& aReflowInput,
|
||||||
nsReflowStatus& aStatus) {
|
nsReflowStatus& aStatus) {
|
||||||
// TODO: Implement me
|
MarkInReflow();
|
||||||
|
DO_GLOBAL_REFLOW_COUNT("PrintedSheetFrame");
|
||||||
|
DISPLAY_REFLOW(aPresContext, this, aReflowInput, aReflowOutput, aStatus);
|
||||||
|
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
|
||||||
|
|
||||||
|
// If we have a prev-in-flow, take its overflowing content:
|
||||||
|
MoveOverflowToChildList();
|
||||||
|
|
||||||
|
const WritingMode wm = aReflowInput.GetWritingMode();
|
||||||
|
|
||||||
|
// Both the sheet and the pages will use this size:
|
||||||
|
const nsSize physPageSize = aPresContext->GetPageSize();
|
||||||
|
const LogicalSize pageSize(wm, physPageSize);
|
||||||
|
|
||||||
|
// Until bug 1631452, we should only have one child (which we might've just
|
||||||
|
// pulled from our prev-in-flow's overflow list). That means the loop below
|
||||||
|
// is trivial & will will run exactly once, for now.
|
||||||
|
MOZ_ASSERT(mFrames.GetLength() == 1,
|
||||||
|
"how did we get more than one page per sheet");
|
||||||
|
for (auto* pageFrame : mFrames) {
|
||||||
|
MOZ_ASSERT(pageFrame->IsPageFrame(),
|
||||||
|
"we're only expecting page frames as children");
|
||||||
|
// Be sure our child has a pointer to the nsSharedPageData:
|
||||||
|
static_cast<nsPageFrame*>(pageFrame)->SetSharedPageData(mPD);
|
||||||
|
|
||||||
|
ReflowInput pageReflowInput(aPresContext, aReflowInput, pageFrame,
|
||||||
|
pageSize);
|
||||||
|
// For now, we'll always position the pageFrame at our origin. (This will
|
||||||
|
// change in bug 1631452 when we support more than 1 page per sheet.)
|
||||||
|
LogicalPoint pagePos(wm);
|
||||||
|
|
||||||
|
// Outparams for reflow:
|
||||||
|
ReflowOutput pageReflowOutput(pageReflowInput);
|
||||||
|
nsReflowStatus status;
|
||||||
|
|
||||||
|
ReflowChild(pageFrame, aPresContext, pageReflowOutput, pageReflowInput, wm,
|
||||||
|
pagePos, physPageSize, ReflowChildFlags::Default, status);
|
||||||
|
|
||||||
|
FinishReflowChild(pageFrame, aPresContext, pageReflowOutput,
|
||||||
|
&pageReflowInput, wm, pagePos, physPageSize,
|
||||||
|
ReflowChildFlags::Default);
|
||||||
|
|
||||||
|
// Did this page complete the document, or do we need to generate
|
||||||
|
// another page frame?
|
||||||
|
nsIFrame* pageNextInFlow = pageFrame->GetNextInFlow();
|
||||||
|
if (status.IsFullyComplete()) {
|
||||||
|
// Normally, we (the parent frame) would be responsible for deleting the
|
||||||
|
// next-in-flow of our fully-complete children. But since we don't
|
||||||
|
// support dynamic changes / incremental reflow for printing (and since
|
||||||
|
// the reflow operation is single-pass at this level of granularity), our
|
||||||
|
// child *shouldn't have had any opportunities* to end up with a
|
||||||
|
// next-in-flow that would need cleaning up here.
|
||||||
|
NS_ASSERTION(!pageNextInFlow, "bad child flow list");
|
||||||
|
} else {
|
||||||
|
// Our page frame child needs a continuation. For now, that makes us need
|
||||||
|
// one as well. (This will change in bug 1631452 when we support more
|
||||||
|
// than 1 page per sheet; at that point, we'll only want to do this when
|
||||||
|
// we max out the number of pages that are allowed on our sheet.)
|
||||||
|
aStatus.SetIncomplete();
|
||||||
|
|
||||||
|
if (!pageNextInFlow) {
|
||||||
|
// We need to create a continuation for our page frame. We add the
|
||||||
|
// continuation to our child list, and then push it to our overflow
|
||||||
|
// list so that our own (perhaps yet-to-be-created) continuation can
|
||||||
|
// pull it forward.
|
||||||
|
nsIFrame* continuingPage =
|
||||||
|
PresShell()->FrameConstructor()->CreateContinuingFrame(pageFrame,
|
||||||
|
this);
|
||||||
|
mFrames.InsertFrame(nullptr, pageFrame, continuingPage);
|
||||||
|
PushChildrenToOverflow(continuingPage, pageFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate our ReflowOutput outparam -- just use up all the
|
||||||
|
// available space, for both our desired size & overflow areas.
|
||||||
|
aReflowOutput.ISize(wm) = aReflowInput.AvailableISize();
|
||||||
|
if (aReflowInput.AvailableBSize() != NS_UNCONSTRAINEDSIZE) {
|
||||||
|
aReflowOutput.BSize(wm) = aReflowInput.AvailableBSize();
|
||||||
|
}
|
||||||
|
aReflowOutput.SetOverflowAreasToDesiredBounds();
|
||||||
|
|
||||||
|
FinishAndStoreOverflow(&aReflowOutput);
|
||||||
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aReflowOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintedSheetFrame::AppendDirectlyOwnedAnonBoxes(
|
||||||
|
nsTArray<OwnedAnonBox>& aResult) {
|
||||||
|
MOZ_ASSERT(mFrames.FirstChild() && mFrames.FirstChild()->IsPageFrame(),
|
||||||
|
"PrintedSheetFrame must have a nsPageFrame child");
|
||||||
|
// Only append the first child; all our children are expected to be
|
||||||
|
// continuations of each other, and our anon box handling always walks
|
||||||
|
// continuations.
|
||||||
|
aResult.AppendElement(mFrames.FirstChild());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "nsHTMLParts.h"
|
#include "nsHTMLParts.h"
|
||||||
|
|
||||||
|
class nsSharedPageData;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class PrintedSheetFrame final : public nsContainerFrame {
|
class PrintedSheetFrame final : public nsContainerFrame {
|
||||||
@ -22,6 +24,8 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
|||||||
friend PrintedSheetFrame* ::NS_NewPrintedSheetFrame(
|
friend PrintedSheetFrame* ::NS_NewPrintedSheetFrame(
|
||||||
mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
|
mozilla::PresShell* aPresShell, ComputedStyle* aStyle);
|
||||||
|
|
||||||
|
void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
||||||
|
|
||||||
// nsIFrame overrides
|
// nsIFrame overrides
|
||||||
void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
|
void Reflow(nsPresContext* aPresContext, ReflowOutput& aReflowOutput,
|
||||||
const ReflowInput& aReflowInput,
|
const ReflowInput& aReflowInput,
|
||||||
@ -30,6 +34,9 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
|||||||
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists) override;
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
|
// Return our first page frame.
|
||||||
|
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
|
||||||
|
|
||||||
#ifdef DEBUG_FRAME_DUMP
|
#ifdef DEBUG_FRAME_DUMP
|
||||||
nsresult GetFrameName(nsAString& aResult) const override;
|
nsresult GetFrameName(nsAString& aResult) const override;
|
||||||
#endif
|
#endif
|
||||||
@ -40,6 +47,10 @@ class PrintedSheetFrame final : public nsContainerFrame {
|
|||||||
PrintedSheetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
PrintedSheetFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
|
||||||
: nsContainerFrame(aStyle, aPresContext, kClassID) {}
|
: nsContainerFrame(aStyle, aPresContext, kClassID) {}
|
||||||
~PrintedSheetFrame() = default;
|
~PrintedSheetFrame() = default;
|
||||||
|
|
||||||
|
// Note: this will be set before reflow, and it's strongly owned by our
|
||||||
|
// nsPageSequenceFrame, which outlives us.
|
||||||
|
nsSharedPageData* mPD = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -526,9 +526,6 @@ void nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
nsDisplayListCollection set(aBuilder);
|
nsDisplayListCollection set(aBuilder);
|
||||||
|
|
||||||
nsPresContext* pc = PresContext();
|
nsPresContext* pc = PresContext();
|
||||||
if (pc->IsScreen()) {
|
|
||||||
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIFrame* child = mFrames.FirstChild();
|
nsIFrame* child = mFrames.FirstChild();
|
||||||
float scale = pc->GetPageScale();
|
float scale = pc->GetPageScale();
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "mozilla/Logging.h"
|
#include "mozilla/Logging.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/PrintedSheetFrame.h"
|
||||||
#include "mozilla/dom/HTMLCanvasElement.h"
|
#include "mozilla/dom/HTMLCanvasElement.h"
|
||||||
#include "mozilla/StaticPresData.h"
|
#include "mozilla/StaticPresData.h"
|
||||||
|
|
||||||
@ -238,19 +239,21 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
mPageData->mReflowSize = pageSize;
|
mPageData->mReflowSize = pageSize;
|
||||||
mPageData->mReflowMargin = mMargin;
|
mPageData->mReflowMargin = mMargin;
|
||||||
|
|
||||||
// We use the CSS "margin" property on the -moz-page pseudoelement
|
// We use the CSS "margin" property on the -moz-printed-sheet pseudoelement
|
||||||
// to determine the space between each page in print preview.
|
// to determine the space between each printed sheet in print preview.
|
||||||
// Keep a running y-offset for each page.
|
// Keep a running y-offset for each printed sheet.
|
||||||
nscoord y = 0;
|
nscoord y = 0;
|
||||||
nscoord maxXMost = 0;
|
nscoord maxXMost = 0;
|
||||||
|
|
||||||
// Tile the pages vertically
|
// Tile the sheets vertically
|
||||||
for (nsIFrame* kidFrame : mFrames) {
|
for (nsIFrame* kidFrame : mFrames) {
|
||||||
// Set the shared data into the page frame before reflow
|
// Set the shared data into the page frame before reflow
|
||||||
auto* pf = static_cast<nsPageFrame*>(kidFrame);
|
MOZ_ASSERT(kidFrame->IsPrintedSheetFrame(),
|
||||||
pf->SetSharedPageData(mPageData.get());
|
"we're only expecting PrintedSheetFrame as children");
|
||||||
|
auto* sheet = static_cast<PrintedSheetFrame*>(kidFrame);
|
||||||
|
sheet->SetSharedPageData(mPageData.get());
|
||||||
|
|
||||||
// Reflow the page
|
// Reflow the sheet
|
||||||
ReflowInput kidReflowInput(
|
ReflowInput kidReflowInput(
|
||||||
aPresContext, aReflowInput, kidFrame,
|
aPresContext, aReflowInput, kidFrame,
|
||||||
LogicalSize(kidFrame->GetWritingMode(), pageSize));
|
LogicalSize(kidFrame->GetWritingMode(), pageSize));
|
||||||
@ -267,7 +270,7 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
nscoord x = pageCSSMargin.left;
|
nscoord x = pageCSSMargin.left;
|
||||||
|
|
||||||
// Place and size the page.
|
// Place and size the sheet.
|
||||||
ReflowChild(kidFrame, aPresContext, kidReflowOutput, kidReflowInput, x, y,
|
ReflowChild(kidFrame, aPresContext, kidReflowOutput, kidReflowInput, x, y,
|
||||||
ReflowChildFlags::Default, status);
|
ReflowChildFlags::Default, status);
|
||||||
|
|
||||||
@ -279,37 +282,46 @@ void nsPageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
maxXMost =
|
maxXMost =
|
||||||
std::max(maxXMost, x + kidReflowOutput.Width() + pageCSSMargin.right);
|
std::max(maxXMost, x + kidReflowOutput.Width() + pageCSSMargin.right);
|
||||||
|
|
||||||
// Is the page complete?
|
// Is the sheet complete?
|
||||||
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
|
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
|
||||||
|
|
||||||
if (status.IsFullyComplete()) {
|
if (status.IsFullyComplete()) {
|
||||||
NS_ASSERTION(!kidNextInFlow, "bad child flow list");
|
NS_ASSERTION(!kidNextInFlow, "bad child flow list");
|
||||||
} else if (!kidNextInFlow) {
|
} else if (!kidNextInFlow) {
|
||||||
// The page isn't complete and it doesn't have a next-in-flow, so
|
// The sheet isn't complete and it doesn't have a next-in-flow, so
|
||||||
// create a continuing page.
|
// create a continuing sheet.
|
||||||
nsIFrame* continuingPage =
|
nsIFrame* continuingSheet =
|
||||||
PresShell()->FrameConstructor()->CreateContinuingFrame(kidFrame,
|
PresShell()->FrameConstructor()->CreateContinuingFrame(kidFrame,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
// Add it to our child list
|
// Add it to our child list
|
||||||
mFrames.InsertFrame(nullptr, kidFrame, continuingPage);
|
mFrames.InsertFrame(nullptr, kidFrame, continuingSheet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Total Page Count
|
// Get Total Page Count
|
||||||
|
// XXXdholbert When we support multiple pages-per-sheet in bug 1631452,
|
||||||
|
// we'll need to be sure to update this computation to account for the
|
||||||
|
// sheet-vs-page distinction.
|
||||||
// XXXdholbert technically we could calculate this in the loop above,
|
// XXXdholbert technically we could calculate this in the loop above,
|
||||||
// instead of needing a separate walk.
|
// instead of needing a separate walk.
|
||||||
int32_t pageTot = mFrames.GetLength();
|
int32_t pageTot = mFrames.GetLength();
|
||||||
|
|
||||||
// Set Page Number Info
|
// Set Page Number Info
|
||||||
int32_t pageNum = 1;
|
int32_t pageNum = 1;
|
||||||
for (nsIFrame* child : mFrames) {
|
for (nsIFrame* sheetFrame : mFrames) {
|
||||||
MOZ_ASSERT(child->IsPageFrame(),
|
MOZ_ASSERT(sheetFrame->IsPrintedSheetFrame(),
|
||||||
"only expecting nsPageFrame children. Other children will make "
|
"only expecting PrintedSheetFrame children");
|
||||||
"this static_cast bogus & probably violate other assumptions");
|
for (nsIFrame* pageFrame : sheetFrame->PrincipalChildList()) {
|
||||||
auto* pf = static_cast<nsPageFrame*>(child);
|
MOZ_ASSERT(
|
||||||
pf->SetPageNumInfo(pageNum, pageTot);
|
pageFrame->IsPageFrame(),
|
||||||
pageNum++;
|
"only expecting nsPageFrame grandchildren. Other types will make "
|
||||||
|
"this static_cast bogus & probably violate other assumptions");
|
||||||
|
static_cast<nsPageFrame*>(pageFrame)->SetPageNumInfo(pageNum, pageTot);
|
||||||
|
// XXXdholbert Perhaps we'll need to keep track of the page count *and*
|
||||||
|
// the printed sheet count?
|
||||||
|
pageNum++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString formattedDateString;
|
nsAutoString formattedDateString;
|
||||||
@ -446,6 +458,25 @@ static void GetPrintCanvasElementsInFrame(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXXdholbert The next four functions[1] exist to support functionality to let
|
||||||
|
// us include/skip various pages (e.g. only print even pages, or page 7, or the
|
||||||
|
// page-range "1,4,6-8"). These four functions are all named in terms of
|
||||||
|
// "page", which is somewhat problematic now that we've got a level of
|
||||||
|
// indirection between us and the actual page frames; but in practice, they're
|
||||||
|
// still valid & fine as long as there's exactly one nsPageFrame per
|
||||||
|
// PrintedSheetFrame (as there is right now).
|
||||||
|
//
|
||||||
|
// When we implement built-in support for N Pages Per Sheet (bug 1631452),
|
||||||
|
// we'll need this logic to cooperate with PrintedSheetFrame, so that a given
|
||||||
|
// PrintedSheetFrame instance can figure out which of the upcoming pages it
|
||||||
|
// should include/skip in its N tiny pages. We may need to change our calling
|
||||||
|
// pattern all the way up to nsPagePrintTimer, too (which currently has a
|
||||||
|
// repeating timer that fires to prompt us to print each successive page, with
|
||||||
|
// a variable delay between firings, depending on whether the last page was
|
||||||
|
// skipped.
|
||||||
|
//
|
||||||
|
// [1] DetermineWhetherToPrintPage(), GetCurrentPageFrame(),
|
||||||
|
// PrePrintNextPage(), and PrintNextPage()
|
||||||
void nsPageSequenceFrame::DetermineWhetherToPrintPage() {
|
void nsPageSequenceFrame::DetermineWhetherToPrintPage() {
|
||||||
// See whether we should print this page
|
// See whether we should print this page
|
||||||
mPrintThisPage = true;
|
mPrintThisPage = true;
|
||||||
@ -737,7 +768,11 @@ void nsPageSequenceFrame::SetDateTimeStr(const nsAString& aDateTimeStr) {
|
|||||||
|
|
||||||
void nsPageSequenceFrame::AppendDirectlyOwnedAnonBoxes(
|
void nsPageSequenceFrame::AppendDirectlyOwnedAnonBoxes(
|
||||||
nsTArray<OwnedAnonBox>& aResult) {
|
nsTArray<OwnedAnonBox>& aResult) {
|
||||||
if (mFrames.NotEmpty()) {
|
MOZ_ASSERT(
|
||||||
aResult.AppendElement(mFrames.FirstChild());
|
mFrames.FirstChild() && mFrames.FirstChild()->IsPrintedSheetFrame(),
|
||||||
}
|
"nsPageSequenceFrame must have a PrintedSheetFrame child");
|
||||||
|
// Only append the first child; all our children are expected to be
|
||||||
|
// continuations of each other, and our anon box handling always walks
|
||||||
|
// continuations.
|
||||||
|
aResult.AppendElement(mFrames.FirstChild());
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,9 @@ class nsSharedPageData {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Page sequence frame class. Manages a series of pages, in paginated mode.
|
// Page sequence frame class. Manages a series of pages, in paginated mode.
|
||||||
|
// (Strictly speaking, this frame's direct children are PrintedSheetFrame
|
||||||
|
// instances, and each of those will usually contain one nsPageFrame, depending
|
||||||
|
// on the "pages-per-sheet" setting.)
|
||||||
class nsPageSequenceFrame final : public nsContainerFrame {
|
class nsPageSequenceFrame final : public nsContainerFrame {
|
||||||
public:
|
public:
|
||||||
friend nsPageSequenceFrame* NS_NewPageSequenceFrame(
|
friend nsPageSequenceFrame* NS_NewPageSequenceFrame(
|
||||||
@ -98,7 +101,7 @@ class nsPageSequenceFrame final : public nsContainerFrame {
|
|||||||
bool HasTransformGetter() const override { return true; }
|
bool HasTransformGetter() const override { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return our first page frame.
|
* Return our first sheet frame.
|
||||||
*/
|
*/
|
||||||
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
|
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ CSS_ANON_BOX(canvas, ":-moz-canvas")
|
|||||||
CSS_ANON_BOX(page, ":-moz-page")
|
CSS_ANON_BOX(page, ":-moz-page")
|
||||||
CSS_ANON_BOX(pageContent, ":-moz-pagecontent")
|
CSS_ANON_BOX(pageContent, ":-moz-pagecontent")
|
||||||
CSS_ANON_BOX(pageSequence, ":-moz-page-sequence")
|
CSS_ANON_BOX(pageSequence, ":-moz-page-sequence")
|
||||||
|
CSS_ANON_BOX(printedSheet, ":-moz-printed-sheet")
|
||||||
CSS_ANON_BOX(scrolledContent, ":-moz-scrolled-content")
|
CSS_ANON_BOX(scrolledContent, ":-moz-scrolled-content")
|
||||||
CSS_ANON_BOX(scrolledCanvas, ":-moz-scrolled-canvas")
|
CSS_ANON_BOX(scrolledCanvas, ":-moz-scrolled-canvas")
|
||||||
CSS_ANON_BOX(scrolledPageSequence, ":-moz-scrolled-page-sequence")
|
CSS_ANON_BOX(scrolledPageSequence, ":-moz-scrolled-page-sequence")
|
||||||
|
@ -301,9 +301,9 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
*|*::-moz-page {
|
*|*::-moz-printed-sheet {
|
||||||
/* Individual page in print/print preview. Visual styles may only appear
|
/* Individual sheet of paper in print/print preview. Visual styles may only
|
||||||
* in print preview. */
|
* appear in print preview. */
|
||||||
display: block;
|
display: block;
|
||||||
background: white;
|
background: white;
|
||||||
box-shadow: 5px 5px 8px #202020;
|
box-shadow: 5px 5px 8px #202020;
|
||||||
|
@ -2515,6 +2515,7 @@ STATIC_ATOMS = [
|
|||||||
InheritingAnonBoxAtom("AnonBox_page", ":-moz-page"),
|
InheritingAnonBoxAtom("AnonBox_page", ":-moz-page"),
|
||||||
InheritingAnonBoxAtom("AnonBox_pageContent", ":-moz-pagecontent"),
|
InheritingAnonBoxAtom("AnonBox_pageContent", ":-moz-pagecontent"),
|
||||||
InheritingAnonBoxAtom("AnonBox_pageSequence", ":-moz-page-sequence"),
|
InheritingAnonBoxAtom("AnonBox_pageSequence", ":-moz-page-sequence"),
|
||||||
|
InheritingAnonBoxAtom("AnonBox_printedSheet", ":-moz-printed-sheet"),
|
||||||
InheritingAnonBoxAtom("AnonBox_scrolledContent", ":-moz-scrolled-content"),
|
InheritingAnonBoxAtom("AnonBox_scrolledContent", ":-moz-scrolled-content"),
|
||||||
InheritingAnonBoxAtom("AnonBox_scrolledCanvas", ":-moz-scrolled-canvas"),
|
InheritingAnonBoxAtom("AnonBox_scrolledCanvas", ":-moz-scrolled-canvas"),
|
||||||
InheritingAnonBoxAtom("AnonBox_scrolledPageSequence", ":-moz-scrolled-page-sequence"),
|
InheritingAnonBoxAtom("AnonBox_scrolledPageSequence", ":-moz-scrolled-page-sequence"),
|
||||||
|
Loading…
Reference in New Issue
Block a user