* 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)
winprint.rs#19 draws each page at the resolution the job's ticket asks for instead of ~96 dpi
(storytold/pdfcraft#4941, #2676). #12 writes QName property values as prefix:local, which
drivers such as the Microsoft IPP Class Driver otherwise reject when merging the ticket
(storytold/pdfcraft#3823). #3 accepts whitespace around xsd:integer values in
PrintCapabilities (Toshiba Universal Printer 2, storytold/pdfcraft#2430).
The public API craft-print uses is unchanged; only the rev and the lockfile move.
Windows.Data.Pdf draws a page on several of its own worker threads, which
share the print control's device context. With winprint 5f80b9b's
single-threaded factory Direct2D takes no locks, so those threads race in
d2d1.dll and the app closes while printing, most often on pages with Type 3
fonts (storytold/pdfcraft#5006, storytold/pdfcraft#2684).
storytold/winprint.rs#11 made the factory multi-threaded; it was merged as
64e7afd4.
craft-winprint-gdi moves to the same revision, so one checkout of
winprint.rs serves both; crates/gdi is unchanged between 417ac3c and
64e7afd4.
Co-authored-by: mertan-wq <235487900+mertan-wq@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Windows.Data.Pdf draws a page on several of its own worker threads, which
share the print control's device context. With winprint 5f80b9b's
single-threaded factory Direct2D takes no locks, so those threads race in
d2d1.dll and the app closes while printing, most often on pages with Type 3
fonts (storytold/pdfcraft#5006, storytold/pdfcraft#2684).
storytold/winprint.rs#11 made the factory multi-threaded; it was merged as
64e7afd4.
craft-winprint-gdi moves to the same revision, so one checkout of
winprint.rs serves both; crates/gdi is unchanged between 417ac3c and
64e7afd4.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* craft-print: log why the printer list is empty when lpstat can't run; document Flatpak needs
Flatpak apps saw "No printers found" with working CUPS printers: the Freedesktop
runtime has libcups but not lpstat/lp, and the sandbox had neither the CUPS socket
nor Avahi (driverless printers come from lpstat -e). Log the spawn failure and say
in the README what a Flatpak must bundle and grant.
* craft-print: log a failed lpstat -p -d; README separates what each Flatpak piece is for
Review (CodeRabbit): a non-zero lpstat exit was dropped silently, and the README
said any missing piece empties the printer list when only lpstat and the socket do.
* craft-print README: driver options need the PPD, remote servers need network, socket paths are remapped
Review (CodeRabbit): printer_options reads /etc/cups/ppd before lpoptions, so it is
the PPD, not lpoptions, that a Flatpak lacks; a client.conf server is reached only
with --share=network.
* craft-print README: scope the CUPS_SERVER override to one app; describe the stricter socket wrapper
Review (CodeRabbit): flatpak override without an app id applies to every app.
craft-print's Windows backend ran an embedded PowerShell script for the printer list and every
job. Under App Control for Business or AppLocker script enforcement that script runs in
Constrained Language Mode and every job fails (storytold/pdfcraft#1107). The backend now runs
in this process and starts no program:
- Printers come from EnumPrinters and the default from GetDefaultPrinter; Printer::two_sided
from each driver's PrintCapabilities. The list is sorted, each name once.
- A job is drawn as vectors by the in-box Windows.Data.Pdf with Direct2D into the XPS print
API (winprint). Copies, collation, duplex (left out for duplex: None), colour, orientation
and the driver's own paper option go in a PrintTicket the driver validates; a ticket the
driver changed (paper, orientation, scaling) is refused before anything is sent. The driver
paper named like the standard size is preferred (pdfcraft#599).
- A job has one ticket, so one paper shape. A small lenient reader (sheets.rs) reads the
print-ready PDF's sheets and, when needed, appends an incremental update: /Rotate for sheets
of the other orientation, and for Scaling::ShrinkToFit a reframe onto the driver's matching
or default paper (shrunk inside its widest hardware margin, never enlarged, centred).
Exact size refuses mixed paper sizes and paper the driver lacks.
- command_preview describes the in-process job on Windows ("xps-print", key=value options).
- windows_print.ps1 and the PowerShell helpers are gone. open_printer_preferences (rundll32)
and the CUPS path are unchanged, as is the public API.
The end-to-end test puts a paused Generic / Text Only printer on LPT1: (no port to remove
afterwards; a paused FILE: queue never takes the job) and checks a mixed-orientation exact job
and a shrink-to-fit job each land as one job with all sheets. The reader is tested on every
platform with classic and compressed cross-references and thousands of truncated and corrupted
files. Windows-only dependencies: winprint =0.2.1 (default features off), winsafe 0.0.29,
roxmltree 0.20, miniz_oxide 0.8.
Ported from PdfCraft's native printing branch (pdfcraft#1132), which carries #599's approach.
Co-authored-by: durtyrobbin <76844303+durtyrobbin@users.noreply.github.com>
Co-authored-by: Dimitar Klaturov <7221384+bulgariamitko@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>