Commit Graph
3466 Commits
Author SHA1 Message Date
David Mann 19d69fd2c7 Merge main into feat/file-215-2-other 2026-10-20 16:52:07 +02:00
David Mann f5c78f7419 Merge main into feat/file-215-2-stylize-pixelate 2026-10-20 16:47:59 +02:00
David MannandClaude Opus 5.5 2f96260c99 Crop: the rotated target-size sampler test expects the turned pixel (10, 9) doubled (#7012)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 16:45:42 +02:00
Thang Nguyen f8d5345a30 fix(psd): write split warps back as quiltWarp
Reading `quiltWarp` left the save path behind, so two warps didn't survive
save and reopen:

- A split warp was written as `warpNone` while `Trnf` was the image of its
  control-point box, so the layer came back stretched and shifted.
- A template's `quiltWarp` was kept when `warp` was rewritten, and reading
  prefers it, so a warp changed to Arc, to none or to another mesh came back
  as the imported split.

`SoLd` now writes a split warp as Photoshop does: a `quiltWarp`
(`deformNumCols` x `deformNumRows` control points, the patch boundaries in
`quiltSliceX` / `quiltSliceY`) before a `warpNone` `warp`. An imported
`quiltWarp` stays as stored while the layer's warp is unchanged, keeps its
slices (Photoshop's units and padding) when the mesh is edited on the same
grid, and is rewritten or dropped otherwise. `PlLd`, which has no split
warp, stores none, with its corners framed by the source rect.
2026-10-20 21:43:56 +07:00
David Mann 7d4f756d2c Merge main into feat/file-215-2-sharpen-noise 2026-10-20 16:36:42 +02:00
David Mann 8aaf526108 Merge main into feat/file-215-18-export-resample 2026-10-20 16:36:25 +02:00
David Mann a738fcb9fe Merge remote-tracking branch 'origin/main' into HEAD 2026-10-20 16:34:25 +02:00
NetterSilverandClaude Opus 5.5 760109e23c fix(psd): give a new Txt2 object its own style and a number past the file's objects
A new object kept the template's style runs, and PhotoCraft's reader takes
font features from Txt2, so a new type layer came back with the template
layer's features (salt, ss01). Its style runs are now generated like the
stub's; only the template's structure is copied.

New type layers were numbered past the kept TextIndex values only, so after
deleting the layer with the highest index a new layer landed on its object
and took its style. They are now numbered past the file's Txt2 objects too.

txt2_extras_survive_a_resave_of_unchanged_text now gives its layer the TySh
index a file's layer has; without one the layer is new and no longer lands
on object 0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 15:57:10 +02:00
Derek GliwaandClaude Opus 5.5 d53101c9a1 Brushes: keep the 512 MiB .abr cap on 32-bit targets
On wasm32 a near-1 GiB .abr arrives as base64 and is copied several times
before decoding; with a 1 GiB sample budget the import could pass 4 GiB and
abort the tab instead of failing cleanly. Pick the decoder budget by pointer
width (like MAX_DECODED_BYTES) and derive the engine's file cap from it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:53:55 -05:00
Rene Leonhardt a686a932c0 perf(compose): reuse bounded scratch and tone tables
Reuse tile scratch and tone tables across rendering work. Skip fully masked
adjustments and identity float curves. Previous-path tests preserve output
across sample depths, masks and clipping.
2026-10-20 15:52:44 +02:00
Derek Gliwa 4992a4305e Merge remote-tracking branch 'upstream/main' into abr-1gib-limit 2026-10-20 08:35:56 -05:00
David MannandClaude Opus 5.5 11d3026eeb Merge main into feat/file-215-2-blur
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:13:56 +02:00
David MannandClaude Opus 5.5 e05142c450 Merge main into feat/file-215-2-noparam
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:11:38 +02:00
Brandon ThomasandClaude Opus 5.5 46e538b3a2 Release 0.11.1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.11.1
2026-10-20 08:47:46 -04:00
Brandon ThomasandClaude Opus 5.5 8ede07b096 Format: build on FreeBSD (rustix has no xattr calls there)
The 0.11.0 release's FreeBSD job failed: copy_xattrs used rustix's
fsetxattr/flistxattr/fgetxattr, which rustix offers only on Linux,
Android and Apple systems. The real copy is now gated to those, and
other Unix systems get a no-op copy_xattrs, as Windows has. The xattr
tests are gated the same way; the Unix mode test now also checks that
no temporary file is left behind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:47:42 -04:00
Brandon ThomasandClaude Opus 5.5 cd79a5a9e8 Release 0.11.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 08:23:58 -04:00
ha1des 472a8d6f29 Preserve near-black ICC colors on the GPU canvas 2026-10-20 14:18:00 +02:00
NetterSilverandClaude Opus 5.5 304f055021 fix(psd): point a new Txt2 object's frame strike at its own frame
new_object copied the template's rendered strikes, whose frame strike
(/99 /F) still named the template's frame in /10. It now names the new
object's frame, like the view's /0.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 14:04:33 +02:00
Korg1ch 09749739ad test(io): a PSB's lnk2/pths/cinf are written as 8B64 with an 8-byte length (#7937) 2026-10-20 13:38:41 +03:00
Korg1ch c706938bde fix(io): PSB writes 8-byte-length global blocks with the 8B64 signature (#7937) 2026-10-20 13:38:07 +03:00
Anim86 8fc62f55ab fix(tablet): support stylus barrel button and brush resize on Windows (#5905, #5364)
On Windows with Windows Ink (WM_POINTER), winit drops penFlags (PEN_FLAG_BARREL) and reports stylus contact as WindowEvent::Touch, which egui-winit maps exclusively to PointerButton::Primary. Additionally, Windows Ink does not update GetAsyncKeyState(VK_RBUTTON) when pressing the pen barrel button. Consequently, Alt + Barrel Button drag was recognized as Alt + Left Drag (triggering the eyedropper and painting strokes instead of brush resize), and right-clicks with the stylus were treated as left-clicks.

This commit resolves the issue by:
1. Adding a native Windows message hook (WH_GETMESSAGE) in crates/tablet/src/windows.rs calling GetPointerPenInfo to intercept PEN_FLAG_BARREL (0x00000001) and POINTER_FLAG_SECONDBUTTON.
2. Exposing 
ight_button_down in Services combining the pointer hook and GetAsyncKeyState(VK_RBUTTON).
3. Updating canvas.rs and paint_mouse.rs to prevent strokes_live and alt_eyedropper from hijacking the stylus gesture when the barrel button is held, and correctly routing resize events.
4. Adding tests asserting that Alt + stylus barrel drag resizes diameter horizontally and adjusts hardness vertically without triggering eyedropper or painting.
2026-10-20 11:17:58 +02:00
NetterSilverandClaude Opus 5.5 78cc36f24a fix(psd): keep preserved TextIndex values when a type layer is added below them
Text indices were assigned in one bottom-up pass, so a new layer took the
next free number before the layers above it claimed the numbers their TySh
keeps. Each of those was then renumbered onto its neighbour's Txt2 object
and took its style (70 of 74 layers on the #7698 file after adding a layer
at index 5). Kept numbers are now claimed first and new layers get numbers
past them.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-20 10:51:26 +02:00
fjamespriceandClaude Opus 5.5 2eb68c7872 fix(camera-raw): a later preview frame clears a worker failure from the status bar
A failed proxy develop on the worker set the status error, and nothing took
it down once a later develop succeeded. The dialog now remembers the message
and the preview revision it failed on, and clears the status when a newer
frame is published, unless something else has reported since.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 04:39:28 -04:00
fjamespriceandClaude Opus 5.5 c57947d6d8 test(camera-raw): settle() fails when the proxy worker's develop fails
poll_render clears the pending develop before it reports the worker's
error, so previewPending turned false with no new frame and settle()
returned as if one had landed. It now fails with the status message
when the dialog reported an error. With the worker forced to fail, all
21 scope tests passed before this change; now the one that settles
after a worker develop fails with "the Camera Raw preview worker
failed".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 00:44:33 -04:00
jonathanwxh-cell 8f4db4bc4f fix: integrate latest upstream and preserve editable clipboard copies 2026-10-20 11:50:34 +08:00
Korg1ch e92e5164a8 test(io): an indexed GIF keeps its table and transparent entry; malformed GIFs give no table (#7886) 2026-10-20 06:18:48 +03:00
jonathanwxh-cell 40130ae99e fix: reconcile PR with upstream changes 2026-10-20 11:16:40 +08:00
aiongg 03d0c7e3b3 Merge pull request #7823 from aiongg/integration-5
Integration batch: 8 PRs on main
2026-10-19 23:11:09 -04:00
fjamespriceandClaude Opus 5.5 bdf2e6cb31 test(camera-raw): wait for the proxy worker before recording a revision
The dialog's own controls develop the preview on a worker (#5964), so after
the scope tone drags its last frame could land after the test recorded
previewRevision and bump it during the hover check that must not re-render.
A settle() helper waits until previewPending is false; the fixture and the
drag test call it before taking a baseline.

With a 20 ms delay added to the worker, the old test failed 9 of 10 runs
with the reviewer's assertion; with settle() all 21 tests passed 10 of 10.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:02:04 -04:00
fjamespriceandClaude Opus 5.5 eafc410ce2 contributors: credit fjamesprice by GitHub profile name
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:02:04 -04:00
fjamespriceandClaude Opus 5.5 f708151c91 perf(camera-raw): develop the preview off the UI thread (#5964)
The Camera Raw dialog developed its preview proxy on the UI thread at the
start of every frame after a control changed. With Shadows or Highlights
set that develop takes 190-250 ms on a 24 MP document (858x572 proxy), so
each frame of a slider drag blocked for that long.

The dialog's own controls now hand the develop, histogram and display
conversion to a worker. One runs at a time; settings changed meanwhile are
developed when it finishes, and the preview shows the latest finished
frame. The control channel and the first frame still render on the UI
thread so a reply describes its own settings, and such a render drops any
worker still running with older settings. The wasm build keeps rendering
synchronously. describe() reports previewPending.

Release build, 6000x4000 document, 20 Highlights/Shadows edits:
worst UI frame 237 ms before, 35.5 ms after.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:01:57 -04:00
Korg1ch 04a2169b44 fix(io): an indexed GIF opens in Indexed Color with its colour table (#7886) 2026-10-20 05:45:16 +03:00
Michael Higgins b05b641122 Merge branch 'storytold:main' into fix/5799-batch-same-format-raw 2026-10-19 19:34:48 -04:00
jonathnwxh 28f27f5a11 Index imported font metadata fallback by name 2026-10-20 07:14:09 +08:00
Hector VillarrealandClaude Opus 5.5 a2f63703a1 Re-run CI
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 16:28:29 -06:00
WolfandClaude Opus 5.5 f8117a535c Print: a turn takes settings and paper from one answer (#7847 review)
The Orientation buttons stored the turned settings from file.print.page
and then asked the driver again (driver_page) for the paper. If that
second query failed, the dialog kept the new settings with the old paper.
take_turned_page now takes both, and the orientation, from the one
answer; an answer without both leaves the dialog as it was and shows why.

The no-driver test used "00ff", which fails when the settings are read,
before any printer is asked, so it never tested the failed-driver path.
It now uses valid settings (a minimal DEVMODEW) and asserts the error
comes from the printer, not from reading the settings; with "00ff" it
fails. a_turn_takes_settings_and_paper_together covers the success path
and partial answers.

Reported by CodeRabbit in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:54:46 +02:00
Ernie SmithandClaude Sonnet 5.5 53effe3c83 Review: keep the missing-adapter note, and forward the override in CPU mode
- A requested adapter that couldn't be used, followed by a software window
  adapter, lost its System Info note to the software-graphics message. Append
  instead of replacing.
- PHOTOCRAFT_GPU_ADAPTER only forces its own process when startup acts on it
  (Linux, outside CPU mode); in CPU mode it is ignored, so the launch may
  still go to the running window.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:31:57 -04:00
Gert Pellin 3f3d61a7ae Merge branch 'main' into feat/4814-psd-palette-modes 2026-10-19 22:27:21 +02:00
Ernie SmithandClaude Sonnet 5.5 0e97ac4ca8 Make adapter choice Linux-only everywhere, not just the dropdown
The Preferences row was Linux-only, but PHOTOCRAFT_GPU_ADAPTER and
performance.gpuAdapter were honoured on every platform, so Windows and macOS
could pick a non-default adapter without being tested for it. Ignore the
request off Linux (and in CPU mode, as before), and don't make a launch
standalone for a variable that is ignored there.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:19:51 -04:00
Ernie SmithandClaude Sonnet 5.5 2644d06081 Review: rustfmt, cap the env adapter name, docs in their own paragraph
- cargo fmt on the adapter selection and its launch code.
- PHOTOCRAFT_GPU_ADAPTER is capped at 256 characters like the saved preference.
- Put the multi-GPU paragraph in docs/development.md on its own instead of
  appending to the --safe-gpu paragraph, so the diff only adds lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-19 16:07:04 -04:00
WolfandClaude Opus 5.5 2f08860383 Print: Portrait and Landscape in the Print dialog on Windows
On Windows the Print dialog takes the paper and its orientation from the
printer driver, and had no way to change the orientation short of the
driver's own Print Settings… dialog. Photoshop has Layout buttons for it.
A print laid out landscape on portrait driver settings (from a script,
the CLI or another app) stopped with "the driver paper or orientation
differs from the print layout".

- The dialog has an Orientation row (Portrait, Landscape) under Print
  Settings…. It turns the driver settings through file.print.page and
  takes the paper from the driver again, so the paper and preview turn.
- file.print.page takes "orientation": "portrait|landscape" and returns
  the turned settings as printerSettings, with the page they give.
- print_windows turns the settings (the given ones or the printer's
  defaults) to the layout's orientation when the driver has the layout's
  paper the other way round; another paper is still refused.

Turning sets dmOrientation and its dmFields bit in the DEVMODE and keeps
every other byte, the driver's private settings included; the driver
validates the result as it does settings from Print Settings…. No new
UI strings: "Orientation", "Portrait" and "Landscape" are in every
catalog.

Tests: the turned settings (orientation set, all else kept, with and
without private driver bytes), when a paper counts as turned, an unknown
orientation refused before any printer is asked, the dialog's reading of
the driver paper and its error path, and, run by hand on Windows, a
real "Microsoft Print to PDF" driver turning for a landscape layout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 21:46:41 +02:00
aiongg 46f7e2422e Integration: drop #7690's benchmark report, as #7690 did before it merged 2026-10-19 18:41:15 +00:00
Michael Higgins 7a8ec58e38 Merge branch 'storytold:main' into fix/6884-pen-tool 2026-10-19 14:32:11 -04:00
Brandon ThomasandClaude Opus 5.5 3a896a5efc docs: regenerate the scorecard (Show File Name In Title adds a preference) (#7829)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:23:47 -04:00
d5c7edacdf Layered TIFF: write PSD-style layer data unless a length overflows (Photoshop opened only the composite) (#5514)
The layered TIFF writer let the PSD exporter pick PSB from its size estimate, which counts every
layer plane uncompressed. A document with many canvas-sized layers passes 2 GB there while its
real layer data is a small fraction of it (a 3000×3441 mockup with 180 layers: estimate ~2.57 GB,
real data ~111 MB), so tag 37724 got the PSB-style header ("Adobe Photoshop Document Data
V0002", 8-byte lengths). Photoshop does not read that in a TIFF: it opens only the composite, as
one locked Background.

PsdExportOptions gains `size_limit_psb` (default true, .psd saves unchanged). The layered TIFF
turns it off and writes PSD-style data ("Document Data Block"), falling back to PSB only past
30000 px, when forced, or when a length really overflows 32 bits.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-19 14:21:01 -04:00
Marco Arnulfo 4f15642ee8 Toolbar: Edit Toolbar, Quick Mask and Screen Mode in every theme (part of #4653) (#4680) 2026-10-19 14:20:48 -04:00
David MannandClaude Opus 5.5 e306bcd685 Crop: a turned crop rotates only what the frame keeps (#5006) (#5007)
A turned crop rotated the whole canvas, then cropped to the frame. With
Delete Cropped Pixels on, every layer, mask and channel is now trimmed to
the frame's source (plus the interpolation kernel's reach) before the
turn, so the rotation costs the frame's size: a 512x442 frame turned 3°
on a 3859x2594 two-layer document goes from 541 ms to 42 ms.

Rotate Canvas also fills the Background with shared tiles instead of a
canvas-sized float buffer.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-19 14:20:42 -04:00
MarekSpodBiedry 1a03735cc6 fix(engine): apply document-wide image and colour conversions to stored video frames (#4956) (#5078) 2026-10-19 14:20:35 -04:00
Nicolas FalesyandClaude Opus 5.5 8bed609ef0 Flatpak on Wayland: say why a paste finds nothing, and how to paste anyway (#5031) (#5279)
In a Flatpak on Wayland, arboard can't open at all: the sandbox hides the
data-control protocol from it, and --socket=fallback-x11 gives no X server
while a compositor runs. Paste then reported "the clipboard holds no image"
even when it held one. Now the clipboard service reports that it had no
clipboard to read, and the paste shows a notice that explains it and gives
the XWayland command for this install.

Also adds my contributors/people.toml entry.


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

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 14:20:29 -04:00
Persi f5af2f3ef5 PSD export: check the Background's opacity from its tiles (#5998) 2026-10-19 14:20:22 -04:00