From e89b2bc6c965599c6d6489f508e22110e0748680 Mon Sep 17 00:00:00 2001 From: "troy%netscape.com" Date: Mon, 7 Dec 1998 03:43:02 +0000 Subject: [PATCH] Added support for printing multiple pages --- layout/base/nsIPresShell.h | 7 + layout/base/nsPresShell.cpp | 28 +++ layout/base/public/MANIFEST | 1 + layout/base/public/Makefile.in | 1 + layout/base/public/makefile.win | 1 + layout/base/public/nsIPresShell.h | 7 + layout/generic/nsFrame.h | 1 + layout/generic/nsPageFrame.cpp | 13 -- layout/generic/nsPageFrame.h | 12 +- layout/generic/nsSimplePageSequence.cpp | 169 +++++++++++++++++- layout/generic/nsSimplePageSequence.h | 23 ++- layout/html/base/src/nsFrame.h | 1 + layout/html/base/src/nsHTMLIIDs.cpp | 3 + layout/html/base/src/nsHTMLIIDs.h | 1 + layout/html/base/src/nsPageFrame.cpp | 13 -- layout/html/base/src/nsPageFrame.h | 12 +- layout/html/base/src/nsPresShell.cpp | 28 +++ layout/html/base/src/nsSimplePageSequence.cpp | 169 +++++++++++++++++- layout/html/base/src/nsSimplePageSequence.h | 23 ++- 19 files changed, 467 insertions(+), 46 deletions(-) diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 50e8615b3e2a..a5ada2dd5698 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -31,6 +31,7 @@ class nsIViewManager; class nsIReflowCommand; class nsIDeviceContext; class nsIRenderingContext; +class nsIPageSequenceFrame; #define NS_IPRESSHELL_IID \ { 0x76e79c60, 0x944e, 0x11d1, \ @@ -94,6 +95,12 @@ public: virtual nsIFrame* GetRootFrame() = 0; + /** + * Returns the page sequence frame associated with the frame hierarchy. + * Returns NULL if not a paginated view. + */ + NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame) = 0; + virtual nsIFrame* FindFrameWithContent(nsIContent* aContent) = 0; virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand) = 0; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index cbeaa34ad098..33d780e66efc 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -223,6 +223,7 @@ public: NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight); NS_IMETHOD StyleChangeReflow(); virtual nsIFrame* GetRootFrame(); + NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame); virtual nsIFrame* FindFrameWithContent(nsIContent* aContent); virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand); virtual void ProcessReflowCommands(); @@ -674,6 +675,33 @@ PresShell::GetRootFrame() return mRootFrame; } +NS_IMETHODIMP +PresShell::GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame) +{ + nsIFrame* child; + nsIPageSequenceFrame* pageSequence; + + // The page sequence frame should be either the immediate child or + // its child + mRootFrame->FirstChild(nsnull, child); + if (nsnull != child) { + if (NS_SUCCEEDED(child->QueryInterface(kIPageSequenceFrameIID, (void**)&pageSequence))) { + aPageSequenceFrame = pageSequence; + return NS_OK; + } + + child->FirstChild(nsnull, child); + if (nsnull != child) { + if (NS_SUCCEEDED(child->QueryInterface(kIPageSequenceFrameIID, (void**)&pageSequence))) { + aPageSequenceFrame = pageSequence; + return NS_OK; + } + } + } + + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP PresShell::BeginUpdate(nsIDocument *aDocument) { diff --git a/layout/base/public/MANIFEST b/layout/base/public/MANIFEST index 32acc8113f32..e593fe3c4209 100644 --- a/layout/base/public/MANIFEST +++ b/layout/base/public/MANIFEST @@ -8,6 +8,7 @@ nsIDocumentContainer.h nsIDocumentObserver.h nsIFrame.h nsIFrameImageLoader.h +nsIPageSequenceFrame.h nsIPresContext.h nsIPresShell.h nsIReflowCommand.h diff --git a/layout/base/public/Makefile.in b/layout/base/public/Makefile.in index bc1f1cbbf61d..6f83e8c933bd 100644 --- a/layout/base/public/Makefile.in +++ b/layout/base/public/Makefile.in @@ -33,6 +33,7 @@ EXPORTS = \ nsIFrame.h \ nsIFrameReflow.h \ nsIFrameImageLoader.h \ + nsIPageSequenceFrame.h \ nsIPresContext.h \ nsIPresShell.h \ nsIReflowCommand.h \ diff --git a/layout/base/public/makefile.win b/layout/base/public/makefile.win index 2bd9def2d9e4..3455a23df2ff 100644 --- a/layout/base/public/makefile.win +++ b/layout/base/public/makefile.win @@ -26,6 +26,7 @@ EXPORTS = \ nsIFrame.h \ nsIFrameReflow.h \ nsIFrameImageLoader.h \ + nsIPageSequenceFrame.h \ nsIPresContext.h \ nsIPresShell.h \ nsIReflowCommand.h \ diff --git a/layout/base/public/nsIPresShell.h b/layout/base/public/nsIPresShell.h index 50e8615b3e2a..a5ada2dd5698 100644 --- a/layout/base/public/nsIPresShell.h +++ b/layout/base/public/nsIPresShell.h @@ -31,6 +31,7 @@ class nsIViewManager; class nsIReflowCommand; class nsIDeviceContext; class nsIRenderingContext; +class nsIPageSequenceFrame; #define NS_IPRESSHELL_IID \ { 0x76e79c60, 0x944e, 0x11d1, \ @@ -94,6 +95,12 @@ public: virtual nsIFrame* GetRootFrame() = 0; + /** + * Returns the page sequence frame associated with the frame hierarchy. + * Returns NULL if not a paginated view. + */ + NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame) = 0; + virtual nsIFrame* FindFrameWithContent(nsIContent* aContent) = 0; virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand) = 0; diff --git a/layout/generic/nsFrame.h b/layout/generic/nsFrame.h index 7f82644d314b..cea98dab81ea 100644 --- a/layout/generic/nsFrame.h +++ b/layout/generic/nsFrame.h @@ -365,6 +365,7 @@ protected: private: nsIView* mView; // must use accessor member functions +protected: NS_IMETHOD_(nsrefcnt) AddRef(void); NS_IMETHOD_(nsrefcnt) Release(void); }; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index d8efacfd3bcb..bc4208495cce 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -136,19 +136,6 @@ nsPageFrame::CreateContinuingFrame(nsIPresContext& aPresContext, return NS_OK; } -NS_METHOD nsPageFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect) -{ - nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); - - // For the time being paint a border around the page so we know - // where each page begins and ends - aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height); - return NS_OK; -} - NS_IMETHODIMP nsPageFrame::GetFrameName(nsString& aResult) const { diff --git a/layout/generic/nsPageFrame.h b/layout/generic/nsPageFrame.h index 01985b1bec31..057e0a08f6bd 100644 --- a/layout/generic/nsPageFrame.h +++ b/layout/generic/nsPageFrame.h @@ -28,14 +28,10 @@ public: const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); - NS_IMETHOD CreateContinuingFrame(nsIPresContext& aCX, - nsIFrame* aParent, - nsIStyleContext* aStyleContext, - nsIFrame*& aContinuingFrame); - - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect); + NS_IMETHOD CreateContinuingFrame(nsIPresContext& aCX, + nsIFrame* aParent, + nsIStyleContext* aStyleContext, + nsIFrame*& aContinuingFrame); // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index bc5b5efba2e4..5d468c662624 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -23,6 +23,26 @@ #include "nsIRenderingContext.h" #include "nsIStyleContext.h" #include "nsHTMLAtoms.h" +#include "nsHTMLIIDs.h" +#include "nsIDeviceContext.h" +#include "nsIViewManager.h" +#include "nsIPresShell.h" + +nsresult +nsSimplePageSequenceFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIPageSequenceFrameIID)) { + *aInstancePtr = (void*)(nsIPageSequenceFrame*)this; + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +//---------------------------------------------------------------------- // XXX Hack #define PAGE_SPACING_TWIPS 100 @@ -163,6 +183,8 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext& aPresContext, return NS_OK; } +//---------------------------------------------------------------------- + NS_IMETHODIMP nsSimplePageSequenceFrame::GetFrameName(nsString& aResult) const { @@ -175,12 +197,157 @@ nsSimplePageSequenceFrame::Paint(nsIPresContext& aPresContext, const nsRect& aDirtyRect) { // Paint a white background - // XXX Crop marks or hash marks would be nice. Use style info... aRenderingContext.SetColor(NS_RGB(255,255,255)); aRenderingContext.FillRect(aDirtyRect); + // XXX Crop marks or hash marks would be nice. Use style info... return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); } +void +nsSimplePageSequenceFrame::PaintChild(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsIFrame* aFrame) +{ + // Let the page paint + nsContainerFrame::PaintChild(aPresContext, aRenderingContext, + aDirtyRect, aFrame); + + // XXX Paint a one-pixel border around the page so it's easy to see where + // each page begins and ends when we're in print preview mode + nsRect pageBounds; + float p2t = aPresContext.GetPixelsToTwips(); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + aFrame->GetRect(pageBounds); + pageBounds.Inflate(p2t, p2t); + aRenderingContext.DrawRect(pageBounds); +} + +//---------------------------------------------------------------------- + +// Helper function that sends the progress notification. Returns PR_TRUE +// if printing should continue and PR_FALSE otherwise +static PRBool +SendStatusNotification(nsIPrintStatusCallback* aStatusCallback, + PRInt32 aPageNumber, + PRInt32 aTotalPages, + nsPrintStatus aStatus) +{ + PRBool ret = PR_TRUE; + + if (nsnull != aStatusCallback) { + aStatusCallback->OnProgress(aPageNumber, aTotalPages, aStatus,ret); + } + + return ret; +} + +NS_IMETHODIMP +nsSimplePageSequenceFrame::Print(nsIPresContext& aPresContext, + const nsPrintOptions& aPrintOptions, + nsIPrintStatusCallback* aStatusCallback) +{ + // If printing a range of pages make sure at least the starting page + // number is valid + PRInt32 totalPages = LengthOf(mFirstChild); + + if (ePrintRange_SpecifiedRange == aPrintOptions.range) { + if (aPrintOptions.startPage > totalPages) { + return NS_ERROR_INVALID_ARG; + } + } + + // Send the notification that we're beginning to print the document + if (!SendStatusNotification(aStatusCallback, -1, totalPages, + ePrintStatus_StartDoc)) { + return NS_ERROR_ABORT; // indicate client cancelled printing + } + + // Begin printing of the document + nsIDeviceContext* dc = aPresContext.GetDeviceContext(); + nsresult rv = NS_OK; + + rv = dc->BeginDocument(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + + } else { + nsIPresShell* presShell = aPresContext.GetShell(); + nsIViewManager* vm = presShell->GetViewManager(); + NS_RELEASE(presShell); + + // Print each specified page + PRInt32 pageNum = 1; + for (nsIFrame* page = mFirstChild; + nsnull != page; + pageNum++, page->GetNextSibling(page)) { + + // If printing a range of pages check whether the page number is in the + // range of pages to print + if (ePrintRange_SpecifiedRange == aPrintOptions.range) { + if (pageNum < aPrintOptions.startPage) { + continue; + } else if (pageNum > aPrintOptions.endPage) { + break; + } + } + + // Start printing of the page + if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, + ePrintStatus_StartPage)) { + rv = NS_ERROR_ABORT; + break; + } + rv = dc->BeginPage(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + break; + } + + // Print the page + nsIView* view; + page->GetView(view); + NS_ASSERTION(nsnull != view, "no page view"); + vm->Display(view); + + // Finish printing of the page + if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, + ePrintStatus_EndPage)) { + rv = NS_ERROR_ABORT; + break; + } + rv = dc->EndPage(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + break; + } + } + + // Finish printing of the document + if (NS_SUCCEEDED(rv)) { + rv = dc->EndDocument(); + } else { + // rv = dc->AbortDocument(); + } + if (NS_FAILED(rv) && (nsnull != aStatusCallback)) { + aStatusCallback->OnError(ePrintError_Error); + } + SendStatusNotification(aStatusCallback, pageNum - 1, totalPages, + ePrintStatus_EndDoc); + NS_RELEASE(vm); + } + + NS_RELEASE(dc); + return rv; +} + //---------------------------------------------------------------------- nsresult diff --git a/layout/generic/nsSimplePageSequence.h b/layout/generic/nsSimplePageSequence.h index 0c7853a7c1d5..ce5a9b18f403 100644 --- a/layout/generic/nsSimplePageSequence.h +++ b/layout/generic/nsSimplePageSequence.h @@ -19,21 +19,42 @@ #define nsSimplePageSequence_h___ #include "nsHTMLContainerFrame.h" +#include "nsIPageSequenceFrame.h" // Simple page sequence frame class. Used when we're in paginated mode -class nsSimplePageSequenceFrame : public nsContainerFrame { +class nsSimplePageSequenceFrame : public nsContainerFrame, + public nsIPageSequenceFrame { public: + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIFrameReflow NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); + // nsIFrame NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); + // nsIPageSequenceFrame + NS_IMETHOD Print(nsIPresContext& aPresContext, + const nsPrintOptions& aPrintOptions, + nsIPrintStatusCallback* aStatusCallback); + // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; + +protected: + virtual void PaintChild(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsIFrame* aFrame); + + NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} + NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} }; #endif /* nsSimplePageSequence_h___ */ diff --git a/layout/html/base/src/nsFrame.h b/layout/html/base/src/nsFrame.h index 7f82644d314b..cea98dab81ea 100644 --- a/layout/html/base/src/nsFrame.h +++ b/layout/html/base/src/nsFrame.h @@ -365,6 +365,7 @@ protected: private: nsIView* mView; // must use accessor member functions +protected: NS_IMETHOD_(nsrefcnt) AddRef(void); NS_IMETHOD_(nsrefcnt) Release(void); }; diff --git a/layout/html/base/src/nsHTMLIIDs.cpp b/layout/html/base/src/nsHTMLIIDs.cpp index b9b82175feb9..6e1565871888 100644 --- a/layout/html/base/src/nsHTMLIIDs.cpp +++ b/layout/html/base/src/nsHTMLIIDs.cpp @@ -20,7 +20,10 @@ #include "nsIAbsoluteItems.h" #include "nsIAnchoredItems.h" #include "nsIHTMLReflow.h" +#include "nsIPageSequenceFrame.h" const nsIID kIAbsoluteItemsIID = NS_IABSOLUTE_ITEMS_IID; const nsIID kIHTMLContentIID = NS_IHTMLCONTENT_IID; const nsIID kIHTMLReflowIID = NS_IHTMLREFLOW_IID; +const nsIID kIPageSequenceFrameIID = NS_IPAGESEQUENCEFRAME_IID; + diff --git a/layout/html/base/src/nsHTMLIIDs.h b/layout/html/base/src/nsHTMLIIDs.h index 74e918d5438d..5cd383af3fc5 100644 --- a/layout/html/base/src/nsHTMLIIDs.h +++ b/layout/html/base/src/nsHTMLIIDs.h @@ -24,5 +24,6 @@ extern const nsIID kIAbsoluteItemsIID; extern const nsIID kIHTMLContentIID; extern const nsIID kIRunaroundIID; extern const nsIID kIHTMLReflowIID; +extern const nsIID kIPageSequenceFrameIID; #endif /* nsHTMLIIDs_h___ */ diff --git a/layout/html/base/src/nsPageFrame.cpp b/layout/html/base/src/nsPageFrame.cpp index d8efacfd3bcb..bc4208495cce 100644 --- a/layout/html/base/src/nsPageFrame.cpp +++ b/layout/html/base/src/nsPageFrame.cpp @@ -136,19 +136,6 @@ nsPageFrame::CreateContinuingFrame(nsIPresContext& aPresContext, return NS_OK; } -NS_METHOD nsPageFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect) -{ - nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); - - // For the time being paint a border around the page so we know - // where each page begins and ends - aRenderingContext.SetColor(NS_RGB(0, 0, 0)); - aRenderingContext.DrawRect(0, 0, mRect.width, mRect.height); - return NS_OK; -} - NS_IMETHODIMP nsPageFrame::GetFrameName(nsString& aResult) const { diff --git a/layout/html/base/src/nsPageFrame.h b/layout/html/base/src/nsPageFrame.h index 01985b1bec31..057e0a08f6bd 100644 --- a/layout/html/base/src/nsPageFrame.h +++ b/layout/html/base/src/nsPageFrame.h @@ -28,14 +28,10 @@ public: const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); - NS_IMETHOD CreateContinuingFrame(nsIPresContext& aCX, - nsIFrame* aParent, - nsIStyleContext* aStyleContext, - nsIFrame*& aContinuingFrame); - - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect); + NS_IMETHOD CreateContinuingFrame(nsIPresContext& aCX, + nsIFrame* aParent, + nsIStyleContext* aStyleContext, + nsIFrame*& aContinuingFrame); // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; diff --git a/layout/html/base/src/nsPresShell.cpp b/layout/html/base/src/nsPresShell.cpp index cbeaa34ad098..33d780e66efc 100644 --- a/layout/html/base/src/nsPresShell.cpp +++ b/layout/html/base/src/nsPresShell.cpp @@ -223,6 +223,7 @@ public: NS_IMETHOD ResizeReflow(nscoord aWidth, nscoord aHeight); NS_IMETHOD StyleChangeReflow(); virtual nsIFrame* GetRootFrame(); + NS_IMETHOD GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame); virtual nsIFrame* FindFrameWithContent(nsIContent* aContent); virtual void AppendReflowCommand(nsIReflowCommand* aReflowCommand); virtual void ProcessReflowCommands(); @@ -674,6 +675,33 @@ PresShell::GetRootFrame() return mRootFrame; } +NS_IMETHODIMP +PresShell::GetPageSequenceFrame(nsIPageSequenceFrame*& aPageSequenceFrame) +{ + nsIFrame* child; + nsIPageSequenceFrame* pageSequence; + + // The page sequence frame should be either the immediate child or + // its child + mRootFrame->FirstChild(nsnull, child); + if (nsnull != child) { + if (NS_SUCCEEDED(child->QueryInterface(kIPageSequenceFrameIID, (void**)&pageSequence))) { + aPageSequenceFrame = pageSequence; + return NS_OK; + } + + child->FirstChild(nsnull, child); + if (nsnull != child) { + if (NS_SUCCEEDED(child->QueryInterface(kIPageSequenceFrameIID, (void**)&pageSequence))) { + aPageSequenceFrame = pageSequence; + return NS_OK; + } + } + } + + return NS_ERROR_FAILURE; +} + NS_IMETHODIMP PresShell::BeginUpdate(nsIDocument *aDocument) { diff --git a/layout/html/base/src/nsSimplePageSequence.cpp b/layout/html/base/src/nsSimplePageSequence.cpp index bc5b5efba2e4..5d468c662624 100644 --- a/layout/html/base/src/nsSimplePageSequence.cpp +++ b/layout/html/base/src/nsSimplePageSequence.cpp @@ -23,6 +23,26 @@ #include "nsIRenderingContext.h" #include "nsIStyleContext.h" #include "nsHTMLAtoms.h" +#include "nsHTMLIIDs.h" +#include "nsIDeviceContext.h" +#include "nsIViewManager.h" +#include "nsIPresShell.h" + +nsresult +nsSimplePageSequenceFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIPageSequenceFrameIID)) { + *aInstancePtr = (void*)(nsIPageSequenceFrame*)this; + return NS_OK; + } + return nsContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +//---------------------------------------------------------------------- // XXX Hack #define PAGE_SPACING_TWIPS 100 @@ -163,6 +183,8 @@ nsSimplePageSequenceFrame::Reflow(nsIPresContext& aPresContext, return NS_OK; } +//---------------------------------------------------------------------- + NS_IMETHODIMP nsSimplePageSequenceFrame::GetFrameName(nsString& aResult) const { @@ -175,12 +197,157 @@ nsSimplePageSequenceFrame::Paint(nsIPresContext& aPresContext, const nsRect& aDirtyRect) { // Paint a white background - // XXX Crop marks or hash marks would be nice. Use style info... aRenderingContext.SetColor(NS_RGB(255,255,255)); aRenderingContext.FillRect(aDirtyRect); + // XXX Crop marks or hash marks would be nice. Use style info... return nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); } +void +nsSimplePageSequenceFrame::PaintChild(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsIFrame* aFrame) +{ + // Let the page paint + nsContainerFrame::PaintChild(aPresContext, aRenderingContext, + aDirtyRect, aFrame); + + // XXX Paint a one-pixel border around the page so it's easy to see where + // each page begins and ends when we're in print preview mode + nsRect pageBounds; + float p2t = aPresContext.GetPixelsToTwips(); + + aRenderingContext.SetColor(NS_RGB(0, 0, 0)); + aFrame->GetRect(pageBounds); + pageBounds.Inflate(p2t, p2t); + aRenderingContext.DrawRect(pageBounds); +} + +//---------------------------------------------------------------------- + +// Helper function that sends the progress notification. Returns PR_TRUE +// if printing should continue and PR_FALSE otherwise +static PRBool +SendStatusNotification(nsIPrintStatusCallback* aStatusCallback, + PRInt32 aPageNumber, + PRInt32 aTotalPages, + nsPrintStatus aStatus) +{ + PRBool ret = PR_TRUE; + + if (nsnull != aStatusCallback) { + aStatusCallback->OnProgress(aPageNumber, aTotalPages, aStatus,ret); + } + + return ret; +} + +NS_IMETHODIMP +nsSimplePageSequenceFrame::Print(nsIPresContext& aPresContext, + const nsPrintOptions& aPrintOptions, + nsIPrintStatusCallback* aStatusCallback) +{ + // If printing a range of pages make sure at least the starting page + // number is valid + PRInt32 totalPages = LengthOf(mFirstChild); + + if (ePrintRange_SpecifiedRange == aPrintOptions.range) { + if (aPrintOptions.startPage > totalPages) { + return NS_ERROR_INVALID_ARG; + } + } + + // Send the notification that we're beginning to print the document + if (!SendStatusNotification(aStatusCallback, -1, totalPages, + ePrintStatus_StartDoc)) { + return NS_ERROR_ABORT; // indicate client cancelled printing + } + + // Begin printing of the document + nsIDeviceContext* dc = aPresContext.GetDeviceContext(); + nsresult rv = NS_OK; + + rv = dc->BeginDocument(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + + } else { + nsIPresShell* presShell = aPresContext.GetShell(); + nsIViewManager* vm = presShell->GetViewManager(); + NS_RELEASE(presShell); + + // Print each specified page + PRInt32 pageNum = 1; + for (nsIFrame* page = mFirstChild; + nsnull != page; + pageNum++, page->GetNextSibling(page)) { + + // If printing a range of pages check whether the page number is in the + // range of pages to print + if (ePrintRange_SpecifiedRange == aPrintOptions.range) { + if (pageNum < aPrintOptions.startPage) { + continue; + } else if (pageNum > aPrintOptions.endPage) { + break; + } + } + + // Start printing of the page + if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, + ePrintStatus_StartPage)) { + rv = NS_ERROR_ABORT; + break; + } + rv = dc->BeginPage(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + break; + } + + // Print the page + nsIView* view; + page->GetView(view); + NS_ASSERTION(nsnull != view, "no page view"); + vm->Display(view); + + // Finish printing of the page + if (!SendStatusNotification(aStatusCallback, pageNum, totalPages, + ePrintStatus_EndPage)) { + rv = NS_ERROR_ABORT; + break; + } + rv = dc->EndPage(); + if (NS_FAILED(rv)) { + if (nsnull != aStatusCallback) { + aStatusCallback->OnError(ePrintError_Error); + } + break; + } + } + + // Finish printing of the document + if (NS_SUCCEEDED(rv)) { + rv = dc->EndDocument(); + } else { + // rv = dc->AbortDocument(); + } + if (NS_FAILED(rv) && (nsnull != aStatusCallback)) { + aStatusCallback->OnError(ePrintError_Error); + } + SendStatusNotification(aStatusCallback, pageNum - 1, totalPages, + ePrintStatus_EndDoc); + NS_RELEASE(vm); + } + + NS_RELEASE(dc); + return rv; +} + //---------------------------------------------------------------------- nsresult diff --git a/layout/html/base/src/nsSimplePageSequence.h b/layout/html/base/src/nsSimplePageSequence.h index 0c7853a7c1d5..ce5a9b18f403 100644 --- a/layout/html/base/src/nsSimplePageSequence.h +++ b/layout/html/base/src/nsSimplePageSequence.h @@ -19,21 +19,42 @@ #define nsSimplePageSequence_h___ #include "nsHTMLContainerFrame.h" +#include "nsIPageSequenceFrame.h" // Simple page sequence frame class. Used when we're in paginated mode -class nsSimplePageSequenceFrame : public nsContainerFrame { +class nsSimplePageSequenceFrame : public nsContainerFrame, + public nsIPageSequenceFrame { public: + // nsISupports + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIFrameReflow NS_IMETHOD Reflow(nsIPresContext& aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aMaxSize, nsReflowStatus& aStatus); + // nsIFrame NS_IMETHOD Paint(nsIPresContext& aPresContext, nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect); + // nsIPageSequenceFrame + NS_IMETHOD Print(nsIPresContext& aPresContext, + const nsPrintOptions& aPrintOptions, + nsIPrintStatusCallback* aStatusCallback); + // Debugging NS_IMETHOD GetFrameName(nsString& aResult) const; + +protected: + virtual void PaintChild(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsIFrame* aFrame); + + NS_IMETHOD_(nsrefcnt) AddRef(void) {return nsContainerFrame::AddRef();} + NS_IMETHOD_(nsrefcnt) Release(void) {return nsContainerFrame::Release();} }; #endif /* nsSimplePageSequence_h___ */