Commit Graph
3466 Commits
Author SHA1 Message Date
David MannandClaude Opus 5.5 8c184c78d5 Merge main into fix/smart-filter-last-mask
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:30:58 +02:00
David MannandClaude Opus 5.5 031e0de625 Merge main into feat/file-215-18-export-resample
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:29:28 +02:00
David MannandClaude Opus 5.5 c7bd182e91 Merge main into fix/lens-filters-smart-locks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:29:14 +02:00
skylar taylor-barrick f9ed9e3e57 ci: refresh timeout draft against current main 2026-10-15 16:27:05 +02:00
David MannandClaude Opus 5.5 5b0d7263e6 Merge main into fix/count-delete-group-active
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:25:43 +02:00
David MannandClaude Opus 5.5 9203a6857a Merge main into fix/adjust-smart-object-locks
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:23:49 +02:00
David MannandClaude Opus 5.5 01184b7083 Merge main into fix/video-fps-validate
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:20:48 +02:00
skylar taylor-barrick 4e7a17cd5d fix(compose): serialize effect identity cache misses
Keep effect-identity memo lookup, pure hashing and insertion atomic across concurrent render callers. Preserve existing identities and add a contention regression with eight synchronized callers.
2026-10-15 08:18:21 -06:00
David MannandClaude Opus 5.5 674340230c Merge main into feat/file-216-2-large-fixtures
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:16:28 +02:00
jonathnwxh e0ddefe7e0 test(text): retain raw TySh as the document importer does 2026-10-15 22:07:31 +08:00
jonathnwxh 2656f8db3d fix(text): preserve imported font records during text and style edits 2026-10-15 22:04:27 +08:00
jonathnwxh 70ffad5a56 test(text): retain imported font metadata after text edits 2026-10-15 22:01:09 +08:00
David MannandClaude Opus 5.5 daaeeda7c7 Merge main into docs/scorecard-stale-rows-2
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 16:00:11 +02:00
David Mann ecaa81b42a Merge branch 'main' into perf/p33-cmyk-dab 2026-10-15 15:57:57 +02:00
David Mann e240016fe4 Merge branch 'main' into fix/smart-filter-last-mask 2026-10-15 15:56:58 +02:00
David Mann 8b5ddbba91 Merge branch 'main' into fix/lens-filters-smart-locks 2026-10-15 15:56:52 +02:00
David Mann 3182414717 Merge branch 'main' into fix/count-delete-group-active 2026-10-15 15:55:59 +02:00
David Mann 6717d228a1 Merge branch 'main' into fix/adjust-smart-object-locks 2026-10-15 15:55:47 +02:00
David Mann ff26781bab Merge branch 'main' into fix/video-fps-validate 2026-10-15 15:55:38 +02:00
David Mann b693494237 Merge branch 'main' into fix/mask-from-transparency-bg-depth 2026-10-15 15:55:29 +02:00
David Mann 9fa9f86c48 Merge branch 'main' into fix/fill-layer-angle-finite 2026-10-15 15:55:12 +02:00
David Mann 8c524c9295 Merge branch 'main' into fix/lock-transparency-atop 2026-10-15 15:54:57 +02:00
David Mann 830676cc7d Merge branch 'main' into fix/multichannel-alpha 2026-10-15 15:54:46 +02:00
jonathanwxh-cell 6b3a6ffd8b Document conservative blend preview coverage
Explain why clip_damage replaces the covered intersection, including an
empty one, while retaining the affected region for uncovered to recompute.
This is a comment-only follow-up to review on storytold/photocraft#5413.

Existing controlled 24 MP release measurement: median refresh/upload-
submission time was 734.677 ms for the full 6000x4000 region and 59.641 ms
for a 1280x720 viewport, five measured samples per region after warmup.
This compares regions in the same candidate binary on CPU fallback with
Vulkan llvmpipe, not two revisions or physical-GPU completion latency.
Evidence: https://github.com/jonathanwxh-cell/photocraft/actions/runs/38512473874
2026-10-15 21:52:28 +08: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
David MannandClaude Opus 5.5 caa28cb7ab CI: run only the font tests in the craft-fonts pass (#6120)
The pass reran every test in the workspace, but CRAFT_FONTS is only read in photocraft-text,
photocraft-io (svg) and photocraft-ui-egui. The build selection stays the same (the disk warning
above still applies); a nextest filter runs those three packages' tests: ~3,800 of ~8,900.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 14:41:12 +02:00
David MannandClaude Opus 5.5 e22c4ec7ab CI: run the tests with cargo nextest (#6117)
cargo test runs the ~258 test binaries one at a time; nextest runs them in parallel. Its new `ci`
profile stops at the first failure (a red PR frees its runner early), fails a test that hangs for
10 minutes instead of letting it hold the runner, and repeats every failure at the end of the log;
the GPU test group still applies. Same --workspace --locked --features heif selection, so the build
is unchanged. Doctests stay on cargo test --doc.

postscript_only_style_shows_actual_subfamily relied on another test in the same process having
started the font scan; under nextest it runs alone, so it starts the scan itself (as #2933 does).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 14:40:15 +02:00
David MannandClaude Opus 5.5 9660dca263 CI: run clippy, layers and scorecard checks before the tests (#6119)
They take about 1.5 min together but ran after all the test passes, so a clippy failure (15 s)
showed red only 41-48 min into the job. Same steps, reordered: no cost on a green run.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 14:22:13 +02:00
David MannandClaude Opus 5.5 2ab37e7e55 Scorecard: regenerate after merging main (TOOL-214-12 done, #5846)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 14:06:00 +02:00
David MannandClaude Opus 5.5 8435a4586f History Brush source: snapshot sources, size check, purge and budget fixes
- Edit > Purge > Histories resets a state source to the default instead of
  leaving every document without one (History::clear).
- The pinned source state counts against the history byte budget first; the
  newest states fill what remains, so trimming stays within max_bytes.
- The History Brush and Fill > History refuse a source of another canvas size
  (after Crop, Canvas Size or Image Size) instead of painting shifted pixels.
- Snapshots can be the source: history.setSource {snapshot}, a source column on
  snapshot rows, HistorySource::State|Snapshot in the engine; deleting the
  snapshot leaves no source, Purge > Histories keeps it.
- paint.historyBrush and Fill > History take History panel rows for `state`
  (redo rows included), as history.setSource does, and accept `snapshot`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 13:58:10 +02:00
David MannandClaude Opus 5.5 e23840f516 History panel menu: review fixes (floating steps, cleared-state memory, clean undo, New Snapshot)
- Step Backward in the History panel puts a floating selection back like Edit > Undo; Step
  Forward and Edit > Redo put it back and step instead of dropping it first (which recorded a
  Move and wiped the redo states); with nothing to step to the piece keeps floating.
- Memory figures and the byte budget count the states Clear History keeps for its undo.
- Undoing Clear History keeps a saved document clean.
- New Snapshot... in the panel menu runs history.newSnapshot.
- Tests: Clear on one document leaves the others alone, and each fix above.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 13:57:54 +02:00
Muhammad Saad f116c3230a Retouch: guard every stroke command, not only Pattern Stamp (#6110)
Pattern Stamp was the only retouch command that refused a stroke it could not
render. Clone Stamp, Healing Brush, Spot Healing and Remove all reach the same
dense conversion: coverage is accumulated in tiles, but dense_coverage()
materialises the whole bounding box, and the retouch paths read a Region over
that box for every channel. The box comes from the stroke's own points, which
are validated against MAX_COORD rather than the document, so it is not bounded
by the canvas. Both allocations go through the infallible vec!, which aborts
instead of returning an error.

With the guards now shared in retouch_cmds, apply them to the rest:
reject_huge_stroke before anything is rendered, and reject_bounds before the
dense region read where the command can return one. spot_heal_surface returns a
Rect, so Spot Healing charges the stroke in the command; Remove builds a list,
so each stroke is charged as it is parsed.

The allowance is unchanged, so no stroke that worked before starts failing.

Test: every retouch stroke refuses the oversized box, leaves the pixels alone,
and still accepts a stroke across the whole canvas.
2026-10-15 15:47:38 +04:00
David Mann ce5af000f2 Merge remote-tracking branch 'origin/main' into fix/history-panel-menu 2026-10-15 13:03:07 +02:00
David Mann 2bc49845a7 Merge remote-tracking branch 'origin/main' into fix/history-brush-source 2026-10-15 13:03:04 +02:00
itsF4LCON d065c874e5 Merge remote-tracking branch 'upstream/main' into fix/5996-help-search-mnemonics 2026-10-15 12:58:26 +02:00
David Mann 43d8572c9f Merge remote-tracking branch 'origin/main' into feat/tool-214-12-shape-feather
# Conflicts:
#	docs/scorecard.md
#	docs/ui-parity.md
2026-10-15 12:12:20 +02:00
David Mann 9e532faa3a Merge remote-tracking branch 'origin/main' into fix/5559-bitmap-dialog
# Conflicts:
#	crates/ui-egui/src/i18n/cs.tsv
#	crates/ui-egui/src/i18n/de.tsv
#	crates/ui-egui/src/i18n/el.tsv
#	crates/ui-egui/src/i18n/es.tsv
#	crates/ui-egui/src/i18n/fr.tsv
#	crates/ui-egui/src/i18n/hu.tsv
#	crates/ui-egui/src/i18n/id.tsv
#	crates/ui-egui/src/i18n/it.tsv
#	crates/ui-egui/src/i18n/ja.tsv
#	crates/ui-egui/src/i18n/ko.tsv
#	crates/ui-egui/src/i18n/nl.tsv
#	crates/ui-egui/src/i18n/pl.tsv
#	crates/ui-egui/src/i18n/pt-br.tsv
#	crates/ui-egui/src/i18n/ru.tsv
#	crates/ui-egui/src/i18n/sr.tsv
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/i18n/uk.tsv
#	crates/ui-egui/src/i18n/vi.tsv
#	crates/ui-egui/src/i18n/zh-hans.tsv
#	crates/ui-egui/src/i18n/zh-hant.tsv
2026-10-15 11:55:20 +02:00
David MannandClaude Opus 5.5 24a86a3f6f Image: Bitmap dialog with Output resolution and per-method settings (#5559)
Image > Mode > Bitmap now opens a dialog laid out like Photoshop's:
Resolution (Input, read-only; Output in pixels/inch or pixels/centimeter),
Method (50% Threshold, Pattern Dither, Diffusion Dither, Halftone Screen,
Custom Pattern) with a pattern picker enabled for Custom Pattern, and the
Halftone Screen settings (Frequency, Angle, Shape) shown only for that method.

The image.mode.bitmap command gains `resolution` (resamples to the Output
resolution keeping the print size, then sets it) and the `customPattern`
method (threshold map ranked from the pattern's lightness, tiled from the
top-left). The halftone screen is laid out at the output resolution. The
live preview keeps the canvas size.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:54:35 +02:00
David MannandClaude Opus 5.5 869b2556d3 io: drop the Photoshop version from the gradient opacity comments (#1954)
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 11:49:50 +02:00
David Mann 09f782b1ff Merge remote-tracking branch 'origin/main' into fix/1954-overlay-opacity-stops 2026-10-15 11:37:40 +02:00
Finn Newick 093c6836c8 Merge remote-tracking branch 'origin/main' into refactor/engine-drop-note-insert 2026-10-15 10:37:03 +01:00
jonathnwxh e338761de9 Merge upstream CI test and web packaging fixes 2026-10-15 17:04:54 +08:00
Persi 5ad0b92aac Merge branch 'main' into psd-background-opaque-check 2026-10-15 10:09:43 +02:00
Brian TorresandClaude Sonnet 5.5 827e4e7094 Codecs: cap what tiff_exif::read copies from overlapping EXIF values (#5982)
An entry's value only has to lie inside the file, so many Exif entries can
point at the same bytes: a 62 KB TIFF with 1,000 such entries made the reader
copy 50 MB (and the block writer copy it again), on every TIFF import and on
export of a document carrying an EXIF block.

read() now has a copy budget shared by IFD0's descriptive tags and the GPS and
Exif directories: at most 4 MiB, and never more than the stream's own length,
since the values of a well-formed stream are distinct bytes of it. An entry
that does not fit is left out and later, smaller ones are still kept; the
small directories are read first so a huge maker note cannot crowd out the
GPS position. Maker notes of 200 KB and 1 MB round-trip as before.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rj8vs4QyUES3uwgX6SuGGh
2026-10-15 01:01:37 -07:00
Nigel Ihza Firdausy 35b4b30f2d style(path): keep regression cases consistently spaced 2026-10-15 15:00:44 +07:00
Nigel Ihza Firdausy caceb01dda test(path): cover invalid Make Selection params and open-path modes 2026-10-15 14:59:18 +07:00
Nigel Ihza Firdausy ec2627dbbb fix(path): validate Make Selection parameters before rasterization 2026-10-15 14:57:59 +07:00
itsF4LCON 116a607697 Window › Arrange: tiles keep their documents, and every tile has rulers (#6017)
With documents tiled side by side, a click into the other one moved it
to the first tile, swapping the two, and only the active tile showed
rulers. Each document now keeps its tile (with more documents than
tiles, the shown run slides just enough to include the active one), and
inactive tiles and floating windows draw their own document's rulers.
Guides and the zero point are still dragged in the active view.
2026-10-15 09:41:16 +02:00
itsF4LCON 510636b19c Type: Korean paragraph text wraps between words, not syllables (#5959)
Unicode's line-breaking rules allow a break between any two Hangul
syllables, so Korean box text split words (설 / 정이나). Korean is set
with breaks at the spaces between words, as Photoshop does: runs of
Hangul now lay out with WordBreak::KeepAll. Chinese and Japanese keep
breaking between characters.
2026-10-15 09:34:09 +02:00