100 Commits
Author SHA1 Message Date
Michael Higgins 616ab9d56a Merge branch 'storytold:main' into fix/6745-atn-event-mapping 2026-10-21 11:37:25 -04:00
Michael Higgins d0ceea9646 Merge branch 'storytold:main' into fix/7885-warp-surface-drag 2026-10-21 11:24:30 -04:00
Michael Higgins 837ad374ed Merge branch 'storytold:main' into fix/8049-alt-wheel-zoom 2026-10-21 11:24:17 -04:00
Michael Higgins 9344d466e4 Merge branch 'storytold:main' into fix/7582-clipboard-crash-guard 2026-10-21 11:24:06 -04:00
Michael Higgins 386f8941e7 Merge branch 'storytold:main' into fix/7568-cpu-canvas-crisp-100 2026-10-21 11:23:57 -04:00
Michael Higgins 7e7defd0fb Merge branch 'storytold:main' into fix/5712-artboard-pasteboard-hides-loose-layers 2026-10-21 11:23:13 -04:00
Michael Higgins 968d8db4e1 Merge branch 'storytold:main' into fix/7524-plugin-preview-px-scale 2026-10-21 11:22:01 -04:00
Michael Higgins 3ae0678678 Merge branch 'storytold:main' into fix/5745-auto-blend 2026-10-21 11:21:07 -04:00
Michael Higgins da307f8f17 Merge branch 'storytold:main' into fix/auto-blend-background-mask 2026-10-21 11:09:47 -04:00
Michael Higginsandcoderabbitai[bot] d781772ed8 Update crates/plugins/src/manifest.rs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-10-21 08:36:06 -04:00
Michael Higgins b05b641122 Merge branch 'storytold:main' into fix/5799-batch-same-format-raw 2026-10-19 19:34:48 -04:00
Michael Higgins 468b96d57d Merge branch 'storytold:main' into fix/321-new-document-color-profile 2026-10-19 19:34:27 -04:00
Michael Higgins d821cb99b4 Merge branch 'storytold:main' into fix/auto-blend-seamless-gain 2026-10-19 19:31:00 -04:00
Michael Higgins 16154d2cff Merge branch 'storytold:main' into fix/5712-artboard-pasteboard-hides-loose-layers 2026-10-19 16:42:55 -04:00
Michael Higgins 3b0f0a7ca4 Merge branch 'storytold:main' into fix/auto-blend-area-past-canvas 2026-10-19 16:04:58 -04:00
Michael Higgins 5a17d92f03 Modify resume action to discard result
Change resume action to ignore the result.
2026-10-19 15:51:30 -04:00
Michael Higginsandcoderabbitai[bot] 4a53af3598 Update crates/io/src/flat.rs
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-10-19 15:45:34 -04:00
Michael Higgins ceaac3dc25 Merge branch 'storytold:main' into fix/5806-displace-asks-for-map 2026-10-19 14:32:43 -04:00
Michael Higgins 7a8ec58e38 Merge branch 'storytold:main' into fix/6884-pen-tool 2026-10-19 14:32:11 -04:00
Michael Higgins a66e6ed0bb Merge branch 'storytold:main' into fix/5727-move-tool-offset-readout 2026-10-19 14:31:58 -04:00
Michael Higgins 2c96d9faa0 Merge branch 'storytold:main' into fix/2603-toolbar-click-without-hover 2026-10-19 14:31:41 -04:00
Michael Higgins fa9f11c7a7 Merge branch 'storytold:main' into fix/2095-android-menus 2026-10-19 14:31:10 -04:00
Michael Higgins c9889c8128 Merge branch 'storytold:main' into fix/6528-solo-restore-cache 2026-10-19 14:30:53 -04:00
Michael HigginsandClaude Opus 5.5 73b79953e6 Print: Save as PDF gets a Browse… button (#5328) (#7586)
Save as PDF was only a free text field, so saving a PDF meant typing a
full path by hand. Browse… opens the standard Save dialog (pick_save),
suggesting the document's name as a PDF, and puts the chosen path in the
field. file_ui::body now gets the dialog id so the answer can be written
back into the Print dialog on a later frame.

Refs storytold/photocraft#5328

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-19 14:19:28 -04:00
Michael Higgins 34b5754efd Merge branch 'storytold:main' into fix/6528-solo-restore-cache 2026-10-19 14:09:18 -04:00
Michael Higgins cd781bb25f Merge branch 'storytold:main' into fix/2095-android-menus 2026-10-19 14:08:55 -04:00
Michael Higgins e4546cc0bc Merge branch 'storytold:main' into fix/2603-toolbar-click-without-hover 2026-10-19 14:08:41 -04:00
Michael Higgins 5e14702c09 Merge branch 'storytold:main' into fix/6884-pen-tool 2026-10-19 14:08:22 -04:00
Michael Higgins 84a1bf37f2 Merge branch 'storytold:main' into fix/5806-displace-asks-for-map 2026-10-19 14:08:06 -04:00
Michael Higgins f9d883b5de Merge branch 'storytold:main' into fix/5727-move-tool-offset-readout 2026-10-19 14:06:54 -04:00
Michael HigginsandClaude Opus 5.5 ac78e0bbca Color Settings: the working-space menus list the installed profiles of their space (#6323) (#6359)
* Color Settings: the working-space menus list the installed profiles of their space (#6323)

Like Convert to Profile and Proof Setup, Edit › Color Settings' RGB, CMYK and Gray working-space
menus now list the profiles installed in the system after the built-ins, by description, so a
press condition (GRACoL, SWOP, FOGRA39) can be the CMYK working space as in Photoshop. Each menu
lists only profiles of its colour space; RGB lists display and colour-space profiles, not
scanner or printer ones. The engine already took .icc paths for these settings.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* rustfmt: format after merging main (CI Format step)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-19 13:04:38 -04:00
adbd40ef55 Actions: Photoshop Shadows/Highlights steps play (#5830) (#5854)
Imported actions stopped at Shadows/Highlights ("adaptCorrect has no
PhotoCraft equivalent yet"), although Image > Adjustments > Shadows/Highlights
exists. The step now maps to it both ways: shadowMode/highlightMode (amount,
width, radius), black/white clip, midtone contrast and colour correction,
each read as its char ID or string ID.

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-19 13:03:20 -04:00
Michael Higgins d90d4041df Merge branch 'main' into fix/5727-move-tool-offset-readout 2026-10-18 10:16:49 -04:00
Michael Higgins f43dac99f5 Merge branch 'main' into fix/5806-displace-asks-for-map 2026-10-18 10:16:44 -04:00
Michael Higgins cd3ef1444f Merge branch 'main' into fix/5799-batch-same-format-raw 2026-10-18 10:16:37 -04:00
Michael Higgins bb3c446fbd Merge branch 'main' into fix/5703-pen-make-selection 2026-10-18 10:16:22 -04:00
Michael Higgins be9672619f Merge branch 'main' into fix/321-new-document-color-profile 2026-10-18 10:16:00 -04:00
Michael Higgins 27260461e1 Merge branch 'main' into fix/iris-xe-texel-guard 2026-10-18 10:15:37 -04:00
Michael Higgins 01e1f3f126 Merge branch 'main' into fix/6744-deselect-noop 2026-10-18 10:15:32 -04:00
Michael Higgins 7ce7a347f8 Merge branch 'main' into fix/6563-layer-texture-oom 2026-10-18 10:15:26 -04:00
Michael Higgins 95f5a19a0a Merge branch 'main' into fix/6752-heic-hlg 2026-10-18 10:15:08 -04:00
Michael Higgins 49e1ae898b Merge branch 'main' into fix/4845-autohide-taskbar 2026-10-18 10:15:00 -04:00
Michael Higgins 76ce0aa217 Merge branch 'main' into fix/6745-atn-event-mapping 2026-10-18 10:14:51 -04:00
Michael Higgins f1cfdf40f5 Merge branch 'main' into fix/6528-solo-restore-cache 2026-10-18 10:14:45 -04:00
Michael Higgins e9c1232ce7 Merge branch 'main' into fix/2095-android-menus 2026-10-18 10:14:40 -04:00
Michael Higgins 1158c79c87 Merge branch 'main' into fix/6865-selection-not-dirty 2026-10-18 10:14:30 -04:00
Michael Higgins d7760fd7c4 Merge branch 'main' into fix/6884-pen-tool 2026-10-18 10:14:26 -04:00
Michael Higgins e8e745b7c2 Merge branch 'main' into fix/txt2-edited-object-6968 2026-10-18 10:14:21 -04:00
Michael Higgins 62f94d3f9f Merge branch 'storytold:main' into fix/5713-smoothing-pressure-follows-brush 2026-10-18 10:10:31 -04:00
Michael Higgins 8b3621fa92 Merge branch 'storytold:main' into fix/2603-toolbar-click-without-hover 2026-10-18 10:04:43 -04:00
Michael Higgins 43ad6f2990 Merge branch 'storytold:main' into fix/5884-delay-load-windows-data-pdf 2026-10-18 09:44:31 -04:00
Michael HigginsandClaude Opus 5.5 a914c58a63 fix(ui): wide ellipse for Elliptical Marquee, dashed C + brush for Quick Selection (#6875) (#6917)
The Elliptical Marquee used a dashed circle and Quick Selection a brush
inside a dashed circular arc, so the two read alike. Photoshop draws the
marquee as a horizontal ellipse and Quick Selection as a brush in an
upright dashed rounded C. New original ellipse-dashed.svg; quick-selection.svg
redrawn; tests check the ellipse is wider than tall and the C runs down
the left edge.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-18 03:34:42 -04:00
Michael HigginsandClaude Opus 5.5 0007cad01a Paste: an image pastes with Ctrl+V whichever key is let go first (#6329) (#6360)
With no text on the clipboard (an image copied from a browser, a file from Explorer) egui-winit
swallows the Ctrl+V press and sends only the V release; the paste then ran only when that release
still carried Ctrl. Letting go of Ctrl first, as many people do, pasted nothing, so Ctrl+V seemed
to need several tries. A V release whose press never arrived, after Ctrl was held and before any
other key, is now that swallowed Ctrl+V and pastes once. A plain V tap (the Move tool) and the
web build, which always gets the key-down, are unchanged.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-18 03:33:29 -04:00
Michael HigginsandClaude Opus 5.5 16774eea6f Twirl, Pinch and Spherize fill the inscribed ellipse (#5643) (#5871)
They acted inside a circle fitted to the bounds' shorter side, so on a wide
or tall image only a central disc changed. Like Photoshop's, they now act
inside the ellipse inscribed in the bounds (selection or layer), reaching all
four edges; square bounds are unchanged.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-18 03:33:04 -04:00
Michael HigginsandClaude Opus 5.5 c408c83a9f Pencil: a 1 px line paints the same pixels whichever end it starts from, at any Smoothing (#6336) (#6341)
The pixel-grid walker stepped between the pixels holding each segment's ends. Smoothing splits
a Shift-click line into pieces along it (so does the pointer on a Shift-drag), and snapping every
piece to its own pixels bent the line into a jagged staircase; rounding the half-pixel ties away
from zero also made the line depend on which end it started from. The walker now samples the
segment's own line at each column (or row) centre and resolves ties on the pixel grid, so the
pieces of a straight line paint exactly the pixels of the whole line, both ways.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-18 03:32:58 -04:00
Michael HigginsandClaude Opus 5.5 4d9f163c61 Linux: Reveal never hands xdg-open a file (#7166) (#7168)
Reveal in Finder on Linux opens the linked file's parent with xdg-open,
which launches whatever it is given. A link stored as `tool.jar/a.png`
names a file as its parent, so Reveal launched that file. Reveal now
refuses a parent that is not a folder.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-17 20:53:59 -06:00
Michael Higgins 72b4a8c0bf Merge branch 'storytold:main' into fix/5884-delay-load-windows-data-pdf 2026-10-17 22:27:05 -04:00
Michael Higgins 2e3aa8ded2 Merge branch 'main' into fix/5884-delay-load-windows-data-pdf 2026-10-17 18:17:21 -04:00
Michael HigginsandClaude Opus 5.5 1d65bd605b Web: Place Embedded and canvas drops place images (#5749) (#5817)
* Web: Place Embedded and canvas drops place images (#5749)

File > Place Embedded was disabled in the browser (the engine command reads a
path), though the menu path reads the picked file's bytes. Files dropped on
the canvas were always opened as new documents. The web shell now tracks the
drag position, and drops on the canvas are placed from their bytes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Format (cargo fmt)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Narrow to the web canvas-drop half: Place Embedded enablement landed in #5585

Drop the picker test that covered the part #5585 now owns.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-17 13:20:44 -07:00
Michael Higgins 4146d61b78 Merge branch 'storytold:main' into fix/6884-pen-tool 2026-10-17 13:36:48 -04:00
Michael Higgins cd9ec5c03e Merge branch 'storytold:main' into fix/6528-solo-restore-cache 2026-10-16 22:24:35 -04:00
Michael Higgins 476a0fc3ef Merge branch 'storytold:main' into fix/2603-toolbar-click-without-hover 2026-10-16 22:20:24 -04:00
Michael Higgins b9dda08d01 Merge branch 'storytold:main' into fix/6528-solo-restore-cache 2026-10-16 22:18:54 -04:00
Michael Higgins 81a4342b18 Merge branch 'storytold:main' into fix/6528-solo-restore-cache 2026-10-16 22:18:47 -04:00
Michael Higginsandahmedhosnypro 3722dfbc63 fix(ui): Arabic and Hebrew layer names and the title read right to left (#5159) (#5385)
egui places font runs left to right with no bidi reordering, so a right-to-left layer name showed every word correctly but in reversed order. bidi_text::visual puts a label into display order with the Unicode Bidirectional Algorithm (unicode-bidi, already in the tree via usvg): right-to-left words stay in logical order for the shaper, everything else in a right-to-left run is reversed around them and brackets are mirrored. The Layers panel's rows and the app-drawn title bar use it; the title keeps a left-to-right paragraph so '— PhotoCraft' stays at the right, and a long right-to-left name is cut at its logical end so its start survives. Display only: stored names and the OS title keep the logical text.

Fixes #5159.

Co-authored-by: ahmedhosnypro <[email protected]>
2026-10-16 17:36:06 -07:00
Michael Higgins 7072965705 Remove duplicate Cicp import from lib.rs 2026-10-16 20:31:17 -04:00
Michael Higgins d356513052 Merge branch 'storytold:main' into fix/6752-heic-hlg 2026-10-16 20:27:09 -04:00
Michael HigginsandClaude Opus 5.5 64520f645e Control channel: connections must authenticate within 10 s, however active (#4965) (#5229)
The only limit on an unauthenticated control connection was the 30 s
idle timeout, which starts again with every read. A local client that
kept sending bytes or blank lines without ever completing `auth` kept
its connection, and one of the 16 connection permits, for as long as it
liked; sixteen of them locked every other client out.

AuthDeadlineStream wraps the read half of a connection: until the
connection authenticates, reads fail once AUTH_DEADLINE (10 s) has
passed since it connected, and a blocking read waits no longer than
what is left. Both transports use it (the desktop app's control server
and the headless `photocraft-cli serve`). After `auth` succeeds only
the idle timeout applies, as before.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 13:39:19 -06:00
Michael HigginsandClaude Opus 5.5 b24c0360f1 Dependencies: require ruzstd 0.9.1 for RUSTSEC-2026-0344 (#4952) (#5225)
ruzstd before 0.9.1 lets a crafted zstd input under 128 KB allocate
several gigabytes at once. PhotoCraft decodes zstd when it opens .pcraft
and Affinity files, so such a file could end the process with an
out-of-memory abort.

Raise the minimum in both crates that use it and update the lockfile
from 0.9.0 to 0.9.1.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-15 13:37:56 -06:00
Michael Higgins 8c027ba257 Merge branch 'storytold:main' into fix/5863-cjk-menu-mnemonics 2026-10-15 11:49:58 -04:00
Michael Higgins 869c2a378d Merge branch 'storytold:main' into fix/5745-auto-blend 2026-10-15 09:40:34 -04:00
Michael Higgins 310c489996 Merge branch 'storytold:main' into fix/5799-batch-same-format-raw 2026-10-15 09:39:09 -04:00
Michael Higgins 0c959f10d4 Merge branch 'storytold:main' into fix/5713-smoothing-pressure-follows-brush 2026-10-15 09:37:28 -04:00
Michael Higgins f571673fc2 Merge branch 'storytold:main' into fix/5806-displace-asks-for-map 2026-10-15 09:34:15 -04:00
Michael Higgins 8251a722b9 Merge branch 'storytold:main' into fix/5727-move-tool-offset-readout 2026-10-15 09:34:00 -04:00
Michael HigginsandClaude Opus 5.5 0c5709e9bd Free Transform: shapes and paths stay on whole pixels (#5751) (#5841)
* Free Transform: shapes and paths stay on whole pixels (#5751)

With Snap Vector Tools and Transforms to Pixel Grid on, only the pointer was
rounded, and only while a shape tool was active. Under the Move tool, or with
a grab offset or a proportional scale, the box landed between pixels (a
rectangle dragged to 540 px came out 539.6). An upright box on a shape layer
or path now keeps whole-pixel edges whatever the tool.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Format (cargo fmt)

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:49:42 -04:00
Michael HigginsandClaude Opus 5.5 6729fa1e50 Layer Style: drag on the image to move a drop or inner shadow (#5701) (#5893)
As in Photoshop, with the Layer Style dialog on a Drop Shadow or Inner Shadow
page, dragging on the image moves the shadow: its offset follows the pointer
and is stored as the effect's angle and distance (whole degrees and pixels),
moving the shared global light angle when the effect uses it. Space and the
middle button still pan; colour pickers still sample.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:49:36 -04:00
Michael HigginsandClaude Opus 5.5 56d3b7f983 Pen and Path Selection: Delete deletes the finished work path (#5702) (#5732)
A finished work path is drawn whenever the Pen, Freeform Pen or Path
Selection tool is active, and it is saved with the document, as in
Photoshop. But once the path was finished, Delete/Backspace fell through
to Edit > Clear (the pixels under it), so the only ways to remove it were
the right-click Delete Path and the Paths panel, and it looked impossible
to delete.

With those tools, no path being drawn and the work path the one they
edit (no shape layer or targeted vector mask in front of it), an
unmodified Delete/Backspace now runs path.delete on the work path: one
undoable Delete Path step. Direct Selection and the Curvature Pen are
left alone, since Photoshop deletes their selected anchors, not the path.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:49:30 -04:00
Michael HigginsandClaude Opus 5.5 3fd787a2b5 Canvas: no scroll glide with Enable Animations off (#5721) (#5883)
Interface > Enable Animations off already made scroll areas jump straight
to their target, but the canvas still panned from egui's smoothed wheel
delta, gliding for several frames after each notch. With the preference off
a plain wheel scroll now moves the canvas by the whole notch in the frame it
arrives and stops there.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:48:37 -04:00
Michael HigginsandClaude Opus 5.5 f44d3b6f06 Brushes: dragging a preset to the list's edge scrolls the list (#5741) (#5862)
A preset, group or folder dragged in the Brushes panel or the Brush Preset
picker couldn't reach rows out of view: the list didn't scroll while
dragging, so the drag stopped at the last visible row. Holding the drag at
the list's top or bottom edge (or past it) now scrolls it, with the same
ramp as the Layers panel's row drags.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:48:26 -04:00
Michael HigginsandClaude Opus 5.5 b8e48d6d4c Filter dialogs: a Random button for seeds (#5710) (#5886)
Clouds, Difference Clouds, Add Noise, Fibers and the other seeded filters
exposed a seed number, but a new pattern meant typing a different one. A
Random button beside every seed field now picks a fresh seed, which the live
preview renders at once. "Random" gains its row in the zh-Hans, zh-Hant, ru,
fr and id catalogs, which claim complete coverage.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 23:48:20 -04:00
Michael HigginsandClaude Opus 5.5 3887d8f738 Title bar: dialogs no longer stop the window dragging on macOS (#5826) (#5860)
The overlay that keeps the title strip's free gap draggable under a dialog's
modal layer (#4913) only ran with the custom title bar. macOS keeps the OS
traffic lights over the app's own title strip (custom_titlebar is false), so
with the Embedded Profile Mismatch prompt or any dialog open the window could
not be moved. The overlay now runs whenever the strip is drawn.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 22:46:36 -04:00
Michael HigginsandClaude Opus 5.5 8e2c5ddb40 macOS: a bundled app keeps its own Dock icon (#5849) (#5879)
The main window set a runtime PNG icon everywhere. On macOS that replaces the
app bundle's PhotoCraft.icns in the Dock, so the system couldn't render it
in its own style (Liquid Glass and its tinted and dark variants). The runtime
icon is now skipped when running from an .app bundle; unbundled runs and the
Windows and Linux builds still set it.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 22:46:30 -04:00
Michael HigginsandClaude Opus 5.5 3aaffdde68 Adjustment layers: a live preview is never coarser than the screen (#5764) (#5778)
Dragging a Curves point (or any control) in the Properties panel of an
adjustment layer previews through `canvas::ensure_proxy_preview`, which
picked its downscale factor from the document size alone
(`proxy::preview_factor`): any document over 5 MP was drawn from a 2-5x
reduced copy at every zoom, so at 100 % the canvas turned blocky until
the mouse was released.

Cap the factor by the view's zoom with the rule the Image > Adjustments
dialogs already use (`adjust_preview::proxy_factor`: the proxy stays at
least at screen resolution) when the wgpu compositor can draw the
full-size document. At 50 % and closer the drag now shows the full-size
composite; zoomed out, the proxy still saves the work. Documents the GPU
compositor doesn't cover keep the old proxy (the full size would be a
CPU composite per change).

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 22:46:20 -04:00
Michael HigginsandClaude Opus 5.5 be4cadd83d Rulers: Alt-drag makes a guide of the other orientation (#5698) (#5885)
As in Photoshop, dragging a guide out of the top ruler with Alt/Option held
makes a vertical guide, and out of the left ruler a horizontal one; without
Alt each ruler makes its own kind, as before.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 22:46:15 -04:00
Michael HigginsandClaude Opus 5.5 f4351cb37c Drag and drop: PhotoCraft comes to the front after a drop (#5687) (#5894)
Files dropped from another app's window (a file manager) were imported, but
the source window stayed in front of PhotoCraft. The frame that takes a drop
now asks for focus, so PhotoCraft comes forward as Photoshop does.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 22:45:59 -04:00
Michael Higgins 5b026c1979 Merge branch 'storytold:main' into fix/5806-displace-asks-for-map 2026-10-14 20:16:07 -04:00
Michael Higgins 17d0a55baf Merge branch 'storytold:main' into fix/5727-move-tool-offset-readout 2026-10-14 20:07:58 -04:00
Michael Higgins 16a7ad1a02 Merge branch 'storytold:main' into fix/5713-smoothing-pressure-follows-brush 2026-10-14 20:04:26 -04:00
Michael Higgins 6ee457cc7a Merge branch 'storytold:main' into fix/5745-auto-blend 2026-10-14 20:02:14 -04:00
Michael Higgins 0f75495246 Merge branch 'storytold:main' into fix/5799-batch-same-format-raw 2026-10-14 19:50:22 -04:00
Michael HigginsandClaude Opus 5.5 7e94c507e9 Smart Objects: Curves preview no longer zooms in on a reduced proxy (#5766) (#5779)
Adjustments and filters on a smart object add a smart filter, so their live
preview re-renders the smart object from its source through its placement.
The preview runs on a proxy document scaled down by k (large documents), and
proxy_document scaled the smart object's cache but left its transform (and
perspective and filter mask) in full-size document coordinates. The re-render
then came out k times too large on the proxy canvas, so the object looked
zoomed in until OK committed the full-size result.

proxy_document now scales the placement and the filter mask with the proxy.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 15:04:19 -07:00
3ee78a368b Free Transform: the box is the selection, and the marching ants follow it (#5297) (#5337)
With a selection, ⌘T and the Move tool's Show Transform Controls framed the
layer's content clipped to the selection, so the box was smaller than the
marching ants wherever the layer did not fill the selection. The ants then
stayed where the selection started until the transform was applied.

- transform_frame / target_frame (engine): the box is the selection's own
  bounds when a selection limits the transform. transform_bounds is unchanged,
  so snapping and the command defaults are as before.
- The selection outline is drawn through the open box (homography, or the warp
  in Warp mode), so it follows move, scale, rotate, skew, distort, perspective
  and warp before the transform is applied. The whole outline is traced while
  such a box is open, not only the part in view where it started.
- marching_ants_lines: ants along screen-space lines; non-finite lines are
  skipped and very long ones are clipped to the view.

Part of #3402.


Claude-Session: https://claude.ai/code/session_015vKPoMXFhSvWmX5D9XM646

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-14 14:07:42 -04:00
Michael HigginsandClaude Opus 5.5 42c5cc64be Canvas: themes without a dot pattern draw no dots texture (#4542) (#5093)
* Canvas: themes without a dot pattern draw no dots texture (#4542)

Switching the dark theme to Pro filled the empty workspace with red and
black blocks on the reporter's machine. The blocks repeat every 22 px,
the tile of the canvas-surround dots texture, so it is that texture
showing wrong contents.

Pro and ten other themes set canvas_dot to their canvas colour: they
have no dot pattern, yet still uploaded a texture for it and tiled it
over the whole pasteboard. dots() now returns None for them, so nothing
is uploaded or drawn. Studio, Studio Light and Solarized Dark, whose
dots differ from the canvas, are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* Contributors: credit Higgs32584 by GitHub profile name

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 13:06:18 -04:00
Michael HigginsandClaude Opus 5.5 a37fa8171b GPU compositor: pattern textures are freed on close, when idle and over a budget (#4971) (#5232)
The compositor kept every pattern texture it ever uploaded (RGBA32F,
16 bytes per pixel) until the device was lost: `forget_doc` and
`retain_docs` skipped them and no budget applied, so a long session
that opened and closed documents with pattern fills or pattern effects
only ever grew.

Each cached pattern now records the document that last painted with it
and the frame it last painted in:

- closing a document (`forget_doc`, `retain_docs`) frees its patterns;
- a pattern no frame has painted with for 240 frames is dropped;
- over PATTERN_BUDGET (256 MiB) the least recently painted go first,
  never one the current frame paints with.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 12:45:52 -04:00
Michael HigginsandClaude Opus 5.5 b059a6d8b3 ICC parser: checked arithmetic on offsets and counts from the file (#4976) (#5227)
Offsets and counts stored in a profile reach u32::MAX, which is
usize::MAX on 32-bit targets such as wasm32. Several places added to or
multiplied them before any bounds check, so a malformed profile could
panic (overflow checks on) or read from a wrapped offset (checks off).

- curv: reject an over-long count before computing the element length.
- mAB/mBA: the matrix and CLUT read through one bounds-checked slice at
  the stored offset instead of adding to the offset.
- mluc: the record offset is computed with checked arithmetic.
- XYZ: one bounds-checked slice instead of off + 4 and off + 8.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 12:45:46 -04:00
Michael HigginsandClaude Opus 5.5 2388d82165 Docs: oracle floor, open issues, workspace size and layer filters match main (#5376) (#5382)
- ROADMAP.md: the oracle floor is 145 of 258 (crates/io/tests/corpus.rs,
  gaps.md G1), not 133 of 256; 953 open issues, not 579.
- docs/architecture.md: ~539,000 lines in ~1,310 files and ~8,040
  #[test] functions, recounted 2026-10-13.
- README.md: "a layer kind filter" instead of "layer filters"; only the
  Kind filter exists.
- AGENTS.md: drop an empty bullet at the end of section 7.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-14 01:58:22 -04:00
Michael HigginsandClaude Opus 5.5 c72dda1914 Assign Profile: list only profiles of the document's colour mode (#4951) (#5020)
The profile menu offered every built-in and installed profile, and picking
one of another colour space only produced "profile is Rgb; the document is
Cmyk" in the status bar. The menu now lists the profiles the command accepts
for the document's mode, and a remembered choice that doesn't fit falls back
to the working space.

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-13 12:11:56 -04:00
Michael HigginsandClaude Opus 5.5 6f9227efa3 Brush Settings: no section title above the options pane (#3477) (#5017)
* Brush Settings: no section title above the options pane (#3477)

The options pane repeated the selected section's name as a title line.
The selected row in the section list already names it, as in Photoshop,
so the title is gone and the options start at the top of the pane.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

* i18n test: the brush section name is drawn once, without a heading (#3477)

dynamic_brush_sections_have_translations_and_draw_in_the_selected_language
still expected the translated section name twice: the list row and the
options pane heading this branch removes. It now expects the row alone.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-13 12:01:40 -04:00
bf5d01b00d Layers panel: shape layers show a shape badge on their thumbnail (#4584) (#4619)
A shape layer's thumbnail shows its pixels like any other layer, so nothing
in the row said it was a vector shape. It now carries a badge in the
bottom-right corner, in the same frame as the smart-object badge: a path
with an anchor point on each corner.

Co-authored-by: Claude Opus 5.5 <[email protected]>
Co-authored-by: Brandon Thomas <[email protected]>
2026-10-13 01:14:14 -04:00