Files
craft-libs/crates/print/Cargo.toml
T
.CooCoo cb9d29c913 print: a Windows driver's own settings dialog for one job
* print: driver_settings_dialog sets a Windows driver's own options for one job

A Windows print job could take a driver's own options, such as media type
and print quality, only from the printer's saved Printing Preferences
(open_printer_preferences), so choosing them for one job changed the
printer's defaults for every later job.

driver_settings_dialog(&mut job, parent) shows the driver's dialog
(DocumentProperties) for the job's printer. It opens on the job's earlier
choices for that printer, without the ones the job decides, when the
driver still reads them, else on the settings the driver gives a new job,
with the job's copies and collation. OK stores the settings in the new
Job::driver_settings. Cancel leaves the job as it was, and so do settings
the dialog returns exactly as it opened on them, since some drivers
return OK from Cancel with the settings they were given. craft-print does
not save the settings as the printer's defaults.

When the job prints, Windows converts the settings to a PrintTicket
(PrintTicket::from_dev_mode). craft-print removes the features the job's
own ticket decides: copies, collation, paper, orientation and scaling,
pages per sheet, binding and posters, two-sided when the job sets it, and
color when it asks for grayscale. It then merges the job's ticket after
the rest. The driver's private settings are kept, so a driver that also
keeps pages per sheet there can still apply it. The existing paper,
orientation and option checks run on the ticket the driver validates.
Settings are used only on the printer whose name they were chosen for,
and command_preview marks them as not used when the job, or the default
printer, is another one. Other platforms return an error, and CUPS jobs
ignore the settings.

winprint is pinned to dotCooCoo/winprint.rs 72951d7, which adds
from_dev_mode on top of storytold/winprint.rs main, until that change is
merged there. examples/driver_settings_dialog.rs opens the dialog and
prints a test sheet.

* print: the hand-run driver test accepts zeroed settings read as defaults

the_driver_dialogs_settings_leave_the_jobs_own_options expected every
driver to refuse a DEVMODE of zeros. Two drivers read it as the settings
they give a new job instead. The test now accepts either outcome: settings
the driver refuses are replaced by the dialog, settings it reads are kept,
and either way the dialog opens as if the job had no settings. The README
says such settings stay on the job after Cancel and print as the driver's
defaults.

* print: the README and hand-run test describe settings with no fields set

The hand-run Windows test compares the seed's replaces_unreadable with
whether the driver refused the settings, in place of a branch whose
check always passed, and describes its input as a DEVMODE with only its
size set. The README says such settings stay on the job after Cancel
and after OK with nothing changed, links the DEVMODE dmFields
description, and no longer says how the job prints with them.

* print: refuse a job whose driver replaced the dialog's media type, resolution or quality

A driver that validates the job's ticket can replace a media type, resolution or
print quality chosen in its dialog when it conflicts with the job's paper, and
Windows reports that as a success. The validated ticket is now compared with the
dialog's settings, by option name and scored values, and the job is refused when
one of them changed.

The Windows preview lists two-sided printing and color that the job leaves open as
"driver settings or queue default" and "driver settings or driver default": it
matches the settings to the printer by name and does not ask the driver to read them.

* print: the driver dialog opens without earlier settings the driver reads but refuses to merge

Earlier settings that a driver still converts to a ticket but then refuses to merge, or to convert back to its DEVMODE, are left out, as unreadable ones already are, so the dialog opens and can replace them.

---------

Co-authored-by: dotCooCoo <RobertLeeLW@gmail.com>
2026-11-12 10:05:25 -05:00

54 lines
2.8 KiB
TOML

[package]
name = "craft-print"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
rust-version.workspace = true
description = "System PDF print spooler for the Craft apps: CUPS and Windows"
[dependencies]
# Safe API; Win32 calls are isolated in this maintained MIT OR Apache-2.0 dependency.
# Keep the public rgb re-export at main's GDI revision: a different Git rev gives
# downstream GDI values a different Rust type identity even when the code is unchanged.
# PDF loader updates below are independent of this public transport API.
craft-winprint-gdi = { git = "https://github.com/storytold/winprint.rs", rev = "64e7afd4d1483512385012c340ecaaaf0f3beb7f" }
[lints]
workspace = true
[target.'cfg(unix)'.dependencies]
# Says why the printer list is empty when lpstat can't run (e.g. a Flatpak without CUPS tools).
log = "0.4"
[target.'cfg(windows)'.dependencies]
# Printing without starting anything (storytold/pdfcraft#1107): the printer list (EnumPrinters)
# and the job (Windows.Data.Pdf drawn with Direct2D into the XPS print API, options as a
# PrintTicket) are safe wrappers over Win32 and WinRT (BSD-3-Clause). Its default `pdfium`
# feature downloads PDFium at build time and is off. The maintained BSD-3-Clause fork
# preserves terminal failures/cancellation and bounds the completion notification wait, and
# creates the Direct2D factory multi-threaded, since Windows.Data.Pdf draws on its own worker
# threads (storytold/pdfcraft#5006). File-backed PDF loading avoids StorageFile access
# denial without whole-job buffering; includes the #15 test cleanup and explicit WinRT
# feature. It draws each page at the job's resolution rather than ~96 dpi (winprint.rs#19,
# storytold/pdfcraft#4941), writes QName values as prefix:local so drivers accept the merged
# 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. The settings chosen in a driver's own dialog become a ticket through
# `PrintTicket::from_dev_mode`: until it is merged into storytold/winprint.rs, the pin is the
# fork commit that adds it on top of storytold/winprint.rs main (e90c444).
winprint = { git = "https://github.com/dotCooCoo/winprint.rs", rev = "72951d7455ebcab569fbd9386c513d3d9f53fb02", default-features = false }
# GetDefaultPrinter (MIT).
winsafe = { version = "0.0.29", default-features = false, features = ["winspool"] }
# The job file's private folder.
tempfile = "3"
# Reading the PrintTicket and PrintCapabilities the driver hands back.
roxmltree = "0.21"
# Inflating the print-ready PDF's cross-reference and object streams (src/sheets.rs).
miniz_oxide = "0.9"
[dev-dependencies]
tempfile = "3"
roxmltree = "0.21"
miniz_oxide = "0.9"