зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
dd5507b91b
Коммит
72fd7de5a6
|
@ -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>
|
||||
|
|
Загрузка…
Ссылка в новой задаче