1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsSimplePageSequenceFrame.h"
9 #include "nsPresContext.h"
10 #include "gfxContext.h"
11 #include "nsRenderingContext.h"
12 #include "nsGkAtoms.h"
13 #include "nsIPresShell.h"
14 #include "nsIPrintSettings.h"
15 #include "nsPageFrame.h"
16 #include "nsSubDocumentFrame.h"
18 #include "nsCSSFrameConstructor.h"
19 #include "nsContentUtils.h"
20 #include "nsDisplayList.h"
21 #include "nsHTMLCanvasFrame.h"
22 #include "mozilla/dom/HTMLCanvasElement.h"
23 #include "nsICanvasRenderingContextInternal.h"
24 #include "nsIDateTimeFormat.h"
25 #include "nsServiceManagerUtils.h"
29 #include "nsDateTimeFormatCID.h"
31 #define OFFSET_NOT_SET -1
34 #include "nsIPrintOptions.h"
36 using namespace mozilla
;
37 using namespace mozilla::dom
;
39 static const char sPrintOptionsContractID
[] = "@mozilla.org/gfx/printsettings-service;1";
46 GetLayoutPrintingLog()
48 static PRLogModuleInfo
*sLog
;
50 sLog
= PR_NewLogModule("printing-layout");
53 #define PR_PL(_p1) PR_LOG(GetLayoutPrintingLog(), PR_LOG_DEBUG, _p1)
58 nsSimplePageSequenceFrame
*
59 NS_NewSimplePageSequenceFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
61 return new (aPresShell
) nsSimplePageSequenceFrame(aContext
);
64 NS_IMPL_FRAMEARENA_HELPERS(nsSimplePageSequenceFrame
)
66 nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext
* aContext
) :
67 nsContainerFrame(aContext
),
71 mCalledBeginPage(false),
72 mCurrentCanvasListSetup(false)
74 nscoord halfInch
= PresContext()->CSSTwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5));
75 mMargin
.SizeTo(halfInch
, halfInch
, halfInch
, halfInch
);
77 // XXX Unsafe to assume successful allocation
78 mPageData
= new nsSharedPageData();
79 mPageData
->mHeadFootFont
=
80 *PresContext()->GetDefaultFont(kGenericFont_serif
,
81 aContext
->StyleFont()->mLanguage
);
82 mPageData
->mHeadFootFont
.size
= nsPresContext::CSSPointsToAppUnits(10);
85 mPageData
->mPrintOptions
= do_GetService(sPrintOptionsContractID
, &rv
);
87 // Doing this here so we only have to go get these formats once
88 SetPageNumberFormat("pagenumber", "%1$d", true);
89 SetPageNumberFormat("pageofpages", "%1$d of %2$d", false);
92 nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame()
95 ResetPrintCanvasList();
98 NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame
)
99 NS_QUERYFRAME_ENTRY(nsIPageSequenceFrame
)
100 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame
)
102 //----------------------------------------------------------------------
105 nsSimplePageSequenceFrame::SetDesiredSize(nsHTMLReflowMetrics
& aDesiredSize
,
106 const nsHTMLReflowState
& aReflowState
,
110 // Aim to fill the whole size of the document, not only so we
111 // can act as a background in print preview but also handle overflow
112 // in child page frames correctly.
113 // Use availableWidth so we don't cause a needless horizontal scrollbar.
114 aDesiredSize
.Width() = std::max(aReflowState
.AvailableWidth(),
115 nscoord(aWidth
* PresContext()->GetPrintPreviewScale()));
116 aDesiredSize
.Height() = std::max(aReflowState
.ComputedHeight(),
117 nscoord(aHeight
* PresContext()->GetPrintPreviewScale()));
121 nsSimplePageSequenceFrame::Reflow(nsPresContext
* aPresContext
,
122 nsHTMLReflowMetrics
& aDesiredSize
,
123 const nsHTMLReflowState
& aReflowState
,
124 nsReflowStatus
& aStatus
)
126 NS_PRECONDITION(aPresContext
->IsRootPaginatedDocument(),
127 "A Page Sequence is only for real pages");
128 DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
129 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
130 NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
132 aStatus
= NS_FRAME_COMPLETE
; // we're always complete
134 // Don't do incremental reflow until we've taught tables how to do
135 // it right in paginated mode.
136 if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW
)) {
137 // Return our desired size
138 SetDesiredSize(aDesiredSize
, aReflowState
, mSize
.width
, mSize
.height
);
139 aDesiredSize
.SetOverflowAreasToDesiredBounds();
140 FinishAndStoreOverflow(&aDesiredSize
);
144 // See if we can get a Print Settings from the Context
145 if (!mPageData
->mPrintSettings
&&
146 aPresContext
->Medium() == nsGkAtoms::print
) {
147 mPageData
->mPrintSettings
= aPresContext
->GetPrintSettings();
150 // now get out margins & edges
151 if (mPageData
->mPrintSettings
) {
152 nsIntMargin unwriteableTwips
;
153 mPageData
->mPrintSettings
->GetUnwriteableMarginInTwips(unwriteableTwips
);
154 NS_ASSERTION(unwriteableTwips
.left
>= 0 && unwriteableTwips
.top
>= 0 &&
155 unwriteableTwips
.right
>= 0 && unwriteableTwips
.bottom
>= 0,
156 "Unwriteable twips should be non-negative");
158 nsIntMargin marginTwips
;
159 mPageData
->mPrintSettings
->GetMarginInTwips(marginTwips
);
160 mMargin
= aPresContext
->CSSTwipsToAppUnits(marginTwips
+ unwriteableTwips
);
163 mPageData
->mPrintSettings
->GetPrintRange(&printType
);
164 mPrintRangeType
= printType
;
166 nsIntMargin edgeTwips
;
167 mPageData
->mPrintSettings
->GetEdgeInTwips(edgeTwips
);
169 // sanity check the values. three inches are sometimes needed
170 int32_t inchInTwips
= NS_INCHES_TO_INT_TWIPS(3.0);
171 edgeTwips
.top
= clamped(edgeTwips
.top
, 0, inchInTwips
);
172 edgeTwips
.bottom
= clamped(edgeTwips
.bottom
, 0, inchInTwips
);
173 edgeTwips
.left
= clamped(edgeTwips
.left
, 0, inchInTwips
);
174 edgeTwips
.right
= clamped(edgeTwips
.right
, 0, inchInTwips
);
176 mPageData
->mEdgePaperMargin
=
177 aPresContext
->CSSTwipsToAppUnits(edgeTwips
+ unwriteableTwips
);
180 // *** Special Override ***
181 // If this is a sub-sdoc (meaning it doesn't take the whole page)
182 // and if this Document is in the upper left hand corner
183 // we need to suppress the top margin or it will reflow too small
185 nsSize pageSize
= aPresContext
->GetPageSize();
187 mPageData
->mReflowSize
= pageSize
;
188 // If we're printing a selection, we need to reflow with
189 // unconstrained height, to make sure we'll get to the selection
190 // even if it's beyond the first page of content.
191 if (nsIPrintSettings::kRangeSelection
== mPrintRangeType
) {
192 mPageData
->mReflowSize
.height
= NS_UNCONSTRAINEDSIZE
;
194 mPageData
->mReflowMargin
= mMargin
;
196 // We use the CSS "margin" property on the -moz-page pseudoelement
197 // to determine the space between each page in print preview.
198 // Keep a running y-offset for each page.
200 nscoord maxXMost
= 0;
202 // Tile the pages vertically
203 nsHTMLReflowMetrics
kidSize(aReflowState
);
204 for (nsFrameList::Enumerator
e(mFrames
); !e
.AtEnd(); e
.Next()) {
205 nsIFrame
* kidFrame
= e
.get();
206 // Set the shared data into the page frame before reflow
207 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(kidFrame
);
208 pf
->SetSharedPageData(mPageData
);
211 nsHTMLReflowState
kidReflowState(aPresContext
, aReflowState
, kidFrame
,
212 LogicalSize(kidFrame
->GetWritingMode(),
214 nsReflowStatus status
;
216 kidReflowState
.SetComputedWidth(kidReflowState
.AvailableWidth());
217 //kidReflowState.SetComputedHeight(kidReflowState.AvailableHeight());
218 PR_PL(("AV W: %d H: %d\n", kidReflowState
.AvailableWidth(), kidReflowState
.AvailableHeight()));
220 nsMargin pageCSSMargin
= kidReflowState
.ComputedPhysicalMargin();
221 y
+= pageCSSMargin
.top
;
222 const nscoord x
= pageCSSMargin
.left
;
224 // Place and size the page. If the page is narrower than our
225 // max width then center it horizontally
226 ReflowChild(kidFrame
, aPresContext
, kidSize
, kidReflowState
, x
, y
, 0, status
);
228 FinishReflowChild(kidFrame
, aPresContext
, kidSize
, nullptr, x
, y
, 0);
229 y
+= kidSize
.Height();
230 y
+= pageCSSMargin
.bottom
;
232 maxXMost
= std::max(maxXMost
, x
+ kidSize
.Width() + pageCSSMargin
.right
);
234 // Is the page complete?
235 nsIFrame
* kidNextInFlow
= kidFrame
->GetNextInFlow();
237 if (NS_FRAME_IS_FULLY_COMPLETE(status
)) {
238 NS_ASSERTION(!kidNextInFlow
, "bad child flow list");
239 } else if (!kidNextInFlow
) {
240 // The page isn't complete and it doesn't have a next-in-flow, so
241 // create a continuing page.
242 nsIFrame
* continuingPage
= aPresContext
->PresShell()->FrameConstructor()->
243 CreateContinuingFrame(aPresContext
, kidFrame
, this);
245 // Add it to our child list
246 mFrames
.InsertFrame(nullptr, kidFrame
, continuingPage
);
250 // Get Total Page Count
251 // XXXdholbert technically we could calculate this in the loop above,
252 // instead of needing a separate walk.
253 int32_t pageTot
= mFrames
.GetLength();
255 // Set Page Number Info
257 for (nsFrameList::Enumerator
e(mFrames
); !e
.AtEnd(); e
.Next()) {
258 MOZ_ASSERT(e
.get()->GetType() == nsGkAtoms::pageFrame
,
259 "only expecting nsPageFrame children. Other children will make "
260 "this static_cast bogus & probably violate other assumptions");
261 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(e
.get());
262 pf
->SetPageNumInfo(pageNum
, pageTot
);
266 // Create current Date/Time String
267 if (!mDateFormatter
) {
268 mDateFormatter
= do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID
);
270 if (!mDateFormatter
) {
273 nsAutoString formattedDateString
;
276 if (NS_SUCCEEDED(mDateFormatter
->FormatTime(nullptr /* nsILocale* locale */,
278 kTimeFormatNoSeconds
,
280 formattedDateString
))) {
281 SetDateTimeStr(formattedDateString
);
284 // Return our desired size
285 // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the
287 SetDesiredSize(aDesiredSize
, aReflowState
, maxXMost
, y
);
289 aDesiredSize
.SetOverflowAreasToDesiredBounds();
290 FinishAndStoreOverflow(&aDesiredSize
);
292 // cache the size so we can set the desired size
293 // for the other reflows that happen
294 mSize
.width
= maxXMost
;
297 NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus
);
298 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
301 //----------------------------------------------------------------------
303 #ifdef DEBUG_FRAME_DUMP
305 nsSimplePageSequenceFrame::GetFrameName(nsAString
& aResult
) const
307 return MakeFrameName(NS_LITERAL_STRING("SimplePageSequence"), aResult
);
311 //====================================================================
313 //====================================================================
315 nsSimplePageSequenceFrame::GetCurrentPageNum(int32_t* aPageNum
)
317 NS_ENSURE_ARG_POINTER(aPageNum
);
319 *aPageNum
= mPageNum
;
324 nsSimplePageSequenceFrame::GetNumPages(int32_t* aNumPages
)
326 NS_ENSURE_ARG_POINTER(aNumPages
);
328 *aNumPages
= mTotalPages
;
333 nsSimplePageSequenceFrame::IsDoingPrintRange(bool* aDoing
)
335 NS_ENSURE_ARG_POINTER(aDoing
);
337 *aDoing
= mDoingPageRange
;
342 nsSimplePageSequenceFrame::GetPrintRange(int32_t* aFromPage
, int32_t* aToPage
)
344 NS_ENSURE_ARG_POINTER(aFromPage
);
345 NS_ENSURE_ARG_POINTER(aToPage
);
347 *aFromPage
= mFromPageNum
;
348 *aToPage
= mToPageNum
;
354 nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName
, const char* aDefPropVal
, bool aPageNumOnly
)
356 // Doing this here so we only have to go get these formats once
357 nsXPIDLString pageNumberFormat
;
358 // Now go get the Localized Page Formating String
360 nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
361 aPropName
, pageNumberFormat
);
362 if (NS_FAILED(rv
)) { // back stop formatting
363 pageNumberFormat
.AssignASCII(aDefPropVal
);
366 SetPageNumberFormat(pageNumberFormat
, aPageNumOnly
);
370 nsSimplePageSequenceFrame::StartPrint(nsPresContext
* aPresContext
,
371 nsIPrintSettings
* aPrintSettings
,
372 const nsAString
& aDocTitle
,
373 const nsAString
& aDocURL
)
375 NS_ENSURE_ARG_POINTER(aPresContext
);
376 NS_ENSURE_ARG_POINTER(aPrintSettings
);
378 if (!mPageData
->mPrintSettings
) {
379 mPageData
->mPrintSettings
= aPrintSettings
;
382 if (!aDocTitle
.IsEmpty()) {
383 mPageData
->mDocTitle
= aDocTitle
;
385 if (!aDocURL
.IsEmpty()) {
386 mPageData
->mDocURL
= aDocURL
;
389 aPrintSettings
->GetStartPageRange(&mFromPageNum
);
390 aPrintSettings
->GetEndPageRange(&mToPageNum
);
391 aPrintSettings
->GetPageRanges(mPageRanges
);
393 mDoingPageRange
= nsIPrintSettings::kRangeSpecifiedPageRange
== mPrintRangeType
||
394 nsIPrintSettings::kRangeSelection
== mPrintRangeType
;
396 // If printing a range of pages make sure at least the starting page
398 int32_t totalPages
= mFrames
.GetLength();
400 if (mDoingPageRange
) {
401 if (mFromPageNum
> totalPages
) {
402 return NS_ERROR_INVALID_ARG
;
406 // Begin printing of the document
409 // Determine if we are rendering only the selection
410 aPresContext
->SetIsRenderingOnlySelection(nsIPrintSettings::kRangeSelection
== mPrintRangeType
);
413 if (mDoingPageRange
) {
414 // XXX because of the hack for making the selection all print on one page
415 // we must make sure that the page is sized correctly before printing.
416 nscoord height
= aPresContext
->GetPageSize().height
;
419 nscoord y
= 0;//mMargin.top;
421 for (nsFrameList::Enumerator
e(mFrames
); !e
.AtEnd(); e
.Next()) {
422 nsIFrame
* page
= e
.get();
423 if (pageNum
>= mFromPageNum
&& pageNum
<= mToPageNum
) {
424 nsRect rect
= page
->GetRect();
426 rect
.height
= height
;
428 y
+= rect
.height
+ mMargin
.top
+ mMargin
.bottom
;
433 // adjust total number of pages
434 if (nsIPrintSettings::kRangeSelection
!= mPrintRangeType
) {
435 totalPages
= pageNum
- 1;
441 if (mTotalPages
== -1) {
442 mTotalPages
= totalPages
;
449 GetPrintCanvasElementsInFrame(nsIFrame
* aFrame
, nsTArray
<nsRefPtr
<HTMLCanvasElement
> >* aArr
)
454 for (nsIFrame::ChildListIterator
childLists(aFrame
);
455 !childLists
.IsDone(); childLists
.Next()) {
457 nsFrameList children
= childLists
.CurrentList();
458 for (nsFrameList::Enumerator
e(children
); !e
.AtEnd(); e
.Next()) {
459 nsIFrame
* child
= e
.get();
461 // Check if child is a nsHTMLCanvasFrame.
462 nsHTMLCanvasFrame
* canvasFrame
= do_QueryFrame(child
);
464 // If there is a canvasFrame, try to get actual canvas element.
466 HTMLCanvasElement
* canvas
=
467 HTMLCanvasElement::FromContentOrNull(canvasFrame
->GetContent());
468 if (canvas
&& canvas
->GetMozPrintCallback()) {
469 aArr
->AppendElement(canvas
);
474 if (!child
->GetFirstPrincipalChild()) {
475 nsSubDocumentFrame
* subdocumentFrame
= do_QueryFrame(child
);
476 if (subdocumentFrame
) {
477 // Descend into the subdocument
478 nsIFrame
* root
= subdocumentFrame
->GetSubdocumentRootFrame();
482 // The current child is not a nsHTMLCanvasFrame OR it is but there is
483 // no HTMLCanvasElement on it. Check if children of `child` might
484 // contain a HTMLCanvasElement.
485 GetPrintCanvasElementsInFrame(child
, aArr
);
491 nsSimplePageSequenceFrame::DetermineWhetherToPrintPage()
493 // See whether we should print this page
494 mPrintThisPage
= true;
495 bool printEvenPages
, printOddPages
;
496 mPageData
->mPrintSettings
->GetPrintOptions(nsIPrintSettings::kPrintEvenPages
, &printEvenPages
);
497 mPageData
->mPrintSettings
->GetPrintOptions(nsIPrintSettings::kPrintOddPages
, &printOddPages
);
499 // If printing a range of pages check whether the page number is in the
500 // range of pages to print
501 if (mDoingPageRange
) {
502 if (mPageNum
< mFromPageNum
) {
503 mPrintThisPage
= false;
504 } else if (mPageNum
> mToPageNum
) {
506 mPrintThisPage
= false;
509 int32_t length
= mPageRanges
.Length();
511 // Page ranges are pairs (start, end)
512 if (length
&& (length
% 2 == 0)) {
513 mPrintThisPage
= false;
516 for (i
= 0; i
< length
; i
+= 2) {
517 if (mPageRanges
[i
] <= mPageNum
&& mPageNum
<= mPageRanges
[i
+1]) {
518 mPrintThisPage
= true;
526 // Check for printing of odd and even pages
527 if (mPageNum
& 0x1) {
528 if (!printOddPages
) {
529 mPrintThisPage
= false; // don't print odd numbered page
532 if (!printEvenPages
) {
533 mPrintThisPage
= false; // don't print even numbered page
537 if (nsIPrintSettings::kRangeSelection
== mPrintRangeType
) {
538 mPrintThisPage
= true;
543 nsSimplePageSequenceFrame::GetCurrentPageFrame()
546 for (nsFrameList::Enumerator
childFrames(mFrames
); !childFrames
.AtEnd();
547 childFrames
.Next()) {
549 return childFrames
.get();
557 nsSimplePageSequenceFrame::PrePrintNextPage(nsITimerCallback
* aCallback
, bool* aDone
)
559 nsIFrame
* currentPage
= GetCurrentPageFrame();
562 return NS_ERROR_FAILURE
;
565 DetermineWhetherToPrintPage();
566 // Nothing to do if the current page doesn't get printed OR rendering to
567 // preview. For preview, the `CallPrintCallback` is called from within the
568 // HTMLCanvasElement::HandlePrintCallback.
569 if (!mPrintThisPage
|| !PresContext()->IsRootPaginatedDocument()) {
574 // If the canvasList is null, then generate it and start the render
575 // process for all the canvas.
576 if (!mCurrentCanvasListSetup
) {
577 mCurrentCanvasListSetup
= true;
578 GetPrintCanvasElementsInFrame(currentPage
, &mCurrentCanvasList
);
580 if (mCurrentCanvasList
.Length() != 0) {
583 // Begin printing of the document
584 nsDeviceContext
*dc
= PresContext()->DeviceContext();
586 PR_PL(("***************** BeginPage *****************\n"));
587 rv
= dc
->BeginPage();
588 NS_ENSURE_SUCCESS(rv
, rv
);
590 mCalledBeginPage
= true;
592 nsRefPtr
<nsRenderingContext
> renderingContext
=
593 dc
->CreateRenderingContext();
595 nsRefPtr
<gfxASurface
> renderingSurface
=
596 renderingContext
->ThebesContext()->CurrentSurface();
597 NS_ENSURE_TRUE(renderingSurface
, NS_ERROR_OUT_OF_MEMORY
);
599 for (int32_t i
= mCurrentCanvasList
.Length() - 1; i
>= 0 ; i
--) {
600 HTMLCanvasElement
* canvas
= mCurrentCanvasList
[i
];
601 nsIntSize size
= canvas
->GetSize();
603 nsRefPtr
<gfxASurface
> printSurface
= renderingSurface
->
604 CreateSimilarSurface(
605 gfxContentType::COLOR_ALPHA
,
613 nsICanvasRenderingContextInternal
* ctx
= canvas
->GetContextAtIndex(0);
619 // Initialize the context with the new printSurface.
620 ctx
->InitializeWithSurface(nullptr, printSurface
, size
.width
, size
.height
);
622 // Start the rendering process.
623 nsWeakFrame weakFrame
= this;
624 canvas
->DispatchPrintCallback(aCallback
);
625 NS_ENSURE_STATE(weakFrame
.IsAlive());
629 uint32_t doneCounter
= 0;
630 for (int32_t i
= mCurrentCanvasList
.Length() - 1; i
>= 0 ; i
--) {
631 HTMLCanvasElement
* canvas
= mCurrentCanvasList
[i
];
633 if (canvas
->IsPrintCallbackDone()) {
637 // If all canvas have finished rendering, return true, otherwise false.
638 *aDone
= doneCounter
== mCurrentCanvasList
.Length();
644 nsSimplePageSequenceFrame::ResetPrintCanvasList()
646 for (int32_t i
= mCurrentCanvasList
.Length() - 1; i
>= 0 ; i
--) {
647 HTMLCanvasElement
* canvas
= mCurrentCanvasList
[i
];
648 canvas
->ResetPrintCallback();
651 mCurrentCanvasList
.Clear();
652 mCurrentCanvasListSetup
= false;
657 nsSimplePageSequenceFrame::PrintNextPage()
659 // Print each specified page
660 // pageNum keeps track of the current page and what pages are printing
662 // printedPageNum keeps track of the current page number to be printed
663 // Note: When print al the pages or a page range the printed page shows the
664 // actual page number, when printing selection it prints the page number starting
665 // with the first page of the selection. For example if the user has a
666 // selection that starts on page 2 and ends on page 3, the page numbers when
667 // print are 1 and then two (which is different than printing a page range, where
668 // the page numbers would have been 2 and then 3)
670 nsIFrame
* currentPage
= GetCurrentPageFrame();
672 return NS_ERROR_FAILURE
;
677 DetermineWhetherToPrintPage();
679 if (mPrintThisPage
) {
680 // Begin printing of the document
681 nsDeviceContext
* dc
= PresContext()->DeviceContext();
683 // XXX This is temporary fix for printing more than one page of a selection
684 // This does a poor man's "dump" pagination (see Bug 89353)
685 // It has laid out as one long page and now we are just moving or view up/down
686 // one page at a time and printing the contents of what is exposed by the rect.
687 // currently this does not work for IFrames
688 // I will soon improve this to work with IFrames
689 bool continuePrinting
= true;
690 nscoord width
, height
;
691 width
= PresContext()->GetPageSize().width
;
692 height
= PresContext()->GetPageSize().height
;
693 height
-= mMargin
.top
+ mMargin
.bottom
;
694 width
-= mMargin
.left
+ mMargin
.right
;
695 nscoord selectionY
= height
;
696 nsIFrame
* conFrame
= currentPage
->GetFirstPrincipalChild();
697 if (mSelectionHeight
>= 0) {
698 conFrame
->SetPosition(conFrame
->GetPosition() + nsPoint(0, -mYSelOffset
));
699 nsContainerFrame::PositionChildViews(conFrame
);
702 // cast the frame to be a page frame
703 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(currentPage
);
704 pf
->SetPageNumInfo(mPageNum
, mTotalPages
);
705 pf
->SetSharedPageData(mPageData
);
707 int32_t printedPageNum
= 1;
708 while (continuePrinting
) {
709 if (PresContext()->IsRootPaginatedDocument()) {
710 if (!mCalledBeginPage
) {
712 PR_PL(("***************** BeginPage *****************\n"));
713 rv
= dc
->BeginPage();
714 NS_ENSURE_SUCCESS(rv
, rv
);
716 mCalledBeginPage
= false;
720 PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf
, mPageNum
));
722 nsRefPtr
<nsRenderingContext
> renderingContext
=
723 dc
->CreateRenderingContext();
725 nsRect
drawingRect(nsPoint(0, 0), currentPage
->GetSize());
726 nsRegion
drawingRegion(drawingRect
);
727 nsLayoutUtils::PaintFrame(renderingContext
, currentPage
,
728 drawingRegion
, NS_RGBA(0,0,0,0),
729 nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES
);
731 if (mSelectionHeight
>= 0 && selectionY
< mSelectionHeight
) {
732 selectionY
+= height
;
734 pf
->SetPageNumInfo(printedPageNum
, mTotalPages
);
735 conFrame
->SetPosition(conFrame
->GetPosition() + nsPoint(0, -height
));
736 nsContainerFrame::PositionChildViews(conFrame
);
738 PR_PL(("***************** End Page (PrintNextPage) *****************\n"));
740 NS_ENSURE_SUCCESS(rv
, rv
);
742 continuePrinting
= false;
750 nsSimplePageSequenceFrame::DoPageEnd()
753 if (PresContext()->IsRootPaginatedDocument() && mPrintThisPage
) {
754 PR_PL(("***************** End Page (DoPageEnd) *****************\n"));
755 rv
= PresContext()->DeviceContext()->EndPage();
756 NS_ENSURE_SUCCESS(rv
, rv
);
759 ResetPrintCanvasList();
766 static gfx::Matrix4x4
767 ComputePageSequenceTransform(nsIFrame
* aFrame
, float aAppUnitsPerPixel
)
769 float scale
= aFrame
->PresContext()->GetPrintPreviewScale();
770 return gfx::Matrix4x4().Scale(scale
, scale
, 1);
774 nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
775 const nsRect
& aDirtyRect
,
776 const nsDisplayListSet
& aLists
)
778 DisplayBorderBackgroundOutline(aBuilder
, aLists
);
780 nsDisplayList content
;
783 // Clear clip state while we construct the children of the
784 // nsDisplayTransform, since they'll be in a different coordinate system.
785 DisplayListClipState::AutoSaveRestore
clipState(aBuilder
);
788 nsIFrame
* child
= GetFirstPrincipalChild();
789 nsRect dirty
= aDirtyRect
;
790 dirty
.ScaleInverseRoundOut(PresContext()->GetPrintPreviewScale());
793 if (child
->GetVisualOverflowRectRelativeToParent().Intersects(dirty
)) {
794 child
->BuildDisplayListForStackingContext(aBuilder
,
795 dirty
- child
->GetPosition(), &content
);
796 aBuilder
->ResetMarkedFramesForDisplayList();
798 child
= child
->GetNextSibling();
802 content
.AppendNewToTop(new (aBuilder
)
803 nsDisplayTransform(aBuilder
, this, &content
, content
.GetVisibleRect(),
804 ::ComputePageSequenceTransform
));
806 aLists
.Content()->AppendToTop(&content
);
810 nsSimplePageSequenceFrame::GetType() const
812 return nsGkAtoms::sequenceFrame
;
815 //------------------------------------------------------------------------------
817 nsSimplePageSequenceFrame::SetPageNumberFormat(const nsAString
& aFormatStr
, bool aForPageNumOnly
)
819 NS_ASSERTION(mPageData
!= nullptr, "mPageData string cannot be null!");
821 if (aForPageNumOnly
) {
822 mPageData
->mPageNumFormat
= aFormatStr
;
824 mPageData
->mPageNumAndTotalsFormat
= aFormatStr
;
828 //------------------------------------------------------------------------------
830 nsSimplePageSequenceFrame::SetDateTimeStr(const nsAString
& aDateTimeStr
)
832 NS_ASSERTION(mPageData
!= nullptr, "mPageData string cannot be null!");
834 mPageData
->mDateTimeStr
= aDateTimeStr
;
837 //------------------------------------------------------------------------------
840 // Return the percentage that the page needs to shrink to
843 nsSimplePageSequenceFrame::GetSTFPercent(float& aSTFPercent
)
845 NS_ENSURE_TRUE(mPageData
, NS_ERROR_UNEXPECTED
);
846 aSTFPercent
= mPageData
->mShrinkToFitRatio
;