1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* ***** BEGIN LICENSE BLOCK *****
3
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
5
* The contents of this file are subject to the Netscape Public License
6
* Version 1.1 (the "License"); you may not use this file except in
7
* compliance with the License. You may obtain a copy of the License at
8
* http://www.mozilla.org/NPL/
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 the GNU General Public License Version 2 or later (the "GPL"), or
26
* 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 NPL, 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 NPL, the GPL or the LGPL.
36
* ***** END LICENSE BLOCK ***** */
37
#include "nsPageFrame.h"
38
#include "nsHTMLParts.h"
39
#include "nsIContent.h"
40
#include "nsIPresContext.h"
41
#include "nsStyleContext.h"
42
#include "nsIRenderingContext.h"
43
#include "nsHTMLAtoms.h"
44
#include "nsLayoutAtoms.h"
45
#include "nsIPresShell.h"
46
#include "nsCSSFrameConstructor.h"
47
#include "nsIDeviceContext.h"
48
#include "nsReadableUtils.h"
49
#include "nsIPrintPreviewContext.h"
50
#include "nsIPrintContext.h"
51
#include "nsPageContentFrame.h"
52
#include "nsTextFrame.h" // for function BinarySearchForPosition
54
#include "nsIView.h" // view flags for clipping
55
#include "nsCSSRendering.h"
57
#include "nsHTMLContainerFrame.h" // view creation
59
#include "nsSimplePageSequence.h" // for nsSharedPageData
61
#include "nsIViewManager.h"
63
// for page number localization formatting
64
#include "nsTextFormatter.h"
67
#include "nsBidiUtils.h"
68
#include "nsBidiPresUtils.h"
72
#include "nsIFontMetrics.h"
75
#include "nsIPrintSettings.h"
76
#include "nsGfxCIID.h"
77
#include "nsIServiceManager.h"
80
#include "nsIWidget.h"
81
#include "nsWidgetsCID.h"
82
static NS_DEFINE_CID(kCChildCID, NS_CHILD_CID);
84
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
85
//#define DEBUG_PRINTING
90
extern PRLogModuleInfo * kLayoutPrintingLogMod;
91
#define PR_PL(_p1) PR_LOG(kLayoutPrintingLogMod, PR_LOG_DEBUG, _p1)
96
// XXX Part of Temporary fix for Bug 127263
97
PRBool nsPageFrame::mDoCreateWidget = PR_TRUE;
100
NS_NewPageFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
102
NS_PRECONDITION(aNewFrame, "null OUT ptr");
104
nsPageFrame* it = new (aPresShell) nsPageFrame;
106
return NS_ERROR_OUT_OF_MEMORY;
112
nsPageFrame::nsPageFrame() :
113
mSupressHF(PR_FALSE),
114
mClipRect(-1, -1, -1, -1)
118
nsPageFrame::~nsPageFrame()
124
nsPageFrame::SetInitialChildList(nsIPresContext* aPresContext,
126
nsIFrame* aChildList)
128
nsIView* view = aChildList->GetView();
129
if (view && mDoCreateWidget) {
130
nsCOMPtr<nsIPrintPreviewContext> ppContext = do_QueryInterface(aPresContext);
131
if (ppContext && view->GetNearestWidget(nsnull)) {
132
view->CreateWidget(kCChildCID);
136
return nsContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList);
139
NS_IMETHODIMP nsPageFrame::Reflow(nsIPresContext* aPresContext,
140
nsHTMLReflowMetrics& aDesiredSize,
141
const nsHTMLReflowState& aReflowState,
142
nsReflowStatus& aStatus)
144
DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason);
145
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
146
aStatus = NS_FRAME_COMPLETE; // initialize out parameter
148
if (eReflowReason_Incremental != aReflowState.reason) {
149
// Do we have any children?
150
// XXX We should use the overflow list instead...
151
nsIFrame* firstFrame = mFrames.FirstChild();
152
nsPageContentFrame* contentPage = NS_STATIC_CAST(nsPageContentFrame*, firstFrame);
153
NS_ASSERTION(contentPage, "There should always be a content page");
154
NS_ASSERTION(nsLayoutAtoms::pageContentFrame == firstFrame->GetType(),
155
"This frame isn't a pageContentFrame");
157
if (contentPage && mPrevInFlow) {
158
nsPageFrame* prevPage = NS_STATIC_CAST(nsPageFrame*, mPrevInFlow);
159
nsPageContentFrame* prevContentPage = NS_STATIC_CAST(nsPageContentFrame*, prevPage->mFrames.FirstChild());
160
nsIFrame* prevLastChild = prevContentPage->mFrames.LastChild();
162
// Create a continuing child of the previous page's last child
165
aPresContext->PresShell()->FrameConstructor()->
166
CreateContinuingFrame(aPresContext, prevLastChild,
167
contentPage, &newFrame);
169
// Make the new area frame the 1st child of the page content frame. There may already be
170
// children placeholders which don't get reflowed but must not be destroyed until the
171
// page content frame is destroyed.
172
contentPage->mFrames.InsertFrame(contentPage, nsnull, newFrame);
175
// Resize our frame allowing it only to be as big as we are
176
// XXX Pay attention to the page's border and padding...
177
if (mFrames.NotEmpty()) {
178
nsIFrame* frame = mFrames.FirstChild();
179
// When availableHeight is NS_UNCONSTRAINEDSIZE it means we are reflowing a single page
180
// to print selection. So this means we want to use NS_UNCONSTRAINEDSIZE without altering it
182
if (aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
183
avHeight = NS_UNCONSTRAINEDSIZE;
185
avHeight = mPD->mReflowRect.height - mPD->mReflowMargin.top - mPD->mReflowMargin.bottom;
187
nsSize maxSize(mPD->mReflowRect.width - mPD->mReflowMargin.right - mPD->mReflowMargin.left,
189
// Get the number of Twips per pixel from the PresContext
191
aPresContext->GetScaledPixelsToTwips(&p2t);
192
nscoord onePixelInTwips = NSToCoordRound(p2t);
193
NS_ASSERTION(maxSize.width >= onePixelInTwips, "maxSize.width must be >= 1 pixel");
194
NS_ASSERTION(maxSize.height >= onePixelInTwips, "maxSize.height must be >= 1 pixel");
195
// insurance against infinite reflow, when reflowing less than a pixel
196
if (maxSize.width < onePixelInTwips || maxSize.height < onePixelInTwips) {
197
aDesiredSize.width = 0;
198
aDesiredSize.height = 0;
202
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
203
kidReflowState.mFlags.mIsTopOfPage = PR_TRUE;
205
// calc location of frame
206
nscoord xc = mPD->mReflowMargin.left + mPD->mDeadSpaceMargin.left + mPD->mExtraMargin.left;
207
nscoord yc = mPD->mReflowMargin.top + mPD->mDeadSpaceMargin.top + mPD->mExtraMargin.top;
209
// Get the child's desired size
210
ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus);
213
// Place and size the child
214
FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, xc, yc, 0);
216
// Make sure the child is at least as tall as our max size (the containing window)
217
if (aDesiredSize.height < aReflowState.availableHeight &&
218
aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
219
aDesiredSize.height = aReflowState.availableHeight;
222
nsIView* view = frame->GetView();
224
nsRegion region(nsRect(0, 0, aDesiredSize.width, aDesiredSize.height));
225
view->GetViewManager()->SetViewChildClipRegion(view, ®ion);
229
// Is the frame complete?
230
if (NS_FRAME_IS_COMPLETE(aStatus)) {
231
nsIFrame* childNextInFlow;
233
frame->GetNextInFlow(&childNextInFlow);
234
NS_ASSERTION(nsnull == childNextInFlow, "bad child flow list");
238
PR_PL(("PageFrame::Reflow %p ", this));
239
PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.availableWidth, aReflowState.availableHeight));
241
// Return our desired size
242
aDesiredSize.width = aReflowState.availableWidth;
243
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
244
aDesiredSize.height = aReflowState.availableHeight;
247
PR_PL(("PageFrame::Reflow %p ", this));
248
PR_PL(("[%d,%d]\n", aReflowState.availableWidth, aReflowState.availableHeight));
250
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
254
void nsPageFrame::SetClipRect(nsRect* aClipRect)
256
mClipRect = *aClipRect;
257
nsIFrame* firstFrame = mFrames.FirstChild();
258
nsPageContentFrame* contentPage = NS_STATIC_CAST(nsPageContentFrame*, firstFrame);
259
NS_ASSERTION(contentPage, "There should always be a content page");
260
contentPage->SetClipRect(aClipRect);
265
nsPageFrame::GetType() const
267
return nsLayoutAtoms::pageFrame;
272
nsPageFrame::GetFrameName(nsAString& aResult) const
274
return MakeFrameName(NS_LITERAL_STRING("Page"), aResult);
279
nsPageFrame::IsContainingBlock() const
284
// Remove fix below when string gets fixed
285
#define WORKAROUND_FOR_BUG_110335
286
// replace the &<code> with the value, but if the value is empty
287
// set the string to zero length
289
SubstValueForCode(nsString& aStr, const PRUnichar * aUKey, const PRUnichar * aUStr)
291
#ifdef WORKAROUND_FOR_BUG_110335
292
const PRUnichar* uKeyStr = aUKey;
294
// Check to make sure our subst code &<code> isn't in the data string
295
// for example &T for title is in QB&T
296
nsAutoString dataStr(aUStr);
297
nsAutoString newKey(aUKey);
298
PRBool fixingSubstr = (dataStr.Find(newKey) != kNotFound);
300
// well, the code is in the data str so make up a new code
301
// but make sure it it isn't in either substs string or the data string
302
char* code = "~!@#$%^*()_+=][}{`';:|?/.,:\"<>";
304
PRInt32 codeLen = PRUint32(strlen(code));
305
while ((dataStr.Find(newKey) > -1 || aStr.Find(newKey) > -1) && codeInx < codeLen) {
306
newKey.SetCharAt((PRUnichar)code[codeInx++], 0);
309
// Check to see if we can do the substitution
310
if (codeInx == codeLen) {
312
return; // bail we just can't do it
315
// Ok, we have the new code, so repplace the old code
316
// in the dest str with the new code
317
aStr.ReplaceSubstring(aUKey, newKey.get());
318
uKeyStr = ToNewUnicode(newKey);
321
if (!aUStr || !*aUStr) {
324
aStr.ReplaceSubstring(uKeyStr, aUStr);
327
// Free uKeyStr only if we fixed the string.
329
nsMemory::Free(NS_CONST_CAST(PRUnichar*, uKeyStr));
333
if (!aUStr || !*aUStr) {
336
aStr.ReplaceSubstring(aUKey, aUStr);
338
#endif // WORKAROUND_FOR_BUG_110335
340
// done with static helper functions
341
//------------------------------------------------------------------------------
343
//------------------------------------------------------------------------------
345
nsPageFrame::ProcessSpecialCodes(const nsString& aStr, nsString& aNewStr)
350
// Search to see if the &D code is in the string
351
// then subst in the current date/time
352
NS_NAMED_LITERAL_STRING(kDate, "&D");
353
if (aStr.Find(kDate) != kNotFound) {
354
if (mPD->mDateTimeStr != nsnull) {
355
aNewStr.ReplaceSubstring(kDate.get(), mPD->mDateTimeStr);
357
aNewStr.ReplaceSubstring(kDate.get(), EmptyString().get());
362
// NOTE: Must search for &PT before searching for &P
364
// Search to see if the "page number and page" total code are in the string
365
// and replace the page number and page total code with the actual
367
NS_NAMED_LITERAL_STRING(kPageAndTotal, "&PT");
368
if (aStr.Find(kPageAndTotal) != kNotFound) {
369
PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumAndTotalsFormat, mPageNum, mTotNumPages);
370
aNewStr.ReplaceSubstring(kPageAndTotal.get(), uStr);
371
nsMemory::Free(uStr);
375
// Search to see if the page number code is in the string
376
// and replace the page number code with the actual value
377
NS_NAMED_LITERAL_STRING(kPage, "&P");
378
if (aStr.Find(kPage) != kNotFound) {
379
PRUnichar * uStr = nsTextFormatter::smprintf(mPD->mPageNumFormat, mPageNum);
380
aNewStr.ReplaceSubstring(kPage.get(), uStr);
381
nsMemory::Free(uStr);
385
NS_NAMED_LITERAL_STRING(kTitle, "&T");
386
if (aStr.Find(kTitle) != kNotFound) {
387
SubstValueForCode(aNewStr, kTitle.get(), mPD->mDocTitle);
391
NS_NAMED_LITERAL_STRING(kDocURL, "&U");
392
if (aStr.Find(kDocURL) != kNotFound) {
393
SubstValueForCode(aNewStr, kDocURL.get(), mPD->mDocURL);
399
//------------------------------------------------------------------------------
400
nscoord nsPageFrame::GetXPosition(nsIRenderingContext& aRenderingContext,
403
const nsString& aStr)
406
aRenderingContext.GetWidth(aStr, width);
410
case nsIPrintSettings::kJustLeft:
411
x += mPD->mExtraMargin.left + mPD->mEdgePaperMargin.left;
414
case nsIPrintSettings::kJustCenter:
415
x += (aRect.width - width) / 2;
418
case nsIPrintSettings::kJustRight:
419
x += aRect.width - width - mPD->mExtraMargin.right - mPD->mEdgePaperMargin.right;
423
NS_ASSERTION(x >= 0, "x can't be less than zero");
428
//------------------------------------------------------------------------------
429
// Draw a Header or footer text lrft,right or center justified
430
// @parm aRenderingContext - rendering content ot draw into
431
// @parm aHeaderFooter - indicates whether it is a header or footer
432
// @parm aJust - indicates the justification of the text
433
// @parm aStr - The string to be drawn
434
// @parm aRect - the rect of the page
435
// @parm aHeight - the height of the text
436
// @parm aUseHalfThePage - indicates whether the text should limited to the width
437
// of the entire page or just half the page
439
nsPageFrame::DrawHeaderFooter(nsIPresContext* aPresContext,
440
nsIRenderingContext& aRenderingContext,
442
nsHeaderFooterEnum aHeaderFooter,
444
const nsString& aStr1,
445
const nsString& aStr2,
446
const nsString& aStr3,
452
if (!aStr1.IsEmpty()) numStrs++;
453
if (!aStr2.IsEmpty()) numStrs++;
454
if (!aStr3.IsEmpty()) numStrs++;
456
if (numStrs == 0) return;
457
nscoord strSpace = aRect.width / numStrs;
459
if (!aStr1.IsEmpty()) {
460
DrawHeaderFooter(aPresContext, aRenderingContext, aFrame, aHeaderFooter, nsIPrintSettings::kJustLeft, aStr1, aRect, aAscent, aHeight, strSpace);
462
if (!aStr2.IsEmpty()) {
463
DrawHeaderFooter(aPresContext, aRenderingContext, aFrame, aHeaderFooter, nsIPrintSettings::kJustCenter, aStr2, aRect, aAscent, aHeight, strSpace);
465
if (!aStr3.IsEmpty()) {
466
DrawHeaderFooter(aPresContext, aRenderingContext, aFrame, aHeaderFooter, nsIPrintSettings::kJustRight, aStr3, aRect, aAscent, aHeight, strSpace);
470
//------------------------------------------------------------------------------
471
// Draw a Header or footer text lrft,right or center justified
472
// @parm aRenderingContext - rendering content ot draw into
473
// @parm aHeaderFooter - indicates whether it is a header or footer
474
// @parm aJust - indicates the justification of the text
475
// @parm aStr - The string to be drawn
476
// @parm aRect - the rect of the page
477
// @parm aHeight - the height of the text
478
// @parm aWidth - available width for any one of the strings
480
nsPageFrame::DrawHeaderFooter(nsIPresContext* aPresContext,
481
nsIRenderingContext& aRenderingContext,
483
nsHeaderFooterEnum aHeaderFooter,
485
const nsString& aStr,
492
nscoord contentWidth = aWidth - (mPD->mEdgePaperMargin.left + mPD->mEdgePaperMargin.right);
494
// first make sure we have a vaild string and that the height of the
495
// text will fit in the margin
496
if (!aStr.IsEmpty() &&
497
((aHeaderFooter == eHeader && aHeight < mMargin.top) ||
498
(aHeaderFooter == eFooter && aHeight < mMargin.bottom))) {
500
ProcessSpecialCodes(aStr, str);
503
PRInt32 textWidth = 0;
504
const PRUnichar* text = str.get();
506
PRInt32 len = (PRInt32)str.Length();
508
return; // bail is empty string
510
// find how much text fits, the "position" is the size of the available area
511
if (BinarySearchForPosition(&aRenderingContext, text, 0, 0, 0, len,
512
PRInt32(contentWidth), indx, textWidth)) {
513
if (indx < len-1 && len > 3) {
514
str.SetLength(indx-3);
515
str.Append(NS_LITERAL_STRING("..."));
518
return; // bail if couldn't find the correct length
521
// cacl the x and y positions of the text
523
nscoord x = GetXPosition(aRenderingContext, rect, aJust, str);
525
if (aHeaderFooter == eHeader) {
526
y = rect.y + mPD->mExtraMargin.top + mPD->mEdgePaperMargin.top;
528
y = rect.y + rect.height - aHeight - mPD->mExtraMargin.bottom - mPD->mEdgePaperMargin.bottom;
531
// set up new clip and draw the text
533
aRenderingContext.PushState();
534
aRenderingContext.SetColor(NS_RGB(0,0,0));
535
aRenderingContext.SetClipRect(rect, nsClipCombine_kReplace, clipEmpty);
537
nsresult rv = NS_ERROR_FAILURE;
539
PRBool isBidiEnabled = PR_FALSE;
540
aPresContext->GetBidiEnabled(&isBidiEnabled);
542
nsBidiPresUtils* bidiUtils;
543
aPresContext->GetBidiUtils(&bidiUtils);
546
PRUnichar* buffer = str.BeginWriting();
547
// Base direction is always LTR for now. If bug 139337 is fixed,
548
// that should change.
549
rv = bidiUtils->RenderText(buffer, str.Length(), NSBIDI_LTR,
550
aPresContext, aRenderingContext,
556
aRenderingContext.DrawString(str, x, y + aAscent);
557
aRenderingContext.PopState(clipEmpty);
559
#ifdef DEBUG_PRINTING
560
PR_PL(("Page: %p", this));
561
PR_PL((" [%s]", NS_ConvertUCS2toUTF8(str).get()));
564
case nsIPrintSettings::kJustLeft:strcpy(justStr, "Left");break;
565
case nsIPrintSettings::kJustCenter:strcpy(justStr, "Center");break;
566
case nsIPrintSettings::kJustRight:strcpy(justStr, "Right");break;
568
PR_PL((" HF: %s ", aHeaderFooter==eHeader?"Header":"Footer"));
569
PR_PL((" JST: %s ", justStr));
570
PR_PL((" x,y: %d,%d", x, y));
571
PR_PL((" Hgt: %d \n", aHeight));
576
//------------------------------------------------------------------------------
578
nsPageFrame::Paint(nsIPresContext* aPresContext,
579
nsIRenderingContext& aRenderingContext,
580
const nsRect& aDirtyRect,
581
nsFramePaintLayer aWhichLayer,
584
aRenderingContext.PushState();
585
aRenderingContext.SetColor(NS_RGB(255,255,255));
589
PRBool specialClipIsSet = mClipRect.width != -1 || mClipRect.height != -1;
591
if (specialClipIsSet) {
592
#ifdef DEBUG_PRINTING
593
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
594
printf("*** ClipRect: %5d,%5d,%5d,%5d\n", mClipRect.x, mClipRect.y, mClipRect.width, mClipRect.height);
597
aRenderingContext.SetClipRect(mClipRect, nsClipCombine_kReplace, clipEmpty);
603
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
605
nsCOMPtr<nsIPrintPreviewContext> ppContext = do_QueryInterface(aPresContext);
607
// fill page with White
608
aRenderingContext.SetColor(NS_RGB(255,255,255));
611
rect.width -= mPD->mShadowSize.width;
612
rect.height -= mPD->mShadowSize.height;
613
aRenderingContext.FillRect(rect);
614
// draw line around outside of page
615
aRenderingContext.SetColor(NS_RGB(0,0,0));
616
aRenderingContext.DrawRect(rect);
618
if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) {
619
aRenderingContext.SetColor(NS_RGB(51,51,51));
620
nsRect r(0,0, mRect.width, mRect.height);
622
shadowRect.x = r.x + r.width - mPD->mShadowSize.width;
623
shadowRect.y = r.y + mPD->mShadowSize.height;
624
shadowRect.width = mPD->mShadowSize.width;
625
shadowRect.height = r.height - mPD->mShadowSize.height;
626
aRenderingContext.FillRect(shadowRect);
628
shadowRect.x = r.x + mPD->mShadowSize.width;
629
shadowRect.y = r.y + r.height - mPD->mShadowSize.height;
630
shadowRect.width = r.width - mPD->mShadowSize.width;
631
shadowRect.height = mPD->mShadowSize.height;
632
aRenderingContext.FillRect(shadowRect);
637
if (NS_FRAME_PAINT_LAYER_BACKGROUND == aWhichLayer) {
638
DrawBackground(aPresContext,aRenderingContext,aDirtyRect);
641
nsresult rv = nsContainerFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer);
643
#if defined(DEBUG_rods) || defined(DEBUG_dcone)
644
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) {
645
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
646
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
647
PR_PL(("PF::Paint -> %p SupHF: %s Rect: [%5d,%5d,%5d,%5d] SC:%s\n", this,
648
mSupressHF?"Yes":"No", mRect.x, mRect.y, mRect.width, mRect.height, specialClipIsSet?"Yes":"No"));
652
if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer && !mSupressHF) {
653
// For PrintPreview the
654
if (!mPD->mPrintSettings) {
655
nsCOMPtr<nsIPrintPreviewContext> ppContext = do_QueryInterface(aPresContext);
657
ppContext->GetPrintSettings(getter_AddRefs(mPD->mPrintSettings));
660
NS_ASSERTION(mPD->mPrintSettings, "Must have a good PrintSettings here!");
662
// get the current margin
663
mPD->mPrintSettings->GetMarginInTwips(mMargin);
665
rect.SetRect(0, 0, mRect.width - mPD->mShadowSize.width, mRect.height - mPD->mShadowSize.height);
667
aRenderingContext.SetFont(*mPD->mHeadFootFont, nsnull);
668
aRenderingContext.SetColor(NS_RGB(0,0,0));
670
// Get the FontMetrics to determine width.height of strings
671
nsCOMPtr<nsIFontMetrics> fontMet;
672
aPresContext->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
673
*getter_AddRefs(fontMet));
675
nscoord visibleHeight = 0;
677
fontMet->GetHeight(visibleHeight);
678
fontMet->GetMaxAscent(ascent);
681
// print document headers and footers
682
PRUnichar * headers[3];
683
mPD->mPrintSettings->GetHeaderStrLeft(&headers[0]); // creates memory
684
mPD->mPrintSettings->GetHeaderStrCenter(&headers[1]); // creates memory
685
mPD->mPrintSettings->GetHeaderStrRight(&headers[2]); // creates memory
686
DrawHeaderFooter(aPresContext, aRenderingContext, this, eHeader, nsIPrintSettings::kJustLeft,
687
nsAutoString(headers[0]), nsAutoString(headers[1]), nsAutoString(headers[2]),
688
rect, ascent, visibleHeight);
690
for (i=0;i<3;i++) nsMemory::Free(headers[i]);
692
PRUnichar * footers[3];
693
mPD->mPrintSettings->GetFooterStrLeft(&footers[0]); // creates memory
694
mPD->mPrintSettings->GetFooterStrCenter(&footers[1]); // creates memory
695
mPD->mPrintSettings->GetFooterStrRight(&footers[2]); // creates memory
696
DrawHeaderFooter(aPresContext, aRenderingContext, this, eFooter, nsIPrintSettings::kJustRight,
697
nsAutoString(footers[0]), nsAutoString(footers[1]), nsAutoString(footers[2]),
698
rect, ascent, visibleHeight);
699
for (i=0;i<3;i++) nsMemory::Free(footers[i]);
703
aRenderingContext.PopState(clipEmpty);
708
//------------------------------------------------------------------------------
710
nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages)
712
mPageNum = aPageNumber;
713
mTotNumPages = aTotalPages;
717
//------------------------------------------------------------------------------
719
nsPageFrame::DrawBackground(nsIPresContext* aPresContext,
720
nsIRenderingContext& aRenderingContext,
721
const nsRect& aDirtyRect)
723
nsSimplePageSequenceFrame* seqFrame = NS_STATIC_CAST(nsSimplePageSequenceFrame*, mParent);
724
if (seqFrame != nsnull) {
725
nsIFrame* pageContentFrame = mFrames.FirstChild();
726
NS_ASSERTION(pageContentFrame, "Must always be there.");
728
const nsStyleBorder* border = GetStyleBorder();
729
const nsStylePadding* padding = GetStylePadding();
731
nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this,
732
aDirtyRect, pageContentFrame->GetRect(), *border, *padding,
738
nsPageFrame::SetSharedPageData(nsSharedPageData* aPD)
741
// Set the shared data into the page frame before reflow
742
nsPageContentFrame * pcf = NS_STATIC_CAST(nsPageContentFrame*, mFrames.FirstChild());
744
pcf->SetSharedPageData(mPD);
750
NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame)
752
NS_PRECONDITION(aPresShell && aNewFrame, "null PresShell or OUT ptr");
754
//check that we are only creating page break frames when printing
755
nsCOMPtr<nsIPresContext> presContext;
756
aPresShell->GetPresContext(getter_AddRefs(presContext));
757
NS_ASSERTION(presContext->IsPaginated(), "created a page break frame while not printing");
760
nsPageBreakFrame* it = new (aPresShell) nsPageBreakFrame;
762
return NS_ERROR_OUT_OF_MEMORY;
768
nsPageBreakFrame::nsPageBreakFrame()
769
: mHaveReflowed(PR_FALSE)
773
nsPageBreakFrame::~nsPageBreakFrame()
778
nsPageBreakFrame::GetDesiredSize(nsIPresContext* aPresContext,
779
const nsHTMLReflowState& aReflowState,
780
nsHTMLReflowMetrics& aDesiredSize)
782
NS_PRECONDITION(aPresContext, "null pres context");
784
aPresContext->GetScaledPixelsToTwips(&p2t);
785
nscoord onePixel = NSToCoordRound(p2t);
787
aDesiredSize.width = onePixel;
789
// If blocks reflow us a 2nd time trying to put us on a new page, then return
790
// a desired height of 0 to avoid an extra page break.
791
aDesiredSize.height = 0;
794
aDesiredSize.height = aReflowState.availableHeight;
795
// round the height down to the nearest pixel
796
aDesiredSize.height -= aDesiredSize.height % onePixel;
799
if (aDesiredSize.mComputeMEW) {
800
aDesiredSize.mMaxElementWidth = onePixel;
802
aDesiredSize.ascent = 0;
803
aDesiredSize.descent = 0;
807
nsPageBreakFrame::Reflow(nsIPresContext* aPresContext,
808
nsHTMLReflowMetrics& aDesiredSize,
809
const nsHTMLReflowState& aReflowState,
810
nsReflowStatus& aStatus)
812
NS_PRECONDITION(aPresContext, "null pres context");
813
DO_GLOBAL_REFLOW_COUNT("nsTableFrame", aReflowState.reason);
814
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
816
aStatus = NS_FRAME_COMPLETE;
817
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
818
mHaveReflowed = PR_TRUE;
824
nsPageBreakFrame::GetType() const
826
return nsLayoutAtoms::pageBreakFrame;