From 05e63b3bcb1f7ac7f9c62388d1e7bd9eb243e519 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 10 Jul 2023 14:26:12 +0000 Subject: [PATCH] Bug 1833244 p1. Create infrastructure to pass page dimensions to PrintTarget::BeginPage. r=dholbert,geckoview-reviewers,jonalmeida OS print drivers/devices know nothing about page dimensions unless we tell them. Previously, the physical page dimensions (including orientation) have always been the same, so communicating their dimensions once at the start of a print has been enough. In preparation for supporting different "physical" page dimensions (in the immediate future only different page orientations) when we save to PDF, we need to have the infrastructure to pass dimensions through on a page-by-page basis. This patch adds that. None of the PrintTarget subclasses do anything with this extra information yet, but in a follow-up patch PrintTargetPDF will use this information to create PDFs with mixed page orientations. Differential Revision: https://phabricator.services.mozilla.com/D179423 --- gfx/src/nsDeviceContext.cpp | 6 +++--- gfx/src/nsDeviceContext.h | 14 ++++++++++++-- gfx/thebes/PrintTarget.h | 6 +++++- gfx/thebes/PrintTargetCG.h | 2 +- gfx/thebes/PrintTargetCG.mm | 4 ++-- gfx/thebes/PrintTargetSkPDF.cpp | 5 +++-- gfx/thebes/PrintTargetSkPDF.h | 2 +- gfx/thebes/PrintTargetThebes.cpp | 2 +- gfx/thebes/PrintTargetThebes.h | 2 +- gfx/thebes/PrintTargetWindows.cpp | 4 ++-- gfx/thebes/PrintTargetWindows.h | 2 +- layout/generic/PrintedSheetFrame.cpp | 10 ++++++++++ layout/generic/PrintedSheetFrame.h | 18 ++++++++++++++++++ layout/generic/nsPageSequenceFrame.cpp | 11 +++++++++-- layout/printing/ipc/PRemotePrintJob.ipdl | 2 +- layout/printing/ipc/RemotePrintJobChild.cpp | 6 ++++-- layout/printing/ipc/RemotePrintJobChild.h | 5 ++++- layout/printing/ipc/RemotePrintJobParent.cpp | 20 ++++++++++++-------- layout/printing/ipc/RemotePrintJobParent.h | 8 ++++++-- widget/android/nsDeviceContextAndroid.h | 5 ++++- widget/cocoa/nsDeviceContextSpecX.h | 2 +- widget/gtk/nsDeviceContextSpecG.h | 2 +- widget/nsDeviceContextSpecProxy.cpp | 6 ++++-- widget/nsDeviceContextSpecProxy.h | 4 +++- widget/nsIDeviceContextSpec.h | 9 ++++++++- widget/windows/nsDeviceContextSpecWin.h | 2 +- 26 files changed, 118 insertions(+), 41 deletions(-) diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index f9fba5841839..1c27cf45bc6f 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -327,14 +327,14 @@ nsresult nsDeviceContext::AbortDocument() { return rv; } -nsresult nsDeviceContext::BeginPage() { +nsresult nsDeviceContext::BeginPage(const IntSize& aSizeInPoints) { MOZ_DIAGNOSTIC_ASSERT(!mIsCurrentlyPrintingDoc || mPrintTarget, "What nulled out our print target while printing?"); if (mDeviceContextSpec) { - MOZ_TRY(mDeviceContextSpec->BeginPage()); + MOZ_TRY(mDeviceContextSpec->BeginPage(aSizeInPoints)); } if (mPrintTarget) { - MOZ_TRY(mPrintTarget->BeginPage()); + MOZ_TRY(mPrintTarget->BeginPage(aSizeInPoints)); } return NS_OK; } diff --git a/gfx/src/nsDeviceContext.h b/gfx/src/nsDeviceContext.h index 8ebb240650b7..5238c1f71da8 100644 --- a/gfx/src/nsDeviceContext.h +++ b/gfx/src/nsDeviceContext.h @@ -20,6 +20,7 @@ #include "nscore.h" // for char16_t, nsAString #include "mozilla/AppUnits.h" // for AppUnits #include "nsFontMetrics.h" // for nsFontMetrics::Params +#include "mozilla/gfx/Point.h" // for IntSize #include "mozilla/gfx/PrintTarget.h" // for PrintTarget::PageDoneCallback #include "mozilla/gfx/PrintPromise.h" @@ -48,7 +49,8 @@ class Screen; class nsDeviceContext final { public: - typedef mozilla::gfx::PrintTarget PrintTarget; + using IntSize = mozilla::gfx::IntSize; + using PrintTarget = mozilla::gfx::PrintTarget; nsDeviceContext(); @@ -223,9 +225,17 @@ class nsDeviceContext final { * Inform the output device that output of a page is beginning * Used for print related device contexts. Must be matched 1:1 with * EndPage() and within a BeginDocument()/EndDocument() pair. + * + * @param aSizeInPoints - The physical dimensions of the page in points. + * Currently only supported (used) by print-to-PDF + * print targets, and then only to switch the + * orientation for a specific page (arbitrary page + * sizes are not supported by the Core Graphics print- + * to-PDF APIs, for example). + * * @return error status */ - nsresult BeginPage(); + nsresult BeginPage(const IntSize& aSizeInPoints); /** * Inform the output device that output of a page is ending diff --git a/gfx/thebes/PrintTarget.h b/gfx/thebes/PrintTarget.h index 9f1d018c6c73..f8da3f3c1127 100644 --- a/gfx/thebes/PrintTarget.h +++ b/gfx/thebes/PrintTarget.h @@ -43,7 +43,11 @@ class PrintTarget { #endif return NS_OK; } - virtual nsresult BeginPage() { + /** + * Note: not all print devices implement mixed page sizing. Most PrintTarget + * subclasses will ignore `aSizeInPoints`. + */ + virtual nsresult BeginPage(const IntSize& aSizeInPoints) { #ifdef DEBUG MOZ_ASSERT(!mHasActivePage, "Missing EndPage() call"); mHasActivePage = true; diff --git a/gfx/thebes/PrintTargetCG.h b/gfx/thebes/PrintTargetCG.h index 01e75bd36ed7..ee3c1ab3ac36 100644 --- a/gfx/thebes/PrintTargetCG.h +++ b/gfx/thebes/PrintTargetCG.h @@ -28,7 +28,7 @@ class PrintTargetCG final : public PrintTarget { int32_t aEndPage) final; nsresult EndPrinting() final; nsresult AbortPrinting() final; - nsresult BeginPage() final; + nsresult BeginPage(const IntSize& aSizeInPoints) final; nsresult EndPage() final; already_AddRefed GetReferenceDrawTarget() final; diff --git a/gfx/thebes/PrintTargetCG.mm b/gfx/thebes/PrintTargetCG.mm index a5c7caea557e..e09f223d23e7 100644 --- a/gfx/thebes/PrintTargetCG.mm +++ b/gfx/thebes/PrintTargetCG.mm @@ -210,7 +210,7 @@ nsresult PrintTargetCG::AbortPrinting() { return EndPrinting(); } -nsresult PrintTargetCG::BeginPage() { +nsresult PrintTargetCG::BeginPage(const IntSize& aSizeInPoints) { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; CGContextRef context; @@ -249,7 +249,7 @@ nsresult PrintTargetCG::BeginPage() { mCairoSurface = surface; - return PrintTarget::BeginPage(); + return PrintTarget::BeginPage(aSizeInPoints); NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE); } diff --git a/gfx/thebes/PrintTargetSkPDF.cpp b/gfx/thebes/PrintTargetSkPDF.cpp index 6cf7d3729e1f..2834877407b6 100644 --- a/gfx/thebes/PrintTargetSkPDF.cpp +++ b/gfx/thebes/PrintTargetSkPDF.cpp @@ -54,10 +54,11 @@ nsresult PrintTargetSkPDF::BeginPrinting(const nsAString& aTitle, return mPDFDoc ? NS_OK : NS_ERROR_FAILURE; } -nsresult PrintTargetSkPDF::BeginPage() { +nsresult PrintTargetSkPDF::BeginPage(const IntSize& aSizeInPoints) { mPageCanvas = mPDFDoc->beginPage(mSize.width, mSize.height); - return !mPageCanvas ? NS_ERROR_FAILURE : PrintTarget::BeginPage(); + return !mPageCanvas ? NS_ERROR_FAILURE + : PrintTarget::BeginPage(aSizeInPoints); } nsresult PrintTargetSkPDF::EndPage() { diff --git a/gfx/thebes/PrintTargetSkPDF.h b/gfx/thebes/PrintTargetSkPDF.h index 9cbe9e4ab31d..af1db0cce71a 100644 --- a/gfx/thebes/PrintTargetSkPDF.h +++ b/gfx/thebes/PrintTargetSkPDF.h @@ -33,7 +33,7 @@ class PrintTargetSkPDF final : public PrintTarget { nsresult EndPrinting() override; void Finish() override; - nsresult BeginPage() override; + nsresult BeginPage(const IntSize& aSizeInPoints) override; nsresult EndPage() override; already_AddRefed MakeDrawTarget( diff --git a/gfx/thebes/PrintTargetThebes.cpp b/gfx/thebes/PrintTargetThebes.cpp index e121b0a7e21d..466ad7b11912 100644 --- a/gfx/thebes/PrintTargetThebes.cpp +++ b/gfx/thebes/PrintTargetThebes.cpp @@ -79,7 +79,7 @@ nsresult PrintTargetThebes::AbortPrinting() { return mGfxSurface->AbortPrinting(); } -nsresult PrintTargetThebes::BeginPage() { +nsresult PrintTargetThebes::BeginPage(const IntSize& aSizeInPoints) { #ifdef DEBUG mHasActivePage = true; #endif diff --git a/gfx/thebes/PrintTargetThebes.h b/gfx/thebes/PrintTargetThebes.h index 1a3b72365dfe..65dfcbf7edb8 100644 --- a/gfx/thebes/PrintTargetThebes.h +++ b/gfx/thebes/PrintTargetThebes.h @@ -33,7 +33,7 @@ class PrintTargetThebes final : public PrintTarget { int32_t aEndPage) override; nsresult EndPrinting() override; nsresult AbortPrinting() override; - nsresult BeginPage() override; + nsresult BeginPage(const IntSize& aSizeInPoints) override; nsresult EndPage() override; void Finish() override; diff --git a/gfx/thebes/PrintTargetWindows.cpp b/gfx/thebes/PrintTargetWindows.cpp index e97a1187e5aa..498309d3aea8 100644 --- a/gfx/thebes/PrintTargetWindows.cpp +++ b/gfx/thebes/PrintTargetWindows.cpp @@ -103,8 +103,8 @@ nsresult PrintTargetWindows::AbortPrinting() { return (result <= 0) ? NS_ERROR_FAILURE : NS_OK; } -nsresult PrintTargetWindows::BeginPage() { - PrintTarget::BeginPage(); +nsresult PrintTargetWindows::BeginPage(const IntSize& aSizeInPoints) { + PrintTarget::BeginPage(aSizeInPoints); int result = ::StartPage(mDC); return (result <= 0) ? NS_ERROR_FAILURE : NS_OK; } diff --git a/gfx/thebes/PrintTargetWindows.h b/gfx/thebes/PrintTargetWindows.h index 4080835e685e..f305fb9bf562 100644 --- a/gfx/thebes/PrintTargetWindows.h +++ b/gfx/thebes/PrintTargetWindows.h @@ -26,7 +26,7 @@ class PrintTargetWindows final : public PrintTarget { int32_t aEndPage) override; nsresult EndPrinting() override; nsresult AbortPrinting() override; - nsresult BeginPage() override; + nsresult BeginPage(const IntSize& aSizeInPoints) override; nsresult EndPage() override; private: diff --git a/layout/generic/PrintedSheetFrame.cpp b/layout/generic/PrintedSheetFrame.cpp index 062ce411f8b4..b66a992ec83e 100644 --- a/layout/generic/PrintedSheetFrame.cpp +++ b/layout/generic/PrintedSheetFrame.cpp @@ -298,6 +298,16 @@ void PrintedSheetFrame::ComputePagesPerSheetGridMetrics( mGridCellHeight = availSpaceOnSheet.height / nscoord(numRows); } +gfx::IntSize PrintedSheetFrame::GetPrintTargetSizeInPoints( + const int32_t aAppUnitsPerPhysicalInch) const { + const auto size = GetSize(); + MOZ_ASSERT(size.width > 0 && size.height > 0); + const float pointsPerAppUnit = + POINTS_PER_INCH_FLOAT / float(aAppUnitsPerPhysicalInch); + return IntSize::Ceil(float(size.width) * pointsPerAppUnit, + float(size.height) * pointsPerAppUnit); +} + #ifdef DEBUG_FRAME_DUMP nsresult PrintedSheetFrame::GetFrameName(nsAString& aResult) const { return MakeFrameName(u"PrintedSheet"_ns, aResult); diff --git a/layout/generic/PrintedSheetFrame.h b/layout/generic/PrintedSheetFrame.h index 183e16fc4e78..4406f030b64c 100644 --- a/layout/generic/PrintedSheetFrame.h +++ b/layout/generic/PrintedSheetFrame.h @@ -9,6 +9,7 @@ #ifndef LAYOUT_GENERIC_PRINTEDSHEETFRAME_H_ #define LAYOUT_GENERIC_PRINTEDSHEETFRAME_H_ +#include "mozilla/gfx/Point.h" #include "nsContainerFrame.h" #include "nsHTMLParts.h" @@ -18,6 +19,8 @@ namespace mozilla { class PrintedSheetFrame final : public nsContainerFrame { public: + using IntSize = mozilla::gfx::IntSize; + NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS(PrintedSheetFrame) @@ -71,6 +74,21 @@ class PrintedSheetFrame final : public nsContainerFrame { nsSize PrecomputeSheetSize(const nsPresContext* aPresContext); nsSize GetPrecomputedSheetSize() const { return mPrecomputedSize; } + /** + * This method returns the dimensions of the physical page that the target + * [pseudo-]printer should create. This may be different from our own + * dimensions in the case where CSS `page-orientation` causes us to be + * rotated, but we only support that if the PrintTarget backend supports + * different page sizes/orientations. That's only the case for our Save-to-PDF + * backends (possibly other save-to-file outputs in future). + * + * The dimensions returned are expected to be passed to + * nsDeviceContext::BeginPage, which will pass them on to + * PrintTarget::BeginPage to use as the physical dimensions of the page. + */ + IntSize GetPrintTargetSizeInPoints( + const int32_t aAppUnitsPerPhysicalInch) const; + private: // Private construtor & destructor, to avoid accidental (non-FrameArena) // instantiation/deletion: diff --git a/layout/generic/nsPageSequenceFrame.cpp b/layout/generic/nsPageSequenceFrame.cpp index 1e84e13973b9..46f4670691b3 100644 --- a/layout/generic/nsPageSequenceFrame.cpp +++ b/layout/generic/nsPageSequenceFrame.cpp @@ -11,6 +11,7 @@ #include "mozilla/PresShell.h" #include "mozilla/PrintedSheetFrame.h" #include "mozilla/dom/HTMLCanvasElement.h" +#include "mozilla/gfx/Point.h" #include "mozilla/StaticPresData.h" #include "nsCOMPtr.h" @@ -584,7 +585,10 @@ nsresult nsPageSequenceFrame::PrePrintNextSheet(nsITimerCallback* aCallback, nsDeviceContext* dc = PresContext()->DeviceContext(); PR_PL(("\n")); PR_PL(("***************** BeginPage *****************\n")); - rv = dc->BeginPage(); + const gfx::IntSize sizeInPoints = + currentSheet->GetPrintTargetSizeInPoints( + dc->AppUnitsPerPhysicalInch()); + rv = dc->BeginPage(sizeInPoints); NS_ENSURE_SUCCESS(rv, rv); mCalledBeginPage = true; @@ -675,7 +679,10 @@ nsresult nsPageSequenceFrame::PrintNextSheet() { // page otherwise. PR_PL(("\n")); PR_PL(("***************** BeginPage *****************\n")); - rv = dc->BeginPage(); + const gfx::IntSize sizeInPoints = + currentSheetFrame->GetPrintTargetSizeInPoints( + dc->AppUnitsPerPhysicalInch()); + rv = dc->BeginPage(sizeInPoints); NS_ENSURE_SUCCESS(rv, rv); } } diff --git a/layout/printing/ipc/PRemotePrintJob.ipdl b/layout/printing/ipc/PRemotePrintJob.ipdl index 00f4d5ff7c9a..50b978cfc778 100644 --- a/layout/printing/ipc/PRemotePrintJob.ipdl +++ b/layout/printing/ipc/PRemotePrintJob.ipdl @@ -25,7 +25,7 @@ parent: // Translate the page recording writen into |fd| and play back the events to // the real print device. - async ProcessPage(uint64_t[] deps); + async ProcessPage(int32_t aWidthInPoints, int32_t aHeightInPoints, uint64_t[] aDeps); // This informs the real print device that we've finished, so it can trigger // the actual print. diff --git a/layout/printing/ipc/RemotePrintJobChild.cpp b/layout/printing/ipc/RemotePrintJobChild.cpp index 5db0b342a36a..bc9227245153 100644 --- a/layout/printing/ipc/RemotePrintJobChild.cpp +++ b/layout/printing/ipc/RemotePrintJobChild.cpp @@ -56,12 +56,14 @@ void RemotePrintJobChild::SetNextPageFD( mNextPageFD = PR_ImportFile(PROsfd(handle.release())); } -void RemotePrintJobChild::ProcessPage(nsTArray&& aDeps) { +void RemotePrintJobChild::ProcessPage(const IntSize& aSizeInPoints, + nsTArray&& aDeps) { MOZ_ASSERT(mPagePrintTimer); mPagePrintTimer->WaitForRemotePrint(); if (!mDestroyed) { - Unused << SendProcessPage(std::move(aDeps)); + Unused << SendProcessPage(aSizeInPoints.width, aSizeInPoints.height, + std::move(aDeps)); } } diff --git a/layout/printing/ipc/RemotePrintJobChild.h b/layout/printing/ipc/RemotePrintJobChild.h index 5ca635d71350..73f2b5ef9c8d 100644 --- a/layout/printing/ipc/RemotePrintJobChild.h +++ b/layout/printing/ipc/RemotePrintJobChild.h @@ -10,6 +10,7 @@ #include "mozilla/layout/PRemotePrintJobChild.h" #include "mozilla/RefPtr.h" +#include "mozilla/gfx/Point.h" #include "nsIWebProgressListener.h" class nsPagePrintTimer; @@ -21,6 +22,8 @@ namespace layout { class RemotePrintJobChild final : public PRemotePrintJobChild, public nsIWebProgressListener { public: + using IntSize = mozilla::gfx::IntSize; + NS_DECL_ISUPPORTS NS_DECL_NSIWEBPROGRESSLISTENER @@ -34,7 +37,7 @@ class RemotePrintJobChild final : public PRemotePrintJobChild, mozilla::ipc::IPCResult RecvPrintInitializationResult( const nsresult& aRv, const FileDescriptor& aFd) final; - void ProcessPage(nsTArray&& aDeps); + void ProcessPage(const IntSize& aSizeInPoints, nsTArray&& aDeps); mozilla::ipc::IPCResult RecvPageProcessed(const FileDescriptor& aFd) final; diff --git a/layout/printing/ipc/RemotePrintJobParent.cpp b/layout/printing/ipc/RemotePrintJobParent.cpp index 8b3d5d5bd949..bf9459b8e062 100644 --- a/layout/printing/ipc/RemotePrintJobParent.cpp +++ b/layout/printing/ipc/RemotePrintJobParent.cpp @@ -106,6 +106,7 @@ nsresult RemotePrintJobParent::PrepareNextPageFD(FileDescriptor* aFd) { } mozilla::ipc::IPCResult RemotePrintJobParent::RecvProcessPage( + const int32_t& aWidthInPoints, const int32_t& aHeightInPoints, nsTArray&& aDeps) { if (!mCurrentPageStream.IsOpen()) { Unused << SendAbortPrint(NS_ERROR_FAILURE); @@ -113,8 +114,10 @@ mozilla::ipc::IPCResult RemotePrintJobParent::RecvProcessPage( } mCurrentPageStream.Seek(0, PR_SEEK_SET); + gfx::IntSize pageSizeInPoints(aWidthInPoints, aHeightInPoints); + if (aDeps.IsEmpty()) { - FinishProcessingPage(); + FinishProcessingPage(pageSizeInPoints); return IPC_OK(); } @@ -126,20 +129,21 @@ mozilla::ipc::IPCResult RemotePrintJobParent::RecvProcessPage( gfx::CrossProcessPaint::Start(std::move(deps)) ->Then( GetCurrentSerialEventTarget(), __func__, - [self = RefPtr{this}]( + [self = RefPtr{this}, pageSizeInPoints]( gfx::CrossProcessPaint::ResolvedFragmentMap&& aFragments) { - self->FinishProcessingPage(&aFragments); + self->FinishProcessingPage(pageSizeInPoints, &aFragments); }, - [self = RefPtr{this}](const nsresult& aRv) { - self->FinishProcessingPage(); + [self = RefPtr{this}, pageSizeInPoints](const nsresult& aRv) { + self->FinishProcessingPage(pageSizeInPoints); }); return IPC_OK(); } void RemotePrintJobParent::FinishProcessingPage( + const gfx::IntSize& aSizeInPoints, gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments) { - nsresult rv = PrintPage(mCurrentPageStream, aFragments); + nsresult rv = PrintPage(aSizeInPoints, mCurrentPageStream, aFragments); mCurrentPageStream.Close(); @@ -147,11 +151,11 @@ void RemotePrintJobParent::FinishProcessingPage( } nsresult RemotePrintJobParent::PrintPage( - PRFileDescStream& aRecording, + const gfx::IntSize& aSizeInPoints, PRFileDescStream& aRecording, gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments) { MOZ_ASSERT(mPrintDeviceContext); - nsresult rv = mPrintDeviceContext->BeginPage(); + nsresult rv = mPrintDeviceContext->BeginPage(aSizeInPoints); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } diff --git a/layout/printing/ipc/RemotePrintJobParent.h b/layout/printing/ipc/RemotePrintJobParent.h index fc568ab3a619..2f805531832b 100644 --- a/layout/printing/ipc/RemotePrintJobParent.h +++ b/layout/printing/ipc/RemotePrintJobParent.h @@ -14,6 +14,7 @@ #include "nsCOMPtr.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" +#include "mozilla/gfx/Point.h" #include "mozilla/gfx/RecordedEvent.h" #include "mozilla/gfx/CrossProcessPaint.h" @@ -38,7 +39,9 @@ class RemotePrintJobParent final : public PRemotePrintJobParent { const int32_t& aStartPage, const int32_t& aEndPage) final; - mozilla::ipc::IPCResult RecvProcessPage(nsTArray&& aDeps) final; + mozilla::ipc::IPCResult RecvProcessPage(const int32_t& aWidthInPoints, + const int32_t& aHeightInPoints, + nsTArray&& aDeps) final; mozilla::ipc::IPCResult RecvFinalizePrint() final; @@ -72,9 +75,10 @@ class RemotePrintJobParent final : public PRemotePrintJobParent { nsresult PrepareNextPageFD(FileDescriptor* aFd); nsresult PrintPage( - PRFileDescStream& aRecording, + const gfx::IntSize& aSizeInPoints, PRFileDescStream& aRecording, gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments = nullptr); void FinishProcessingPage( + const gfx::IntSize& aSizeInPoints, gfx::CrossProcessPaint::ResolvedFragmentMap* aFragments = nullptr); /** diff --git a/widget/android/nsDeviceContextAndroid.h b/widget/android/nsDeviceContextAndroid.h index 1ab3c72c1cd1..094f3911519c 100644 --- a/widget/android/nsDeviceContextAndroid.h +++ b/widget/android/nsDeviceContextAndroid.h @@ -7,6 +7,7 @@ #include "nsIDeviceContextSpec.h" #include "nsCOMPtr.h" +#include "mozilla/gfx/Point.h" #include "mozilla/gfx/PrintPromise.h" class nsDeviceContextSpecAndroid final : public nsIDeviceContextSpec { @@ -14,6 +15,8 @@ class nsDeviceContextSpecAndroid final : public nsIDeviceContextSpec { virtual ~nsDeviceContextSpecAndroid(); public: + using IntSize = mozilla::gfx::IntSize; + NS_DECL_ISUPPORTS already_AddRefed MakePrintTarget() final; @@ -23,7 +26,7 @@ class nsDeviceContextSpecAndroid final : public nsIDeviceContextSpec { const nsAString& aPrintToFileName, int32_t aStartPage, int32_t aEndPage) override; RefPtr EndDocument() override; - NS_IMETHOD BeginPage() override { return NS_OK; } + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) override { return NS_OK; } NS_IMETHOD EndPage() override { return NS_OK; } private: diff --git a/widget/cocoa/nsDeviceContextSpecX.h b/widget/cocoa/nsDeviceContextSpecX.h index 9f44446c7d66..a5a5bbb9d9f8 100644 --- a/widget/cocoa/nsDeviceContextSpecX.h +++ b/widget/cocoa/nsDeviceContextSpecX.h @@ -28,7 +28,7 @@ class nsDeviceContextSpecX : public nsIDeviceContextSpec { const nsAString& aPrintToFileName, int32_t aStartPage, int32_t aEndPage) override; RefPtr EndDocument() override; - NS_IMETHOD BeginPage() override { return NS_OK; }; + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) override { return NS_OK; }; NS_IMETHOD EndPage() override { return NS_OK; }; void GetPaperRect(double* aTop, double* aLeft, double* aBottom, diff --git a/widget/gtk/nsDeviceContextSpecG.h b/widget/gtk/nsDeviceContextSpecG.h index eb43053b2bfb..93388b34a395 100644 --- a/widget/gtk/nsDeviceContextSpecG.h +++ b/widget/gtk/nsDeviceContextSpecG.h @@ -39,7 +39,7 @@ class nsDeviceContextSpecGTK : public nsIDeviceContextSpec { const nsAString& aPrintToFileName, int32_t aStartPage, int32_t aEndPage) override; RefPtr EndDocument() override; - NS_IMETHOD BeginPage() override { return NS_OK; } + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) override { return NS_OK; } NS_IMETHOD EndPage() override { return NS_OK; } protected: diff --git a/widget/nsDeviceContextSpecProxy.cpp b/widget/nsDeviceContextSpecProxy.cpp index d2c74fa77630..eed6e9b9995d 100644 --- a/widget/nsDeviceContextSpecProxy.cpp +++ b/widget/nsDeviceContextSpecProxy.cpp @@ -130,13 +130,14 @@ nsDeviceContextSpecProxy::EndDocument() { } NS_IMETHODIMP -nsDeviceContextSpecProxy::BeginPage() { +nsDeviceContextSpecProxy::BeginPage(const IntSize& aSizeInPoints) { if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) { mRemotePrintJob = nullptr; return NS_ERROR_NOT_AVAILABLE; } mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD()); + mCurrentPageSizeInPoints = aSizeInPoints; return NS_OK; } @@ -150,7 +151,8 @@ nsDeviceContextSpecProxy::EndPage() { // Send the page recording to the parent. mRecorder->Close(); - mRemotePrintJob->ProcessPage(std::move(mRecorder->TakeDependentSurfaces())); + mRemotePrintJob->ProcessPage(mCurrentPageSizeInPoints, + std::move(mRecorder->TakeDependentSurfaces())); return NS_OK; } diff --git a/widget/nsDeviceContextSpecProxy.h b/widget/nsDeviceContextSpecProxy.h index ee8a8b1fa35c..843811c34bd5 100644 --- a/widget/nsDeviceContextSpecProxy.h +++ b/widget/nsDeviceContextSpecProxy.h @@ -24,6 +24,7 @@ class RemotePrintJobChild; class nsDeviceContextSpecProxy final : public nsIDeviceContextSpec { public: + using IntSize = mozilla::gfx::IntSize; using RemotePrintJobChild = mozilla::layout::RemotePrintJobChild; explicit nsDeviceContextSpecProxy(RemotePrintJobChild* aRemotePrintJob); @@ -43,7 +44,7 @@ class nsDeviceContextSpecProxy final : public nsIDeviceContextSpec { RefPtr EndDocument() final; - NS_IMETHOD BeginPage() final; + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) final; NS_IMETHOD EndPage() final; @@ -52,6 +53,7 @@ class nsDeviceContextSpecProxy final : public nsIDeviceContextSpec { RefPtr mRemotePrintJob; RefPtr mRecorder; + IntSize mCurrentPageSizeInPoints; }; #endif // nsDeviceContextSpecProxy_h diff --git a/widget/nsIDeviceContextSpec.h b/widget/nsIDeviceContextSpec.h index 0432a6816bbc..6afe4ea850a9 100644 --- a/widget/nsIDeviceContextSpec.h +++ b/widget/nsIDeviceContextSpec.h @@ -9,6 +9,7 @@ #include "gfxPoint.h" #include "nsISupports.h" #include "mozilla/StaticPrefs_print.h" +#include "mozilla/gfx/Point.h" #include "mozilla/gfx/PrintPromise.h" #include "mozilla/MoveOnlyFunction.h" @@ -32,6 +33,7 @@ class PrintTarget; class nsIDeviceContextSpec : public nsISupports { public: typedef mozilla::gfx::PrintTarget PrintTarget; + using IntSize = mozilla::gfx::IntSize; NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDEVICE_CONTEXT_SPEC_IID) @@ -79,7 +81,12 @@ class nsIDeviceContextSpec : public nsISupports { int32_t aStartPage, int32_t aEndPage) = 0; virtual RefPtr EndDocument() = 0; - NS_IMETHOD BeginPage() = 0; + /** + * Note: not all print devices implement mixed page sizing. Internally, + * aSizeInPoints gets handed off to a PrintTarget, and most PrintTarget + * subclasses will ignore `aSizeInPoints`. + */ + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) = 0; NS_IMETHOD EndPage() = 0; protected: diff --git a/widget/windows/nsDeviceContextSpecWin.h b/widget/windows/nsDeviceContextSpecWin.h index 74baeda54931..fff6472d62f3 100644 --- a/widget/windows/nsDeviceContextSpecWin.h +++ b/widget/windows/nsDeviceContextSpecWin.h @@ -31,7 +31,7 @@ class nsDeviceContextSpecWin : public nsIDeviceContextSpec { return NS_OK; } RefPtr EndDocument() override; - NS_IMETHOD BeginPage() override { return NS_OK; } + NS_IMETHOD BeginPage(const IntSize& aSizeInPoints) override { return NS_OK; } NS_IMETHOD EndPage() override { return NS_OK; } NS_IMETHOD Init(nsIPrintSettings* aPS, bool aIsPrintPreview) override;