259 Commits

Author SHA1 Message Date
.CooCoo 289dd0a874 Format: take the .pcraft envelope from craft-pcraft-format (#10724)
* Format: take the .pcraft envelope from craft-pcraft-format

The manifest envelope, TileRef, Hash, FORMAT_VERSION, EXTENSION, the
entry names, tile_path and blob_path, is_valid_hash, the manifest
nesting and item checks and the migration runner now come from
craft-libs' craft-pcraft-format. photocraft-format re-exports them, so
callers do not change. Manifest is craft_pcraft_format::Manifest<DocM>.

Saved bundles keep the same bytes. A save still checks only the nesting
and the item count of its manifest, not its size, and the manifest
nesting limit is still computed from photocraft_doc::MAX_GROUP_DEPTH.

Tests: a save, load and save again gives the same bytes in every color
mode and depth, with and without previews; MAX_GROUP_DEPTH equals
craft_pcraft_format::MAX_GROUP_DEPTH.

* Format: pin craft-pcraft-format from storytold/craft-libs

* Format: read manifests with craft-pcraft-format's read_manifest_with

Pins craft-pcraft-format to dca870a0, the head of craft-libs #407.
Loading reads the manifest with read_manifest_with, which runs the
limit check, the version check, the migration steps and the envelope
read in one path; the layers are still decoded one at a time after the
rest of the document. A save builds the manifest with Manifest::new and
tile references with TileRef::new, and the bundle's directory names and
the .zst suffix come from the crate's constants. Saved bytes and error
messages are unchanged.

* Format: pin craft-pcraft-format to craft-libs #407's head 04dd1bd

04dd1bd changes only the crate's docs and a test, so photocraft-format
builds the same code.

* Format: pin craft-pcraft-format to craft-libs main at b8f7d93

craft-libs #407 merged as b8f7d93. Its read_manifest also refuses a
thumbnail other than thumb.png and a composite other than
composite/preview.png, the only names photocraft-format writes.
2026-11-02 11:43:46 -05:00
aiongg fab871dadb Merge pull request #10535 from davidmann4/integration-batch-11
Integration batch 11: 9 ATN PRs on main
2026-11-01 19:11:02 -05:00
Brandon Thomas 2df9f80770 Release 0.19.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:58:51 -05:00
David Mann d86f678325 Merge main into #8327 2026-11-01 14:27:37 +01:00
David Mann 9ec0f51dc1 Merge remote-tracking branch 'origin/main' into HEAD
# Conflicts:
#	crates/ui-egui/src/i18n/nb.tsv
2026-10-31 13:55:06 +01:00
aiongg 6c1da97387 updates: show check results with craft-update's CheckResultDialog 2026-10-31 04:43:12 +00:00
Brandon Thomas 8a87a457ab Release 0.18.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 23:26:40 -04: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
Ben Huyck fe7f48fe2e PSD: guess the legacy code page of 8-bit names (#6743) 2026-10-30 09:43:49 +00:00
Dylan M. Taylor 28be431b4a UPD.1: honor app pretend versions in update checks (#10254) 2026-10-30 03:00:13 -04:00
FredApps 0f120bbda1 Merge current main, reconcile streamed PNG profiles and workflow inputs 2026-10-30 06:52:05 +01:00
Dylan M. Taylor 249d126626 Update prompt shows the app icon and accent color instead of a letter (#10243)
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#2f7bf5, its colour in ArtCraft Launcher). The updater, the self-update
helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the
prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer).

craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434).
Clippy fixes for Rust 1.99 in untouched code (same logic):
- apps/photocraft/src/app_dirs.rs
- crates/codecs/src/codecs/via_image.rs
- crates/engine/src/canvas_geom/tests.rs
- crates/ui-egui/src/panels/blend_preview.rs
2026-10-30 01:27:27 -04:00
David Mann fea300dd4c Merge origin/main into integration batch 10 2026-10-30 01:47:01 +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
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
FredApps 53dbfe280c Integrate 16 reviewed performance and usability PRs
Includes #8472 #8488 #9461 #9793 #9809 #9813 #9814 #9822 #9826 #9847 #9850 #9852 #9921 #9924 #9961 #10080 at reviewed heads.

Preserves each PR head as a parent. Reconciles CI workflow inputs and benchmark jobs without dropping checks. Excludes #8536 #9825 #9969 #10129. Combined CI pending; no manual validation claimed.
2026-10-29 14:31:15 +01:00
FredApps f85bc4c545 Merge approved PhotoCraft PR #3387: feat(codecs): add lossless JPEG XL export for 8/16-bit images
Port behavior and regression coverage into current modules; preserve current upstream behavior.
Integrate lossless export-only JXL and independent decoder regression matrix, preserving current JPEG/TIFF save extensions and 12-bit/arithmetic JPEG decoder dependency.
2026-10-29 06:34:37 +01:00
Federico Olivares 50f4602c33 Merge main into the integration batch 2026-10-28 18:20:58 -03:00
Brandon Thomas b8c3f3aa8e Release 0.17.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:25:48 -04: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
David Mann fa0e095941 Merge main
# Conflicts:
#	crates/ui-egui/src/tools/type_tool/fonts.rs
#	crates/ui-egui/src/tools/type_tool/ime_tests.rs
2026-10-27 16:26:20 +01:00
aiongg 07bd794686 fix(ui): dropdown menus grow back after a search with no matches (#9849)
* refactor(ui): build every dropdown on craft_ui::ComboBox

Repin craft-libs to the revision with craft_ui::ComboBox, whose menu grows back
after its contents shrink while it is open (egui#5225), and ban egui::ComboBox
in clippy.toml.

* fix(type): the font menu grows back after a search

The search field is the ComboBox header and only the family list scrolls, so
the menu follows the list's height: no unfiltered height kept while searching.

* chore(deps): craft-libs 60d60d48 (dropdown fixes)

* chore(deps): craft-libs 6af63481 (dropdown fixes)

* chore(deps): craft-libs 4d7b82f7 (dropdown fixes)

* chore(deps): craft-libs 92d392cf (#387 merged)
2026-10-27 10:32:56 -04:00
Khawar Zamman Wani cc6837355b perf(paint): accumulate serial dabs in place with packed tile keys 2026-10-27 18:26:47 +05:30
David Mann c14a707d2a Merge PR #6583: PSD/PSB open without reading the whole file: channel data read as decoded, in bands into tiles (#5106)
Merged at the fix-up commit before its main merge (362947695d); the
conflicts with the batch are resolved here: psd_import.rs keeps both
sides' tests, tiff_layers.rs takes ImageData::new.
2026-10-27 13:50:37 +01:00
David Mann cd485b6c2c Merge remote-tracking branch 'origin/main' into pr-7689-fixup 2026-10-27 01:54:27 +01:00
Don Omondi 4c76339c36 Address CodeRabbit review: macOS app bundles, label, digest cache, SVG warp bounds
- External vector editing on macOS: discover VectorCraft.app in /Applications and
  ~/Applications, offer Illustrator when an Adobe Illustrator*.app is found, and accept a
  chosen .app under Other application. CFBundleExecutable is read from a bounded Info.plist
  (XML or binary, streamed with a nesting cap) and must resolve inside Contents/MacOS;
  chosen bundles open with /usr/bin/open -a. vectorcraft-cli is looked for in the same
  bundle, then in known installs. Logic is compiled and unit-tested on every Unix.
- Windows "not found" errors name the dialog's "Other application" option.
- Native preview hash verification is remembered per source allocation in a 32-entry
  Weak-keyed LRU (no strong references, no reusable stale addresses, lock not held
  while hashing), so refreshes and warp frames hash a shared source once.
- source_box uses the new io::svg::bounded_canvas_bounds for SVG without Stack Mode, so
  warp setup gets a frame for drawings whose editable layer caches exceed the budget.
  Stack Mode and Edit Contents stay strict. Exact 24,000,000-pixel boundary tested.
- Document every non-test function this PR adds; describe macOS behaviour in
  docs/embedded-vector-editing.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 03:02:40 +03:00
Don Omondi c129dd50e0 Merge main and preserve original-format embedded vector save-back 2026-10-27 00:45:48 +03:00
Federico Olivares 8aaa03e2db Merge main into the integration batch 2026-10-26 11:52:45 -03:00
aiongg da02d0ef2d Merge remote-tracking branch 'upstream/main' into docking-adopt
# Conflicts:
#	Cargo.toml
#	crates/ui-egui/Cargo.toml
2026-10-26 00:12:23 +00:00
aiongg cece50d513 Merge pull request #9386 from davidmann4/integration-batch-8
Integration batch 8: 37 reviewed community PRs on main
2026-10-25 20:04:41 -04:00
Federico Olivares 9f588ad085 Merge main into the integration batch 2026-10-25 20:42:06 -03:00
skylar taylor-barrick 718950cab6 chore(deps): refresh safe dependency bumps (#9558)
serde_json 1.0.154, proptest 1.12, criterion 0.8, crc32fast 1.5.3, rmcp 3.6,
tokio 1.54.1, base64 0.23 (direct deps), schemars 1.2.3, wat 1.262, libc 0.2.191,
objc2 =0.6.5, arboard 3.7, open 5.4.5, muda =0.21.2, winresource 0.1.34.
2026-10-25 19:30:07 -04:00
Dylan M. Taylor 5bb8536541 build: pin craft-update to craft-libs main (495e597) (#9548)
Picks up the startup prompt without the glyphs a font may lack (storytold/craft-libs#343, #344): the close mark is painted and the version pill is ASCII, so apps that panic on a missing glyph no longer take the prompt down.

Part of tracking issue storytold/craft-libs#319
2026-10-25 17:55:21 -04:00
Federico Olivares 9f4290b0d0 Merge main into the integration batch 2026-10-25 17:31:11 -03:00
Dylan M. Taylor 669a7f8a94 feat(updates): add startup self-update prompt modal (#9322)
* feat(updates): startup update prompt modal and direct self-updating

Release checks and the install go through craft-update's Updater: the engine's Help ▸ Check for Updates command keeps its status machine, its transport asks craft-update instead of a private GitHub client, and a found release opens the startup prompt. An install holds back while documents are unsaved, and a finished update closes through the guarded close path. craft-update stays out of the wasm build.

Ref: storytold/craft-libs#319

* fix(updates): address review feedback

Wake the UI when a manual check is queued from a menu callback; the update prompt owns the keyboard while it is open (LightCraft); Download opens through the desktop URL hook (FilmCraft); the Help menu dispatches through menus::invoke (FigCraft); print jobs and comment drafts hold an install back (WordCraft); Check for Updates is a registered command (GridCraft); an install holds back while documents are unsaved.
2026-10-25 15:55:45 -04:00
David Mann 8812fe1e73 Merge main (egui 0.37, #9363)
Conflicts: the batch's wheel reads (#5547 Animated Zoom) keep their extra
argument with main's ids (`Id::unique`, `ui.scope_id()`); crop presets keep
#6620's `apply_choice` with main's accessible name; Bevel & Emboss keeps
#9370's per-mode id with main's name argument; the Stroke field keeps
#7203's gradients with main's name; tone.rs keeps #9139's move of the
Histogram panel to histogram_panel.rs (main only renamed ids there);
translation catalogs as unions.

Not flagged by git, the batch's new code follows egui 0.37 too: dropdowns
take an accessible name (Histogram Channel/Source #9139, tool Mode #5504,
Art History Style #1610, New Snapshot From #3567), MouseWheel events carry
`source`, `WidgetType` is `Role` (ColorButton is ColorWell, #7203),
`Id::new`/`Ui::id` are `Id::unique`/`Ui::scope_id`.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-25 20:53:11 +01:00
skylar taylor-barrick 5c9192bbe2 Migrate PhotoCraft to egui 0.37 (#9363)
* egui037: name each control for what it sets, and order the eager fonts for the UI

CodeRabbit review follow-ups on the migration: the Artboard X/Y fields, the CAF
dropdowns, the channel Solidity field, the GPU backend/adapter dropdowns, the
corner radius fields and the canvas extension colour all had an accessible name
that named another control (or was shared by four). The eager craft-fonts
registration now puts the UI Japanese face first, as the lazy loader does, so
Japanese UI is not drawn in the manifest's Mincho face and shared Han characters
do not take Japanese forms.

Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>

* egui037: rustfmt the eager craft-font order

---------

Co-authored-by: Dylan M. Taylor <dylan@dylanmtaylor.com>
Co-authored-by: Codebuff <noreply@codebuff.com>
2026-10-25 15:04:35 -04:00
Phil Trinh 4915f0970e PSD/PSB open without reading the whole file: channel data read as it is decoded, in bands straight into tiles (#5106)
Opening a 2.14 GB PSD (2000×2000, 109 layers, 821 MB of embedded smart objects) peaked at
7.28 GB and took 6.8 s; it now peaks at 3.00 GB and takes 3.6 s (macOS peak memory footprint,
`cargo run --release -p photocraft-io --example psd_open_mem`).

- photocraft-psd: `PsdFile::from_source` parses from a `ReadAt` source (`FileSource`: pread /
  seek_read in bounded reads). Channel data and the merged image become `Stored` ranges read
  when decoded; the model equals `from_bytes`'s and writes back the same bytes (tests compare
  the two on every generated file, including Lr16/Lr32 layer blocks and truncated files).
- `ChannelData::row_decoder` decodes any band of rows: RLE via its row table (a stored channel
  reads only the band's bytes), raw by offset, ZIP inflated once.
- photocraft-io: `import_file` opens a path; PSD/PSB through `from_source`, other formats read
  whole. Layers decode in bands of whole tile rows (~32 MB) into tiles: no whole-layer plane or
  interleaved buffer. Global blocks move into the document instead of being copied; finding an
  embedded smart object no longer copies every file in `lnk2`.
- photocraft-raster: `Surface::share_uniform_tiles` + `TileInterner`; the PSD import shares
  single-value tiles (backgrounds, fill caches, masks) across layers.
- The background open job and the CLI/MCP (`automation::files::open`) use `import_file`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-26 02:37:20 +08:00
aiongg 292f869d8a Merge remote-tracking branch 'upstream/egui037' into docking-adopt
# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	crates/ui-egui/src/gallery_ui.rs
#	crates/ui-egui/src/layer_props_ui.rs
#	crates/ui-egui/src/lib.rs
#	crates/ui-egui/src/panel_docking.rs
#	crates/ui-egui/src/panel_docking_tests.rs
#	crates/ui-egui/src/view_cmds.rs
#	crates/ui-egui/tests/it/batch_export_options.rs
2026-10-25 17:51:11 +00:00
aiongg a4c74d84ea Panels: pin craft-libs at 5bbe9f62 2026-10-25 16:28:09 +00:00
aiongg e3f242af38 Merge remote-tracking branch 'upstream/main' into docking-adopt 2026-10-25 16:25:21 +00:00
David Mann c01dc04b5f Revert "Merge PR #4573: Interface: Animation Effects follows the system setting, or is on or off"
This reverts commit acd7e07252, reversing
changes made to bc0354db5d.
2026-10-25 16:36:09 +01:00
David Mann 38609e5615 Merge PR #8885: PSD: spot channels in Photoshop's polarity; PSDs from earlier PhotoCraft versions keep their ink
Merged with our fix-up branch pr-8885-fixup (8f6863f53) on the author's head 996b55eb4.

Conflicts resolved:
- crates/io/src/tiff_layers.rs: #9148's tiff_source (an empty LMsk gets Photoshop's 14 bytes)
  gives way to #8885's tiff_image_source, which writes the same bytes for an empty or short
  LMsk; #9148's test stays.
- crates/io/src/flat.rs: #8776's DDS alpha step and #8885's TIFF channel stamp both run.
- crates/io/Cargo.toml, Cargo.lock: #8402's zune dev-deps and #8885's tiff dev-dep.
- crates/io/tests/it/tiff_layers.rs, docs: unions; docs/scorecard.md kept as is, regenerated at
  the batch gate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:28:00 +01:00
David Mann 4365c0537d Integration: merge main, resolve conflicts (#8885)
psd_import.rs keeps main's warning for an incomplete merged extra channel
next to the PR's Photoshop spot polarity. people.toml takes main's entries
plus jasallen's own. Docs take both sides' status lines and revision rows;
docs/scorecard.md is regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 16:07:44 +01:00
Federico Olivares 5554a342bf Merge main into the integration batch 2026-10-25 11:58:39 -03:00
David Mann ef98aa507a Merge PR #3281: Vanishing Point: tear off planes and clone in perspective (#3280) 2026-10-25 15:57:43 +01:00
David Mann bb39b4a8dd Revert "Merge PR #1199: Add optional local models for subject matting and object selection"
This reverts commit 5f2a7b9903, reversing
changes made to 9ef4c0a487.
2026-10-25 15:19:27 +01:00
aiongg 36d69e550d Panels: pin craft-libs d24e4bcc 2026-10-25 14:11:34 +00:00