mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-30 03:02:19 +01:00
68 lines
4.3 KiB
Markdown
68 lines
4.3 KiB
Markdown
# Printing
|
||||
|
|
|
|||
|
|
File › Print renders the flattened document onto one PDF page (paper size and orientation,
|
|||
|
|
position and scale, crop and registration marks, labels, colour handling) and hands that page
|
|||
|
|
to a printer. The rendering is `print_cmds.rs` in `photocraft-engine`, shared by the dialog, the
|
|||
|
|
batch commands and automation (`file.print`, `file.printOneCopy`); this page is about the hand-off.
|
|||
|
|
|
|||
|
|
## Routes to the printer
|
|||
|
|
|
|||
|
|
| Route | When | What the user sees |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **`craft-print`** (`lp` on CUPS, the Windows spooler) | Whenever `lp` is on the path (macOS, Linux outside a sandbox) or on Windows | `Sent to the printer (request id is Office-42)` |
|
|||
|
|
| **CUPS over IPP** (`photocraft-ipp`) | No `lp` on the path (a Flatpak) and a print server answers: `CUPS_SERVER`, then `/run/cups/cups.sock`, `/var/run/cups/cups.sock`, `/private/var/run/cupsd`, then `localhost:631`; always for a `printServer` named in the request | `Sent to the printer (job 42 on Office)` |
|
|||
|
|
| **Print portal** (`org.freedesktop.portal.Print`, desktop app on Linux) | No print server reachable or no printer set up, or always with `PHOTOCRAFT_PRINT_PORTAL=1` | The system print dialog, seeded with the copies and paper; the outcome goes to the log |
|
|||
|
|
| **Print to PDF** | `output` given (the Output field of the dialog) | The file; nothing is spooled unless `send` is true |
|
|||
|
|
|
|||
|
|
A route that exists but fails (an unknown printer, a job the queue refuses) is an error; only a
|
|||
|
|
missing route (no `lp`, no print server, no printer) moves on to the next one.
|
|||
|
|
|
|||
|
|
The IPP client is in-process, pure Rust (RFC 8010/8011: `CUPS-Get-Printers`, `CUPS-Get-Classes`,
|
|||
|
|
`CUPS-Get-Default`, `Print-Job` with the PDF as the document), so no `lp` binary is needed. That
|
|||
|
|
is what makes printing work in the Flatpak: the manifest grants `--socket=cups`, which mounts the
|
|||
|
|
host's CUPS socket, and the sandbox has no `lp`. On a system without CUPS, or in a sandbox
|
|||
|
|
without the socket, the app falls back to the print portal, whose dialog runs outside the sandbox.
|
|||
|
|
|
|||
|
|
## Which printer
|
|||
|
|
|
|||
|
|
The dialog's Printer field, or `"printer"` in the command, names a queue (case-insensitively; a
|
|||
|
|
CUPS class counts, as with `lp -d`).
|
|||
|
|
Left empty, the server's default printer is used; without a default, the only printer; with
|
|||
|
|
several and no default, the error names them. With no printer at all, the portal takes over when
|
|||
|
|
it is available, otherwise the error says to add one in the system settings or print to PDF.
|
|||
|
|
|
|||
|
|
`file.printers` lists what the print server knows: `{"printServer": "host[:port]|socket"}`
|
|||
|
|
is optional and defaults to the system's CUPS; the result is
|
|||
|
|
`{server, default, printers: [{name, info, state, acceptingJobs, default, class}]}`, or an empty list
|
|||
|
|
with a `note` when no server answers. `"printServer"` on `file.print` sends one job to a named
|
|||
|
|
server; `"dryRun": true` renders the page and reports the equivalent `lp` command without
|
|||
|
|
spooling.
|
|||
|
|
|
|||
|
|
## Results
|
|||
|
|
|
|||
|
|
`file.print` returns `sent`, `backend` (`lp`, `windows`, `ipp`, `portal`), `spooler` (where the
|
|||
|
|
job went) and `pdf` (the page's path, only when `output` named one).
|
|||
|
|
|
|||
|
|
## Environment
|
|||
|
|
|
|||
|
|
| Variable | Effect |
|
|||
|
|
|---|---|
|
|||
|
|
| `CUPS_SERVER` | The print server, as CUPS itself reads it: `host[:port]` or a socket path |
|
|||
|
|
| `PHOTOCRAFT_PRINT_PORTAL=1` | Always use the system print dialog (the portal) instead of `lp` or CUPS directly |
|
|||
|
|
| `PHOTOCRAFT_PRINT_PORTAL=0` | Never use the portal; a missing print server is then an error |
|
|||
|
|
|
|||
|
|
## Verification
|
|||
|
|
|
|||
|
|
- `crates/ipp/src/tests.rs`: the client against a fake CUPS over TCP and a Unix socket:
|
|||
|
|
printer listing with state and default, the default printer and its absence, `Print-Job`
|
|||
|
|
with the document and the job id, chunked and content-length replies, HTTP and IPP error
|
|||
|
|
statuses, broken replies.
|
|||
|
|
- `crates/engine/src/print_cmds/tests.rs`: printer resolution (requested, default, only one,
|
|||
|
|
several without a default, unknown, none); a complete `file.print` against a fake CUPS
|
|||
|
|
(printer URI, copies, job name, document format, the PDF itself) and `file.printers`;
|
|||
|
|
`lp` taking the job when it is on the path; the IPP route when it is not (a child process
|
|||
|
|
with an empty path); the app's spooler when preferred, as the fallback without a printer, and
|
|||
|
|
skipped when a server is named; print to PDF untouched.
|
|||
|
|
- `apps/photocraft/src/print_portal.rs`: the request path rule and the paper/copies seeding of
|
|||
|
|
the dialog (PWG names for the standard papers, millimetres for custom sizes).
|