Bug 624699. Fix some landscape printing bugs. r=roc
authorAdrian Johnson <ajohnson@redneon.com>
Thu, 14 Jul 2011 13:02:20 -0400
changeset 72827 0ab660ee24ab2a9f0909d0a592a9000541f49995
parent 72826 553625d7875d4b0e855cab739b64298a84003df1
child 72828 caf2dc068c233798f49b39f1c4a98e6c7c0e4d89
push id20776
push usereakhgari@mozilla.com
push dateFri, 15 Jul 2011 12:13:35 +0000
treeherdermozilla-central@9349ae9094f6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs624699
milestone8.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 624699. Fix some landscape printing bugs. r=roc Specifically: 1) Only rotate print output for PostScript, not PDF. 2) Rotate in the correct direction for PostScript. 3) Set the %%Orientation comment correctly.
gfx/thebes/gfxASurface.h
gfx/thebes/gfxContext.cpp
gfx/thebes/gfxPSSurface.cpp
gfx/thebes/gfxPSSurface.h
layout/generic/nsSimplePageSequence.cpp
layout/printing/nsPrintEngine.cpp
widget/src/gtk2/nsDeviceContextSpecG.cpp
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -122,16 +122,18 @@ public:
 
     gfxSurfaceType GetType() const;
 
     gfxContentType GetContentType() const;
 
     void SetDeviceOffset(const gfxPoint& offset);
     gfxPoint GetDeviceOffset() const;
 
+    virtual PRBool GetRotateForLandscape() { return PR_FALSE; }
+
     void Flush() const;
     void MarkDirty();
     void MarkDirty(const gfxRect& r);
 
     /* Printing backend functions */
     virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
     virtual nsresult EndPrinting();
     virtual nsresult AbortPrinting();
--- a/gfx/thebes/gfxContext.cpp
+++ b/gfx/thebes/gfxContext.cpp
@@ -58,16 +58,25 @@
 
 gfxContext::gfxContext(gfxASurface *surface) :
     mSurface(surface)
 {
     MOZ_COUNT_CTOR(gfxContext);
 
     mCairo = cairo_create(surface->CairoSurface());
     mFlags = surface->GetDefaultContextFlags();
+    if (mSurface->GetRotateForLandscape()) {
+        // Rotate page 90 degrees to draw landscape page on portrait paper
+        gfxIntSize size = mSurface->GetSize();
+        Translate(gfxPoint(0, size.width));
+        gfxMatrix matrix(0, -1,
+                         1,  0,
+                         0,  0);
+        Multiply(matrix);
+    }
 }
 gfxContext::~gfxContext()
 {
     cairo_destroy(mCairo);
 
     MOZ_COUNT_DTOR(gfxContext);
 }
 
--- a/gfx/thebes/gfxPSSurface.cpp
+++ b/gfx/thebes/gfxPSSurface.cpp
@@ -49,31 +49,49 @@ write_func(void *closure, const unsigned
         if (NS_FAILED(out->Write((const char*)data, length, &wrote)))
             break;
         data += wrote; length -= wrote;
     } while (length > 0);
     NS_ASSERTION(length == 0, "not everything was written to the file");
     return CAIRO_STATUS_SUCCESS;
 }
 
-gfxPSSurface::gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints)
-    : mStream(aStream), mXDPI(-1), mYDPI(-1), mSize(aSizeInPoints)
+gfxPSSurface::gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints, PageOrientation aOrientation)
+    : mStream(aStream), mXDPI(-1), mYDPI(-1), mOrientation(aOrientation)
 {
-    cairo_surface_t* ps_surface = cairo_ps_surface_create_for_stream(write_func, (void*)mStream, mSize.width, mSize.height);
+    mSize = gfxIntSize(aSizeInPoints.width, aSizeInPoints.height);
+
+    // The PS output does not specify the page size so to print
+    // landscape we need to rotate the drawing 90 degrees and print on
+    // portrait paper. If printing landscape, swap the width/height
+    // supplied to cairo to select a portrait print area. gfxContext
+    // will perform the rotation when GetRotateForLandscape() is TRUE.
+    gfxIntSize cairoSize;
+    if (mOrientation == PORTRAIT) {
+        cairoSize = mSize;
+    } else {
+        cairoSize = gfxIntSize(mSize.height, mSize.width);
+    }
+    cairo_surface_t* ps_surface = cairo_ps_surface_create_for_stream(write_func, (void*)mStream, cairoSize.width, cairoSize.height);
     cairo_ps_surface_restrict_to_level(ps_surface, CAIRO_PS_LEVEL_2);
     Init(ps_surface);
 }
 
 gfxPSSurface::~gfxPSSurface()
 {
 }
 
 nsresult
 gfxPSSurface::BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName)
 {
+    if (mOrientation == PORTRAIT) {
+      cairo_ps_surface_dsc_comment (mSurface, "%%Orientation: Portrait");
+    } else {
+      cairo_ps_surface_dsc_comment (mSurface, "%%Orientation: Landscape");
+    }
     return NS_OK;
 }
 
 nsresult
 gfxPSSurface::EndPrinting()
 {
     return NS_OK;
 }
--- a/gfx/thebes/gfxPSSurface.h
+++ b/gfx/thebes/gfxPSSurface.h
@@ -42,41 +42,49 @@
 
 /* for the output stream */
 #include "nsCOMPtr.h"
 #include "nsIOutputStream.h"
 #include "gfxContext.h"
 
 class THEBES_API gfxPSSurface : public gfxASurface {
 public:
-    gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints);
+    enum PageOrientation {
+        PORTRAIT,
+        LANDSCAPE
+    };
+
+    gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints, PageOrientation aOrientation);
     virtual ~gfxPSSurface();
 
     virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
     virtual nsresult EndPrinting();
     virtual nsresult AbortPrinting();
     virtual nsresult BeginPage();
     virtual nsresult EndPage();
     virtual void Finish();
 
     void SetDPI(double x, double y);
     void GetDPI(double *xDPI, double *yDPI);
 
+    virtual PRBool GetRotateForLandscape() { return (mOrientation == LANDSCAPE); }
+
     // this is in points!
     virtual const gfxIntSize GetSize() const
     {
-        return gfxIntSize(mSize.width, mSize.height);
+        return mSize;
     }
 
     virtual PRInt32 GetDefaultContextFlags() const
     {
         return gfxContext::FLAG_SIMPLIFY_OPERATORS |
                gfxContext::FLAG_DISABLE_SNAPPING;
     }
 
 private:
     nsCOMPtr<nsIOutputStream> mStream;
     double mXDPI;
     double mYDPI;
-    gfxSize mSize;
+    gfxIntSize mSize;
+    PageOrientation mOrientation;
 };
 
 #endif /* GFX_PSSURFACE_H */
--- a/layout/generic/nsSimplePageSequence.cpp
+++ b/layout/generic/nsSimplePageSequence.cpp
@@ -609,29 +609,16 @@ nsSimplePageSequenceFrame::PrintNextPage
       }
 
       PR_PL(("SeqFr::PrintNextPage -> %p PageNo: %d", pf, mPageNum));
 
       nsRefPtr<nsRenderingContext> renderingContext;
       dc->CreateRenderingContext(*getter_AddRefs(renderingContext));
       NS_ENSURE_TRUE(renderingContext, NS_ERROR_OUT_OF_MEMORY);
 
-#if defined(XP_UNIX) && !defined(XP_MACOSX)
-      // On linux, need to rotate landscape-mode output on printed surfaces
-      PRInt32 orientation;
-      mPageData->mPrintSettings->GetOrientation(&orientation);
-      if (nsIPrintSettings::kLandscapeOrientation == orientation) {
-        // Shift up by one landscape-page-height (in points) before we rotate.
-        float offset = POINTS_PER_INCH_FLOAT *
-           (mCurrentPageFrame->GetSize().height / float(dc->AppUnitsPerCSSInch()));
-        renderingContext->ThebesContext()->Translate(gfxPoint(offset, 0));
-        renderingContext->ThebesContext()->Rotate(M_PI/2);
-      }
-#endif // XP_UNIX && !XP_MACOSX
-
       nsRect drawingRect(nsPoint(0, 0),
                          mCurrentPageFrame->GetSize());
       nsRegion drawingRegion(drawingRect);
       nsLayoutUtils::PaintFrame(renderingContext, mCurrentPageFrame,
                                 drawingRegion, NS_RGBA(0,0,0,0),
                                 nsLayoutUtils::PAINT_SYNC_DECODE_IMAGES);
 
       if (mSelectionHeight >= 0 && selectionY < mSelectionHeight) {
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -1907,30 +1907,17 @@ nsPrintEngine::ReflowPrintObject(nsPrint
       view = view->GetFirstChild();
       NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
       parentView = view;
       canCreateScrollbars = PR_FALSE;
     }
   } else {
     nscoord pageWidth, pageHeight;
     mPrt->mPrintDC->GetDeviceSurfaceDimensions(pageWidth, pageHeight);
-#if defined(XP_UNIX) && !defined(XP_MACOSX)
-    // If we're in landscape mode on Linux, the device surface will have 
-    // been rotated, so for the purposes of reflowing content, we'll 
-    // treat device's height as our width and its width as our height, 
-    PRInt32 orientation;
-    mPrt->mPrintSettings->GetOrientation(&orientation);
-    if (nsIPrintSettings::kLandscapeOrientation == orientation) {
-      adjSize = nsSize(pageHeight, pageWidth);
-    } else {
-      adjSize = nsSize(pageWidth, pageHeight);
-    }
-#else
     adjSize = nsSize(pageWidth, pageHeight);
-#endif // XP_UNIX && !XP_MACOSX
     documentIsTopLevel = PR_TRUE;
 
     if (mIsCreatingPrintPreview) {
       nsCOMPtr<nsIDocumentViewer> dv = do_QueryInterface(mDocViewerPrint);
       if (dv) {
         parentView = dv->FindContainerView();
       }
     }
--- a/widget/src/gtk2/nsDeviceContextSpecG.cpp
+++ b/widget/src/gtk2/nsDeviceContextSpecG.cpp
@@ -420,26 +420,16 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::Ge
   *aSurface = nsnull;
 
   const char *path;
   GetPath(&path);
 
   double width, height;
   mPrintSettings->GetEffectivePageSize(&width, &height);
 
-  // If we're in landscape mode, we'll be rotating the output --
-  // need to swap width & height.
-  PRInt32 orientation;
-  mPrintSettings->GetOrientation(&orientation);
-  if (nsIPrintSettings::kLandscapeOrientation == orientation) {
-    double tmp = width;
-    width = height;
-    height = tmp;
-  }
-
   // convert twips to points
   width  /= TWIPS_PER_POINT_FLOAT;
   height /= TWIPS_PER_POINT_FLOAT;
 
   DO_PR_DEBUG_LOG(("\"%s\", %f, %f\n", path, width, height));
   nsresult rv;
 
   // Spool file. Use Glib's temporary file function since we're
@@ -502,17 +492,23 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::Ge
         format = nsIPrintSettings::kOutputFormatPS;
       }
     }
   }
 
   if (format == nsIPrintSettings::kOutputFormatPDF) {
     surface = new gfxPDFSurface(stream, surfaceSize);
   } else {
-    surface = new gfxPSSurface(stream, surfaceSize);
+    PRInt32 orientation;
+    mPrintSettings->GetOrientation(&orientation);
+    if (nsIPrintSettings::kPortraitOrientation == orientation) {
+      surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::PORTRAIT);
+    } else {
+      surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::LANDSCAPE);
+    }
   }
 
   if (!surface)
     return NS_ERROR_OUT_OF_MEMORY;
 
   surface.swap(*aSurface);
 
   return NS_OK;