Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / layout / generic / nsPageFrame.cpp
blob26455b91dbba07dc5f1f516f32a6a8a461a042da
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
13 * License.
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.
22 * Contributor(s):
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
53 #ifdef IBMBIDI
54 #include "nsBidiUtils.h"
55 #endif
56 #include "nsIFontMetrics.h"
57 #include "nsIPrintSettings.h"
58 #include "nsRegion.h"
60 #include "prlog.h"
61 #ifdef PR_LOGGING
62 extern PRLogModuleInfo * kLayoutPrintingLogMod;
63 #define PR_PL(_p1) PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
64 #else
65 #define PR_PL(_p1)
66 #endif
68 nsIFrame*
69 NS_NewPageFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
71 return new (aPresShell) nsPageFrame(aContext);
74 nsPageFrame::nsPageFrame(nsStyleContext* aContext)
75 : nsContainerFrame(aContext)
79 nsPageFrame::~nsPageFrame()
83 NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext,
84 nsHTMLReflowMetrics& aDesiredSize,
85 const nsHTMLReflowState& aReflowState,
86 nsReflowStatus& aStatus)
88 DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
89 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
90 aStatus = NS_FRAME_COMPLETE; // initialize out parameter
92 NS_ASSERTION(mFrames.FirstChild() &&
93 nsGkAtoms::pageContentFrame == mFrames.FirstChild()->GetType(),
94 "pageFrame must have a pageContentFrame child");
96 // Resize our frame allowing it only to be as big as we are
97 // XXX Pay attention to the page's border and padding...
98 if (mFrames.NotEmpty()) {
99 nsIFrame* frame = mFrames.FirstChild();
100 // When the reflow size is NS_UNCONSTRAINEDSIZE it means we are reflowing
101 // a single page to print selection. So this means we want to use
102 // NS_UNCONSTRAINEDSIZE without altering it
103 nscoord avHeight;
104 if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) {
105 avHeight = NS_UNCONSTRAINEDSIZE;
106 } else {
107 avHeight = mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom();
109 nsSize maxSize(mPD->mReflowSize.width - mPD->mReflowMargin.LeftRight(),
110 avHeight);
111 float scale = aPresContext->GetPageScale();
112 maxSize.width = NSToCoordCeil(maxSize.width / scale);
113 if (maxSize.height != NS_UNCONSTRAINEDSIZE) {
114 maxSize.height = NSToCoordCeil(maxSize.height / scale);
116 // Get the number of Twips per pixel from the PresContext
117 nscoord onePixelInTwips = nsPresContext::CSSPixelsToAppUnits(1);
118 // insurance against infinite reflow, when reflowing less than a pixel
119 // XXX Shouldn't we do something more friendly when invalid margins
120 // are set?
121 if (maxSize.width < onePixelInTwips || maxSize.height < onePixelInTwips) {
122 aDesiredSize.width = 0;
123 aDesiredSize.height = 0;
124 NS_WARNING("Reflow aborted; no space for content");
125 return NS_OK;
128 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
129 kidReflowState.mFlags.mIsTopOfPage = PR_TRUE;
130 kidReflowState.mFlags.mTableIsSplittable = PR_TRUE;
132 // calc location of frame
133 nscoord xc = mPD->mReflowMargin.left + mPD->mExtraMargin.left;
134 nscoord yc = mPD->mReflowMargin.top + mPD->mExtraMargin.top;
136 // Get the child's desired size
137 ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus);
139 // Place and size the child
140 FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, xc, yc, 0);
142 NS_ASSERTION(!NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
143 !frame->GetNextInFlow(), "bad child flow list");
145 PR_PL(("PageFrame::Reflow %p ", this));
146 PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.availableWidth, aReflowState.availableHeight));
148 // Return our desired size
149 aDesiredSize.width = aReflowState.availableWidth;
150 if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
151 aDesiredSize.height = aReflowState.availableHeight;
153 PR_PL(("PageFrame::Reflow %p ", this));
154 PR_PL(("[%d,%d]\n", aReflowState.availableWidth, aReflowState.availableHeight));
156 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
157 return NS_OK;
160 nsIAtom*
161 nsPageFrame::GetType() const
163 return nsGkAtoms::pageFrame;
166 #ifdef DEBUG
167 NS_IMETHODIMP
168 nsPageFrame::GetFrameName(nsAString& aResult) const
170 return MakeFrameName(NS_LITERAL_STRING("Page"), aResult);
172 #endif
174 /* virtual */ PRBool
175 nsPageFrame::IsContainingBlock() const
177 return PR_TRUE;
180 void
181 nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
184 aNewStr = aStr;
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 if (mPD->mDateTimeStr != nsnull) {
191 aNewStr.ReplaceSubstring(kDate.get(), mPD->mDateTimeStr);
192 } else {
193 aNewStr.ReplaceSubstring(kDate.get(), EmptyString().get());
197 // NOTE: Must search for &PT before searching for &P
199 // Search to see if the "page number and page" total code are in the string
200 // and replace the page number and page total code with the actual
201 // values
202 NS_NAMED_LITERAL_STRING(kPageAndTotal, "&PT");
203 if (aStr.Find(kPageAndTotal) != kNotFound) {
204 PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat, mPageNum, mTotNumPages);
205 aNewStr.ReplaceSubstring(kPageAndTotal.get(), uStr);
206 nsMemory::Free(uStr);
209 // Search to see if the page number code is in the string
210 // and replace the page number code with the actual value
211 NS_NAMED_LITERAL_STRING(kPage, "&P");
212 if (aStr.Find(kPage) != kNotFound) {
213 PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mPageNum);
214 aNewStr.ReplaceSubstring(kPage.get(), uStr);
215 nsMemory::Free(uStr);
218 NS_NAMED_LITERAL_STRING(kTitle, "&T");
219 if (aStr.Find(kTitle) != kNotFound) {
220 if (mPD->mDocTitle != nsnull) {
221 aNewStr.ReplaceSubstring(kTitle.get(), mPD->mDocTitle);
222 } else {
223 aNewStr.ReplaceSubstring(kTitle.get(), EmptyString().get());
227 NS_NAMED_LITERAL_STRING(kDocURL, "&U");
228 if (aStr.Find(kDocURL) != kNotFound) {
229 if (mPD->mDocURL != nsnull) {
230 aNewStr.ReplaceSubstring(kDocURL.get(), mPD->mDocURL);
231 } else {
232 aNewStr.ReplaceSubstring(kDocURL.get(), EmptyString().get());
236 NS_NAMED_LITERAL_STRING(kPageTotal, "&L");
237 if (aStr.Find(kPageTotal) != kNotFound) {
238 PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mTotNumPages);
239 aNewStr.ReplaceSubstring(kPageTotal.get(), uStr);
240 nsMemory::Free(uStr);
245 //------------------------------------------------------------------------------
246 nscoord nsPageFrame::GetXPosition(nsIRenderingContext& aRenderingContext,
247 const nsRect& aRect,
248 PRInt32 aJust,
249 const nsString& aStr)
251 nscoord width = nsLayoutUtils::GetStringWidth(this, &aRenderingContext,
252 aStr.get(), aStr.Length());
254 nscoord x = aRect.x;
255 switch (aJust) {
256 case nsIPrintSettings::kJustLeft:
257 x += mPD->mExtraMargin.left + mPD->mEdgePaperMargin.left;
258 break;
260 case nsIPrintSettings::kJustCenter:
261 x += (aRect.width - width) / 2;
262 break;
264 case nsIPrintSettings::kJustRight:
265 x += aRect.width - width - mPD->mExtraMargin.right - mPD->mEdgePaperMargin.right;
266 break;
267 } // switch
269 return x;
272 // Draw a header or footer
273 // @param aRenderingContext - rendering content ot draw into
274 // @param aHeaderFooter - indicates whether it is a header or footer
275 // @param aStrLeft - string for the left header or footer; can be empty
276 // @param aStrCenter - string for the center header or footer; can be empty
277 // @param aStrRight - string for the right header or footer; can be empty
278 // @param aRect - the rect of the page
279 // @param aAscent - the ascent of the font
280 // @param aHeight - the height of the font
281 void
282 nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext,
283 nsHeaderFooterEnum aHeaderFooter,
284 const nsString& aStrLeft,
285 const nsString& aStrCenter,
286 const nsString& aStrRight,
287 const nsRect& aRect,
288 nscoord aAscent,
289 nscoord aHeight)
291 PRInt32 numStrs = 0;
292 if (!aStrLeft.IsEmpty()) numStrs++;
293 if (!aStrCenter.IsEmpty()) numStrs++;
294 if (!aStrRight.IsEmpty()) numStrs++;
296 if (numStrs == 0) return;
297 nscoord strSpace = aRect.width / numStrs;
299 if (!aStrLeft.IsEmpty()) {
300 DrawHeaderFooter(aRenderingContext, aHeaderFooter,
301 nsIPrintSettings::kJustLeft, aStrLeft, aRect, aAscent,
302 aHeight, strSpace);
304 if (!aStrCenter.IsEmpty()) {
305 DrawHeaderFooter(aRenderingContext, aHeaderFooter,
306 nsIPrintSettings::kJustCenter, aStrCenter, aRect, aAscent,
307 aHeight, strSpace);
309 if (!aStrRight.IsEmpty()) {
310 DrawHeaderFooter(aRenderingContext, aHeaderFooter,
311 nsIPrintSettings::kJustRight, aStrRight, aRect, aAscent,
312 aHeight, strSpace);
316 // Draw a header or footer string
317 // @param aRenderingContext - rendering content ot draw into
318 // @param aHeaderFooter - indicates whether it is a header or footer
319 // @param aJust - indicates where the string is located within the header/footer
320 // @param aStr - the string to be drawn
321 // @param aRect - the rect of the page
322 // @param aHeight - the height of the font
323 // @param aAscent - the ascent of the font
324 // @param aWidth - available width for the string
325 void
326 nsPageFrame::DrawHeaderFooter(nsIRenderingContext& aRenderingContext,
327 nsHeaderFooterEnum aHeaderFooter,
328 PRInt32 aJust,
329 const nsString& aStr,
330 const nsRect& aRect,
331 nscoord aAscent,
332 nscoord aHeight,
333 nscoord aWidth)
336 nscoord contentWidth = aWidth - (mPD->mEdgePaperMargin.left + mPD->mEdgePaperMargin.right);
338 if ((aHeaderFooter == eHeader && aHeight < mPD->mReflowMargin.top) ||
339 (aHeaderFooter == eFooter && aHeight < mPD->mReflowMargin.bottom)) {
340 nsAutoString str;
341 ProcessSpecialCodes(aStr, str);
343 PRInt32 indx;
344 PRInt32 textWidth = 0;
345 const PRUnichar* text = str.get();
347 PRInt32 len = (PRInt32)str.Length();
348 if (len == 0) {
349 return; // bail is empty string
351 // find how much text fits, the "position" is the size of the available area
352 if (nsLayoutUtils::BinarySearchForPosition(&aRenderingContext, text, 0, 0, 0, len,
353 PRInt32(contentWidth), indx, textWidth)) {
354 if (indx < len-1 ) {
355 // we can't fit in all the text
356 if (indx > 3) {
357 // But we can fit in at least 4 chars. Show all but 3 of them, then
358 // an ellipsis.
359 // XXXbz for non-plane0 text, this may be cutting things in the
360 // middle of a codepoint! Also, we have no guarantees that the three
361 // dots will fit in the space the three chars we removed took up with
362 // these font metrics!
363 str.Truncate(indx-3);
364 str.AppendLiteral("...");
365 } else {
366 // We can only fit 3 or fewer chars. Just show nothing
367 str.Truncate();
370 } else {
371 return; // bail if couldn't find the correct length
374 if (HasRTLChars(str)) {
375 PresContext()->SetBidiEnabled();
378 // cacl the x and y positions of the text
379 nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
380 nscoord y;
381 if (aHeaderFooter == eHeader) {
382 y = aRect.y + mPD->mExtraMargin.top + mPD->mEdgePaperMargin.top;
383 } else {
384 y = aRect.YMost() - aHeight - mPD->mExtraMargin.bottom - mPD->mEdgePaperMargin.bottom;
387 // set up new clip and draw the text
388 aRenderingContext.PushState();
389 aRenderingContext.SetColor(NS_RGB(0,0,0));
390 aRenderingContext.SetClipRect(aRect, nsClipCombine_kReplace);
391 nsLayoutUtils::DrawString(this, &aRenderingContext, str.get(), str.Length(), nsPoint(x, y + aAscent));
392 aRenderingContext.PopState();
396 static void PaintPrintPreviewBackground(nsIFrame* aFrame, nsIRenderingContext* aCtx,
397 const nsRect& aDirtyRect, nsPoint aPt)
399 static_cast<nsPageFrame*>(aFrame)->PaintPrintPreviewBackground(*aCtx, aPt);
402 static void PaintPageContent(nsIFrame* aFrame, nsIRenderingContext* aCtx,
403 const nsRect& aDirtyRect, nsPoint aPt)
405 static_cast<nsPageFrame*>(aFrame)->PaintPageContent(*aCtx, aDirtyRect, aPt);
408 static void PaintHeaderFooter(nsIFrame* aFrame, nsIRenderingContext* aCtx,
409 const nsRect& aDirtyRect, nsPoint aPt)
411 static_cast<nsPageFrame*>(aFrame)->PaintHeaderFooter(*aCtx, aPt);
414 //------------------------------------------------------------------------------
415 NS_IMETHODIMP
416 nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
417 const nsRect& aDirtyRect,
418 const nsDisplayListSet& aLists)
420 nsDisplayListCollection set;
421 nsresult rv;
423 if (PresContext()->IsScreen()) {
424 rv = set.BorderBackground()->AppendNewToTop(new (aBuilder)
425 nsDisplayGeneric(this, ::PaintPrintPreviewBackground, "PrintPreviewBackground"));
426 NS_ENSURE_SUCCESS(rv, rv);
429 rv = set.BorderBackground()->AppendNewToTop(new (aBuilder)
430 nsDisplayGeneric(this, ::PaintPageContent, "PageContent"));
431 NS_ENSURE_SUCCESS(rv, rv);
433 if (PresContext()->IsRootPaginatedDocument()) {
434 rv = set.Content()->AppendNewToTop(new (aBuilder)
435 nsDisplayGeneric(this, ::PaintHeaderFooter, "HeaderFooter"));
436 NS_ENSURE_SUCCESS(rv, rv);
439 set.MoveTo(aLists);
440 return NS_OK;
443 //------------------------------------------------------------------------------
444 void
445 nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages)
447 mPageNum = aPageNumber;
448 mTotNumPages = aTotalPages;
452 void
453 nsPageFrame::PaintPrintPreviewBackground(nsIRenderingContext& aRenderingContext,
454 nsPoint aPt)
456 // fill page with White
457 aRenderingContext.SetColor(NS_RGB(255,255,255));
458 // REVIEW: this used to have rect's width and height be the
459 // mClipRect if specialClipIsSet ... but that seems completely bogus
460 // and inconsistent with the painting of the shadow below
461 nsRect rect(aPt, GetSize());
462 rect.width -= mPD->mShadowSize.width;
463 rect.height -= mPD->mShadowSize.height;
464 aRenderingContext.FillRect(rect);
465 // draw line around outside of page
466 aRenderingContext.SetColor(NS_RGB(0,0,0));
467 aRenderingContext.DrawRect(rect);
469 if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) {
470 aRenderingContext.SetColor(NS_RGB(51,51,51));
471 nsRect r(aPt.x,aPt.y, mRect.width, mRect.height);
472 nsRect shadowRect;
473 shadowRect.x = r.x + r.width - mPD->mShadowSize.width;
474 shadowRect.y = r.y + mPD->mShadowSize.height;
475 shadowRect.width = mPD->mShadowSize.width;
476 shadowRect.height = r.height - mPD->mShadowSize.height;
477 aRenderingContext.FillRect(shadowRect);
479 shadowRect.x = r.x + mPD->mShadowSize.width;
480 shadowRect.y = r.y + r.height - mPD->mShadowSize.height;
481 shadowRect.width = r.width - mPD->mShadowSize.width;
482 shadowRect.height = mPD->mShadowSize.height;
483 aRenderingContext.FillRect(shadowRect);
487 void
488 nsPageFrame::PaintHeaderFooter(nsIRenderingContext& aRenderingContext,
489 nsPoint aPt)
491 nsPresContext* pc = PresContext();
493 if (!mPD->mPrintSettings) {
494 if (pc->Type() == nsPresContext::eContext_PrintPreview || pc->IsDynamic())
495 mPD->mPrintSettings = pc->GetPrintSettings();
496 if (!mPD->mPrintSettings)
497 return;
500 nsRect rect(aPt.x, aPt.y, mRect.width - mPD->mShadowSize.width,
501 mRect.height - mPD->mShadowSize.height);
503 aRenderingContext.SetColor(NS_RGB(0,0,0));
505 // Get the FontMetrics to determine width.height of strings
506 nsCOMPtr<nsIFontMetrics> fontMet;
507 pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
508 pc->GetUserFontSet(),
509 *getter_AddRefs(fontMet));
511 aRenderingContext.SetFont(fontMet);
513 nscoord ascent = 0;
514 nscoord visibleHeight = 0;
515 if (fontMet) {
516 fontMet->GetHeight(visibleHeight);
517 fontMet->GetMaxAscent(ascent);
520 // print document headers and footers
521 nsXPIDLString headerLeft, headerCenter, headerRight;
522 mPD->mPrintSettings->GetHeaderStrLeft(getter_Copies(headerLeft));
523 mPD->mPrintSettings->GetHeaderStrCenter(getter_Copies(headerCenter));
524 mPD->mPrintSettings->GetHeaderStrRight(getter_Copies(headerRight));
525 DrawHeaderFooter(aRenderingContext, eHeader,
526 headerLeft, headerCenter, headerRight,
527 rect, ascent, visibleHeight);
529 nsXPIDLString footerLeft, footerCenter, footerRight;
530 mPD->mPrintSettings->GetFooterStrLeft(getter_Copies(footerLeft));
531 mPD->mPrintSettings->GetFooterStrCenter(getter_Copies(footerCenter));
532 mPD->mPrintSettings->GetFooterStrRight(getter_Copies(footerRight));
533 DrawHeaderFooter(aRenderingContext, eFooter,
534 footerLeft, footerCenter, footerRight,
535 rect, ascent, visibleHeight);
538 //------------------------------------------------------------------------------
539 void
540 nsPageFrame::PaintPageContent(nsIRenderingContext& aRenderingContext,
541 const nsRect& aDirtyRect,
542 nsPoint aPt) {
543 nsIFrame* pageContentFrame = mFrames.FirstChild();
544 nsRect rect = aDirtyRect;
545 float scale = PresContext()->GetPageScale();
546 aRenderingContext.PushState();
547 nsPoint framePos = aPt + pageContentFrame->GetOffsetTo(this);
548 aRenderingContext.Translate(framePos.x, framePos.y);
549 // aPt translates to coords relative to this, then margins translate to
550 // pageContentFrame's coords
551 rect -= framePos;
552 aRenderingContext.Scale(scale, scale);
553 rect.ScaleRoundOut(1.0f / scale);
554 // Make sure we don't draw where we aren't supposed to draw, especially
555 // when printing selection
556 nsRect clipRect(nsPoint(0, 0), pageContentFrame->GetSize());
557 // Note: this computation matches how we compute maxSize.height
558 // in nsPageFrame::Reflow
559 nscoord expectedPageContentHeight =
560 NSToCoordCeil((GetSize().height - mPD->mReflowMargin.TopBottom()) / scale);
561 if (clipRect.height > expectedPageContentHeight) {
562 // We're doing print-selection, with one long page-content frame.
563 // Clip to the appropriate page-content slice for the current page.
564 NS_ASSERTION(mPageNum > 0, "page num should be positive");
565 // Note: The pageContentFrame's y-position has been set such that a zero
566 // y-value matches the top edge of the current page. So, to clip to the
567 // current page's content (in coordinates *relative* to the page content
568 // frame), we just negate its y-position and add the top margin.
569 clipRect.y = NSToCoordCeil((-pageContentFrame->GetRect().y +
570 mPD->mReflowMargin.top) / scale);
571 clipRect.height = expectedPageContentHeight;
572 NS_ASSERTION(clipRect.y < pageContentFrame->GetSize().height,
573 "Should be clipping to region inside the page content bounds");
575 aRenderingContext.SetClipRect(clipRect, nsClipCombine_kIntersect);
577 nsRect backgroundRect = nsRect(nsPoint(0, 0), pageContentFrame->GetSize());
578 nsCSSRendering::PaintBackground(PresContext(), aRenderingContext, this,
579 rect, backgroundRect, PR_TRUE);
581 nsLayoutUtils::PaintFrame(&aRenderingContext, pageContentFrame,
582 nsRegion(rect), NS_RGBA(0,0,0,0));
584 aRenderingContext.PopState();
587 void
588 nsPageFrame::SetSharedPageData(nsSharedPageData* aPD)
590 mPD = aPD;
591 // Set the shared data into the page frame before reflow
592 nsPageContentFrame * pcf = static_cast<nsPageContentFrame*>(mFrames.FirstChild());
593 if (pcf) {
594 pcf->SetSharedPageData(mPD);
599 nsIFrame*
600 NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
602 NS_PRECONDITION(aPresShell, "null PresShell");
603 //check that we are only creating page break frames when printing
604 NS_ASSERTION(aPresShell->GetPresContext()->IsPaginated(), "created a page break frame while not printing");
606 return new (aPresShell) nsPageBreakFrame(aContext);
609 nsPageBreakFrame::nsPageBreakFrame(nsStyleContext* aContext) :
610 nsLeafFrame(aContext), mHaveReflowed(PR_FALSE)
614 nsPageBreakFrame::~nsPageBreakFrame()
618 nscoord
619 nsPageBreakFrame::GetIntrinsicWidth()
621 return nsPresContext::CSSPixelsToAppUnits(1);
624 nscoord
625 nsPageBreakFrame::GetIntrinsicHeight()
627 return 0;
630 nsresult
631 nsPageBreakFrame::Reflow(nsPresContext* aPresContext,
632 nsHTMLReflowMetrics& aDesiredSize,
633 const nsHTMLReflowState& aReflowState,
634 nsReflowStatus& aStatus)
636 DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
637 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
639 // Override reflow, since we don't want to deal with what our
640 // computed values are.
641 aDesiredSize.width = GetIntrinsicWidth();
642 aDesiredSize.height = (aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE ?
643 0 : aReflowState.availableHeight);
644 // round the height down to the nearest pixel
645 aDesiredSize.height -=
646 aDesiredSize.height % nsPresContext::CSSPixelsToAppUnits(1);
648 // Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
649 // DidReflow will always get called before the next Reflow() call.
650 mHaveReflowed = PR_TRUE;
651 aStatus = NS_FRAME_COMPLETE;
652 return NS_OK;
655 nsIAtom*
656 nsPageBreakFrame::GetType() const
658 return nsGkAtoms::pageBreakFrame;