Bug 1278276 - Remove gfxPSSurface and move its logic to a PrintTargetPS subclass of PrintTarget. r=Bas
authorJonathan Watt <jwatt@jwatt.org>
Mon, 06 Jun 2016 16:10:28 +0100
changeset 301426 136d378b0efe1f02d72ce2771061535bb136d556
parent 301425 759cd5d6285b29e10fb121db1e831c558158f3be
child 301427 3f33cce615f98fc3f4a2887efd71c46a0358a8b3
push id30333
push usercbook@mozilla.com
push dateFri, 10 Jun 2016 13:39:58 +0000
treeherdermozilla-central@52679ce4756c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1278276
milestone50.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 1278276 - Remove gfxPSSurface and move its logic to a PrintTargetPS subclass of PrintTarget. r=Bas
gfx/src/nsDeviceContext.cpp
gfx/thebes/PrintTarget.cpp
gfx/thebes/PrintTarget.h
gfx/thebes/PrintTargetPS.cpp
gfx/thebes/PrintTargetPS.h
gfx/thebes/PrintTargetThebes.cpp
gfx/thebes/PrintTargetThebes.h
gfx/thebes/gfxASurface.h
gfx/thebes/gfxPSSurface.cpp
gfx/thebes/gfxPSSurface.h
gfx/thebes/moz.build
widget/gtk/nsDeviceContextSpecG.cpp
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -37,24 +37,16 @@
 #include "nsTArray.h"                   // for nsTArray, nsTArray_Impl
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "mozilla/gfx/Logging.h"
 
 #if !XP_MACOSX
 #include "gfxPDFSurface.h"
 #endif
 
-#ifdef MOZ_WIDGET_GTK
-#include "gfxPSSurface.h"
-#elif XP_WIN
-#include "gfxWindowsSurface.h"
-#elif XP_MACOSX
-#include "gfxQuartzSurface.h"
-#endif
-
 using namespace mozilla;
 using namespace mozilla::gfx;
 using mozilla::services::GetObserverService;
 
 class nsFontCache final : public nsIObserver
 {
 public:
     nsFontCache()   { MOZ_COUNT_CTOR(nsFontCache); }
--- a/gfx/thebes/PrintTarget.cpp
+++ b/gfx/thebes/PrintTarget.cpp
@@ -1,29 +1,83 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "PrintTarget.h"
 
+#include "cairo.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/Logging.h"
 
 namespace mozilla {
 namespace gfx {
 
-PrintTarget::PrintTarget(const IntSize& aSize)
-  : mSize(aSize)
+PrintTarget::PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize)
+  : mCairoSurface(aCairoSurface)
+  , mSize(aSize)
   , mIsFinished(false)
 {
+#if 0
+  // aCairoSurface is null when our PrintTargetThebes subclass's ctor calls us.
+  // Once PrintTargetThebes is removed, enable this assertion.
+  MOZ_ASSERT(aCairoSurface && !cairo_surface_status(aCairoSurface),
+             "CreateOrNull factory methods should not call us without a "
+             "valid cairo_surface_t*");
+#endif
+
+  // CreateOrNull factory methods hand over ownership of aCairoSurface,
+  // so we don't call cairo_surface_reference(aSurface) here.
+
+  // This code was copied from gfxASurface::Init:
+#ifdef MOZ_TREE_CAIRO
+  if (mCairoSurface &&
+      cairo_surface_get_content(mCairoSurface) != CAIRO_CONTENT_COLOR) {
+    cairo_surface_set_subpixel_antialiasing(mCairoSurface,
+                                            CAIRO_SUBPIXEL_ANTIALIASING_DISABLED);
+  }
+#endif
 }
 
 PrintTarget::~PrintTarget()
 {
+  // null surfaces are allowed here
+  cairo_surface_destroy(mCairoSurface);
+  mCairoSurface = nullptr;
+}
+
+already_AddRefed<DrawTarget>
+PrintTarget::MakeDrawTarget(const IntSize& aSize,
+                            DrawEventRecorder* aRecorder)
+{
+  MOZ_ASSERT(mCairoSurface,
+             "We shouldn't have been constructed without a cairo surface");
+
+  if (cairo_surface_status(mCairoSurface)) {
+    return nullptr;
+  }
+
+  // Note than aSize may not be the same as mSize (the size of mCairoSurface).
+  // See the comments in our header.  If the sizes are different a clip will
+  // be applied to mCairoSurface.
+  RefPtr<DrawTarget> dt =
+    Factory::CreateDrawTargetForCairoSurface(mCairoSurface, aSize);
+  if (!dt || !dt->IsValid()) {
+    return nullptr;
+  }
+
+  if (aRecorder) {
+    dt = CreateRecordingDrawTarget(aRecorder, dt);
+    if (!dt || !dt->IsValid()) {
+      return nullptr;
+    }
+  }
+
+  return dt.forget();
 }
 
 already_AddRefed<DrawTarget>
 PrintTarget::CreateRecordingDrawTarget(DrawEventRecorder* aRecorder,
                                        DrawTarget* aDrawTarget)
 {
   MOZ_ASSERT(aRecorder);
   MOZ_ASSERT(aDrawTarget);
@@ -46,12 +100,15 @@ PrintTarget::CreateRecordingDrawTarget(D
 
 void
 PrintTarget::Finish()
 {
   if (mIsFinished) {
     return;
   }
   mIsFinished = true;
+
+  // null surfaces are allowed here
+  cairo_surface_finish(mCairoSurface);
 }
 
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/PrintTarget.h
+++ b/gfx/thebes/PrintTarget.h
@@ -104,30 +104,31 @@ public:
    * XXX In the long run, this class and its sub-classes should be converted to
    * use STL classes and mozilla::RefCounted<> so the can be moved to Moz2D.
    *
    * TODO: Consider adding a SetDPI method that calls
    * cairo_surface_set_fallback_resolution.
    */
   virtual already_AddRefed<DrawTarget>
   MakeDrawTarget(const IntSize& aSize,
-                 DrawEventRecorder* aRecorder = nullptr) = 0;
+                 DrawEventRecorder* aRecorder = nullptr);
 
 protected:
 
   // Only created via subclass's constructors
-  explicit PrintTarget(const IntSize& aSize);
+  explicit PrintTarget(cairo_surface_t* aCairoSurface, const IntSize& aSize);
 
   // Protected because we're refcounted
   virtual ~PrintTarget();
 
   already_AddRefed<DrawTarget>
   CreateRecordingDrawTarget(DrawEventRecorder* aRecorder,
                             DrawTarget* aDrawTarget);
 
+  cairo_surface_t* mCairoSurface;
   IntSize mSize;
   bool mIsFinished;
 };
 
 } // namespace gfx
 } // namespace mozilla
 
 #endif /* MOZILLA_GFX_PRINTTARGET_H */
rename from gfx/thebes/gfxPSSurface.cpp
rename to gfx/thebes/PrintTargetPS.cpp
--- a/gfx/thebes/gfxPSSurface.cpp
+++ b/gfx/thebes/PrintTargetPS.cpp
@@ -1,107 +1,110 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "gfxPSSurface.h"
+#include "PrintTargetPS.h"
 
 #include "cairo.h"
 #include "cairo-ps.h"
 
+namespace mozilla {
+namespace gfx {
+
 static cairo_status_t
 write_func(void *closure, const unsigned char *data, unsigned int length)
 {
-    nsCOMPtr<nsIOutputStream> out = reinterpret_cast<nsIOutputStream*>(closure);
-    do {
-        uint32_t wrote = 0;
-        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;
+  nsCOMPtr<nsIOutputStream> out = reinterpret_cast<nsIOutputStream*>(closure);
+  do {
+    uint32_t wrote = 0;
+    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;
+}
+
+PrintTargetPS::PrintTargetPS(cairo_surface_t* aCairoSurface,
+                             const IntSize& aSize,
+                             nsIOutputStream *aStream,
+                             PageOrientation aOrientation)
+  : PrintTarget(aCairoSurface, aSize)
+  , mStream(aStream)
+  , mOrientation(aOrientation)
+{
 }
 
-gfxPSSurface::gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints, PageOrientation aOrientation)
-    : mStream(aStream), mXDPI(-1), mYDPI(-1), mOrientation(aOrientation)
+PrintTargetPS::~PrintTargetPS()
 {
-    mSize = mozilla::gfx::IntSize(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.
-    mozilla::gfx::IntSize cairoSize;
-    if (mOrientation == PORTRAIT) {
-        cairoSize = mSize;
-    } else {
-        cairoSize = mozilla::gfx::IntSize(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);
+  // We get called first, then PrintTarget's dtor.  That means that mStream
+  // is destroyed before PrintTarget's dtor calls cairo_surface_destroy.  This
+  // can be a problem if Finish() hasn't been called on us, since
+  // cairo_surface_destroy will then call cairo_surface_finish and that will
+  // end up invoking write_func above with the by now dangling pointer mStream
+  // that mCairoSurface stored.  To prevent that from happening we must call
+  // Flush here before mStream is deleted.
+  Finish();
 }
 
-gfxPSSurface::~gfxPSSurface()
+/* static */ already_AddRefed<PrintTargetPS>
+PrintTargetPS::CreateOrNull(nsIOutputStream *aStream,
+                            IntSize aSizeInPoints,
+                            PageOrientation aOrientation)
 {
+  // 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.  Our consumers are responsible for checking
+  // RotateForLandscape() and applying a rotation transform if true.
+  if (aOrientation == LANDSCAPE) {
+    Swap(aSizeInPoints.width, aSizeInPoints.height);
+  }
+
+  cairo_surface_t* surface =
+    cairo_ps_surface_create_for_stream(write_func, (void*)aStream,
+                                       aSizeInPoints.width,
+                                       aSizeInPoints.height);
+  if (cairo_surface_status(surface)) {
+    return nullptr;
+  }
+  cairo_ps_surface_restrict_to_level(surface, CAIRO_PS_LEVEL_2);
+
+  // The new object takes ownership of our surface reference.
+  RefPtr<PrintTargetPS> target = new PrintTargetPS(surface, aSizeInPoints,
+                                                   aStream, aOrientation);
+  return target.forget();
 }
 
 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()
+PrintTargetPS::BeginPrinting(const nsAString& aTitle,
+                             const nsAString& aPrintToFileName)
 {
-    return NS_OK;
-}
-
-nsresult
-gfxPSSurface::AbortPrinting()
-{
-    return NS_OK;
-}
-
-nsresult
-gfxPSSurface::BeginPage()
-{
-    return NS_OK;
+  if (mOrientation == PORTRAIT) {
+    cairo_ps_surface_dsc_comment(mCairoSurface, "%%Orientation: Portrait");
+  } else {
+    cairo_ps_surface_dsc_comment(mCairoSurface, "%%Orientation: Landscape");
+  }
+  return NS_OK;
 }
 
 nsresult
-gfxPSSurface::EndPage()
+PrintTargetPS::EndPage()
 {
-    cairo_surface_show_page(CairoSurface());
-    return NS_OK;
-}
-
-void
-gfxPSSurface::Finish()
-{
-    gfxASurface::Finish();
-    mStream->Close();
+  cairo_surface_show_page(mCairoSurface);
+  return NS_OK;
 }
 
 void
-gfxPSSurface::SetDPI(double xDPI, double yDPI)
+PrintTargetPS::Finish()
 {
-    mXDPI = xDPI;
-    mYDPI = yDPI;
-    cairo_surface_set_fallback_resolution(CairoSurface(), xDPI, yDPI);
+  if (mIsFinished) {
+    return; // We don't want to call Close() on mStream more than once
+  }
+  PrintTarget::Finish();
+  mStream->Close();
 }
 
-void
-gfxPSSurface::GetDPI(double *xDPI, double *yDPI)
-{
-    *xDPI = mXDPI;
-    *yDPI = mYDPI;
-}
-
+} // namespace gfx
+} // namespace mozilla
rename from gfx/thebes/gfxPSSurface.h
rename to gfx/thebes/PrintTargetPS.h
--- a/gfx/thebes/gfxPSSurface.h
+++ b/gfx/thebes/PrintTargetPS.h
@@ -1,52 +1,54 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef GFX_PSSURFACE_H
-#define GFX_PSSURFACE_H
+#ifndef MOZILLA_GFX_PRINTINGTARGETPS_H
+#define MOZILLA_GFX_PRINTINGTARGETPS_H
 
-#include "gfxASurface.h"
-
-/* for the output stream */
 #include "nsCOMPtr.h"
 #include "nsIOutputStream.h"
-#include "gfxContext.h"
+#include "PrintTarget.h"
 
-class gfxPSSurface : public gfxASurface {
-public:
-    enum PageOrientation {
-        PORTRAIT,
-        LANDSCAPE
-    };
-
-    gfxPSSurface(nsIOutputStream *aStream, const gfxSize& aSizeInPoints, PageOrientation aOrientation);
-    virtual ~gfxPSSurface();
+namespace mozilla {
+namespace gfx {
 
-    virtual nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
-    virtual nsresult EndPrinting();
-    virtual nsresult AbortPrinting();
-    virtual nsresult BeginPage();
-    virtual nsresult EndPage();
-    virtual void Finish();
+/**
+ * PostScript printing target.
+ */
+class PrintTargetPS final : public PrintTarget {
+public:
+  enum PageOrientation {
+    PORTRAIT,
+    LANDSCAPE
+  };
 
-    void SetDPI(double x, double y);
-    void GetDPI(double *xDPI, double *yDPI);
-
-    virtual bool GetRotateForLandscape() { return (mOrientation == LANDSCAPE); }
+  static already_AddRefed<PrintTargetPS>
+  CreateOrNull(nsIOutputStream *aStream,
+               IntSize aSizeInPoints,
+               PageOrientation aOrientation);
 
-    // this is in points!
-    virtual const mozilla::gfx::IntSize GetSize() const
-    {
-        return mSize;
-    }
+  virtual nsresult BeginPrinting(const nsAString& aTitle,
+                                 const nsAString& aPrintToFileName) override;
+  virtual nsresult EndPage() override;
+  virtual void Finish() override;
+
+  virtual bool GetRotateForLandscape() {
+    return (mOrientation == LANDSCAPE);
+  }
 
 private:
-    nsCOMPtr<nsIOutputStream> mStream;
-    double mXDPI;
-    double mYDPI;
-    mozilla::gfx::IntSize mSize;
-    PageOrientation mOrientation;
+  PrintTargetPS(cairo_surface_t* aCairoSurface,
+                const IntSize& aSize,
+                nsIOutputStream *aStream,
+                PageOrientation aOrientation);
+  virtual ~PrintTargetPS();
+
+  nsCOMPtr<nsIOutputStream> mStream;
+  PageOrientation mOrientation;
 };
 
-#endif /* GFX_PSSURFACE_H */
+} // namespace gfx
+} // namespace mozilla
+
+#endif /* MOZILLA_GFX_PRINTINGTARGETPS_H */
--- a/gfx/thebes/PrintTargetThebes.cpp
+++ b/gfx/thebes/PrintTargetThebes.cpp
@@ -22,17 +22,17 @@ PrintTargetThebes::CreateOrNull(gfxASurf
   }
 
   RefPtr<PrintTargetThebes> target = new PrintTargetThebes(aSurface);
 
   return target.forget();
 }
 
 PrintTargetThebes::PrintTargetThebes(gfxASurface* aSurface)
-  : PrintTarget(aSurface->GetSize())
+  : PrintTarget(nullptr, aSurface->GetSize())
   , mGfxSurface(aSurface)
 {
 }
 
 already_AddRefed<DrawTarget>
 PrintTargetThebes::MakeDrawTarget(const IntSize& aSize,
                                   DrawEventRecorder* aRecorder)
 {
@@ -84,16 +84,10 @@ PrintTargetThebes::EndPage()
 }
 
 void
 PrintTargetThebes::Finish()
 {
   return mGfxSurface->Finish();
 }
 
-bool
-PrintTargetThebes::RotateNeededForLandscape() const
-{
-  return mGfxSurface->GetRotateForLandscape();
-}
-
 } // namespace gfx
 } // namespace mozilla
--- a/gfx/thebes/PrintTargetThebes.h
+++ b/gfx/thebes/PrintTargetThebes.h
@@ -32,18 +32,16 @@ public:
   virtual nsresult BeginPrinting(const nsAString& aTitle,
                                  const nsAString& aPrintToFileName) override;
   virtual nsresult EndPrinting() override;
   virtual nsresult AbortPrinting() override;
   virtual nsresult BeginPage() override;
   virtual nsresult EndPage() override;
   virtual void Finish() override;
 
-  virtual bool RotateNeededForLandscape() const override;
-
   virtual already_AddRefed<DrawTarget>
   MakeDrawTarget(const IntSize& aSize,
                  DrawEventRecorder* aRecorder = nullptr) override;
 
 private:
 
   // Only created via CreateOrNull
   explicit PrintTargetThebes(gfxASurface* aSurface);
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -59,18 +59,16 @@ public:
 
     gfxSurfaceType GetType() const;
 
     gfxContentType GetContentType() const;
 
     void SetDeviceOffset(const gfxPoint& offset);
     gfxPoint GetDeviceOffset() const;
 
-    virtual bool GetRotateForLandscape() { return 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/moz.build
+++ b/gfx/thebes/moz.build
@@ -102,29 +102,30 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
     ]
 elif 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
     EXPORTS += [
         'gfxFontconfigFonts.h',
         'gfxFT2FontBase.h',
         'gfxGdkNativeRenderer.h',
         'gfxPDFSurface.h',
         'gfxPlatformGtk.h',
-        'gfxPSSurface.h',
     ]
-
+    EXPORTS.mozilla.gfx += [
+        'PrintTargetPS.h',
+    ]
     SOURCES += [
         'gfxFcPlatformFontList.cpp',
         'gfxFontconfigFonts.cpp',
         'gfxFontconfigUtils.cpp',
         'gfxFT2FontBase.cpp',
         'gfxFT2Utils.cpp',
         'gfxGdkNativeRenderer.cpp',
         'gfxPDFSurface.cpp',
         'gfxPlatformGtk.cpp',
-        'gfxPSSurface.cpp',
+        'PrintTargetPS.cpp',
     ]
 
     if CONFIG['MOZ_X11']:
         EXPORTS += [
             'gfxXlibNativeRenderer.h',
             'gfxXlibSurface.h',
         ]
         SOURCES += [
--- a/widget/gtk/nsDeviceContextSpecG.cpp
+++ b/widget/gtk/nsDeviceContextSpecG.cpp
@@ -1,20 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "nsDeviceContextSpecG.h"
+
+#include "mozilla/gfx/PrintTargetPS.h"
 #include "mozilla/gfx/PrintTargetThebes.h"
 #include "mozilla/Logging.h"
 
 #include "plstr.h"
-
-#include "nsDeviceContextSpecG.h"
-
 #include "prenv.h" /* for PR_GetEnv */
 
 #include "nsPrintfCString.h"
 #include "nsReadableUtils.h"
 #include "nsStringEnumerator.h"
 #include "nsIServiceManager.h" 
 
 #include "nsPSPrinters.h"
@@ -29,17 +29,19 @@
 #include "mozilla/Preferences.h"
 
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 
 using namespace mozilla;
 
+using mozilla::gfx::IntSize;
 using mozilla::gfx::PrintTarget;
+using mozilla::gfx::PrintTargetPS;
 using mozilla::gfx::PrintTargetThebes;
 
 static PRLogModuleInfo *
 GetDeviceContextSpecGTKLog()
 {
   static PRLogModuleInfo *sLog;
   if (!sLog)
     sLog = PR_NewLogModule("DeviceContextSpecGTK");
@@ -100,17 +102,16 @@ nsDeviceContextSpecGTK::~nsDeviceContext
     g_object_unref(mGtkPrintSettings);
   }
 }
 
 NS_IMPL_ISUPPORTS(nsDeviceContextSpecGTK,
                   nsIDeviceContextSpec)
 
 #include "gfxPDFSurface.h"
-#include "gfxPSSurface.h"
 already_AddRefed<PrintTarget> nsDeviceContextSpecGTK::MakePrintTarget()
 {
   double width, height;
   mPrintSettings->GetEffectivePageSize(&width, &height);
 
   // convert twips to points
   width  /= TWIPS_PER_POINT_FLOAT;
   height /= TWIPS_PER_POINT_FLOAT;
@@ -145,46 +146,44 @@ already_AddRefed<PrintTarget> nsDeviceCo
   nsCOMPtr<nsIFileOutputStream> stream = do_CreateInstance("@mozilla.org/network/file-output-stream;1");
   rv = stream->Init(mSpoolFile, -1, -1, 0);
   if (NS_FAILED(rv))
     return nullptr;
 
   int16_t format;
   mPrintSettings->GetOutputFormat(&format);
 
-  RefPtr<gfxASurface> surface;
-  gfxSize surfaceSize(width, height);
-
   // Determine the real format with some GTK magic
   if (format == nsIPrintSettings::kOutputFormatNative) {
     if (mIsPPreview) {
       // There is nothing to detect on Print Preview, use PS.
       format = nsIPrintSettings::kOutputFormatPS;
     } else {
       return nullptr;
     }
   }
 
+  IntSize size(width, height);
+
   if (format == nsIPrintSettings::kOutputFormatPDF) {
-    surface = new gfxPDFSurface(stream, surfaceSize);
-  } else {
-    int32_t orientation;
-    mPrintSettings->GetOrientation(&orientation);
-    if (nsIPrintSettings::kPortraitOrientation == orientation) {
-      surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::PORTRAIT);
-    } else {
-      surface = new gfxPSSurface(stream, surfaceSize, gfxPSSurface::LANDSCAPE);
+    RefPtr<gfxASurface> surface = new gfxPDFSurface(stream,
+                                                    gfxSize(width, height));
+    if (!surface) {
+      return nullptr;
     }
+    return PrintTargetThebes::CreateOrNull(surface);
   }
 
-  if (!surface) {
-    return nullptr;
-  }
-
-  return PrintTargetThebes::CreateOrNull(surface);
+  int32_t orientation;
+  mPrintSettings->GetOrientation(&orientation);
+  return PrintTargetPS::CreateOrNull(stream,
+                                     size,
+                                     orientation == nsIPrintSettings::kPortraitOrientation
+                                       ? PrintTargetPS::PORTRAIT
+                                       : PrintTargetPS::LANDSCAPE);
 }
 
 /** -------------------------------------------------------
  *  Initialize the nsDeviceContextSpecGTK
  *  @update   dc 2/15/98
  *  @update   syd 3/2/99
  */
 NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget *aWidget,