mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-30 04:47:09 -06:00
* Add the Patch tool (#213) paint.patch heals the selected area with texture from where the selection is dragged (Source) or copies the selection onto the dragged-to area (Destination), seamless-cloned like the Healing Brush. The solve is clipped to the canvas, so patches at the edge stay opaque. Tool::Patch joins the J group: outside the selection it draws a lasso (Shift/Alt add/subtract), inside it drags the patch, the outline follows the pointer and the offset is clamped to the canvas. Options bar: Source / Destination. Strings translated in all six catalogs. Tests at 8/16/32 bit, a UI gesture test, panic_hunt green. Scorecard TOOL-213-3 is partial: the drag previews the outline, not the pixels. retouch_bench: patch 250x250 22 ms, 1000x1000 362 ms (release). generated with Claude Code * Patch tool: live preview of the heal while dragging (#213) The canvas shows the document healed at the pointer's offset (patch_preview.rs, modelled on the Move tool's preview) and recomposites only the healed area; release commits the exact paint.patch and its damage rect refreshes the same area. The preview (retouch_cmds::patch_preview) solves the colour fit on a coarse grid (at most 128x128 cells) and interpolates it back: the Poisson result is source + a harmonic correction, so the texture stays exact and only the smooth correction is approximated (worst pixel 0.022 at 8x coarser in the test). Selection coverage is read tile-wise and the interpolation runs per row in parallel. retouch_bench (release, 6016x6016): preview 250x250 7 ms, 500x500 17 ms, 1000x1000 52 ms (exact patch: 21 / 90 / 354 ms). Scorecard TOOL-213-3 done. Also applies rustfmt to the first commit's code. generated with Claude Code * Patch tool: cap patches at 16M pixels, drop product names from comments (#213) The solve needs roughly 150 bytes per pixel, so the old 64M cap allowed about 10 GB and risked an allocation abort instead of an error. generated with Claude Code * Regenerate docs/scorecard.md Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Tool::ALL holds both the Patch tool and the Mixer Brush (rebase onto #433) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Brandon Thomas <echelon@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
217 lines
6.9 KiB
TOML
217 lines
6.9 KiB
TOML
# Scorecard checklist: tools (#213 painting and retouching, #214 selection, transform, drawing).
|
|
# An item is done when it has a command, a UI and tests.
|
|
# Statuses must be true on main. Verified against 4b53f62 on 2026-10-05.
|
|
area = "tools"
|
|
title = "Tools"
|
|
order = 3
|
|
|
|
[[item]]
|
|
id = "TOOL-213-1"
|
|
target = "Pencil tool: aliased 1 px painting, square pixel-aligned cursor"
|
|
status = "done"
|
|
issue = 213
|
|
note = "Tool::Pencil (B group): live aliased strokes on the pixel grid, square cursor, Auto Erase; pencil_tests.rs"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-2"
|
|
target = "Mixer Brush tool on the toolbar"
|
|
status = "done"
|
|
issue = 213
|
|
note = "Tool::MixerBrush in the Brush (B) flyout; Wet/Load/Mix/Flow/Sample All Layers options, command/control dispatch and selection-clipping tests"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-3"
|
|
target = "Patch tool with a live preview of the patched area"
|
|
status = "done"
|
|
issue = 213
|
|
note = "paint.patch (retouch_cmds/patch.rs, source/destination) + Tool::Patch (J group: lasso, then drag the selection); the drag shows the heal live (patch_preview.rs, coarse colour fit: 1000x1000 in 52 ms)"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-4"
|
|
target = "Content-Aware Move tool reusing inpaint completion"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "inpaint::complete only used by spot healing (retouch_cmds.rs:386)"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-5"
|
|
target = "Painting a type/shape/smart/fill layer offers to rasterize, then continues the stroke"
|
|
status = "done"
|
|
issue = 213
|
|
note = "rasterize_prompt.rs: OK rasterizes then paints (two history states), Cancel does nothing; drivable via ui.dialog.confirm"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-6"
|
|
target = "Fill dialog: contents, blend, opacity, preserve transparency; remembered; Shift+Backspace"
|
|
status = "done"
|
|
issue = 213
|
|
note = "fill_ui.rs dialog over edit.fill (fill_cmds.rs): all contents, mode, opacity, preserve; remembered in prefs; Shift+F5 / Shift+Backspace"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-7"
|
|
target = "Live stroke preview for every brush-based retouch tool"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "Live stroke only for Brush and Eraser (canvas.rs:1684)"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-8"
|
|
target = "Clone Source: W/H link, drawn overlay (opacity/blend/clip/auto-hide), Alt target cursor"
|
|
status = "partial"
|
|
issue = 213
|
|
note = "Panel W/H + overlay settings (preset_panels.rs:946-1015); no link, overlay never drawn"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-9"
|
|
target = "Eyedropper comparison ring (new colour above, current below) while sampling"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "sample_eyedropper (canvas.rs:1552) draws no ring"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-10"
|
|
target = "Ctrl+Alt drag resizes brush size/hardness with an on-canvas readout"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "Only [ ] resize (shortcuts.rs:270)"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-11"
|
|
target = "Editable pressure curve, global and per control"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "No pressure curve in engine, paint or ui-egui"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-12"
|
|
target = "Import an image file as a brush tip"
|
|
status = "missing"
|
|
issue = 213
|
|
note = "Only brush.defineFromSelection and brush.presets.importAbr"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-13"
|
|
target = "Brush regression tests: no seams, hard edge, zero-scatter defaults, ABR never black"
|
|
status = "partial"
|
|
issue = 213
|
|
note = "Missing-pattern ABR test (abr_map/tests.rs:181), hardness test; no seam/black tests"
|
|
|
|
[[item]]
|
|
id = "TOOL-213-14"
|
|
target = "Tablet: no OS arrow cursor over the canvas on macOS, Windows and Linux"
|
|
status = "partial"
|
|
issue = 213
|
|
note = "Brush tools set CursorIcon::None (canvas.rs:1259-1275); not verified per OS"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-1"
|
|
target = "Select and Mask workspace: view modes, Refine Edge brush, 6 outputs"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "Opens the generic select.refineEdge dialog (menus.rs:308)"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-2"
|
|
target = "Marquee: Shift square, Alt from centre, live W x H readout"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "marquee_end supports shift (chrome_ui.rs:167) but canvas.rs passes false (#208)"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-3"
|
|
target = "Color Range test: Sampled Colors at Fuzziness 0 selects the exact match only"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "Fuzziness-0 tests cover midtones/shadows only (selection_cmds.rs:444-447)"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-4"
|
|
target = "Move tool: box-select layers, Auto-Select hover outline, double-click fit, drag to a tab"
|
|
status = "missing"
|
|
issue = 214
|
|
note = "move_mods.rs covers Shift/Alt/arrows only"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-5"
|
|
target = "Right-click menu during Free Transform (scale, rotate, skew, warp, flip, rotate 90/180)"
|
|
status = "missing"
|
|
issue = 214
|
|
note = "No context menu in canvas.rs or transform_tool.rs"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-6"
|
|
target = "Puppet Warp mesh follows the object outline (constrained triangulation)"
|
|
status = "missing"
|
|
issue = 214
|
|
note = "algo/puppet.rs:136 builds a block-grid mesh"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-7"
|
|
target = "Content-Aware Scale through the Free Transform box with a live proxy preview"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "edit.contentAwareScale (edit_menu_cmds.rs:899) behind a parameter dialog"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-8"
|
|
target = "A measured ruler angle prefills Image Rotation > Arbitrary (0.01 deg)"
|
|
status = "missing"
|
|
issue = 214
|
|
note = "Arbitrary rotation is a generic dialog; ruler only feeds straighten"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-9"
|
|
target = "Crop: W x H x Resolution with units, saved crop presets, Straighten in the options bar"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "Ratio dropdown and fields only (panels.rs:551-579)"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-10"
|
|
target = "Pen: Alt breaks a handle, Shift 45 deg, Ctrl direct-selects, Backspace, close-drag handle"
|
|
status = "missing"
|
|
issue = 214
|
|
note = "pen_down gets no modifiers (canvas.rs:1632)"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-11"
|
|
target = "Stroke Path dialog: pick any brush-based tool, Simulate Pressure"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "path.stroke brush, pencil, eraser (vector_cmds.rs:1170); brush-only button, no dialog"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-12"
|
|
target = "Shapes: on-canvas corner radius handles, shape feather, selection to shape with tolerance"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "select.convertToShape with tolerance (vector_cmds.rs:1256); radius as a field only"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-13"
|
|
target = "Mask Properties: Density and Feather controls"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "Vector-mask density/feather in the engine (vector_cmds.rs:948); no UI controls"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-14"
|
|
target = "Vanishing Point window: draw and edit planes, paste, clone in perspective"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "filter.vanishingPoint (vp_cmds.rs:15) behind a parameter dialog"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-15"
|
|
target = "Content-Aware Fill workspace: paint the sampling area, preview, rotate/scale/mirror, new layer"
|
|
status = "partial"
|
|
issue = 214
|
|
note = "Engine sampling auto, rect, custom (edit_menu_cmds.rs:324); generic dialog"
|
|
|
|
[[item]]
|
|
id = "TOOL-214-16"
|
|
target = "Liquify: redo (Cmd+Shift+Z)"
|
|
status = "done"
|
|
issue = 214
|
|
note = "liquify_ui.rs supports bounded redo through Cmd+Shift+Z and the control channel; new strokes clear redo"
|