Bug 1658299 Part 2: Add createDefaultSettings() to nsIPrinter for Windows. r=jwatt,jfkthame

This retrieves the same settings from the printer as
InitPrintSettingsFromPrinter.
There is probably a lot of scope for de-duplication of code here, but I decided
to try and protect the old fallback paths.

Depends on D87125

Differential Revision: https://phabricator.services.mozilla.com/D87604
This commit is contained in:
Bob Owen 2020-08-20 23:25:10 +00:00
Родитель dd5507b91b
Коммит 72fd7de5a6
6 изменённых файлов: 136 добавлений и 36 удалений

Просмотреть файл

@ -26,6 +26,7 @@ async function run() {
settings.QueryInterface(Ci.nsIPrintSettings);
is(typeof settings.printerName, "string", "Printer name should be a string.");
is(settings.printerName, printer.name, "Print settings' printer should match the printer that created them.");
console.log(typeof settings.paperWidth);
is(typeof settings.paperName, "string", "Paper name should never be null.");
@ -44,6 +45,8 @@ async function run() {
ok(settings.marginBottom >= 0.0, "Paper margins should be greater than or equal to zero.");
ok(settings.marginLeft >= 0.0, "Paper margins should be greater than or equal to zero.");
is(settings.printInColor, await printer.supportsColor, "Print settings' color mode should match the printer's color support.");
ok(settings.isInitializedFromPrinter, "Print settings were initialized from printer");
ok(!settings.isInitializedFromPrefs);
}

Просмотреть файл

@ -66,6 +66,7 @@ void nsPrintSettings::InitWithInitializer(
SetPrinterName(aSettings.mPrinter);
SetPrintInColor(aSettings.mPrintInColor);
SetResolution(aSettings.mResolution);
SetPaperName(aSettings.mPaperInfo.mName);
SetPaperWidth(aSettings.mPaperInfo.mSize.Width() * kInchesPerPoint);
SetPaperHeight(aSettings.mPaperInfo.mSize.Height() * kInchesPerPoint);

Просмотреть файл

@ -29,6 +29,10 @@ struct PrintSettingsInitializer {
nsString mPrinter;
PaperInfo mPaperInfo;
bool mPrintInColor = false;
int mResolution = 0;
#ifdef XP_WIN
nsTArray<uint8_t> mDevmodeWStorage;
#endif
};
} // namespace mozilla
@ -47,7 +51,7 @@ class nsPrintSettings : public nsIPrintSettings {
* This is specifically not a constructor so that we can ensure that the
* relevant setters are dynamically dispatched to derived classes.
*/
void InitWithInitializer(const PrintSettingsInitializer& aSettings);
virtual void InitWithInitializer(const PrintSettingsInitializer& aSettings);
nsPrintSettings& operator=(const nsPrintSettings& rhs);

Просмотреть файл

@ -7,8 +7,11 @@
#include "mozilla/ArrayUtils.h"
#include "nsCRT.h"
#include "nsDeviceContextSpecWin.h"
#include "nsPrintSettingsImpl.h"
#include "WinUtils.h"
using namespace mozilla;
// Using paper sizes from wingdi.h and the units given there, plus a little
// extra research for the ones it doesn't give. Looks like the list hasn't
// changed since Windows 2000, so should be fairly stable now.
@ -160,37 +163,76 @@ nsPrintSettingsWin::nsPrintSettingsWin(const nsPrintSettingsWin& aPS)
*this = aPS;
}
void nsPrintSettingsWin::InitWithInitializer(
const PrintSettingsInitializer& aSettings) {
nsPrintSettings::InitWithInitializer(aSettings);
if (aSettings.mDevmodeWStorage.Length() < sizeof(DEVMODEW)) {
MOZ_DIAGNOSTIC_ASSERT(false, "Why did nsPrinterWin::DefaultSettings fail?");
return;
}
const DEVMODEW* devmode =
reinterpret_cast<const DEVMODEW*>(aSettings.mDevmodeWStorage.Elements());
if (devmode->dmFields & DM_ORIENTATION) {
SetOrientation(devmode->dmOrientation == DMORIENT_PORTRAIT
? kPortraitOrientation
: kLandscapeOrientation);
}
if (devmode->dmFields & DM_COPIES) {
SetNumCopies(devmode->dmCopies);
}
if (devmode->dmFields & DM_SCALE) {
double scale = double(devmode->dmScale) / 100.0f;
if (mScaling == 1.0 || scale != 1.0) {
SetScaling(scale);
}
}
if (devmode->dmFields & DM_PAPERSIZE) {
SetPaperData(devmode->dmPaperSize);
if (devmode->dmPaperSize > 0 &&
devmode->dmPaperSize < int32_t(mozilla::ArrayLength(kPaperSizeUnits))) {
SetPaperSizeUnit(kPaperSizeUnits[mPaperData]);
}
} else {
SetPaperData(-1);
}
// Set the paper sizes to match the unit.
double pointsToSizeUnit =
mPaperSizeUnit == kPaperSizeInches ? 1.0 / 72.0 : 25.4 / 72.0;
SetPaperWidth(aSettings.mPaperInfo.mSize.width * pointsToSizeUnit);
SetPaperHeight(aSettings.mPaperInfo.mSize.height * pointsToSizeUnit);
double printableWidthInPoints = aSettings.mPaperInfo.mSize.width;
double printableHeightInPoints = aSettings.mPaperInfo.mSize.height;
if (aSettings.mPaperInfo.mUnwriteableMargin.isSome()) {
const auto& margin = aSettings.mPaperInfo.mUnwriteableMargin.value();
printableWidthInPoints -= (margin.top + margin.bottom);
printableHeightInPoints -= (margin.left + margin.right);
}
// Keep these values in portrait format, so we can reflect our own changes
// to mOrientation.
if (mOrientation == kPortraitOrientation) {
mPrintableWidthInInches = printableWidthInPoints / POINTS_PER_INCH_FLOAT;
mPrintableHeightInInches = printableHeightInPoints / POINTS_PER_INCH_FLOAT;
} else {
mPrintableHeightInInches = printableWidthInPoints / POINTS_PER_INCH_FLOAT;
mPrintableWidthInInches = printableHeightInPoints / POINTS_PER_INCH_FLOAT;
}
SetDevMode(const_cast<DEVMODEW*>(devmode)); // copies devmode
}
already_AddRefed<nsIPrintSettings> CreatePlatformPrintSettings(
const PrintSettingsInitializer& aSettings) {
auto settings = MakeRefPtr<nsPrintSettingsWin>();
settings->InitWithInitializer(aSettings);
// When printing to PDF on Windows there is no associated printer driver.
int16_t outputFormat;
settings->GetOutputFormat(&outputFormat);
if (outputFormat == nsIPrintSettings::kOutputFormatPDF) {
return settings.forget();
}
RefPtr<nsDeviceContextSpecWin> devSpecWin = new nsDeviceContextSpecWin();
nsString name;
settings->GetPrinterName(name);
devSpecWin->GetDataFromPrinter(name);
LPDEVMODEW devmode;
devSpecWin->GetDevMode(devmode);
if (NS_WARN_IF(!devmode)) {
return settings.forget();
}
// TODO(nordzilla, 1658299)
// We need to get information from the device as well.
// See InitPrintSettingsFromPrinter call to CreateICW and the code
// below it. The issue is that we can't do it here. It needs to
// happen async, off the main thread, similar to the code that
// populates the PrintSettingsInitializer argument.
return settings.forget();
}

Просмотреть файл

@ -23,7 +23,8 @@ class nsPrintSettingsWin : public nsPrintSettings, public nsIPrintSettingsWin {
nsPrintSettingsWin();
nsPrintSettingsWin(const nsPrintSettingsWin& aPS);
explicit nsPrintSettingsWin(const PrintSettingsInitializer&);
void InitWithInitializer(const PrintSettingsInitializer& aSettings) final;
/**
* Makes a new copy

Просмотреть файл

@ -7,15 +7,19 @@
#include <algorithm>
#include <windows.h>
#include <winspool.h>
#include "mozilla/Array.h"
#include "nsPaper.h"
#include "nsPrintSettingsImpl.h"
#include "nsWindowsHelpers.h"
#include "WinUtils.h"
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
static const float kTenthMMToPoint =
(POINTS_PER_INCH_FLOAT / MM_PER_INCH_FLOAT) / 10;
static const double kTenthMMToPoint = 72.0 / 254.0;
nsPrinterWin::nsPrinterWin(const nsAString& aName) : mName(aName) {}
@ -24,12 +28,57 @@ already_AddRefed<nsPrinterWin> nsPrinterWin::Create(const nsAString& aName) {
return do_AddRef(new nsPrinterWin(aName));
}
// TODO(nordzilla, 165829) This needs to be implemented for windows.
// It should basically collect the same information as
// nsPrinterListWin::InitPrintSettingsFromPrinter.
PrintSettingsInitializer nsPrinterWin::DefaultSettings() const {
PrintSettingsInitializer settings;
return settings;
nsAutoPrinter autoPrinter(nsHPRINTER(nullptr));
BOOL status = ::OpenPrinterW(mName.get(), &autoPrinter.get(), nullptr);
if (NS_WARN_IF(!status)) {
return PrintSettingsInitializer();
}
// Allocate devmode storage of the correct size.
LONG bytesNeeded = ::DocumentPropertiesW(nullptr, autoPrinter.get(),
mName.get(), nullptr, nullptr, 0);
if (NS_WARN_IF(bytesNeeded < 0)) {
return PrintSettingsInitializer();
}
nsTArray<uint8_t> devmodeWStorage(bytesNeeded);
devmodeWStorage.SetLength(bytesNeeded);
DEVMODEW* devmode = reinterpret_cast<DEVMODEW*>(devmodeWStorage.Elements());
LONG ret = ::DocumentPropertiesW(nullptr, autoPrinter.get(), mName.get(),
devmode, nullptr, DM_OUT_BUFFER);
if (NS_WARN_IF(ret != IDOK)) {
return PrintSettingsInitializer();
}
nsAutoHDC printerDc(::CreateICW(nullptr, mName.get(), nullptr, devmode));
if (NS_WARN_IF(!printerDc)) {
return PrintSettingsInitializer();
}
nsString paperName;
SizeDouble paperSize;
for (auto paperInfo : PaperList()) {
if (paperInfo.mPaperId == devmode->dmPaperSize) {
paperName.Assign(paperInfo.mName);
paperSize = paperInfo.mSize;
break;
}
}
auto margin = WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
margin.top *= POINTS_PER_INCH_FLOAT;
margin.right *= POINTS_PER_INCH_FLOAT;
margin.bottom *= POINTS_PER_INCH_FLOAT;
margin.left *= POINTS_PER_INCH_FLOAT;
// Using Y to match existing code for print scaling calculations.
int resolution = GetDeviceCaps(printerDc, LOGPIXELSY);
return PrintSettingsInitializer{mName,
PaperInfo(paperName, paperSize, Some(margin)),
devmode->dmColor == DMCOLOR_COLOR, resolution,
std::move(devmodeWStorage)};
}
template <class T>