215 Commits
Author SHA1 Message Date
06c1b9ae07 Use crw craftlib (#3503)
* CRW-LIB: decode Canon CRW through the shared craft-crw crate

LightCraft decodes Canon CRW (the CIFF raws of the EOS D30, D60, 10D, 300D and the
PowerShot G1/G6) through craft-libs' `craft-crw`, the clean-room decoder derived and
verified on the `clean-room-crw-format-decode` branch and moved there with its frozen
tables and derivation record. `crates/raw/src/vendor/crw.rs` is now the adapter: it maps
the crate's header and samples onto `RawImage` (CFA, levels, active area, orientation,
as-shot white balance, the make/model/time records a CRW keeps instead of Exif) and
converts the capture time through chrono. The dependency is a local path
(`../craft-libs/crates/crw`) until the craft-libs branch merges; then it becomes a git
revision.

Everything LightCraft-side from that branch comes along unchanged: `probe_bytes` fills
metadata gaps from the decoder's records so CRW imports name their camera; the EOS D60
bundled camera profile and its chart-measured dual-illuminant matrices (`chart_table.rs`,
`spectral::Camera` carries its illuminant pair) give the D60 a Kelvin white-balance scale;
CRW joins the JPEG-fitted starting look, the catalog's raw formats and `lightcraft-cli
calibrate`; `RENDER_CACHE_VERSION` 71; the CC0 CRW corpus entries for `cargo xtask corpus`;
coverage, parity, gaps, raw-parity, target-app-parity and ROADMAP updates. The G5 stays
preview-only (the crate refuses it with the reason) and the robustness test keeps its CRW
sample.

What does not come along: the decoder, its tables and `crw_oracle.rs` (now craft-crw's
digest-pinned sample test) and the derivation record, which lives in craft-libs
`crates/crw/clean-room/`. `clean-room/crw/` here keeps only the EOS D60 chart-calibration
document and its capture list, with a README pointing at the record.

Gates: fmt, clippy -D warnings (raw all targets; engine, catalog, cli), lightcraft-raw tests
(475 + 134, the corpus files decoding through the adapter), catalog tests, engine lib tests
(1,300 pass; the two failures, `tests_import::recursive_discovery_…` and
`originals::tests::write_targets_pin_absent_paths_…`, are in files unchanged from main),
`cargo xtask parity`, `assets`, `layers`, `coverage.py --check`.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* no message

* no message

* Update documentation after moving code to craft-libs

* Review coment fixes

* CRW: pin craft-crw f3b62ec, a truncated entropy stream is Corrupt

craft-libs #472 makes craft_crw::decode refuse a stream that ends more than
Limits::max_stream_end_fill (64 samples, one block) before the frame does,
instead of filling the rest with predictor values and returning success.
The adapter already maps craft_crw::Error::Corrupt to RawError::Corrupt;
a regression test proves a truncated CRW now fails at this boundary (it
decoded as a flat frame on the old pin) while its header still reads.

Only craft-crw moves; craft-ui/docpath/update/window stay on c5a1cbf.

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

* Code review comment fix

* Add some tests

---------

Co-authored-by: Robert Woldberg <314159+rwoldberg@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-11-02 20:41:34 -05:00
Brandon ThomasandClaude Opus 5.5 32d569ad5d Release 0.18.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 19:26:25 -05:00
Brandon ThomasandClaude Opus 5.5 5a09d07530 Release 0.17.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 13:57:58 -05:00
aiongg e80c3e3e13 Merge upstream main into integration-r3 2026-10-31 05:09:34 +00:00
aiongg e31f826d5f updates: show check results with craft-update's CheckResultDialog 2026-10-31 04:42:29 +00:00
Brandon ThomasandClaude Opus 5.5 cdf00cc84b Release 0.16.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 23:22:53 -04:00
aiongg ee0a627536 Merge track r3-t10
# Conflicts:
#	crates/engine/src/cmd/masks.rs
#	crates/ui-egui/locales/de.json
#	crates/ui-egui/locales/es.json
#	crates/ui-egui/locales/fr.json
#	crates/ui-egui/locales/ja.json
#	crates/ui-egui/locales/ka.json
#	crates/ui-egui/locales/pt-br.json
#	crates/ui-egui/locales/ru.json
#	crates/ui-egui/locales/uk.json
#	crates/ui-egui/locales/zh-hant.json
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:31:38 +00:00
aiongg 1f111b5e80 Merge track r3-t07
# Conflicts:
#	crates/engine/src/tests/libops.rs
#	docs/gaps.md
#	docs/parity-checklist.md
#	docs/whats-new.md
2026-10-31 02:30:21 +00:00
aiongg 78e70ab8f8 Merge PR #2545: Issue #136: applying the GPU setting never waits for the device on the UI thread 2026-10-31 02:10:21 +00:00
aiongg 0c264a6a49 Merge PR #2290: #2284: read the Exif and XMP items of HEIF files 2026-10-31 02:06:35 +00:00
Nathaniel Ledford c208859ec2 PERF-SMART: a filePath rule over a non-ASCII path folds case in stack buffers instead of allocating two strings per photo 2026-10-30 09:09:43 -04:00
Dylan M. Taylor 5194cc20de UPD.1: honor pretend versions and track the updater icon in CI (#3365) 2026-10-30 09:02:24 -04:00
Dylan M. Taylor 445dd3106e Update prompt shows the app icon and accent color instead of a letter (#3362)
UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#f2a516, 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):
- crates/engine/src/cmd/export.rs
- crates/ui-egui/src/dialogs/rules_editor/rules_move.rs
- crates/ui-egui/src/panels/detail.rs
2026-10-30 01:27:49 -04:00
Dylan M. Taylor 260d797acc deps: bump tar, zip, roxmltree, rustls-webpki and symphonia to their latest versions (#3358)
- `rustls-webpki`: 0.102.8, 0.103.15 → 0.102.8, 0.103.16
- `zip`: 7.2.0, 9.1.0 → 7.4.0, 9.1.3

Lockfile only.
2026-10-29 22:21:27 -04:00
Brandon ThomasandClaude Opus 5.5 e381c1ae6b Release 0.15.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 12:09:24 -04:00
aiongg 94ea495bdb Merge pull request #3020 from dotCooCoo/fix/windows-hard-link-write-target
Originals: on Windows a hard link to an original counts as that original
2026-10-27 13:46:50 -04:00
aiongg 3a3e49af53 fix(ui): dropdown menus grow back after a search with no matches (#3154)
* Use craft-ui's dropdown so menus grow back after shrinking

The album picker keeps its choices and search field in a fixed header and scrolls only
the list; combo_box and the print dialog's combos use craft_ui::ComboBox. egui::ComboBox
is now disallowed by clippy.

* 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:27:42 -04:00
dotCooCoo 0c7640f7d3 Reject unavailable Windows file identities in strict comparisons
Return an error when either file index is zero. Keep the resolved-path fallback for lenient comparisons. Test both unknown-identity orderings and distinguish identity lookup failures from known-original refusals.

Merge main at 662df66f.
2026-10-26 20:28:34 -07:00
tecari0andClaude Sonnet 5.5 3ae66b2d2f Merge main into fix-2284-heif-exif
Resolve the conflict in the crates/meta/src/lib.rs doc comment: list
both PSD/PSB (from main) and HEIF/HEIC/AVIF (from this branch).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 15:15:45 -07:00
dotCooCoo 4826fff734 Originals: a Windows file index of 0 does not identify a file
same_file::is_same_file treats two files with the same volume serial
number and file index as one file, also when both report index 0. The
Windows comparison now reads both identities through winapi-util and
accepts a match only when both file indexes are nonzero; otherwise the
resolved paths are compared, as for a volume without file indexes.
2026-10-26 11:34:06 -07:00
dotCooCoo a97f19605c Originals: compare lengths before the Windows file identity
On ReFS two files can share the 64-bit file index that same_file
compares, so same_file now rejects files of different lengths before
it checks the volume serial number and file index.

The hard-link test skips with a recorded reason when the temporary
folder's volume has no hard links (FAT/exFAT, some shares), the same
errors publish_new treats as a volume without hard links.
2026-10-25 22:32:37 -07:00
OneSlips c515219270 Merge remote-tracking branch 'origin/main' into pr/gpu-setting-no-wait 2026-10-26 14:50:08 +10:00
aiongg 21a53cf61f Merge title-bar-movable (lightcraft#2930) into docking-adoption; every craft-libs crate at craft-libs main 1e6f127 2026-10-26 02:20:20 +00:00
aiongg 1952d4fd3c Merge upstream main into docking-adoption 2026-10-26 02:18:38 +00:00
aiongg 003779ce51 Merge upstream main into title-bar-movable; craft-window at craft-libs main 1e6f127 2026-10-26 02:18:22 +00:00
skylar taylor-barrick 387bed199f chore(deps): refresh safe dependency bumps (#2994) 2026-10-25 19:30:51 -04:00
dotCooCoo 7ebbb17a82 Originals: on Windows a hard link to an original counts as that original
safe_file::same_file compared length and canonical paths on every
platform other than Unix. On Windows canonicalize returns a hard link's
own path, so a hard link to a library original under another name was
not the same file, and pin_write_target accepted it as a screenshot
destination. For this reason the engine test
write_targets_pin_absent_paths_and_recheck_the_current_library failed
on Windows.

On Windows same_file now first compares the volume serial number and
file index through the same-file crate (already in Cargo.lock through
walkdir), then falls back to the resolved-path comparison. The catalog
crate takes same-file as a Windows-only dependency.
2026-10-25 15:55:21 -07:00
Dylan M. Taylor 522beb0c3e build: pin craft-update to craft-libs main (495e597) (#2990)
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:29 -04:00
Dylan M. Taylor 2833d8fc9a Merge pull request #2780 from storytold/security/raw
security/raw: bound hostile-memory paths in the raw decoders
2026-10-25 16:45:57 -04:00
Dylan M. Taylor d8ceb3a6af security/meta,merge,raw,tiff,denoise: bound memory sized by attacker-shaped inputs
XMP flattening, sparse-focus EXIF decode (plus the maker-note and TIFF value
budgets), lossy-DNG chunk staging, panorama stitch frames, the reference ONNX
executor's tensors and the denoise product reader all now reject or cap what a
malformed file can make them allocate: each result is checked before the
memory behind it is reserved, every regression carrying a test that fails
without its bound.
2026-10-25 15:42:19 -04:00
Dylan M. Taylor 2d3c7275b2 fix(updates): drop the manual window's custom id; pin craft-update to craft-libs main (db19c37) 2026-10-25 15:07:57 -04:00
OneSlips 23c669ece5 Merge remote-tracking branch 'origin/main' into pr/gpu-setting-no-wait 2026-10-26 05:04:58 +10:00
Dylan M. Taylor 8e5a6fc2e7 refactor(updates): hold the install back while documents are unsaved 2026-10-25 14:53:33 -04:00
Dylan M. Taylor 2b9317519c feat: startup update prompt modal and direct self-updating
The update flow (check at start or on request, the startup prompt, the self-update worker) is craft-update's Updater; the app only supplies the suite, its close path and its status window. The check at start is opt-in for the desktop app, and the Windows update helper runs before argument parsing.

Ref: storytold/craft-libs#319
2026-10-25 14:22:14 -04:00
Dylan M. Taylor 1a3d9aff1e Merge pull request #2913 from storytold/codex/egui-037-lightcraft-20261023
Migrate LightCraft to egui 0.37 with current main preserved
2026-10-25 14:10:49 -04:00
aiongg 672baaea46 Merge lightcraft#2913 (egui 0.37) into docking-adoption; craft-ui and craft-docpath at craft-libs main a091680 2026-10-25 17:36:59 +00:00
aiongg c01d4c7074 Merge lightcraft#2913 (egui 0.37) into title-bar-movable; craft-window at craft-libs main a091680 2026-10-25 17:19:47 +00:00
aiongg 649e84b0ed Top bar: repin craft-window to craft-libs main 5bbe9f6 2026-10-25 16:25:27 +00:00
aiongg 1291d391d9 Docking: repin craft-ui and craft-docpath to craft-libs main 5bbe9f6 2026-10-25 16:25:25 +00:00
aiongg f52df54f13 Merge upstream main into title-bar-movable 2026-10-25 16:24:58 +00:00
aiongg fd26427cab Merge upstream main into docking-adoption 2026-10-25 16:24:58 +00:00
aiongg 901a115bf7 Top bar: repin craft-window to craft-libs main ea4c823 2026-10-25 13:53:10 +00:00
Brandon ThomasandClaude Opus 5.5 03c88c166c Release 0.14.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 09:26:32 -04:00
aiongg 19ab821477 Top bar: repin craft-window to craft-libs 4093ea4; the title bar is announced from empty_area's response 2026-10-25 12:41:42 +00:00
aiongg 577b6cfced Top bar: the title-bar drag uses craft-window's title_bar, and a panel over the bar keeps the window still on macOS 2026-10-25 12:35:44 +00:00
aiongg b477efd3da Docking: repin craft-ui and craft-docpath to craft-libs b6d35e2 2026-10-25 12:17:31 +00:00
aiongg 4e6c210a5f Docking: repin craft-ui and craft-docpath to craft-libs 4dc543c 2026-10-25 05:57:50 +00:00
aiongg e8588b925b Docking: repin craft-ui and craft-docpath to craft-libs 8a503cf 2026-10-25 03:59:13 +00:00
OneSlipsandClaude Opus 5.5 9a6ac9aea7 Issue #136: a non-waiting GPU query starts the device; Settings repaints while it starts
- `app.gpu {wait: false}` with GPU rendering on starts creating the device in the background
  (`warm_up`), so a caller that never waits still gets an answer later. `warm_up` starts one
  thread at most, and may start again if GPU rendering was turned off before it ran.
- Settings > Performance asks for a repaint every 250 ms while it shows "GPU: starting…": the
  device is created on another thread, which doesn't wake the window.
- CLI test: `{enabled: true, wait: false}` answers enabled with available, adapter and reason
  null (skips with LIGHTCRAFT_GPU=0, since it starts creating a device).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 13:48:25 +10:00
skylartaylor c057ccc23f Migrate LightCraft to egui 0.37 and reconcile dependency and font locks
Preserve current main, adapt frame/input and IME handling, and keep library
check results stable across layout passes. Include the matching Nix font lock
and reviewed attribution changes.
2026-10-25 02:54:42 +01:00