Commit Graph
117 Commits
Author SHA1 Message Date
aiongg 562f550221 Merge main into backlog-r1 2026-10-31 05:27:25 +00:00
aiongg 5c18340e3f docs: tidy agent, contributor and asset docs 2026-10-31 04:17:32 +00:00
aiongg 8595147b71 Merge integration track i18n 2026-10-31 02:17:34 +00:00
aiongg 69ed33ae57 Merge integration track io 2026-10-31 02:17:17 +00:00
aiongg abeac167cc Merge PR #1423: #1421: roadmap.md and gaps.md G14: mark shipped codecs and languages as done 2026-10-31 02:15:16 +00:00
aiongg 6ea11662a1 Merge PR #1412: #1411: docs/gaps.md: remove entries for features that already shipped 2026-10-31 02:14:54 +00:00
aiongg 2a501fa39e Merge PR #2116: feat(media): import PSD files as their flattened composite (Merge All Layers)
# Conflicts:
#	docs/file-format-parity.md
#	docs/gaps.md
2026-10-31 02:14:38 +00:00
aiongg 59695f22ae Merge PR #2344: i18n: Turkish (tr) interface catalog (#1377) 2026-10-31 02:13:56 +00:00
aiongg 7e608027ea Merge PR #2288: i18n: Russian covers the whole interface 2026-10-31 02:13:09 +00:00
aiongg 5e5c67a372 Merge PR #1617: #1583: still images honour EXIF Orientation 2026-10-31 02:10:02 +00:00
vangel76andCodex 0bd571cb9f Merge upstream/main into docs-roadmap-g14
Keep GIF transparency notes and refresh the existing localization counts against the merged tree.

Co-Authored-By: Codex <noreply@openai.com>
2026-10-30 22:52:54 +01:00
MOzcelik14 2e2f10498f Merge branch 'upstream/main' into feature/turkish-localization
Resolve conflict in crates/ui-egui/src/i18n/tests.rs using switch_and_check
helper and add 22 new catalog entries to tr.tsv matching upstream additions.
2026-10-30 13:50:46 +03:00
Michael ButlerandCodex d74379858d Export: preserve optional binary transparency in animated GIFs (#3396) (#3423)
* #3396: preserve binary transparency in animated GIF exports

Enable Include Alpha Channel for GIF with an explicit 128/255 threshold. Cover transparent, opaque and partial-alpha pixels, frame disposal and the Export UI. Document the behavior and add the requested username-only contributor credit.

Co-Authored-By: Codex <noreply@openai.com>

* #3396: clarify when the GIF alpha threshold applies

Begin the export hint with "When enabled," and wrap the longer label so its explanation remains visible. Alpha behavior and threshold wording remain unchanged.

Co-Authored-By: Codex <noreply@openai.com>

* #3396: cover GIF transparency during palette quantization

Round-trip two frames with more than 256 post-conversion RGBA colors, a moving isolated transparent pixel, and opaque black and near-black neighbors. Require exact alpha and bounded RGB error. Document commands for the GIF and export test suites; leave the encoder unchanged.

Co-Authored-By: Codex <noreply@openai.com>

---------

Co-authored-by: Codex <noreply@openai.com>
2026-10-30 01:22:02 -04:00
MOzcelik14 9fc1631cbd Merge remote-tracking branch 'upstream/main' into feature/turkish-localization 2026-10-27 11:35:55 +03:00
Marco Arnulfo c41a8fa561 Program: drag a marquee or Shift-click to select several mask vertices, and move them together (#3209) 2026-10-25 09:42:57 -04:00
dotCooCoo 7749c41691 docs: gaps.md revision history records the G8 cut drag 2026-10-24 09:43:44 -07:00
dotCooCoo a988b671f7 effect controls: drag a transition's cut to move it with the transition
In a selected transition's own timeline in Effect Controls, the cut line
over the transition can now be dragged. While it is dragged, the clips
and the transition are drawn where the rolling edit would put them, with
the same limits as `timeline.roll`. On release one rolling edit moves
the cut, so the clips' In and Out points change and the sequence keeps
its length. The ends of the transition still resize it, and the rest of
it still slides it.

A rolling edit now stops where the transition on its cut would leave
one of its two clips. When a ripple trim, a slide or a ripple speed
change moves a cut far enough that the transition on it would leave its
two clips, the transition is moved back within them, shortened when the
clips are now shorter than it, and its stored alignment is updated.
2026-10-24 05:06:39 -07:00
vangel76andClaude Sonnet 5.5 7f1649761e Merge upstream/main into docs-roadmap-g14
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-24 13:24:33 +02:00
MOzcelik14 b1bc3decea Merge upstream/main into feature/turkish-localization 2026-10-24 11:03:36 +03:00
aiongg 0a881266c8 CI: xtask ci in the dev profile, one test binary per crate, nextest (#2860)
* Tests: one integration-test binary per crate

Each crate with several tests/*.rs files keeps them as modules of tests/it/,
so cargo links one test executable per crate instead of one per file. Files
that change process-wide state or time a workload stay binaries of their own.

* Profiles: line tables for workspace crates, no debug info for dependencies

* Windows ARM64: nightly and on release pushes instead of every push to main

* xtask ci: clippy and tests in the dev profile

The release profile's thin LTO and single codegen unit made linking the test
binaries take most of the gate. The codec and audio crates stay at opt-level 3
in the dev profile, so their tests run at release speed.

* xtask ci: nextest, doctests, no examples, one wasm check

Tests run with cargo nextest when it is installed (cargo test otherwise) and
build with --lib --bins --tests, so examples aren't linked; doctests run
separately. The wasm check keeps going past the first failing crate. VP8
fixture generation locks across processes, since nextest runs each test in
its own.

* VP9 synthetic fixtures: write aside and rename

A test in another process could read a fixture ffmpeg was still writing.

* Fuzz tests: a third of each sweep by default, all of it with FILMCRAFT_FUZZ_ITERS

Every seed, mutation kind and thread count still runs. Header bytes each get
one overwrite value and two bit flips in rotation, so every value and bit
index still occurs across the region. FILMCRAFT_FUZZ_ITERS=N runs the whole
sweep plus N random rounds per seed, as before.

* Platform fallback tests: one failure point per hybrid path

The failure-anywhere test injected a failure at four points around every
restart point; the hybrid's paths differ only in the first GOP, around the
second and last restart points, at the end and never. The replay test needs
the first two GOPs.

* Export tests: shorter ranges with the same checks

The bitrate test measures 0.5–1.5 s, where each preset reaches its own
target (on 0–3 s the simple demo left two presets at the same rate). The
every-preset test exports three frames per preset.

* Audio tests: effects in parallel, a table-driven FFT for the Opus quality metric

The extreme-settings test keeps both settings and the 40 s tail for every
effect, one thread each. The Opus quality metric's FFT builds its twiddles
once and allocates nothing per transform (same algorithm and summation order).

* CI: dev-profile gate with nextest

xtask ci no longer builds with --release, so the release-profile overrides
go; nextest is installed for the test step.

* CI: apt packages through the cached install-apt-packages action

* Review fixes: fuzz tests with a panic hook in their own binaries, loud fixture lock

The fuzz tests of av1, h264, hevc, mpeg2v, vp8 and vp9 count panics through
a process-wide hook, so a panic in another test of the same process would
fail them; they are binaries of their own again. The VP8 fixture lock fails
the test instead of skipping it silently, and the full-sweep doc comments say
how many truncation points the full run samples.

* Fuzz tests: rotate the default subset per run (FILMCRAFT_FUZZ_SEED replays one)

* platform tests: decode-switch tests in their own binaries, one NVENC lock
2026-10-23 13:34:16 -04:00
Marco Arnulfo e9127e0890 docs: record the PSD import in the parity doc and gaps (#2116) 2026-10-21 12:31:58 +02:00
MOzcelik14 81dfe43350 Merge upstream/main into feature/turkish-localization 2026-10-20 11:16:48 +03:00
vangel76andClaude Sonnet 5.5 50eceb6981 Merge upstream/main into docs-roadmap-g14; re-measure G14 on merged tree
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 01:05:48 +02:00
vangel76andClaude Sonnet 5.5 73d38d9c06 docs: leave G14 localization text to #1423
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 01:05:18 +02:00
vangel76andClaude Sonnet 5.5 ba4cc17c40 Merge upstream/main into docs-gaps-stale
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 01:04:54 +02:00
grib_job 08432644e5 i18n: Russian catalog covers the whole interface
- ru.tsv: all 3,592 strings of the reference catalog (was 355), translated
  from the English sources with ordinary, Premiere-style Russian vocabulary.
  Fixes the known mistranslations (Sequence -> Последовательность, Bin ->
  Корзина, Lumetri Scopes -> Осциллограммы Lumetri, Wipe -> Вытеснение,
  Normalize Mix Track, «мастер-дорожка») and applies one glossary throughout.
- Tests: russian_covers_the_whole_interface requires every Spanish entry and
  no dead ones; a font test covers the Cyrillic alphabet including «ё»;
  System Language maps ru-* to Russian.
- Docs: localization-parity, roadmap, gaps, ROADMAP, the ui-egui README and
  the catalog's attribution sidecar.
2026-10-19 20:01:55 +03:00
irgendwasmitfelixandClaude Opus 5.5 1d7e2238b0 i18n: German has every Spanish entry; scope the coverage claims
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 12:32:36 +02:00
Claude f4b1bee71f i18n: German (de) covers the whole interface
#630 shipped German for the menus. This adds the other 3,213 strings, so
de.tsv has every entry of the Spanish catalog (3,590): panels, dialogs,
effects and their parameters, transitions, presets, Settings, shortcut
commands, export presets, tooltips and status messages. Same style as the
menus (du, infinitives, placeholders, ellipses and escapes kept); the
glossary in the header is extended. The 377 menu entries are unchanged.

german_entries_cover_the_original_menu_catalog required every entry to be
a menu label. It becomes german_covers_the_menus_and_has_no_dead_entries,
like the French and Italian tests: every entry needs a Spanish counterpart,
the core menus and the native macOS app menu are required, later strings
may stay English. german_renders_with_bundled_fonts checks the umlauts,
ß and German quotation marks against the bundled fonts.

Docs: ROADMAP.md, docs/localization-parity.md, docs/gaps.md, ui-egui README.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KJhvSJ5odpWzFw9HhPzAix
2026-10-19 09:41:57 +02:00
MOzcelik14 17eda1dea6 i18n: Turkish (tr) interface translation and language support
Add crates/ui-egui/src/i18n/tr.tsv, clean-room Turkish translations matching every entry in the Spanish catalog plus the native macOS Settings menu (3,590 entries).

Language::Tr ("Türkçe") is persisted as `tr` in `general.interfaceLanguage`; it appears in Edit > Language (and native macOS menu), Settings > General, and System Language picks it for `tr-*` locales.

Tests cover the core menus, reject dead entries, verify bundled font rendering for Turkish characters (Ç, Ğ, İ, Ö, Ş, Ü, ç, ğ, ı, ö, ş, ü), switching/persistence across restarts, and locale matching. Attribution sidecar, ATTRIBUTION.md, ui-egui README, gaps.md, and localization-parity.md updated.
2026-10-18 12:53:46 +03:00
Marco Arnulfo b70a36c7d8 feat(media): import PSD files as their flattened composite (Merge All Layers) 2026-10-16 00:39:39 +02:00
vangel76andClaude Sonnet 5.5 a1969eb397 Merge upstream/main into docs-roadmap-g14
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 19:05:28 +02:00
vangel76andClaude Sonnet 5.5 a0cdb46c2e Merge upstream/main into docs-gaps-stale
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 19:04:11 +02:00
Andrew b85f626f86 #1583: still images honour EXIF Orientation
Portrait phone photos imported sideways: decode_raster decoded JPEG,
PNG, WebP and TIFF stills with image::load_from_memory, which never
applies the EXIF Orientation tag.

The orientation is now read from the headers alone (no pixels decoded,
the probe's copy of the file dropped before the real decode) and
applied with DynamicImage::apply_orientation before the RGBA
conversion, so MediaInfo, the frame, the auto anchor and Scale to
Frame Size all see the upright size, like rotated phone video. Pixels
still go through load_from_memory, keeping its allocation limit for
hostile headers. A missing, unknown or damaged tag means no transform,
never a failed import.

Tests build every orientation 1-8 in JPEG, PNG, WebP and TIFF and check
size and pixel placement against the EXIF definition, plus open_bytes,
image sequences (also with mixed orientations), invalid values and a
mutation fuzz under catch_unwind. Docs list what is left (YCbCr TIFF,
DNG, the export image overlay) and the effect on projects saved before.
2026-10-13 11:25:05 +02:00
Brandon ThomasandClaude Opus 5.5 48cae3e5a3 Merge origin/main into #1389 (Italian beside Korean: 12 languages)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 02:40:02 -04:00
Brandon Thomas 6b2a36e2dd Merge remote-tracking branch 'origin/main' into fix-1389 2026-10-13 02:04:51 -04:00
Brandon ThomasandClaude Opus 5.5 9c00138b4b Merge origin/main into #1404 (gaps.md: keep only the PXR24 edits)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 01:19:55 -04:00
Brandon Thomas 76f423db77 Merge pull request #1532 from JeremyYao/fix/windows-duplicate-vulkan-driver
graphics: draw with the newer driver when Windows lists one GPU through two versions of it (#609 on the #827 start-up)
2026-10-13 00:03:37 -04:00
Brandon Thomas e8dd5ffc45 Merge pull request #1410 from vangel76/gap-radiance-hdr
#1407: import Radiance HDR stills and image sequences
2026-10-13 00:03:11 -04:00
Brandon Thomas 4ac34587b0 Merge pull request #1409 from vangel76/feat-gap-slot1
#1408: Shift constrains mask vertex and whole-mask drags to 45°
2026-10-13 00:03:11 -04:00
Jeremy YaoandClaude Opus 5.5 1d1cec80b1 graphics: draw with the newer driver when Windows lists one GPU through two versions of it (#609)
A PC whose GPUs were installed from different driver packages of one vendor
(an ASUS G513QY: the integrated Radeon on the 2021 package, the RX 6800M on a
2026 one) gives the Vulkan loader two versions of that vendor's driver, and
the RX 6800M is listed once through each. wgpu's request_adapter takes the
first discrete entry, the 2021 driver's, and the window drawn through it dies
inside amdvlk64.dll (0xc0000005) before it paints: the main thread is in the
2021 driver, the fault on a thread of the 2026 one, no Rust frame anywhere.
Left to the #820 ladder, two crashed launches end in DirectX 12 only.

filmcraft_gpu::adapter::choose is wgpu's own rule (the adapters that can draw
to the surface, by device type for WGPU_POWER_PREF, then as enumerated) with
one addition: when the adapter that rule picks is listed again by the same
driver (same backend, device type, PCI vendor and device and driver name; the
same bus id when both report one), the entry exposing the most wgpu features
is used, i.e. the newer version (68 against 60 here, a strict superset).
Without such a duplicate the choice is wgpu's own, and entries of one GPU from
different drivers (RADV and AMDVLK, a vendor's driver and Dozen) are left
alone.

graphics::apply installs it as egui-wgpu's native_adapter_selector in the
default mode on Windows, as #609 was asked to be rebased onto the #827
start-up. DirectX 12 only, software mode and the other platforms keep their
adapter choice, and the ladder is untouched. The adapters and the choice go
to the log.

Tests: the laptop's listing (wgpu's rule picks the entry that crashed, choose
the other one), listings without two versions of one driver over every power
preference (choose equals wgpu's rule), surface, bus id and driver cases, and
one against the adapters of the machine running the tests (the rule is what
request_adapter returns there).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:31:02 -04:00
vangel76andClaude Sonnet 5.5 5ee1b652b1 #1421: roadmap.md and gaps.md G14: mark shipped codecs and languages as done
E-AC-3 (#788, closes #647), AVI import (#650, closes #598), Russian (#610),
French (#804), Indonesian (#878), pt-BR (#866) and German menus (#630) are
merged; roadmap.md Alpha gate row, B3, M9 and L10N still listed them as open.
G14 heading and summary row now say 4 of the 12 key languages missing (hi, ar,
ko, vi); counts re-measured from crates/ui-egui/src/i18n/*.tsv (union 3,576).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:34:34 +02:00
vangel76andClaude Sonnet 5.5 5ecd177cc6 #1411: docs/gaps.md: remove entries for features that already shipped
Verified against upstream/main: AVI import (#598, crates/avi), FLAC in MP4
(#603, mp4_flac_audio test), multicam paging beyond 16 angles
(render/multicam.rs page_layout), image-sequence downloads in Chrome (#378,
#624), streamed interchange import (#461, #664), deselect on empty space
(#683) and Project-panel marquee (#578). German (#630) and Russian (#610)
menus are listed. The FLAC-in-MP4 "silent" claim is removed from
codec-parity.md and target-app-parity.md as well.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:14:29 +02:00
vangel76andClaude Sonnet 5.5 595f94f303 #1407: import Radiance HDR stills and image sequences
Problem: Premiere reads Radiance HDR (.hdr) pictures; FilmCraft listed
the extension nowhere and could not open them.

Fix: clean-room RGBE decoder in filmcraft-media from the public format
description: header with FORMAT, all eight axis orders, flat, old
run-length and new per-channel run-length scan lines. Frames are linear
float (Rec.709), like EXR. Allocations are bounded by the data present;
hostile headers and truncated data return errors. "hdr" joins the
importable still extensions; stills and image sequences share the decoder.
Output equals ffmpeg's decode exactly for flat and RLE files; EXPOSURE and
PRIMARIES lines are ignored and XYZE is refused.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:12:44 +02:00
vangel76andClaude Sonnet 5.5 9deba4a830 #1408: Shift constrains mask vertex and whole-mask drags to 45 degrees
Problem: Shift snapped pen segments (#853) but dragging an existing mask
vertex or the whole mask still moved freely.

Fix: while Shift is held the movement since the press is constrained to
horizontal/vertical/diagonal steps (accumulated raw vs applied totals per
gesture, so each frame's delta stays a single undo step). Unit test for
the pure step function; gaps.md G18 updated.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 21:12:19 +02:00
vangel76andClaude Sonnet 5.5 af5d29310e #828: import PXR24-compressed OpenEXR
Problem: OpenEXR files with PXR24 compression (a common lossy 24-bit
float format from renderers and compositors) were refused with "not
supported yet".

Fix: decode PXR24 chunks (16 lines, deflated byte planes of per-line
sample differences; floats keep their top 24 bits) into the existing
scan-line pipeline. Bounds-checked, no panics on damaged data. Tests:
hand-built chunks with half/float/uint channels and a partial last
chunk, damaged-file cases, and an OpenImageIO-written oracle comparing
our decode with OpenEXR's own (skips without oiiotool). Docs updated;
stale AVI / FLAC-in-MP4 entries removed from G10.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:56:26 +02:00
vangel76andClaude Sonnet 5.5 3516207de7 #1402: import MP1 (A_MPEG/L1) audio from Matroska
Problem: the Matroska demuxer mapped A_MPEG/L2 and A_MPEG/L3 only, so a
Layer I track was reported as an unsupported codec even though the MP1/MP2
decoder (#809) reads Layer I.

Fix: add Codec::Mp1 for A_MPEG/L1 and route it through the same packet
duration and decoder path as Mp2. Test remuxes synthetic Layer I frames
into Matroska with ffmpeg and compares our decode (max error 3e-5).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-12 20:55:35 +02:00
Nai-ITA d2ae945c30 Add files via upload 2026-10-12 18:56:50 +02:00
Brandon ThomasandClaude Opus 5.5 59bf7cc21f Merge main into #837 (EXR next to DNG and APNG); cap EXR chunk size, fallible chunk buffers
A tiny header naming ~1000 channels on a 64M-pixel line sized each chunk
buffer at hundreds of GB and Vec::with_capacity aborted the process.
Chunks over 256 MB are refused, and the RLE / zlib buffers reserve with
try_reserve_exact. Regression test: huge_scan_lines_are_refused_before_allocating.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:18:05 -04:00
Brandon ThomasandClaude Opus 5.5 71ceebe857 Merge main into #879 (export schema next to FLAC, catalogs, parity table)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 22:01:41 -04:00
Brandon ThomasandClaude Opus 5.5 7c21ec5e13 Merge main into #1068 (engine dev-dependencies, docs)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:55:08 -04:00