From 3b71cbe23b3a2616655e0f5504f3be05ee60bd74 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Fri, 31 Aug 2012 14:20:56 -0700 Subject: [PATCH] Bug 115199 - CSS2 @page rule rendering support. r=roc --- layout/generic/nsPageContentFrame.cpp | 28 +++-------- layout/generic/nsPageContentFrame.h | 9 ---- layout/generic/nsPageFrame.cpp | 57 +++++++++++++++++----- layout/generic/nsSimplePageSequence.cpp | 22 +-------- layout/generic/nsSimplePageSequence.h | 3 -- layout/reftests/printing/115199-1-ref.html | 20 ++++++++ layout/reftests/printing/115199-1.html | 25 ++++++++++ layout/reftests/printing/115199-2-ref.html | 18 +++++++ layout/reftests/printing/115199-2a.html | 24 +++++++++ layout/reftests/printing/115199-2b.html | 24 +++++++++ layout/reftests/printing/reftest.list | 3 ++ 11 files changed, 169 insertions(+), 64 deletions(-) create mode 100644 layout/reftests/printing/115199-1-ref.html create mode 100644 layout/reftests/printing/115199-1.html create mode 100644 layout/reftests/printing/115199-2-ref.html create mode 100644 layout/reftests/printing/115199-2a.html create mode 100644 layout/reftests/printing/115199-2b.html diff --git a/layout/generic/nsPageContentFrame.cpp b/layout/generic/nsPageContentFrame.cpp index f2a6511b650..ff55ae5d178 100644 --- a/layout/generic/nsPageContentFrame.cpp +++ b/layout/generic/nsPageContentFrame.cpp @@ -24,19 +24,6 @@ NS_NewPageContentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) NS_IMPL_FRAMEARENA_HELPERS(nsPageContentFrame) -/* virtual */ nsSize -nsPageContentFrame::ComputeSize(nsRenderingContext *aRenderingContext, - nsSize aCBSize, nscoord aAvailableWidth, - nsSize aMargin, nsSize aBorder, nsSize aPadding, - uint32_t aFlags) -{ - NS_ASSERTION(mPD, "Pages are supposed to have page data"); - nscoord height = (!mPD || mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) - ? NS_UNCONSTRAINEDSIZE - : (mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom()); - return nsSize(aAvailableWidth, height); -} - NS_IMETHODIMP nsPageContentFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -57,18 +44,19 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, // Set our size up front, since some parts of reflow depend on it // being already set. Note that the computed height may be // unconstrained; that's ok. Consumers should watch out for that. - SetSize(nsSize(aReflowState.availableWidth, aReflowState.availableHeight)); + nsSize maxSize(aReflowState.ComputedWidth(), + aReflowState.ComputedHeight()); + SetSize(maxSize); // A PageContentFrame must always have one child: the canvas frame. // Resize our frame allowing it only to be as big as we are // XXX Pay attention to the page's border and padding... if (mFrames.NotEmpty()) { nsIFrame* frame = mFrames.FirstChild(); - nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize); - kidReflowState.SetComputedHeight(aReflowState.availableHeight); + kidReflowState.SetComputedHeight(maxSize.height); - mPD->mPageContentSize = aReflowState.availableWidth; + mPD->mPageContentSize = maxSize.width; // Reflow the page content area rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); @@ -112,9 +100,9 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext, NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete"); // Return our desired size - aDesiredSize.width = aReflowState.availableWidth; - if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) { - aDesiredSize.height = aReflowState.availableHeight; + aDesiredSize.width = aReflowState.ComputedWidth(); + if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) { + aDesiredSize.height = aReflowState.ComputedHeight(); } FinishAndStoreOverflow(&aDesiredSize); diff --git a/layout/generic/nsPageContentFrame.h b/layout/generic/nsPageContentFrame.h index 88834a9d25d..462491fa8bd 100644 --- a/layout/generic/nsPageContentFrame.h +++ b/layout/generic/nsPageContentFrame.h @@ -33,15 +33,6 @@ public: virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; } - /** - * Computes page size based on shared page data; SetSharedPageData must be - * given valid data first. - */ - virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, - nsSize aCBSize, nscoord aAvailableWidth, - nsSize aMargin, nsSize aBorder, nsSize aPadding, - uint32_t aFlags) MOZ_OVERRIDE; - virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; } /** diff --git a/layout/generic/nsPageFrame.cpp b/layout/generic/nsPageFrame.cpp index 8c1c6bc3a08..5a5ed5a28c9 100644 --- a/layout/generic/nsPageFrame.cpp +++ b/layout/generic/nsPageFrame.cpp @@ -72,10 +72,9 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) { avHeight = NS_UNCONSTRAINEDSIZE; } else { - avHeight = mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom(); + avHeight = mPD->mReflowSize.height; } - nsSize maxSize(mPD->mReflowSize.width - mPD->mReflowMargin.LeftRight(), - avHeight); + nsSize maxSize(mPD->mReflowSize.width, avHeight); float scale = aPresContext->GetPageScale(); maxSize.width = NSToCoordCeil(maxSize.width / scale); if (maxSize.height != NS_UNCONSTRAINEDSIZE) { @@ -97,9 +96,46 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext, kidReflowState.mFlags.mIsTopOfPage = true; kidReflowState.mFlags.mTableIsSplittable = true; + // Use the margins given in the @page rule. + // If a margin is 'auto', use the margin from the print settings for that side. + nsMargin pageContentMargin; + const nsStyleSides& marginStyle = kidReflowState.mStyleMargin->mMargin; + NS_FOR_CSS_SIDES(side) { + if (marginStyle.GetUnit(side) == eStyleUnit_Auto) { + pageContentMargin.Side(side) = mPD->mReflowMargin.Side(side); + } else { + pageContentMargin.Side(side) = kidReflowState.mComputedMargin.Side(side); + } + } + + + nscoord maxWidth = maxSize.width - pageContentMargin.LeftRight() / scale; + nscoord maxHeight; + if (maxSize.height == NS_UNCONSTRAINEDSIZE) { + maxHeight = NS_UNCONSTRAINEDSIZE; + } else { + maxHeight = maxSize.height - pageContentMargin.TopBottom() / scale; + } + + // Check the width and height, if they're too small we reset the margins + // back to the default. + if (maxWidth < onePixelInTwips || + (maxHeight != NS_UNCONSTRAINEDSIZE && maxHeight < onePixelInTwips)) { + NS_FOR_CSS_SIDES(side) { + pageContentMargin.Side(side) = mPD->mReflowMargin.Side(side); + } + maxWidth = maxSize.width - pageContentMargin.LeftRight() / scale; + if (maxHeight != NS_UNCONSTRAINEDSIZE) { + maxHeight = maxSize.height - pageContentMargin.TopBottom() / scale; + } + } + + kidReflowState.SetComputedWidth(maxWidth); + kidReflowState.SetComputedHeight(maxHeight); + // calc location of frame - nscoord xc = mPD->mReflowMargin.left + mPD->mExtraMargin.left; - nscoord yc = mPD->mReflowMargin.top + mPD->mExtraMargin.top; + nscoord xc = pageContentMargin.left; + nscoord yc = pageContentMargin.top; // Get the child's desired size ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus); @@ -220,7 +256,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext, nscoord x = aRect.x; switch (aJust) { case nsIPrintSettings::kJustLeft: - x += mPD->mExtraMargin.left + mPD->mEdgePaperMargin.left; + x += mPD->mEdgePaperMargin.left; break; case nsIPrintSettings::kJustCenter: @@ -228,7 +264,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext, break; case nsIPrintSettings::kJustRight: - x += aRect.width - width - mPD->mExtraMargin.right - mPD->mEdgePaperMargin.right; + x += aRect.width - width - mPD->mEdgePaperMargin.right; break; } // switch @@ -345,9 +381,9 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext, nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str); nscoord y; if (aHeaderFooter == eHeader) { - y = aRect.y + mPD->mExtraMargin.top + mPD->mEdgePaperMargin.top; + y = aRect.y + mPD->mEdgePaperMargin.top; } else { - y = aRect.YMost() - aHeight - mPD->mExtraMargin.bottom - mPD->mEdgePaperMargin.bottom; + y = aRect.YMost() - aHeight - mPD->mEdgePaperMargin.bottom; } // set up new clip and draw the text @@ -511,8 +547,7 @@ nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, nsRect clipRect(nsPoint(0, 0), child->GetSize()); // Note: this computation matches how we compute maxSize.height // in nsPageFrame::Reflow - nscoord expectedPageContentHeight = - NSToCoordCeil((GetSize().height - mPD->mReflowMargin.TopBottom()) / scale); + nscoord expectedPageContentHeight = NSToCoordCeil(GetSize().height / scale); if (clipRect.height > expectedPageContentHeight) { // We're doing print-selection, with one long page-content frame. // Clip to the appropriate page-content slice for the current page. diff --git a/layout/generic/nsSimplePageSequence.cpp b/layout/generic/nsSimplePageSequence.cpp index e5dd41d1c66..09baa2437af 100644 --- a/layout/generic/nsSimplePageSequence.cpp +++ b/layout/generic/nsSimplePageSequence.cpp @@ -65,7 +65,6 @@ nsSharedPageData::nsSharedPageData() : mDocURL(nullptr), mReflowSize(0,0), mReflowMargin(0,0,0,0), - mExtraMargin(0,0,0,0), mEdgePaperMargin(0,0,0,0), mPageContentXMost(0), mPageContentSize(0) @@ -220,31 +219,12 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, } mPageData->mReflowMargin = mMargin; - // Compute the size of each page and the x coordinate that each page will - // be placed at - nscoord extraThreshold = NS_MAX(pageSize.width, pageSize.height)/10; - int32_t gapInTwips = Preferences::GetInt("print.print_extra_margin"); - gapInTwips = NS_MAX(0, gapInTwips); - - nscoord extraGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); - extraGap = NS_MIN(extraGap, extraThreshold); // clamp to 1/10 of the largest dim of the page - - nsMargin extraMargin(0,0,0,0); - if (aPresContext->IsScreen()) { - extraMargin.SizeTo(extraGap, extraGap, extraGap, extraGap); - } - - mPageData->mExtraMargin = extraMargin; - // 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 + extraMargin.LeftRight(), - pageSize.height + extraMargin.TopBottom()); - // Tile the pages vertically nsHTMLReflowMetrics kidSize; for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) { @@ -254,7 +234,7 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, // Reflow the page nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, - availSize); + pageSize); nsReflowStatus status; kidReflowState.SetComputedWidth(kidReflowState.availableWidth); diff --git a/layout/generic/nsSimplePageSequence.h b/layout/generic/nsSimplePageSequence.h index 4d2e1f8c719..5955af07528 100644 --- a/layout/generic/nsSimplePageSequence.h +++ b/layout/generic/nsSimplePageSequence.h @@ -31,9 +31,6 @@ public: nsSize mReflowSize; nsMargin mReflowMargin; - // Extra Margin between the device area and the edge of the page; - // approximates unprintable area - nsMargin mExtraMargin; // Margin for headers and footers; it defaults to 4/100 of an inch on UNIX // and 0 elsewhere; I think it has to do with some inconsistency in page size // computations diff --git a/layout/reftests/printing/115199-1-ref.html b/layout/reftests/printing/115199-1-ref.html new file mode 100644 index 00000000000..7899e1c092f --- /dev/null +++ b/layout/reftests/printing/115199-1-ref.html @@ -0,0 +1,20 @@ + + + + + + +
+ + diff --git a/layout/reftests/printing/115199-1.html b/layout/reftests/printing/115199-1.html new file mode 100644 index 00000000000..1aaef1e7b02 --- /dev/null +++ b/layout/reftests/printing/115199-1.html @@ -0,0 +1,25 @@ + + + + + + +
+ + diff --git a/layout/reftests/printing/115199-2-ref.html b/layout/reftests/printing/115199-2-ref.html new file mode 100644 index 00000000000..b6c15e62d29 --- /dev/null +++ b/layout/reftests/printing/115199-2-ref.html @@ -0,0 +1,18 @@ + + + + + + +
+ + diff --git a/layout/reftests/printing/115199-2a.html b/layout/reftests/printing/115199-2a.html new file mode 100644 index 00000000000..1e70f47e354 --- /dev/null +++ b/layout/reftests/printing/115199-2a.html @@ -0,0 +1,24 @@ + + + + + + +
+ + diff --git a/layout/reftests/printing/115199-2b.html b/layout/reftests/printing/115199-2b.html new file mode 100644 index 00000000000..620542fe2c7 --- /dev/null +++ b/layout/reftests/printing/115199-2b.html @@ -0,0 +1,24 @@ + + + + + + +
+ + diff --git a/layout/reftests/printing/reftest.list b/layout/reftests/printing/reftest.list index 55d6378d132..13e9543c94d 100644 --- a/layout/reftests/printing/reftest.list +++ b/layout/reftests/printing/reftest.list @@ -20,5 +20,8 @@ == 626395-2c.html 626395-2-ref.html == 626395-2d.html 626395-2-ref.html == 652178-1.html 652178-1-ref.html +== 115199-1.html 115199-1-ref.html +== 115199-2a.html 115199-2-ref.html +== 115199-2b.html 115199-2-ref.html == 652178-1.html 652178-1-ref2.html == 745025-1.html 745025-1-ref.html