From 121f0e1b6ffcd5628d61fb68a3b82974379c04c4 Mon Sep 17 00:00:00 2001 From: Michael Ventnor Date: Fri, 10 Jun 2011 20:07:26 +1000 Subject: [PATCH] Bug 663028 - Make Print Preview themable with CSS, and modernize its look r=roc --- layout/base/nsCSSRendering.cpp | 1 - layout/base/nsDisplayItemTypes.h | 1 - layout/base/nsDocumentViewer.cpp | 10 +--- layout/generic/nsIPageSequenceFrame.h | 3 -- layout/generic/nsPageFrame.cpp | 54 +++------------------ layout/generic/nsPageFrame.h | 6 ++- layout/generic/nsSimplePageSequence.cpp | 63 +++++++++++++------------ layout/generic/nsSimplePageSequence.h | 15 ++++-- layout/style/ua.css | 16 ++++++- 9 files changed, 69 insertions(+), 100 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 56d55a6e6ab..5f076c7aaa8 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -923,7 +923,6 @@ nsCSSRendering::IsCanvasFrame(nsIFrame* aFrame) nsIAtom* frameType = aFrame->GetType(); return frameType == nsGkAtoms::canvasFrame || frameType == nsGkAtoms::rootFrame || - frameType == nsGkAtoms::pageFrame || frameType == nsGkAtoms::pageContentFrame || frameType == nsGkAtoms::viewportFrame; } diff --git a/layout/base/nsDisplayItemTypes.h b/layout/base/nsDisplayItemTypes.h index cd934864261..512d6e075a5 100644 --- a/layout/base/nsDisplayItemTypes.h +++ b/layout/base/nsDisplayItemTypes.h @@ -79,7 +79,6 @@ enum Type { TYPE_PAGE_SEQUENCE, TYPE_PLUGIN, TYPE_PLUGIN_READBACK, - TYPE_PRINT_PREVIEW_BACKGROUND, TYPE_PRINT_PLUGIN, TYPE_REMOTE, TYPE_REMOTE_SHADOW, diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 97b49e064e8..d115d4f484b 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -3859,16 +3859,8 @@ DocumentViewerImpl::PrintPreviewNavigate(PRInt16 aType, PRInt32 aPageNum) } if (fndPageFrame) { - nscoord deadSpaceGapTwips = 0; - nsIPageSequenceFrame * sqf = do_QueryFrame(seqFrame); - if (sqf) { - sqf->GetDeadSpaceValue(&deadSpaceGapTwips); - } - - nscoord deadSpaceGap = nsPresContext::CSSTwipsToAppUnits(deadSpaceGapTwips); nscoord newYPosn = - nscoord(mPrintEngine->GetPrintPreviewScale() * - float(fndPageFrame->GetPosition().y - deadSpaceGap)); + nscoord(mPrintEngine->GetPrintPreviewScale() * fndPageFrame->GetPosition().y); sf->ScrollTo(nsPoint(pt.x, newYPosn), nsIScrollableFrame::INSTANT); } return NS_OK; diff --git a/layout/generic/nsIPageSequenceFrame.h b/layout/generic/nsIPageSequenceFrame.h index f39e8687a96..8222c886ebf 100644 --- a/layout/generic/nsIPageSequenceFrame.h +++ b/layout/generic/nsIPageSequenceFrame.h @@ -81,9 +81,6 @@ public: NS_IMETHOD SetTotalNumPages(PRInt32 aTotal) = 0; - // Gets the dead space (the gray area) around the Print Preview Page - NS_IMETHOD GetDeadSpaceValue(nscoord* aValue) = 0; - // For Shrink To Fit NS_IMETHOD GetSTFPercent(float& aSTFPercent) = 0; }; diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index a3897c115e8..492a547e683 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -150,6 +150,10 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { aDesiredSize.height = aReflowState.availableHeight; } + + aDesiredSize.SetOverflowAreasToDesiredBounds(); + FinishAndStoreOverflow(&aDesiredSize); + PR_PL(("PageFrame::Reflow %p ", this)); PR_PL(("[%d,%d]\n", aReflowState.availableWidth, aReflowState.availableHeight)); @@ -393,12 +397,6 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext, } } -static void PaintPrintPreviewBackground(nsIFrame* aFrame, nsRenderingContext* aCtx, - const nsRect& aDirtyRect, nsPoint aPt) -{ - static_cast(aFrame)->PaintPrintPreviewBackground(*aCtx, aPt); -} - static void PaintPageContent(nsIFrame* aFrame, nsRenderingContext* aCtx, const nsRect& aDirtyRect, nsPoint aPt) { @@ -421,10 +419,7 @@ nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsresult rv; if (PresContext()->IsScreen()) { - rv = set.BorderBackground()->AppendNewToTop(new (aBuilder) - nsDisplayGeneric(aBuilder, this, ::PaintPrintPreviewBackground, - "PrintPreviewBackground", - nsDisplayItem::TYPE_PRINT_PREVIEW_BACKGROUND)); + rv = DisplayBorderBackgroundOutline(aBuilder, aLists); NS_ENSURE_SUCCESS(rv, rv); } @@ -455,41 +450,6 @@ nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) } -void -nsPageFrame::PaintPrintPreviewBackground(nsRenderingContext& aRenderingContext, - nsPoint aPt) -{ - // fill page with White - aRenderingContext.SetColor(NS_RGB(255,255,255)); - // REVIEW: this used to have rect's width and height be the - // mClipRect if specialClipIsSet ... but that seems completely bogus - // and inconsistent with the painting of the shadow below - nsRect rect(aPt, GetSize()); - rect.width -= mPD->mShadowSize.width; - rect.height -= mPD->mShadowSize.height; - aRenderingContext.FillRect(rect); - // draw line around outside of page - aRenderingContext.SetColor(NS_RGB(0,0,0)); - aRenderingContext.DrawRect(rect); - - if (mPD->mShadowSize.width > 0 && mPD->mShadowSize.height > 0) { - aRenderingContext.SetColor(NS_RGB(51,51,51)); - nsRect r(aPt.x,aPt.y, mRect.width, mRect.height); - nsRect shadowRect; - shadowRect.x = r.x + r.width - mPD->mShadowSize.width; - shadowRect.y = r.y + mPD->mShadowSize.height; - shadowRect.width = mPD->mShadowSize.width; - shadowRect.height = r.height - mPD->mShadowSize.height; - aRenderingContext.FillRect(shadowRect); - - shadowRect.x = r.x + mPD->mShadowSize.width; - shadowRect.y = r.y + r.height - mPD->mShadowSize.height; - shadowRect.width = r.width - mPD->mShadowSize.width; - shadowRect.height = mPD->mShadowSize.height; - aRenderingContext.FillRect(shadowRect); - } -} - void nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext, nsPoint aPt) @@ -503,9 +463,7 @@ nsPageFrame::PaintHeaderFooter(nsRenderingContext& aRenderingContext, return; } - nsRect rect(aPt.x, aPt.y, mRect.width - mPD->mShadowSize.width, - mRect.height - mPD->mShadowSize.height); - + nsRect rect(aPt, mRect.Size()); aRenderingContext.SetColor(NS_RGB(0,0,0)); // Get the FontMetrics to determine width.height of strings diff --git a/layout/generic/nsPageFrame.h b/layout/generic/nsPageFrame.h index e95052ce17c..901516b0bc6 100644 --- a/layout/generic/nsPageFrame.h +++ b/layout/generic/nsPageFrame.h @@ -81,8 +81,10 @@ public: virtual void SetSharedPageData(nsSharedPageData* aPD); - void PaintPrintPreviewBackground(nsRenderingContext& aRenderingContext, - nsPoint aPt); + // We must allow Print Preview UI to have a background, no matter what the + // user's settings + virtual PRBool HonorPrintBackgroundSettings() { return PR_FALSE; } + void PaintHeaderFooter(nsRenderingContext& aRenderingContext, nsPoint aPt); void PaintPageContent(nsRenderingContext& aRenderingContext, diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index ba485049709..d8cf62230b1 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -87,7 +87,6 @@ nsSharedPageData::nsSharedPageData() : mDocURL(nsnull), mReflowSize(0,0), mReflowMargin(0,0,0,0), - mShadowSize(0,0), mExtraMargin(0,0,0,0), mEdgePaperMargin(0,0,0,0), mPageContentXMost(0), @@ -146,6 +145,22 @@ NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame) //---------------------------------------------------------------------- +void +nsSimplePageSequenceFrame::SetDesiredSize(nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aWidth, + nscoord aHeight) +{ + // Aim to fill the whole size of the document, not only so we + // can act as a background in print preview but also handle overflow + // in child page frames correctly. + // Use availableWidth so we don't cause a needless horizontal scrollbar. + aDesiredSize.width = NS_MAX(aReflowState.availableWidth, + nscoord(aWidth * PresContext()->GetPrintPreviewScale())); + aDesiredSize.height = NS_MAX(aReflowState.ComputedHeight(), + nscoord(aHeight * PresContext()->GetPrintPreviewScale())); +} + NS_IMETHODIMP nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -164,16 +179,12 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, // it right in paginated mode. if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // Return our desired size - aDesiredSize.height = mSize.height * PresContext()->GetPrintPreviewScale(); - aDesiredSize.width = mSize.width * PresContext()->GetPrintPreviewScale(); + SetDesiredSize(aDesiredSize, aReflowState, mSize.width, mSize.height); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); return NS_OK; } - PRBool isPrintPreview = - aPresContext->Type() == nsPresContext::eContext_PrintPreview; - // See if we can get a Print Settings from the Context if (!mPageData->mPrintSettings && aPresContext->Medium() == nsGkAtoms::print) { @@ -235,29 +246,21 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, nscoord extraGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); extraGap = NS_MIN(extraGap, extraThreshold); // clamp to 1/10 of the largest dim of the page - nscoord deadSpaceGap = 0; - if (isPrintPreview) { - GetDeadSpaceValue(&gapInTwips); - deadSpaceGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); - } - nsMargin extraMargin(0,0,0,0); - nsSize shadowSize(0,0); if (aPresContext->IsScreen()) { extraMargin.SizeTo(extraGap, extraGap, extraGap, extraGap); - nscoord fourPixels = nsPresContext::CSSPixelsToAppUnits(4); - shadowSize.SizeTo(fourPixels, fourPixels); } - mPageData->mShadowSize = shadowSize; - mPageData->mExtraMargin = extraMargin; + mPageData->mExtraMargin = extraMargin; - const nscoord x = deadSpaceGap; - nscoord y = deadSpaceGap;// Running y-offset for each page + // We use the CSS "margin" property on the -moz-page pseudoelement + // to determine the space between each page in print preview. + // Keep a running y-offset for each page. + nscoord y = 0; + nscoord maxXMost = 0; - nsSize availSize(pageSize.width + shadowSize.width + extraMargin.LeftRight(), - pageSize.height + shadowSize.height + - extraMargin.TopBottom()); + nsSize availSize(pageSize.width + extraMargin.LeftRight(), + pageSize.height + extraMargin.TopBottom()); // Tile the pages vertically nsHTMLReflowMetrics kidSize; @@ -275,15 +278,19 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, //kidReflowState.SetComputedHeight(kidReflowState.availableHeight); PR_PL(("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight)); + nsMargin pageCSSMargin = kidReflowState.mComputedMargin; + y += pageCSSMargin.top; + const nscoord x = pageCSSMargin.left; + // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, x, y, 0); y += kidSize.height; + y += pageCSSMargin.bottom; - // Leave a slight gap between the pages - y += deadSpaceGap; + maxXMost = NS_MAX(maxXMost, x + kidSize.width + pageCSSMargin.right); // Is the page complete? nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow(); @@ -344,18 +351,16 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, } // Return our desired size - // Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the + // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the // correct size - nscoord w = (x + availSize.width + deadSpaceGap); - aDesiredSize.height = y * PresContext()->GetPrintPreviewScale(); // includes page heights and dead space - aDesiredSize.width = w * PresContext()->GetPrintPreviewScale(); + SetDesiredSize(aDesiredSize, aReflowState, maxXMost, y); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); // cache the size so we can set the desired size // for the other reflows that happen - mSize.width = w; + mSize.width = maxXMost; mSize.height = y; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); diff --git a/layout/generic/nsSimplePageSequence.h b/layout/generic/nsSimplePageSequence.h index 0f90ea3cd80..0d9df1d9d90 100644 --- a/layout/generic/nsSimplePageSequence.h +++ b/layout/generic/nsSimplePageSequence.h @@ -61,8 +61,6 @@ public: nsSize mReflowSize; nsMargin mReflowMargin; - // shadow of page in PrintPreview; drawn around bottom and right edges - nsSize mShadowSize; // Extra Margin between the device area and the edge of the page; // approximates unprintable area nsMargin mExtraMargin; @@ -101,9 +99,6 @@ public: NS_IMETHOD SetPageNo(PRInt32 aPageNo) { return NS_OK;} NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) { mYSelOffset = aYOffset; mSelectionHeight = aHeight; return NS_OK; } NS_IMETHOD SetTotalNumPages(PRInt32 aTotal) { mTotalPages = aTotal; return NS_OK; } - - // Gets the dead space (the gray area) around the Print Preview Page - NS_IMETHOD GetDeadSpaceValue(nscoord* aValue) { *aValue = NS_INCHES_TO_INT_TWIPS(0.25); return NS_OK; } // For Shrink To Fit NS_IMETHOD GetSTFPercent(float& aSTFPercent); @@ -120,6 +115,10 @@ public: NS_IMETHOD GetPrintRange(PRInt32* aFromPage, PRInt32* aToPage); NS_IMETHOD DoPageEnd(); + // We must allow Print Preview UI to have a background, no matter what the + // user's settings + virtual PRBool HonorPrintBackgroundSettings() { return PR_FALSE; } + /** * Get the "type" of the frame * @@ -145,6 +144,12 @@ protected: void SetDateTimeStr(PRUnichar * aDateTimeStr); void SetPageNumberFormat(PRUnichar * aFormatStr, PRBool aForPageNumOnly); + // Sets the frame desired size to the size of the viewport, or the given + // nscoords, whichever is larger. Print scaling is applied in this function. + void SetDesiredSize(nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nscoord aWidth, nscoord aHeight); + nsMargin mMargin; // I18N date formatter service which we'll want to cache locally. diff --git a/layout/style/ua.css b/layout/style/ua.css index bb7fa4d962a..876ab83b1ae 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -185,9 +185,21 @@ height: 100%; } -*|*::-moz-page, *|*::-moz-page-sequence, *|*::-moz-scrolled-page-sequence { +*|*::-moz-page-sequence, *|*::-moz-scrolled-page-sequence { + /* Collection of pages in print/print preview. Visual styles may only appear + * in print preview. */ display: block !important; - background: transparent; + background: -moz-linear-gradient(top, #606060, #8a8a8a) fixed; + height: 100%; +} + +*|*::-moz-page { + /* Individual page in print/print preview. Visual styles may only appear + * in print preview. */ + display: block !important; + background: white; + box-shadow: 5px 5px 8px #202020; + margin: 0.125in 0.25in; } *|*::-moz-pagecontent {