Skip to content

chore: track upstream thorvg main, keep web video - #614

Open
theashraf wants to merge 4 commits into
mainfrom
chore/rebase-thorvg-v1.1.1
Open

chore: track upstream thorvg main, keep web video#614
theashraf wants to merge 4 commits into
mainfrom
chore/rebase-thorvg-v1.1.1

Conversation

@theashraf

@theashraf theashraf commented Aug 28, 2026

Copy link
Copy Markdown
Member

Pins `dotlottie-rs/deps/thorvg` to upstream thorvg/thorvg main (4f968a5f, 2026-09-05) and drops the theashraf fork.

What changed vs. the fork

  • Upstream already has video-in-image-assets, so the fork only carried two patches: removal of the 1s seek dead-band in `LottieImage::play`, and the slot w/h fix. The slot fix is covered in-crate by `Player::normalize_image_slot` (image slot tests pass). The dead-band stays, and the web player was rewritten to work with it.
  • `MediaLoader::open` now returns `Result` and takes `const LoaderOps&`; shim updated.
  • WebGPU stubs gained the compute-pass entry points upstream's WG engine now uses.
  • New `remainderf` stub for wasm32-unknown-unknown (upstream stroker uses it since 3ee06eaf).

Web video player
ThorVG lets the clip free-run and only seeks it when it drifts more than 1s from the animation clock. The previous tracker assumed a per-tick target and, under the dead-band, oscillated between 0.5x and 1x with a hard seek every ~2s. The element now plays on its own clock, only while ThorVG wants the layer playing and the dotLottie player is not paused, at the player's speed via `playbackRate`. Reverse playback pauses the element and relies on ThorVG's seeks.

Known limits inherited from the dead-band (to raise upstream): after a scrub or a reverse→forward switch an offset of up to 1s can persist, and reverse playback advances in ~1s steps.

Verification

  • `cargo fmt --check`, `cargo test --features dev --test-threads=1`, `cargo clippy --features dev --all-targets -D clippy::print_stdout`: green.
  • `make wasm`, `make wasm-webgl`, `make wasm-webgpu`: build, env-import check clean.
  • Chrome, `video_demo.lottie` (480x270 H.264, 30s) via the sw build: video follows the animation clock within ~40ms at 1x and ~100ms at 2x; pause freezes the frame; scrubbing while playing or paused resyncs; reverse holds frames between seeks.

Review pass (code-review, 15 findings)
Fixed: ended-clip restart loop; clip left running in the background while the player is stopped; load-kick counter accumulating across seeks; completion and load never halting videos; missing rate sync on load and tween resume; registry lock held across DOM calls; shim returning InvalidArguments (ThorVG kept probing other loaders) → NonSupport; into_result panicking on the new TVG_RESULT_SYSTEM_ERRORErr.
Documented, inherent to upstream's dead-band: ~1s steps whenever the element is paused (reverse, paused scrub), and drift + periodic hard seeks when clip duration ≠ layer span (ThorVG stretches the clip over the layer).
Deferred, pre-existing: the video registry is per wasm module, not per Player (now also carries rate); remainderf stub is hand-written (fine for ThorVG's angle use, libm crate would make it exact).
Re-verified after the fixes: fmt/test/clippy green, all three wasm bundles link clean; browser scenarios A–F pass again, plus completion halts the video and a 2s clip on a 5s layer holds its last frame with no restarts.

@changeset-bot

changeset-bot Bot commented Aug 28, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 6296ded

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@theashraf
theashraf force-pushed the chore/rebase-thorvg-v1.1.1 branch from 0c66f41 to cee64cf Compare August 28, 2026 15:37
@theashraf theashraf changed the title chore: rebase thorvg onto v1.1.1 chore: track upstream thorvg main Aug 28, 2026
Track thorvg/thorvg main directly instead of the theashraf fork. Upstream
already ships video-in-image-assets, so the fork's only remaining patches
were the 1s seek dead-band removal and the slot w/h fix; the crate covers
the latter via normalize_image_slot and the web player now follows the
upstream seek contract.

Adds a remainderf stub for wasm32-unknown-unknown, which the new stroker
code in tvgSwStroke.cpp calls.
Upstream keeps a 1s tolerance before seeking a video, so the web player no
longer gets a target every tick. The old tracker extrapolated from a stale
target and fought the element: rate oscillated between 0.5x and 1x with a
hard seek every couple of seconds.

The element now runs on its own clock. It plays only while ThorVG wants the
layer playing and the dotLottie player is not paused, at the player's speed
via playbackRate; reverse playback holds the frame between ThorVG's seeks.
Speed and direction are pushed from the player on play, set_speed and every
direction flip, and applied to videos opened later.
@theashraf theashraf changed the title chore: track upstream thorvg main chore: track upstream thorvg main, keep web video Sep 5, 2026
- Don't call play() on an ended element: it restarts from 0 and ThorVG's
  drift check then yanks it back every few frames. A clip shorter than its
  layer now holds its last frame until the next seek.
- The warm-up play() no longer leaves the clip running while the player is
  stopped: a loadeddata listener pauses it unless something wants it.
- Reset the load-kick counter once frames arrive and ignore seeks (Chrome
  drops readyState on every seek); the kick is a bare play(), not load().
- Halt videos when a non-looping animation completes and when a new
  animation loads; sync rate on load and when resuming from a tween.
- Release the registry lock before calling into the DOM.
- MediaLoader::open returns NonSupport on failure so ThorVG stops probing
  the other loaders with the MP4 bytes.
- Unknown ThorVG result codes (new SystemError) map to Err instead of
  unreachable!().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant