Commit Graph
842 Commits
Author SHA1 Message Date
Khawar Zamman Wani 86ddfb72f7 Reuse large buffers so returning freed memory to the OS doesn't slow filters (#10479) (#10514)
* perf: reuse large buffers so a pinned glibc trim threshold costs no speed (#10479)

With MALLOC_TRIM_THRESHOLD_ set (#8743), glibc maps every allocation over
128 KiB fresh, so tiles, compositor bands and filter scratch were page-faulted
in on every call: viewport compose 3.6x slower, Gaussian Blur up to 1.8x,
.pcraft save 2.4x.

- photocraft_raster::scratch: a process-wide, capped pool of large Vec
  buffers (u8/u16/f32/[f32; 4]). A miss drops the oldest buffers worth its
  size down to a 256 MiB floor, so peak memory stays near glibc's defaults.
  The engine releases the pool after any command that closes a document,
  Headless::close does too, and an idle thread releases it after 2 s unused.
- Tiles, compose Buffer/masks/bands, algo Image and the blur paths, engine
  adjustment/filter scratch, GPU tile upload and io import buffers go through
  the pool.
- .pcraft save reuses one zstd FrameCompressor per worker (byte-identical).
- interactive_bench reports minor page faults per run.

36 MP, trim threshold set vs glibc defaults: viewport 5.6 vs 6.1 ms (was
22.7), Blur r4 445 vs 437 ms (was 852), Curves CPU proxy 35.0 vs 35.7 ms
(was 50), flatten 146 vs 147 ms (was 237), save .pcraft 251 vs 230 ms (was
545). RSS after closing a 5400x7200 document: 21 MB with trim set.

* fix: corpus tests build again; return remaining pooled buffers (#10479 review)

- Corpus-gated io tests and the Photoshop-oracle test moved `.px` out of a
  `Buffer`, which now implements `Drop` (E0509 with `--features corpus`):
  use `into_px()`.
- io: masks, the merged image, extra channels, smart-filter masks,
  smart-object pixels and patterns give their `interleave` buffers back to
  the scratch pool after writing them.
- compose: recycle the mask values of a pass-through group, `effect_shape`
  and both `split_parts` callers.
- Styled Free Transform preview copies each band out instead of moving it,
  so the band returns to the pool.
- interactive_bench: the fault count covers each whole run, untimed setup
  included; say so.

* fix: recycle the masks of adjustment-atop and shape layers (#10479 review)

* fix: recycle effect hiding masks (#10479 review)

* fix: recycle knockout, CMYK and GPU shape masks; release the pool when Split/Merge Channels close a document (#10479 review)

* fix: release the pool when a closed document's cancelled workers exit; idle-release switch for tests; don't pool PSD planes (#10479 review)

* fix: release the pool for workers cancelled before their document closes; take the pool lock for budget and idle-release changes (#10479 review)

* fix: idle release rechecks activity under the lock; try_take_exact releases the pool and retries before failing (#10479 review)

* test: cover a successful try_take_exact miss; name the failed-reservation test for what it checks (#10479 review)

* fix: pool the final GPU effect shape buffer and return it after use (#10479 review)

* docs: describe scratch pool lifecycle regression invariants

* test: verify polling releases cancelled document scratch buffers

* perf: recycle remaining transform selection and PSD scratch buffers

* fix: free PSD gather bands before allocating channel planes

* test: assert exact scratch take reuses pooled storage
2026-11-02 09:29:59 +01:00
Gabriel Heuser 24be8ea6e2 Add editable arrowheads to Line tool (#6408) (#9259)
* Add configurable arrowheads to line tool

* Add editable arrowheads to Line tool

* Fix arrow scaling validation and PSD import defaults

* Preserve arrow geometry under affine transforms

* Preserve scaled arrowhead dimensions and prevent non-finite geometry

* Localize arrowhead Start and End labels

* Fix arrow transform editability and short line handling

* Fix PSD arrow concavity serialization

* Fix arrow dimension fallback validation

* Refine arrowhead options UI to match Photoshop

* Add opt-in arrowhead defaults to Shape properties

* Fix tool reset syntax after upstream merge

* Validate arrowhead flags and clamp copied defaults

* Preserve editable headless lines under transforms

* Fix arrowhead UI imports and formatting after v0.17 merge

* Format arrowhead properties after v0.18 merge

* Fix Clippy lint errors in arrow geometry and tests

* Fix headless arrow geometry after nonuniform scaling

* Fix proportional arrow scaling in Properties panel

* Fix Rust formatting in Properties arrow scaling tests

* test: validate invalid arrowhead dimensions without mutation

* fix: preserve arrow compatibility with older pcraft versions
2026-11-01 18:46:05 -05:00
Khawar Zamman WaniandFredApps 209bce8d46 Budget PSD pattern expansion and bound multichannel conversion (#10541)
* Stream PSD user and real masks into tile rows

* Correct streamed-mask fixture metadata and test lint issues

* Budget PSD pattern expansion and bound multichannel conversion

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-01 16:00:21 +01:00
Khawar Zamman WaniandFredApps 5d815c5a4b Stream PSD user and real masks into tile rows (#10532)
* Bound PSD import pixel storage before decoding

* Include ZIP inflater workspace in PSD preflight

* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)

* Stream PSD user and real masks into tile rows

* Correct streamed-mask fixture metadata and test lint issues

---------

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-01 14:03:08 +01:00
Khawar Zamman Wani 97a83f074f Bound PSD layer and mask import memory before decoding (#10503)
* Bound PSD import pixel storage before decoding

* Include ZIP inflater workspace in PSD preflight

* PSD import: budget unknown-mode layers, stop after a fatal layer error, keep best-effort for non-allocation limits (#8593 review)
2026-11-01 12:33:09 +01:00
David MannandClaude Opus 5.5 01b8472845 Integration: compile after merging main at b1cfff9d3
The FIFO export test new on main builds a SmartObject without #8571's
vector_preview field, and #8311's typeBoxOverflow key takes the inspect
snapshot's json! past the default macro recursion limit of 128.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 18:36:42 +01:00
David Mann b2db24400e Merge main at b1cfff9d3 into integration batch 10
Conflicts resolved as unions of both sides: codecs re-exports (PngRows + TiffBands), smart_cmds source imports
(main's source_surface_from_buffer and cache API with #8571's svg_source_image_in/convert_svg_source; main's
duplicate rendering import dropped), io flat.rs test modules (#8536's banded TIFF tests and main's PNG ones),
menus/invoke.rs (#8571's smart SVG intercept and main's layer.selectUnderCursor), state.rs (#8311's
type_box_overflow and main's type_insertion_style), the canvas_geom test keeps the is_finite guard, docs
status lines keep both change lists, i18n catalogs keep both sides' rows (hi.tsv: main's wording where both
added the same string).
2026-10-30 14:28:02 +01:00
FredApps 722a9bd5cf Merge current main and remove app-local integration workflow additions 2026-10-30 12:22:42 +01:00
FredApps 0f120bbda1 Merge current main, reconcile streamed PNG profiles and workflow inputs 2026-10-30 06:52:05 +01:00
FredApps a4ab4873e8 Merge current main, retain full-sweep and new benchmark inputs 2026-10-30 03:05:00 +01:00
David Mann fea300dd4c Merge origin/main into integration batch 10 2026-10-30 01:47:01 +01:00
FredApps c8c8fc7821 Reduce repeated GPU setup and UI work; partition remaining regression matrices 2026-10-30 00:39:19 +01:00
FredApps c93c0bb36d Merge main into trimmed integration; reconcile blur, pattern and Liquify behavior 2026-10-29 23:47:53 +01:00
FredApps 29bf828ec2 Merge upstream main into reviewed performance integration
Preserve both UI parity status entries; retain all reviewed performance changes.
2026-10-29 23:35:19 +01:00
FredApps 4f6ebb1b6e test: partition long parity matrices without dropping cases 2026-10-29 23:23:32 +01:00
David Mann a3f8ef4816 Merge PR #8536: TIFF: images over 2^30 px open, decoded a group of rows at a time into the layer (#8169)
# Conflicts:
#	docs/file-format-parity.md
2026-10-29 21:06:41 +01:00
c62c987000 Integration: TIFF memory check only for sizes main refused, cgroup page cache, bounded conversion (#8536)
- The free-memory check ran for every flat TIFF on Linux with a 512 MiB
  reserve, so small TIFFs that open on main were refused on a small VM or
  in a container: it now runs only for sizes the whole-image decode
  refused (over 2^30 px or its byte budget).
- In a cgroup, memory.current counts page cache the kernel reclaims
  before memory.max is hit; its inactive_file part now counts as free.
  A `docker --memory=2g` batch whose cache filled up refused every TIFF.
- A single-strip TIFF is one group, the whole image, and every converted
  piece of it was held at once: conversion now runs in rounds of at most
  32 MiB of source rows per core.
- TiffBands::open reported no ExtraSamplesDropped/OverLimit warnings on
  32-bit targets (wasm); both decoders now share prepared_warnings, and
  Truncated goes before MorePages by position.
- Drops the ar.tsv rows of "Fix CI after merging upstream": main added the
  same two keys (#10173), so the merged catalogue had duplicates and
  i18n::tests::bundled_catalogs_are_consistent failed.
- Doc comments: the swap cap is every cgroup's above too (the ancestor
  walk FredApps asked for); a cut-off strip decodes as zeros.

Co-authored-by: Khawar Zamman Wani <28915582+wanikhawar@users.noreply.github.com>
Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:00:43 +01:00
FredApps 255ecc81d0 Remove 21 requested PR contributions from the 108-PR integration
Retain 87 PRs. Reconcile overlapping integration fixes and update testing scope.
Removed: #7153 #7742 #5493 #9282 #3455 #9172 #3139 #3967 #4783 #5453 #8347 #1991 #3345 #4042 #4305 #4883 #4890 #5090 #6621 #5870 #5939.

Combined CI pending for this source; historical portable artifact is not applicable.
2026-10-29 18:49:17 +01:00
1acb1f464b Integration: SVG contents open and render as on main; AI originals for other editors (#8571)
- Smart-object contents (Replace Contents, Convert to Layers, Stack Mode,
  internal Edit Contents) refused any SVG whose canvas area times its
  node count passed 24 MP, e.g. a 1920x1080 layout with 12 shapes.
  decode_source now uses the bounded image parse with File > Open's
  layered import (import_svg_bounded_images). Convert to Layers' shape
  cache cap is 1 GiB in the document's format, the import's own budget,
  not 24 MP (four full-canvas shapes in a 4K document failed).
- The bounded resolver failed the whole drawing on an embedded image it
  can't read (an unknown MIME type, a corrupt PNG); it now leaves it out
  as usvg does, so such SVGs place and render again. Byte and decode
  overruns stay errors.
- resvg gives each embedded SVG image a scratch pixmap the size of its
  target and frees it after, so the scratch budget counts the deepest
  chain of nested SVG images, not every sibling: 12 SVG icons on a 2 MP
  canvas, or one at a 12 MP render, no longer fail.
- Main's shared nesting budget (#9397) now covers the bounded path too:
  511 + 511 levels across a drawing and its embedded SVG overflowed a
  1 MB stack.
- An AI working copy is regenerated through VectorCraft only when
  VectorCraft is the editor; Illustrator or another program gets the
  original bytes. VectorCraft is recognised by bundle id, a known
  install, or its name (vectorcraft[.exe], vectorcraft-<version> AppImage,
  ai.storyteller.vectorcraft).
- updateSvg refuses an AI/PDF/EPS source (updateVectorSource saves it
  back in its own format); the doc no longer calls updateSvg "existing".
- Edit Contents on contents already open in the internal editor switches
  to that document, as main does, instead of an error.
- Stack Mode on an SVG refuses up front when one float frame per layer
  would pass 1 GiB (the layered import no longer refuses for it).
- A stored display preview still fails on an embedded image it can't
  read (strict budget, its own import_svg_preview_with_work; external-
  editor saves and conversions leave the image out as placement does); skipped embedded SVGs still use up the XML byte
  budget; an image under an unknown MIME type or with no pixels is left
  out uncharged.
- Merge: the PSD import reads a preview's native source from the
  document's global blocks; main's owned open moves them out of the
  file, so every stored preview was dropped.
- Main's strict Clippy rules on the PR's app code (explicit import, a
  Unix-only test helper, one long opt-in test).

Co-authored-by: Mocky Digital <282319807+mockydevs@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 18:13:23 +01:00
Khawar Zamman Wani a24e155a6f Merge upstream main into large TIFF fix 2026-10-29 22:39:27 +05:30
Khawar Zamman Wani 42870a6851 TIFF: account for ancestor cgroup swap limits 2026-10-29 21:26:31 +05:30
David Mann afacb057f7 Merge origin/main into pr-8571-fixup
Conflicts: svg.rs (main's bufread inflate and shared render helper, kept
with the PR's bounded raster path), psd_import.rs (the PR's vector
preview moved into main's smart_content), menus/invoke.rs (the SVG
intercept moved into main's split invoke_unguarded), rendering.rs and
the ui-egui import lists (main's explicit imports), Cargo.lock, docs
status lines (unions).
2026-10-29 16:38:24 +01:00
Khawar Zamman Wani f5dfe82a53 Test PNG export conflict resolution on upstream main 2026-10-29 13:11:59 +05:30
FredApps 964a47b51c Reconcile history, gradient, type safety and UI validation behavior 2026-10-29 07:30:56 +01:00
FredApps 4f23f459ba Merge approved PhotoCraft PR #3464: fix(vector): target selected saved paths and own Pen gestures
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Reconcile captured Pen and Freeform targets with current resumed-subpath, Type Path, Path Operation and draft recovery behavior. Valid source-owned tab switches commit to captured original target; invalid snapshots cancel with a diagnostic; refused commits retain draft and suppress automatic retries. Preserve current Saved(index) API and hidden-work-path protections, register all new ownership/gesture tests and add original-target tab-switch/deleted-target cases. Includes verified compile/API corrections from prior checkpoints.
2026-10-29 06:33:02 +01:00
FredApps c9430c92e3 Merge approved PhotoCraft PR #3748: control: suggest near matches for unknown command ids and methods (#3674)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Add bounded deterministic suggestions via current error/session/control modules while preserving authorization/modal checks. Register hints and all original tests; fix scrollbar choice import and updated PSD image fixture field found by 100-head check.
2026-10-29 06:14:31 +01:00
FredApps dd428d2780 Merge approved PhotoCraft PR #4035: fix(cmyk): Flatten Image and merges keep the inks of a tagged CMYK document (#3778)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Current compositor already preserves plain CMYK inks, tagged profile separation and uncropped merge bounds. Keep stronger native CMYK/Lab paths and current merge API; apply profile context to style rasterization and retain approved tagged-CMYK regression fixtures.
2026-10-29 06:12:35 +01:00
FredApps 7836d4b9e6 Merge approved PhotoCraft PR #4783: Fix/4758 type extreme finite geometry 20261013s1215
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Apply stricter finite 1e9 geometry bound to current parse/import safety paths; prevent corrected legacy origin bypass and retain current full PSD unsafe-import warning/raster fallback regression. Keep split import/build modules and port new overflow tests into import module.
2026-10-29 06:10:30 +01:00
FredApps a62b9ee217 Merge approved PhotoCraft PR #8347: Type: Roman Hanging Punctuation (trailing marks hang, don't steer the alignment)
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Ported hanging punctuation into current line placement and kerning modules, preserving forced breaks, bounded edge-tip row merging, justified-last-line behavior, area exclusions and independent Roman orientation shaping; kept PSD/engine/UI regression coverage.
2026-10-29 05:22:57 +01:00
FredApps cf786a3851 Merge approved PhotoCraft PR #8897: fix(io): read linked smart objects for PSD export as regular files only
Preserve both independent additions and moved regression modules without changing production merge semantics.
2026-10-29 04:41:10 +01:00
FredApps f63560732a Merge approved PhotoCraft PR #9590: fix(io): PSD layer-effect contours keep at most 16 points
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Keep PSD contours within 16 points while preserving endpoints and dominant bends, with all limit and tiny-span regressions registered.
2026-10-29 04:22:41 +01:00
FredApps bf33e45694 Merge approved PhotoCraft PR #9342: fix(io, engine): Embed Color Profile writes sRGB for an untagged document (#9325)
Preserve current module structure and port the approved source/test changes to unique current locations.
2026-10-29 03:51:21 +01:00
FredApps b58c93b6c6 Merge approved PhotoCraft PR #9596: fix(io): drop a kept Txt2 once no type layers are left
Port unchanged PR hunks to their unique current module locations after upstream file splits.
2026-10-29 03:37:03 +01:00
FredApps 7e061febf4 Merge approved PhotoCraft PR #9472: fix(io): import a Displace smart filter that names its map file without embedding it (#9162) 2026-10-29 03:29:54 +01:00
Federico Olivares 5a6270921c Merge main into the integration batch
Main now carries #9031 (Halftone) and #8923; this branch keeps only what it adds on top: the guard for a setting beside a Gallery stack's effect list, its test, and the PSD open warning for patterns that paint nothing.
2026-10-28 11:17:59 -03:00
aiongg 2b1c6b93c3 Merge main into split-filter-adjust-crop-fx-builders
crop_ui.rs moved to tools/; the PR's builders replace main's Clippy extractions of the same code; #6723's Color Lookup save carried into the moved encoder.
2026-10-28 04:22:40 +00:00
Khawar Zamman Wani 0ce7991aaa Merge origin/main into fix/8169-huge-tiff-open 2026-10-28 09:22:54 +05:30
Dylan M. Taylor ab9b27b80d Restore rationale comments dropped by the Clippy refactors 2026-10-28 02:13:42 +00:00
Dylan M. Taylor 163caeb86b Make the PSD size-limit test fail when a size-based PSB promotion happens 2026-10-28 02:13:42 +00:00
Dylan M. Taylor 63eb3eabe4 Drop the unused band_rows export and its dead_code allow from io 2026-10-28 02:13:42 +00:00
Dylan M. Taylor 1a3415608b Restore the PSD frame stroke import after the io refactor 2026-10-28 01:49:51 +00:00
Dylan M. Taylor 2a3135d796 Refactor io for strict Clippy checks 2026-10-27 23:47:06 +00:00
David MannandClaude Opus 5.5 5ccb6fb723 Merge main
Conflicts with main's batch #9880:
- psd file.rs / layer.rs: #5287 (PSB by encoded size, RLE tables widened on
  promotion) against #6583's lazy reader. Main's new widening and length code
  read `.data`, which #6583 leaves empty while the bytes stay in the source;
  it now goes through `encoded()` / `encoded_len()` (also the auto-merged
  lines in `rle_widening`, `encoded_len` and `LayerRecord::write`), and the
  lazy reader sets `write_as_psb: false`. New test
  `a_lazy_psd_promotes_to_the_same_psb_as_an_eager_one`: a lazily read PSD
  writes the same PSB bytes as an eager one; it fails with a `.data` read.
- direct_select.rs / vector_ui.rs: #9321's Type Path and #6353's hidden
  Work Path both kept.
- io tests main.rs: both modules. scorecard.md regenerated (12 of 181);
  ui-parity.md and gaps.md follow it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-27 19:49:42 +01:00
David Mann 8bc71f924b Merge main
# Conflicts:
#	crates/format/src/store.rs
2026-10-27 19:10:28 +01:00
aiongg 0e3a6f7e8d Merge #9421: XML: deeply nested ORA, KRA, Camera Raw XMP, .kys and layer XMP are an error, not a crash (#9419) 2026-10-27 17:44:23 +00:00
aiongg 3e0ec5004c Merge #9398: SVG: an embedded data-URL SVG gets the nesting-depth check (#9397) 2026-10-27 17:44:19 +00:00
aiongg fa86237e63 Merge #7154: Paste: a drawing copied as SVG markup pastes its pixels 2026-10-27 17:44:07 +00:00
aiongg 6e9fb30dbc Merge #6723: Color Lookup: PSD save keeps a .3dl/.look LUT file as loaded (#6544) 2026-10-27 17:44:05 +00:00
aiongg bf825aa490 Merge #6303: PSD: Diffuse, Trace Contour, Crystallize and Pointillize smart filters open and save like Photoshop (#6302) 2026-10-27 17:44:02 +00:00
aiongg 01594f1f25 Merge #5890: PSD: Frame layers keep their stroke (#4381) 2026-10-27 17:44:01 +00:00