зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1717292 - Prefer ppd to ipp to custom names in GTK code. r=AlaskanEmily
Try to find a PPD paper size from our IPP paper size to workaround print driver bugs. Before: Apr 25 18:43:47 ryzen cupsd[850753]: cupsdProcessIPPRequest: media keyword 'iso_a4_210x297mm' After: Apr 25 19:22:54 ryzen cupsd[850753]: cupsdProcessIPPRequest: PageSize nameWithoutLanguage 'A4' Differential Revision: https://phabricator.services.mozilla.com/D144606
This commit is contained in:
Родитель
9788952c5a
Коммит
b1878d8eee
|
@ -9,6 +9,7 @@
|
|||
// Provides GUniquePtr to g_free a given pointer.
|
||||
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "mozilla/UniquePtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -17,6 +18,7 @@ struct GFreeDeleter {
|
|||
constexpr GFreeDeleter() = default;
|
||||
void operator()(GError* aPtr) const { g_error_free(aPtr); }
|
||||
void operator()(void* aPtr) const { g_free(aPtr); }
|
||||
void operator()(GtkPaperSize* aPtr) const { gtk_paper_size_free(aPtr); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "mozilla/gfx/PrintTargetPDF.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/GUniquePtr.h"
|
||||
#include "mozilla/WidgetUtilsGtk.h"
|
||||
|
||||
#include "plstr.h"
|
||||
|
@ -124,14 +125,15 @@ struct {
|
|||
#undef DECLARE_KNOWN_MONOCHROME_SETTING
|
||||
|
||||
// https://developer.gnome.org/gtk3/stable/GtkPaperSize.html#gtk-paper-size-new-from-ipp
|
||||
static GtkPaperSize* GtkPaperSizeFromIpp(const gchar* aIppName, gdouble aWidth,
|
||||
gdouble aHeight) {
|
||||
static GUniquePtr<GtkPaperSize> GtkPaperSizeFromIpp(const gchar* aIppName,
|
||||
gdouble aWidth,
|
||||
gdouble aHeight) {
|
||||
static auto sPtr = (GtkPaperSize * (*)(const gchar*, gdouble, gdouble))
|
||||
dlsym(RTLD_DEFAULT, "gtk_paper_size_new_from_ipp");
|
||||
if (gtk_check_version(3, 16, 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
return sPtr(aIppName, aWidth, aHeight);
|
||||
return GUniquePtr<GtkPaperSize>(sPtr(aIppName, aWidth, aHeight));
|
||||
}
|
||||
|
||||
static bool PaperSizeAlmostEquals(GtkPaperSize* aSize,
|
||||
|
@ -149,43 +151,70 @@ static bool PaperSizeAlmostEquals(GtkPaperSize* aSize,
|
|||
return true;
|
||||
}
|
||||
|
||||
// This is a horrible workaround for some printer driver bugs that treat
|
||||
// custom page sizes different to standard ones. If our paper object matches
|
||||
// one of a standard one, use a standard paper size object instead.
|
||||
// Prefer the ppd name because some printers don't deal well even with standard
|
||||
// ipp names.
|
||||
static GUniquePtr<GtkPaperSize> PpdSizeFromIppName(const gchar* aIppName) {
|
||||
static constexpr struct {
|
||||
const char* mCups;
|
||||
const char* mGtk;
|
||||
} kMap[] = {
|
||||
{CUPS_MEDIA_A3, GTK_PAPER_NAME_A3},
|
||||
{CUPS_MEDIA_A4, GTK_PAPER_NAME_A4},
|
||||
{CUPS_MEDIA_A5, GTK_PAPER_NAME_A5},
|
||||
{CUPS_MEDIA_LETTER, GTK_PAPER_NAME_LETTER},
|
||||
{CUPS_MEDIA_LEGAL, GTK_PAPER_NAME_LEGAL},
|
||||
// Other gtk sizes with no standard CUPS constant: _EXECUTIVE and _B5
|
||||
};
|
||||
|
||||
for (const auto& entry : kMap) {
|
||||
if (!strcmp(entry.mCups, aIppName)) {
|
||||
return GUniquePtr<GtkPaperSize>(gtk_paper_size_new(entry.mGtk));
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is a horrible workaround for some printer driver bugs that treat custom
|
||||
// page sizes different to standard ones. If our paper object matches one of a
|
||||
// standard one, use a standard paper size object instead.
|
||||
//
|
||||
// See bug 414314 and bug 1691798 for more info.
|
||||
static GtkPaperSize* GetStandardGtkPaperSize(GtkPaperSize* aGeckoPaperSize) {
|
||||
// We prefer ppd to ipp to custom sizes.
|
||||
//
|
||||
// See bug 414314, bug 1691798, and bug 1717292 for more info.
|
||||
static GUniquePtr<GtkPaperSize> GetStandardGtkPaperSize(
|
||||
GtkPaperSize* aGeckoPaperSize) {
|
||||
// We should get an ipp name from cups, try to get a ppd from that first.
|
||||
const gchar* geckoName = gtk_paper_size_get_name(aGeckoPaperSize);
|
||||
|
||||
// We try ipp size first because that's the names we get from CUPS, and
|
||||
// because even though gtk_paper_size_new deals with ipp, it has rounding
|
||||
// issues, see https://gitlab.gnome.org/GNOME/gtk/-/issues/3685.
|
||||
GtkPaperSize* size = GtkPaperSizeFromIpp(
|
||||
geckoName, gtk_paper_size_get_width(aGeckoPaperSize, GTK_UNIT_POINTS),
|
||||
gtk_paper_size_get_height(aGeckoPaperSize, GTK_UNIT_POINTS));
|
||||
if (size && !gtk_paper_size_is_custom(size)) {
|
||||
return size;
|
||||
if (auto ppd = PpdSizeFromIppName(geckoName)) {
|
||||
return ppd;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
gtk_paper_size_free(size);
|
||||
}
|
||||
|
||||
size = gtk_paper_size_new(geckoName);
|
||||
if (gtk_paper_size_is_equal(size, aGeckoPaperSize)) {
|
||||
return size;
|
||||
// We try gtk_paper_size_new_from_ipp next, because even though
|
||||
// gtk_paper_size_new tries to deal with ipp, it has some rounding issues that
|
||||
// the ipp equivalent doesn't have, see
|
||||
// https://gitlab.gnome.org/GNOME/gtk/-/issues/3685.
|
||||
if (auto ipp = GtkPaperSizeFromIpp(
|
||||
geckoName, gtk_paper_size_get_width(aGeckoPaperSize, GTK_UNIT_POINTS),
|
||||
gtk_paper_size_get_height(aGeckoPaperSize, GTK_UNIT_POINTS))) {
|
||||
if (!gtk_paper_size_is_custom(ipp.get())) {
|
||||
if (auto ppd = PpdSizeFromIppName(gtk_paper_size_get_name(ipp.get()))) {
|
||||
return ppd;
|
||||
}
|
||||
return ipp;
|
||||
}
|
||||
}
|
||||
|
||||
GUniquePtr<GtkPaperSize> size(gtk_paper_size_new(geckoName));
|
||||
// gtk_paper_size_is_equal compares just paper names. The name in Gecko
|
||||
// might come from CUPS, which is an ipp size, and gets normalized by gtk.
|
||||
//
|
||||
// So check also for the same actual paper size.
|
||||
if (PaperSizeAlmostEquals(aGeckoPaperSize, size)) {
|
||||
if (gtk_paper_size_is_equal(size.get(), aGeckoPaperSize) ||
|
||||
PaperSizeAlmostEquals(aGeckoPaperSize, size.get())) {
|
||||
return size;
|
||||
}
|
||||
|
||||
// Not the same after all, so use our custom paper size.
|
||||
gtk_paper_size_free(size);
|
||||
// Not the same after all, so use our custom paper sizes instead.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -206,7 +235,8 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget* aWidget,
|
|||
mGtkPageSetup = mPrintSettings->GetGtkPageSetup();
|
||||
|
||||
GtkPaperSize* geckoPaperSize = gtk_page_setup_get_paper_size(mGtkPageSetup);
|
||||
GtkPaperSize* gtkPaperSize = GetStandardGtkPaperSize(geckoPaperSize);
|
||||
GUniquePtr<GtkPaperSize> gtkPaperSize =
|
||||
GetStandardGtkPaperSize(geckoPaperSize);
|
||||
|
||||
mGtkPageSetup = gtk_page_setup_copy(mGtkPageSetup);
|
||||
mGtkPrintSettings = gtk_print_settings_copy(mGtkPrintSettings);
|
||||
|
@ -225,14 +255,11 @@ NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIWidget* aWidget,
|
|||
nsPrinterCUPS::ForEachExtraMonochromeSetting(applySetting);
|
||||
}
|
||||
|
||||
GtkPaperSize* properPaperSize = gtkPaperSize ? gtkPaperSize : geckoPaperSize;
|
||||
GtkPaperSize* properPaperSize =
|
||||
gtkPaperSize ? gtkPaperSize.get() : geckoPaperSize;
|
||||
gtk_print_settings_set_paper_size(mGtkPrintSettings, properPaperSize);
|
||||
gtk_page_setup_set_paper_size_and_default_margins(mGtkPageSetup,
|
||||
properPaperSize);
|
||||
if (gtkPaperSize) {
|
||||
gtk_paper_size_free(gtkPaperSize);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче