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 "nsPageFrame.h"
39 #include "nsPresContext.h"
40 #include "nsStyleContext.h"
41 #include "nsIRenderingContext.h"
42 #include "nsGkAtoms.h"
43 #include "nsIPresShell.h"
44 #include "nsCSSFrameConstructor.h"
45 #include "nsIDeviceContext.h"
46 #include "nsReadableUtils.h"
47 #include "nsPageContentFrame.h"
48 #include "nsDisplayList.h"
49 #include "nsLayoutUtils.h" // for function BinarySearchForPosition
50 #include "nsCSSRendering.h"
51 #include "nsSimplePageSequence.h" // for nsSharedPageData
52 #include "nsTextFormatter.h" // for page number localization formatting
54 #include "nsBidiUtils.h"
56 #include "nsIFontMetrics.h"
57 #include "nsIPrintSettings.h"
62 extern PRLogModuleInfo
* kLayoutPrintingLogMod
;
63 #define PR_PL(_p1) PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
69 NS_NewPageFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
71 return new (aPresShell
) nsPageFrame(aContext
);
74 NS_IMPL_FRAMEARENA_HELPERS(nsPageFrame
)
76 nsPageFrame::nsPageFrame(nsStyleContext
* aContext
)
77 : nsContainerFrame(aContext
)
81 nsPageFrame::~nsPageFrame()
85 NS_IMETHODIMP
nsPageFrame::Reflow(nsPresContext
* aPresContext
,
86 nsHTMLReflowMetrics
& aDesiredSize
,
87 const nsHTMLReflowState
& aReflowState
,
88 nsReflowStatus
& aStatus
)
90 DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
91 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
92 aStatus
= NS_FRAME_COMPLETE
; // initialize out parameter
94 NS_ASSERTION(mFrames
.FirstChild() &&
95 nsGkAtoms::pageContentFrame
== mFrames
.FirstChild()->GetType(),
96 "pageFrame must have a pageContentFrame child");
98 // Resize our frame allowing it only to be as big as we are
99 // XXX Pay attention to the page's border and padding...
100 if (mFrames
.NotEmpty()) {
101 nsIFrame
* frame
= mFrames
.FirstChild();
102 // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing
103 // a single page to print selection. So this means we want to use
104 // NS_UNCONSTRAINEDSIZE without altering it
106 if (mPD
->mReflowSize
.height
== NS_UNCONSTRAINEDSIZE
) {
107 avHeight
= NS_UNCONSTRAINEDSIZE
;
109 avHeight
= mPD
->mReflowSize
.height
- mPD
->mReflowMargin
.TopBottom();
111 nsSize
maxSize(mPD
->mReflowSize
.width
- mPD
->mReflowMargin
.LeftRight(),
113 float scale
= aPresContext
->GetPageScale();
114 maxSize
.width
= NSToCoordCeil(maxSize
.width
/ scale
);
115 if (maxSize
.height
!= NS_UNCONSTRAINEDSIZE
) {
116 maxSize
.height
= NSToCoordCeil(maxSize
.height
/ scale
);
118 // Get the number of Twips per pixel from the PresContext
119 nscoord onePixelInTwips
= nsPresContext::CSSPixelsToAppUnits(1);
120 // insurance against infinite reflow, when reflowing less than a pixel
121 // XXX Shouldn't we do something more friendly when invalid margins
123 if (maxSize
.width
< onePixelInTwips
|| maxSize
.height
< onePixelInTwips
) {
124 aDesiredSize
.width
= 0;
125 aDesiredSize
.height
= 0;
126 NS_WARNING("Reflow aborted; no space for content");
130 nsHTMLReflowState
kidReflowState(aPresContext
, aReflowState
, frame
, maxSize
);
131 kidReflowState
.mFlags
.mIsTopOfPage
= PR_TRUE
;
132 kidReflowState
.mFlags
.mTableIsSplittable
= PR_TRUE
;
134 // calc location of frame
135 nscoord xc
= mPD
->mReflowMargin
.left
+ mPD
->mExtraMargin
.left
;
136 nscoord yc
= mPD
->mReflowMargin
.top
+ mPD
->mExtraMargin
.top
;
138 // Get the child's desired size
139 ReflowChild(frame
, aPresContext
, aDesiredSize
, kidReflowState
, xc
, yc
, 0, aStatus
);
141 // Place and size the child
142 FinishReflowChild(frame
, aPresContext
, &kidReflowState
, aDesiredSize
, xc
, yc
, 0);
144 NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus
) ||
145 !frame
->GetNextInFlow(), "bad child flow list");
147 PR_PL(("PageFrame::Reflow %p ", this));
148 PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize
.width
, aDesiredSize
.height
, aReflowState
.availableWidth
, aReflowState
.availableHeight
));
150 // Return our desired size
151 aDesiredSize
.width
= aReflowState
.availableWidth
;
152 if (aReflowState
.availableHeight
!= NS_UNCONSTRAINEDSIZE
) {
153 aDesiredSize
.height
= aReflowState
.availableHeight
;
155 PR_PL(("PageFrame::Reflow %p ", this));
156 PR_PL(("[%d,%d]\n", aReflowState
.availableWidth
, aReflowState
.availableHeight
));
158 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
163 nsPageFrame::GetType() const
165 return nsGkAtoms::pageFrame
;
170 nsPageFrame::GetFrameName(nsAString
& aResult
) const
172 return MakeFrameName(NS_LITERAL_STRING("Page"), aResult
);
177 nsPageFrame::IsContainingBlock() const
183 nsPageFrame::ProcessSpecialCodes(const nsString
& aStr
, nsString
& aNewStr
)
188 // Search to see if the &D code is in the string
189 // then subst in the current date/time
190 NS_NAMED_LITERAL_STRING(kDate
, "&D");
191 if (aStr
.Find(kDate
) != kNotFound
) {
192 if (mPD
->mDateTimeStr
!= nsnull
) {
193 aNewStr
.ReplaceSubstring(kDate
.get(), mPD
->mDateTimeStr
);
195 aNewStr
.ReplaceSubstring(kDate
.get(), EmptyString().get());
199 // NOTE: Must search for &PT before searching for &P
201 // Search to see if the "page number and page" total code are in the string
202 // and replace the page number and page total code with the actual
204 NS_NAMED_LITERAL_STRING(kPageAndTotal
, "&PT");
205 if (aStr
.Find(kPageAndTotal
) != kNotFound
) {
206 PRUnichar
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumAndTotalsFormat
, mPageNum
, mTotNumPages
);
207 aNewStr
.ReplaceSubstring(kPageAndTotal
.get(), uStr
);
208 nsMemory::Free(uStr
);
211 // Search to see if the page number code is in the string
212 // and replace the page number code with the actual value
213 NS_NAMED_LITERAL_STRING(kPage
, "&P");
214 if (aStr
.Find(kPage
) != kNotFound
) {
215 PRUnichar
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumFormat
, mPageNum
);
216 aNewStr
.ReplaceSubstring(kPage
.get(), uStr
);
217 nsMemory::Free(uStr
);
220 NS_NAMED_LITERAL_STRING(kTitle
, "&T");
221 if (aStr
.Find(kTitle
) != kNotFound
) {
222 if (mPD
->mDocTitle
!= nsnull
) {
223 aNewStr
.ReplaceSubstring(kTitle
.get(), mPD
->mDocTitle
);
225 aNewStr
.ReplaceSubstring(kTitle
.get(), EmptyString().get());
229 NS_NAMED_LITERAL_STRING(kDocURL
, "&U");
230 if (aStr
.Find(kDocURL
) != kNotFound
) {
231 if (mPD
->mDocURL
!= nsnull
) {
232 aNewStr
.ReplaceSubstring(kDocURL
.get(), mPD
->mDocURL
);
234 aNewStr
.ReplaceSubstring(kDocURL
.get(), EmptyString().get());
238 NS_NAMED_LITERAL_STRING(kPageTotal
, "&L");
239 if (aStr
.Find(kPageTotal
) != kNotFound
) {
240 PRUnichar
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumFormat
, mTotNumPages
);
241 aNewStr
.ReplaceSubstring(kPageTotal
.get(), uStr
);
242 nsMemory::Free(uStr
);
247 //------------------------------------------------------------------------------
248 nscoord
nsPageFrame::GetXPosition(nsIRenderingContext
& aRenderingContext
,
251 const nsString
& aStr
)
253 nscoord width
= nsLayoutUtils::GetStringWidth(this, &aRenderingContext
,
254 aStr
.get(), aStr
.Length());
258 case nsIPrintSettings::kJustLeft
:
259 x
+= mPD
->mExtraMargin
.left
+ mPD
->mEdgePaperMargin
.left
;
262 case nsIPrintSettings::kJustCenter
:
263 x
+= (aRect
.width
- width
) / 2;
266 case nsIPrintSettings::kJustRight
:
267 x
+= aRect
.width
- width
- mPD
->mExtraMargin
.right
- mPD
->mEdgePaperMargin
.right
;
274 // Draw a header or footer
275 // @param aRenderingContext - rendering content ot draw into
276 // @param aHeaderFooter - indicates whether it is a header or footer
277 // @param aStrLeft - string for the left header or footer; can be empty
278 // @param aStrCenter - string for the center header or footer; can be empty
279 // @param aStrRight - string for the right header or footer; can be empty
280 // @param aRect - the rect of the page
281 // @param aAscent - the ascent of the font
282 // @param aHeight - the height of the font
284 nsPageFrame::DrawHeaderFooter(nsIRenderingContext
& aRenderingContext
,
285 nsHeaderFooterEnum aHeaderFooter
,
286 const nsString
& aStrLeft
,
287 const nsString
& aStrCenter
,
288 const nsString
& aStrRight
,
294 if (!aStrLeft
.IsEmpty()) numStrs
++;
295 if (!aStrCenter
.IsEmpty()) numStrs
++;
296 if (!aStrRight
.IsEmpty()) numStrs
++;
298 if (numStrs
== 0) return;
299 nscoord strSpace
= aRect
.width
/ numStrs
;
301 if (!aStrLeft
.IsEmpty()) {
302 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
303 nsIPrintSettings::kJustLeft
, aStrLeft
, aRect
, aAscent
,
306 if (!aStrCenter
.IsEmpty()) {
307 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
308 nsIPrintSettings::kJustCenter
, aStrCenter
, aRect
, aAscent
,
311 if (!aStrRight
.IsEmpty()) {
312 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
313 nsIPrintSettings::kJustRight
, aStrRight
, aRect
, aAscent
,
318 // Draw a header or footer string
319 // @param aRenderingContext - rendering context to draw into
320 // @param aHeaderFooter - indicates whether it is a header or footer
321 // @param aJust - indicates where the string is located within the header/footer
322 // @param aStr - the string to be drawn
323 // @param aRect - the rect of the page
324 // @param aHeight - the height of the font
325 // @param aAscent - the ascent of the font
326 // @param aWidth - available width for the string
328 nsPageFrame::DrawHeaderFooter(nsIRenderingContext
& aRenderingContext
,
329 nsHeaderFooterEnum aHeaderFooter
,
331 const nsString
& aStr
,
338 nscoord contentWidth
= aWidth
- (mPD
->mEdgePaperMargin
.left
+ mPD
->mEdgePaperMargin
.right
);
340 if ((aHeaderFooter
== eHeader
&& aHeight
< mPD
->mReflowMargin
.top
) ||
341 (aHeaderFooter
== eFooter
&& aHeight
< mPD
->mReflowMargin
.bottom
)) {
343 ProcessSpecialCodes(aStr
, str
);
346 PRInt32 textWidth
= 0;
347 const PRUnichar
* text
= str
.get();
349 PRInt32 len
= (PRInt32
)str
.Length();
351 return; // bail is empty string
353 // find how much text fits, the "position" is the size of the available area
354 if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext
, text
, 0, 0, 0, len
,
355 PRInt32(contentWidth
), indx
, textWidth
)) {
357 // we can't fit in all the text
359 // But we can fit in at least 4 chars. Show all but 3 of them, then
361 // XXXbz for non-plane0 text, this may be cutting things in the
362 // middle of a codepoint! Also, we have no guarantees that the three
363 // dots will fit in the space the three chars we removed took up with
364 // these font metrics!
365 str
.Truncate(indx
-3);
366 str
.AppendLiteral("...");
368 // We can only fit 3 or fewer chars. Just show nothing
373 return; // bail if couldn't find the correct length
376 if (HasRTLChars(str
)) {
377 PresContext()->SetBidiEnabled();
380 // cacl the x and y positions of the text
381 nscoord x
= GetXPosition(aRenderingContext
, aRect
, aJust
, str
);
383 if (aHeaderFooter
== eHeader
) {
384 y
= aRect
.y
+ mPD
->mExtraMargin
.top
+ mPD
->mEdgePaperMargin
.top
;
386 y
= aRect
.YMost() - aHeight
- mPD
->mExtraMargin
.bottom
- mPD
->mEdgePaperMargin
.bottom
;
389 // set up new clip and draw the text
390 aRenderingContext
.PushState();
391 aRenderingContext
.SetColor(NS_RGB(0,0,0));
392 aRenderingContext
.SetClipRect(aRect
, nsClipCombine_kIntersect
);
393 nsLayoutUtils::DrawString(this, &aRenderingContext
, str
.get(), str
.Length(), nsPoint(x
, y
+ aAscent
));
394 aRenderingContext
.PopState();
398 static void PaintPrintPreviewBackground(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
399 const nsRect
& aDirtyRect
, nsPoint aPt
)
401 static_cast<nsPageFrame
*>(aFrame
)->PaintPrintPreviewBackground(*aCtx
, aPt
);
404 static void PaintPageContent(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
405 const nsRect
& aDirtyRect
, nsPoint aPt
)
407 static_cast<nsPageFrame
*>(aFrame
)->PaintPageContent(*aCtx
, aDirtyRect
, aPt
);
410 static void PaintHeaderFooter(nsIFrame
* aFrame
, nsIRenderingContext
* aCtx
,
411 const nsRect
& aDirtyRect
, nsPoint aPt
)
413 static_cast<nsPageFrame
*>(aFrame
)->PaintHeaderFooter(*aCtx
, aPt
);
416 //------------------------------------------------------------------------------
418 nsPageFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
419 const nsRect
& aDirtyRect
,
420 const nsDisplayListSet
& aLists
)
422 nsDisplayListCollection set
;
425 if (PresContext()->IsScreen()) {
426 rv
= set
.BorderBackground()->AppendNewToTop(new (aBuilder
)
427 nsDisplayGeneric(aBuilder
, this, ::PaintPrintPreviewBackground
,
428 "PrintPreviewBackground",
429 nsDisplayItem::TYPE_PRINT_PREVIEW_BACKGROUND
));
430 NS_ENSURE_SUCCESS(rv
, rv
);
433 rv
= set
.BorderBackground()->AppendNewToTop(new (aBuilder
)
434 nsDisplayGeneric(aBuilder
, this, ::PaintPageContent
,
436 nsDisplayItem::TYPE_PAGE_CONTENT
));
437 NS_ENSURE_SUCCESS(rv
, rv
);
439 if (PresContext()->IsRootPaginatedDocument()) {
440 rv
= set
.Content()->AppendNewToTop(new (aBuilder
)
441 nsDisplayGeneric(aBuilder
, this, ::PaintHeaderFooter
,
443 nsDisplayItem::TYPE_HEADER_FOOTER
));
444 NS_ENSURE_SUCCESS(rv
, rv
);
451 //------------------------------------------------------------------------------
453 nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber
, PRInt32 aTotalPages
)
455 mPageNum
= aPageNumber
;
456 mTotNumPages
= aTotalPages
;
461 nsPageFrame::PaintPrintPreviewBackground(nsIRenderingContext
& aRenderingContext
,
464 // fill page with White
465 aRenderingContext
.SetColor(NS_RGB(255,255,255));
466 // REVIEW: this used to have rect's width and height be the
467 // mClipRect if specialClipIsSet ... but that seems completely bogus
468 // and inconsistent with the painting of the shadow below
469 nsRect
rect(aPt
, GetSize());
470 rect
.width
-= mPD
->mShadowSize
.width
;
471 rect
.height
-= mPD
->mShadowSize
.height
;
472 aRenderingContext
.FillRect(rect
);
473 // draw line around outside of page
474 aRenderingContext
.SetColor(NS_RGB(0,0,0));
475 aRenderingContext
.DrawRect(rect
);
477 if (mPD
->mShadowSize
.width
> 0 && mPD
->mShadowSize
.height
> 0) {
478 aRenderingContext
.SetColor(NS_RGB(51,51,51));
479 nsRect
r(aPt
.x
,aPt
.y
, mRect
.width
, mRect
.height
);
481 shadowRect
.x
= r
.x
+ r
.width
- mPD
->mShadowSize
.width
;
482 shadowRect
.y
= r
.y
+ mPD
->mShadowSize
.height
;
483 shadowRect
.width
= mPD
->mShadowSize
.width
;
484 shadowRect
.height
= r
.height
- mPD
->mShadowSize
.height
;
485 aRenderingContext
.FillRect(shadowRect
);
487 shadowRect
.x
= r
.x
+ mPD
->mShadowSize
.width
;
488 shadowRect
.y
= r
.y
+ r
.height
- mPD
->mShadowSize
.height
;
489 shadowRect
.width
= r
.width
- mPD
->mShadowSize
.width
;
490 shadowRect
.height
= mPD
->mShadowSize
.height
;
491 aRenderingContext
.FillRect(shadowRect
);
496 nsPageFrame::PaintHeaderFooter(nsIRenderingContext
& aRenderingContext
,
499 nsPresContext
* pc
= PresContext();
501 if (!mPD
->mPrintSettings
) {
502 if (pc
->Type() == nsPresContext::eContext_PrintPreview
|| pc
->IsDynamic())
503 mPD
->mPrintSettings
= pc
->GetPrintSettings();
504 if (!mPD
->mPrintSettings
)
508 nsRect
rect(aPt
.x
, aPt
.y
, mRect
.width
- mPD
->mShadowSize
.width
,
509 mRect
.height
- mPD
->mShadowSize
.height
);
511 aRenderingContext
.SetColor(NS_RGB(0,0,0));
513 // Get the FontMetrics to determine width.height of strings
514 nsCOMPtr
<nsIFontMetrics
> fontMet
;
515 pc
->DeviceContext()->GetMetricsFor(*mPD
->mHeadFootFont
,
516 pc
->GetUserFontSet(),
517 *getter_AddRefs(fontMet
));
519 aRenderingContext
.SetFont(fontMet
);
522 nscoord visibleHeight
= 0;
524 fontMet
->GetHeight(visibleHeight
);
525 fontMet
->GetMaxAscent(ascent
);
528 // print document headers and footers
529 nsXPIDLString headerLeft
, headerCenter
, headerRight
;
530 mPD
->mPrintSettings
->GetHeaderStrLeft(getter_Copies(headerLeft
));
531 mPD
->mPrintSettings
->GetHeaderStrCenter(getter_Copies(headerCenter
));
532 mPD
->mPrintSettings
->GetHeaderStrRight(getter_Copies(headerRight
));
533 DrawHeaderFooter(aRenderingContext
, eHeader
,
534 headerLeft
, headerCenter
, headerRight
,
535 rect
, ascent
, visibleHeight
);
537 nsXPIDLString footerLeft
, footerCenter
, footerRight
;
538 mPD
->mPrintSettings
->GetFooterStrLeft(getter_Copies(footerLeft
));
539 mPD
->mPrintSettings
->GetFooterStrCenter(getter_Copies(footerCenter
));
540 mPD
->mPrintSettings
->GetFooterStrRight(getter_Copies(footerRight
));
541 DrawHeaderFooter(aRenderingContext
, eFooter
,
542 footerLeft
, footerCenter
, footerRight
,
543 rect
, ascent
, visibleHeight
);
546 //------------------------------------------------------------------------------
548 nsPageFrame::PaintPageContent(nsIRenderingContext
& aRenderingContext
,
549 const nsRect
& aDirtyRect
,
551 nsIFrame
* pageContentFrame
= mFrames
.FirstChild();
552 nsRect rect
= aDirtyRect
;
553 float scale
= PresContext()->GetPageScale();
554 aRenderingContext
.PushState();
555 nsPoint framePos
= aPt
+ pageContentFrame
->GetOffsetTo(this);
556 aRenderingContext
.Translate(framePos
.x
, framePos
.y
);
557 // aPt translates to coords relative to this, then margins translate to
558 // pageContentFrame's coords
560 aRenderingContext
.Scale(scale
, scale
);
561 rect
.ScaleRoundOut(1.0f
/ scale
);
562 // Make sure we don't draw where we aren't supposed to draw, especially
563 // when printing selection
564 nsRect
clipRect(nsPoint(0, 0), pageContentFrame
->GetSize());
565 // Note: this computation matches how we compute maxSize.height
566 // in nsPageFrame::Reflow
567 nscoord expectedPageContentHeight
=
568 NSToCoordCeil((GetSize().height
- mPD
->mReflowMargin
.TopBottom()) / scale
);
569 if (clipRect
.height
> expectedPageContentHeight
) {
570 // We're doing print-selection, with one long page-content frame.
571 // Clip to the appropriate page-content slice for the current page.
572 NS_ASSERTION(mPageNum
> 0, "page num should be positive");
573 // Note: The pageContentFrame's y-position has been set such that a zero
574 // y-value matches the top edge of the current page. So, to clip to the
575 // current page's content (in coordinates *relative* to the page content
576 // frame), we just negate its y-position and add the top margin.
577 clipRect
.y
= NSToCoordCeil((-pageContentFrame
->GetRect().y
+
578 mPD
->mReflowMargin
.top
) / scale
);
579 clipRect
.height
= expectedPageContentHeight
;
580 NS_ASSERTION(clipRect
.y
< pageContentFrame
->GetSize().height
,
581 "Should be clipping to region inside the page content bounds");
583 aRenderingContext
.SetClipRect(clipRect
, nsClipCombine_kIntersect
);
585 nsRect backgroundRect
= nsRect(nsPoint(0, 0), pageContentFrame
->GetSize());
586 nsCSSRendering::PaintBackground(PresContext(), aRenderingContext
, this,
587 rect
, backgroundRect
,
588 nsCSSRendering::PAINTBG_SYNC_DECODE_IMAGES
);
590 nsLayoutUtils::PaintFrame(&aRenderingContext
, pageContentFrame
,
591 nsRegion(rect
), NS_RGBA(0,0,0,0),
592 nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES
);
594 aRenderingContext
.PopState();
598 nsPageFrame::SetSharedPageData(nsSharedPageData
* aPD
)
601 // Set the shared data into the page frame before reflow
602 nsPageContentFrame
* pcf
= static_cast<nsPageContentFrame
*>(mFrames
.FirstChild());
604 pcf
->SetSharedPageData(mPD
);
610 NS_NewPageBreakFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
612 NS_PRECONDITION(aPresShell
, "null PresShell");
613 //check that we are only creating page break frames when printing
614 NS_ASSERTION(aPresShell
->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
616 return new (aPresShell
) nsPageBreakFrame(aContext
);
619 NS_IMPL_FRAMEARENA_HELPERS(nsPageBreakFrame
)
621 nsPageBreakFrame::nsPageBreakFrame(nsStyleContext
* aContext
) :
622 nsLeafFrame(aContext
), mHaveReflowed(PR_FALSE
)
626 nsPageBreakFrame::~nsPageBreakFrame()
631 nsPageBreakFrame::GetIntrinsicWidth()
633 return nsPresContext::CSSPixelsToAppUnits(1);
637 nsPageBreakFrame::GetIntrinsicHeight()
643 nsPageBreakFrame::Reflow(nsPresContext
* aPresContext
,
644 nsHTMLReflowMetrics
& aDesiredSize
,
645 const nsHTMLReflowState
& aReflowState
,
646 nsReflowStatus
& aStatus
)
648 DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
649 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
651 // Override reflow, since we don't want to deal with what our
652 // computed values are.
653 aDesiredSize
.width
= GetIntrinsicWidth();
654 aDesiredSize
.height
= (aReflowState
.availableHeight
== NS_UNCONSTRAINEDSIZE
?
655 0 : aReflowState
.availableHeight
);
656 // round the height down to the nearest pixel
657 aDesiredSize
.height
-=
658 aDesiredSize
.height
% nsPresContext::CSSPixelsToAppUnits(1);
660 // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
661 // DidReflow will always get called before the next Reflow() call.
662 mHaveReflowed
= PR_TRUE
;
663 aStatus
= NS_FRAME_COMPLETE
;
668 nsPageBreakFrame::GetType() const
670 return nsGkAtoms::pageBreakFrame
;
675 nsPageBreakFrame::GetFrameName(nsAString
& aResult
) const
677 return MakeFrameName(NS_LITERAL_STRING("PageBreak"), aResult
);