mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 115199 - CSS2 @page rule rendering support. r=roc
This commit is contained in:
parent
cf3b64d2eb
commit
3b71cbe23b
@ -24,19 +24,6 @@ NS_NewPageContentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
|||||||
|
|
||||||
NS_IMPL_FRAMEARENA_HELPERS(nsPageContentFrame)
|
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
|
NS_IMETHODIMP
|
||||||
nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
||||||
nsHTMLReflowMetrics& aDesiredSize,
|
nsHTMLReflowMetrics& aDesiredSize,
|
||||||
@ -57,18 +44,19 @@ nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
// Set our size up front, since some parts of reflow depend on it
|
// Set our size up front, since some parts of reflow depend on it
|
||||||
// being already set. Note that the computed height may be
|
// being already set. Note that the computed height may be
|
||||||
// unconstrained; that's ok. Consumers should watch out for that.
|
// 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.
|
// A PageContentFrame must always have one child: the canvas frame.
|
||||||
// Resize our frame allowing it only to be as big as we are
|
// Resize our frame allowing it only to be as big as we are
|
||||||
// XXX Pay attention to the page's border and padding...
|
// XXX Pay attention to the page's border and padding...
|
||||||
if (mFrames.NotEmpty()) {
|
if (mFrames.NotEmpty()) {
|
||||||
nsIFrame* frame = mFrames.FirstChild();
|
nsIFrame* frame = mFrames.FirstChild();
|
||||||
nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
|
|
||||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
|
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
|
// Reflow the page content area
|
||||||
rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus);
|
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");
|
NS_ASSERTION(NS_FRAME_IS_COMPLETE(fixedStatus), "fixed frames can be truncated, but not incomplete");
|
||||||
|
|
||||||
// Return our desired size
|
// Return our desired size
|
||||||
aDesiredSize.width = aReflowState.availableWidth;
|
aDesiredSize.width = aReflowState.ComputedWidth();
|
||||||
if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
|
if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE) {
|
||||||
aDesiredSize.height = aReflowState.availableHeight;
|
aDesiredSize.height = aReflowState.ComputedHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
FinishAndStoreOverflow(&aDesiredSize);
|
FinishAndStoreOverflow(&aDesiredSize);
|
||||||
|
@ -33,15 +33,6 @@ public:
|
|||||||
|
|
||||||
virtual void SetSharedPageData(nsSharedPageData* aPD) { mPD = aPD; }
|
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; }
|
virtual bool HasTransformGetter() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,10 +72,9 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) {
|
if (mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE) {
|
||||||
avHeight = NS_UNCONSTRAINEDSIZE;
|
avHeight = NS_UNCONSTRAINEDSIZE;
|
||||||
} else {
|
} else {
|
||||||
avHeight = mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom();
|
avHeight = mPD->mReflowSize.height;
|
||||||
}
|
}
|
||||||
nsSize maxSize(mPD->mReflowSize.width - mPD->mReflowMargin.LeftRight(),
|
nsSize maxSize(mPD->mReflowSize.width, avHeight);
|
||||||
avHeight);
|
|
||||||
float scale = aPresContext->GetPageScale();
|
float scale = aPresContext->GetPageScale();
|
||||||
maxSize.width = NSToCoordCeil(maxSize.width / scale);
|
maxSize.width = NSToCoordCeil(maxSize.width / scale);
|
||||||
if (maxSize.height != NS_UNCONSTRAINEDSIZE) {
|
if (maxSize.height != NS_UNCONSTRAINEDSIZE) {
|
||||||
@ -97,9 +96,46 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
kidReflowState.mFlags.mIsTopOfPage = true;
|
kidReflowState.mFlags.mIsTopOfPage = true;
|
||||||
kidReflowState.mFlags.mTableIsSplittable = 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
|
// calc location of frame
|
||||||
nscoord xc = mPD->mReflowMargin.left + mPD->mExtraMargin.left;
|
nscoord xc = pageContentMargin.left;
|
||||||
nscoord yc = mPD->mReflowMargin.top + mPD->mExtraMargin.top;
|
nscoord yc = pageContentMargin.top;
|
||||||
|
|
||||||
// Get the child's desired size
|
// Get the child's desired size
|
||||||
ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus);
|
ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, xc, yc, 0, aStatus);
|
||||||
@ -220,7 +256,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
|
|||||||
nscoord x = aRect.x;
|
nscoord x = aRect.x;
|
||||||
switch (aJust) {
|
switch (aJust) {
|
||||||
case nsIPrintSettings::kJustLeft:
|
case nsIPrintSettings::kJustLeft:
|
||||||
x += mPD->mExtraMargin.left + mPD->mEdgePaperMargin.left;
|
x += mPD->mEdgePaperMargin.left;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIPrintSettings::kJustCenter:
|
case nsIPrintSettings::kJustCenter:
|
||||||
@ -228,7 +264,7 @@ nscoord nsPageFrame::GetXPosition(nsRenderingContext& aRenderingContext,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIPrintSettings::kJustRight:
|
case nsIPrintSettings::kJustRight:
|
||||||
x += aRect.width - width - mPD->mExtraMargin.right - mPD->mEdgePaperMargin.right;
|
x += aRect.width - width - mPD->mEdgePaperMargin.right;
|
||||||
break;
|
break;
|
||||||
} // switch
|
} // switch
|
||||||
|
|
||||||
@ -345,9 +381,9 @@ nsPageFrame::DrawHeaderFooter(nsRenderingContext& aRenderingContext,
|
|||||||
nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
|
nscoord x = GetXPosition(aRenderingContext, aRect, aJust, str);
|
||||||
nscoord y;
|
nscoord y;
|
||||||
if (aHeaderFooter == eHeader) {
|
if (aHeaderFooter == eHeader) {
|
||||||
y = aRect.y + mPD->mExtraMargin.top + mPD->mEdgePaperMargin.top;
|
y = aRect.y + mPD->mEdgePaperMargin.top;
|
||||||
} else {
|
} 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
|
// set up new clip and draw the text
|
||||||
@ -511,8 +547,7 @@ nsPageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
nsRect clipRect(nsPoint(0, 0), child->GetSize());
|
nsRect clipRect(nsPoint(0, 0), child->GetSize());
|
||||||
// Note: this computation matches how we compute maxSize.height
|
// Note: this computation matches how we compute maxSize.height
|
||||||
// in nsPageFrame::Reflow
|
// in nsPageFrame::Reflow
|
||||||
nscoord expectedPageContentHeight =
|
nscoord expectedPageContentHeight = NSToCoordCeil(GetSize().height / scale);
|
||||||
NSToCoordCeil((GetSize().height - mPD->mReflowMargin.TopBottom()) / scale);
|
|
||||||
if (clipRect.height > expectedPageContentHeight) {
|
if (clipRect.height > expectedPageContentHeight) {
|
||||||
// We're doing print-selection, with one long page-content frame.
|
// We're doing print-selection, with one long page-content frame.
|
||||||
// Clip to the appropriate page-content slice for the current page.
|
// Clip to the appropriate page-content slice for the current page.
|
||||||
|
@ -65,7 +65,6 @@ nsSharedPageData::nsSharedPageData() :
|
|||||||
mDocURL(nullptr),
|
mDocURL(nullptr),
|
||||||
mReflowSize(0,0),
|
mReflowSize(0,0),
|
||||||
mReflowMargin(0,0,0,0),
|
mReflowMargin(0,0,0,0),
|
||||||
mExtraMargin(0,0,0,0),
|
|
||||||
mEdgePaperMargin(0,0,0,0),
|
mEdgePaperMargin(0,0,0,0),
|
||||||
mPageContentXMost(0),
|
mPageContentXMost(0),
|
||||||
mPageContentSize(0)
|
mPageContentSize(0)
|
||||||
@ -220,31 +219,12 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
}
|
}
|
||||||
mPageData->mReflowMargin = mMargin;
|
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
|
// We use the CSS "margin" property on the -moz-page pseudoelement
|
||||||
// to determine the space between each page in print preview.
|
// to determine the space between each page in print preview.
|
||||||
// Keep a running y-offset for each page.
|
// Keep a running y-offset for each page.
|
||||||
nscoord y = 0;
|
nscoord y = 0;
|
||||||
nscoord maxXMost = 0;
|
nscoord maxXMost = 0;
|
||||||
|
|
||||||
nsSize availSize(pageSize.width + extraMargin.LeftRight(),
|
|
||||||
pageSize.height + extraMargin.TopBottom());
|
|
||||||
|
|
||||||
// Tile the pages vertically
|
// Tile the pages vertically
|
||||||
nsHTMLReflowMetrics kidSize;
|
nsHTMLReflowMetrics kidSize;
|
||||||
for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) {
|
for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) {
|
||||||
@ -254,7 +234,7 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// Reflow the page
|
// Reflow the page
|
||||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
|
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
|
||||||
availSize);
|
pageSize);
|
||||||
nsReflowStatus status;
|
nsReflowStatus status;
|
||||||
|
|
||||||
kidReflowState.SetComputedWidth(kidReflowState.availableWidth);
|
kidReflowState.SetComputedWidth(kidReflowState.availableWidth);
|
||||||
|
@ -31,9 +31,6 @@ public:
|
|||||||
|
|
||||||
nsSize mReflowSize;
|
nsSize mReflowSize;
|
||||||
nsMargin mReflowMargin;
|
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
|
// 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
|
// and 0 elsewhere; I think it has to do with some inconsistency in page size
|
||||||
// computations
|
// computations
|
||||||
|
20
layout/reftests/printing/115199-1-ref.html
Normal file
20
layout/reftests/printing/115199-1-ref.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0.1in 0.1in;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
border: 0.25in solid green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
layout/reftests/printing/115199-1.html
Normal file
25
layout/reftests/printing/115199-1.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
/*
|
||||||
|
* Default page margins are .5in and the reference file adds .1inch margin
|
||||||
|
* to the body hence we do .6in to match this.
|
||||||
|
*/
|
||||||
|
margin: 0.6in;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.25in solid green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
18
layout/reftests/printing/115199-2-ref.html
Normal file
18
layout/reftests/printing/115199-2-ref.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.25in solid green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
layout/reftests/printing/115199-2a.html
Normal file
24
layout/reftests/printing/115199-2a.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
/*
|
||||||
|
* Test a margin that causes the page to have zero width.
|
||||||
|
*/
|
||||||
|
margin: 0 2.5in;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.25in solid green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
layout/reftests/printing/115199-2b.html
Normal file
24
layout/reftests/printing/115199-2b.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="reftest-print">
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
@page {
|
||||||
|
/*
|
||||||
|
* Test huge margins, they should be reset back the default margin size.
|
||||||
|
*/
|
||||||
|
margin: 10in;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100%;
|
||||||
|
border: 0.25in solid green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -20,5 +20,8 @@
|
|||||||
== 626395-2c.html 626395-2-ref.html
|
== 626395-2c.html 626395-2-ref.html
|
||||||
== 626395-2d.html 626395-2-ref.html
|
== 626395-2d.html 626395-2-ref.html
|
||||||
== 652178-1.html 652178-1-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
|
== 652178-1.html 652178-1-ref2.html
|
||||||
== 745025-1.html 745025-1-ref.html
|
== 745025-1.html 745025-1-ref.html
|
||||||
|
Loading…
Reference in New Issue
Block a user