fix pale colours and map driverless print options
ci/woodpecker/push/build Pipeline was successful

Set *DefaultBRColorMode: None in the vendor PPD so every job sends
<</UseCIEColor false>>: Brother's Normal/Vivid modes enable the printer's
own CIE conversion, which washed the colours out.

Add six APPrinterPreset entries mapping print-color-mode and
print-quality from driverless (AirPrint/IPP) clients onto the Brother
device options; they use the notation CUPS generates itself (Apple
metadata as 'key value' pairs, PPD options as '*Name Value'), because
key=value strings are silently discarded. print-quality is 3/4/5.

Add the PRINTER_OPTIONS env var: whitespace-separated key=value pairs
applied as queue defaults on every start via lpadmin -o, validated
against the queue's PPD, with warnings instead of a failed startup.

Document all of it in the README. The VividNoCIE candidate was dropped
after test prints showed no difference from None. Archive the OpenSpec
change and sync the printserver/cups spec with the two new
requirements.
This commit is contained in:
juergen committed 2026-10-20 08:28:08 +02:00
1 parent 75b68fe438
commit 30670de93b
9 files changed
+319 -33

No files matched your search

+99 -1
View File
@@ -85,11 +85,26 @@ podman run -d --name printserver \
| `PRINTER_NAME` | `HL4150CDN` | CUPS queue name. Also used as the name advertised via AirPrint/DNS-SD. |
| `PRINTER_DESCRIPTION` | *(empty)* | CUPS printer description (`lpadmin -D`), shown in the CUPS web UI. |
| `PPD_FILE` | `/usr/share/cups/model/BR4150_2.PPD` | PPD used for the queue. |
| `PRINTER_OPTIONS` | *(empty)* | Space-separated PPD option assignments (`key=value`) applied as queue defaults on every start, e.g. `BRColorMode=Vivid TonerSaveMode=False`. Discover the names with `lpoptions -p <queue> -l`. |
| `CERT_EXTRA_NAMES` | *(empty)* | Comma-separated extra DNS names and/or IP addresses to put into the generated `_ipps` certificate. |
| `CERT_DAYS` | `3650` | Validity of the generated certificate, in days. |
No queue is created when neither `PRINTER_IP` nor `PRINTER_URI` is set.
`PRINTER_OPTIONS` sets queue defaults that survive the recreation of the queue,
because they are re-applied on every start:
```sh
podman run -d --name printserver \
--network host \
-e PRINTER_IP=192.168.100.7 \
-e PRINTER_OPTIONS="BRMediaType=Plain BRColorMode=Vivid TonerSaveMode=False" \
printserver:latest
```
Entries that the PPD does not know are logged as a warning and ignored; the
remaining ones are applied and the container starts normally.
### Choosing the connection
The HL-4150CDN accepts PostScript directly, so the default is raw AppSocket.
@@ -187,7 +202,7 @@ The BR-Script3 PPD exposes the HL-4150CDN's hardware options. Common ones:
| Paper source | `InputSlot` | `AutoSelect`, `Tray1`, `Tray2`, `MPTray` |
| Two-sided printing | `Duplex` | `None`, `DuplexNoTumble` (long edge), `DuplexTumble` (short edge) |
| Colour / mono | `BRPrintQuality` | `Auto`, `Color`, `Black` |
| Colour mode | `BRColorMode` | `Normal`, `Vivid`, `None` |
| Colour mode | `BRColorMode` | `Normal`, `Vivid`, `None` (default) |
| Media type | `BRMediaType` | `Plain`, `Thin`, `Thick`, `Recycled`, `Glossy`, `Label`, envelopes, … |
| Print quality | `CAPT` | `Fine` (600×600), `SuperFine` (2400 dpi class) |
| Toner save | `TonerSaveMode` | `True`, `False` |
@@ -200,6 +215,57 @@ podman exec printserver lp -d HL4150CDN \
-o Duplex=DuplexNoTumble -o BRPrintQuality=Color -o InputSlot=Tray1 report.pdf
```
### Why the macOS/iOS dialog shows fewer options
macOS and iOS print driverless (AirPrint / IPP Everywhere), so the dialog shows
only IPP-standard options: media size, duplex, pages per sheet, the
black-and-white/colour toggle and the quality slider. Brother-specific options
(`BRColorMode`, `BRMediaType`, `TonerSaveMode`, `CAPT`, …) have no IPP
equivalent and can never appear there. Set them server-side instead:
- as queue defaults at container start via `PRINTER_OPTIONS` (see
*Environment variables*),
- per job with `lp -o …`, or
- interactively in the CUPS web UI (`http://<host>:631/admin`, *Printing Options*).
The dialog's black-and-white/colour toggle maps to `print-color-mode` and the
quality slider to `print-quality`; the PPD presets documented below translate
both onto the Brother options, so they now really take effect:
| Dialog / IPP | PPD option it becomes |
| --- | --- |
| `print-color-mode=monochrome` | `BRPrintQuality=Black` |
| `print-color-mode=color` | `BRPrintQuality=Auto` |
| `print-quality=3` (draft) | `TonerSaveMode=True` |
| `print-quality=4` (normal) | defaults (`Fine`, toner save off) |
| `print-quality=5` (high) | `CAPT=SuperFine` (2400 dpi class) |
Client-specified values always win over the preset.
### Changes to the vendor PPD
`assets/Brother HL-4150CDN/ppd/BR4150_2.PPD` is Brother's original file plus
two additions, each marked with a `%` comment in the file:
- **`*DefaultBRColorMode: None` instead of `Normal`.** `Normal` and `Vivid` both
set `<</UseCIEColor true>>`; the printer's own CIE conversion washes the
colours out (see [Colours are printed pale / washed out](#colours-are-printed-pale--washed-out)).
- **Six `APPrinterPreset` entries** mapping `print-color-mode`
(color/monochrome) and `print-quality` (draft/normal/high) onto
`BRPrintQuality`, `CAPT` and `TonerSaveMode`. CUPS applies such presets for
driverless clients and always lets the client's own option values win. In
particular `print-color-mode=monochrome` becomes `BRPrintQuality=Black`, so
black-and-white printing works: the server cannot do the greyscale conversion
itself, because `pdftops` uses Poppler for Brother printers and Poppler
cannot produce greyscale (`WARNING: Grayscale/monochrome could be printed as
color with Poppler` in the CUPS log). The presets use the notation CUPS
generates itself — Apple metadata as `key value` pairs *without* `=`, PPD
options as `*Name Value` pairs on separate lines inside a multiline
`"…"` string. With `key=value` on a single line CUPS silently ignores the
whole preset (verified against libcups 2.4.2: `_ppdParseOptions()` splits on
whitespace, so `key=value` becomes the option *name* and the lookup fails).
Note that IPP `print-quality` is `3` (draft), `4` (normal), `5` (high).
## Client support
| Platform | Path | Notes |
@@ -384,6 +450,38 @@ still being rejected — fix that, or add the queue from the command line as
above. macOS caches the failed attempt, so remove and re-add the printer after
changing anything on the server.
### Colours are printed pale / washed out
Symptom: colour printouts look desaturated compared to the same PDF printed
directly from the Mac, or with Brother's own driver.
Cause: the PPD colour mode `Normal` (Brother's default) makes the printer's
PostScript interpreter apply its own CIE conversion (`<</UseCIEColor true>>`),
which washes colours out. `Vivid` sets `UseCIEColor` as well, so it does not
help either; `BRPrintQuality` (`BRColorAdapt`) and `TonerSaveMode` made no
visible difference in a side-by-side test. The container therefore ships the
PPD with `*DefaultBRColorMode: None` (`UseCIEColor` off), which produces
saturated output.
Check and, if needed, override the current default:
```sh
podman exec printserver lpoptions -p <queue> -l | grep BRColorMode # expect *None
podman exec printserver lp -d <queue> -o BRColorMode=None test.pdf
```
If output is still pale with `BRColorMode=None`, check the printer's own menu
(Toner → Toner Save off) and make sure `BRMediaType` matches the media in the
tray.
Black-and-white is a related but separate path: `print-color-mode=monochrome`
from a driverless client is mapped by the PPD presets onto
`BRPrintQuality=Black` (the printer renders mono). It is deliberately *not* done
by the server — with its Poppler renderer, `pdftops` cannot convert to
greyscale. Forcing Ghostscript with `-o pdftops-renderer=gs` would, but that
path is not recommended for Brother printers (bugs in their PostScript
interpreters).
## CUPS 3 and the future of PPDs
Adding the queue with a PPD makes `lpadmin` print:
+46 -1
View File
@@ -374,9 +374,12 @@ restore
*CloseUI: *BRPrintQuality
*% Color Mode Information ===============
*% Modified by this repo (see README, "Changes to the vendor PPD"):
*% - default switched from Normal to None: with UseCIEColor off the printer
*% skips its CIE conversion, which otherwise washes out the colours.
*OpenUI *BRColorMode/Colour Mode: PickOne
*OrderDependency: 131.0 AnySetup *BRColorMode
*DefaultBRColorMode: Normal
*DefaultBRColorMode: None
*BRColorMode Normal/Normal: "
<</UseCIEColor true>>setpagedevice
<</BRColorMode 0>>setpagedevice
@@ -393,6 +396,48 @@ restore
*End
*CloseUI: *BRColorMode
*% Added by this repo: presets mapping the IPP attributes of driverless
*% (AirPrint/IPP Everywhere) clients onto the device options below. CUPS applies
*% them automatically when a job carries print-color-mode / print-quality;
*% options the client states explicitly always take precedence. Format follows
*% the presets CUPS generates itself: Apple metadata as "key value" pairs
*% (no '='), PPD options as "*Name Value" pairs.
*APPrinterPreset ColorDraft/Colour, Draft: "
com.apple.print.preset.output-mode color
com.apple.print.preset.quality low
*TonerSaveMode True
"
*APPrinterPreset ColorNormal/Colour, Normal: "
com.apple.print.preset.output-mode color
com.apple.print.preset.quality normal
*TonerSaveMode False
"
*APPrinterPreset ColorHigh/Colour, High: "
com.apple.print.preset.output-mode color
com.apple.print.preset.quality high
*CAPT SuperFine
*TonerSaveMode False
"
*APPrinterPreset MonoDraft/B&W, Draft: "
com.apple.print.preset.output-mode monochrome
com.apple.print.preset.quality low
*BRPrintQuality Black
*TonerSaveMode True
"
*APPrinterPreset MonoNormal/B&W, Normal: "
com.apple.print.preset.output-mode monochrome
com.apple.print.preset.quality normal
*BRPrintQuality Black
*TonerSaveMode False
"
*APPrinterPreset MonoHigh/B&W, High: "
com.apple.print.preset.output-mode monochrome
com.apple.print.preset.quality high
*BRPrintQuality Black
*CAPT SuperFine
*TonerSaveMode False
"
*% Improve Gray Color Information ===============
*OpenUI *BRImprovedGray/Improve Grey Colour: PickOne
*OrderDependency: 132.0 AnySetup *BRImprovedGray
+48
View File
@@ -18,6 +18,9 @@
# PRINTER_NAME CUPS queue name and advertised (DNS-SD) name.
# PRINTER_DESCRIPTION CUPS Description (lpadmin -D) shown in the web UI.
# PPD_FILE PPD used for the queue.
# PRINTER_OPTIONS Space-separated PPD option assignments (key=value)
# applied as queue defaults on every start, e.g.
# "BRColorMode=Vivid TonerSaveMode=False".
# CERT_EXTRA_NAMES Comma-separated extra DNS names / IP addresses to put
# into the generated IPPS certificate (server SANs).
# CERT_DAYS Validity of the generated certificate (default 3650).
@@ -29,6 +32,7 @@ PRINTER_URI="${PRINTER_URI:-}"
PRINTER_PROTOCOL="${PRINTER_PROTOCOL:-socket}"
PRINTER_DESCRIPTION="${PRINTER_DESCRIPTION:-}"
PPD_FILE="${PPD_FILE:-/usr/share/cups/model/BR4150_2.PPD}"
PRINTER_OPTIONS="${PRINTER_OPTIONS:-}"
LOG_PREFIX="[entrypoint]"
log() { echo "${LOG_PREFIX} $*"; }
@@ -331,6 +335,50 @@ if lpstat -p "${PRINTER_NAME}" >/dev/null 2>&1; then
log "queue ${PRINTER_NAME} is shared and set as default"
fi
# Apply optional queue defaults from PRINTER_OPTIONS (see README). Runs on every
# start so the settings survive the (re)creation of the queue; an unusable entry
# only logs a warning instead of aborting the startup ("set -eu"). Names and
# values are checked against the queue's options first, because lpadmin would
# happily store unknown assignments as queue defaults.
apply_printer_options() {
[ -n "${PRINTER_OPTIONS}" ] || return 0
if ! lpstat -p "${PRINTER_NAME}" >/dev/null 2>&1; then
log "warning: queue ${PRINTER_NAME} does not exist; skipping PRINTER_OPTIONS"
return 0
fi
ppd_options="$(lpoptions -p "${PRINTER_NAME}" -l 2>/dev/null || true)"
for opt in ${PRINTER_OPTIONS}; do
case "${opt}" in
?*=*) ;;
*)
log "warning: ignoring malformed PRINTER_OPTIONS entry '${opt}' (expected key=value)"
continue
;;
esac
name="${opt%%=*}"
value="${opt#*=}"
line="$(printf '%s\n' "${ppd_options}" | grep "^${name}/")" || {
log "warning: PPD has no option '${name}'; ignoring (names/values: 'lpoptions -p ${PRINTER_NAME} -l')"
continue
}
# Option lines look like "Name/Text: value1 value2 ..." ('*' = default).
values="$(printf '%s\n' "${line#*: }" | tr ' ' '\n' | sed 's/^\*//')"
if ! printf '%s\n' "${values}" | grep -qxF "${value}" \
&& ! { case "${value}" in Custom.*)
printf '%s\n' "${values}" | grep -q 'Custom\.'
;; *) false ;; esac; }; then
log "warning: PPD option '${name}' has no value '${value}'; ignoring"
continue
fi
if lpadmin -p "${PRINTER_NAME}" -o "${opt}" >/dev/null 2>&1; then
log "queue default ${opt} applied"
else
log "warning: lpadmin -o ${opt} failed; ignoring"
fi
done
}
apply_printer_options
# --- Verify CUPS is reachable on the network --------------------------------
# cupsd also runs with nothing but its domain socket, e.g. when it cannot bind
# the privileged port 631 (rootless Podman with host networking). It then still
@@ -85,6 +85,30 @@ geschickt hat – clientseitige Auswahl gewinnt also weiterhin
(`ppd-mark.c`: „as long as the corresponding names are not already defined
in the IPP request").
**Preset-Notation (2026-10-20 empirisch geklärt).** Die Preset-Werte müssen so
geschrieben werden, wie CUPS sie selbst erzeugt (`ppd-cache.c`, Funktion
`cupsFilePrintf fp "*APPrinterPreset %s: \""`): eine mehrzeilige Zeichenkette,
in der Apple-Metadaten als `key value`-**Paare ohne `=`** und PPD-Optionen als
`*Name Value`-Paare stehen, jeweils durch Leerzeichen getrennt:
```
*APPrinterPreset MonoNormal/B&W, Normal: "
com.apple.print.preset.output-mode monochrome
com.apple.print.preset.quality normal
*BRPrintQuality Black
*TonerSaveMode False
"
```
`_ppdCacheCreateWithPPD()` parst den Wert mit `_ppdParseOptions()`, das an
Whitespace trennt – `key=value` in einer Zeile würde den *Namen*
`key=value` ergeben und der Lookup (`cupsGetOption("com.apple.print.preset.
quality", …)`) schlüge fehl. CUPS verwirft das Preset dann **stillschweigend**
(`num_presets[…]=0`), was im Test zunächst genau passierte. Verifiziert mit
einem libcups-2.4.2-Harness (`_ppd_cache_t` inspiziert) und im
`pstops`-Filterpfad. Zusätzlich: IPP-`print-quality` ist **3/4/5**
(Draft/Normal/High), nicht 2/5.
**2. PPD direkt im Repository ändern (nicht zur Build-Zeit patchen).**
Die Asset-Datei `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD` wird bereits
@@ -112,13 +136,12 @@ damit gilt es auch für eine persistente Queue. Fehler pro Token abfangen
(`|| log warning`), da `set -eu` sonst den Start abbricht; unbekannte Namen
werden verworfen, ohne die übrigen zu blockieren.
**5. Neue `BRColorMode`-Choice `VividNoCIE` nur unter Vorbehalt.**
**5. Neue `BRColorMode`-Choice `VividNoCIE` verworfen.**
`<</UseCIEColor false /BRColorMode 1>>` – Kombi, die es bisher nicht gibt
(`None` lässt `/BRColorMode` unangetastet, `Vivid` erzwingt CIE). Wird als
Testdruck gegen `None` verglichen; nur übernommen, wenn der Ausdruck
deutlich besser ist. Spezifikation hängt nicht davon ab (Default bleibt
`None`, Überschreibung ist ohnehin möglich).
(`None` lässt `/BRColorMode` unangetastet, `Vivid` erzwingt CIE). Als
Testdruck gegen `None` verglichen (2026-10-20): **nicht unterscheidbar**,
daher nicht übernommen. `None` bleibt der einzige geänderte Default.
## Risks / Trade-offs
@@ -151,8 +174,6 @@ deutlich besser ist. Spezifikation hängt nicht davon ab (Default bleibt
## Open Questions
- Ob `VividNoCIE` mehr Sättigung liefert als `None` – wird im Tasks-Test
entschieden; ändert weder Spec (Default bleibt `None`) noch Aufbau.
- Ob macOS/iOS den Qualitätsregler als `print-quality` sendet – falls nicht,
bleiben die `print-quality`-Presets inert, `print-color-mode`-Presets
wirken unabhängig davon (Server-seitig per `lp -o print-quality=…`
@@ -41,16 +41,16 @@ Drucker-Queue):
Start als Queue-Defaults gesetzt werden – damit überleben
PPD-Optionen (z. B. `BRMediaType`, `TonerSaveMode`, `BRColorMode=Vivid`)
die Neuerzeugung der Queue.
- **Optionale neue PPD-Choice `BRColorMode=VividNoCIE`**
(`<</UseCIEColor false /BRColorMode 1>>`) als Testkandidat für noch
gesättigtere Ausgabe als `None`; nur behalten, wenn der Testdruck
besser ist als `None`.
- **README**: neuer Abschnitt, warum der AirPrint-Dialog nur
IPP-Standardoptionen zeigt und wie PPD-Optionen gesetzt werden (Env-Var,
CUPS-Web-UI, `lp`); Troubleshooting „Farben sind blass" mit der
durchgeführten Testreihe; Dokumentation der funktionierenden
S/W-Abbildung.
Verworfen: eine zusätzliche Choice `BRColorMode=VividNoCIE`
(`UseCIEColor false` + `/BRColorMode 1`) – die Testdrucke waren von `None`
nicht unterscheidbar, siehe `design.md`.
Kein Bestandteil: Änderungen am Containerfile (die PPD wird bereits
installiert), am Verbindungs-/Zertifikatsverhalten oder eine
Server-seitige Erzwingung von Graustufen über `pdftops-renderer=gs`
@@ -2,29 +2,35 @@
## 1. PPD: Farbmodus-Default, Presets und Dokumentation
- [ ] 1.1 `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`: `*DefaultBRColorMode`
- [x] 1.1 `assets/Brother HL-4150CDN/ppd/BR4150_2.PPD`: `*DefaultBRColorMode`
von `Normal` auf `None` ändern, alle eigenen Ergänzungen mit
`%`-Kommentar (Herkunft/Zweck) markieren.
Verifikation: `grep -n 'DefaultBRColorMode\|^% Modified' "assets/Brother HL-4150CDN/ppd/BR4150_2.PPD"`
zeigt `*DefaultBRColorMode: None` und den Kommentar.
- [ ] 1.2 PPD: sechs `APPrinterPreset`-Einträge ergänzen (Kombinationen
color/monochrome × low/normal/high gemäß Tabelle in `design.md`,
z. B. `*APPrinterPreset MonoNormal/Schwarz-Weiß Normal:
"*com.apple.print.preset.output-mode=monochrome
*com.apple.print.preset.quality=normal *BRPrintQuality=Black
*TonerSaveMode=False"`).
- [x] 1.2 PPD: sechs `APPrinterPreset`-Einträge ergänzen (Kombinationen
color/monochrome × low/normal/high gemäß Tabelle in `design.md`).
Verifikation: `grep -c '^\*APPrinterPreset' "assets/Brother HL-4150CDN/ppd/BR4150_2.PPD"`
ergibt 6, und nach einem Build listet
`lpoptions -p <queue> -l` weiterhin alle Optionen ohne
PPD-Warnung in `/var/log/cups/error_log`.
- [ ] 1.3 PPD: Choice `VividNoCIE` unter `BRColorMode` ergänzen
Ergebnis (2026-10-20): Zunächst als einzeilige `key=value`-Strings
geschrieben – CUPS verwarf alle sechs stillschweigend
(`_ppdParseOptions()` trennt an Whitespace, `key=value` wurde zum
*Namen*). Mit libcups-2.4.2-Harness (`_ppd_cache_t`-Inspektion) belegt
und auf das von CUPS selbst erzeugte Format umgestellt (mehrzeilig,
Apple-Metadaten als `key value`, PPD-Optionen als `*Name Value`).
Danach greifen alle sechs im `pstops`-Pfad (siehe 3.x).
- [x] 1.3 PPD: Choice `VividNoCIE` unter `BRColorMode` ergänzen
(`<</UseCIEColor false /BRColorMode 1>>setpagedevice`) und per
Testdruck gegen `None` vergleichen; nur behalten, wenn der Ausdruck
deutlich gesättigter ist.
Verifikation: `lpoptions -p <queue> -l` zeigt die Choice, die
Entscheidung (behalten/entfernen) ist im README-Auswertungs-Abschnitt
notiert.
- [ ] 1.4 README: Abschnitt „Farben sind blass" (Ursache `UseCIEColor`,
Ergebnis (2026-10-20): Testdrucke `BRColorMode=VividNoCIE` (Job 5) und
`BRColorMode=None` (Job 6) sind **nicht unterscheidbar** → Choice
wieder entfernt (README/Tabelle bereinigt).
- [x] 1.4 README: Abschnitt „Farben sind blass" (Ursache `UseCIEColor`,
durchgeführte Testreihe mit `lp -o BRColorMode=…`,
Ergebnis `None`), Abschnitt „Änderungen an der Hersteller-PPD"
(welche Einträge ergänzt wurden und warum) und Abschnitt
@@ -35,7 +41,7 @@
## 2. entrypoint: `PRINTER_OPTIONS`
- [ ] 2.1 `entrypoint.sh`: `PRINTER_OPTIONS` (Standard leer) nach der
- [x] 2.1 `entrypoint.sh`: `PRINTER_OPTIONS` (Standard leer) nach der
Queue-Erzeugung in Tokens `key=value` zerlegen und jedes per
`lpadmin -o` setzen, an derselben Stelle wie
`printer-is-shared`/`-D`/`-d`, bei jedem Start.
@@ -43,12 +49,12 @@
`PRINTER_OPTIONS="BRColorMode=Vivid TonerSaveMode=False"` und
`lpoptions -p <queue> -l` zeigt `Vivid` und `True` als Default
(`*Vivid`, `*True`).
- [ ] 2.2 Fehler pro Token abfangen, damit `set -eu` den Start nicht
- [x] 2.2 Fehler pro Token abfangen, damit `set -eu` den Start nicht
abbricht, und warnen.
Verifikation: Start mit `PRINTER_OPTIONS="NoSuchOption=Foo"` erzeugt
eine Warning-Zeile im Log, der Container erreicht
„ready: CUPS on 631/tcp" und `lpstat -r` meldet „scheduler is running".
- [ ] 2.3 README: neue Zeile in der Env-Var-Tabelle plus Kurzbeispiel unter
- [x] 2.3 README: neue Zeile in der Env-Var-Tabelle plus Kurzbeispiel unter
„Environment variables" (inkl. Hinweis `lpoptions -p <queue> -l` zur
Entdeckbarkeit der Namen).
Verifikation: das Beispiel aus der Tabelle in einen `podman run`-Befehl
@@ -56,21 +62,38 @@
## 3. Integrationstests am laufenden System
- [ ] 3.1 Image neu bauen und Container starten.
- [x] 3.1 Image neu bauen und Container starten.
Verifikation: `podman build -t printserver:latest .` endet ohne Fehler,
das Log enthält „ready: CUPS on 631/tcp, mDNS on 5353/udp".
- [ ] 3.2 S/W-Druck aus dem macOS-Dialog (derselbe Farbjob wie zuvor).
Ergebnis (2026-10-20, podman 6.1.4/macOS-VM): Build und Start ok; der
Container bindet 631 nur nach
`podman machine ssh -- sudo sysctl -w net.ipv4.ip_unprivileged_port_start=631`
(rootless VM) – danach „ready".
- [x] 3.2 S/W-Druck aus dem macOS-Dialog (derselbe Farbjob wie zuvor).
Verifikation: Ausdruck ist schwarz/weiß – vorher kam er farbig heraus.
- [ ] 3.3 Farbdruck ohne weitere Optionen aus dem Dialog und per
Server-seitig verifiziert (2026-10-20): `print-color-mode=monochrome`
→ `<</BRProcessColor 1>>`. Sichtprüfung durch Nutzer (2026-10-20):
Testseite 2 ist schwarz/weiß. **Bestanden.**
- [x] 3.3 Farbdruck ohne weitere Optionen aus dem Dialog und per
`lp -d <queue> test.pdf`.
Verifikation: Ausdruck ist so gesättigt wie der bisherige
`BRColorMode=None`-Testdruck; `lpoptions -p <queue> -l` zeigt `*None`
als Farbmodus-Default.
- [ ] 3.4 Qualitätsstufen prüfen.
Verifikation: `lp -o print-quality=2 test.pdf` (draft, sichtbar
tonersparender) und `lp -o print-quality=5 test.pdf` (high, `CAPT`
SuperFine) erzeugen unterscheidbare Ausdrucke gegenüber
`print-quality=3`.
Verifiziert (2026-10-20): `lpoptions` zeigt `*None`, `pstops` emittiert
`<</UseCIEColor false>>` auch ohne Job-Optionen. Sichtprüfung durch
Nutzer: Testseite 1 ist kräftig/gesättigt (nicht mehr blass).
**Bestanden.**
- [x] 3.4 Qualitätsstufen prüfen.
Verifikation: `lp -o print-quality=3 test.pdf` (IPP draft, sichtbar
tonersparender: `true tonersave`) und `lp -o print-quality=5 test.pdf`
(IPP high, `CAPT SuperFine`, `<</BRApt 2 /HWResolution [600 600]>>`)
erzeugen unterscheidbare Ausdrucke gegenüber `print-quality=4`
(IPP normal). Hinweis: IPP-`print-quality` ist 3/4/5 – nicht 2/5.
Verifiziert (2026-10-20): serverseitig im `pstops`-Output (3 →
`true tonersave`, 5 → `BRApt 2`); Sichtprüfung durch Nutzer: Seite 3
(draft) blass/tonersparend, klar unterscheidbar von 1/4. Seite 1 = 4
erwartungsgemäß (SuperFine vs. Fine bei diesem Testmotiv optisch
gleich, serverseitig aber gesetzt). **Bestanden.**
## Workflow follow-up
+51
View File
@@ -54,6 +54,57 @@ The system SHALL translate the PPD's device options into PostScript
- **WHEN** a job selects colour or mono
- **THEN** the emitted PostScript sets the corresponding colour/mono device parameters
#### Scenario: A driverless client selects black and white
- **WHEN** an AirPrint/IPP client sends `print-color-mode=monochrome`
- **THEN** the emitted PostScript sets the mono device parameters (`/BRProcessColor 1`) and the job prints in black and white, independent of the PDF renderer used by the server
#### Scenario: A driverless client selects colour
- **WHEN** an AirPrint/IPP client sends `print-color-mode=color`
- **THEN** the job prints in colour and the emitted PostScript disables toner saving
#### Scenario: A driverless client selects the print quality
- **WHEN** an AirPrint/IPP client sends `print-quality=draft`, `normal` or `high`
- **THEN** the emitted PostScript selects the mapped device settings: toner saving for draft, full toner for normal, and the `CAPT` high-resolution setting for high
### Requirement: Queue defaults are configurable at runtime
The container SHALL accept a `PRINTER_OPTIONS` environment variable holding
space-separated PPD option assignments (`key=value`) and apply each assignment
as a queue default on every start, so PPD-specific device options survive the
recreation of the queue.
#### Scenario: Options are applied on start
- **WHEN** the container is started with `PRINTER_OPTIONS="BRColorMode=Vivid TonerSaveMode=False"`
- **THEN** after startup the queue defaults include `BRColorMode=Vivid` and `TonerSaveMode=False`
#### Scenario: Defaults apply to driverless clients
- **WHEN** a macOS or iOS client prints a job that does not specify that PPD option
- **THEN** the job is printed with the configured queue default
#### Scenario: An unusable option must not stop startup
- **WHEN** `PRINTER_OPTIONS` contains an option name or value the PPD does not provide
- **THEN** the entrypoint logs a warning, applies the remaining assignments and continues starting
#### Scenario: Nothing configured
- **WHEN** `PRINTER_OPTIONS` is unset or empty
- **THEN** the queue keeps the PPD defaults and the container starts as before
### Requirement: Colour output is saturated by default
Unless overridden through `PRINTER_OPTIONS`, the queue SHALL default to the
colour mode `None`, which leaves the printer's CIE colour conversion
(`UseCIEColor`) switched off so that printed colours are not washed out.
#### Scenario: Default colour mode
- **WHEN** a colour job is printed without any colour-mode options
- **THEN** the emitted PostScript contains `<</UseCIEColor false>>` rather than `UseCIEColor true`
#### Scenario: Default is overridable
- **WHEN** the container is started with `PRINTER_OPTIONS` containing `BRColorMode=Vivid`
- **THEN** the queue default is `Vivid` instead of `None`
#### Scenario: A job's own selection wins
- **WHEN** a job explicitly selects another `BRColorMode` value
- **THEN** that value is used for the job instead of the queue default
### Requirement: Jobs are printed via direct PostScript
The container SHALL forward the converted job as PostScript to the printer
without a server-side vendor filter or host-side rasterisation.