Bug 1655558 - Retrieve the paper margins lazily on Windows. r=jwatt,bobowen

This is no worse than what we were doing.

In the future, instead of just querying the margin we may want to query
extra information that requires a DC in windows too or what not, for
example.

Differential Revision: https://phabricator.services.mozilla.com/D85919
This commit is contained in:
Emilio Cobos Álvarez
2020-08-05 11:26:13 +00:00
parent 913fa9c769
commit 4bfe2ce33f
15 changed files with 297 additions and 141 deletions

View File

@@ -26,7 +26,8 @@ async function run() {
for (let paper of paperList) {
paper.QueryInterface(Ci.nsIPaper);
info(`${paper.name}: ${paper.width}x${paper.height} with margin: ${paper.unwriteableMarginTop} ${paper.unwriteableMarginRight} ${paper.unwriteableMarginBottom} ${paper.unwriteableMarginLeft}`);
info(`${paper.name}: ${paper.width}x${paper.height}`);
isnot(paper.name, null, "Paper name should never be null.");
isnot(paper.name, "", "Paper name should never be empty.");
@@ -36,20 +37,24 @@ async function run() {
isnot(paper.height, null, "Paper height should never be null.");
ok(paper.height > 0.0, "Paper height should be greater than zero.");
isnot(paper.unwriteableMarginTop, null, "Paper unwriteableMarginTop should never be null.");
ok(paper.unwriteableMarginTop >= 0.0, "Paper unwriteableMarginTop should be greater than or equal to zero.");
isnot(paper.unwriteableMarginBottom, null, "Paper unwriteableMarginBottom should never be null.");
ok(paper.unwriteableMarginBottom >= 0.0, "Paper unwriteableMarginBottom should be greater than or equal to zero.");
let margin = await paper.unwriteableMargin;
margin.QueryInterface(Ci.nsIPaperMargin);
isnot(paper.unwriteableMarginLeft, null, "Paper unwriteableMarginLeft should never be null.");
ok(paper.unwriteableMarginLeft >= 0.0, "Paper unwriteableMarginLeft should be greater than or equal to zero.");
info(`with margin: ${margin.top} ${margin.right} ${margin.bottom} ${margin.left}`);
is(typeof(margin.top), 'number', "Paper unwriteable margin top should be a number.");
is(typeof(margin.right), 'number', "Paper unwriteable margin right should be a number.");
is(typeof(margin.bottom), 'number', "Paper unwriteable margin bottom should be a number.");
is(typeof(margin.left), 'number', "Paper unwriteable margin left should be a number.");
isnot(paper.unwriteableMarginRight, null, "Paper unwriteableMarginRight should never be null.");
ok(paper.unwriteableMarginRight >= 0.0, "Paper unwriteableMarginRight should be greater than or equal to zero.");
ok(margin.top >= 0.0, "Paper unwriteable margin top should be greater than or equal to zero.");
ok(margin.right >= 0.0, "Paper unwriteable margin right should be greater than or equal to zero.");
ok(margin.bottom >= 0.0, "Paper unwriteable bottom right should be greater than or equal to zero.");
ok(margin.left >= 0.0, "Paper unwriteable margin left should be greater than or equal to zero.");
}
}
} catch (e) {
ok(false, `Shouldn't throw: ${e}`);
Cu.reportError(e);
}
SimpleTest.finish();

View File

@@ -110,6 +110,7 @@ XPIDL_SOURCES += [
'nsIGfxInfo.idl',
'nsIGfxInfoDebug.idl',
'nsIPaper.idl',
'nsIPaperMargin.idl',
'nsIPrinter.idl',
'nsIPrinterList.idl',
'nsIPrintSession.idl',
@@ -237,6 +238,7 @@ if CONFIG['MOZ_XUL'] and CONFIG['NS_PRINTING']:
UNIFIED_SOURCES += [
'nsDeviceContextSpecProxy.cpp',
'nsPaper.cpp',
'nsPaperMargin.cpp',
'nsPrinterBase.cpp',
'nsPrintSession.cpp',
'nsPrintSettingsService.cpp',

View File

@@ -23,23 +23,5 @@ interface nsIPaper : nsISupports
*/
readonly attribute double height;
/**
* The unwritable margin at the top of the paper in points.
*/
readonly attribute double unwriteableMarginTop;
/**
* The unwritable margin at the bottom of the paper in points.
*/
readonly attribute double unwriteableMarginBottom;
/**
* The unwritable margin at the left of the paper in points.
*/
readonly attribute double unwriteableMarginLeft;
/**
* The unwritable margin at the right of the paper in points.
*/
readonly attribute double unwriteableMarginRight;
[implicit_jscontext] readonly attribute Promise unwriteableMargin;
};

16
widget/nsIPaperMargin.idl Normal file
View File

@@ -0,0 +1,16 @@
/* -*- Mode: C++; tab-width: 4; 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 "nsISupports.idl"
// A margin for a sheet of paper.
[builtinclass, scriptable, uuid(0858d1a7-b646-4b15-a1e8-7eb5ab572d0a)]
interface nsIPaperMargin : nsISupports
{
[infallible] readonly attribute double top;
[infallible] readonly attribute double right;
[infallible] readonly attribute double bottom;
[infallible] readonly attribute double left;
};

View File

@@ -4,8 +4,27 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsPaper.h"
#include "nsPaperMargin.h"
#include "nsPrinterBase.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Promise.h"
NS_IMPL_ISUPPORTS(nsPaper, nsIPaper);
using mozilla::ErrorResult;
NS_IMPL_CYCLE_COLLECTION(nsPaper, mMarginPromise, mPrinter)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPaper)
NS_INTERFACE_MAP_ENTRY(nsIPaper)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPaper)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPaper)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPaper)
nsPaper::nsPaper(nsPrinterBase& aPrinter, const mozilla::PaperInfo& aInfo)
: mPrinter(&aPrinter), mInfo(aInfo) {}
nsPaper::~nsPaper() = default;
NS_IMETHODIMP
nsPaper::GetName(nsAString& aName) {
@@ -16,41 +35,38 @@ nsPaper::GetName(nsAString& aName) {
NS_IMETHODIMP
nsPaper::GetWidth(double* aWidth) {
NS_ENSURE_ARG_POINTER(aWidth);
*aWidth = mInfo.mWidth;
*aWidth = mInfo.mSize.Width();
return NS_OK;
}
NS_IMETHODIMP
nsPaper::GetHeight(double* aHeight) {
NS_ENSURE_ARG_POINTER(aHeight);
*aHeight = mInfo.mHeight;
*aHeight = mInfo.mSize.Height();
return NS_OK;
}
NS_IMETHODIMP
nsPaper::GetUnwriteableMarginTop(double* aUnwriteableMarginTop) {
NS_ENSURE_ARG_POINTER(aUnwriteableMarginTop);
*aUnwriteableMarginTop = mInfo.mUnwriteableMarginTop;
return NS_OK;
}
nsPaper::GetUnwriteableMargin(JSContext* aCx, Promise** aPromise) {
if (RefPtr<Promise> existing = mMarginPromise) {
existing.forget(aPromise);
return NS_OK;
}
ErrorResult rv;
RefPtr<Promise> promise = Promise::Create(xpc::CurrentNativeGlobal(aCx), rv);
if (MOZ_UNLIKELY(rv.Failed())) {
return rv.StealNSResult();
}
NS_IMETHODIMP
nsPaper::GetUnwriteableMarginBottom(double* aUnwriteableMarginBottom) {
NS_ENSURE_ARG_POINTER(aUnwriteableMarginBottom);
*aUnwriteableMarginBottom = mInfo.mUnwriteableMarginBottom;
return NS_OK;
}
mMarginPromise = promise;
NS_IMETHODIMP
nsPaper::GetUnwriteableMarginLeft(double* aUnwriteableMarginLeft) {
NS_ENSURE_ARG_POINTER(aUnwriteableMarginLeft);
*aUnwriteableMarginLeft = mInfo.mUnwriteableMarginLeft;
return NS_OK;
}
if (mInfo.mUnwriteableMargin) {
auto margin = mozilla::MakeRefPtr<nsPaperMargin>(*mInfo.mUnwriteableMargin);
mMarginPromise->MaybeResolve(margin);
} else {
mPrinter->QueryMarginsForPaper(*mMarginPromise, mInfo.mPaperId);
}
NS_IMETHODIMP
nsPaper::GetUnwriteableMarginRight(double* aUnwriteableMarginRight) {
NS_ENSURE_ARG_POINTER(aUnwriteableMarginRight);
*aUnwriteableMarginRight = mInfo.mUnwriteableMarginRight;
promise.forget(aPromise);
return NS_OK;
}

View File

@@ -7,52 +7,55 @@
#define nsPaper_h__
#include "mozilla/dom/ToJSValue.h"
#include "js/TypeDecls.h"
#include "mozilla/gfx/Point.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/Maybe.h"
#include "nsIPaper.h"
#include "nsISupportsImpl.h"
#include "js/RootingAPI.h"
#include "nsString.h"
struct JSContext;
namespace mozilla {
// Simple struct that can be used off the main thread to hold all the info from
// an nsPaper instance.
struct PaperInfo {
using MarginDouble = mozilla::gfx::MarginDouble;
using SizeDouble = mozilla::gfx::SizeDouble;
const nsString mName;
const double mWidth;
const double mHeight;
const double mUnwriteableMarginTop;
const double mUnwriteableMarginRight;
const double mUnwriteableMarginBottom;
const double mUnwriteableMarginLeft;
SizeDouble mSize;
// The margins may not be known by some back-ends.
const Maybe<MarginDouble> mUnwriteableMargin;
// The paper id from the device, this is only useful on Windows, right now.
uint64_t mPaperId{0};
};
} // namespace mozilla
class nsPaper final : public nsIPaper {
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPAPER
nsPaper() = delete;
class nsPrinterBase;
explicit nsPaper(const mozilla::PaperInfo& aInfo) : mInfo(aInfo) {}
class nsPaper final : public nsIPaper {
using Promise = mozilla::dom::Promise;
public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsPaper)
NS_DECL_NSIPAPER
nsPaper() = delete;
nsPaper(nsPrinterBase&, const mozilla::PaperInfo&);
private:
~nsPaper() = default;
~nsPaper();
RefPtr<nsPrinterBase> mPrinter;
RefPtr<Promise> mMarginPromise;
const mozilla::PaperInfo mInfo;
};
namespace mozilla {
// Turns this into a JSValue by wrapping it in an nsPaper struct.
//
// FIXME: If using WebIDL dictionaries we'd get this for ~free...
MOZ_MUST_USE inline bool ToJSValue(JSContext* aCx, const PaperInfo& aInfo,
JS::MutableHandleValue aValue) {
RefPtr<nsPaper> paper = new nsPaper(aInfo);
return dom::ToJSValue(aCx, paper, aValue);
}
} // namespace mozilla
#endif /* nsPaper_h__ */

32
widget/nsPaperMargin.cpp Normal file
View File

@@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 4; 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 "nsPaperMargin.h"
NS_IMPL_ISUPPORTS(nsPaperMargin, nsIPaperMargin)
NS_IMETHODIMP
nsPaperMargin::GetTop(double* aTop) {
*aTop = mMargin.top;
return NS_OK;
}
NS_IMETHODIMP
nsPaperMargin::GetRight(double* aRight) {
*aRight = mMargin.right;
return NS_OK;
}
NS_IMETHODIMP
nsPaperMargin::GetBottom(double* aBottom) {
*aBottom = mMargin.bottom;
return NS_OK;
}
NS_IMETHODIMP
nsPaperMargin::GetLeft(double* aLeft) {
*aLeft = mMargin.left;
return NS_OK;
}

29
widget/nsPaperMargin.h Normal file
View File

@@ -0,0 +1,29 @@
/* -*- Mode: C++; tab-width: 4; 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/. */
#ifndef nsPaperMargin_h_
#define nsPaperMargin_h_
#include "nsISupportsImpl.h"
#include "nsIPaperMargin.h"
#include "mozilla/gfx/Rect.h"
class nsPaperMargin final : public nsIPaperMargin {
using MarginDouble = mozilla::gfx::MarginDouble;
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPAPERMARGIN
nsPaperMargin() = delete;
explicit nsPaperMargin(const MarginDouble& aMargin) : mMargin(aMargin) {}
private:
~nsPaperMargin() = default;
const MarginDouble mMargin;
};
#endif

View File

@@ -16,6 +16,10 @@ class nsPrinter final : public nsPrinterBase {
bool SupportsDuplex() const final { return false; }
bool SupportsColor() const final { return false; }
nsTArray<mozilla::PaperInfo> PaperList() const final { return {}; }
MarginDouble GetMarginsForPaper(uint64_t) const final {
MOZ_ASSERT_UNREACHABLE("We have no paper so this shouldn't be reached");
return {};
}
nsPrinter() = delete;

View File

@@ -4,11 +4,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsPrinterBase.h"
#include "nsPaperMargin.h"
#include <utility>
#include "nsPrinter.h"
#include "nsPaper.h"
#include "mozilla/dom/Promise.h"
using namespace mozilla;
using mozilla::dom::Promise;
using mozilla::gfx::MarginDouble;
template <typename Index, Index Size, typename Value>
inline void ImplCycleCollectionTraverse(
@@ -30,9 +34,65 @@ inline void ImplCycleCollectionUnlink(
}
template <typename T>
void ResolveOrReject(Promise& aPromise, nsPrinterBase&, T& aResult) {
aPromise.MaybeResolve(std::forward<T>(aResult));
}
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase&,
const MarginDouble& aResult) {
auto margin = MakeRefPtr<nsPaperMargin>(aResult);
aPromise.MaybeResolve(margin);
}
template <>
void ResolveOrReject(Promise& aPromise, nsPrinterBase& aPrinter,
const nsTArray<PaperInfo>& aResult) {
nsTArray<RefPtr<nsPaper>> result;
result.SetCapacity(aResult.Length());
for (const PaperInfo& info : aResult) {
result.AppendElement(MakeRefPtr<nsPaper>(aPrinter, info));
}
aPromise.MaybeResolve(result);
}
template <typename T, typename... Args>
void nsPrinterBase::SpawnBackgroundTask(
Promise& aPromise, BackgroundTask<T, Args...> aBackgroundTask,
Args... aArgs) {
auto promiseHolder = MakeRefPtr<nsMainThreadPtrHolder<Promise>>(
"nsPrinterBase::SpawnBackgroundTaskPromise", &aPromise);
// We actually want to allow to access the printer data from the callback, so
// disable strict checking. They should of course only access immutable
// members.
auto holder = MakeRefPtr<nsMainThreadPtrHolder<nsPrinterBase>>(
"nsPrinterBase::SpawnBackgroundTaskPrinter", this, /* strict = */ false);
// See
// https://stackoverflow.com/questions/47496358/c-lambdas-how-to-capture-variadic-parameter-pack-from-the-upper-scope
// about the tuple shenanigans. It could be improved with C++20
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"nsPrinterBase::SpawnBackgroundTask",
[holder = std::move(holder), promiseHolder = std::move(promiseHolder),
aBackgroundTask, aArgs = std::make_tuple(std::forward<Args>(aArgs)...)] {
T result = std::apply(
[&](auto&&... args) {
return (holder->get()->*aBackgroundTask)(args...);
},
std::move(aArgs));
NS_DispatchToMainThread(NS_NewRunnableFunction(
"nsPrinterBase::SpawnBackgroundTaskResolution",
[holder = std::move(holder),
promiseHolder = std::move(promiseHolder),
result = std::move(result)] {
ResolveOrReject(*promiseHolder->get(), *holder->get(), result);
}));
}));
}
template <typename T, typename... Args>
nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
JSContext* aCx, Promise** aResultPromise, AsyncAttribute aAttribute,
AsyncAttributeBackgroundTask<T> aBackgroundTask) {
BackgroundTask<T, Args...> aBackgroundTask, Args... aArgs) {
MOZ_ASSERT(NS_IsMainThread());
if (RefPtr<Promise> existing = mAsyncAttributePromises[aAttribute]) {
existing.forget(aResultPromise);
@@ -45,29 +105,10 @@ nsresult nsPrinterBase::AsyncPromiseAttributeGetter(
return rv.StealNSResult();
}
// We actually want to allow to access the printer data from the callback, so
// disable strict checking. They should of course only access immutable
// members.
auto holder = MakeRefPtr<nsMainThreadPtrHolder<nsPrinterBase>>(
"nsPrinterBase::AsyncPromiseAttributeGetter", this, /* strict = */ false);
NS_DispatchBackgroundTask(NS_NewRunnableFunction(
"nsPrinterBase::AsyncPromiseAttributeGetter",
[holder = std::move(holder), aAttribute, aBackgroundTask] {
T result = (holder->get()->*aBackgroundTask)();
NS_DispatchToMainThread(NS_NewRunnableFunction(
"nsPrinterBase::AsyncPromiseAttributeGetterResult",
[holder = std::move(holder), result = std::move(result),
aAttribute] {
nsPrinterBase* printer = holder->get();
// There could be no promise, could've been CC'd or what not.
if (Promise* p = printer->mAsyncAttributePromises[aAttribute]) {
p->MaybeResolve(result);
}
}));
}));
RefPtr<Promise> promise = mAsyncAttributePromises[aAttribute];
SpawnBackgroundTask(*promise, aBackgroundTask, aArgs...);
RefPtr<Promise> existing = mAsyncAttributePromises[aAttribute];
existing.forget(aResultPromise);
promise.forget(aResultPromise);
return NS_OK;
}
@@ -92,6 +133,11 @@ NS_IMETHODIMP nsPrinterBase::GetPaperList(JSContext* aCx,
&nsPrinterBase::PaperList);
}
void nsPrinterBase::QueryMarginsForPaper(Promise& aPromise, uint64_t aPaperId) {
return SpawnBackgroundTask<MarginDouble, uint64_t>(
aPromise, &nsPrinterBase::GetMarginsForPaper, aPaperId);
}
NS_IMPL_CYCLE_COLLECTION(nsPrinterBase, mAsyncAttributePromises)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPrinterBase)

View File

@@ -6,6 +6,7 @@
#ifndef nsPrinterBase_h__
#define nsPrinterBase_h__
#include "mozilla/gfx/Rect.h"
#include "nsIPrinter.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupportsImpl.h"
@@ -25,6 +26,7 @@ class Promise;
class nsPrinterBase : public nsIPrinter {
public:
using Promise = mozilla::dom::Promise;
using MarginDouble = mozilla::gfx::MarginDouble;
NS_IMETHOD GetSupportsDuplex(JSContext*, Promise**) final;
NS_IMETHOD GetSupportsColor(JSContext*, Promise**) final;
@@ -37,6 +39,8 @@ class nsPrinterBase : public nsIPrinter {
nsPrinterBase(const nsPrinterBase&) = delete;
nsPrinterBase(nsPrinterBase&&) = delete;
void QueryMarginsForPaper(Promise&, uint64_t aPaperId);
private:
enum class AsyncAttribute {
SupportsDuplex = 0,
@@ -46,14 +50,18 @@ class nsPrinterBase : public nsIPrinter {
Last,
};
template <typename T>
using AsyncAttributeBackgroundTask = T (nsPrinterBase::*)() const;
template <typename T, typename... Args>
using BackgroundTask = T (nsPrinterBase::*)(Args...) const;
// Resolves a promise when a background task finishes.
template <typename T, typename... Args>
void SpawnBackgroundTask(Promise&, BackgroundTask<T, Args...>, Args... aArgs);
// Resolves an async attribute via a background task.
template <typename T>
nsresult AsyncPromiseAttributeGetter(JSContext* aCx, Promise** aResultPromise,
AsyncAttribute,
AsyncAttributeBackgroundTask<T>);
template <typename T, typename... Args>
nsresult AsyncPromiseAttributeGetter(JSContext*, Promise**, AsyncAttribute,
BackgroundTask<T, Args...>,
Args... aArgs);
protected:
nsPrinterBase();
@@ -64,6 +72,7 @@ class nsPrinterBase : public nsIPrinter {
virtual bool SupportsDuplex() const = 0;
virtual bool SupportsColor() const = 0;
virtual nsTArray<mozilla::PaperInfo> PaperList() const = 0;
virtual MarginDouble GetMarginsForPaper(uint64_t aPaperId) const = 0;
private:
mozilla::EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,

View File

@@ -7,6 +7,8 @@
#include "nsPaper.h"
#include "nsPrinterBase.h"
using namespace mozilla;
nsPrinterCUPS::nsPrinterCUPS(const nsCUPSShim& aShim, cups_dest_t* aPrinter)
: mShim(aShim) {
MOZ_ASSERT(aPrinter);
@@ -51,7 +53,7 @@ bool nsPrinterCUPS::Supports(const char* option, const char* value) const {
mPrinterInfo, option, value);
}
nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
if (!mPrinterInfo) {
return {};
}
@@ -72,7 +74,7 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
return {};
}
nsTArray<mozilla::PaperInfo> paperList;
nsTArray<PaperInfo> paperList;
for (int i = 0; i < paperCount; ++i) {
cups_size_t info;
int getInfoSucceded = mShim.mCupsGetDestMediaByIndex(
@@ -96,14 +98,14 @@ nsTArray<mozilla::PaperInfo> nsPrinterCUPS::PaperList() const {
NS_ConvertUTF8toUTF16 name(localizedName);
const double kPointsPerHundredthMillimeter = 0.0283465;
paperList.AppendElement(mozilla::PaperInfo{
paperList.AppendElement(PaperInfo{
std::move(name),
info.width * kPointsPerHundredthMillimeter,
info.length * kPointsPerHundredthMillimeter,
info.top * kPointsPerHundredthMillimeter,
info.right * kPointsPerHundredthMillimeter,
info.bottom * kPointsPerHundredthMillimeter,
info.left * kPointsPerHundredthMillimeter,
{info.width * kPointsPerHundredthMillimeter,
info.length * kPointsPerHundredthMillimeter},
Some(MarginDouble{info.top * kPointsPerHundredthMillimeter,
info.right * kPointsPerHundredthMillimeter,
info.bottom * kPointsPerHundredthMillimeter,
info.left * kPointsPerHundredthMillimeter}),
});
}

View File

@@ -19,6 +19,12 @@ class nsPrinterCUPS final : public nsPrinterBase {
bool SupportsDuplex() const final;
bool SupportsColor() const final;
nsTArray<mozilla::PaperInfo> PaperList() const final;
MarginDouble GetMarginsForPaper(uint64_t) const final {
MOZ_ASSERT_UNREACHABLE(
"The CUPS API requires us to always get the margin when fetching the "
"paper list so there should be no need to query it separately");
return {};
}
nsPrinterCUPS() = delete;

View File

@@ -96,7 +96,6 @@ nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
return {};
}
static const wchar_t kDriverName[] = L"WINSPOOL";
nsTArray<mozilla::PaperInfo> paperList;
paperList.SetCapacity(paperNames.Length());
for (size_t i = 0; i < paperNames.Length(); ++i) {
@@ -112,34 +111,38 @@ nsTArray<mozilla::PaperInfo> nsPrinterWin::PaperList() const {
continue;
}
WORD id = paperIds[i];
// Now get the margin info.
// We need a DEVMODE to set the paper size on the context.
DEVMODEW devmode = {};
devmode.dmSize = sizeof(DEVMODEW);
devmode.dmFields = DM_PAPERSIZE;
devmode.dmPaperSize = id;
// Create an information context, so that we can get margin information.
// Note: this blocking call interacts with the driver and can be slow.
nsAutoHDC printerDc(
::CreateICW(kDriverName, mName.get(), nullptr, &devmode));
auto marginInInches =
WinUtils::GetUnwriteableMarginsForDeviceInInches(printerDc);
// We don't resolve the margins eagerly because they're really expensive (on
// the order of seconds for some drivers).
nsDependentSubstring name(paperNames[i].cbegin(), nameLength);
paperList.AppendElement(mozilla::PaperInfo{
nsString(name),
width,
height,
marginInInches.top * POINTS_PER_INCH_FLOAT,
marginInInches.right * POINTS_PER_INCH_FLOAT,
marginInInches.bottom * POINTS_PER_INCH_FLOAT,
marginInInches.left * POINTS_PER_INCH_FLOAT,
{width, height},
Nothing(),
paperIds[i],
});
}
return paperList;
}
mozilla::gfx::MarginDouble nsPrinterWin::GetMarginsForPaper(
uint64_t aPaperId) const {
static const wchar_t kDriverName[] = L"WINSPOOL";
// Now get the margin info.
// We need a DEVMODE to set the paper size on the context.
DEVMODEW devmode = {};
devmode.dmSize = sizeof(DEVMODEW);
devmode.dmFields = DM_PAPERSIZE;
devmode.dmPaperSize = aPaperId;
// Create an information context, so that we can get margin information.
// Note: this blocking call interacts with the driver and can be slow.
nsAutoHDC printerDc(::CreateICW(kDriverName, mName.get(), nullptr, &devmode));
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;
return margin;
}

View File

@@ -15,6 +15,7 @@ class nsPrinterWin final : public nsPrinterBase {
bool SupportsDuplex() const final;
bool SupportsColor() const final;
nsTArray<mozilla::PaperInfo> PaperList() const final;
MarginDouble GetMarginsForPaper(uint64_t aId) const final;
nsPrinterWin() = delete;
static already_AddRefed<nsPrinterWin> Create(const nsAString& aName);