feat(print): 1:1 TIFF raster loader and headless page canvas (#201 Phase 3) #205

Merged
gronod merged 1 commits from feat/201-raster-canvas into milestone/m12-native-spool 2026-09-17 15:08:08 +01:00
Owner

Summary

Phase 3 of the M12 megaplan (#201): the raster decode + headless draw pipeline the native spooler (Phase 4) will drive. No spooling changes yet.

  • TargetRaster.swift — TargetPageRaster / TargetRasterLoader / TargetRasterError: TIFF decode via CGImageSource, DPI metadata with 72 dpi fallback + warn, DPI-derived pointSize (the only size the canvas draws at), manifest-drift check (>0.5 mm), and deviceTagged(_:) — re-tag into DeviceGray/DeviceRGB/DeviceCMYK reusing the source dataProvider (no resample, no bit-depth change, D10). Alpha relaxed per approved fix.
  • TargetPageCanvasView.swift — headless NSView for NSPrintOperation: flipped top-down page stack, knowsPageRange/rectForPage, top-left-anchored destinationRect snapped to 0.001 pt, draw with interpolation/antialias off and a drawProbe test seam.

Tests

  • TargetRasterFixtures.swift — makeTIFF(px:dpi:components:bitsPerComponent:) via CGImageDestination.
  • TargetRasterTests — pointSize math, missing-DPI fallback, device-tag per layout (RGB-8/16, CMYK, Gray), pixel-byte equality, unsupported-layout rejection.
  • TargetCanvasGeometryTests — rectForPage/destinationRect, draw-flag assertions via offscreen NSGraphicsContext.
  • NativeSpoolPDFTests — real NSPrintOperation with jobDisposition = .save → PDF page count, mediaBox, top-left pixel check. Skippable via ICCERY_SKIP_PRINT_PDF=1.

Gate

xcodebuild build test -scheme ICCery -destination 'platform=macOS' ARCHS="$(uname -m)" green locally. PDF harness: ran on host.

Part of #201.

## Summary Phase 3 of the M12 megaplan (#201): the raster decode + headless draw pipeline the native spooler (Phase 4) will drive. No spooling changes yet. - `TargetRaster.swift` — `TargetPageRaster` / `TargetRasterLoader` / `TargetRasterError`: TIFF decode via `CGImageSource`, DPI metadata with 72 dpi fallback + warn, DPI-derived `pointSize` (the only size the canvas draws at), manifest-drift check (>0.5 mm), and `deviceTagged(_:)` — re-tag into DeviceGray/DeviceRGB/DeviceCMYK reusing the source `dataProvider` (no resample, no bit-depth change, D10). Alpha relaxed per approved fix. - `TargetPageCanvasView.swift` — headless `NSView` for `NSPrintOperation`: flipped top-down page stack, `knowsPageRange`/`rectForPage`, top-left-anchored `destinationRect` snapped to 0.001 pt, `draw` with interpolation/antialias off and a `drawProbe` test seam. ## Tests - `TargetRasterFixtures.swift` — `makeTIFF(px:dpi:components:bitsPerComponent:)` via `CGImageDestination`. - `TargetRasterTests` — pointSize math, missing-DPI fallback, device-tag per layout (RGB-8/16, CMYK, Gray), pixel-byte equality, unsupported-layout rejection. - `TargetCanvasGeometryTests` — `rectForPage`/`destinationRect`, draw-flag assertions via offscreen `NSGraphicsContext`. - `NativeSpoolPDFTests` — real `NSPrintOperation` with `jobDisposition = .save` → PDF page count, mediaBox, top-left pixel check. Skippable via `ICCERY_SKIP_PRINT_PDF=1`. ## Gate `xcodebuild build test -scheme ICCery -destination 'platform=macOS' ARCHS="$(uname -m)"` green locally. PDF harness: ran on host. Part of #201.
gronod added 1 commit 2026-09-17 15:07:51 +01:00
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).
gronod merged commit de142a9690 into milestone/m12-native-spool 2026-09-17 15:08:08 +01:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: gronod/iccery-v2-mac#205