Commit Graph
188 Commits
Author SHA1 Message Date
aiongg 360150dcd4 Merge pull request #7281 from wanikhawar/claude/blur-tool-lag-684245
perf(retouch): releasing a Blur/Smudge/Dodge stroke takes its live pixels
2026-10-24 11:13:32 -04:00
David Mann 2b0deddec2 Merge remote-tracking branch 'origin/main' into integration-batch-7
# Conflicts:
#	crates/ui-egui/src/panels.rs
2026-10-24 00:51:37 +02:00
Omar SaidahmedandBrandon Thomas afd5127dc8 perf: skip redundant smart object resamples and per-pixel reads (#6406)
* skip redundant smart object resamples and per-pixel reads

* resample smart objects only when their re-render fails

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-23 18:36:54 -04:00
Perchenko AntonandBrandon Thomas f3941972df fix(actions): preserve scalar Selective Color settings in ATN export (#7681)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-23 18:34:54 -04:00
David Mann 9c5a7b907a Merge remote-tracking branch 'origin/main' into integration-batch-7
# Conflicts:
#	crates/ui-egui/src/i18n/tr.tsv
#	docs/ui-parity.md
2026-10-24 00:34:11 +02:00
5750ed40f9 Fix pasted shape group bounds and effects across documents (#8992)
* fix(clipboard): render copied shapes in destination canvas space

When a copied shape group is placed beyond its source canvas, rebuild its vector caches against the destination canvas and pixel format. Previously a centered paste into a larger document could clip the caches to an empty source-sized frame, leaving no transform bounds and incorrect effects until a point edit refreshed each shape.

Restore missing shape caches and refresh source-clipped caches when canvas dimensions change. Cover Paste and Copy to Document, nested group contents, 8/16-bit destinations, rendered cache equality, transform bounds and movement Undo.

* fix(clipboard): measure shape placement before destination clipping

Restore missing source-space shape caches before measuring copy bounds, then adapt and translate for the destination. Re-render empty caches when shapes move back onto the canvas instead of shifting an empty raster.

Add focused integration coverage for 32 combinations of partial and full destination clipping, grouped shapes, missing caches, 8/16-bit output, centered and point placement, and Undo/Redo. Clippy and WASM checks pass.

---------

Co-authored-by: kotulsky <7805437+kotulsky@users.noreply.github.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-23 17:54:26 -04:00
Zuujis 4bda8d7388 test(panic_hunt): give the panic-counting self-test its own deadline (#8473)
contained_panics_count_and_graceful_errors_do_not used the 4 s hang
budget meant for fuzzed commands. With RUST_BACKTRACE=1 the panic hook
prints a backtrace, and on loaded Windows runners the first symbol
lookup took long enough (19.6 s) that run_watched returned None instead
of Some(false). The self-test now waits up to 120 s; the fuzz keeps 4 s.
2026-10-23 17:40:32 -04:00
aiongg 7aaa59712a Merge main into integration-batch-7 2026-10-23 20:37:05 +00:00
aiongg 18f4b5348c Tests: spread three format-by-geometry matrices over the days, and build one precheck state per case
The tilt-shift reference tests and tiled_clear_and_fill_match_one_pass_over_the_area cross pixel
formats or channel counts with independent geometry and fill settings. Each run takes a quarter of
the combinations through Sweep, a different quarter each UTC day.

precheck_agrees_with_execute built all five document states for every call and kept one; it now
builds only the state the call needs.
2026-10-23 08:30:48 +00:00
David Mann 24051914fd Merge PR #6352: fix(engine): honor lock all on layer mask commands 2026-10-22 23:40:15 +02:00
David Mann 6e4d89d13d Merge PR #8473: test(panic_hunt): give the panic-counting self-test its own deadline 2026-10-22 23:40:12 +02:00
edea110601 Integration: refuse Paste Into a Lock-All group before pasting (#6352)
With the mask commands now honouring Lock All, Paste Into / Paste Outside with a
child of a Lock-All group active committed edit.paste and then failed on the
refused layer.layerMask.revealAll, leaving an unmasked pasted layer behind an
Err. paste_into now checks the destination group's locks first and refuses
cleanly. Test: mask_lock_all::paste_into_a_lock_all_group_refuses_before_pasting
(layer count and history unchanged). Also moves mask_lock_all.rs into main's
one-binary tests/it layout.

Co-authored-by: osaidahmed <170216456+osaidahmed@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-22 20:52:59 +02:00
David Mann 9095272487 Integration: merge main (#6352) 2026-10-22 20:38:21 +02:00
aiongg ffa400c754 Keep tests correct and docs current with one test binary per crate
- gpu: the test modules share one GPU_LOCK, and timing and vector_mask
  take it too, so one process drives one wgpu device at a time.
- ui-egui: the wgpu tests in pattern_preview_canvas, adjust_preview_gpu,
  marquee_autoscroll and layout_perf take gpu_lock().
- affinity compound_limits: the child process selects its test by the
  module path (compound_limits::<name>); with --exact, the bare name
  matches no test and the child passes without running the check.
- xtask scorecard reads crates/io/tests/it/corpus.rs.
- Docs and comments name the new test paths and the --test it filters.
2026-10-22 16:55:34 +00:00
aiongg a6428d3dfb Build each crate's integration tests as one binary
Every tests/*.rs file is its own executable that links the whole crate
graph. Move each crate's test files into tests/it/ as modules of one
tests/it/main.rs; helper modules under tests/common move with them.

These keep their own binary (own process):
- engine panic_hunt: a process-wide panic hook counts every panic.
- engine text_gamma: changes the process-wide text gamma.
- engine smart_filter_stages, mask_cache_purge: assert on global caches.
- codecs pnm_peak_memory: reads the process's peak RSS.
- photocraft mac_menu_appkit: harness = false.
2026-10-22 16:55:34 +00:00
aiongg f618cdea29 Integration: #8371 the .atn corpus round trip merges the per-property Sets that Save now writes 2026-10-22 15:39:49 +00:00
aiongg 2496742eaa Integration: merge main
Merges main through #3283 (Smart Filters: distinct editors, shared
disclosure and stable alpha).

filter_dialog.rs: main's split of the preview into is_smart_edit,
smart_preview_factor and scale_preview_params is kept. The plug-in branch
from #7524 (plugin_cmds::scale_for_preview scales only declared pixel
lengths) moved into scale_preview_params, so it applies to a plug-in run
on its own and to a plug-in recorded as a smart filter.

smart_ui.rs open_editor: main's smart_filter_dialog::target flow and the
shared adjust/filter dialog opening are kept; the Liquify re-open with
recorded strokes (r4) stays ahead of it. The old per-adjustment
edit_filter call is dropped with main's rewrite.
2026-10-22 15:39:28 +00:00
aiongg f72c3c2187 Integration: track t08
# Conflicts:
#	crates/ui-egui/src/camera_raw_ui.rs
#	crates/ui-egui/src/jobs_ui.rs
#	crates/ui-egui/src/widgets.rs
#	docs/file-format-parity.md
#	docs/gaps.md
2026-10-22 15:38:23 +00:00
aiongg 446b74a8de Integration: track t07
# 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
#	crates/ui-egui/src/layer_shortcut_tests.rs
2026-10-22 15:38:21 +00:00
aiongg 9c7cc91f82 Integration: track t05
# Conflicts:
#	crates/ui-egui/src/i18n/tr.tsv
#	crates/ui-egui/src/shortcuts.rs
#	docs/ui-parity.md
2026-10-22 15:38:18 +00:00
aiongg 1f0177f23c Integration: track t04
# Conflicts:
#	ATTRIBUTION.md
#	contributors/people.toml
#	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
#	docs/gaps.md
2026-10-22 15:38:17 +00:00
aiongg 4d1b922ddf Integration: track t02
# Conflicts:
#	contributors/people.toml
#	crates/engine/src/file_cmds/tests.rs
#	crates/engine/src/print_cmds/tests.rs
#	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-22 15:38:14 +00:00
aiongg 9172ad7525 Merge PR #7215: Corrective Camera Raw - fix(import/camera-raw): preserve document identity across asynchronous opens and re-develop 2026-10-22 15:37:37 +00:00
zuujiscom afa4cc7964 test(panic_hunt): give the panic-counting self-test its own deadline
contained_panics_count_and_graceful_errors_do_not used the 4 s hang
budget meant for fuzzed commands. With RUST_BACKTRACE=1 the panic hook
prints a backtrace, and on loaded Windows runners the first symbol
lookup took long enough (19.6 s) that run_watched returned None instead
of Some(false). The self-test now waits up to 120 s; the fuzz keeps 4 s.
2026-10-22 00:53:45 -05:00
skylar taylor-barrick f4cff2780c test(retouch): name live dab replay regressions by behavior 2026-10-22 08:16:51 +05:30
skylar taylor-barrick 0635061b86 fix(retouch): preserve Smudge pickup through live stroke release 2026-10-22 08:16:51 +05:30
aiongg 02c9e32d1d Merge PR #8088: fix(type): resolve exact PostScript names in type.create 2026-10-22 02:26:06 +00:00
aiongg ff2ba37278 Merge PR #8353: Scale shape strokes when resizing for Export As
crates/ui-egui/src/export_dialog.rs: tests appended by both sides; kept both whole.
2026-10-22 02:23:59 +00:00
aiongg d8acd0579a Integration: #7976 bound the ';' search in xml_unescape to 13 bytes
A long run of '&' without a nearby ';' scanned to the end of the string for every '&' (quadratic). Adds a test with a 200k-ampersand description.
2026-10-22 02:23:17 +00:00
aiongg 9a9aab3bb3 Merge PR #7976: Decode numeric character references in File Info XMP text 2026-10-22 02:23:01 +00:00
aiongg 2d74af4c8e Merge PR #7721: fix(actions): refuse lossy fractional Crystallize ATN export
crates/engine/src/atn_cmds.rs: kept main's fields_from/fields_to doc comments and range-checked Kind::Long arm; one ExactLong definition (main's); Ripple Amnt stays ExactLong and Crystallize ClSz becomes ExactLong.
2026-10-22 02:22:59 +00:00
aiongg 4502ff75d6 Merge PR #6457: fix(engine): keep comps, slices and variables when converting to a smart object 2026-10-22 02:22:01 +00:00
aiongg 4484a07a5c Merge PR #6440: fix(engine): convert the background and match mask depth where they were missed 2026-10-22 02:22:00 +00:00
aiongg 4a3d69ac74 Merge PR #6455: fix(engine): match smart object re-renders to the document's mode and depth 2026-10-22 02:21:58 +00:00
aiongg 61adf55731 Merge PR #6433: fix(engine): keep the rendering of smart filters that cannot be reproduced 2026-10-22 02:21:56 +00:00
aiongg 3458eee861 Merge main into #3283
dialogs.rs: main's Displace-map prompt runs before the fallible confirm_command. filter_dialog.rs: main's ask_displace_map uses the new confirm_command signature; SMART_FILTER_SET_PARAMS stays for main's uses; a smart-filter edit without a "layer" param previews the active layer, as the command runs it (main's smart_displace_preview_uses_the_map_document).
2026-10-22 02:16:49 +00:00
aiongg dd83f87d3c Merge PR #5581: Layers: Group Layers creates the group collapsed (#5571) 2026-10-21 21:56:20 +00:00
aiongg 5189019b5b Merge PR #7696: fix(actions): preserve effective Stroke width in ATN export 2026-10-21 21:56:10 +00:00
aiongg c2d5a3fd64 Merge PR #7708: fix(actions): refuse lossy fractional Ripple ATN export 2026-10-21 21:56:10 +00:00
abc2cbandClaude Opus 5.5 6da0673cd1 Merge upstream/main 6d8cbac7 into the Smart Filters branch
Conflicts:
- filter_dialog.rs: preview_document_for_target keeps our proxy scaling
  and `p` clone; main's Bitmap rule (the preview drops Output resolution,
  #5559) is applied to the same `p`.
- hu/sr/tr/vi catalogs: both sides appended rows at the end; kept both, no
  duplicate keys.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 00:14:11 +03:00
bommerts e2a238737d Scale shape strokes when resampling documents (#8341) 2026-10-21 16:15:22 -04:00
aiongg 66e54580b7 Merge PR #7838: Free Transform: a result may take what Memory Usage allows, not 2^30 px (#7807) 2026-10-21 18:15:11 +00:00
aiongg 77557d75f1 Merge PR #8229: Integration batch: 8 PRs on main
# Conflicts:
#	crates/engine/src/layer_style.rs
#	crates/io/src/psd_export.rs
#	crates/io/src/smart_map.rs
#	docs/file-format-parity.md
2026-10-21 15:45:07 +00:00
4decb8dd30 Address CodeRabbit review: .act vs .aco by content, strict corpus walks (#5407, #4496)
- swatches.import with bytes only (no path or format): an .act whose first
  colour is 0, 1, x or 0, 2, x still went to the .aco reader, which ignores
  trailing bytes and returned a handful of junk swatches. At the two .act
  lengths (768/772) an .aco header now counts only when its sections span
  the whole file (new `aco::sections_len`); a Photoshop .aco of exactly
  768 bytes is still an .aco. Test: act_that_starts_like_an_aco_is_still_an_act.
- The .atn corpus tests (psd and engine) skipped unreadable folders and
  entries silently; they now fail with the path.
- act::write doc: the trailer is written when `count` or `transparent` is given.

Co-authored-by: Abdul karim mia <97598943+abdul-karim-mia@users.noreply.github.com>
Co-authored-by: Fabio Lissi <fabio.lissi@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 14:06:56 +02:00
aiongg b1e408d28f Merge the smart-filter track (#7066 #6398 #6397 #6297 #6299 #6301 #6303 #6315 #6305 #6317)
# Conflicts:
#	docs/file-format-parity.md
2026-10-21 05:04:04 +00:00
aiongg 3a3796af05 Merge PR #6397: PSD: Perspective Warp smart filters open and save like Photoshop (#6268)
# Conflicts:
#	crates/io/src/smart_map.rs
#	docs/file-format-parity.md
#	docs/scorecard.md
#	scorecard/file_compat.toml
2026-10-21 01:07:59 +00:00
aiongg 8c942e481d Merge PR #7224: Image: Trim and merged Duplicate report an error on documents over 2^30 px (#7223) 2026-10-21 01:06:16 +00:00
David MannandClaude Opus 5.5 c9b0bb0cbc Integration: merge main, resolve conflicts (#4496)
fill_to (Paint Bucket export): keep main's `source` alias and explicit
colour (`Usng` = `Clr ` plus `Clr `, #7199) together with the PR's
optional `Tlrn`/`AntA`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 02:05:34 +02:00
Gabrieljr42 797c7852f9 fix(type): clear retained wght variation when resolving exact face 2026-10-20 21:01:11 -03:00
Gabrieljr42 99a234d2e2 fix(type): resolve exact PostScript names in type.create
type.create stored the font field as a family name, so an exact
PostScript face such as Arial-Black warned and fell back. Resolve
only an exact PostScript match and keep that face's family, weight,
slant, and name. Unknown families still warn.

Fixes #8063

Signed-off-by: Gabrieljr42 <gabrieljunior42566@gmail.com>
2026-10-20 20:34:08 -03:00