/* -*- Mode: C++; tab-width: 2; 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/. */
staticbool PaperSizeAlmostEquals(GtkPaperSize* aSize,
GtkPaperSize* aOtherSize) { constdouble kEpsilon = 1.0; // millimetres // GTK stores sizes internally in millimetres so just use that. if (fabs(gtk_paper_size_get_height(aSize, GTK_UNIT_MM) -
gtk_paper_size_get_height(aOtherSize, GTK_UNIT_MM)) > kEpsilon) { returnfalse;
} if (fabs(gtk_paper_size_get_width(aSize, GTK_UNIT_MM) -
gtk_paper_size_get_width(aOtherSize, GTK_UNIT_MM)) > kEpsilon) { returnfalse;
} returntrue;
}
// 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 { constchar* mCups; constchar* 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 (constauto& 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. // // 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); if (auto ppd = PpdSizeFromIppName(geckoName)) { return ppd;
}
// 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 (gtk_paper_size_is_equal(size.get(), aGeckoPaperSize) ||
PaperSizeAlmostEquals(aGeckoPaperSize, size.get())) { return size;
}
// Not the same after all, so use our custom paper sizes instead. return nullptr;
}
/** ------------------------------------------------------- * Initialize the nsDeviceContextSpecGTK * @update dc 2/15/98 * @update syd 3/2/99
*/
NS_IMETHODIMP nsDeviceContextSpecGTK::Init(nsIPrintSettings* aPS, bool aIsPrintPreview) {
RefPtr<nsPrintSettingsGTK> settings = do_QueryObject(aPS); if (!settings) { return NS_ERROR_NO_INTERFACE;
}
mPrintSettings = aPS;
if (spec->mHasEnumerationFoundAMatch) { // We're already done, but we're letting the enumeration run its course, // to avoid a GTK bug. returnFALSE;
}
// Find the printer whose name matches the one inside the settings.
nsString printerName;
nsresult rv = spec->mPrintSettings->GetPrinterName(printerName); if (NS_SUCCEEDED(rv) && !printerName.IsVoid()) {
NS_ConvertUTF16toUTF8 requestedName(printerName); constchar* currentName = gtk_printer_get_name(aPrinter); if (requestedName.Equals(currentName)) {
nsPrintSettingsGTK::From(spec->mPrintSettings)->SetGtkPrinter(aPrinter);
// Bug 1145916 - attempting to kick off a print job for this printer // during this tick of the event loop will result in the printer backend // misunderstanding what the capabilities of the printer are due to a // GTK bug (https://bugzilla.gnome.org/show_bug.cgi?id=753041). We // sidestep this by deferring the print to the next tick.
NS_DispatchToCurrentThread(
NewRunnableMethod("nsDeviceContextSpecGTK::StartPrintJob", spec,
&nsDeviceContextSpecGTK::StartPrintJob));
// We're already done, but we need to let the enumeration run its course, // to avoid a GTK bug. So we record that we've found a match and // then return FALSE. // TODO: If/when we can be sure that GTK handles this OK, we could // return TRUE to avoid some needless enumeration.
spec->mHasEnumerationFoundAMatch = true; returnFALSE;
}
}
// We haven't found it yet - keep searching... returnFALSE;
}
if (!gtk_print_job_set_source_file(job, mSpoolName.get(), nullptr)) return;
// Now gtk owns the print job, and will be released via our callback.
gtk_print_job_send(job, print_callback, mSpoolFile.forget().take(),
[](gpointer aData) { auto* spoolFile = static_cast<nsIFile*>(aData);
NS_RELEASE(spoolFile);
});
}
NS_IMETHODIMP
nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage) { // Print job names exceeding 255 bytes are safe with GTK version 3.18.2 or // newer. This is a workaround for old GTK. if (gtk_check_version(3, 18, 2) != nullptr) {
PrintTarget::AdjustPrintJobNameForIPP(aTitle, mTitle);
} else {
CopyUTF16toUTF8(aTitle, mTitle);
}
return NS_OK;
}
RefPtr<PrintEndDocumentPromise> nsDeviceContextSpecGTK::EndDocument() { switch (mPrintSettings->GetOutputDestination()) { case nsIPrintSettings::kOutputDestinationPrinter: { // At this point, we might have a GtkPrinter set up in nsPrintSettingsGTK, // or we might not. In the single-process case, we probably will, as this // is populated by the print settings dialog, or set to the default // printer. // In the multi-process case, we proxy the print settings dialog over to // the parent process, and only get the name of the printer back on the // content process side. In that case, we need to enumerate the printers // on the content side, and find a printer with a matching name.
if (nsPrintSettingsGTK::From(mPrintSettings)->GetGtkPrinter()) { // We have a printer, so we can print right away.
StartPrintJob();
} else { // We don't have a printer. We have to enumerate the printers and find // one with a matching name.
NS_DispatchToCurrentThread(
NewRunnableMethod("nsDeviceContextSpecGTK::EnumeratePrinters", this,
&nsDeviceContextSpecGTK::EnumeratePrinters));
} break;
} case nsIPrintSettings::kOutputDestinationFile: { // Handle print-to-file ourselves for the benefit of embedders
nsString targetPath;
nsCOMPtr<nsIFile> destFile;
mPrintSettings->GetToFileName(targetPath);
// This is the standard way to get the UNIX umask. Ugh.
mode_t mask = umask(0);
umask(mask); // If you're not familiar with umasks, they contain the bits of what // NOT to set in the permissions (thats because files and // directories have different numbers of bits for their permissions)
destFile->SetPermissions(0666 & ~(mask)); return NS_OK;
});
break;
} case nsIPrintSettings::kOutputDestinationStream: // Nothing to do, handled in MakePrintTarget.
MOZ_ASSERT(!mSpoolFile); break;
} return PrintEndDocumentPromise::CreateAndResolve(true, __func__);
}
¤ Dauer der Verarbeitung: 0.16 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.