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 "nsPageFrame.h"
7 #include "nsPresContext.h"
8 #include "nsRenderingContext.h"
10 #include "nsIPresShell.h"
11 #include "nsPageContentFrame.h"
12 #include "nsDisplayList.h"
13 #include "nsLayoutUtils.h" // for function BinarySearchForPosition
14 #include "nsSimplePageSequenceFrame.h" // for nsSharedPageData
15 #include "nsTextFormatter.h" // for page number localization formatting
16 #include "nsBidiUtils.h"
17 #include "nsIPrintSettings.h"
21 extern PRLogModuleInfo
*GetLayoutPrintingLog();
22 #define PR_PL(_p1) PR_LOG(GetLayoutPrintingLog(), PR_LOG_DEBUG, _p1)
27 using namespace mozilla
;
30 NS_NewPageFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
32 return new (aPresShell
) nsPageFrame(aContext
);
35 NS_IMPL_FRAMEARENA_HELPERS(nsPageFrame
)
37 nsPageFrame::nsPageFrame(nsStyleContext
* aContext
)
38 : nsContainerFrame(aContext
)
42 nsPageFrame::~nsPageFrame()
47 nsPageFrame::Reflow(nsPresContext
* aPresContext
,
48 nsHTMLReflowMetrics
& aDesiredSize
,
49 const nsHTMLReflowState
& aReflowState
,
50 nsReflowStatus
& aStatus
)
52 DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
53 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
54 aStatus
= NS_FRAME_COMPLETE
; // initialize out parameter
56 NS_ASSERTION(mFrames
.FirstChild() &&
57 nsGkAtoms::pageContentFrame
== mFrames
.FirstChild()->GetType(),
58 "pageFrame must have a pageContentFrame child");
60 // Resize our frame allowing it only to be as big as we are
61 // XXX Pay attention to the page's border and padding...
62 if (mFrames
.NotEmpty()) {
63 nsIFrame
* frame
= mFrames
.FirstChild();
64 // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing
65 // a single page to print selection. So this means we want to use
66 // NS_UNCONSTRAINEDSIZE without altering it
68 if (mPD
->mReflowSize
.height
== NS_UNCONSTRAINEDSIZE
) {
69 avHeight
= NS_UNCONSTRAINEDSIZE
;
71 avHeight
= mPD
->mReflowSize
.height
;
73 nsSize
maxSize(mPD
->mReflowSize
.width
, avHeight
);
74 float scale
= aPresContext
->GetPageScale();
75 maxSize
.width
= NSToCoordCeil(maxSize
.width
/ scale
);
76 if (maxSize
.height
!= NS_UNCONSTRAINEDSIZE
) {
77 maxSize
.height
= NSToCoordCeil(maxSize
.height
/ scale
);
79 // Get the number of Twips per pixel from the PresContext
80 nscoord onePixelInTwips
= nsPresContext::CSSPixelsToAppUnits(1);
81 // insurance against infinite reflow, when reflowing less than a pixel
82 // XXX Shouldn't we do something more friendly when invalid margins
84 if (maxSize
.width
< onePixelInTwips
|| maxSize
.height
< onePixelInTwips
) {
85 aDesiredSize
.ClearSize();
86 NS_WARNING("Reflow aborted; no space for content");
90 nsHTMLReflowState
kidReflowState(aPresContext
, aReflowState
, frame
,
91 LogicalSize(frame
->GetWritingMode(),
93 kidReflowState
.mFlags
.mIsTopOfPage
= true;
94 kidReflowState
.mFlags
.mTableIsSplittable
= true;
96 // Use the margins given in the @page rule.
97 // If a margin is 'auto', use the margin from the print settings for that side.
98 nsMargin pageContentMargin
;
99 const nsStyleSides
& marginStyle
= kidReflowState
.mStyleMargin
->mMargin
;
100 NS_FOR_CSS_SIDES(side
) {
101 if (marginStyle
.GetUnit(side
) == eStyleUnit_Auto
) {
102 pageContentMargin
.Side(side
) = mPD
->mReflowMargin
.Side(side
);
104 pageContentMargin
.Side(side
) = kidReflowState
.ComputedPhysicalMargin().Side(side
);
109 nscoord maxWidth
= maxSize
.width
- pageContentMargin
.LeftRight() / scale
;
111 if (maxSize
.height
== NS_UNCONSTRAINEDSIZE
) {
112 maxHeight
= NS_UNCONSTRAINEDSIZE
;
114 maxHeight
= maxSize
.height
- pageContentMargin
.TopBottom() / scale
;
117 // Check the width and height, if they're too small we reset the margins
118 // back to the default.
119 if (maxWidth
< onePixelInTwips
||
120 (maxHeight
!= NS_UNCONSTRAINEDSIZE
&& maxHeight
< onePixelInTwips
)) {
121 NS_FOR_CSS_SIDES(side
) {
122 pageContentMargin
.Side(side
) = mPD
->mReflowMargin
.Side(side
);
124 maxWidth
= maxSize
.width
- pageContentMargin
.LeftRight() / scale
;
125 if (maxHeight
!= NS_UNCONSTRAINEDSIZE
) {
126 maxHeight
= maxSize
.height
- pageContentMargin
.TopBottom() / scale
;
130 kidReflowState
.SetComputedWidth(maxWidth
);
131 kidReflowState
.SetComputedHeight(maxHeight
);
133 // calc location of frame
134 nscoord xc
= pageContentMargin
.left
;
135 nscoord yc
= pageContentMargin
.top
;
137 // Get the child's desired size
138 ReflowChild(frame
, aPresContext
, aDesiredSize
, kidReflowState
, xc
, yc
, 0, aStatus
);
140 // Place and size the child
141 FinishReflowChild(frame
, aPresContext
, aDesiredSize
, &kidReflowState
, xc
, yc
, 0);
143 NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus
) ||
144 !frame
->GetNextInFlow(), "bad child flow list");
146 PR_PL(("PageFrame::Reflow %p ", this));
147 PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize
.Width(), aDesiredSize
.Height(),
148 aReflowState
.AvailableWidth(), aReflowState
.AvailableHeight()));
150 // Return our desired size
151 WritingMode wm
= aReflowState
.GetWritingMode();
152 aDesiredSize
.ISize(wm
) = aReflowState
.AvailableISize();
153 if (aReflowState
.AvailableBSize() != NS_UNCONSTRAINEDSIZE
) {
154 aDesiredSize
.BSize(wm
) = aReflowState
.AvailableBSize();
157 aDesiredSize
.SetOverflowAreasToDesiredBounds();
158 FinishAndStoreOverflow(&aDesiredSize
);
160 PR_PL(("PageFrame::Reflow %p ", this));
161 PR_PL(("[%d,%d]\n", aReflowState
.AvailableWidth(), aReflowState
.AvailableHeight()));
163 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
167 nsPageFrame::GetType() const
169 return nsGkAtoms::pageFrame
;
172 #ifdef DEBUG_FRAME_DUMP
174 nsPageFrame::GetFrameName(nsAString
& aResult
) const
176 return MakeFrameName(NS_LITERAL_STRING("Page"), aResult
);
181 nsPageFrame::ProcessSpecialCodes(const nsString
& aStr
, nsString
& aNewStr
)
186 // Search to see if the &D code is in the string
187 // then subst in the current date/time
188 NS_NAMED_LITERAL_STRING(kDate
, "&D");
189 if (aStr
.Find(kDate
) != kNotFound
) {
190 aNewStr
.ReplaceSubstring(kDate
.get(), mPD
->mDateTimeStr
.get());
193 // NOTE: Must search for &PT before searching for &P
195 // Search to see if the "page number and page" total code are in the string
196 // and replace the page number and page total code with the actual
198 NS_NAMED_LITERAL_STRING(kPageAndTotal
, "&PT");
199 if (aStr
.Find(kPageAndTotal
) != kNotFound
) {
200 char16_t
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumAndTotalsFormat
.get(), mPageNum
, mTotNumPages
);
201 aNewStr
.ReplaceSubstring(kPageAndTotal
.get(), uStr
);
202 nsMemory::Free(uStr
);
205 // Search to see if the page number code is in the string
206 // and replace the page number code with the actual value
207 NS_NAMED_LITERAL_STRING(kPage
, "&P");
208 if (aStr
.Find(kPage
) != kNotFound
) {
209 char16_t
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumFormat
.get(), mPageNum
);
210 aNewStr
.ReplaceSubstring(kPage
.get(), uStr
);
211 nsMemory::Free(uStr
);
214 NS_NAMED_LITERAL_STRING(kTitle
, "&T");
215 if (aStr
.Find(kTitle
) != kNotFound
) {
216 aNewStr
.ReplaceSubstring(kTitle
.get(), mPD
->mDocTitle
.get());
219 NS_NAMED_LITERAL_STRING(kDocURL
, "&U");
220 if (aStr
.Find(kDocURL
) != kNotFound
) {
221 aNewStr
.ReplaceSubstring(kDocURL
.get(), mPD
->mDocURL
.get());
224 NS_NAMED_LITERAL_STRING(kPageTotal
, "&L");
225 if (aStr
.Find(kPageTotal
) != kNotFound
) {
226 char16_t
* uStr
= nsTextFormatter::smprintf(mPD
->mPageNumFormat
.get(), mTotNumPages
);
227 aNewStr
.ReplaceSubstring(kPageTotal
.get(), uStr
);
228 nsMemory::Free(uStr
);
233 //------------------------------------------------------------------------------
234 nscoord
nsPageFrame::GetXPosition(nsRenderingContext
& aRenderingContext
,
237 const nsString
& aStr
)
239 nscoord width
= nsLayoutUtils::GetStringWidth(this, &aRenderingContext
,
240 aStr
.get(), aStr
.Length());
244 case nsIPrintSettings::kJustLeft
:
245 x
+= mPD
->mEdgePaperMargin
.left
;
248 case nsIPrintSettings::kJustCenter
:
249 x
+= (aRect
.width
- width
) / 2;
252 case nsIPrintSettings::kJustRight
:
253 x
+= aRect
.width
- width
- mPD
->mEdgePaperMargin
.right
;
260 // Draw a header or footer
261 // @param aRenderingContext - rendering content ot draw into
262 // @param aHeaderFooter - indicates whether it is a header or footer
263 // @param aStrLeft - string for the left header or footer; can be empty
264 // @param aStrCenter - string for the center header or footer; can be empty
265 // @param aStrRight - string for the right header or footer; can be empty
266 // @param aRect - the rect of the page
267 // @param aAscent - the ascent of the font
268 // @param aHeight - the height of the font
270 nsPageFrame::DrawHeaderFooter(nsRenderingContext
& aRenderingContext
,
271 nsHeaderFooterEnum aHeaderFooter
,
272 const nsString
& aStrLeft
,
273 const nsString
& aStrCenter
,
274 const nsString
& aStrRight
,
280 if (!aStrLeft
.IsEmpty()) numStrs
++;
281 if (!aStrCenter
.IsEmpty()) numStrs
++;
282 if (!aStrRight
.IsEmpty()) numStrs
++;
284 if (numStrs
== 0) return;
285 nscoord strSpace
= aRect
.width
/ numStrs
;
287 if (!aStrLeft
.IsEmpty()) {
288 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
289 nsIPrintSettings::kJustLeft
, aStrLeft
, aRect
, aAscent
,
292 if (!aStrCenter
.IsEmpty()) {
293 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
294 nsIPrintSettings::kJustCenter
, aStrCenter
, aRect
, aAscent
,
297 if (!aStrRight
.IsEmpty()) {
298 DrawHeaderFooter(aRenderingContext
, aHeaderFooter
,
299 nsIPrintSettings::kJustRight
, aStrRight
, aRect
, aAscent
,
304 // Draw a header or footer string
305 // @param aRenderingContext - rendering context to draw into
306 // @param aHeaderFooter - indicates whether it is a header or footer
307 // @param aJust - indicates where the string is located within the header/footer
308 // @param aStr - the string to be drawn
309 // @param aRect - the rect of the page
310 // @param aHeight - the height of the font
311 // @param aAscent - the ascent of the font
312 // @param aWidth - available width for the string
314 nsPageFrame::DrawHeaderFooter(nsRenderingContext
& aRenderingContext
,
315 nsHeaderFooterEnum aHeaderFooter
,
317 const nsString
& aStr
,
324 nscoord contentWidth
= aWidth
- (mPD
->mEdgePaperMargin
.left
+ mPD
->mEdgePaperMargin
.right
);
326 if ((aHeaderFooter
== eHeader
&& aHeight
< mPD
->mReflowMargin
.top
) ||
327 (aHeaderFooter
== eFooter
&& aHeight
< mPD
->mReflowMargin
.bottom
)) {
329 ProcessSpecialCodes(aStr
, str
);
332 int32_t textWidth
= 0;
333 const char16_t
* text
= str
.get();
335 int32_t len
= (int32_t)str
.Length();
337 return; // bail is empty string
339 // find how much text fits, the "position" is the size of the available area
340 if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext
, text
, 0, 0, 0, len
,
341 int32_t(contentWidth
), indx
, textWidth
)) {
343 // we can't fit in all the text
345 // But we can fit in at least 4 chars. Show all but 3 of them, then
347 // XXXbz for non-plane0 text, this may be cutting things in the
348 // middle of a codepoint! Also, we have no guarantees that the three
349 // dots will fit in the space the three chars we removed took up with
350 // these font metrics!
351 str
.Truncate(indx
-3);
352 str
.AppendLiteral("...");
354 // We can only fit 3 or fewer chars. Just show nothing
359 return; // bail if couldn't find the correct length
362 if (HasRTLChars(str
)) {
363 PresContext()->SetBidiEnabled();
366 // cacl the x and y positions of the text
367 nscoord x
= GetXPosition(aRenderingContext
, aRect
, aJust
, str
);
369 if (aHeaderFooter
== eHeader
) {
370 y
= aRect
.y
+ mPD
->mEdgePaperMargin
.top
;
372 y
= aRect
.YMost() - aHeight
- mPD
->mEdgePaperMargin
.bottom
;
375 // set up new clip and draw the text
376 aRenderingContext
.PushState();
377 aRenderingContext
.SetColor(NS_RGB(0,0,0));
378 aRenderingContext
.IntersectClip(aRect
);
379 nsLayoutUtils::DrawString(this, &aRenderingContext
, str
.get(), str
.Length(), nsPoint(x
, y
+ aAscent
));
380 aRenderingContext
.PopState();
385 * Remove all leaf display items that are not for descendants of
386 * aBuilder->GetReferenceFrame() from aList.
387 * @param aPage the page we're constructing the display list for
388 * @param aExtraPage the page we constructed aList for
389 * @param aList the list that is modified in-place
392 PruneDisplayListForExtraPage(nsDisplayListBuilder
* aBuilder
,
393 nsPageFrame
* aPage
, nsIFrame
* aExtraPage
,
394 nsDisplayList
* aList
)
396 nsDisplayList newList
;
399 nsDisplayItem
* i
= aList
->RemoveBottom();
402 nsDisplayList
* subList
= i
->GetSameCoordinateSystemChildren();
404 PruneDisplayListForExtraPage(aBuilder
, aPage
, aExtraPage
, subList
);
405 i
->UpdateBounds(aBuilder
);
407 nsIFrame
* f
= i
->Frame();
408 if (!nsLayoutUtils::IsProperAncestorFrameCrossDoc(aPage
, f
)) {
409 // We're throwing this away so call its destructor now. The memory
410 // is owned by aBuilder which destroys all items at once.
415 newList
.AppendToTop(i
);
417 aList
->AppendToTop(&newList
);
421 BuildDisplayListForExtraPage(nsDisplayListBuilder
* aBuilder
,
422 nsPageFrame
* aPage
, nsIFrame
* aExtraPage
,
423 const nsRect
& aDirtyRect
, nsDisplayList
* aList
)
425 // The only content in aExtraPage we care about is out-of-flow content whose
426 // placeholders have occurred in aPage. If
427 // NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO is not set, then aExtraPage has
429 if (!aExtraPage
->HasAnyStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO
)) {
433 aExtraPage
->BuildDisplayListForStackingContext(aBuilder
, aDirtyRect
, &list
);
434 PruneDisplayListForExtraPage(aBuilder
, aPage
, aExtraPage
, &list
);
435 aList
->AppendToTop(&list
);
439 GetNextPage(nsIFrame
* aPageContentFrame
)
442 nsIFrame
* pageFrame
= aPageContentFrame
->GetParent();
443 NS_ASSERTION(pageFrame
->GetType() == nsGkAtoms::pageFrame
,
444 "pageContentFrame has unexpected parent");
445 nsIFrame
* nextPageFrame
= pageFrame
->GetNextSibling();
448 NS_ASSERTION(nextPageFrame
->GetType() == nsGkAtoms::pageFrame
,
449 "pageFrame's sibling is not a page frame...");
450 nsIFrame
* f
= nextPageFrame
->GetFirstPrincipalChild();
451 NS_ASSERTION(f
, "pageFrame has no page content frame!");
452 NS_ASSERTION(f
->GetType() == nsGkAtoms::pageContentFrame
,
453 "pageFrame's child is not page content!");
457 static void PaintHeaderFooter(nsIFrame
* aFrame
, nsRenderingContext
* aCtx
,
458 const nsRect
& aDirtyRect
, nsPoint aPt
)
460 static_cast<nsPageFrame
*>(aFrame
)->PaintHeaderFooter(*aCtx
, aPt
);
463 static gfx::Matrix4x4
ComputePageTransform(nsIFrame
* aFrame
, float aAppUnitsPerPixel
)
465 float scale
= aFrame
->PresContext()->GetPageScale();
466 return gfx::Matrix4x4().Scale(scale
, scale
, 1);
469 //------------------------------------------------------------------------------
471 nsPageFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
472 const nsRect
& aDirtyRect
,
473 const nsDisplayListSet
& aLists
)
475 nsDisplayListCollection set
;
477 if (PresContext()->IsScreen()) {
478 DisplayBorderBackgroundOutline(aBuilder
, aLists
);
481 nsIFrame
*child
= mFrames
.FirstChild();
482 float scale
= PresContext()->GetPageScale();
483 nsRect
clipRect(nsPoint(0, 0), child
->GetSize());
484 // Note: this computation matches how we compute maxSize.height
485 // in nsPageFrame::Reflow
486 nscoord expectedPageContentHeight
= NSToCoordCeil(GetSize().height
/ scale
);
487 if (clipRect
.height
> expectedPageContentHeight
) {
488 // We're doing print-selection, with one long page-content frame.
489 // Clip to the appropriate page-content slice for the current page.
490 NS_ASSERTION(mPageNum
> 0, "page num should be positive");
491 // Note: The pageContentFrame's y-position has been set such that a zero
492 // y-value matches the top edge of the current page. So, to clip to the
493 // current page's content (in coordinates *relative* to the page content
494 // frame), we just negate its y-position and add the top margin.
495 clipRect
.y
= NSToCoordCeil((-child
->GetRect().y
+
496 mPD
->mReflowMargin
.top
) / scale
);
497 clipRect
.height
= expectedPageContentHeight
;
498 NS_ASSERTION(clipRect
.y
< child
->GetSize().height
,
499 "Should be clipping to region inside the page content bounds");
501 clipRect
+= aBuilder
->ToReferenceFrame(child
);
503 nsDisplayList content
;
505 DisplayListClipState::AutoSaveRestore
clipState(aBuilder
);
507 // Overwrite current clip, since we're going to wrap in a transform
508 // and the current clip is no longer meaningful.
510 clipState
.ClipContainingBlockDescendants(clipRect
, nullptr);
512 nsRect dirtyRect
= child
->GetVisualOverflowRectRelativeToSelf();
513 child
->BuildDisplayListForStackingContext(aBuilder
, dirtyRect
, &content
);
515 // We may need to paint out-of-flow frames whose placeholders are
516 // on other pages. Add those pages to our display list. Note that
517 // out-of-flow frames can't be placed after their placeholders so
518 // we don't have to process earlier pages. The display lists for
519 // these extra pages are pruned so that only display items for the
520 // page we currently care about (which we would have reached by
521 // following placeholders to their out-of-flows) end up on the list.
522 nsIFrame
* page
= child
;
523 while ((page
= GetNextPage(page
)) != nullptr) {
524 BuildDisplayListForExtraPage(aBuilder
, this, page
,
525 dirtyRect
+ child
->GetOffsetTo(page
), &content
);
528 // Invoke AutoBuildingDisplayList to ensure that the correct dirtyRect
529 // is used to compute the visible rect if AddCanvasBackgroundColorItem
530 // creates a display item.
531 nsDisplayListBuilder::AutoBuildingDisplayList
532 building(aBuilder
, child
, dirtyRect
, true);
534 // Add the canvas background color to the bottom of the list. This
535 // happens after we've built the list so that AddCanvasBackgroundColorItem
536 // can monkey with the contents if necessary.
537 nsRect backgroundRect
=
538 nsRect(aBuilder
->ToReferenceFrame(child
), child
->GetSize());
539 PresContext()->GetPresShell()->AddCanvasBackgroundColorItem(
540 *aBuilder
, content
, child
, backgroundRect
, NS_RGBA(0,0,0,0));
543 content
.AppendNewToTop(new (aBuilder
) nsDisplayTransform(aBuilder
, child
,
544 &content
, content
.GetVisibleRect(), ::ComputePageTransform
));
546 set
.Content()->AppendToTop(&content
);
548 if (PresContext()->IsRootPaginatedDocument()) {
549 set
.Content()->AppendNewToTop(new (aBuilder
)
550 nsDisplayGeneric(aBuilder
, this, ::PaintHeaderFooter
,
552 nsDisplayItem::TYPE_HEADER_FOOTER
));
558 //------------------------------------------------------------------------------
560 nsPageFrame::SetPageNumInfo(int32_t aPageNumber
, int32_t aTotalPages
)
562 mPageNum
= aPageNumber
;
563 mTotNumPages
= aTotalPages
;
568 nsPageFrame::PaintHeaderFooter(nsRenderingContext
& aRenderingContext
,
571 nsPresContext
* pc
= PresContext();
573 if (!mPD
->mPrintSettings
) {
574 if (pc
->Type() == nsPresContext::eContext_PrintPreview
|| pc
->IsDynamic())
575 mPD
->mPrintSettings
= pc
->GetPrintSettings();
576 if (!mPD
->mPrintSettings
)
580 nsRect
rect(aPt
, mRect
.Size());
581 aRenderingContext
.SetColor(NS_RGB(0,0,0));
583 // Get the FontMetrics to determine width.height of strings
584 nsRefPtr
<nsFontMetrics
> fontMet
;
585 pc
->DeviceContext()->GetMetricsFor(mPD
->mHeadFootFont
, nullptr,
586 pc
->GetUserFontSet(),
587 pc
->GetTextPerfMetrics(),
588 *getter_AddRefs(fontMet
));
590 aRenderingContext
.SetFont(fontMet
);
593 nscoord visibleHeight
= 0;
595 visibleHeight
= fontMet
->MaxHeight();
596 ascent
= fontMet
->MaxAscent();
599 // print document headers and footers
600 nsXPIDLString headerLeft
, headerCenter
, headerRight
;
601 mPD
->mPrintSettings
->GetHeaderStrLeft(getter_Copies(headerLeft
));
602 mPD
->mPrintSettings
->GetHeaderStrCenter(getter_Copies(headerCenter
));
603 mPD
->mPrintSettings
->GetHeaderStrRight(getter_Copies(headerRight
));
604 DrawHeaderFooter(aRenderingContext
, eHeader
,
605 headerLeft
, headerCenter
, headerRight
,
606 rect
, ascent
, visibleHeight
);
608 nsXPIDLString footerLeft
, footerCenter
, footerRight
;
609 mPD
->mPrintSettings
->GetFooterStrLeft(getter_Copies(footerLeft
));
610 mPD
->mPrintSettings
->GetFooterStrCenter(getter_Copies(footerCenter
));
611 mPD
->mPrintSettings
->GetFooterStrRight(getter_Copies(footerRight
));
612 DrawHeaderFooter(aRenderingContext
, eFooter
,
613 footerLeft
, footerCenter
, footerRight
,
614 rect
, ascent
, visibleHeight
);
618 nsPageFrame::SetSharedPageData(nsSharedPageData
* aPD
)
621 // Set the shared data into the page frame before reflow
622 nsPageContentFrame
* pcf
= static_cast<nsPageContentFrame
*>(mFrames
.FirstChild());
624 pcf
->SetSharedPageData(mPD
);
630 NS_NewPageBreakFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
632 NS_PRECONDITION(aPresShell
, "null PresShell");
633 //check that we are only creating page break frames when printing
634 NS_ASSERTION(aPresShell
->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
636 return new (aPresShell
) nsPageBreakFrame(aContext
);
639 NS_IMPL_FRAMEARENA_HELPERS(nsPageBreakFrame
)
641 nsPageBreakFrame::nsPageBreakFrame(nsStyleContext
* aContext
) :
642 nsLeafFrame(aContext
), mHaveReflowed(false)
646 nsPageBreakFrame::~nsPageBreakFrame()
651 nsPageBreakFrame::GetIntrinsicISize()
653 return nsPresContext::CSSPixelsToAppUnits(1);
657 nsPageBreakFrame::GetIntrinsicBSize()
663 nsPageBreakFrame::Reflow(nsPresContext
* aPresContext
,
664 nsHTMLReflowMetrics
& aDesiredSize
,
665 const nsHTMLReflowState
& aReflowState
,
666 nsReflowStatus
& aStatus
)
668 DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
669 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
671 // Override reflow, since we don't want to deal with what our
672 // computed values are.
673 WritingMode wm
= aReflowState
.GetWritingMode();
674 LogicalSize
finalSize(wm
, GetIntrinsicISize(),
675 aReflowState
.AvailableBSize() == NS_UNCONSTRAINEDSIZE
?
676 0 : aReflowState
.AvailableBSize());
677 // round the height down to the nearest pixel
678 finalSize
.BSize(wm
) -=
679 finalSize
.BSize(wm
) % nsPresContext::CSSPixelsToAppUnits(1);
680 aDesiredSize
.SetSize(wm
, finalSize
);
682 // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
683 // DidReflow will always get called before the next Reflow() call.
684 mHaveReflowed
= true;
685 aStatus
= NS_FRAME_COMPLETE
;
689 nsPageBreakFrame::GetType() const
691 return nsGkAtoms::pageBreakFrame
;
694 #ifdef DEBUG_FRAME_DUMP
696 nsPageBreakFrame::GetFrameName(nsAString
& aResult
) const
698 return MakeFrameName(NS_LITERAL_STRING("PageBreak"), aResult
);