Bug 1238964 Part 1: Hold new printable page sizes in print nsIPrintSettingsWin. r=jimm
authorBob Owen <bobowencode@gmail.com>
Fri, 22 Jan 2016 16:05:19 +0000
changeset 281250 e7d43e96b14cbd528b6b93342851d573d2c7eb73
parent 281249 955993ba4a2a6ed9c85b9fc6c3a4c0fe582b178f
child 281251 fb4737474a9c50b44e0ec38e43d42ed8a119b7ee
push id29934
push userphilringnalda@gmail.com
push dateSun, 24 Jan 2016 01:56:15 +0000
treeherdermozilla-central@d0df4221d105 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1238964
milestone46.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 1238964 Part 1: Hold new printable page sizes in print nsIPrintSettingsWin. r=jimm This also holds the resolution in the print settings, so that we can start to remove the access to the native Windows print devices in the child process.
embedding/components/printingui/ipc/PPrintingTypes.ipdlh
embedding/components/printingui/win/nsPrintDialogUtil.cpp
gfx/src/nsDeviceContext.cpp
gfx/thebes/gfxWindowsSurface.cpp
widget/nsDeviceContextSpecProxy.cpp
widget/nsIPrintSettingsWin.idl
widget/nsPrintOptionsImpl.cpp
widget/windows/nsDeviceContextSpecWin.cpp
widget/windows/nsDeviceContextSpecWin.h
widget/windows/nsPrintOptionsWin.cpp
widget/windows/nsPrintSettingsWin.cpp
widget/windows/nsPrintSettingsWin.h
--- a/embedding/components/printingui/ipc/PPrintingTypes.ipdlh
+++ b/embedding/components/printingui/ipc/PPrintingTypes.ipdlh
@@ -70,16 +70,18 @@ struct PrintData {
   bool isInitializedFromPrinter;
   bool isInitializedFromPrefs;
   bool persistMarginBoxSettings;
   int32_t optionFlags;
 
   /* Windows-specific things */
   nsString driverName;
   nsString deviceName;
+  double printableWidthInInches;
+  double printableHeightInInches;
   bool isFramesetDocument;
   bool isFramesetFrameSelected;
   bool isIFrameSelected;
   bool isRangeSelection;
   uint8_t[] devModeData;
 
   /**
    * GTK-specific things. Some of these might look like dupes of the
--- a/embedding/components/printingui/win/nsPrintDialogUtil.cpp
+++ b/embedding/components/printingui/win/nsPrintDialogUtil.cpp
@@ -982,23 +982,25 @@ ShowNativePrintDialog(HWND              
     } else {
       aPrintSettings->SetPrintFrameType(nsIPrintSettings::kNoFrames);
     }
     // Unlock DeviceNames
     ::GlobalUnlock(prntdlg.hDevNames);
 
     // Transfer the settings from the native data to the PrintSettings
     LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
-    if (devMode == nullptr) {
+    if (!devMode || !prntdlg.hDC) {
       ::GlobalFree(hGlobalDevMode);
       return NS_ERROR_FAILURE;
     }
     psWin->SetDevMode(devMode); // copies DevMode
     SetPrintSettingsFromDevMode(aPrintSettings, devMode);
     ::GlobalUnlock(prntdlg.hDevMode);
+    psWin->CopyFromNative(prntdlg.hDC);
+    ::DeleteDC(prntdlg.hDC);
 
 #if defined(DEBUG_rods) || defined(DEBUG_dcone)
     bool    printSelection = prntdlg.Flags & PD_SELECTION;
     bool    printAllPages  = prntdlg.Flags & PD_ALLPAGES;
     bool    printNumPages  = prntdlg.Flags & PD_PAGENUMS;
     int32_t fromPageNum    = 0;
     int32_t toPageNum      = 0;
 
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -675,48 +675,23 @@ nsDeviceContext::FindScreen(nsIScreen** 
 
 bool
 nsDeviceContext::CalcPrintingSize()
 {
     if (!mPrintingSurface) {
         return (mWidth > 0 && mHeight > 0);
     }
 
-    bool inPoints = true;
-
-    gfxSize size(0, 0);
-    switch (mPrintingSurface->GetType()) {
-#ifdef XP_WIN
-    case gfxSurfaceType::Win32Printing:
-        {
-            inPoints = false;
-            HDC dc = reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
-            if (!dc)
-                dc = GetDC((HWND)mWidget->GetNativeData(NS_NATIVE_WIDGET));
-            size.width = NSFloatPixelsToAppUnits(::GetDeviceCaps(dc, HORZRES)/mPrintingScale, AppUnitsPerDevPixel());
-            size.height = NSFloatPixelsToAppUnits(::GetDeviceCaps(dc, VERTRES)/mPrintingScale, AppUnitsPerDevPixel());
-            mDepth = (uint32_t)::GetDeviceCaps(dc, BITSPIXEL);
-            if (dc != reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC())
-                ReleaseDC((HWND)mWidget->GetNativeData(NS_NATIVE_WIDGET), dc);
-            break;
-        }
-#endif
-    default:
-        size = mPrintingSurface->GetSize();
-    }
-
-    if (inPoints) {
-        // For printing, CSS inches and physical inches are identical
-        // so it doesn't matter which we use here
-        mWidth = NSToCoordRound(float(size.width) * AppUnitsPerPhysicalInch() / 72);
-        mHeight = NSToCoordRound(float(size.height) * AppUnitsPerPhysicalInch() / 72);
-    } else {
-        mWidth = NSToIntRound(size.width);
-        mHeight = NSToIntRound(size.height);
-    }
+    gfxSize size = mPrintingSurface->GetSize();
+    // For printing, CSS inches and physical inches are identical
+    // so it doesn't matter which we use here
+    mWidth = NSToCoordRound(size.width * AppUnitsPerPhysicalInch()
+                            / POINTS_PER_INCH_FLOAT);
+    mHeight = NSToCoordRound(size.height * AppUnitsPerPhysicalInch()
+                             / POINTS_PER_INCH_FLOAT);
 
     return (mWidth > 0 && mHeight > 0);
 }
 
 bool nsDeviceContext::CheckDPIChange() {
     int32_t oldDevPixels = mAppUnitsPerDevPixelAtUnitFullZoom;
     int32_t oldInches = mAppUnitsPerPhysicalInch;
 
--- a/gfx/thebes/gfxWindowsSurface.cpp
+++ b/gfx/thebes/gfxWindowsSurface.cpp
@@ -305,16 +305,25 @@ gfxWindowsSurface::EndPage()
 #else
     return NS_ERROR_FAILURE;
 #endif
 }
 
 const mozilla::gfx::IntSize
 gfxWindowsSurface::GetSize() const
 {
+    if (mForPrinting) {
+        // On Windows we need to use the printable area of the page.
+        float width = (::GetDeviceCaps(mDC, HORZRES) * POINTS_PER_INCH_FLOAT)
+                      / ::GetDeviceCaps(mDC, LOGPIXELSX);
+        float height = (::GetDeviceCaps(mDC, VERTRES) * POINTS_PER_INCH_FLOAT)
+                       / ::GetDeviceCaps(mDC, LOGPIXELSY);
+        return mozilla::gfx::IntSize(width, height);
+    }
+
     if (!mSurfaceValid) {
         NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
         return mozilla::gfx::IntSize(-1, -1);
     }
 
     NS_ASSERTION(mSurface != nullptr, "CairoSurface() shouldn't be nullptr when mSurfaceValid is TRUE!");
 
     return mozilla::gfx::IntSize(cairo_win32_surface_get_width(mSurface),
--- a/widget/nsDeviceContextSpecProxy.cpp
+++ b/widget/nsDeviceContextSpecProxy.cpp
@@ -62,25 +62,18 @@ nsDeviceContextSpecProxy::Init(nsIWidget
 }
 
 NS_IMETHODIMP
 nsDeviceContextSpecProxy::GetSurfaceForPrinter(gfxASurface** aSurface)
 {
   MOZ_ASSERT(aSurface);
   MOZ_ASSERT(mRealDeviceContextSpec);
 
-  // The real device context may need to have created a real printing surface
-  // even though we're not using it directly.
-  nsresult rv = mRealDeviceContextSpec->GetSurfaceForPrinter(aSurface);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
   double width, height;
-  rv = mPrintSettings->GetEffectivePageSize(&width, &height);
+  nsresult rv = mPrintSettings->GetEffectivePageSize(&width, &height);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // convert twips to points
   width /= TWIPS_PER_POINT_FLOAT;
   height /= TWIPS_PER_POINT_FLOAT;
 
--- a/widget/nsIPrintSettingsWin.idl
+++ b/widget/nsIPrintSettingsWin.idl
@@ -8,21 +8,22 @@
 %{ C++
 #include "windows.h"
 %}
 
 /**
  * Native types
  */
   [ptr] native nsDevMode(DEVMODEW);
+  native nsHdc(HDC);
 
 /**
  * Simplified PrintSettings for Windows interface 
  */
-[scriptable, uuid(f13b225d-473e-4372-b11f-b6dff9fe0c5b)]
+[scriptable, uuid(57c22cc1-311f-44c3-bb49-4d1cf411a3b5)]
 
 interface nsIPrintSettingsWin : nsISupports
 {
   /**
    * Data Members
    *
    * Each of these data members make a copy 
    * of the contents. If you get the value, 
@@ -34,9 +35,27 @@ interface nsIPrintSettingsWin : nsISuppo
    * via the "m_pd" data member of the CPrintDialog
    * in MFC.
    */
   [noscript] attribute wstring deviceName;
   [noscript] attribute wstring driverName;
 
   [noscript] attribute nsDevMode devMode;
 
+  /**
+   * On Windows we use the printable width and height for the printing surface.
+   * We don't want to have to create native print device contexts in the content
+   * process, so we need to store these in the settings.
+   * Storing in Inches is most convenient as they are retrieved from the device
+   * using fields which are in pixels and pixels per inch.
+   * Note these are stored in portrait format to ensure that we can take account
+   * of our own changes to the orientation print setting.
+   */
+  [noscript] attribute double printableWidthInInches;
+  [noscript] attribute double printableHeightInInches;
+
+  /**
+   * Copy relevant print settings from native Windows device.
+   *
+   * @param hdc HDC to copy from
+   */
+  [notxpcom] void copyFromNative(in nsHdc hdc);
 };
--- a/widget/nsPrintOptionsImpl.cpp
+++ b/widget/nsPrintOptionsImpl.cpp
@@ -209,16 +209,18 @@ nsPrintOptions::SerializeToPrintData(nsI
   aSettings->GetPrintOptionsBits(&data->optionFlags());
 
   // Initialize the platform-specific values that don't
   // default-initialize, so that we don't send uninitialized data over
   // IPC (which leads to valgrind warnings, and, for bools, fatal
   // assertions).
   // data->driverName() default-initializes
   // data->deviceName() default-initializes
+  data->printableWidthInInches() = 0;
+  data->printableHeightInInches() = 0;
   data->isFramesetDocument() = false;
   data->isFramesetFrameSelected() = false;
   data->isIFrameSelected() = false;
   data->isRangeSelection() = false;
   // data->GTKPrintSettings() default-initializes
   // data->printJobName() default-initializes
   data->printAllPages() = true;
   data->mustCollate() = false;
--- a/widget/windows/nsDeviceContextSpecWin.cpp
+++ b/widget/windows/nsDeviceContextSpecWin.cpp
@@ -44,16 +44,18 @@
 #include "mozilla/gfx/Logging.h"
 
 #include "mozilla/Logging.h"
 PRLogModuleInfo * kWidgetPrintingLogMod = PR_NewLogModule("printing-widget");
 #define PR_PL(_p1)  MOZ_LOG(kWidgetPrintingLogMod, mozilla::LogLevel::Debug, _p1)
 
 using namespace mozilla;
 
+static const wchar_t kDriverName[] =  L"WINSPOOL";
+
 //----------------------------------------------------------------------------------
 // The printer data is shared between the PrinterEnumerator and the nsDeviceContextSpecWin
 // The PrinterEnumerator creates the printer info
 // but the nsDeviceContextSpecWin cleans it up
 // If it gets created (via the Page Setup Dialog) but the user never prints anything
 // then it will never be delete, so this class takes care of that.
 class GlobalPrinters {
 public:
@@ -76,16 +78,23 @@ protected:
   static GlobalPrinters    mGlobalPrinters;
   static nsTArray<LPWSTR>* mPrinters;
 };
 //---------------
 // static members
 GlobalPrinters    GlobalPrinters::mGlobalPrinters;
 nsTArray<LPWSTR>* GlobalPrinters::mPrinters = nullptr;
 
+struct AutoFreeGlobalPrinters
+{
+  ~AutoFreeGlobalPrinters() {
+    GlobalPrinters::GetInstance()->FreeGlobalPrinters();
+  }
+};
+
 
 //******************************************************
 // Define native paper sizes
 //******************************************************
 typedef struct {
   short  mPaperSize; // native enum
   double mWidth;
   double mHeight;
@@ -316,29 +325,28 @@ NS_IMETHODIMP nsDeviceContextSpecWin::Ge
       newSurface = new gfxWindowsSurface(dc, gfxWindowsSurface::FLAG_TAKE_DC | gfxWindowsSurface::FLAG_FOR_PRINTING);
       if (newSurface->GetType() == (gfxSurfaceType)-1) {
         gfxCriticalError() << "Invalid windows surface from " << gfx::hexa(dc);
         return NS_ERROR_FAILURE;
       }
     }
   }
 
-  mPrintingSurface = newSurface;
   newSurface.forget(surface);
   return NS_OK;
 }
 
 float
 nsDeviceContextSpecWin::GetPrintingScale()
 {
-  MOZ_ASSERT(mPrintingSurface);
+  MOZ_ASSERT(mPrintSettings);
 
-  HDC dc = reinterpret_cast<gfxWindowsSurface*>(mPrintingSurface.get())->GetDC();
-  int32_t OSVal = GetDeviceCaps(dc, LOGPIXELSY);
-  return float(OSVal) / GetDPI();
+  int32_t resolution;
+  mPrintSettings->GetResolution(&resolution);
+  return float(resolution) / GetDPI();
 }
 
 //----------------------------------------------------------------------------------
 void nsDeviceContextSpecWin::SetDeviceName(char16ptr_t aDeviceName)
 {
   CleanAndCopyString(mDeviceName, aDeviceName);
 }
 
@@ -507,17 +515,17 @@ nsDeviceContextSpecWin::GetDataFromPrint
       DISPLAY_LAST_ERROR
       return NS_ERROR_FAILURE;
     }
 
     SetDevMode(pDevMode); // cache the pointer and takes responsibility for the memory
 
     SetDeviceName(aName);
 
-    SetDriverName(L"WINSPOOL");
+    SetDriverName(kDriverName);
 
     ::ClosePrinter(hPrinter);
     rv = NS_OK;
   } else {
     rv = NS_ERROR_GFX_PRINTER_NAME_NOT_FOUND;
     PR_PL(("***** nsDeviceContextSpecWin::GetDataFromPrinter - Couldn't open printer: [%s]\n", NS_ConvertUTF16toUTF8(aName).get()));
     DISPLAY_LAST_ERROR
   }
@@ -652,28 +660,40 @@ nsPrinterEnumeratorWin::InitPrintSetting
 
   RefPtr<nsDeviceContextSpecWin> devSpecWin = new nsDeviceContextSpecWin();
   if (!devSpecWin) return NS_ERROR_OUT_OF_MEMORY;
 
   if (NS_FAILED(GlobalPrinters::GetInstance()->EnumeratePrinterList())) {
     return NS_ERROR_FAILURE;
   }
 
+  AutoFreeGlobalPrinters autoFreeGlobalPrinters;
+
   devSpecWin->GetDataFromPrinter(aPrinterName);
 
   LPDEVMODEW devmode;
   devSpecWin->GetDevMode(devmode);
-  NS_ASSERTION(devmode, "DevMode can't be NULL here");
-  if (devmode) {
-    aPrintSettings->SetPrinterName(aPrinterName);
-    nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(aPrintSettings, devmode);
+  if (NS_WARN_IF(!devmode)) {
+    return NS_ERROR_FAILURE;
   }
 
-  // Free them, we won't need them for a while
-  GlobalPrinters::GetInstance()->FreeGlobalPrinters();
+  aPrintSettings->SetPrinterName(aPrinterName);
+  nsDeviceContextSpecWin::SetPrintSettingsFromDevMode(aPrintSettings, devmode);
+
+  // We need to get information from the device as well.
+  HDC dc = ::CreateICW(kDriverName, aPrinterName, nullptr, devmode);
+  if (NS_WARN_IF(!dc)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPrintSettings);
+  MOZ_ASSERT(psWin);
+  psWin->CopyFromNative(dc);
+  ::DeleteDC(dc);
+
   return NS_OK;
 }
 
 
 //----------------------------------------------------------------------------------
 // Enumerate all the Printers from the global array and pass their
 // names back (usually to script)
 NS_IMETHODIMP 
--- a/widget/windows/nsDeviceContextSpecWin.h
+++ b/widget/windows/nsDeviceContextSpecWin.h
@@ -64,17 +64,16 @@ protected:
 
   virtual ~nsDeviceContextSpecWin();
 
   wchar_t*      mDriverName;
   wchar_t*      mDeviceName;
   LPDEVMODEW mDevMode;
 
   nsCOMPtr<nsIPrintSettings> mPrintSettings;
-  RefPtr<gfxASurface> mPrintingSurface;
 };
 
 
 //-------------------------------------------------------------------------
 // Printer Enumerator
 //-------------------------------------------------------------------------
 class nsPrinterEnumeratorWin final : public nsIPrinterEnumerator
 {
--- a/widget/windows/nsPrintOptionsWin.cpp
+++ b/widget/windows/nsPrintOptionsWin.cpp
@@ -62,20 +62,22 @@ nsPrintOptionsWin::SerializeToPrintData(
   psWin->GetDriverName(&driverName);
 
   data->deviceName().Assign(deviceName);
   data->driverName().Assign(driverName);
 
   free(deviceName);
   free(driverName);
 
-  // When creating the print dialog on Windows, the parent creates a DEVMODE
-  // which is used to convey print settings to the Windows printing backend.
-  // We don't, therefore, want or care about DEVMODEs sent up from the child.
+  // When creating the print dialog on Windows, we only need to send certain
+  // print settings information from the parent to the child not vice versa.
   if (XRE_IsParentProcess()) {
+    psWin->GetPrintableWidthInInches(&data->printableWidthInInches());
+    psWin->GetPrintableHeightInInches(&data->printableHeightInInches());
+
     // A DEVMODE can actually be of arbitrary size. If it turns out that it'll
     // make our IPC message larger than the limit, then we'll error out.
     LPDEVMODEW devModeRaw;
     psWin->GetDevMode(&devModeRaw); // This actually allocates a copy of the
                                     // the nsIPrintSettingsWin DEVMODE, so
                                     // we're now responsible for deallocating
                                     // it. We'll use an nsAutoDevMode helper
                                     // to do this.
@@ -113,16 +115,19 @@ nsPrintOptionsWin::DeserializeToPrintSet
   if (!settings) {
     return NS_ERROR_FAILURE;
   }
 
   if (XRE_IsContentProcess()) {
     psWin->SetDeviceName(data.deviceName().get());
     psWin->SetDriverName(data.driverName().get());
 
+    psWin->SetPrintableWidthInInches(data.printableWidthInInches());
+    psWin->SetPrintableHeightInInches(data.printableHeightInInches());
+
     nsXPIDLString printerName;
     settings->GetPrinterName(getter_Copies(printerName));
 
     DEVMODEW* devModeRaw = (DEVMODEW*)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
                                                   data.devModeData().Length());
     if (!devModeRaw) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
--- a/widget/windows/nsPrintSettingsWin.cpp
+++ b/widget/windows/nsPrintSettingsWin.cpp
@@ -106,16 +106,92 @@ NS_IMETHODIMP nsPrintSettingsWin::SetDev
   }
 
   if (aDevMode) {
     CopyDevMode(aDevMode, mDevMode);
   }
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsPrintSettingsWin::GetPrintableWidthInInches(double* aPrintableWidthInInches)
+{
+  MOZ_ASSERT(aPrintableWidthInInches);
+  *aPrintableWidthInInches = mPrintableWidthInInches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintSettingsWin::SetPrintableWidthInInches(double aPrintableWidthInInches)
+{
+  mPrintableWidthInInches = aPrintableWidthInInches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintSettingsWin::GetPrintableHeightInInches(double* aPrintableHeightInInches)
+{
+  MOZ_ASSERT(aPrintableHeightInInches);
+  *aPrintableHeightInInches = mPrintableHeightInInches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintSettingsWin::SetPrintableHeightInInches(double aPrintableHeightInInches)
+{
+  mPrintableHeightInInches = aPrintableHeightInInches;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsPrintSettingsWin::GetEffectivePageSize(double *aWidth, double *aHeight)
+{
+  // If printable page size not set, fall back to nsPrintSettings.
+  if (mPrintableWidthInInches == 0l || mPrintableHeightInInches == 0l) {
+    return nsPrintSettings::GetEffectivePageSize(aWidth, aHeight);
+  }
+
+  if (mOrientation == kPortraitOrientation) {
+    *aWidth = NS_INCHES_TO_TWIPS(mPrintableWidthInInches);
+    *aHeight = NS_INCHES_TO_TWIPS(mPrintableHeightInInches);
+  } else {
+    *aHeight = NS_INCHES_TO_TWIPS(mPrintableWidthInInches);
+    *aWidth = NS_INCHES_TO_TWIPS(mPrintableHeightInInches);
+  }
+  return NS_OK;
+}
+
+void
+nsPrintSettingsWin::CopyFromNative(HDC aHdc)
+{
+  MOZ_ASSERT(aHdc);
+
+  // On Windows we currently create a surface using the printable area of the
+  // page and don't set the unwriteable [sic] margins. Using the unwriteable
+  // margins doesn't appear to work on Windows, but I am not sure if this is a
+  // bug elsewhere in our code or a Windows quirk.
+  int32_t printableWidthInDots = GetDeviceCaps(aHdc, HORZRES);
+  int32_t printableHeightInDots = GetDeviceCaps(aHdc, VERTRES);
+  int32_t widthDPI = GetDeviceCaps(aHdc, LOGPIXELSX);
+  int32_t heightDPI = GetDeviceCaps(aHdc, LOGPIXELSY);
+
+  // Keep these values in portrait format, so we can reflect our own changes
+  // to mOrientation.
+  if (mOrientation == kPortraitOrientation) {
+    mPrintableWidthInInches = double(printableWidthInDots) / widthDPI;
+    mPrintableHeightInInches = double(printableHeightInDots) / heightDPI;
+  } else {
+    mPrintableHeightInInches = double(printableWidthInDots) / widthDPI;
+    mPrintableWidthInInches = double(printableHeightInDots) / heightDPI;
+  }
+
+  // Using Y to match existing code, X DPI should be the same for printing.
+  mResolution = heightDPI;
+}
+
 //-------------------------------------------
 nsresult 
 nsPrintSettingsWin::_Clone(nsIPrintSettings **_retval)
 {
   RefPtr<nsPrintSettingsWin> printSettings = new nsPrintSettingsWin(*this);
   printSettings.forget(_retval);
   return NS_OK;
 }
--- a/widget/windows/nsPrintSettingsWin.h
+++ b/widget/windows/nsPrintSettingsWin.h
@@ -37,19 +37,23 @@ public:
    */
   virtual nsresult _Assign(nsIPrintSettings* aPS);
 
   /**
    * Assignment
    */
   nsPrintSettingsWin& operator=(const nsPrintSettingsWin& rhs);
 
+  NS_IMETHOD GetEffectivePageSize(double *aWidth, double *aHeight) override;
+
 protected:
   void CopyDevMode(DEVMODEW* aInDevMode, DEVMODEW *& aOutDevMode);
 
   wchar_t*      mDeviceName;
   wchar_t*      mDriverName;
   LPDEVMODEW mDevMode;
+  double mPrintableWidthInInches = 0l;
+  double mPrintableHeightInInches = 0l;
 };
 
 
 
 #endif /* nsPrintSettingsWin_h__ */