Add all measured naming components, nested starting serial, compatibility flags, complete-step refusal for unknown settings and exact descriptor retention. Keep literal text and extension placement separate from image encoding, and preserve the legacy native template, save snapshots and output protections. Reuse only the serial-letter helper from #4579 by @FabioLissi at 720a1e4b9c, with Adobe's independent letter counter. Unsupported Batch routing and Alias forms remain explicit gaps; combined validation is pending.
Adapt only Custom from #10631 by @hectorviov at 4ed3f5b591 and Fibers from #10620 at 33ee38b431. Retain the measured ranges and whole unsupported descriptors without importing unrelated filters. Source and fixtures only; combined validation remains.
Port the ten backend, automation and test paths from #5493 by
@jonathanwxh-cell, pinned at 43920ab780.
Keep its original CSH codec, bounded preset reader and protection tests.
The prerequisite's UI, translation and parity-document changes are excluded.
Adapt ShapePreset construction to retain the exact source identifier. Empty
identifiers remain anonymous presets; repeated identifiers resolve when their
geometry is identical and refuse resolution when it conflicts. Add one
import-to-ATN Shape Blur regression and document the source attribution.
Original contribution: https://github.com/storytold/photocraft/pull/5493
Source-only integration; compilation and combined runtime validation remain.
Every remaining event recorded in the reference application through its
menus: Scale Effects, Create Layers, Frame and Artboards, all eleven
Stack Modes with their plug-in codes, video layer and frame commands,
Create Work Path, Find and Replace, Check Spelling, measurement scale
and Scale Marker, Close All, data sets (apply, import, export), Package,
Video Frames to Layers, Import Notes, Photomerge, Crop and Straighten
Photos, Conditional Mode Change and Fit Image. Close Others and Define
Variables record nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured in the reference application: Batch source and destination keys
(open documents, Save and Close, override Open and Save As, suppress open
options), file naming output (the extension component only gets a dot as
the last component), processing order, flat output with subfolders, name
clashes, stop and log error modes with the log file format, and Esc.
What a normal recording names (layers by name, merged nudges and typing,
document offsets) and how it plays on another document. Trace Contour's
recorded keys and its 0..255 level; Quick Export records no step.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured in the reference application through its dialogs and recorded
actions: Shear point ranges and what ShrS/ShrE mean, the classic and the
new Gradient tool steps, Content-Aware Fill, Perspective Warp, Print,
Create Droplet and Sky Replacement descriptors, the mmdd/ddmm Batch date
components, and every layer comp reference form. Export As records no
step; Convert Stroke to Fill was not available in the measured version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Stream PSD user and real masks into tile rows
* Correct streamed-mask fixture metadata and test lint issues
* Budget PSD pattern expansion and bound multichannel conversion
---------
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Addresses CodeRabbit on #10603: the Group A intro said every Filter Gallery effect loads as a
kept step, but Spatter is mapped; Custom's scale, offset and matrix cells now have their
measured ranges and the matrix has no default (a step carries all 25 cells).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Recorded in the reference application through its menus and read back from the saved Actions
panel, or returned by the dialog on OK: Custom, Fibers, Displace (with ranges), Color Lookup,
Shape Blur, Lighting Effects, Blur Gallery, Liquify, Camera Raw Filter, Vanishing Point,
Calculations; how Image Size, Canvas Size, Convert Mode and New Group are recorded. The Batch
descriptor with its file naming components, and the Actions panel menu and Playback Options.
Known gaps gain four rows: Convert Mode is saved with an enum the reference application
rejects, adjustment layer opacity on Make, Canvas Size in percent, Image Size in cm/inches.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Known gaps: every exported step of the round-trip test was played in the reference
application (128 of 151 ran); six codes the mapping writes are wrong there (Vibrance and
Gradient Map events, Stroke Outside, Pass Through, canvas extension colour, Absolute
Colorimetric), and a document offset wraps around there.
- Reference forms: layers and documents by index, id, offset and ordinal, measured.
- Newer events: 63 candidates from the menu catalogue run in the reference application;
which need no settings, which were measured with settings, which need their dialog.
- Version 12 files: the older descriptor layout, checked on 325 real sets.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The contract tests no longer compiled on main (AtnItem::dictionary is now
Vec<u8>, so it is compared with b"Future event"), sat outside main's
tests/it layout, and the new atn.yml added six legs (two macOS) to every
PR against ci.yml's policy. Move the tests into tests/it so the existing
CI runs them, drop atn.yml and docs/atn-testing.md, keep main's ci.yml and
fuzz target, and note the committed fixtures in ATTRIBUTION.md.
Co-authored-by: denstu473 <63150090+denstu473@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Bound PSD import pixel storage before decoding
* Include ZIP inflater workspace in PSD preflight
* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)
* Stream PSD user and real masks into tile rows
* Correct streamed-mask fixture metadata and test lint issues
---------
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Every mapped event was checked against the reference application: the corpus sets'
5 296 recorded steps and factory descriptors went through Load and Save Actions and were
compared with the original, and the forms PhotoCraft writes were played there. The new
section lists the settings mapped events still lose (transform reference point, show
only this layer, group names, clipping and colour labels on Make, shape layers, layer
via copy options, load selection from another layer, Background by property, Close that
asks, Lab Photo Filter colours) and the settings the commands do not have yet.
The supported table showed 15 direct adjustment events with shifted columns.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Bound PSD import pixel storage before decoding
* Include ZIP inflater workspace in PSD preflight
* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)
Importing an .abr or .grd whose name matched an existing group silently
deleted that group's user presets (edited or moved-in ones included); the
preset libraries are outside document history, so it could not be undone.
- brush.presets.importAbr / gradient.presets.importGrd: `replace` now
defaults to false; a taken group name imports beside it as "Kit (2)",
"Kit (3)"…, and the result's `group` names the one it landed in.
- UI: when the group already holds the user's presets, a prompt asks
Import as New Group (default) / Replace (can't be undone) / Cancel.
Agents drive it with ui.dialog.set {"choice":"replace"} / confirm / cancel.
- The status bar names the group the file landed in.
Fixes#10640
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The supported table read the command list of the next entry for an event whose
list is a constant: Filter Gallery (`GEfc`) maps to `filter.gallery.spatter`, not
Shadows/Highlights. The table now resolves constants and reads each entry alone.
- Steps measured in a prepared document (Fade, Replace Color, Trap, selection
combinations, ...) show the example values that were sent, labelled as such, not
as factory defaults.
- Mosaic cell size: write `#Pxl`, read a value without a unit as pixels.
- Custom: no factory matrix; the test matrix is no longer shown as defaults.
- Intro: kept steps with no document effect are imported switched off and skipped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/atn.md lists the 117 events PhotoCraft maps today and, for 101 events it does
not map yet, every key the step carries in recorded order, with type, unit, factory
default, exact range and accepted enum values, measured in the reference application.
An implementation needs no further checks there. Linked from file-format-parity.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#4985 added a canvas Shift+right-click popup that worked only for the
Brush and listed only its painting modes. In the reference application
Shift+right-click opens a menu for every painting tool: Edit Brush…
(the Brush Preset picker a plain right-click opens), a separator, then
the tool's own Mode list from its options bar:
- Brush, Pencil: the painting modes with Behind and Clear
- Clone Stamp, Pattern Stamp, History Brush: the blend modes
- Mixer Brush, Color Replacement, Background Eraser: Edit Brush… only
- Eraser: Brush / Pencil / Block (no Edit Brush…)
- Blur, Sharpen, Smudge: Edit Brush… (the reference lists modes too)
- Dodge, Burn: Shadows / Midtones / Highlights; Sponge: Desaturate /
Saturate
- Healing Brush: its blend modes; Gradient: the blend modes; Paint
Bucket: the blend modes with Clear (no Edit Brush…)
- Spot Healing, Magic Eraser and non-painting tools: no menu, the
gesture keeps its old route
brush_mode_menu.rs is now a per-tool item list (Item enum + items(tool))
instead of a Brush-only list. Each row sets exactly what the tool's
options-bar control sets: a brush-based tool's mode through
tools.setBrush (Brush/Pencil also Behind and their own Clear flag), the
Eraser mode, tone range, sponge mode, gradient and bucket modes as tool
options. Blend modes are grouped with separators; the current choice is
checked; Behind and Clear are greyed on the Background layer. The menu
remembers the tool that opened it and closes on a tool change.
Only settings the options bar already has are offered. Not offered yet
(no setting here): Behind for the stamps, History Brush, Gradient and
Paint Bucket; the Blur/Sharpen/Smudge modes; the Spot Healing modes;
the Healing Brush's Sampled/Pattern source and Replace; the History
Brush source.
Control: ui.inspect's brushModeMenu reports tool, mode, choices (the
active tool's labels) and items (label/enabled/checked, separators);
ui.context.choose {id: <label>} picks a row, an unknown or greyed row
is an error that changes nothing.
Tests (kittest): each representative tool's rows in order, choosing a
row sets the options-bar state and journal, Edit Brush… opens the
picker at the click, Behind/Clear greyed on the Background, Magic
Eraser and Spot Healing open nothing; control graceful failure for bad
choices. "Edit Brush…" added to every catalog.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The swatches that now open the full Color Picker changed only on OK, so Photo Filter, B&W Tint,
Gradient Map stops (Properties and Image > Adjustments), the Content-Aware Fill and Select and Mask
overlays, Neon Glow and Save for Web lost the live preview main's popup had. The open picker now
previews its colour on the swatch every frame, Cancel (or OK unchanged) restores the exact opening
value (bit-exact for linear floats), and the Properties panel commits one history step when the
picker closes. A picker closed without OK or a preview changes nothing (a Gradient Map stop at a
PSD's 1229/4096 kept its location on Cancel).
With no document open, the options-bar popover's Color Picker refused OK ("no document open")
before reaching the tool-only path; it now sets the next shape's colour as on main.
A popover swatch the shape refused (a job holding the document) still joined Recently Used Colors;
it now joins only after the edit succeeds. Adds a CAF keys test for an open widget picker, and
fixes the ui-parity date and count the main merge set back.
Co-authored-by: SimoneRecchia <201361065+SimoneRecchia@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#6236 made Escape put back the colour the gesture started from. In the
reference application Escape while the right button is held closes the
HUD and keeps the colour picked so far; moving the pointer afterwards
changes nothing (measured: picked 0,40,96 from 40,90,160; after Esc and
a further move it stayed 0,40,96, also after the release).
Escape now ends the gesture like the button release does. The pick is
still one coalesced history step, so Undo takes it back.
Test: Escape closes the HUD with the picked colour kept, a later move
picks nothing, and releasing the button afterwards opens nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#6236 drew the hue strip left of the saturation/value square and opened
the HUD just below the press point. In the reference application the
square is on the left with the hue strip to its right, and the HUD opens
so the colour you start from sits under the pointer: pressing without
moving changes nothing, and a small move nudges the colour from there.
The HUD now uses that layout and placement (still pulled in to stay on
screen near an edge). The rects come from one `layout` function, shared
by drawing, hit-testing and the tests.
Tests: the square is left of the strip and the starting colour's spot is
under the pointer; a mid colour opens with the pointer inside the square
and picks nothing until it moves; near the bottom-right corner the HUD
stays on screen and the press alone picks nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>