>_EXECUTIVE SUMMARY
zphoto is a single Rust engine that ports two Adobe products into one command surface. The raster side is a Photoshop / GIMP port — layers, masks, blend modes, smart objects, 444 commands across 19 groups, with an 8/16/32-bit (f32 working-space) pixel pipeline. The vector side is an Adobe Illustrator port — Bézier paths, gradients, meshes, patterns, Pathfinder, symbols, type, masks and SVG/PDF/AI/EPS round-trip, exposed through 114 vec.* commands — that rasterizes into the raster layer stack, so layer opacity, blend modes, masks, filters and PSD save all apply to vector artwork for free. Every number below is grepped from source, not estimated.
Photoshop port — PORT_CHECKLIST.md (347 rows, 346 in scope)
Illustrator port — VECTOR_CHECKLIST.md (120 rows, 119 in scope)
One engine test is currently red: pick_and_histogram_read_the_render (tests/engine.rs:646) still asserts that an out-of-bounds image.pick is an error, but the command was deliberately changed to return {"color": null} instead. The assertion is stale, not the engine.
01RASTER ENGINE — PHOTOSHOP / GIMP PORT
Unique group.verb dispatch arms grepped from zphoto-core/src/lib.rs. The feature matrix in PORT_CHECKLIST.md stands at 342 ✅ / 2 🚧 / 2 ⬜ / 1 N/A.
| Group | Cmds | Area |
|---|---|---|
| filter.* | 138 | Blur / sharpen / noise / distort / stylize neighbourhood + gallery filters |
| op.* | 80 | Point ops — curves, levels, hue/sat, exposure, adjustments, perceptual audits |
| layer.* | 65 | Layers, masks, blend modes, smart objects, groups, layer styles |
| image.* | 36 | New/open/save, mode & bit-depth convert, resize, crop, transform, colour table |
| select.* | 31 | Marquee, lasso, magic wand, refine, feather, grow/shrink, texture |
| paint.* | 24 | Brush, pencil, eraser, clone, smudge, dodge/burn, gradient |
| fill.* | 15 | Bucket, pattern, gradient, content-aware, fill layers, generative render |
| edit.* | 8 | Undo / redo / copy / paste / fade / history |
| action.* | 7 | Actions panel — record / replay macros |
| path.* | 6 | Pen paths, path ↔ selection, stroke path |
| comp / sampler | 10 | Layer comps + perceptual edit attribution; Info-panel colour samplers and their solve targets |
| program.* | 4 | Edit-program compiler (analyze / optimize / apply) and Constraint Solve |
| brush / channel / note / pattern / text / project | 20 | Brush presets, spot channels, notes, define pattern, type, native save/load |
| 19 groups | 444 | Raster command surface (excludes the 114 vec.* below) |
Precision: pixels carry an 8/16/32-bit depth over an f32 working space; image.convert changes depth; 16-bit PSD encode/decode round-trips. Remaining: a few advanced filters / niche adjustments (🚧/⬜); 32-bit PSD currently folds to 16-bit on save; native-project pixels persist at 8-bit (depth tag preserved).
02VECTOR ENGINE — ILLUSTRATOR PORT
114 vec.* commands · src/vector.rs 12,521 LOC · f64 geometry, anti-aliased rasterizer (4× vertical SSAA + analytic horizontal span coverage), non-zero & even-odd fill rules.
| Area | Status | What's implemented |
|---|---|---|
| Document / artboards | ✅ | New, layers, multiple artboards + per-artboard render (vec.artboard.add), guides |
| Drawing | ✅ | Rect/round-rect, ellipse, polygon, star, line, arc, spiral, grid, flare, pen (Bézier), pencil, blob brush, compound paths |
| Fill | ✅ | Solid, non-zero/even-odd, linear/radial gradients, gradient mesh, freeform gradient, pattern swatches, Live Paint |
| Stroke | ✅ | Width/colour, caps, real miter/bevel/round joins, dashes, gradient stroke, arrowheads, variable-width profiles |
| Transform / arrange | ✅ | Move/scale/rotate/shear/matrix, reflect, transform-each, 3D rotate / Extrude / Revolve, group/ungroup, z-order, align/distribute, radial / grid / mirror Repeat |
| Pathfinder | ✅ | Unite / Intersect / Minus / Exclude, Divide / Trim / Merge / Crop / Outline, Outline Stroke, Offset Path, Shape Builder |
| Type | ✅ | Point type, type-on-path, area type (word-wrap), threaded text, text wrap, change-case, Create Outlines |
| Masks / blend / effects | ✅ | Clipping mask, opacity mask, 29 per-object blend modes (the shared LayerMode set), Warp envelopes, mesh envelopes, Liquify, Free Distort, glow / scribble |
| Symbols | ✅ | Symbol registry + placed instances, Symbol Sprayer, Symbolism Shifter/Sizer/Spinner/Screener |
| File I/O | ✅ | SVG import + export (full round-trip), PDF / AI / EPS import + export, raster export, Image Trace, trim marks |
| 120 rows | 119 ✅ | 0 🚧 · 0 ⬜ · 1 N/A (Shape Builder's interactive region-pick is editor UI) |
03REMAINING
The ⬜ / 🚧 items left in the two checklists, plus the deliberate scope limits recorded in PRECISION_REFACTOR.md. VECTOR_CHECKLIST.md has none left — the Illustrator roadmap is closed.
Single-Channel Buffers (🚧)
BaseType GRAY desaturates and INDEXED carries a real editable colormap, but pixels stay RGBA-backed — there is no single-channel or index buffer behind either mode.
Tiled Buffer (⬜)
Layer pixels are a flat Vec<RgbaF>; GEGL-style tiling is an optimization left for later.
Progress Streaming (⬜)
Long-running ops complete atomically — no event sink emitting progress, as the sibling engines have.
GUI Polish Gate (🚧)
Terminal, hooks editor, file browser and the 27-locale catalogue are wired; the 18 i18n proof tests, shared-component tables and the rest of the haxor script surface are not.
32-bit PSD
32-bit documents fold to 16-bit channels on PSD save; 32-bit channel I/O is a follow-up.
High-Bit Project Persistence
The native .zpo format stores the document's depth but persists pixels at 8-bit, so older projects load unchanged.
16-bit PNG Export
PNG export still routes through the 8-bit image-crate path even for 16/32-bit documents.
Float Composite
Image::render() returns the 8-bit display composite; per-layer float precision lives in the layer buffers where the operations run.
?KEY DESIGN DECISIONS
Why the two ports share one engine.
Vectors Render Into Raster Layers
vec.render rasterizes each vector layer into a raster Layer, so the existing compositor — opacity, the 29 LayerMode blend modes, masks, filters, PSD/project save — applies to vector artwork with zero new code.
One Command Surface
Both engines dispatch through Engine::invoke(cmd, args). Raster is image.* / layer.* / op.* / filter.* / …; vector is vec.*. Hosts (Tauri, JUCE WebView, headless tests) talk to one transport.
f64 Geometry, f32 Pixels
Vector geometry is resolution-independent f64; the raster pipeline computes in an f32 working space and quantizes to the document's 8/16/32-bit grid per command.
Region-Trace Operators
Pathfinder, Offset Path, Outline Stroke, Create Outlines and Image Trace all reuse one mask → boundary-trace pipeline — exact for axis-aligned shapes, supersampled for curves.
SVG as Interchange
SVG export and import round-trip paths, shapes, gradients and text. AI files (PDF containers) route through zpdf-core.
Reused Glyph Rasterizer
Vector type renders through the same bundled-font text module the raster engine uses — no duplicate glyph code, and Create Outlines just traces its output.