1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsReadableUtils.h"
39 #include "nsSimplePageSequence.h"
40 #include "nsPresContext.h"
41 #include "gfxContext.h"
42 #include "nsIRenderingContext.h"
43 #include "nsGkAtoms.h"
44 #include "nsIDeviceContext.h"
45 #include "nsIPresShell.h"
46 #include "nsIFontMetrics.h"
47 #include "nsIPrintSettings.h"
48 #include "nsPageFrame.h"
49 #include "nsStyleConsts.h"
51 #include "nsCSSFrameConstructor.h"
52 #include "nsContentUtils.h"
53 #include "nsDisplayList.h"
56 #include "nsDateTimeFormatCID.h"
58 #define OFFSET_NOT_SET -1
61 #include "nsIPrintSettings.h"
62 #include "nsIPrintOptions.h"
63 #include "nsGfxCIID.h"
64 #include "nsIServiceManager.h"
66 static const char sPrintOptionsContractID
[] = "@mozilla.org/gfx/printsettings-service;1";
72 PRLogModuleInfo
* kLayoutPrintingLogMod
= PR_NewLogModule("printing-layout");
73 #define PR_PL(_p1) PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
78 // This object a shared by all the nsPageFrames
79 // parented to a SimplePageSequenceFrame
80 nsSharedPageData::nsSharedPageData() :
82 mHeadFootFont(nsnull
),
83 mPageNumFormat(nsnull
),
84 mPageNumAndTotalsFormat(nsnull
),
88 mReflowMargin(0,0,0,0),
90 mExtraMargin(0,0,0,0),
91 mEdgePaperMargin(0,0,0,0),
97 nsSharedPageData::~nsSharedPageData()
99 nsMemory::Free(mDateTimeStr
);
100 if (mHeadFootFont
) delete mHeadFootFont
;
101 nsMemory::Free(mPageNumFormat
);
102 nsMemory::Free(mPageNumAndTotalsFormat
);
103 if (mDocTitle
) nsMemory::Free(mDocTitle
);
104 if (mDocURL
) nsMemory::Free(mDocURL
);
108 NS_NewSimplePageSequenceFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
110 return new (aPresShell
) nsSimplePageSequenceFrame(aContext
);
113 nsSimplePageSequenceFrame::nsSimplePageSequenceFrame(nsStyleContext
* aContext
) :
114 nsContainerFrame(aContext
),
116 mSelectionHeight(-1),
119 nscoord halfInch
= PresContext()->TwipsToAppUnits(NS_INCHES_TO_TWIPS(0.5));
120 mMargin
.SizeTo(halfInch
, halfInch
, halfInch
, halfInch
);
122 // XXX Unsafe to assume successful allocation
123 mPageData
= new nsSharedPageData();
124 mPageData
->mHeadFootFont
= new nsFont(*PresContext()->GetDefaultFont(kGenericFont_serif
));
125 mPageData
->mHeadFootFont
->size
= PresContext()->PointsToAppUnits(10);
128 mPageData
->mPrintOptions
= do_GetService(sPrintOptionsContractID
, &rv
);
130 // Doing this here so we only have to go get these formats once
131 SetPageNumberFormat("pagenumber", "%1$d", PR_TRUE
);
132 SetPageNumberFormat("pageofpages", "%1$d of %2$d", PR_FALSE
);
135 nsSimplePageSequenceFrame::~nsSimplePageSequenceFrame()
137 if (mPageData
) delete mPageData
;
141 nsSimplePageSequenceFrame::QueryInterface(const nsIID
& aIID
, void** aInstancePtr
)
143 NS_PRECONDITION(aInstancePtr
, "null out param");
145 if (aIID
.Equals(NS_GET_IID(nsIPageSequenceFrame
))) {
146 *aInstancePtr
= static_cast<nsIPageSequenceFrame
*>(this);
149 return nsContainerFrame::QueryInterface(aIID
, aInstancePtr
);
152 //----------------------------------------------------------------------
154 // Creates a continuing page frame
156 nsSimplePageSequenceFrame::CreateContinuingPageFrame(nsPresContext
* aPresContext
,
157 nsIFrame
* aPageFrame
,
158 nsIFrame
** aContinuingPage
)
160 // Create the continuing frame
161 return aPresContext
->PresShell()->FrameConstructor()->
162 CreateContinuingFrame(aPresContext
, aPageFrame
, this, aContinuingPage
);
166 nsSimplePageSequenceFrame::Reflow(nsPresContext
* aPresContext
,
167 nsHTMLReflowMetrics
& aDesiredSize
,
168 const nsHTMLReflowState
& aReflowState
,
169 nsReflowStatus
& aStatus
)
171 NS_PRECONDITION(aPresContext
->IsRootPaginatedDocument(),
172 "A Page Sequence is only for real pages");
173 DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
174 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
175 NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
177 aStatus
= NS_FRAME_COMPLETE
; // we're always complete
179 // Don't do incremental reflow until we've taught tables how to do
180 // it right in paginated mode.
181 if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW
)) {
182 // Return our desired size
183 aDesiredSize
.height
= mSize
.height
;
184 aDesiredSize
.width
= mSize
.width
;
185 aDesiredSize
.mOverflowArea
= nsRect(0, 0, aDesiredSize
.width
,
186 aDesiredSize
.height
);
187 FinishAndStoreOverflow(&aDesiredSize
);
191 PRBool isPrintPreview
=
192 aPresContext
->Type() == nsPresContext::eContext_PrintPreview
;
194 // See if we can get a Print Settings from the Context
195 if (!mPageData
->mPrintSettings
&&
196 aPresContext
->Medium() == nsGkAtoms::print
) {
197 mPageData
->mPrintSettings
= aPresContext
->GetPrintSettings();
200 // now get out margins & edges
201 if (mPageData
->mPrintSettings
) {
202 nsMargin unwriteableTwips
;
203 mPageData
->mPrintSettings
->GetUnwriteableMarginInTwips(unwriteableTwips
);
204 NS_ASSERTION(unwriteableTwips
.left
>= 0 && unwriteableTwips
.top
>= 0 &&
205 unwriteableTwips
.right
>= 0 && unwriteableTwips
.bottom
>= 0,
206 "Unwriteable twips should be non-negative");
208 nsMargin marginTwips
;
209 mPageData
->mPrintSettings
->GetMarginInTwips(marginTwips
);
210 mMargin
= aPresContext
->TwipsToAppUnits(marginTwips
+ unwriteableTwips
);
213 mPageData
->mPrintSettings
->GetPrintRange(&printType
);
214 mPrintRangeType
= printType
;
217 mPageData
->mPrintSettings
->GetEdgeInTwips(edgeTwips
);
219 // sanity check the values. three inches are sometimes needed
220 nscoord inchInTwips
= NS_INCHES_TO_TWIPS(3.0);
221 edgeTwips
.top
= PR_MIN(PR_MAX(edgeTwips
.top
, 0), inchInTwips
);
222 edgeTwips
.bottom
= PR_MIN(PR_MAX(edgeTwips
.bottom
, 0), inchInTwips
);
223 edgeTwips
.left
= PR_MIN(PR_MAX(edgeTwips
.left
, 0), inchInTwips
);
224 edgeTwips
.right
= PR_MIN(PR_MAX(edgeTwips
.right
, 0), inchInTwips
);
226 mPageData
->mEdgePaperMargin
=
227 aPresContext
->TwipsToAppUnits(edgeTwips
+ unwriteableTwips
);
230 // *** Special Override ***
231 // If this is a sub-sdoc (meaning it doesn't take the whole page)
232 // and if this Document is in the upper left hand corner
233 // we need to suppress the top margin or it will reflow too small
235 nsSize pageSize
= aPresContext
->GetPageSize();
237 mPageData
->mReflowSize
= pageSize
;
238 // If we're printing a selection, we need to reflow with
239 // unconstrained height, to make sure we'll get to the selection
240 // even if it's beyond the first page of content.
241 if (nsIPrintSettings::kRangeSelection
== mPrintRangeType
) {
242 mPageData
->mReflowSize
.height
= NS_UNCONSTRAINEDSIZE
;
244 mPageData
->mReflowMargin
= mMargin
;
246 // Compute the size of each page and the x coordinate that each page will
248 nscoord extraThreshold
= PR_MAX(pageSize
.width
, pageSize
.height
)/10;
249 PRInt32 gapInTwips
= nsContentUtils::GetIntPref("print.print_extra_margin");
250 gapInTwips
= PR_MAX(0, gapInTwips
);
252 nscoord extraGap
= aPresContext
->TwipsToAppUnits(gapInTwips
);
253 extraGap
= PR_MIN(extraGap
, extraThreshold
); // clamp to 1/10 of the largest dim of the page
255 nscoord deadSpaceGap
= 0;
256 if (isPrintPreview
) {
257 GetDeadSpaceValue(&gapInTwips
);
258 deadSpaceGap
= aPresContext
->TwipsToAppUnits(gapInTwips
);
261 nsMargin
extraMargin(0,0,0,0);
262 nsSize
shadowSize(0,0);
263 if (aPresContext
->IsScreen()) {
264 extraMargin
.SizeTo(extraGap
, extraGap
, extraGap
, extraGap
);
265 nscoord fourPixels
= nsPresContext::CSSPixelsToAppUnits(4);
266 shadowSize
.SizeTo(fourPixels
, fourPixels
);
269 mPageData
->mShadowSize
= shadowSize
;
270 mPageData
->mExtraMargin
= extraMargin
;
272 const nscoord x
= deadSpaceGap
;
273 nscoord y
= deadSpaceGap
;// Running y-offset for each page
275 nsSize
availSize(pageSize
.width
+ shadowSize
.width
+ extraMargin
.LeftRight(),
276 pageSize
.height
+ shadowSize
.height
+
277 extraMargin
.TopBottom());
279 // Tile the pages vertically
280 nsHTMLReflowMetrics kidSize
;
281 for (nsIFrame
* kidFrame
= mFrames
.FirstChild(); nsnull
!= kidFrame
; ) {
282 // Set the shared data into the page frame before reflow
283 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(kidFrame
);
284 pf
->SetSharedPageData(mPageData
);
287 nsHTMLReflowState
kidReflowState(aPresContext
, aReflowState
, kidFrame
,
289 nsReflowStatus status
;
291 kidReflowState
.SetComputedWidth(kidReflowState
.availableWidth
);
292 //kidReflowState.SetComputedHeight(kidReflowState.availableHeight);
293 PR_PL(("AV W: %d H: %d\n", kidReflowState
.availableWidth
, kidReflowState
.availableHeight
));
295 // Place and size the page. If the page is narrower than our
296 // max width then center it horizontally
297 ReflowChild(kidFrame
, aPresContext
, kidSize
, kidReflowState
, x
, y
, 0, status
);
299 FinishReflowChild(kidFrame
, aPresContext
, nsnull
, kidSize
, x
, y
, 0);
302 // Leave a slight gap between the pages
305 // Is the page complete?
306 nsIFrame
* kidNextInFlow
= kidFrame
->GetNextInFlow();
308 if (NS_FRAME_IS_FULLY_COMPLETE(status
)) {
309 NS_ASSERTION(nsnull
== kidNextInFlow
, "bad child flow list");
310 } else if (nsnull
== kidNextInFlow
) {
311 // The page isn't complete and it doesn't have a next-in-flow, so
312 // create a continuing page
313 nsIFrame
* continuingPage
;
314 nsresult rv
= CreateContinuingPageFrame(aPresContext
, kidFrame
,
320 // Add it to our child list
321 kidFrame
->SetNextSibling(continuingPage
);
325 kidFrame
= kidFrame
->GetNextSibling();
328 // Get Total Page Count
331 for (page
= mFrames
.FirstChild(); page
; page
= page
->GetNextSibling()) {
335 // Set Page Number Info
337 for (page
= mFrames
.FirstChild(); page
; page
= page
->GetNextSibling()) {
338 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(page
);
340 pf
->SetPageNumInfo(pageNum
, pageTot
);
345 // Create current Date/Time String
347 mDateFormatter
= do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID
);
349 NS_ENSURE_TRUE(mDateFormatter
, NS_ERROR_FAILURE
);
351 nsAutoString formattedDateString
;
354 if (NS_SUCCEEDED(mDateFormatter
->FormatTime(nsnull
/* nsILocale* locale */,
356 kTimeFormatNoSeconds
,
358 formattedDateString
))) {
359 PRUnichar
* uStr
= ToNewUnicode(formattedDateString
);
360 SetDateTimeStr(uStr
); // memory will be freed
364 // Return our desired size
365 // Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the
367 aDesiredSize
.height
= y
* PresContext()->GetPrintPreviewScale(); // includes page heights and dead space
368 aDesiredSize
.width
= (x
+ availSize
.width
+ deadSpaceGap
) * PresContext()->GetPrintPreviewScale();
370 aDesiredSize
.mOverflowArea
= nsRect(0, 0, aDesiredSize
.width
,
371 aDesiredSize
.height
);
372 FinishAndStoreOverflow(&aDesiredSize
);
374 // cache the size so we can set the desired size
375 // for the other reflows that happen
376 mSize
.width
= aDesiredSize
.width
;
377 mSize
.height
= aDesiredSize
.height
;
379 NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus
);
380 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
384 //----------------------------------------------------------------------
388 nsSimplePageSequenceFrame::GetFrameName(nsAString
& aResult
) const
390 return MakeFrameName(NS_LITERAL_STRING("SimplePageSequence"), aResult
);
394 //====================================================================
396 //====================================================================
398 nsSimplePageSequenceFrame::GetCurrentPageNum(PRInt32
* aPageNum
)
400 NS_ENSURE_ARG_POINTER(aPageNum
);
402 *aPageNum
= mPageNum
;
407 nsSimplePageSequenceFrame::GetNumPages(PRInt32
* aNumPages
)
409 NS_ENSURE_ARG_POINTER(aNumPages
);
411 *aNumPages
= mTotalPages
;
416 nsSimplePageSequenceFrame::IsDoingPrintRange(PRBool
* aDoing
)
418 NS_ENSURE_ARG_POINTER(aDoing
);
420 *aDoing
= mDoingPageRange
;
425 nsSimplePageSequenceFrame::GetPrintRange(PRInt32
* aFromPage
, PRInt32
* aToPage
)
427 NS_ENSURE_ARG_POINTER(aFromPage
);
428 NS_ENSURE_ARG_POINTER(aToPage
);
430 *aFromPage
= mFromPageNum
;
431 *aToPage
= mToPageNum
;
437 nsSimplePageSequenceFrame::SetPageNumberFormat(const char* aPropName
, const char* aDefPropVal
, PRBool aPageNumOnly
)
439 // Doing this here so we only have to go get these formats once
440 nsXPIDLString pageNumberFormat
;
441 // Now go get the Localized Page Formating String
443 nsContentUtils::GetLocalizedString(nsContentUtils::ePRINTING_PROPERTIES
,
444 aPropName
, pageNumberFormat
);
445 if (NS_FAILED(rv
)) { // back stop formatting
446 pageNumberFormat
.AssignASCII(aDefPropVal
);
449 // Sets the format into a static data member which will own the memory and free it
450 PRUnichar
* uStr
= ToNewUnicode(pageNumberFormat
);
451 if (uStr
!= nsnull
) {
452 SetPageNumberFormat(uStr
, aPageNumOnly
); // nsPageFrame will own the memory
458 nsSimplePageSequenceFrame::StartPrint(nsPresContext
* aPresContext
,
459 nsIPrintSettings
* aPrintSettings
,
460 PRUnichar
* aDocTitle
,
463 NS_ENSURE_ARG_POINTER(aPresContext
);
464 NS_ENSURE_ARG_POINTER(aPrintSettings
);
466 if (!mPageData
->mPrintSettings
) {
467 mPageData
->mPrintSettings
= aPrintSettings
;
470 // Only set them if they are not null
471 if (aDocTitle
) mPageData
->mDocTitle
= aDocTitle
;
472 if (aDocURL
) mPageData
->mDocURL
= aDocURL
;
474 aPrintSettings
->GetStartPageRange(&mFromPageNum
);
475 aPrintSettings
->GetEndPageRange(&mToPageNum
);
477 mDoingPageRange
= nsIPrintSettings::kRangeSpecifiedPageRange
== mPrintRangeType
||
478 nsIPrintSettings::kRangeSelection
== mPrintRangeType
;
480 // If printing a range of pages make sure at least the starting page
482 PRInt32 totalPages
= mFrames
.GetLength();
484 if (mDoingPageRange
) {
485 if (mFromPageNum
> totalPages
) {
486 return NS_ERROR_INVALID_ARG
;
490 // Begin printing of the document
493 // Determine if we are rendering only the selection
494 aPresContext
->SetIsRenderingOnlySelection(nsIPrintSettings::kRangeSelection
== mPrintRangeType
);
497 if (mDoingPageRange
) {
498 // XXX because of the hack for making the selection all print on one page
499 // we must make sure that the page is sized correctly before printing.
500 nscoord height
= aPresContext
->GetPageSize().height
;
503 nscoord y
= 0;//mMargin.top;
505 for (nsIFrame
* page
= mFrames
.FirstChild(); page
;
506 page
= page
->GetNextSibling()) {
507 if (pageNum
>= mFromPageNum
&& pageNum
<= mToPageNum
) {
508 nsRect rect
= page
->GetRect();
510 rect
.height
= height
;
512 y
+= rect
.height
+ mMargin
.top
+ mMargin
.bottom
;
517 // adjust total number of pages
518 if (nsIPrintSettings::kRangeSelection
!= mPrintRangeType
) {
519 totalPages
= pageNum
- 1;
524 mCurrentPageFrame
= mFrames
.FirstChild();
526 if (mTotalPages
== -1) {
527 mTotalPages
= totalPages
;
534 nsSimplePageSequenceFrame::PrintNextPage()
536 // Print each specified page
537 // pageNum keeps track of the current page and what pages are printing
539 // printedPageNum keeps track of the current page number to be printed
540 // Note: When print al the pages or a page range the printed page shows the
541 // actual page number, when printing selection it prints the page number starting
542 // with the first page of the selection. For example if the user has a
543 // selection that starts on page 2 and ends on page 3, the page numbers when
544 // print are 1 and then two (which is different than printing a page range, where
545 // the page numbers would have been 2 and then 3)
547 if (mCurrentPageFrame
== nsnull
) {
548 return NS_ERROR_FAILURE
;
551 PRBool printEvenPages
, printOddPages
;
552 mPageData
->mPrintSettings
->GetPrintOptions(nsIPrintSettings::kPrintEvenPages
, &printEvenPages
);
553 mPageData
->mPrintSettings
->GetPrintOptions(nsIPrintSettings::kPrintOddPages
, &printOddPages
);
555 // Begin printing of the document
556 nsIDeviceContext
*dc
= PresContext()->DeviceContext();
560 // See whether we should print this page
561 mPrintThisPage
= PR_TRUE
;
563 // If printing a range of pages check whether the page number is in the
564 // range of pages to print
565 if (mDoingPageRange
) {
566 if (mPageNum
< mFromPageNum
) {
567 mPrintThisPage
= PR_FALSE
;
568 } else if (mPageNum
> mToPageNum
) {
570 mCurrentPageFrame
= nsnull
;
575 // Check for printing of odd and even pages
576 if (mPageNum
& 0x1) {
577 if (!printOddPages
) {
578 mPrintThisPage
= PR_FALSE
; // don't print odd numbered page
581 if (!printEvenPages
) {
582 mPrintThisPage
= PR_FALSE
; // don't print even numbered page
586 if (nsIPrintSettings::kRangeSelection
== mPrintRangeType
) {
587 mPrintThisPage
= PR_TRUE
;
590 if (mPrintThisPage
) {
591 // XXX This is temporary fix for printing more than one page of a selection
592 // This does a poor man's "dump" pagination (see Bug 89353)
593 // It has laid out as one long page and now we are just moving or view up/down
594 // one page at a time and printing the contents of what is exposed by the rect.
595 // currently this does not work for IFrames
596 // I will soon improve this to work with IFrames
597 PRBool continuePrinting
= PR_TRUE
;
598 nscoord width
, height
;
599 width
= PresContext()->GetPageSize().width
;
600 height
= PresContext()->GetPageSize().height
;
601 height
-= mMargin
.top
+ mMargin
.bottom
;
602 width
-= mMargin
.left
+ mMargin
.right
;
603 nscoord selectionY
= height
;
604 nsIFrame
* conFrame
= mCurrentPageFrame
->GetFirstChild(nsnull
);
605 if (mSelectionHeight
>= 0) {
606 conFrame
->SetPosition(conFrame
->GetPosition() + nsPoint(0, -mYSelOffset
));
607 nsContainerFrame::PositionChildViews(conFrame
);
610 // cast the frame to be a page frame
611 nsPageFrame
* pf
= static_cast<nsPageFrame
*>(mCurrentPageFrame
);
612 pf
->SetPageNumInfo(mPageNum
, mTotalPages
);
613 pf
->SetSharedPageData(mPageData
);
615 PRInt32 printedPageNum
= 1;
616 while (continuePrinting
) {
617 if (PresContext()->IsRootPaginatedDocument()) {
619 PR_PL(("***************** BeginPage *****************\n"));
620 rv
= dc
->BeginPage();
621 NS_ENSURE_SUCCESS(rv
, rv
);
624 PR_PL(("SeqFr::Paint -> %p PageNo: %d", pf
, mPageNum
));
626 nsCOMPtr
<nsIRenderingContext
> renderingContext
;
627 PresContext()->PresShell()->
628 CreateRenderingContext(mCurrentPageFrame
,
629 getter_AddRefs(renderingContext
));
631 #if defined(XP_UNIX) && !defined(XP_MACOSX)
632 // On linux, need to rotate landscape-mode output on printed surfaces
634 mPageData
->mPrintSettings
->GetOrientation(&orientation
);
635 if (nsIPrintSettings::kLandscapeOrientation
== orientation
) {
636 // Shift up by one landscape-page-height (in points) before we rotate.
637 float offset
= POINTS_PER_INCH_FLOAT
*
638 (mCurrentPageFrame
->GetSize().height
/ float(dc
->AppUnitsPerInch()));
639 renderingContext
->ThebesContext()->Translate(gfxPoint(offset
, 0));
640 renderingContext
->ThebesContext()->Rotate(M_PI
/2);
642 #endif // XP_UNIX && !XP_MACOSX
644 nsRect
drawingRect(nsPoint(0, 0),
645 mCurrentPageFrame
->GetSize());
646 nsRegion
drawingRegion(drawingRect
);
647 nsLayoutUtils::PaintFrame(renderingContext
, mCurrentPageFrame
,
648 drawingRegion
, NS_RGBA(0,0,0,0));
650 if (mSelectionHeight
>= 0 && selectionY
< mSelectionHeight
) {
651 selectionY
+= height
;
653 pf
->SetPageNumInfo(printedPageNum
, mTotalPages
);
654 conFrame
->SetPosition(conFrame
->GetPosition() + nsPoint(0, -height
));
655 nsContainerFrame::PositionChildViews(conFrame
);
657 PR_PL(("***************** End Page (PrintNextPage) *****************\n"));
659 NS_ENSURE_SUCCESS(rv
, rv
);
661 continuePrinting
= PR_FALSE
;
669 nsSimplePageSequenceFrame::DoPageEnd()
672 if (PresContext()->IsRootPaginatedDocument() && mPrintThisPage
) {
673 PR_PL(("***************** End Page (DoPageEnd) *****************\n"));
674 rv
= PresContext()->DeviceContext()->EndPage();
675 NS_ENSURE_SUCCESS(rv
, rv
);
680 if (mCurrentPageFrame
) {
681 mCurrentPageFrame
= mCurrentPageFrame
->GetNextSibling();
687 static void PaintPageSequence(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
688 const nsRect
& aDirtyRect
, nsPoint aPt
)
690 static_cast<nsSimplePageSequenceFrame
*>(aFrame
)->PaintPageSequence(*aCtx
, aDirtyRect
, aPt
);
693 //------------------------------------------------------------------------------
695 nsSimplePageSequenceFrame::PaintPageSequence(nsIRenderingContext
& aRenderingContext
,
696 const nsRect
& aDirtyRect
,
698 nsRect rect
= aDirtyRect
;
699 float scale
= PresContext()->GetPrintPreviewScale();
700 aRenderingContext
.PushState();
701 nsPoint framePos
= aPt
;
702 aRenderingContext
.Translate(framePos
.x
, framePos
.y
);
704 aRenderingContext
.Scale(scale
, scale
);
705 rect
.ScaleRoundOut(1.0f
/ scale
);
707 // Now the rect and the rendering coordinates are are relative to this frame.
708 // Loop over the pages and paint them.
709 nsIFrame
* child
= GetFirstChild(nsnull
);
711 nsPoint pt
= child
->GetPosition();
712 // The rendering context has to be translated before each call to PaintFrame
713 aRenderingContext
.PushState();
714 aRenderingContext
.Translate(pt
.x
, pt
.y
);
715 nsLayoutUtils::PaintFrame(&aRenderingContext
, child
,
716 nsRegion(rect
- pt
), NS_RGBA(0,0,0,0));
717 aRenderingContext
.PopState();
718 child
= child
->GetNextSibling();
721 aRenderingContext
.PopState();
725 nsSimplePageSequenceFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
726 const nsRect
& aDirtyRect
,
727 const nsDisplayListSet
& aLists
)
729 nsresult rv
= DisplayBorderBackgroundOutline(aBuilder
, aLists
);
730 NS_ENSURE_SUCCESS(rv
, rv
);
732 rv
= aLists
.Content()->AppendNewToTop(new (aBuilder
)
733 nsDisplayGeneric(this, ::PaintPageSequence
, "PageSequence"));
734 NS_ENSURE_SUCCESS(rv
, rv
);
740 nsSimplePageSequenceFrame::GetType() const
742 return nsGkAtoms::sequenceFrame
;
745 //------------------------------------------------------------------------------
747 nsSimplePageSequenceFrame::SetPageNumberFormat(PRUnichar
* aFormatStr
, PRBool aForPageNumOnly
)
749 NS_ASSERTION(aFormatStr
!= nsnull
, "Format string cannot be null!");
750 NS_ASSERTION(mPageData
!= nsnull
, "mPageData string cannot be null!");
752 if (aForPageNumOnly
) {
753 if (mPageData
->mPageNumFormat
!= nsnull
) {
754 nsMemory::Free(mPageData
->mPageNumFormat
);
756 mPageData
->mPageNumFormat
= aFormatStr
;
758 if (mPageData
->mPageNumAndTotalsFormat
!= nsnull
) {
759 nsMemory::Free(mPageData
->mPageNumAndTotalsFormat
);
761 mPageData
->mPageNumAndTotalsFormat
= aFormatStr
;
765 //------------------------------------------------------------------------------
767 nsSimplePageSequenceFrame::SetDateTimeStr(PRUnichar
* aDateTimeStr
)
769 NS_ASSERTION(aDateTimeStr
!= nsnull
, "DateTime string cannot be null!");
770 NS_ASSERTION(mPageData
!= nsnull
, "mPageData string cannot be null!");
772 if (mPageData
->mDateTimeStr
!= nsnull
) {
773 nsMemory::Free(mPageData
->mDateTimeStr
);
775 mPageData
->mDateTimeStr
= aDateTimeStr
;
778 //------------------------------------------------------------------------------
781 // Return the percentage that the page needs to shrink to
784 nsSimplePageSequenceFrame::GetSTFPercent(float& aSTFPercent
)
786 NS_ENSURE_TRUE(mPageData
, NS_ERROR_UNEXPECTED
);
788 if (mPageData
&& (mPageData
->mPageContentXMost
> mPageData
->mPageContentSize
)) {
789 aSTFPercent
= float(mPageData
->mPageContentSize
) / float(mPageData
->mPageContentXMost
);