Commit Graph
9592 Commits
Author SHA1 Message Date
Triwarr 399cd6ea4d PDF: import every page as an artboard; export a page per artboard
The PDF importer renders each page with PDFium at the import DPI (default 300), lays the
pages out side by side and wraps each in an artboard, so a 2-page PDF opens as 2 artboards
and saves back as a 2-page PDF (one page per artboard, page-sized, labelled). The import
caps at 16 pages for now.

The PDF writer now takes a list of pages: shared font/ICC/selection objects, one image per
page, and the existing one-page export is the single-page case. Artboards with vector/text
layers are rasterised in this path.

Tested: artboards_export_as_one_page_each; convert sample.pdf app-multi.pdf (2 pages),
rendered back with the probe.
2026-11-06 19:15:08 +01:00
Triwarr 95c9d3c9eb PDF import: open the first page with PDFium
File > Open, drag-and-drop and photocraft-cli now accept PDF files. The first page is
rendered with PDFium at 300 dpi (ImportOptions.pdf_dpi), built through the flat
importer, and the document resolution keeps the page's print size. The page count is
reported; multi-page import is the next step (#2541 / FILE-215-10).

- crates/io: pdf_import module, native-only pdfium-render + image deps, import and
  preflight dispatch (.ai keeps its existing path).
- PDFium loads from the executable's folder or PDFIUM_DIR.
2026-11-06 19:15:07 +01:00
2ff8f419cb ci: run the GPU tests on lavapipe on Linux and fail if they skip (#7975)
The Linux runner has no GPU, so the GPU tests ran on Mesa llvmpipe over
GL, which can't render Rgba32Float: 57 GPU checks (50 GPU parity, 3
canvas, 2 adjustment preview parity, 2 effect-map recovery) returned
early and passed without comparing anything. A new step after Test
installs mesa-vulkan-drivers and runs the nextest `gpu` group on
lavapipe (Vulkan), reusing Test's build, and fails unless the parity
tests report the Vulkan backend and no test printed a skip.

No code change: photocraft's tests take whatever adapter wgpu returns,
software adapters included. Follows the CI half of lightcraft#1148.

Co-authored-by: FredApps <FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:44:13 +01:00
f23d173933 Add an opt-in WinTab backend for pen pressure on Windows (#11331)
* Add an opt-in WinTab backend for pen pressure on Windows

Windows Ink stays the default. Preferences > Tools > Pen Tablet has a Tablet
input dropdown (Windows Ink (default) / WinTab). WinTab opens a WinTab 1.4
system context on PhotoCraft's window and polls pressure and the eraser end
(tilt on devices that report orientation axes; rotation only with a pen and
driver that report twist) into the stylus feed. The row says to turn Windows
Ink off in the tablet's software utility; the choice applies at next launch.

- crates/tablet: Windows-only wintab/wintab-sys backend. Devices with
  orientation axes use the orientation packet; pressure-only devices open a
  packet without it and report neutral tilt. Leaving is the driver's hardware
  proximity message (WT_PROXIMITY) and the packet's out-of-context status, with
  a long fallback for drivers that never report either. Overlap priority
  follows window focus, and the message hook requests a frame for each WinTab
  message so pressure-only strokes update without cursor movement.
- apps/photocraft: install the backend when the preference is on; poll it at
  the start of each frame; the installed wake repaints the UI.
- ui-egui: TabletPollFn service; the Windows-only Pen Tablet row with the
  Tablet input dropdown and the note.
- engine: tools.tabletInput (windowsInk/winTab), default windowsInk.
- docs: hardware-parity WinTab gap entry, qualifying tilt to orientation axes
  and rotation to twist-reporting pens.

Tested locally on a Wacom tablet with Windows Ink off: pressure, tilt and the
eraser end reach the brush (rotation where the pen reports twist); the default
path is unchanged.

* WinTab: a message that finds the state borrowed is skipped, not a panic in the hook

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* WinTab: rustfmt

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Scorecard: count the Tablet input setting

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: FredApps <153173854+FredApps@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 18:39:40 +01:00
FredApps d2ce418bb3 Merge pull request #11641 from wanikhawar/claude/agitated-jones-8e1a8e
A little free memory no longer refuses every PSD; the refusal says what to do
2026-11-06 18:36:17 +01:00
FredApps 91a2fd1d85 Merge pull request #11652 from wanikhawar/claude/stoic-yalow-d695ab
A scratch folder that stops answering no longer freezes the app
2026-11-06 18:28:41 +01:00
FredApps ce97bde34b Merge pull request #11628 from wanikhawar/claude/brave-wu-261567
Network scratch folders report their own free space, or say they can't
2026-11-06 18:15:40 +01:00
FredApps 71aa3eef9a Merge pull request #10164 from wanikhawar/fix/10031-web-place-steps
Web build: Place runs a slice per frame, so a large PNG no longer freezes the page
2026-11-06 18:12:11 +01:00
FredApps 1659ceb2b7 Merge pull request #11613 from wanikhawar/fix/smart-filter-dialog-seed-shadows-alias
Stop an adjustment smart filter losing settings when its dialog is confirmed
2026-11-06 18:09:40 +01:00
FredApps a81d9f9220 Merge pull request #11609 from wanikhawar/fix/smart-filter-stale-adjust-params
Stop stale settings overriding edits to adjustment smart filters
2026-11-06 18:09:27 +01:00
FredApps c49c1fd6fc Describe scratch settings without promising memory admission
Present the live scratch state as current configuration rather than the cause of a file's refusal. Explain that configured scratch capacity cannot override caller/build limits or replace non-spillable memory. Keep the typed error and admission policy unchanged, and add wording regressions.

Formatting and whitespace checks passed. No local build or test execution; validation awaits hosted CI.
2026-11-06 17:51:45 +01:00
FredApps d41e29a24f fix(ui): identify the active scratch directory in warnings 2026-11-06 17:51:33 +01:00
FredApps 1eba8f6c72 Bound scratch capacity test query waits 2026-11-06 17:51:32 +01:00
FredApps 96cb31b8d2 Merge commit '0a2365e925567d0b4144bd9acef673081965889d' into fix/11641-final 2026-11-06 17:51:32 +01:00
FredApps 0a2365e925 Keep rejected scratch growth queries due for retry 2026-11-06 17:50:54 +01:00
David Mann b837027c41 Merge pull request #7064 from davidmann4/fix/rotated-view-drag-previews
Rotated view: Type box and Move marquee previews follow the document axes (#7063)
2026-11-06 17:29:48 +01:00
FredApps 8d2ee0787f Merge scratch query updates into memory admission policy 2026-11-06 17:29:23 +01:00
FredApps aee46a2fc6 Merge remote-tracking branch 'origin/main' into fix/10164-final-prune-u2 2026-11-06 17:28:48 +01:00
David Mann af99f69602 Merge pull request #7719 from davidmann4/fix/cas-background-selection
Content-Aware Scale works on the Background with a selection (#7717)
2026-11-06 17:28:41 +01:00
FredApps 07580bfb34 Merge commit '898979da306fe9af29e2ec60341951f098225cb5' into review/g-11652-update 2026-11-06 17:28:13 +01:00
FredApps 086c250d7c Keep final resize pruning cooperative
Visit at most four output tiles per closing work unit and honor the caller's deadline between batches. Sparse images with distant opaque corners otherwise make one final poll scan the whole resized surface.

Add a sparse-output regression at 8, 16 and 32-bit requiring multiple closing polls, identical pixels, and removal of the same empty tiles. Formatting and whitespace checks passed; compilation and test execution await hosted CI.
2026-11-06 17:28:13 +01:00
FredApps 6c6f5ff04c fix(ui): retain Selective Color row when reopening smart filters 2026-11-06 17:27:59 +01:00
FredApps 8afc35fdf9 Merge commit '2ce36bd66' into review/u1-11613-integrated 2026-11-06 17:27:58 +01:00
FredApps 898979da30 Merge main into scratch folder capacity queries 2026-11-06 17:27:38 +01:00
FredApps 2ce36bd66c Merge main and use replacement for adjustment smart filter edits 2026-11-06 17:27:16 +01:00
David Mann 1e82972ee1 Merge pull request #9667 from davidmann4/fix/system-tools-full-path
Windows: run explorer.exe and reg.exe by full path (#9666)
2026-11-06 17:26:45 +01:00
FredApps 8ab527b1e6 Merge pull request #11474 from wanikhawar/claude/selective-colours-isolation-329d87
Keep each colour's values in the Selective Color dialog
2026-11-06 17:26:42 +01:00
FredApps c8e4376ec6 Merge pull request #11513 from wanikhawar/claude/investigate-issue-e27e90
Windows: count scratch room when opening large files; refusal names the build's limit
2026-11-06 17:26:22 +01:00
David Mann 8b70147d06 Merge pull request #9244 from davidmann4/fix/flip-angle-gradient-sweep
Image Rotation: a flip reverses an Angle gradient fill's sweep (#9243)
2026-11-06 17:26:13 +01:00
David Mann 3768e84b67 Merge pull request #9480 from davidmann4/fix/remove-enable-animations
Interface: remove the Enable animations preference (#9479)
2026-11-06 17:25:38 +01:00
David Mann 89235b39ac Merge pull request #10501 from davidmann4/fix/10328-review-followup
Review follow-up to #10328: Liquify saved twirl, copied type brings its styles, restored tests (#10500)
2026-11-06 17:25:11 +01:00
David Mann 16348db38b Merge pull request #9138 from davidmann4/fix/9137-control-click-coord-range
ui.click / ui.move reject coordinates beyond the screen range (#9137)
2026-11-06 17:24:27 +01:00
David Mann fff0db9850 Merge pull request #9309 from davidmann4/fix/match-rotation-crop-turn
Match Rotation leaves a pending crop's turn out (#9308)
2026-11-06 17:23:58 +01:00
Khawar Zamman Wani 146d49f5a2 PSD write recipes: keep every exported candidate and pin the base file (#11607)
* PSD write recipes: keep every exported candidate and pin the base file

A case that failed after export dropped out of manifest.json, losing the
file a reference-editor check most needs. The CLI also reopened the corpus
path after the hash was taken.

- Keep the candidate and its hash once export succeeds.
- Run the CLI on a copy of the hashed bytes, so it never opens the corpus.
- Compare numbers by value, so 17 equals 17.0.
- tracking-split also checks runs 0 and 2 and all three run lengths.

Part of #6130.

* PSD write recipes: compare large integers exactly, reject case-only id clashes

Converting to f64 made 9007199254740993 equal 9007199254740992. Ids that
differ only by letter case name one output directory on a case-insensitive
filesystem, so they are now rejected as duplicates.

* PSD write recipes: test that the CLI receives the hashed bytes

* PSD write recipes: reject the contour library commands

Their path param can read or write any file, including the pinned base and
the corpus, and they edit no document.
2026-11-06 17:23:40 +01:00
David Mann 90f6d9aab6 Merge pull request #9300 from davidmann4/fix/trim-subquantum-alpha
Image: Trim (Transparent Pixels) ignores alpha that rounds to 0 at the document's depth (#9299)
2026-11-06 17:23:32 +01:00
Khawar Zamman Wani cd2250cb25 Scratch folder queries: address second review
A stuck close no longer holds up the files queued behind it (up to four
closer threads), and a query identifies the current file by the configured
folder. Tests don't read the room and the status across a late answer, and
the growth-check step proves its query is stalled.
2026-11-06 20:48:08 +05:30
Khawar Zamman Wani e01c8719a0 Scratch folder queries: address review
The whole folder change now waits 2 s at most, old files close on one
background thread, the cap counts query threads until they finish, and
writes during a query aren't counted twice. Capacity is refused if a sweep
paused spilling meanwhile, a query opens a file unless this folder has one,
and on macOS an unrelated dead mount only costs the purgeable figure.
2026-11-06 19:44:03 +05:30
FredApps c101cbfb7e Merge pull request #11632 from storytold/house-rules
Copy the shared house rules into AGENTS.md
2026-11-06 14:58:47 +01:00
David MannandClaude Opus 5.5 4f124949b5 Address CodeRabbit review: convert type style colours with the type; keep Basic Paragraph on Duplicate to New
Converting a document (layer copy to another mode/profile, Image > Mode,
Convert to Profile with or without dither, Duotone inks) converted run colours
but not the colours set by character/paragraph styles and Basic Paragraph, so
converted runs showed a false local override and stopped following later
style edits. Duplicate Layer > New Document dropped the source's Basic
Paragraph, giving inheriting type false overrides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 14:20:31 +01:00
Khawar Zamman Wani 6c720c3765 Merge remote-tracking branch 'origin/main' into claude/stoic-yalow-d695ab 2026-11-06 18:38:44 +05:30
Khawar Zamman Wani 3f03e3e99d Merge remote-tracking branch 'pr/11628' into claude/stoic-yalow-d695ab
# Conflicts:
#	crates/raster/src/spill.rs
2026-11-06 18:38:44 +05:30
David Mann 1c754c72f5 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/tools/crop_mode/tests.rs
2026-11-06 14:04:32 +01:00
David Mann a9de7ebee8 Merge remote-tracking branch 'origin/main' into HEAD 2026-11-06 14:03:38 +01:00
Khawar Zamman Wani 20c0d65342 PSD admission: no free-memory advice when the platform cap also binds
Where the 32-bit cap equals the measured room, more free memory can't raise the
limit, so the refusal shouldn't tell the user to close other apps.
2026-11-06 18:01:16 +05:30
Khawar Zamman Wani 2c68c07dbf A scratch folder that stops answering no longer freezes the app
Opening and measuring the folder ran under the config lock, which the UI
takes every frame, and could run on the UI thread itself. They now run on
a short-lived thread, one per folder and question and 16 overall; callers
wait at most 2 s, and a late answer applies if the folder is still current.
No answer counts as unmeasured, or pauses spilling if nothing is open yet.
2026-11-06 17:45:34 +05:30
David Mann 7904eee761 Merge pull request #11563 from davidmann4/integration-batch-18
Integration batch 18: 23 epic PRs (toolbar, move, selection, artboard, menus)
2026-11-06 12:42:38 +01:00
Khawar Zamman Wani 21da95dbc1 Merge remote-tracking branch 'pr/11628' into claude/stoic-yalow-d695ab 2026-11-06 17:05:22 +05:30
Khawar Zamman Wani 1ce1bced95 PSD admission: a little free memory no longer refuses every file
With 1 GiB or less of free RAM, or 512 MiB or less of commit headroom, the
hard limit was exactly 0, so even a small file was refused with a message that
didn't say memory was low.

The reserve now shrinks with the measurement: up to a quarter of free RAM opens
automatically, the rest goes to approval, and an approved import always leaves
at least 256 MiB free. Limits are unchanged for automatic opening above 4/3 GiB
free and for approval from 4 GiB free. A refusal set by measured memory now
gives the free amount and says to close other apps and try again, and the
approval prompt warns when little memory would be left.

An unreadable cgroup still measures Some(0) and stays refused.
2026-11-06 17:03:50 +05:30
Khawar Zamman WaniandClaude 873ed7bf37 Scratch status: hold the lock across the directory check and the store
A guard that is a temporary in an if condition drops before the body runs, so a configuration change
could still land between the two.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-11-06 16:46:04 +05:30
FredApps 7d8648dfcb Copy the shared house rules into AGENTS.md.
The blocks come from craft-contrib at dde09ea31e2e457f5b4653a6e76f7cdf55944bdf. The house-rules workflow checks the copy.
2026-11-06 11:50:05 +01:00