Centralise every Core Printing (PM*) call in one @MainActor bridge so
the upcoming ticket serialise/restore path and native spooler share a
single documented ownership policy. Pure move — no behaviour change.
Serialise PMPrintSettings/PMPageFormat to XML data plus a plist-safe
NSPrintInfo dictionary snapshot (PrintTicket), restore via
PM*CreateWithDataRepresentation -> PMCopy* -> PMSessionValidate* ->
updateFromPM*, and refuse cross-queue replay (R3).
PrintPanelService.showProperties now returns PanelCaptureResult; the
view model stores tickets in capturedTickets keyed by queue.
Also fixes a latent over-release: PMSessionGetCurrentPrinter hands back
the session's own printer (borrowed) — the extracted currentPrinterID
was PMRelease-ing it, which dangled the session and crashed AppKit's
_printerInPrintSession path and session teardown.
TargetRasterLoader decodes printtarg TIFFs via ImageIO and re-tags
into DeviceGray/DeviceRGB/DeviceCMYK around the decoder's own
dataProvider — no resample, no bit-depth change (D10). Skip-only
alpha padding (noneSkipLast/First, which ImageIO emits for opaque
RGB TIFFs) is accepted; real coverage alpha, indexed, float and
non-1/3/4-component layouts are rejected as unsupportedLayout.
DPI metadata drives pointSize (px/dpi*72) with a 72 dpi fallback +
warn; manifestDrift reports >0.5 mm disagreement with the printtarg
manifest (D9).
TargetPageCanvasView is the headless flipped canvas NSPrintOperation
paginates: rectForPage stacks pages top-down, destinationRect anchors
1:1 at the page's top-left snapped to 0.001 pt, and draw() forces
interpolation/antialias/font-smoothing off per page with a drawProbe
seam for tests.
PDF harness (NativeSpoolPDFTests, skippable via ICCERY_SKIP_PRINT_PDF=1)
ran on this host: run() -> true, 2 pages at A4 media box, and the
fixture's 72 pt patch verified 1:1 at the painted top-left (printer
unprintable-margin offset tolerated per R10).
Replace the LpArgs argv builder with the deterministic
TicketWriteResolver (locked 1-10 write order, Stage 2 overrides win
unconditionally, no raw, nil overrides emit no write) and spool via a
headless NSPrintOperation over TargetPageCanvasView instead of the
CUPS lp binary. RecordingTargetSpooler (DEBUG) logs deterministic
request lines to ICCERY_TEST_SPOOL_LOG for tests. Single spool job
toggle switches printAllPages between per-page requests and one
multi-page job. CupsService keeps lpstat/lpoptions enumeration but
loses printTarget; ProcessID.lp* renamed cupsLp*; LpArgs, its tests
and the lp fixture deleted.
226e7b2 un-flipped the canvas but left destinationRect anchored at
pageRect.minY — the page's BOTTOM edge in bottom-up space — so
sub-page targets printed at the foot of the sheet and oversize
targets clipped their top rows. Anchor at pageRect.maxY - height,
restoring the spec'd top-left anchor (docs/14 §6, D9).
Adds the missing regression coverage: the geometry test now asserts
the top anchor with a sub-page raster, and the PDF harness gains a
banded (red-over-blue) fixture that fails on either a mirrored draw
or a bottom anchor — solid fills could catch neither.
lpoptions -l only exposes the global quality list, so the picker offered every token for every media — the driver then rejected invalid pairs (e.g. Fast Economy on Premium Semigloss) at print time. Neither the Epson nor the Canon PPD carries standard *UIConstraints, so resolve the media-to-quality map from each driver's own data: Epson InkjetPrinter2 *EPIJUIConstraint forbid-rules in the machine bundle's PDEData.dat (non-media LHS terms evaluated against lpoptions defaults), Canon BJPrinter's binary cnb_<TableID>0.tbl record table via *CNIJNameTblPath/*CNIJTableID, and generic PPD *UIConstraints pairs.
MediaQualityConstraints picks the first non-empty source and fails open — queues without constraint data keep the full list. PrinterCapabilities gains qualityIDsByMediaType plus filtered qualities(forMediaType:)/allowsQuality accessors; the view model exposes availableQualities, clamps the pick on media change / seeding / panel apply-back, and substitutes a stale quality defensively in makeRequest so an invalid pair can never reach the ticket.
press(forDuration:thenDragTo:) is inert on macOS — content-drag
scrolling is iOS-only, so the helper burned its 20s budget with the
gallery frame never moving. The scroll wheel is the mechanism the
platform supports: one scroll(byDeltaX:deltaY:) call on a coordinate
inside app.scrollViews["stage-2"] per poll iteration, negative deltaY
to move content up off the Dock zone.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
273c319152to2407abfd9e