| // Copyright 2022 the Vello Authors |
| // SPDX-License-Identifier: Apache-2.0 OR MIT |
| |
| //! Scenes |
| |
| // The following lints are part of the Linebender standard set, |
| // but resolving them has been deferred for now. |
| // Feel free to send a PR that solves one or more of these. |
| #![allow( |
| missing_debug_implementations, |
| unreachable_pub, |
| missing_docs, |
| clippy::cast_possible_truncation, |
| clippy::shadow_unrelated, |
| clippy::allow_attributes_without_reason |
| )] |
| |
| mod images; |
| mod mmark; |
| mod pico_svg; |
| mod simple_text; |
| mod svg; |
| pub mod test_scenes; |
| |
| use clap::Args; |
| pub use images::ImageCache; |
| pub use simple_text::SimpleText; |
| use std::path::PathBuf; |
| pub use svg::{default_scene, scene_from_files}; |
| use test_scenes::test_scenes; |
| |
| use vello::Scene; |
| use vello::kurbo::Vec2; |
| use vello::peniko::{Color, color}; |
| |
| pub struct SceneParams<'a> { |
| pub time: f64, |
| /// Whether blocking should be limited |
| /// Will not change between runs |
| // TODO: Just never block/handle this automatically? |
| pub interactive: bool, |
| pub text: &'a mut SimpleText, |
| pub images: &'a mut ImageCache, |
| pub resolution: Option<Vec2>, |
| pub base_color: Option<Color>, |
| pub complexity: usize, |
| } |
| |
| pub struct SceneConfig { |
| // TODO: This is currently unused |
| pub animated: bool, |
| pub name: String, |
| } |
| |
| pub struct ExampleScene { |
| pub function: Box<dyn TestScene>, |
| pub config: SceneConfig, |
| } |
| |
| pub trait TestScene { |
| fn render(&mut self, scene: &mut Scene, params: &mut SceneParams<'_>); |
| } |
| |
| impl<F: FnMut(&mut Scene, &mut SceneParams<'_>)> TestScene for F { |
| fn render(&mut self, scene: &mut Scene, params: &mut SceneParams<'_>) { |
| self(scene, params); |
| } |
| } |
| |
| pub struct SceneSet { |
| pub scenes: Vec<ExampleScene>, |
| } |
| |
| #[derive(Args, Debug)] |
| /// Shared config for scene selection |
| pub struct Arguments { |
| #[arg(help_heading = "Scene Selection")] |
| #[arg(long, global(false))] |
| /// Whether to use the test scenes created by code |
| test_scenes: bool, |
| #[arg(help_heading = "Scene Selection", global(false))] |
| /// The svg files paths to render |
| svgs: Option<Vec<PathBuf>>, |
| #[arg(help_heading = "Render Parameters")] |
| #[arg(long, global(false), value_parser = parse_color_arg)] |
| /// The base color applied as the blend background to the rasterizer. |
| /// Format is CSS style hexadecimal (#RGB, #RGBA, #RRGGBB, #RRGGBBAA) or |
| /// an SVG color name such as "aliceblue" |
| pub base_color: Option<Color>, |
| } |
| |
| impl Arguments { |
| pub fn select_scene_set(&self) -> anyhow::Result<Option<SceneSet>> { |
| // There is no file access on WASM, and on Android we haven't set up the assets |
| // directory. |
| // TODO: Upload the assets directory on Android |
| // Therefore, only render the `test_scenes` (including one SVG example) |
| #[cfg(any(target_arch = "wasm32", target_os = "android"))] |
| return Ok(Some(test_scenes())); |
| #[cfg(not(any(target_arch = "wasm32", target_os = "android")))] |
| if self.test_scenes { |
| Ok(test_scenes()) |
| } else if let Some(svgs) = &self.svgs { |
| scene_from_files(svgs) |
| } else { |
| default_scene() |
| } |
| .map(Some) |
| } |
| } |
| |
| fn parse_color_arg(s: &str) -> Result<Color, color::ParseError> { |
| color::parse_color(s).map(|c| c.to_alpha_color()) |
| } |