Commit Graph
12391 Commits
Author SHA1 Message Date
Trevor BrownandClaude Sonnet 5.5 66f9f9eee7 Fix upstream alt test for the follower selection (#12769)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium
2026-11-11 21:06:59 -05:00
Trevor BrownandClaude Sonnet 5.5 d98b149ce1 Merge remote-tracking branch 'upstream/main' into fix/delete-anchor-shown-only-12769
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Model-Effort: Opus 5.5 drove; Opus 5.5 briefed; Sonnet 5.5 wrote at medium
2026-11-11 20:38:08 -05:00
David Mann de7cb6c0c4 Merge pull request #13234 from Raghav2012Code/fix/13065-pcrop-keep-clicked-corners
fix(ui): a Perspective Crop drag with no area keeps the clicked corners (#13065)
2026-11-12 02:20:01 +01:00
David Mann 3e6d361735 Merge pull request #13215 from TrevorBrown-dev/fix/add-anchor-straight-smooth-12706
Add Anchor Point: an anchor added to a straight segment is smooth, with handles (#12706)
2026-11-12 02:19:45 +01:00
David Mann 35887692ff Merge pull request #13176 from Raghav2012Code/fix/13072-delete-anchor-escape-stage
Delete Anchor Point keeps its path on the first Escape, and leaves a drag alone (#13072)
2026-11-12 02:19:30 +01:00
David Mann b554be38e7 Merge pull request #13303 from NaufalDzz/fix/issue-13244
Line tool: a drag is one History step named "Line Tool" (#13244)
2026-11-12 02:17:52 +01:00
David Mann 9677f2e73a Merge pull request #13020 from slafebre/feat/12054-type-bar-panels-toggle
Type options bar: Toggle Character and Paragraph panels button
2026-11-12 02:17:17 +01:00
David Mann 7755675ce7 Merge pull request #13342 from RickiNano/fix/13308-star-outer-corner-radius
Polygon tool: a rounded star rounds only its outer points (#13308)
2026-11-12 02:16:48 +01:00
David Mann 2a4e0f4c99 Merge pull request #13378 from storytold/fix/paint-tests-use-stroke-results
paint: two stroke tests check the result the stroke now returns
2026-11-12 01:40:04 +01:00
David Mann 41280a2bcd Merge pull request #12206 from hectorviov/fix/count-options-bar
Count tool options bar: every control from the start in the reference order, tooltips and greying, scrubby size captions (#11765)
2026-11-12 01:36:14 +01:00
David Mann c4ae585613 Merge pull request #13305 from RickiNano/fix/13241-line-tool-defaults
Line tool: Weight 1 px and 5 × 10 px arrowheads by default and after Reset Tool (#13241)
2026-11-12 01:36:02 +01:00
David Mann 6ba21e3475 Merge pull request #13313 from rmsff/fix/freeform-pen-close-tolerance-12830
Freeform Pen: close a stroke only within 3 px of its start on each axis
2026-11-12 01:35:51 +01:00
David Mann 2bb1c3d0c6 Merge pull request #13141 from rmsff/fix/convert-point-drag-segment-12741
Convert Point: drag a segment as Direct Selection does
2026-11-12 01:35:41 +01:00
David Mann ef2a5031c5 Merge pull request #13188 from rmsff/fix/delete-anchor-alt-click-12770
Delete Anchor Point: Alt-click on an anchor selects its whole subpath
2026-11-12 01:35:30 +01:00
David Mann 8c8ba2c978 Merge pull request #13013 from RickiNano/feat/12066-zoom-out-mode
Zoom tool: Zoom In / Zoom Out mode buttons (#12066)
2026-11-12 01:35:18 +01:00
Dylan M. Taylor f33bdad496 paint: two stroke tests check the result the stroke now returns
apply_color_replacement and apply_mixer_stroke return a Result since #11070.
Two tests that landed on main after that PR's CI ran still dropped it, so
clippy's unused-must-use lint fails the gate on main.
2026-11-11 22:31:50 +00:00
FredApps f1b5e7d727 CI: nightly release dry run (#13374)
release.yml also runs nightly on main with craft-common-actions' dry-run: every release build
except macOS, with nothing signed, pushed or drafted. Breakage that only the release build hits
(riscv64, Flatpak, FreeBSD, packaging) then shows up the next morning instead of on release
day, as it did on 11 Nov 2026.
2026-11-11 23:04:35 +01:00
Trevor Brown 63644ce5a1 Merge remote-tracking branch 'upstream/main' into fix/delete-anchor-shown-only-12769 2026-11-11 16:37:43 -05:00
Dylan M. Taylor abeb16c96b paint: refuse a sequential-dab stroke whose working copy is too large (#11070)
* paint: refuse a sequential-dab stroke whose working copy is too large

apply_dab_stroke read the whole rectangle enclosing a stroke's dabs into
two dense f32 copies (and a third for the mix), sized by the area
between the dabs rather than what they paint. Two distant points asked
for gigabytes on a sparse document.

Check the three planes against a 4 GiB budget (1 GiB on 32-bit) before
reading, and paint nothing past it.

* address review: apply_dab_stroke returns Result so over-budget dab strokes fail with 'stroke too large'

* fix tests: apply_dab_stroke returns a Result

* fix tests: handle the Result of the dab-stroke functions
2026-11-11 16:31:47 -05:00
Dylan M. Taylor f7771c8545 Engine: check dense working buffers against a budget before expanding sparse content (#10964)
* Engine: check dense working buffers against a budget before expanding sparse content

A native document stores only the tiles it holds, so a few distant tiles (or a
huge empty canvas) make a small file whose content bounds span trillions of
pixels. Several commands read those bounds, or the whole canvas, into dense
f32 buffers without checking the size first, and ran the process out of memory.

- allocation::check_dense refuses an area whose dense buffers would pass
  MAX_DENSE_BYTES (the Image Size allowance), before anything is allocated.
- Adjustments run through process_surface, Apply Layer Mask, channel sources
  (Apply Image / Calculations / Load Selection), face detection and Multichannel
  conversion (both directions) check their buffers first.
- Auto-Blend checks the final work area too, not only the layers' union.
- Liquify's selection blend works over the part of the content the selection
  reaches, on a copy of the old pixels, and checks that area.
- Floating a selection visits only stored source or selection tiles when a
  default is empty, and checks the full grid otherwise.
- Frame from Layers and the Frame tool fill their mask without a dense buffer
  and check its area.
- Image Size checks every surface's resampled content bounds, off-canvas
  pixels included, not only the canvas.

* cargo fmt

* address review: propagate budget error out of adjust_as_filter

* address review: budget merged CMYK channel planes, frame mask GRAY8 source, Duotone inks and the stored surface in Multichannel conversions

* address review: budget the Frame mask at its tile footprint and Auto-Blend stack pyramids

* address review: non-seamless stack blend skips the fusion pyramids in its budget; canvas refresh returns smart-object refresh errors

* address merge: take main's resample_doc signature in Bitmap; fmt

* address merge: Image Size over distant tiles is bounded by main's resample budget; drop the duplicate test

* address merge: keep brush_clear_background_tests test-only

* address CI: a smart object that cannot re-render keeps its resampled fallback (main's tested behavior); drop the refresh error propagation
2026-11-11 16:31:22 -05:00
Dylan M. Taylor 479f8e643e Actions: charge skipped steps to the playback budget, bound batch nesting, clip the set override (#10969)
* Actions: charge skipped steps to the playback budget, bound batch nesting, clip the set override

- actions.play charges every stored step of a call (run, disabled or before
  `from`) to the playback tree, and refuses a call that no longer fits before
  copying the action, so repeated calls to a large disabled child stop at the
  shared limit.
- file.automate.batch and runDroplet refuse to nest more than MAX_BATCH_DEPTH
  deep, checked before the droplet is read; nested batches charge the shared
  step budget like batches inside played actions.
- actions.load clips the `set` override to the importer's name limit before
  copying it into every action.

* address review: check the script step limit before charging skipped playback steps

* address review: nested batches keep the shared playback count, and nesting or playback limits fail the enclosing input

* address review: a limit stop inside a called action or nested batch fails the enclosing input

* address review: keep begin_playback's signature; the call that starts mid-action uses begin_playback_from

* address review: keep child results in limit failures, history after the script-limit check, trim a clipped set name, open-document batches carry the nesting state
2026-11-11 16:30:57 -05:00
Dylan M. Taylor 2e10342cdb fix(engine): authorization for nested scratch sessions and preset calls, CSV and PostScript text escaping (#11188)
* fix(engine): authorization for nested scratch sessions and preset calls, CSV and PostScript text escaping

* address review: Batch checks the authorization gate for each save point

* address merge: restore the #[test] attribute

* address merge: batch save points answer to the authorization gate in the rewritten batch

* address review: neutralize leading line feeds and full-width formula characters; test the preset command gate

* address review: check formula prefixes after leading spaces
2026-11-11 16:30:33 -05:00
Dylan M. Taylor dd19c295d1 fix(engine): bound sparse remap, scaled clone sources, path reads, export format, name lookups (#11181)
* fix(engine): bound sparse remap, scaled clone sources, path reads, export format, name lookups

* address review: read footage frames by Path so non-UTF-8 file names still import
2026-11-11 16:30:07 -05:00
Dylan M. Taylor ab4ba9f37c fix(codecs): checked sizes in encoders, EXR name lookup, FITS float limit, VP8 plane copies, EXIF thumbnail bytes (#11164)
* fix(codecs): checked sizes in encoders, EXR name lookup, FITS float limit, VP8 plane copies, EXIF thumbnail bytes

* address review: thumbnail range must be one SHORT/LONG tag and clear of IFD0

* address review: keep the TIFF header and Exif/GPS sub-IFDs out of the blanked thumbnail range

* address review: bound the Exif/GPS sub-IFD overlap scan with a total budget

* address review: keep the Interoperability IFD out of a blanked thumbnail range
2026-11-11 16:29:41 -05:00
Dylan M. Taylor f373ec181c fix(format,engine): limit zstd windows, set bundle modes via the handle, refuse symlinked presets (#11145)
* fix(format): limit zstd windows, set bundle permissions through the handle, refuse symlinked presets

* test(engine): create the symlink test's directory

* address review: preset writes never follow a symlink swapped in after the check

* address review: a zstd window past the limit is a limit error; replacing a link never reads its target's attributes

* test: replacing a link to a FIFO does not block
2026-11-11 16:29:17 -05:00
Dylan M. Taylor e6c9ce340b fix(io): charge importers for the whole tiles surfaces keep (#11144)
* fix(io): charge importers for the whole tiles surfaces keep

* test(io): size the affinity and SVG pixel budgets in whole tiles

* address review: charge retained tiles after prune, logical scratch in SVG peak check

* address review: charge only the tiles a raster layer keeps

* fix PsdImportBudget initializer after merging main

* address review: leave the multichannel tile budget to the PSD preflight

* address review: charge a shape cache for the tiles it keeps
2026-11-11 16:28:51 -05:00
Dylan M. Taylor b4ad74fda8 fix(gpu): cap plan accumulator slots and gradient lookup tables (#11061) 2026-11-11 16:28:26 -05:00
Dylan M. Taylor bbcb4b825a codecs: list each Cryptomatte layer once and index streams by name (#10978)
* codecs: list each Cryptomatte layer once and index streams by name

layers() cloned the cached stream list for every cryptomatte/<key>/name
attribute that named a layer, so many keys naming one layer (in any
case or _/- spelling) retained keys x channels strings. Streams are now
indexed by normalized layer name in one pass over the channels, each
layer's list is moved into the first key that names it, and later keys
naming the same layer are skipped (decode resolves a name to its first
layer anyway).

decode() searched the layer's stream list for every decoded channel;
it now builds a stream-name -> slot map once.

* address review: compare cryptomatte layer names normalized in decode

* address review: prefer exact Cryptomatte layer name

* address review: sort cryptomatte keys so layer names are stable

* address review: prefer the key with a usable manifest when keys name one cryptomatte layer
2026-11-11 16:28:01 -05:00
Dylan M. Taylor 648d742a50 fix(algo): bound EXIF text decoding, warp scans, gallery windows, inpaint sizes, pyramid depth (#11161)
* fix(algo): bound EXIF text decoding, warp scans, gallery windows, inpaint sizes, pyramid depth

* address review: gallery window budget no longer scales with the effect count; assert blended pixels in the level-clamp test

* address review: Filter Gallery window budget counts the working window and effect temporaries

* address review: empty Filter Gallery is not charged working buffers; document the warp scan skip

* address merge: multiband returns a Result; keep apply_tiled_with_impl under the complexity limit
2026-11-11 16:27:36 -05:00
Dylan M. Taylor 3b43cb451a fix(algo): hold raw filter parameters to their ranges (Water Paper, Box Blur, Lanczos, Camera Raw noise) (#11199) 2026-11-11 16:27:11 -05:00
Dylan M. Taylor 556382bab8 fix(ui-egui): bound the RAW re-read and treat symlinked names as taken in batch export (#11204)
* fix(ui-egui): bound the RAW re-read and treat symlinked names as taken in batch export

* address review: refuse an oversized RAW file from its length and reserve the read buffer fallibly

* address review: lower the RAW re-read ceiling to the decoder's 2 GiB allocation limit
2026-11-11 16:26:46 -05:00
Dylan M. Taylor b01e6c0270 Save: a replacement in another group does not widen group access (#11232)
* Save: a replacement in another group does not widen group access

* address review: set the group before copying extended attributes; skip the group test when the original's group is not assignable

* address review: copy the permissions (minus group bits) when the group lookup fails
2026-11-11 16:26:21 -05:00
Dylan M. Taylor c6a71929ef fix(cms): charge decoded CLUT values against a per-profile budget (#11055) 2026-11-11 16:25:57 -05:00
Dylan M. Taylor d49ebf4a41 Camera Raw: read each source row once when building the preview proxy (#11064)
* Camera Raw: read each source row once when building the preview proxy

The proxy box-averages k x k blocks, with k chosen from the longer side
of the domain. Blocks past the last row re-read that row once per
missing row, so a one-row domain (a sparse document a pixel high and a
million wide) read the same row k times: quadratic in its width, on the
UI thread.

Read every source row once and weight the last one by the block rows it
stands for; the averages are unchanged.

* address review: accumulate camera raw preview rows in f64
2026-11-11 16:25:33 -05:00
Dylan M. Taylor 9f606d83d1 fix(compose): bisect gradient stops, evict oversized effect maps, skip empty distance transforms (#11056)
* fix(compose): bisect gradient stops, evict oversized effect maps, skip empty distance transforms

* address review: handle NaN gradient position in stop samplers
2026-11-11 16:25:08 -05:00
Dylan M. Taylor e4efca36aa fix(engine): apply the metadata choice to WebP Quick Export (#11058) 2026-11-11 16:24:44 -05:00
Dylan M. Taylor d51e4bce94 text: charge the rasterizer's output tiles, not only its pixels (#11047)
* text: charge the rasterizer's output tiles, not only its pixels

The renderer checked a layer's pixel count and working buffers, but its
output surface stores whole 256x256 tiles. An extreme transform of short
text gives a thin rectangle that crosses tens of thousands of tiles while
holding few pixels, so the tile storage far exceeded the budget.

Refuse a render whose output tiles exceed MAX_RASTER_BYTES.

* address review: charge text accumulator with output tiles

* address review: compute the accumulator size in u64
2026-11-11 16:24:19 -05:00
Dylan M. Taylor 46f6ec4ccf Escape control characters in log lines and diagnostic output taken from files and plug-ins (#11218)
* Escape control characters in log lines and diagnostic output taken from files and plug-ins

* address review: escape the plug-in load error and the atn_dump path before printing
2026-11-11 16:23:55 -05:00
Dylan M. Taylor bf162c2215 automation: save_bytes never reads linked files (#11233) 2026-11-11 16:23:30 -05:00
Dylan M. Taylor 5a935b2830 Place: refuse a scale that makes the placed image exceed the render pixel limit (#11229)
* Place: refuse a scale that makes the placed image exceed the render pixel limit

* address review: bound the rounded-up resampled size when placing at a scale

* address review: the oversized-scale error names the placing command
2026-11-11 16:23:05 -05:00
Dylan M. Taylor f6741eff4d macOS signing: decode the certificate into an exclusive temp file (#11028)
import-cert.sh wrote the decoded .p12 to a fixed name in the temp
directory. If another account had created that file first, the shell
redirection truncated and reused it, keeping its owner and mode, and the
signing key was readable to that account. Create it with mktemp.
2026-11-11 16:22:40 -05:00
Dylan M. Taylor 23c2b85a4f ci: use StepSecurity's maintained actions (#13337)
Each third-party action that StepSecurity publishes a secure drop-in
replacement for now uses that replacement, pinned to a commit with its
version as a comment. Versions follow what we used: the newest
StepSecurity release in the same major, or the closest major they
publish. dtolnay/rust-toolchain refs that named a toolchain (stable,
nightly, 1.76) become the replacement's `toolchain` input.
2026-11-11 16:02:46 -05:00
David Mann 63b641b55e Merge pull request #6413 from marmitoTH/fix/pen-undo-resumes-path
Pen: Undo after finishing a path gives it back to the Pen instead of deleting it (#6619)
2026-11-11 21:15:51 +01:00
ae2be4c786 Count size caption test: skip without the craft-i18n catalogs (PR #12206)
Main moved the catalogs out to the optional craft-i18n build input; built
without it, Lang::from_code("de") is None and the test's expect panicked.
It now skips like main's other translation tests (needs_catalogs).

Co-Authored-By: Hector Villarreal <hectorviov@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 21:09:48 +01:00
David Mann 0549be857e Merge pull request #13171 from rmsff/fix/remove-locked-layer-alert-12552
Remove: alert on a pixel layer with Lock All
2026-11-11 21:08:34 +01:00
RickiNano e0be355ebf Merge remote-tracking branch 'origin/main' into fix/13241-line-tool-defaults
# Conflicts:
#	crates/ui-egui/src/tools.rs
2026-11-11 20:56:46 +01:00
FredAppsandFredApps 8a909b2673 Release: PhotoCraft v0.23.0 on main (#13345)
Co-authored-by: FredApps <FredApps@users.noreply.github.com>
2026-11-11 20:54:32 +01:00
RickiNano cb5298e9d4 Polygon tool: a rounded star rounds only its outer points (#13308)
live_path rounds a star's outer points and leaves its inner points
sharp corners, as the reference application does: a 5-point star at
Star Ratio 50 % with corner radius 10 has 15 anchors instead of 20.
Plain polygons keep rounding every vertex.

The on-canvas corner radius widget shows knobs at the outer points only
and takes its largest radius from them, so it previews the same path
as shape.create.
2026-11-11 20:41:00 +01:00
21498a957b Merge main into fix/count-options-bar (conflicts in analysis_ui.rs, widgets.rs, widgets/fields.rs)
Keeps both sides: main's value_field_whole_alerting and new test modules
next to the PR's value_field_whole and count_options_bar_tests.

Co-Authored-By: Hector Villarreal <hectorviov@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 20:37:04 +01:00
RickiNano e2c4555891 Line tool defaults test: options missing from a saved file take the new defaults (#13241) 2026-11-11 20:35:23 +01:00