зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1663652 part 2 - Add combined printerInfo method to nsPrinterCUPS r=emilio
Since we no longer are using the PaperList or CreateDefaultSettings methods on nsPrinterBase, and we can remove them from nsPrinterBase. This should dramatically improve latency when the remote printer is not available, or when the print server is slower. In the best-case scenario it may increase the latency to displaying the print preview somewhat. Differential Revision: https://phabricator.services.mozilla.com/D94482
This commit is contained in:
Родитель
1fbcb914c4
Коммит
6635212e1a
|
@ -199,10 +199,6 @@ nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray* aPaperInfoArray)
|
|||
}
|
||||
nsPrinterBase::~nsPrinterBase() = default;
|
||||
|
||||
nsPrinterBase::PrinterInfo nsPrinterBase::CreatePrinterInfo() const {
|
||||
return PrinterInfo{PaperList(), DefaultSettings()};
|
||||
}
|
||||
|
||||
const PaperInfo* nsPrinterBase::FindCommonPaperSize(
|
||||
const gfx::SizeDouble& aSize) const {
|
||||
for (const PaperInfo& paper : *mCommonPaperInfo) {
|
||||
|
|
|
@ -90,14 +90,12 @@ class nsPrinterBase : public nsIPrinter {
|
|||
|
||||
// Implementation-specific methods. These must not make assumptions about
|
||||
// which thread they run on.
|
||||
virtual PrintSettingsInitializer DefaultSettings() const = 0;
|
||||
virtual bool SupportsDuplex() const = 0;
|
||||
virtual bool SupportsColor() const = 0;
|
||||
virtual bool SupportsMonochrome() const = 0;
|
||||
virtual bool SupportsCollation() const = 0;
|
||||
virtual nsTArray<mozilla::PaperInfo> PaperList() const = 0;
|
||||
virtual MarginDouble GetMarginsForPaper(nsString aPaperId) const = 0;
|
||||
virtual PrinterInfo CreatePrinterInfo() const;
|
||||
virtual PrinterInfo CreatePrinterInfo() const = 0;
|
||||
// Searches our built-in list of commonly used PWG paper sizes for a matching,
|
||||
// localized PaperInfo. Returns null if there is no matching size.
|
||||
const mozilla::PaperInfo* FindCommonPaperSize(
|
||||
|
|
|
@ -90,78 +90,6 @@ nsPrinterCUPS::~nsPrinterCUPS() {
|
|||
}
|
||||
}
|
||||
|
||||
PrintSettingsInitializer nsPrinterCUPS::DefaultSettings() const {
|
||||
nsString printerName;
|
||||
GetPrinterName(printerName);
|
||||
auto printerInfoLock = mPrinterInfoMutex.Lock();
|
||||
TryEnsurePrinterInfo(*printerInfoLock);
|
||||
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
|
||||
|
||||
cups_size_t media;
|
||||
|
||||
// cupsGetDestMediaDefault appears to return more accurate defaults on macOS,
|
||||
// and the IPP attribute appears to return more accurate defaults on Linux.
|
||||
#ifdef XP_MACOSX
|
||||
bool hasDefaultMedia =
|
||||
mShim.cupsGetDestMediaDefault(CUPS_HTTP_DEFAULT, mPrinter, printerInfo,
|
||||
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||
#else
|
||||
ipp_attribute_t* defaultMediaIPP = mShim.cupsFindDestDefault(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, printerInfo, "media");
|
||||
|
||||
const char* defaultMediaName =
|
||||
mShim.ippGetString(defaultMediaIPP, 0, nullptr);
|
||||
|
||||
bool hasDefaultMedia = mShim.cupsGetDestMediaByName(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, printerInfo, defaultMediaName,
|
||||
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||
#endif
|
||||
|
||||
if (!hasDefaultMedia) {
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
PaperInfo(),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
// Check if this is a localized fallback paper size, in which case we can
|
||||
// avoid using the CUPS localization methods.
|
||||
const gfx::SizeDouble sizeDouble{
|
||||
media.width * kPointsPerHundredthMillimeter,
|
||||
media.length * kPointsPerHundredthMillimeter};
|
||||
if (const PaperInfo* const paperInfo = FindCommonPaperSize(sizeDouble)) {
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
MakePaperInfo(paperInfo->mName, media),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
// blocking call
|
||||
http_t* connection = mShim.cupsConnectDest(mPrinter, CUPS_DEST_FLAGS_NONE,
|
||||
/* timeout(ms) */ 5000,
|
||||
/* cancel */ nullptr,
|
||||
/* resource */ nullptr,
|
||||
/* resourcesize */ 0,
|
||||
/* callback */ nullptr,
|
||||
/* user_data */ nullptr);
|
||||
|
||||
// XXX Do we actually have the guarantee that this is utf-8?
|
||||
NS_ConvertUTF8toUTF16 localizedName{
|
||||
connection ? LocalizeMediaName(*connection, media) : ""};
|
||||
|
||||
if (connection) {
|
||||
mShim.httpClose(connection);
|
||||
}
|
||||
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
MakePaperInfo(localizedName, media),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPrinterCUPS::GetName(nsAString& aName) {
|
||||
GetPrinterName(aName);
|
||||
|
@ -230,6 +158,11 @@ bool nsPrinterCUPS::SupportsCollation() const {
|
|||
return type & CUPS_PRINTER_COLLATE;
|
||||
}
|
||||
|
||||
nsPrinterBase::PrinterInfo nsPrinterCUPS::CreatePrinterInfo() const {
|
||||
Connection connection{mShim};
|
||||
return PrinterInfo{PaperList(connection), DefaultSettings(connection)};
|
||||
}
|
||||
|
||||
bool nsPrinterCUPS::Supports(const char* aOption, const char* aValue) const {
|
||||
auto printerInfoLock = mPrinterInfoMutex.Lock();
|
||||
TryEnsurePrinterInfo(*printerInfoLock);
|
||||
|
@ -263,28 +196,101 @@ bool nsPrinterCUPS::IsCUPSVersionAtLeast(uint64_t aCUPSMajor,
|
|||
return aCUPSPatch <= printerInfoLock->mCUPSPatch;
|
||||
}
|
||||
|
||||
nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
|
||||
// blocking call
|
||||
http_t* connection = mShim.cupsConnectDest(mPrinter, CUPS_DEST_FLAGS_NONE,
|
||||
/* timeout(ms) */ 5000,
|
||||
/* cancel */ nullptr,
|
||||
/* resource */ nullptr,
|
||||
/* resourcesize */ 0,
|
||||
/* callback */ nullptr,
|
||||
/* user_data */ nullptr);
|
||||
http_t* nsPrinterCUPS::Connection::GetConnection(cups_dest_t* aDest) {
|
||||
if (mWasInited) {
|
||||
return mConnection;
|
||||
}
|
||||
mWasInited = true;
|
||||
|
||||
if (!connection) {
|
||||
connection = CUPS_HTTP_DEFAULT;
|
||||
// blocking call
|
||||
http_t* const connection = mShim.cupsConnectDest(aDest, CUPS_DEST_FLAGS_NONE,
|
||||
/* timeout(ms) */ 5000,
|
||||
/* cancel */ nullptr,
|
||||
/* resource */ nullptr,
|
||||
/* resourcesize */ 0,
|
||||
/* callback */ nullptr,
|
||||
/* user_data */ nullptr);
|
||||
if (connection) {
|
||||
mConnection = connection;
|
||||
}
|
||||
return mConnection;
|
||||
}
|
||||
|
||||
nsPrinterCUPS::Connection::~Connection() {
|
||||
if (mWasInited && mConnection) {
|
||||
mShim.httpClose(mConnection);
|
||||
}
|
||||
}
|
||||
|
||||
PrintSettingsInitializer nsPrinterCUPS::DefaultSettings(
|
||||
Connection& aConnection) const {
|
||||
nsString printerName;
|
||||
GetPrinterName(printerName);
|
||||
auto printerInfoLock = mPrinterInfoMutex.Lock();
|
||||
TryEnsurePrinterInfo(*printerInfoLock);
|
||||
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
|
||||
|
||||
cups_size_t media;
|
||||
|
||||
// cupsGetDestMediaDefault appears to return more accurate defaults on macOS,
|
||||
// and the IPP attribute appears to return more accurate defaults on Linux.
|
||||
#ifdef XP_MACOSX
|
||||
bool hasDefaultMedia =
|
||||
mShim.cupsGetDestMediaDefault(CUPS_HTTP_DEFAULT, mPrinter, printerInfo,
|
||||
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||
#else
|
||||
ipp_attribute_t* defaultMediaIPP = mShim.cupsFindDestDefault(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, printerInfo, "media");
|
||||
|
||||
const char* defaultMediaName =
|
||||
mShim.ippGetString(defaultMediaIPP, 0, nullptr);
|
||||
|
||||
bool hasDefaultMedia = mShim.cupsGetDestMediaByName(
|
||||
CUPS_HTTP_DEFAULT, mPrinter, printerInfo, defaultMediaName,
|
||||
CUPS_MEDIA_FLAGS_DEFAULT, &media);
|
||||
#endif
|
||||
|
||||
if (!hasDefaultMedia) {
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
PaperInfo(),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
// Check if this is a localized fallback paper size, in which case we can
|
||||
// avoid using the CUPS localization methods.
|
||||
const gfx::SizeDouble sizeDouble{
|
||||
media.width * kPointsPerHundredthMillimeter,
|
||||
media.length * kPointsPerHundredthMillimeter};
|
||||
if (const PaperInfo* const paperInfo = FindCommonPaperSize(sizeDouble)) {
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
MakePaperInfo(paperInfo->mName, media),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
http_t* const connection = aConnection.GetConnection(mPrinter);
|
||||
// XXX Do we actually have the guarantee that this is utf-8?
|
||||
NS_ConvertUTF8toUTF16 localizedName{
|
||||
connection ? LocalizeMediaName(*connection, media) : ""};
|
||||
|
||||
return PrintSettingsInitializer{
|
||||
std::move(printerName),
|
||||
MakePaperInfo(localizedName, media),
|
||||
SupportsColor(),
|
||||
};
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList(
|
||||
Connection& aConnection) const {
|
||||
http_t* const connection = aConnection.GetConnection(mPrinter);
|
||||
auto printerInfoLock = mPrinterInfoMutex.Lock();
|
||||
TryEnsurePrinterInfo(*printerInfoLock, connection);
|
||||
cups_dinfo_t* const printerInfo = printerInfoLock->mPrinterInfo;
|
||||
|
||||
if (!printerInfo) {
|
||||
if (connection) {
|
||||
mShim.httpClose(connection);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -317,10 +323,6 @@ nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
|
|||
}
|
||||
}
|
||||
|
||||
if (connection) {
|
||||
mShim.httpClose(connection);
|
||||
}
|
||||
|
||||
return paperList;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,12 +21,11 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
|||
public:
|
||||
NS_IMETHOD GetName(nsAString& aName) override;
|
||||
NS_IMETHOD GetSystemName(nsAString& aName) override;
|
||||
PrintSettingsInitializer DefaultSettings() const final;
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
bool SupportsMonochrome() const final;
|
||||
bool SupportsCollation() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
PrinterInfo CreatePrinterInfo() const final;
|
||||
MarginDouble GetMarginsForPaper(nsString aPaperId) const final {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"The CUPS API requires us to always get the margin when fetching the "
|
||||
|
@ -82,6 +81,22 @@ class nsPrinterCUPS final : public nsPrinterBase {
|
|||
bool IsCUPSVersionAtLeast(uint64_t aCUPSMajor, uint64_t aCUPSMinor,
|
||||
uint64_t aCUPSPatch) const;
|
||||
|
||||
class Connection {
|
||||
public:
|
||||
http_t* GetConnection(cups_dest_t* aDest);
|
||||
|
||||
inline explicit Connection(const nsCUPSShim& aShim) : mShim(aShim) {}
|
||||
Connection() = delete;
|
||||
~Connection();
|
||||
|
||||
protected:
|
||||
const nsCUPSShim& mShim;
|
||||
http_t* mConnection = CUPS_HTTP_DEFAULT;
|
||||
bool mWasInited = false;
|
||||
};
|
||||
|
||||
PrintSettingsInitializer DefaultSettings(Connection& aConnection) const;
|
||||
nsTArray<mozilla::PaperInfo> PaperList(Connection& aConnection) const;
|
||||
/**
|
||||
* Attempts to populate the CUPSPrinterInfo object.
|
||||
* This usually works with the CUPS default connection,
|
||||
|
|
|
@ -34,110 +34,6 @@ already_AddRefed<nsPrinterWin> nsPrinterWin::Create(
|
|||
return do_AddRef(new nsPrinterWin(aArray, aName));
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> nsPrinterWin::CopyDefaultDevmodeW() const {
|
||||
nsTArray<uint8_t> devmodeStorageW;
|
||||
|
||||
auto devmodeStorageWLock = mDefaultDevmodeWStorage.Lock();
|
||||
if (devmodeStorageWLock->IsEmpty()) {
|
||||
nsHPRINTER hPrinter = nullptr;
|
||||
// OpenPrinter could fail if, for example, the printer has been removed
|
||||
// or otherwise become inaccessible since it was selected.
|
||||
if (NS_WARN_IF(!::OpenPrinterW(mName.get(), &hPrinter, nullptr))) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
nsAutoPrinter autoPrinter(hPrinter);
|
||||
// Allocate devmode storage of the correct size.
|
||||
LONG bytesNeeded = ::DocumentPropertiesW(nullptr, autoPrinter.get(),
|
||||
mName.get(), nullptr, nullptr, 0);
|
||||
// Note that we must cast the sizeof() to a signed type so that comparison
|
||||
// with the signed, potentially-negative bytesNeeded will work!
|
||||
MOZ_ASSERT(bytesNeeded >= LONG(sizeof(DEVMODEW)),
|
||||
"DocumentPropertiesW failed to get valid size");
|
||||
if (bytesNeeded < LONG(sizeof(DEVMODEW))) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
|
||||
// Allocate extra space in case of bad drivers that return a too-small
|
||||
// result from DocumentProperties.
|
||||
// (See https://bugzilla.mozilla.org/show_bug.cgi?id=1664530#c5)
|
||||
devmodeStorageWLock->SetLength(bytesNeeded * 2);
|
||||
auto* devmode =
|
||||
reinterpret_cast<DEVMODEW*>(devmodeStorageWLock->Elements());
|
||||
LONG ret = ::DocumentPropertiesW(nullptr, autoPrinter.get(), mName.get(),
|
||||
devmode, nullptr, DM_OUT_BUFFER);
|
||||
MOZ_ASSERT(ret == IDOK, "DocumentPropertiesW failed");
|
||||
if (ret != IDOK) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
}
|
||||
|
||||
devmodeStorageW.Assign(devmodeStorageWLock.ref());
|
||||
return devmodeStorageW;
|
||||
}
|
||||
|
||||
PrintSettingsInitializer nsPrinterWin::DefaultSettings() const {
|
||||
// Initialize to something reasonable, in case we fail to get usable data
|
||||
// from the devmode below.
|
||||
nsString paperIdString(u"1"); // DMPAPER_LETTER
|
||||
bool color = true;
|
||||
|
||||
nsTArray<uint8_t> devmodeWStorage = CopyDefaultDevmodeW();
|
||||
if (devmodeWStorage.IsEmpty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto* devmode =
|
||||
reinterpret_cast<const DEVMODEW*>(devmodeWStorage.Elements());
|
||||
|
||||
// XXX If DM_PAPERSIZE is not set, or is not a known value, should we
|
||||
// be returning a "Custom" name of some kind?
|
||||
if (devmode->dmFields & DM_PAPERSIZE) {
|
||||
paperIdString.Truncate(0);
|
||||
paperIdString.AppendInt(devmode->dmPaperSize);
|
||||
}
|
||||
|
||||
if (devmode->dmFields & DM_COLOR) {
|
||||
// See comment for PrintSettingsInitializer.mPrintInColor
|
||||
color = devmode->dmColor != DMCOLOR_MONOCHROME;
|
||||
}
|
||||
|
||||
nsAutoHDC printerDc(::CreateICW(nullptr, mName.get(), nullptr, devmode));
|
||||
MOZ_ASSERT(printerDc, "CreateICW failed");
|
||||
if (!printerDc) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int pixelsPerInchY = ::GetDeviceCaps(printerDc, LOGPIXELSY);
|
||||
int physicalHeight = ::GetDeviceCaps(printerDc, PHYSICALHEIGHT);
|
||||
double heightInInches = double(physicalHeight) / pixelsPerInchY;
|
||||
int pixelsPerInchX = ::GetDeviceCaps(printerDc, LOGPIXELSX);
|
||||
int physicalWidth = ::GetDeviceCaps(printerDc, PHYSICALWIDTH);
|
||||
double widthInches = double(physicalWidth) / pixelsPerInchX;
|
||||
if (devmode->dmFields & DM_ORIENTATION &&
|
||||
devmode->dmOrientation == DMORIENT_LANDSCAPE) {
|
||||
std::swap(widthInches, heightInInches);
|
||||
}
|
||||
SizeDouble paperSize(widthInches * kPointsPerInch,
|
||||
heightInInches * kPointsPerInch);
|
||||
|
||||
gfx::MarginDouble margin =
|
||||
WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
margin.top *= kPointsPerInch;
|
||||
margin.right *= kPointsPerInch;
|
||||
margin.bottom *= kPointsPerInch;
|
||||
margin.left *= kPointsPerInch;
|
||||
|
||||
// Using Y to match existing code for print scaling calculations.
|
||||
int resolution = pixelsPerInchY;
|
||||
|
||||
// We don't actually need the paper name in the settings because the
|
||||
// paperIdString is used to look up the paper details in the front end.
|
||||
nsString paperName;
|
||||
return PrintSettingsInitializer{
|
||||
mName, PaperInfo(paperIdString, paperName, paperSize, Some(margin)),
|
||||
color, resolution, std::move(devmodeWStorage)};
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static nsTArray<T> GetDeviceCapabilityArray(const LPWSTR aPrinterName,
|
||||
WORD aCapabilityID, int& aCount) {
|
||||
|
@ -248,6 +144,78 @@ bool nsPrinterWin::SupportsCollation() const {
|
|||
return ::DeviceCapabilitiesW(mName.get(), nullptr, DC_COLLATE, nullptr,
|
||||
nullptr) == 1;
|
||||
}
|
||||
|
||||
nsPrinterBase::PrinterInfo nsPrinterWin::CreatePrinterInfo() const {
|
||||
return PrinterInfo{PaperList(), DefaultSettings()};
|
||||
}
|
||||
|
||||
mozilla::gfx::MarginDouble nsPrinterWin::GetMarginsForPaper(
|
||||
nsString aPaperId) const {
|
||||
gfx::MarginDouble margin;
|
||||
|
||||
nsTArray<uint8_t> devmodeWStorage = CopyDefaultDevmodeW();
|
||||
if (devmodeWStorage.IsEmpty()) {
|
||||
return margin;
|
||||
}
|
||||
|
||||
auto* devmode = reinterpret_cast<DEVMODEW*>(devmodeWStorage.Elements());
|
||||
|
||||
devmode->dmFields = DM_PAPERSIZE;
|
||||
devmode->dmPaperSize = _wtoi((const wchar_t*)aPaperId.BeginReading());
|
||||
nsAutoHDC printerDc(::CreateICW(nullptr, mName.get(), nullptr, devmode));
|
||||
MOZ_ASSERT(printerDc, "CreateICW failed");
|
||||
if (!printerDc) {
|
||||
return margin;
|
||||
}
|
||||
margin = WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
margin.top *= kPointsPerInch;
|
||||
margin.right *= kPointsPerInch;
|
||||
margin.bottom *= kPointsPerInch;
|
||||
margin.left *= kPointsPerInch;
|
||||
|
||||
return margin;
|
||||
}
|
||||
|
||||
nsTArray<uint8_t> nsPrinterWin::CopyDefaultDevmodeW() const {
|
||||
nsTArray<uint8_t> devmodeStorageW;
|
||||
|
||||
auto devmodeStorageWLock = mDefaultDevmodeWStorage.Lock();
|
||||
if (devmodeStorageWLock->IsEmpty()) {
|
||||
nsHPRINTER hPrinter = nullptr;
|
||||
// OpenPrinter could fail if, for example, the printer has been removed
|
||||
// or otherwise become inaccessible since it was selected.
|
||||
if (NS_WARN_IF(!::OpenPrinterW(mName.get(), &hPrinter, nullptr))) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
nsAutoPrinter autoPrinter(hPrinter);
|
||||
// Allocate devmode storage of the correct size.
|
||||
LONG bytesNeeded = ::DocumentPropertiesW(nullptr, autoPrinter.get(),
|
||||
mName.get(), nullptr, nullptr, 0);
|
||||
// Note that we must cast the sizeof() to a signed type so that comparison
|
||||
// with the signed, potentially-negative bytesNeeded will work!
|
||||
MOZ_ASSERT(bytesNeeded >= LONG(sizeof(DEVMODEW)),
|
||||
"DocumentPropertiesW failed to get valid size");
|
||||
if (bytesNeeded < LONG(sizeof(DEVMODEW))) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
|
||||
// Allocate extra space in case of bad drivers that return a too-small
|
||||
// result from DocumentProperties.
|
||||
// (See https://bugzilla.mozilla.org/show_bug.cgi?id=1664530#c5)
|
||||
devmodeStorageWLock->SetLength(bytesNeeded * 2);
|
||||
auto* devmode =
|
||||
reinterpret_cast<DEVMODEW*>(devmodeStorageWLock->Elements());
|
||||
LONG ret = ::DocumentPropertiesW(nullptr, autoPrinter.get(), mName.get(),
|
||||
devmode, nullptr, DM_OUT_BUFFER);
|
||||
MOZ_ASSERT(ret == IDOK, "DocumentPropertiesW failed");
|
||||
if (ret != IDOK) {
|
||||
return devmodeStorageW;
|
||||
}
|
||||
}
|
||||
|
||||
devmodeStorageW.Assign(devmodeStorageWLock.ref());
|
||||
return devmodeStorageW;
|
||||
}
|
||||
|
||||
nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
|
||||
// Paper IDs are returned as WORDs.
|
||||
|
@ -305,29 +273,65 @@ nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
|
|||
return paperList;
|
||||
}
|
||||
|
||||
mozilla::gfx::MarginDouble nsPrinterWin::GetMarginsForPaper(
|
||||
nsString aPaperId) const {
|
||||
gfx::MarginDouble margin;
|
||||
PrintSettingsInitializer nsPrinterWin::DefaultSettings() const {
|
||||
// Initialize to something reasonable, in case we fail to get usable data
|
||||
// from the devmode below.
|
||||
nsString paperIdString(u"1"); // DMPAPER_LETTER
|
||||
bool color = true;
|
||||
|
||||
nsTArray<uint8_t> devmodeWStorage = CopyDefaultDevmodeW();
|
||||
if (devmodeWStorage.IsEmpty()) {
|
||||
return margin;
|
||||
return {};
|
||||
}
|
||||
|
||||
auto* devmode = reinterpret_cast<DEVMODEW*>(devmodeWStorage.Elements());
|
||||
const auto* devmode =
|
||||
reinterpret_cast<const DEVMODEW*>(devmodeWStorage.Elements());
|
||||
|
||||
// XXX If DM_PAPERSIZE is not set, or is not a known value, should we
|
||||
// be returning a "Custom" name of some kind?
|
||||
if (devmode->dmFields & DM_PAPERSIZE) {
|
||||
paperIdString.Truncate(0);
|
||||
paperIdString.AppendInt(devmode->dmPaperSize);
|
||||
}
|
||||
|
||||
if (devmode->dmFields & DM_COLOR) {
|
||||
// See comment for PrintSettingsInitializer.mPrintInColor
|
||||
color = devmode->dmColor != DMCOLOR_MONOCHROME;
|
||||
}
|
||||
|
||||
devmode->dmFields = DM_PAPERSIZE;
|
||||
devmode->dmPaperSize = _wtoi((const wchar_t*)aPaperId.BeginReading());
|
||||
nsAutoHDC printerDc(::CreateICW(nullptr, mName.get(), nullptr, devmode));
|
||||
MOZ_ASSERT(printerDc, "CreateICW failed");
|
||||
if (!printerDc) {
|
||||
return margin;
|
||||
return {};
|
||||
}
|
||||
margin = WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
|
||||
int pixelsPerInchY = ::GetDeviceCaps(printerDc, LOGPIXELSY);
|
||||
int physicalHeight = ::GetDeviceCaps(printerDc, PHYSICALHEIGHT);
|
||||
double heightInInches = double(physicalHeight) / pixelsPerInchY;
|
||||
int pixelsPerInchX = ::GetDeviceCaps(printerDc, LOGPIXELSX);
|
||||
int physicalWidth = ::GetDeviceCaps(printerDc, PHYSICALWIDTH);
|
||||
double widthInches = double(physicalWidth) / pixelsPerInchX;
|
||||
if (devmode->dmFields & DM_ORIENTATION &&
|
||||
devmode->dmOrientation == DMORIENT_LANDSCAPE) {
|
||||
std::swap(widthInches, heightInInches);
|
||||
}
|
||||
SizeDouble paperSize(widthInches * kPointsPerInch,
|
||||
heightInInches * kPointsPerInch);
|
||||
|
||||
gfx::MarginDouble margin =
|
||||
WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
|
||||
margin.top *= kPointsPerInch;
|
||||
margin.right *= kPointsPerInch;
|
||||
margin.bottom *= kPointsPerInch;
|
||||
margin.left *= kPointsPerInch;
|
||||
|
||||
return margin;
|
||||
// Using Y to match existing code for print scaling calculations.
|
||||
int resolution = pixelsPerInchY;
|
||||
|
||||
// We don't actually need the paper name in the settings because the
|
||||
// paperIdString is used to look up the paper details in the front end.
|
||||
nsString paperName;
|
||||
return PrintSettingsInitializer{
|
||||
mName, PaperInfo(paperIdString, paperName, paperSize, Some(margin)),
|
||||
color, resolution, std::move(devmodeWStorage)};
|
||||
}
|
||||
|
|
|
@ -14,12 +14,11 @@ class nsPrinterWin final : public nsPrinterBase {
|
|||
public:
|
||||
NS_IMETHOD GetName(nsAString& aName) override;
|
||||
NS_IMETHOD GetSystemName(nsAString& aName) override;
|
||||
PrintSettingsInitializer DefaultSettings() const final;
|
||||
bool SupportsDuplex() const final;
|
||||
bool SupportsColor() const final;
|
||||
bool SupportsMonochrome() const final;
|
||||
bool SupportsCollation() const final;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const final;
|
||||
PrinterInfo CreatePrinterInfo() const final;
|
||||
MarginDouble GetMarginsForPaper(nsString aPaperId) const final;
|
||||
|
||||
nsPrinterWin() = delete;
|
||||
|
@ -33,6 +32,8 @@ class nsPrinterWin final : public nsPrinterBase {
|
|||
~nsPrinterWin() = default;
|
||||
|
||||
nsTArray<uint8_t> CopyDefaultDevmodeW() const;
|
||||
nsTArray<mozilla::PaperInfo> PaperList() const;
|
||||
PrintSettingsInitializer DefaultSettings() const;
|
||||
|
||||
const nsString mName;
|
||||
mutable mozilla::DataMutex<nsTArray<uint8_t>> mDefaultDevmodeWStorage;
|
||||
|
|
Загрузка…
Ссылка в новой задаче