Bug 1667486 part 2 - Use our own localization for nsPrinterCUPS paper sizes when possible r=emilio

This should be able to avoid creating a printer-specific HTTP connection in
nsPrinterCUPS::DefaultSettings when the paper size is a PWG-recognized size.

The current maximum error when comparing paper sizes is 4 points. This may need
to be revised later.

Differential Revision: https://phabricator.services.mozilla.com/D91497
This commit is contained in:
Emily McDonough 2020-10-13 21:52:04 +00:00
Родитель 8202fe3024
Коммит 31f2236856
9 изменённых файлов: 93 добавлений и 24 удалений

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

@ -15,6 +15,14 @@ using namespace mozilla;
using mozilla::dom::Promise;
using mozilla::gfx::MarginDouble;
// The maximum error when considering a paper size equal, in points.
// There is some variance in the actual sizes returned by printer drivers and
// print servers for paper sizes. This is a best-guess based on initial
// telemetry which should catch most near-miss dimensions. This should let us
// get consistent paper size names even when the size isn't quite exactly the
// correct size.
static constexpr double kPaperSizePointsEpsilon = 4.0;
void nsPrinterBase::CachePrintSettingsInitializer(
const PrintSettingsInitializer& aInitializer) {
if (mPrintSettingsInitializer.isNothing()) {
@ -166,5 +174,20 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPrinterBase)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPrinterBase)
nsPrinterBase::nsPrinterBase() = default;
nsPrinterBase::nsPrinterBase(const CommonPaperInfoArray* aPaperInfoArray)
: mCommonPaperInfo(aPaperInfoArray) {
MOZ_DIAGNOSTIC_ASSERT(aPaperInfoArray, "Localized paper info was null");
}
nsPrinterBase::~nsPrinterBase() = default;
const PaperInfo* nsPrinterBase::FindCommonPaperSize(
const gfx::SizeDouble& aSize) const {
for (const PaperInfo& paper : *mCommonPaperInfo) {
if (std::abs(paper.mSize.width - aSize.width) <= kPaperSizePointsEpsilon &&
std::abs(paper.mSize.height - aSize.height) <=
kPaperSizePointsEpsilon) {
return &paper;
}
}
return nullptr;
}

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

@ -41,6 +41,9 @@ class nsPrinterBase : public nsIPrinter {
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsPrinterBase)
// We require the paper info array
nsPrinterBase() = delete;
// No copy or move, we're an identity.
nsPrinterBase(const nsPrinterBase&) = delete;
nsPrinterBase(nsPrinterBase&&) = delete;
@ -84,7 +87,7 @@ class nsPrinterBase : public nsIPrinter {
Maybe<PrintSettingsInitializer> mPrintSettingsInitializer;
protected:
nsPrinterBase();
nsPrinterBase(const mozilla::CommonPaperInfoArray* aPaperInfoArray);
virtual ~nsPrinterBase();
// Implementation-specific methods. These must not make assumptions about
@ -96,11 +99,17 @@ class nsPrinterBase : public nsIPrinter {
virtual bool SupportsCollation() const = 0;
virtual nsTArray<mozilla::PaperInfo> PaperList() const = 0;
virtual MarginDouble GetMarginsForPaper(nsString aPaperId) 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(
const mozilla::gfx::SizeDouble& aSize) const;
private:
mozilla::EnumeratedArray<AsyncAttribute, AsyncAttribute::Last,
RefPtr<Promise>>
mAsyncAttributePromises;
// List of built-in, commonly used paper sizes.
const RefPtr<const mozilla::CommonPaperInfoArray> mCommonPaperInfo;
};
#endif

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

@ -18,13 +18,14 @@ using namespace mozilla;
static constexpr Array<const char* const, 1> requestedAttributes{
"cups-version"};
static PaperInfo MakePaperInfo(const char* aName, const cups_size_t& aMedia) {
const double kPointsPerHundredthMillimeter = 72.0 / 2540.0;
// XXX Do we actually have the guarantee that these are utf-8?
static constexpr double kPointsPerHundredthMillimeter = 72.0 / 2540.0;
static PaperInfo MakePaperInfo(const nsAString& aName,
const cups_size_t& aMedia) {
// XXX Do we actually have the guarantee that this is utf-8?
NS_ConvertUTF8toUTF16 paperId(aMedia.media); // internal paper name/ID
NS_ConvertUTF8toUTF16 paperName(aName); // localized human-friendly name
return PaperInfo(
paperId, paperName,
paperId, aName,
{aMedia.width * kPointsPerHundredthMillimeter,
aMedia.length * kPointsPerHundredthMillimeter},
Some(gfx::MarginDouble{aMedia.top * kPointsPerHundredthMillimeter,
@ -123,7 +124,18 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings() const {
};
}
const char* localizedName = nullptr;
// 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,
@ -134,8 +146,11 @@ PrintSettingsInitializer nsPrinterCUPS::DefaultSettings() const {
/* 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) {
localizedName = LocalizeMediaName(*connection, media);
mShim.httpClose(connection);
}
@ -281,18 +296,28 @@ nsTArray<PaperInfo> nsPrinterCUPS::PaperList() const {
nsTArray<PaperInfo> paperList;
nsTHashtable<nsCharPtrHashKey> paperSet(std::max(paperCount, 0));
paperList.SetCapacity(paperCount);
for (int i = 0; i < paperCount; ++i) {
cups_size_t media;
int getInfoSucceeded = mShim.cupsGetDestMediaByIndex(
const int getInfoSucceeded = mShim.cupsGetDestMediaByIndex(
connection, mPrinter, printerInfo, i, CUPS_MEDIA_FLAGS_DEFAULT, &media);
if (!getInfoSucceeded || !paperSet.EnsureInserted(media.media)) {
continue;
}
const char* mediaName =
connection ? LocalizeMediaName(*connection, media) : media.media;
paperList.AppendElement(MakePaperInfo(mediaName, media));
// Check if this is a PWG 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)) {
paperList.AppendElement(MakePaperInfo(paperInfo->mName, media));
} else {
const char* const mediaName =
connection ? LocalizeMediaName(*connection, media) : media.media;
paperList.AppendElement(
MakePaperInfo(NS_ConvertUTF8toUTF16(mediaName), media));
}
}
if (connection) {

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

@ -36,9 +36,11 @@ class nsPrinterCUPS final : public nsPrinterBase {
nsPrinterCUPS() = delete;
nsPrinterCUPS(const nsCUPSShim& aShim, nsString aDisplayName,
nsPrinterCUPS(const mozilla::CommonPaperInfoArray* aArray,
const nsCUPSShim& aShim, nsString aDisplayName,
cups_dest_t* aPrinter)
: mShim(aShim),
: nsPrinterBase(aArray),
mShim(aShim),
mDisplayName(std::move(aDisplayName)),
mPrinter(aPrinter),
mPrinterInfoMutex("nsPrinterCUPS::mPrinterInfoMutex") {}

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

@ -53,6 +53,7 @@ void ResolveOrReject(dom::Promise& aPromise, nsPrinterListBase& aList,
NS_IMETHODIMP nsPrinterListBase::GetPrinters(JSContext* aCx,
Promise** aResult) {
EnsureCommonPaperInfo(aCx);
return mozilla::AsyncPromiseAttributeGetter(*this, mPrintersPromise, aCx,
aResult, "Printers"_ns,
&nsPrinterListBase::Printers);
@ -61,6 +62,7 @@ NS_IMETHODIMP nsPrinterListBase::GetPrinters(JSContext* aCx,
NS_IMETHODIMP nsPrinterListBase::GetPrinterByName(const nsAString& aPrinterName,
JSContext* aCx,
Promise** aResult) {
EnsureCommonPaperInfo(aCx);
return PrintBackgroundTaskPromise(*this, aCx, aResult, "PrinterByName"_ns,
&nsPrinterListBase::PrinterByName,
nsString{aPrinterName});
@ -68,6 +70,7 @@ NS_IMETHODIMP nsPrinterListBase::GetPrinterByName(const nsAString& aPrinterName,
NS_IMETHODIMP nsPrinterListBase::GetPrinterBySystemName(
const nsAString& aPrinterName, JSContext* aCx, Promise** aResult) {
EnsureCommonPaperInfo(aCx);
return PrintBackgroundTaskPromise(
*this, aCx, aResult, "PrinterBySystemName"_ns,
&nsPrinterListBase::PrinterBySystemName, nsString{aPrinterName});
@ -75,6 +78,7 @@ NS_IMETHODIMP nsPrinterListBase::GetPrinterBySystemName(
NS_IMETHODIMP nsPrinterListBase::GetNamedOrDefaultPrinter(
const nsAString& aPrinterName, JSContext* aCx, Promise** aResult) {
EnsureCommonPaperInfo(aCx);
return PrintBackgroundTaskPromise(
*this, aCx, aResult, "NamedOrDefaultPrinter"_ns,
&nsPrinterListBase::NamedOrDefaultPrinter, nsString{aPrinterName});

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

@ -108,7 +108,7 @@ nsTArray<PrinterInfo> nsPrinterListCUPS::Printers() const {
RefPtr<nsIPrinter> nsPrinterListCUPS::CreatePrinter(PrinterInfo aInfo) const {
return mozilla::MakeRefPtr<nsPrinterCUPS>(
sCupsShim, std::move(aInfo.mName),
mCommonPaperInfo, sCupsShim, std::move(aInfo.mName),
static_cast<cups_dest_t*>(aInfo.mCupsHandle));
}

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

@ -586,7 +586,7 @@ Maybe<nsPrinterListBase::PrinterInfo> nsPrinterListWin::PrinterBySystemName(
}
RefPtr<nsIPrinter> nsPrinterListWin::CreatePrinter(PrinterInfo aInfo) const {
return nsPrinterWin::Create(std::move(aInfo.mName));
return nsPrinterWin::Create(mCommonPaperInfo, std::move(aInfo.mName));
}
nsresult nsPrinterListWin::SystemDefaultPrinterName(nsAString& aName) const {

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

@ -22,13 +22,16 @@ using namespace mozilla::widget;
static const double kPointsPerTenthMM = 72.0 / 254.0;
static const double kPointsPerInch = 72.0;
nsPrinterWin::nsPrinterWin(const nsAString& aName)
: mName(aName),
nsPrinterWin::nsPrinterWin(const CommonPaperInfoArray* aArray,
const nsAString& aName)
: nsPrinterBase(aArray),
mName(aName),
mDefaultDevmodeWStorage("nsPrinterWin::mDefaultDevmodeWStorage") {}
// static
already_AddRefed<nsPrinterWin> nsPrinterWin::Create(const nsAString& aName) {
return do_AddRef(new nsPrinterWin(aName));
already_AddRefed<nsPrinterWin> nsPrinterWin::Create(
const CommonPaperInfoArray* aArray, const nsAString& aName) {
return do_AddRef(new nsPrinterWin(aArray, aName));
}
nsTArray<uint8_t> nsPrinterWin::CopyDefaultDevmodeW() const {

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

@ -23,10 +23,13 @@ class nsPrinterWin final : public nsPrinterBase {
MarginDouble GetMarginsForPaper(nsString aPaperId) const final;
nsPrinterWin() = delete;
static already_AddRefed<nsPrinterWin> Create(const nsAString& aName);
static already_AddRefed<nsPrinterWin> Create(
const mozilla::CommonPaperInfoArray* aPaperInfoArray,
const nsAString& aName);
private:
explicit nsPrinterWin(const nsAString& aName);
nsPrinterWin(const mozilla::CommonPaperInfoArray* aPaperInfoArray,
const nsAString& aName);
~nsPrinterWin() = default;
nsTArray<uint8_t> CopyDefaultDevmodeW() const;