Bug 663028 - Make Print Preview themable with CSS, and modernize its look r=roc
authorMichael Ventnor <mventnor@mozilla.com>
Fri, 10 Jun 2011 20:07:26 +1000
changeset 71386 251688029a9d0427ad83d9cf869ec138dda84a57
parent 71369 1e3af440ce238c3dcd850237c340a4cfb741332c
child 71387 bf46495e80aeda5c898a81ae771ab55c61276f1e
push id159
push usereakhgari@mozilla.com
push dateTue, 16 Aug 2011 17:53:11 +0000
treeherdermozilla-beta@8786e3e49240 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs663028
milestone7.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 663028 - Make Print Preview themable with CSS, and modernize its look r=roc
layout/base/nsCSSRendering.cpp
layout/base/nsDisplayItemTypes.h
layout/base/nsDocumentViewer.cpp
layout/generic/nsIPageSequenceFrame.h
layout/generic/nsPageFrame.cpp
layout/generic/nsPageFrame.h
layout/generic/nsSimplePageSequence.cpp
layout/generic/nsSimplePageSequence.h
layout/style/ua.css
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -918,17 +918,16 @@ nsCSSRendering::FindNonTransparentBackgr
 // it does not actually paint a background, we need to get the right
 // background style so we correctly detect transparent documents.
 PRBool
 nsCSSRendering::IsCanvasFrame(nsIFrame* aFrame)
 {
   nsIAtom* frameType = aFrame->GetType();
   return frameType == nsGkAtoms::canvasFrame ||
          frameType == nsGkAtoms::rootFrame ||
-         frameType == nsGkAtoms::pageFrame ||
          frameType == nsGkAtoms::pageContentFrame ||
          frameType == nsGkAtoms::viewportFrame;
 }
 
 nsIFrame*
 nsCSSRendering::FindBackgroundStyleFrame(nsIFrame* aForFrame)
 {
   const nsStyleBackground* result = aForFrame->GetStyleBackground();
--- a/layout/base/nsDisplayItemTypes.h
+++ b/layout/base/nsDisplayItemTypes.h
@@ -74,17 +74,16 @@ enum Type {
   TYPE_OPACITY,
   TYPE_OPTION_EVENT_GRABBER,
   TYPE_OUTLINE,
   TYPE_OWN_LAYER,
   TYPE_PAGE_CONTENT,
   TYPE_PAGE_SEQUENCE,
   TYPE_PLUGIN,
   TYPE_PLUGIN_READBACK,
-  TYPE_PRINT_PREVIEW_BACKGROUND,
   TYPE_PRINT_PLUGIN,
   TYPE_REMOTE,
   TYPE_REMOTE_SHADOW,
   TYPE_SCROLL_LAYER,
   TYPE_SCROLL_INFO_LAYER,
   TYPE_SELECTION_OVERLAY,
   TYPE_SOLID_COLOR,
   TYPE_SVG_EFFECTS,
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -3854,26 +3854,18 @@ DocumentViewerImpl::PrintPreviewNavigate
     }
   } else { // If we get here we are doing "GoTo"
     if (aPageNum < 0 || aPageNum > pageCount) {
       return NS_OK;
     }
   }
 
   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;
 
 }
 
 /* readonly attribute nsIPrintSettings globalPrintSettings; */
 NS_IMETHODIMP
--- a/layout/generic/nsIPageSequenceFrame.h
+++ b/layout/generic/nsIPageSequenceFrame.h
@@ -76,18 +76,15 @@ public:
   NS_IMETHOD IsDoingPrintRange(PRBool* aDoing) = 0;
   NS_IMETHOD GetPrintRange(PRInt32* aFromPage, PRInt32* aToPage) = 0;
 
   NS_IMETHOD DoPageEnd() = 0;
   NS_IMETHOD SetSelectionHeight(nscoord aYOffset, nscoord aHeight) = 0;
 
   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;
 };
 
 #endif /* nsIPageSequenceFrame_h___ */
 
 
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -145,16 +145,20 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPres
   PR_PL(("PageFrame::Reflow %p ", this));
   PR_PL(("[%d,%d][%d,%d]\n", aDesiredSize.width, aDesiredSize.height, aReflowState.availableWidth, aReflowState.availableHeight));
 
   // Return our desired size
   aDesiredSize.width = aReflowState.availableWidth;
   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));
 
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 nsIAtom*
@@ -388,22 +392,16 @@ nsPageFrame::DrawHeaderFooter(nsRenderin
     aRenderingContext.PushState();
     aRenderingContext.SetColor(NS_RGB(0,0,0));
     aRenderingContext.IntersectClip(aRect);
     nsLayoutUtils::DrawString(this, &aRenderingContext, str.get(), str.Length(), nsPoint(x, y + aAscent));
     aRenderingContext.PopState();
   }
 }
 
-static void PaintPrintPreviewBackground(nsIFrame* aFrame, nsRenderingContext* aCtx,
-                                        const nsRect& aDirtyRect, nsPoint aPt)
-{
-  static_cast<nsPageFrame*>(aFrame)->PaintPrintPreviewBackground(*aCtx, aPt);
-}
-
 static void PaintPageContent(nsIFrame* aFrame, nsRenderingContext* aCtx,
                              const nsRect& aDirtyRect, nsPoint aPt)
 {
   static_cast<nsPageFrame*>(aFrame)->PaintPageContent(*aCtx, aDirtyRect, aPt);
 }
 
 static void PaintHeaderFooter(nsIFrame* aFrame, nsRenderingContext* aCtx,
                               const nsRect& aDirtyRect, nsPoint aPt)
@@ -416,20 +414,17 @@ NS_IMETHODIMP
 nsPageFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists)
 {
   nsDisplayListCollection set;
   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);
   }
 
   rv = set.BorderBackground()->AppendNewToTop(new (aBuilder)
         nsDisplayGeneric(aBuilder, this, ::PaintPageContent,
                          "PageContent",
                          nsDisplayItem::TYPE_PAGE_CONTENT));
   NS_ENSURE_SUCCESS(rv, rv);
@@ -451,66 +446,29 @@ void
 nsPageFrame::SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages) 
 { 
   mPageNum     = aPageNumber; 
   mTotNumPages = 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)
 {
   nsPresContext* pc = PresContext();
 
   if (!mPD->mPrintSettings) {
     if (pc->Type() == nsPresContext::eContext_PrintPreview || pc->IsDynamic())
       mPD->mPrintSettings = pc->GetPrintSettings();
     if (!mPD->mPrintSettings)
       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
   nsRefPtr<nsFontMetrics> fontMet;
   pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
                                      pc->GetUserFontSet(),
                                      *getter_AddRefs(fontMet));
 
--- a/layout/generic/nsPageFrame.h
+++ b/layout/generic/nsPageFrame.h
@@ -76,18 +76,20 @@ public:
   // For Printing
   //////////////////
 
   // Tell the page which page number it is out of how many
   virtual void  SetPageNumInfo(PRInt32 aPageNumber, PRInt32 aTotalPages);
 
   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,
                         const nsRect&        aDirtyRect,
                         nsPoint              aPt);
 
 protected:
   nsPageFrame(nsStyleContext* aContext);
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -82,17 +82,16 @@ nsSharedPageData::nsSharedPageData() :
   mDateTimeStr(nsnull),
   mHeadFootFont(nsnull),
   mPageNumFormat(nsnull),
   mPageNumAndTotalsFormat(nsnull),
   mDocTitle(nsnull),
   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),
   mPageContentSize(0)
 {
 }
 
 nsSharedPageData::~nsSharedPageData()
@@ -141,16 +140,32 @@ nsSimplePageSequenceFrame::~nsSimplePage
 }
 
 NS_QUERYFRAME_HEAD(nsSimplePageSequenceFrame)
   NS_QUERYFRAME_ENTRY(nsIPageSequenceFrame)
 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,
                                   const nsHTMLReflowState& aReflowState,
                                   nsReflowStatus&          aStatus)
 {
   NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(),
                   "A Page Sequence is only for real pages");
@@ -159,26 +174,22 @@ nsSimplePageSequenceFrame::Reflow(nsPres
   NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
 
   aStatus = NS_FRAME_COMPLETE;  // we're always complete
 
   // Don't do incremental reflow until we've taught tables how to do
   // 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) {
       mPageData->mPrintSettings = aPresContext->GetPrintSettings();
   }
 
   // now get out margins & edges
   if (mPageData->mPrintSettings) {
@@ -230,39 +241,31 @@ nsSimplePageSequenceFrame::Reflow(nsPres
   // be placed at
   nscoord extraThreshold = NS_MAX(pageSize.width, pageSize.height)/10;
   PRInt32 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
 
-  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;
   for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) {
     // Set the shared data into the page frame before reflow
     nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame);
     pf->SetSharedPageData(mPageData);
 
@@ -270,25 +273,29 @@ nsSimplePageSequenceFrame::Reflow(nsPres
     nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
                                      availSize);
     nsReflowStatus  status;
 
     kidReflowState.SetComputedWidth(kidReflowState.availableWidth);
     //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();
 
     if (NS_FRAME_IS_FULLY_COMPLETE(status)) {
       NS_ASSERTION(!kidNextInFlow, "bad child flow list");
     } else if (!kidNextInFlow) {
       // The page isn't complete and it doesn't have a next-in-flow, so
@@ -339,28 +346,26 @@ nsSimplePageSequenceFrame::Reflow(nsPres
                                               kTimeFormatNoSeconds,
                                               ltime,
                                               formattedDateString))) {
     PRUnichar * uStr = ToNewUnicode(formattedDateString);
     SetDateTimeStr(uStr); // memory will be freed
   }
 
   // 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);
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   return NS_OK;
 }
 
 //----------------------------------------------------------------------
--- a/layout/generic/nsSimplePageSequence.h
+++ b/layout/generic/nsSimplePageSequence.h
@@ -56,18 +56,16 @@ public:
   nsFont *    mHeadFootFont;
   PRUnichar * mPageNumFormat;
   PRUnichar * mPageNumAndTotalsFormat;
   PRUnichar * mDocTitle;
   PRUnichar * mDocURL;
 
   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;
   // 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
   nsMargin    mEdgePaperMargin;
 
@@ -96,35 +94,36 @@ public:
   NS_IMETHOD  BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                const nsRect&           aDirtyRect,
                                const nsDisplayListSet& aLists);
 
   // nsIPageSequenceFrame
   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);
 
   // Async Printing
   NS_IMETHOD StartPrint(nsPresContext*  aPresContext,
                         nsIPrintSettings* aPrintSettings,
                         PRUnichar*        aDocTitle,
                         PRUnichar*        aDocURL);
   NS_IMETHOD PrintNextPage();
   NS_IMETHOD GetCurrentPageNum(PRInt32* aPageNum);
   NS_IMETHOD GetNumPages(PRInt32* aNumPages);
   NS_IMETHOD IsDoingPrintRange(PRBool* aDoing);
   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
    *
    * @see nsGkAtoms::sequenceFrame
    */
   virtual nsIAtom* GetType() const;
   
 #ifdef NS_DEBUG
@@ -140,16 +139,22 @@ protected:
   virtual ~nsSimplePageSequenceFrame();
 
   void SetPageNumberFormat(const char* aPropName, const char* aDefPropVal, PRBool aPageNumOnly);
 
   // SharedPageData Helper methods
   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.
   nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
 
   nsSize       mSize;
   nsSharedPageData* mPageData; // data shared by all the nsPageFrames
 
--- a/layout/style/ua.css
+++ b/layout/style/ua.css
@@ -180,19 +180,31 @@
   unicode-bidi: inherit;
   /* inherit the outer frame's display, otherwise we turn into an inline */
   display: inherit !important;
   /* Carry through our parent's height so that %-height children get
   their heights set */
   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 {
   display: block !important;
 }
 
 *|*::-moz-pagebreak {
   display: block !important;