mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-11 15:22:08 +00:00
print: xps_driver says whether a Windows printer's driver renders XPS itself (#804)
* print: xps_driver says whether a Windows printer's driver renders XPS itself craft_print::xps_driver(printer) reads PRINTER_DRIVER_XPS through winprint's new PrinterDevice::is_xps_driver (storytold/winprint.rs#21): Some(true) for v4 drivers and v3 drivers with an XPS rendering filter, Some(false) for GDI drivers, None when it can't be read and on other systems. On a GDI driver, reached through Windows' XPS-to-GDI conversion, a page with transparency prints with halos, as black boxes or not at all (storytold/pdfcraft#6155, #5838, #5940), so PdfCraft will flatten it for those drivers only. The Windows end-to-end test checks the CI queue's "Generic / Text Only" driver reads as GDI. * Test: the GDI-driver check in a helper (keeps the end-to-end test under the complexity limit) * winprint bc06a7c48b768eb27a828c7986f6d2868b245ee0: storytold/winprint.rs main with #21 (PrinterDevice::is_xps_driver)
This commit is contained in:
Generated
+1
-1
@@ -7142,7 +7142,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "winprint"
|
||||
version = "0.2.1"
|
||||
source = "git+https://github.com/storytold/winprint.rs?rev=3c978dfcf3d460577fabd87aeea7a84ffdcfb396#3c978dfcf3d460577fabd87aeea7a84ffdcfb396"
|
||||
source = "git+https://github.com/storytold/winprint.rs?rev=bc06a7c48b768eb27a828c7986f6d2868b245ee0#bc06a7c48b768eb27a828c7986f6d2868b245ee0"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"fmt-derive",
|
||||
|
||||
@@ -35,7 +35,7 @@ log = "0.4"
|
||||
# ticket (winprint.rs#12, storytold/pdfcraft#3823), and reads whitespace-padded integers in
|
||||
# PrintCapabilities (winprint.rs#3, storytold/pdfcraft#2430). Pinned to an immutable revision;
|
||||
# review before bumping.
|
||||
winprint = { git = "https://github.com/storytold/winprint.rs", rev = "3c978dfcf3d460577fabd87aeea7a84ffdcfb396", default-features = false }
|
||||
winprint = { git = "https://github.com/storytold/winprint.rs", rev = "bc06a7c48b768eb27a828c7986f6d2868b245ee0", default-features = false }
|
||||
# GetDefaultPrinter (MIT).
|
||||
winsafe = { version = "0.0.29", default-features = false, features = ["winspool"] }
|
||||
# The job file's private folder.
|
||||
|
||||
@@ -653,6 +653,23 @@ pub fn two_sided(printer: &str) -> Option<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether `printer`'s driver renders XPS itself: on Windows, `Some(true)` for v4 drivers and v3
|
||||
/// drivers with an XPS rendering filter, `Some(false)` for GDI drivers, which the XPS print API
|
||||
/// reaches through Windows' XPS-to-GDI conversion. A page with transparency can come out wrong or
|
||||
/// fail to print there (storytold/pdfcraft#6155, #5838, #5940), so an app may flatten it first.
|
||||
/// `None` when it can't be read or no queue has that name, and on other systems.
|
||||
pub fn xps_driver(printer: &str) -> Option<bool> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
windows::xps_driver_named(printer)
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
let _ = printer;
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// The Print dialog's printers from lpstat's two answers: the spooler's queues (`-p -d`), then
|
||||
/// the driverless destinations of `available` (`-e`) that have no queue — CUPS builds a temporary
|
||||
/// queue when `lp` sends them a job. Each destination once, queues first; the default still comes
|
||||
|
||||
@@ -454,6 +454,14 @@ fn windows_powershell(script: &str, printer: &str) -> Result<String, String> {
|
||||
/// them; the test uses PowerShell only to add, inspect and remove the printer. Its driver is the
|
||||
/// inbox "Generic / Text Only"; a machine that cannot add one (no rights, no driver) skips the
|
||||
/// test, unless `CRAFT_PRINT_REQUIRE_QUEUE=1` (CI) makes it mandatory.
|
||||
/// "Generic / Text Only" is a GDI (v3) driver: the XPS print API reaches it through Windows'
|
||||
/// XPS-to-GDI conversion, where an app may flatten transparency first (storytold/pdfcraft#6155).
|
||||
#[cfg(windows)]
|
||||
fn assert_gdi_driver(name: &str) {
|
||||
assert_eq!(spool::xps_driver(name), Some(false), "the test queue's driver is a GDI driver");
|
||||
assert_eq!(spool::xps_driver("Craft Test Print: no such queue"), None);
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn windows_jobs_reach_the_spooler() {
|
||||
@@ -474,6 +482,7 @@ fn windows_jobs_reach_the_spooler() {
|
||||
return;
|
||||
}
|
||||
let (listed, probed) = driver_queries(|| spool::printers().into_iter().find(|p| p.name == name));
|
||||
assert_gdi_driver(name);
|
||||
// The list a Print dialog shows first: the same queue, named without asking its driver (a
|
||||
// networked printer in power save can hold that query, storytold/wordcraft#5710).
|
||||
let (queue, unprobed) = driver_queries(|| spool::printer_queues().into_iter().find(|p| p.name == name));
|
||||
|
||||
@@ -68,6 +68,12 @@ pub(crate) fn two_sided_named(name: &str) -> Option<bool> {
|
||||
PrinterDevice::all().ok()?.iter().find(|d| d.name() == name).and_then(two_sided)
|
||||
}
|
||||
|
||||
/// Whether the driver of the queue `name` renders XPS itself (`PRINTER_DRIVER_XPS`); `None`
|
||||
/// when no queue has that name or its driver can't be read.
|
||||
pub(crate) fn xps_driver_named(name: &str) -> Option<bool> {
|
||||
PrinterDevice::all().ok()?.iter().find(|d| d.name() == name)?.is_xps_driver().ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
thread_local! {
|
||||
/// The driver capability queries printer discovery made on this thread, so a test can show
|
||||
|
||||
Reference in New Issue
Block a user