diff --git a/CHANGELOG.md b/CHANGELOG.md index d33b258..8386f4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,34 @@ Subheadings to categorize changes are `added, changed, deprecated, removed, fixe This release has an [MSRV][] of 1.86. +### Migration + +To continue rendering with Vello you can follow the following migration instructions: + +If you previously had codee like: + +```rust +let lottie = Composition = ...; +let renderer : velato::Renderer = ...; +let frame : f64 = ...; +let scene : vello::Scene = renderer.render(lottie, frame, Affine::IDENTITY, 1.0); +``` + +You should replace it with the following: + +```rust +let lottie = Composition = ...; +let renderer : velato::Renderer = ...; +let frame : f64 = ...; +let mut scene = vello::Scene::new(); +let mut painter = anyrender_vello::VelloScenePainter::new(&mut scene); +renderer.render(lottie, frame, Affine::IDENTITY, 1.0, &mut painter); +``` + +### Changed + +- Velato no longer depends directly on [Vello](https://github.com/linebender/vello). It now depends on the [AnyRender](https://github.com/dioxuslabs/anyrender) rendering abstraction instead. This allows Velato to be integrated with any rendering backend by implementing AnyRender's [PaintScene](https://docs.rs/anyrender/latest/anyrender/trait.PaintScene.html) trait (The AnyRender projects currently provides implementations Vello, Vello CPU, Vello Hybrid, and Skia). ([#92][] by [@nicoburns][]) + ## [0.8.1] This release has an [MSRV][] of 1.86. @@ -26,7 +54,7 @@ This release has an [MSRV][] of 1.86. ### Added -- Added image schema layer. ([#78][] by [@RobertBrewitz][]) +- Added image schema layer. - Added deserializer to deserialize into the correct Layer type based on the "ty" field. ([#78][] by [@RobertBrewitz][]) - Added twist, stroke_dash, modifier and rounded_corners schema shapes. ([#78][] by [@RobertBrewitz][]) - Added support for trim paths in animations. ([#83][] by [@RobertBrewitz][]) @@ -137,6 +165,7 @@ This release has an [MSRV][] of 1.75. [@atoktoto]: https://github.com/atoktoto [@RishiChalla]: https://github.com/RishiChalla [@RobertBrewitz]: https://github.com/RobertBrewitz +[@nicoburns]: https://github.com/nicoburns [#16]: https://github.com/linebender/velato/pull/16 [#17]: https://github.com/linebender/velato/pull/17 @@ -153,6 +182,7 @@ This release has an [MSRV][] of 1.75. [#83]: https://github.com/linebender/velato/pull/83 [#84]: https://github.com/linebender/velato/pull/82 [#85]: https://github.com/linebender/velato/pull/85 +[#92]: https://github.com/linebender/velato/pull/92 [Unreleased]: https://github.com/linebender/velato/compare/v0.8.1...HEAD [0.8.1]: https://github.com/linebender/velato/compare/v0.8.0...v0.8.1 diff --git a/Cargo.lock b/Cargo.lock index 2b54aa5..4347f0e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -156,6 +156,34 @@ version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +[[package]] +name = "anyrender" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c6900aa6fa601379c17b824d0882c5c4ffd2f974124b273ba083b64f76077" +dependencies = [ + "kurbo", + "peniko", + "raw-window-handle", +] + +[[package]] +name = "anyrender_vello" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd9574a872584fa9c7be06ed8be1c4875aeae37e74a567597125f3ec4579bd3" +dependencies = [ + "anyrender", + "debug_timer", + "kurbo", + "peniko", + "pollster 0.4.0", + "rustc-hash 2.1.1", + "vello", + "wgpu", + "wgpu_context", +] + [[package]] name = "arrayref" version = "0.3.9" @@ -649,6 +677,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" +[[package]] +name = "debug_timer" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da220af51a1a335e9a930beaaef53d261e41ea9eecfb3d973a3ddae1a7284b9c" + [[package]] name = "devserver_lib" version = "0.4.2" @@ -1648,7 +1682,7 @@ dependencies = [ "log", "num-traits", "once_cell", - "rustc-hash", + "rustc-hash 1.1.0", "spirv", "thiserror 2.0.17", "unicode-ident", @@ -1940,6 +1974,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + [[package]] name = "portable-atomic" version = "1.11.0" @@ -2204,6 +2244,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustix" version = "0.38.44" @@ -2278,6 +2324,8 @@ name = "scenes" version = "0.0.0" dependencies = [ "anyhow", + "anyrender", + "anyrender_vello", "byte-unit", "bytemuck", "clap", @@ -2285,6 +2333,8 @@ dependencies = [ "image", "inquire", "instant", + "kurbo", + "peniko", "rand", "skrifa 0.26.6", "ureq", @@ -2781,6 +2831,10 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "velato" version = "0.8.1" dependencies = [ + "anyrender", + "anyrender_vello", + "kurbo", + "peniko", "serde", "serde_json", "serde_repr", @@ -3227,7 +3281,7 @@ dependencies = [ "portable-atomic", "profiling", "raw-window-handle", - "rustc-hash", + "rustc-hash 1.1.0", "smallvec", "thiserror 2.0.17", "wgpu-core-deps-apple", @@ -3326,6 +3380,16 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wgpu_context" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f49e6f733fcc61e41a5ecdb36910baa5148497036784bca319289bfdca6141" +dependencies = [ + "futures-intrusive", + "wgpu", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3777,9 +3841,11 @@ dependencies = [ "env_logger 0.11.8", "getrandom 0.2.16", "instant", + "kurbo", "log", "notify-debouncer-mini", - "pollster", + "peniko", + "pollster 0.3.0", "scenes", "vello", "wasm-bindgen-futures", diff --git a/Cargo.toml b/Cargo.toml index 1e8bdfa..aaa4250 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,22 +86,31 @@ clippy.wildcard_dependencies = "warn" [workspace.dependencies] # NOTE: Make sure to keep this in sync with the version badge in README.md +anyrender = { version = "0.6.0" } +anyrender_vello = { version = "0.6.0" } vello = { version = "0.6.0", default-features = false } +kurbo = { version = "0.12.0" } +peniko = { version = "0.5.0" } [lints] workspace = true [dependencies] -vello = { workspace = true } +anyrender = { workspace = true } +kurbo = { workspace = true } +peniko = { workspace = true } # For the parser serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.145" serde_repr = "0.1.20" +[dev-dependencies] +vello = { workspace = true } +anyrender_vello = { workspace = true } + [target.'cfg(target_arch = "wasm32")'.dev-dependencies] wasm-bindgen-test = "0.3.56" [features] default = [] -wgpu = ["vello/wgpu"] diff --git a/examples/scenes/Cargo.toml b/examples/scenes/Cargo.toml index 01e0e04..3e279a4 100644 --- a/examples/scenes/Cargo.toml +++ b/examples/scenes/Cargo.toml @@ -10,7 +10,11 @@ publish = false workspace = true [dependencies] +anyrender = { workspace = true } +anyrender_vello = { workspace = true } vello = { workspace = true } +kurbo = { workspace = true } +peniko = { workspace = true } velato = { path = "../.." } anyhow = "1" clap = { version = "4.5.38", features = ["derive"] } diff --git a/examples/scenes/src/lib.rs b/examples/scenes/src/lib.rs index 7256d47..e7c25d2 100644 --- a/examples/scenes/src/lib.rs +++ b/examples/scenes/src/lib.rs @@ -37,9 +37,9 @@ pub use lottie::{default_scene, scene_from_files}; pub use simple_text::RobotoText; pub use test_scenes::test_scenes; +use kurbo::Vec2; +use peniko::{Color, color}; use vello::Scene; -use vello::kurbo::Vec2; -use vello::peniko::{Color, color}; pub struct SceneParams<'a> { pub time: f64, diff --git a/examples/scenes/src/lottie.rs b/examples/scenes/src/lottie.rs index 94a16f3..a25b821 100644 --- a/examples/scenes/src/lottie.rs +++ b/examples/scenes/src/lottie.rs @@ -7,6 +7,7 @@ use crate::{ExampleScene, SceneSet}; #[cfg(not(target_arch = "wasm32"))] use anyhow::{Ok, Result}; use instant::Instant; +use kurbo::{Affine, Vec2}; use std::sync::Arc; #[cfg(not(target_arch = "wasm32"))] use std::{ @@ -15,7 +16,6 @@ use std::{ }; use velato::Composition; use vello::Scene; -use vello::kurbo::{Affine, Vec2}; #[cfg(not(target_arch = "wasm32"))] pub fn scene_from_files(files: &[PathBuf]) -> Result { @@ -106,7 +106,11 @@ pub fn lottie_function_of>( let frame = ((start.elapsed().as_secs_f64() * lottie.frame_rate) % (lottie.frames.end - lottie.frames.start)) + lottie.frames.start; - renderer.render(lottie, frame, Affine::IDENTITY, 1.0) + + let mut scene = vello::Scene::new(); + let mut painter = anyrender_vello::VelloScenePainter::new(&mut scene); + renderer.render(lottie, frame, Affine::IDENTITY, 1.0, &mut painter); + scene } let started = Instant::now(); let mut renderer = velato::Renderer::new(); diff --git a/examples/scenes/src/simple_text.rs b/examples/scenes/src/simple_text.rs index e6c2b14..7622d07 100644 --- a/examples/scenes/src/simple_text.rs +++ b/examples/scenes/src/simple_text.rs @@ -1,11 +1,11 @@ // Copyright 2022 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +use kurbo::Affine; +use peniko::{Blob, Brush, BrushRef, FontData, StyleRef}; use skrifa::MetadataProvider; use skrifa::raw::FontRef; use std::sync::Arc; -use vello::kurbo::Affine; -use vello::peniko::{Blob, Brush, BrushRef, FontData, StyleRef}; use vello::{Glyph, Scene}; // This is very much a hack to get things working. @@ -113,7 +113,7 @@ impl RobotoText { transform: Affine, text: &str, ) { - use vello::peniko::{Color, Fill}; + use peniko::{Color, Fill}; let brush = brush.unwrap_or(&Brush::Solid(Color::WHITE)); self.add_run( scene, diff --git a/examples/scenes/src/test_scenes.rs b/examples/scenes/src/test_scenes.rs index 7f78b43..12aafd1 100644 --- a/examples/scenes/src/test_scenes.rs +++ b/examples/scenes/src/test_scenes.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 OR MIT use crate::{ExampleScene, SceneConfig, SceneParams, SceneSet}; -use vello::kurbo::Affine; +use kurbo::Affine; use vello::*; macro_rules! scene { diff --git a/examples/with_winit/Cargo.toml b/examples/with_winit/Cargo.toml index 214baeb..7f186d6 100644 --- a/examples/with_winit/Cargo.toml +++ b/examples/with_winit/Cargo.toml @@ -21,6 +21,8 @@ workspace = true [dependencies] vello = { workspace = true, features = ["wgpu"] } +kurbo = { workspace = true } +peniko = { workspace = true } wgpu = { version = "26.0", features = ["vulkan", "metal", "dx12"] } scenes = { path = "../scenes" } anyhow = "1" diff --git a/examples/with_winit/src/lib.rs b/examples/with_winit/src/lib.rs index 23c5f3c..af0f346 100644 --- a/examples/with_winit/src/lib.rs +++ b/examples/with_winit/src/lib.rs @@ -24,10 +24,10 @@ use std::sync::Arc; use anyhow::Result; use clap::{CommandFactory, Parser}; +use kurbo::{Affine, Vec2}; +use peniko::Color; use scenes::{RobotoText, SceneParams, SceneSet}; -use vello::kurbo::{Affine, Vec2}; use vello::low_level::BumpAllocators; -use vello::peniko::Color; use vello::util::{RenderContext, RenderSurface}; use vello::{AaConfig, Renderer, RendererOptions, Scene, wgpu}; diff --git a/examples/with_winit/src/multi_touch.rs b/examples/with_winit/src/multi_touch.rs index db35439..1922640 100644 --- a/examples/with_winit/src/multi_touch.rs +++ b/examples/with_winit/src/multi_touch.rs @@ -4,7 +4,7 @@ /// Adapted from use std::{collections::BTreeMap, fmt::Debug}; -use vello::kurbo::{Point, Vec2}; +use kurbo::{Point, Vec2}; use winit::event::{Touch, TouchPhase}; /// All you probably need to know about a multi-touch gesture. diff --git a/examples/with_winit/src/stats.rs b/examples/with_winit/src/stats.rs index 8b2a600..3fe4cd1 100644 --- a/examples/with_winit/src/stats.rs +++ b/examples/with_winit/src/stats.rs @@ -1,11 +1,11 @@ // Copyright 2023 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +use kurbo::{Affine, PathEl, Rect, Stroke}; +use peniko::{Brush, Color, Fill}; use scenes::RobotoText; use std::collections::VecDeque; -use vello::kurbo::{Affine, PathEl, Rect, Stroke}; use vello::low_level::BumpAllocators; -use vello::peniko::{Brush, Color, Fill}; use vello::{AaConfig, Scene}; const SLIDING_WINDOW_SIZE: usize = 100; diff --git a/src/import/builders.rs b/src/import/builders.rs index e001f52..e2d7624 100644 --- a/src/import/builders.rs +++ b/src/import/builders.rs @@ -6,7 +6,7 @@ use super::defaults::FLOAT_VALUE_ONE_HUNDRED; use crate::runtime::model::Layer; use crate::schema::helpers::int_boolean::BoolInt; use crate::{runtime, schema}; -use vello::peniko::{self, BlendMode, Compose, Mix}; +use peniko::{self, BlendMode, Compose, Mix}; pub struct LayerSetupParams { pub layer_index: usize, diff --git a/src/import/converters.rs b/src/import/converters.rs index f3f1223..ed85cbc 100644 --- a/src/import/converters.rs +++ b/src/import/converters.rs @@ -18,9 +18,9 @@ use crate::schema::animated_properties::split_vector::SplitVector; use crate::schema::constants::gradient_type::GradientType; use crate::schema::helpers::int_boolean::BoolInt; use crate::{Composition, schema}; +use kurbo::{Cap, Join, Point, Size, Vec2}; +use peniko::{BlendMode, Color, Mix}; use std::collections::HashMap; -use vello::kurbo::{Cap, Join, Point, Size, Vec2}; -use vello::peniko::{BlendMode, Color, Mix}; fn process_layers( source_layers: &[schema::layers::AnyLayer], diff --git a/src/lib.rs b/src/lib.rs index 9059807..594f4a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,34 +1,29 @@ // Copyright 2024 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT -//! Render a Lottie animation to a Vello [`Scene`](crate::vello::Scene). -//! -//! This currently lacks support for a [number of important](crate#unsupported-features) SVG features. -//! -//! This is also intended to be the preferred integration between Vello and [usvg](https://crates.io/crates/usvg), -//! so [consider contributing](https://github.com/linebender/vello_svg) if you need a feature which is missing. -//! -//! This crate also re-exports [`vello`], so you can easily use the specific version that is compatible with Velato. +//! Render a Lottie animation to any type that implements the [PaintScene](https://docs.rs/anyrender/latest/anyrender/trait.PaintScene.html) +//! trait from the [`anyrender`](https://github.com/DioxusLabs/anyrender) crate. There are implementations available for `vello`, `vello_cpu`, +//! `vello_hybrid`, and `skia_safe`, or you can implement the trait yourself. //! //! ## Usage //! //! ```no_run //! # use std::str::FromStr; -//! use velato::vello; //! //! // Parse your lottie file //! let lottie = include_str!("../examples/assets/google_fonts/Tiger.json"); //! let composition = velato::Composition::from_str(lottie).expect("valid file"); //! //! // Render to a scene -//! let mut new_scene = vello::Scene::new(); +//! let mut scene = vello::Scene::new(); +//! let mut painter = anyrender_vello::VelloScenePainter::new(&mut scene); //! //! // Render to a scene! //! let mut renderer = velato::Renderer::new(); //! let frame = 0.0; // Arbitrary number chosen. Ensure it's a valid frame! //! let transform = vello::kurbo::Affine::IDENTITY; //! let alpha = 1.0; -//! let scene = renderer.render(&composition, frame, transform, alpha); +//! let scene = renderer.render(&composition, frame, transform, alpha, &mut painter); //! ``` //! //! # Unsupported features @@ -90,7 +85,4 @@ pub mod schema; mod error; pub use error::Error; -// Re-export vello -pub use vello; - pub use runtime::{Composition, Renderer, model}; diff --git a/src/runtime/model/fixed.rs b/src/runtime/model/fixed.rs index c2546d1..75e1c0b 100644 --- a/src/runtime/model/fixed.rs +++ b/src/runtime/model/fixed.rs @@ -7,8 +7,7 @@ Representations of fixed (non-animated) values. use std::mem::swap; -use vello::kurbo::{self, Affine, Point, Vec2}; -use vello::peniko; +use kurbo::{Affine, Point, Vec2}; /// Fixed affine transformation. pub type Transform = kurbo::Affine; diff --git a/src/runtime/model/mod.rs b/src/runtime/model/mod.rs index e0522e5..c6fb4e4 100644 --- a/src/runtime/model/mod.rs +++ b/src/runtime/model/mod.rs @@ -1,9 +1,9 @@ // Copyright 2024 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT +use kurbo::{Affine, PathEl, Point, Shape as _, Size, Vec2}; +use peniko::{BlendMode, Color}; use std::ops::Range; -use vello::kurbo::{self, Affine, PathEl, Point, Shape as _, Size, Vec2}; -use vello::peniko::{self, BlendMode, Color}; mod spline; mod value; diff --git a/src/runtime/model/spline.rs b/src/runtime/model/spline.rs index d4c5bfb..aa7d834 100644 --- a/src/runtime/model/spline.rs +++ b/src/runtime/model/spline.rs @@ -1,7 +1,7 @@ // Copyright 2024 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT -use vello::kurbo::{PathEl, Point}; +use kurbo::{PathEl, Point}; /// Helper trait for converting cubic splines to paths. pub trait SplineToPath { diff --git a/src/runtime/model/value.rs b/src/runtime/model/value.rs index 97a2cb7..10ca3cb 100644 --- a/src/runtime/model/value.rs +++ b/src/runtime/model/value.rs @@ -1,12 +1,9 @@ // Copyright 2024 the Velato Authors // SPDX-License-Identifier: Apache-2.0 OR MIT -use vello::{ - kurbo::{ - self, ParamCurve, Point, - common::{solve_cubic, solve_itp}, - }, - peniko, +use kurbo::{ + ParamCurve, Point, + common::{solve_cubic, solve_itp}, }; /// Fixed or animated value. diff --git a/src/runtime/render.rs b/src/runtime/render.rs index 9a76d0d..68996c9 100644 --- a/src/runtime/render.rs +++ b/src/runtime/render.rs @@ -3,13 +3,14 @@ use super::Composition; use super::model::{Content, Draw, Geometry, GroupTransform, Layer, Shape, fixed}; -use std::mem::swap; -use std::ops::Range; -use vello::kurbo::{ +use anyrender::PaintScene; +use kurbo::{ Affine, BezPath, CubicBez, Line, ParamCurve, ParamCurveArclen, PathEl, PathSeg, Point, QuadBez, Rect, }; -use vello::peniko::{Fill, Mix}; +use peniko::{BrushRef, Fill, Mix}; +use std::mem::swap; +use std::ops::Range; /// Renders a composition into a scene. #[derive(Debug, Default)] @@ -31,10 +32,9 @@ impl Renderer { frame: f64, transform: Affine, alpha: f64, - ) -> vello::Scene { - let mut scene = vello::Scene::new(); - self.append(animation, frame, transform, alpha, &mut scene); - scene + scene: &mut impl PaintScene, + ) { + self.append(animation, frame, transform, alpha, scene); } /// Renders and appends the animation at a given frame to the provided scene. @@ -44,7 +44,7 @@ impl Renderer { frame: f64, transform: Affine, alpha: f64, - scene: &mut vello::Scene, + scene: &mut impl PaintScene, ) { self.batch.clear(); scene.push_clip_layer( @@ -77,7 +77,7 @@ impl Renderer { transform: Affine, alpha: f64, frame: f64, - scene: &mut vello::Scene, + scene: &mut impl PaintScene, ) { if !layer.frames.contains(&frame) { return; @@ -447,7 +447,7 @@ impl Batch { self.trim_elements.clear(); } - fn render(&self, scene: &mut vello::Scene) { + fn render(&self, scene: &mut impl PaintScene) { // Process all draws in reverse for draw in self.draws.iter().rev() { // Some nastiness to avoid cloning the brush if unnecessary @@ -456,11 +456,11 @@ impl Batch { } else { None }; - let brush = modified_brush.as_ref().unwrap_or(&draw.brush); + let brush = BrushRef::from(modified_brush.as_ref().unwrap_or(&draw.brush)); for geometry in self.geometries[draw.geometry.clone()].iter() { let path = &self.elements[geometry.elements.clone()]; let transform = geometry.transform; - if let Some(stroke) = draw.stroke.as_ref() { + if let Some(stroke) = &draw.stroke { scene.stroke(stroke, transform, brush, None, &path); } else { scene.fill(Fill::NonZero, transform, brush, None, &path);