9.4 KiB
pdfcraft-print
Layer L4: printing (execution plan M10.5).
let pages = select_pages(count, Some("1-3, ii, 9-"), &labels, Subset::All, false)?;
let settings = Settings { pages, paper: PAPERS[0].1, layout: Layout::multiple(4), ..Default::default() };
let sheets = layout(&display_sizes, &settings)?; // geometry only (previews)
let pdf = impose(&doc, &settings)?; // the print-ready PDF
spool::submit(&pdf, &spool::Job { printer: None, copies: 2, ..Default::default() })?;
- Size: fit (to the sheet minus an 18 pt margin), actual size, shrink oversized, custom %; centred; auto orientation turns the sheet for landscape pages.
- Multiple: 2/4/6/9/16 (or any n) pages per sheet, horizontal/vertical (reversed) order,
page borders, auto-rotation of pages that don't match the cell. With auto orientation a
predefined count turns the sheet to suit its grid (2 per sheet prints side by side on
landscape). A custom grid (
Layout::grid,doc_printcols/rows, 1-99 each) is laid out across and down the sheet as given and doesn't turn it: auto prints portrait. - Cut and stack (Multiple's page order): consecutive pages in each cell's pile,
with aligned cut marks in the gutters. For example, 10 pages at 4 per sheet give
[1, 4, 7, 10],[2, 5, 8, blank],[3, 6, 9, blank]. Print single-sided, keep sheets in output order, cut at the marks, then stack the cell piles from left to right, top to bottom. Blank cells can be discarded. Page ranges and Reverse pages are applied before imposition. Duplex imposition is not supported. Headless:doc_printwithlayout: "multiple",order: "cut-stack"andper_sheet: 4(or any supported grid size), pluspathorprinter. - Booklet: saddle-stitch imposition padded to a multiple of 4; both sides, front or back
only; left or right binding; creep compensation, which moves each sheet's pages toward the
fold by its place from the outside times the creep (points per sheet, up to
MAX_CREEP), clipped at the fold. Headless:doc_printwithlayout: "booklet"andcreep. - Poster: tile scale, overlap shared by neighbouring tiles, cut marks.
- Comments & forms: document, + markups, + stamps, or form fields only; annotations print only with their Print flag, drawn from their appearance streams (Algorithm 8.1). Existing Link appearances are document content in the first three modes; Link appearances are not synthesized when absent, and form fields only excludes them.
- Properties… on CUPS reads the queue's PPD and its current defaults (
lpoptions -l) off the GUI thread, and giveslpoptionsten seconds: a CUPS that has stopped answering leaves the PPD's own defaults in force instead of holding the dialog (#1818;spool::output_withinkills and reaps the command at the deadline). - Remembered choices (#2001): the dialog keeps two-sided (including leaving it to the
printer), grayscale, collate, page sizing (with its custom percent), Comments & forms and a
booklet's binding side across restarts, in the settings file under
printwith the namesdoc_printtakes (names::duplex,names::content,names::size_modeand theirparse_*counterparts are the one vocabulary). The paper is saved by its own setting (#2156). - Each job starts afresh: copies, pages (the choice, the range, odd/even and reverse), the layout with its own options (pages per sheet, order, borders, booklet subset, poster scale, overlap and cut marks) and orientation reset to the defaults each time Print opens, in the same session too; ISO 32000-2 Table 147 initialises them per document when the print dialog opens. Picked thumbnails still open it on Selected pages. The printer picked last carries over within a session (#3537) but is not saved.
Each source page becomes a Form XObject (its content wrapped in q/Q, plus the printable annotations); sheets place them with a clip. The result is a fresh, unencrypted, garbage-collected file (callers check the print permission). Annotation appearances receive unused XObject names, preserving existing page resources even when they use the same naming prefix.
The GUI Print dialog remembers its last selected paper size across application sessions,
including when Print is cancelled. The preference stores a canonical name such as A4;
unrecognized saved values retain the current selection (US Letter on a fresh app).
This change does not alter persistence of other print preferences.
Headless doc_print defaults are unchanged.
spool delegates discovery, driver options, preferences and submission to
craft-print.
PdfCraft retains page selection, imposition, annotations and print-permission checks.
CUPS jobs stream through stdin with fit-to-page=false, and with orientation-requested=4 when
every sheet is landscape (cups_orientation), since CUPS would otherwise shrink a landscape
sheet into portrait paper. On macOS they also carry the job name and owner
(com.apple.print.JobInfo.PMJobName, PMJobOwner) as the system print dialog sends them, which
some vendors' filters need (#5743). Windows renders sheets through
Windows.Data.Pdf and spools them at their physical PDF size with per-page paper and
orientation, zero added margins and hardware-edge clipping. Long-edge and short-edge duplex
use the corresponding Windows binding edges. Random, exclusively created Windows job files
are removed on success and failure. Other targets offer the print-ready PDF instead.
On Windows, Printer default reads the selected driver's current DEVMODEW duplex
setting immediately before submission and carries that binding explicitly into the job
(#5130). This also applies to doc_print with duplex: "printer"; its omitted-argument
default remains off. Explicit Off/Long Edge/Short Edge choices, booklet binding and
single-sided cut-and-stack bypass this lookup. Drivers without DM_DUPLEX retain the
unspecified setting. Two-sided defaults also stay unspecified when the driver does not
confirm automatic two-sided support, preserving manual duplex preferences (#5772).
A failed lookup, settings read or invalid declared duplex value is
logged and falls back to leaving duplex unspecified, so the driver can still choose its default.
If the queue was resolved before the settings failure, the job remains pinned to that queue. CUPS still leaves the choice to the queue. The Windows backend
selects JobDuplexAllDocumentsContiguously, falling back to DocumentDuplex when
the driver exposes only document-level duplex, and validates the retained binding before submission
(craft-libs #411).
Before a job reaches the Windows spooler, every embedded TrueType or OpenType program is
renamed PdfCraftPrint<n> in its name table and in the PDF (/BaseFont, /FontName; a
subset keeps its tag). Windows otherwise draws a subset's renumbered glyphs with the installed
font of the same name, so ReportLab's Arial subsets printed as shifted letters (#3132). Glyphs,
encodings and /ToUnicode are unchanged, and CUPS and Save as PDF get the PDF as it was. A
program PdfCraft can't read and rewrite keeps its old name in the PDF too, so a viewer that
can't load it either still picks its substitute by that name.
The shared dependency requires Rust 1.95. Transport and native Windows regression tests live in craft-libs; local tests retain composition, facade, engine, automation and UI coverage. The desktop UI discovers printers and submits jobs on workers, so neither operation blocks the dialog; the Windows backend starts without a console window. Physical printer output still needs hardware validation.
In a browser there is no spooler: the app (pdfcraft-ui-egui's web_print) draws the print-ready
PDF's sheets with PdfCraft's renderer and prints them through the browser's print dialog, which
sets copies, two-sided printing and colour. This crate stays free of web APIs.
Not yet: print as image, poster labels, PostScript output, colour conversion for grayscale.
Architectural sheets and scale
The Paper menu and doc_print share Letter, Legal, Tabloid, A3/A4/A5/A6 plus
ARCH A/B/C/D/E1/E, ANSI C/D/E and ISO A0/A1/A2. ARCH D is 24 × 36 inches;
ANSI D is 22 × 34 inches. Dimensions follow the HP DesignJet paper-size table.
Automation accepts short names such as "ARCH D" (case-insensitive) or the full menu label.
For example, doc_print with paper: "ARCH D", layout: "actual",
orientation: "auto" and path: "plan.pdf" writes a print-ready PDF at 100%.
Match page at 100% uses the currently viewed document page to choose a standard sheet (either orientation, within 0.5 pt for rounded metric dimensions), Actual size and Auto orientation. It leaves the selected page range intact. It is disabled for a custom page size with no matching preset. One preset applies to the whole job; this is not per-page paper-source selection.
PDF scale describes the source-to-sheet transform in the previewed print-ready PDF, not measured physical output. Fit reserves an 18 pt margin and can reduce even a matching page. On Windows craft-print sends the sheets as vectors with a PrintTicket for the sheet's exact paper and no scaling (#599's approach), validated by the driver: a job is refused, not shrunk, when the driver lacks the paper or would change it. Verify the driver's paper settings and physical calibration before relying on drawing scale.