Commit Graph
10642 Commits
Author SHA1 Message Date
Hector VillarrealandClaude Opus 5.5 fa5dfb3e19 Regenerate the parity checklist
Main added a Layer menu item of its own, so after the rebase the menu
counts 663 items; raise the floor to match.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 dee9cacba8 Copy CSS: wait for a pending Free Transform, as Save for Web does (CodeRabbit review on invoke.rs:90)
Free Transform keeps its box in a preview until it is committed; the
document's layers stay where they were. Layer › Copy CSS reads the
document, so with a box moved but not yet committed it put the old
left/top/width/height on the clipboard, not what the canvas showed.

Copy CSS now joins Save for Web (#6737) in the transform tool's guard:
the menu item is disabled under an open box, and any caller (menu,
shortcut, palette, control channel) gets "Commit or cancel the
transform first", with nothing copied and the box left open. After
Cancel it copies the old place, after a commit the new one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 0f6524ffbd Copy CSS: write no border-radius for an unequally scaled rounded rectangle (CodeRabbit review on layer_css_cmds.rs:144)
Scaled 200 % across and 100 % down, a live rounded rectangle keeps one
radius per corner (r times the smaller scale), while its path, which is
what renders, has r·sx by r·sy elliptical corners. The rule wrote the
single circular radius. It now writes border-radius only when the path's
anchors are the ones the live radii draw (in any order, so a flipped
shape still writes its corners); otherwise none, as the module doc says.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 13e7b0fe0e Copy CSS: test a rounded rectangle's border-radius after a 2x scale (CodeRabbit review on layer_css_cmds/tests.rs:165)
No test checked the copied border-radius after `shape.edit`'s
`transform` scales the live radii. With radii 12 and a uniform 2x scale
the rule now has to say `border-radius: 24px;`, so a regression in that
scaling fails the test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 1bdba8264d Copy CSS: write border-radius: 50% for a live ellipse (CodeRabbit review on layer_css_cmds.rs:147)
A solid live ellipse got the plain rectangle rule, so pasting it showed a
rectangle. It now writes `border-radius: 50%;` where a rounded rectangle
writes its radii, before the fill. The module doc lists it, and lists the
geometry of other shapes (live polygons, stars and lines, custom paths)
as not written.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 d4622f78f2 Copy CSS: test a comment closer in a name and a layer with a drop shadow (FredApps review)
A layer named `a */ b` writes no `*/` outside its quoted image name and a
sanitised class; a layer with a drop shadow writes the same rule as
without it, with no shadow and no panic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 64fa77d5a6 Copy CSS: say exactly what the module writes and what it doesn't (FredApps review)
The module doc said it writes CSS "as Photoshop writes it", but strokes,
layer effects, CSS gradients, blend modes and fill opacity are never
written. List what each kind of layer gives, in order, and what is left
out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 38337c8c6d Copy CSS: write a live rounded rectangle's border-radius (FredApps review)
A shape layer that is still a live rectangle with rounded corners now gets
`border-radius` before its fill, as Photoshop writes it: one value when all
four corners are equal, else top-left, top-right, bottom-right,
bottom-left, in px. Sharp rectangles write none.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 fc49818c58 Copy CSS: place paragraph text at its box and give it a size (CodeRabbit review on crates/engine/src/cmd/layer_css_cmds.rs:78)
Every type layer was written like point text: no width or height, placed at its first pixel.
Photoshop 2025 writes paragraph text differently. For a 200 × 120 box at (60, 40) whose two
lines span 156 × 51 px it writes `left: 59.937px; top: 36.948px; width: 156px; height: 51px;`:
placed at the box (within a few px, from its font metrics), moved down by an explicit leading
(36 px gives `top: 72.948px`), and sized by its text rather than the box (centred "Hi" in the
same box: `width: 19px; height: 17px;`). Do the same; point text keeps its position only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 fc66229188 Copy CSS: escape layer and font names in quoted values (CodeRabbit review on crates/engine/src/cmd/layer_css_cmds.rs:73)
A `"` in a layer name ended `url("…")` early, a backslash started an escape, and a `"` in a font
family was turned into `'`, which names another font. Write each name as a CSS string the way
CSSOM serializes one (`\"`, `\\`, hex escapes for control characters). Photoshop 2025 writes
these names unescaped (`url("Say "hi".png")`); ordinary names come out exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 69305189f0 Copy CSS: start class names that begin with a digit with _ (CodeRabbit review on crates/engine/src/cmd/layer_css_cmds.rs:37)
A layer named "2nd Box" gave `.2nd_Box`, which isn't a valid class selector. Photoshop 2025
writes `._2nd_Box`: it puts a `_` in front of a leading digit and turns a hyphen into `_` like
the other punctuation ("-2x" is `._2x`, "my-box" `.my_box`). Do the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
Hector VillarrealandClaude Opus 5.5 4cd60bc06b Layer › Copy CSS
Photoshop's Layer › Copy CSS puts CSS for the selected layers on the
clipboard. The new engine command layer.copyCSS writes each layer as a
class named after it (characters CSS doesn't allow become _): a type
layer's font size, family, colour, line height and alignment, a solid
fill or shape's background colour, or an image named after the layer;
then its opacity under 100 %, its absolute position and size (none for
type) and its z-index from the bottom, in Photoshop's format and order.
The Layer menu item copies the result to the clipboard.

Fixes #9372

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 23:23:58 -06:00
FredApps aae9b7ea61 Merge pull request #11647 from Triwarr/pdf
PDF: import pages as artboards, export a page per artboard (+ recursive group export)
2026-11-08 05:01:46 +01:00
Triwarr 2d16a609ea Merge remote-tracking branch 'origin/main' into pdf
# Conflicts:
#	docs/scorecard.md
2026-11-08 03:48:47 +01:00
David Mann e04ecbdaa3 Merge pull request #10448 from qvest-ssels/feat/export-last-folder-10192
Export dialogs start in the last exported folder (#10192)
2026-11-08 03:45:55 +01:00
David Mann fda05f7b02 Regenerate docs/scorecard.md (merge queue)
On main + #10448, so main's gate stays green after the merge.
2026-11-08 03:45:37 +01:00
David Mann 62776f4b58 Merge branch 'main' into feat/export-last-folder-10192 (merge queue) 2026-11-08 03:45:33 +01:00
David Mann 420a9364e6 Merge pull request #10222 from aethelisdev/fix-wayland-drag-and-drop
ui-egui: support native file drag and drop on Wayland
2026-11-08 03:44:16 +01:00
David Mann b30c5c8095 Merge pull request #12142 from hectorviov/fix/star-tool
Toolbar: Star Tool in the shape slot between Polygon and Line (#11377)
2026-11-08 02:56:14 +01:00
David Mann ed893ea812 Merge pull request #12188 from davidmann4/fix/11909-bg-eraser-tolerance-field
Background Eraser: Tolerance takes whole numbers 1-100 with an alert, bar tooltips (#11909)
2026-11-08 02:54:43 +01:00
David Mann f28cf95c88 Merge pull request #11921 from davidmann4/fix/11733-color-sampler-context-menu
Color Sampler: right-click menu on the canvas (#11733)
2026-11-08 02:51:57 +01:00
David Mann 02abef5983 Merge pull request #11920 from davidmann4/fix/11907-bg-eraser-digit-keys
Background Eraser: number keys set the Tolerance (#11907)
2026-11-08 02:50:02 +01:00
David Mann 4a7d746c0a Merge pull request #11823 from davidmann4/fix/11812-brush-opacity-minimum
Brush: opacity minimum 1 % and "00" sets 100 % (#11812)
2026-11-08 02:49:28 +01:00
Triwarr 3ef91ec45a PDF: widen the dense-page cancellation margin
Raise the synthetic page to a million strokes so the 45 ms watcher
threshold keeps a wide margin on an optimised test build, and record why
the importer keeps one RenderCache per page.
2026-11-08 02:41:37 +01:00
David Mann 4da02a98a6 Merge pull request #9975 from ljkx/feat/cli-metadata-option
CLI: --metadata none|all leaves document XMP out of convert, run --out and batch exports (#9466)
2026-11-08 02:40:35 +01:00
Triwarr 1df674997b PDF: cancel dense pages, complete page labels, isolate artboards
- render_page: forward Interrupt to craft-pdf through an owned flag and a
  scoped 5 ms watcher, so dense vector pages stop mid-render.
- Warn when craft-pdf reports a substituted font (the backend does not emit
  the flag yet).
- /PageLabels: emit an entry for every page, start at 0, and write no tree
  when every artboard name is empty.
- Export budget: charge retained page data plus the largest page's two f32
  buffers instead of the whole document canvas, saturating on overflow.
- Render each artboard from a document holding only its group, so
  overlapping boards no longer paint on each other's pages. One document
  shell is cloned and reused.
- Tests: dense-page cancellation, labels with an empty middle name and all
  empty, overlapping artboard pixels, sparse 9000x9000 canvas, seven US
  Letter pages.
2026-11-08 02:34:58 +01:00
David MannandClaude Opus 5.5 caae1c8a1f Address CodeRabbit review: close the sampler menu when its sampler changes
The Color Sampler menu kept only the sampler's index. If a control
command deleted an earlier sampler while the menu was open, the index
named another sampler and Delete removed that one. The menu now also
remembers the active document and the sampler's position; when either
no longer matches, Delete greys out and the menu closes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 02:19:35 +01:00
David Mann f27b78a75c Merge pull request #12080 from davidmann4/fix/cmyk-ref-rounding-tie
CMYK: the test reference keeps the source ink over nothing (#12079)
2026-11-08 01:52:54 +01:00
David Mann 9ac3fa22b2 Merge pull request #9280 from davidmann4/fix/crop-invalid-rect
Crop: refuse an invalid explicit rectangle instead of cropping to the selection (#9279)
2026-11-08 01:50:23 +01:00
David Mann 940b352ca0 Merge pull request #9256 from davidmann4/fix/scale-effects-bevel-texture
Scale Effects and Image Size scale Bevel & Emboss Texture's scale (#9254)
2026-11-08 01:50:08 +01:00
David Mann 2e9a1d267e Merge pull request #9233 from davidmann4/fix/crop-shift-letter-keys
Crop: Shift+H, Shift+P and Shift+I switch tools again (#9232)
2026-11-08 01:49:51 +01:00
David Mann 0059bd597e Merge pull request #3498 from davidmann4/feat/auto-219-8-panel-command-check
xtask: check that every panel button routes through a command id (#3495)
2026-11-08 01:48:45 +01:00
David Mann ce517049a7 Merge pull request #11221 from yoriswind/codex/transform-hit-zones-11097
Use whole-edge Free Transform handles and consistent rotate cursors
2026-11-08 01:41:27 +01:00
David Mann 5c1b628973 Merge pull request #9970 from ljkx/feat/photo-filter-last-settings
Photo Filter opens at its last settings (#9879)
2026-11-08 01:40:42 +01:00
50b877645f Merge origin/main into feat/cli-metadata-option (#9975)
Conflicts with main's --no-maximize-compatibility (#8064) in the CLI
export args, output mapping and dev-dependencies, and in the
file-format parity status line and revision history: both sides kept.

Co-Authored-By: ljkx <ljkx@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 01:26:47 +01:00
Triwarr 0525197133 Merge remote-tracking branch 'origin/main' into pdf
# Conflicts:
#	docs/scorecard.md
2026-11-08 01:09:29 +01:00
David MannandClaude Opus 5.5 4750447f23 Floor an imported brush's opacity at 1 % when it is selected
Importing an .abr with select picked its first brush without the 1 %
opacity floor, so a preset saved at 0 % showed 1 % but painted nothing
(#11812).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 01:03:17 +01:00
David MannandClaude Opus 5.5 6547fadccd Floor a restored brush's opacity at 1 %
A brush remembered at 0 % opacity (saved before the 1 % floor) read back
at 0: the options bar showed 1 % but strokes painted nothing. Restoring
now floors opacity at 1 %, like tools.setBrush (#11812).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 01:24:18 +00:00
David Mann 1d9c654b3a Merge remote-tracking branch 'origin/main' into fix/11812-brush-opacity-minimum 2026-11-08 00:57:07 +00:00
David Mann 3aa1d9f432 Merge pull request #12164 from ElNeMeR70/fix/patch-sample-all-layers-default-on-12125
Patch tool: start Content-Aware Sample All Layers on (#12125)
2026-11-08 00:41:59 +01:00
Hector VillarrealandClaude Opus 5.5 fe13a8acc3 Star Tool test: the star layer keeps the tool's fill and stroke (maintainer suggestion)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 17:41:12 -06:00
Hector Villarreal de9e11df9b Toolbar: Star Tool in the shape slot between Polygon and Line (#11377) 2026-11-07 17:32:45 -06:00
47e14b5da2 Photo Filter keeps only Preserve Luminosity from its last OK (#9970)
#9970 reopened Image > Adjustments > Photo Filter... at the filter, colour,
density and Preserve Luminosity of its last OK. Measured in the reference
application: after OK at 60, 70 and 74 %, with a preset or with Color and a
custom colour, it reopens every time at Warming Filter (85), the orange
swatch and 25 %; only Preserve Luminosity carries over (off after an OK with
it off, on after an OK with it on). Opening now starts from the neutral
settings and takes just that one value from the last OK; Alt still reopens
at all the last settings (#8900). Tests and the ui-parity row follow the
measured behaviour.

Co-Authored-By: ljkx <177671075+ljkx@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 00:30:59 +01:00
David Mann 153fcff8c3 Merge pull request #7121 from texjer/feat/camera-raw-sidecars
Camera Raw: Done saves the raws' settings to their sidecars without opening them
2026-11-08 00:30:42 +01:00
David Mann 36a754da5c Merge pull request #12173 from hectorviov/fix/sampler-drag-gestures
Color Sampler: a new point lands where the drag ends, markers follow the pointer, a click on a point moves it, Escape cancels (#11729)
2026-11-08 00:30:07 +01:00
David Mann 15be79be5e Merge pull request #9058 from Gotya-OFFCIAL/raw-hasselblad-3fr
raw: decode Hasselblad 3FR/FFF (X2D II 100C, uncompressed)
2026-11-08 00:29:05 +01:00
David Mann be26364ebc Merge pull request #12093 from yoriswind/codex/count-psd-resource-11759
Preserve Count groups in PSD resource 1080
2026-11-08 00:28:20 +01:00
David MannandClaude Opus 5.5 e6992a855d Background Eraser: a Tolerance set elsewhere wins over an interrupted edit (#11909)
The typed-text draft remembers the setting it was stored with and is only
used while that setting is unchanged, so a value set meanwhile (a tool
preset while the options bar was hidden) shows from the first frame.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 00:17:09 +01:00
David Mann 2da9714b74 Merge origin/main into feat/photo-filter-last-settings
# Conflicts:
#	crates/ui-egui/src/panels/smart_ui.rs
#	docs/ui-parity.md
2026-11-08 00:16:29 +01:00
David Mann 49eabafbcb Merge pull request #11238 from NaufalDzz/layer-filter-find-layers
Select › Find Layers opens the Layers panel's Name filter (#10884)
2026-11-08 00:13:30 +01:00