Added a Rust runtime.
This patch adds a Rust runtime, rive-rs, that binds to rive-cpp and includes an optional Vello back-end. It also ports the Vello demo to this new runtime.
Stuff to do before merging:
- [ ] README.md & CONTRIBUTING.md
- [x] set up repo pushing
- [x] make more types public
- [x] events API
Diffs=
52a1a6f88 Added a Rust runtime. (#6027)
Co-authored-by: DragoČ™ Tiselice <dragos@rive.app>
diff --git a/.rive_head b/.rive_head
index 8da8b8d..413d351 100644
--- a/.rive_head
+++ b/.rive_head
@@ -1 +1 @@
-22077bedae4c277e5e8a81c732167ab5d559917c
+52a1a6f8888c9134de8dce0393dd3b0d6757f7de
diff --git a/vello/Cargo.toml b/vello/Cargo.toml
index 4a4d533..255a639 100644
--- a/vello/Cargo.toml
+++ b/vello/Cargo.toml
@@ -3,15 +3,9 @@
version = "0.1.0"
edition = "2021"
-[build-dependencies]
-cc = { version = "1.0", features = ["parallel"] }
-walkdir = "2.3.3"
-
[dependencies]
-clap = { version = "4.3.19", features = ["derive"] }
-image = "0.24.6"
pollster = "0.3.0"
-smallvec = "1.8.0"
-vello = { git = "https://github.com/linebender/vello", rev = "3cb5462" }
+rive-rs = { path = "../../rive_rs", features = ["vello"] }
+vello = { workspace = true }
wgpu = "0.17.0"
winit = "0.28.6"
diff --git a/vello/build.rs b/vello/build.rs
deleted file mode 100644
index 0f7163d..0000000
--- a/vello/build.rs
+++ /dev/null
@@ -1,116 +0,0 @@
-use std::{
- env,
- ffi::OsString,
- path::{Path, PathBuf},
- process::Command,
-};
-
-use walkdir::WalkDir;
-
-const CHECKOUT_DIRECTORY: &str = "target";
-
-struct Checkout {
- path: PathBuf,
-}
-
-impl Checkout {
- pub fn new(repo: &str, tag: &str) -> Self {
- let name = repo.rsplit_once('/').expect("URL format invalid").1;
- let mut path = PathBuf::from(CHECKOUT_DIRECTORY);
-
- path.push(name);
-
- if !path.is_dir() {
- Command::new("git")
- .args([
- "clone",
- "-b",
- tag,
- repo,
- &path.as_os_str().to_string_lossy(),
- ])
- .output()
- .unwrap_or_else(|_| panic!("failed to clone {}; is git CLI available?", name));
- }
-
- Self { path }
- }
-
- pub fn join<P: AsRef<Path>>(&self, path: P) -> PathBuf {
- self.path.join(path)
- }
-}
-
-fn all_files_with_extension<P: AsRef<Path>>(
- path: P,
- extension: &str,
-) -> impl Iterator<Item = PathBuf> + '_ {
- WalkDir::new(path).into_iter().filter_map(move |entry| {
- entry
- .ok()
- .map(|entry| entry.into_path())
- .filter(|path| path.extension() == Some(&OsString::from(extension)))
- })
-}
-
-fn main() {
- println!("cargo:rerun-if-changed=src/vello_renderer.hpp");
- println!("cargo:rerun-if-changed=src/vello_renderer.cpp");
- println!("cargo:rerun-if-changed=src/winit_viewer.cpp");
-
- let harfbuzz = Checkout::new("https://github.com/harfbuzz/harfbuzz", "8.1.1");
- let sheen_bidi = Checkout::new("https://github.com/Tehreer/SheenBidi", "v2.6");
-
- let target = env::var("TARGET").unwrap();
- let profile = env::var("PROFILE").unwrap();
-
- let mut cfg = cc::Build::new();
- cfg.cpp(true)
- .flag_if_supported("-std=c++11") // for unix
- .warnings(false)
- .file(harfbuzz.join("src/harfbuzz.cc"));
-
- if !target.contains("windows") {
- cfg.define("HAVE_PTHREAD", "1");
- }
-
- if target.contains("apple") && profile.contains("release") {
- cfg.define("HAVE_CORETEXT", "1");
- }
-
- if target.contains("windows") {
- cfg.define("HAVE_DIRECTWRITE", "1");
- }
-
- if target.contains("windows-gnu") {
- cfg.flag("-Wa,-mbig-obj");
- }
-
- cfg.compile("harfbuzz");
-
- cc::Build::new()
- .files(all_files_with_extension(sheen_bidi.join("Source"), "c"))
- .include(sheen_bidi.join("Headers"))
- .warnings(false)
- .compile("sheenbidi");
-
- cc::Build::new()
- .cpp(true)
- .files(all_files_with_extension("../src", "cpp"))
- .files(all_files_with_extension(
- "../viewer/src/viewer_content",
- "cpp",
- ))
- .file("src/vello_renderer.cpp")
- .file("src/winit_viewer.cpp")
- .include("src")
- .include("../include")
- .include("../viewer/include")
- .include(harfbuzz.join("src"))
- .include(sheen_bidi.join("Headers"))
- .flag("-std=c++14")
- .warnings(false)
- .define("RIVE_SKIP_IMGUI", None)
- .define("WITH_RIVE_TEXT", None)
- .compile("rive");
-}
diff --git a/vello/src/lib.rs b/vello/src/lib.rs
deleted file mode 100644
index f50f50a..0000000
--- a/vello/src/lib.rs
+++ /dev/null
@@ -1,564 +0,0 @@
-#![allow(clippy::missing_safety_doc)]
-
-use core::slice;
-use std::{io::Cursor, ptr::NonNull};
-
-use image::io::Reader;
-use smallvec::SmallVec;
-use util::{ScaleFromOrigin, UnwrapAndDeref};
-use vello::{
- kurbo::{Affine, BezPath, Line, PathSeg, Point, Rect, Shape, Vec2},
- peniko::{
- BlendMode, Brush, BrushRef, Cap, Color, ColorStop, ColorStopsSource, Fill, Format,
- Gradient, Image, Join, Mix, Stroke,
- },
- SceneBuilder, SceneFragment,
-};
-
-mod rive;
-mod util;
-mod viewer;
-
-pub use viewer::ViewerContent;
-
-fn from_bgra8(color: u32) -> Color {
- Color::rgba8(
- (color >> 16) as u8,
- (color >> 8) as u8,
- color as u8,
- (color >> 24) as u8,
- )
-}
-
-#[derive(Debug)]
-enum RenderStyle {
- Fill,
- Stroke(Stroke),
-}
-
-#[derive(Debug)]
-struct SliceStops<'s> {
- colors: &'s [u32],
- stops: &'s [f32],
-}
-
-impl ColorStopsSource for SliceStops<'_> {
- fn collect_stops(&self, vec: &mut SmallVec<[ColorStop; 4]>) {
- vec.extend(
- self.colors
- .iter()
- .zip(self.stops.iter())
- .map(|(&color, &offset)| ColorStop {
- offset,
- color: from_bgra8(color),
- }),
- );
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_gradient_new_linear(
- sx: f32,
- sy: f32,
- ex: f32,
- ey: f32,
- colors_data: *const u32,
- stops_data: *const f32,
- len: usize,
-) -> Option<NonNull<Gradient>> {
- let colors = slice::from_raw_parts(colors_data, len);
- let stops = slice::from_raw_parts(stops_data, len);
-
- let raw_stops = SliceStops { colors, stops };
- let gradient =
- Gradient::new_linear((sx as f64, sy as f64), (ex as f64, ey as f64)).with_stops(raw_stops);
-
- NonNull::new(Box::into_raw(Box::new(gradient)))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_gradient_new_radial(
- cx: f32,
- cy: f32,
- radius: f32,
- colors_data: *const u32,
- stops_data: *const f32,
- len: usize,
-) -> Option<NonNull<Gradient>> {
- let colors = slice::from_raw_parts(colors_data, len);
- let stops = slice::from_raw_parts(stops_data, len);
-
- let raw_stops = SliceStops { colors, stops };
- let gradient = Gradient::new_radial((cx as f64, cy as f64), radius).with_stops(raw_stops);
-
- NonNull::new(Box::into_raw(Box::new(gradient)))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_gradient_release(gradient: Option<NonNull<Gradient>>) {
- gradient.map(|ptr| Box::from_raw(ptr.as_ptr())).unwrap();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_image_new(data: *const u8, len: usize) -> Option<NonNull<Image>> {
- let image = Reader::new(Cursor::new(slice::from_raw_parts(data, len)))
- .with_guessed_format()
- .ok()?
- .decode()
- .ok()?
- .into_rgba8();
- let width = image.width();
- let height = image.height();
-
- NonNull::new(Box::into_raw(Box::new(Image::new(
- image.into_raw().into(),
- Format::Rgba8,
- width,
- height,
- ))))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_image_release(image: Option<NonNull<Image>>) {
- image.map(|ptr| Box::from_raw(ptr.as_ptr())).unwrap();
-}
-
-#[derive(Debug)]
-pub struct VelloPaint {
- style: RenderStyle,
- brush: Brush,
- blend_mode: BlendMode,
-}
-
-impl Default for VelloPaint {
- fn default() -> Self {
- Self {
- style: RenderStyle::Fill,
- brush: Brush::Solid(Color::TRANSPARENT),
- blend_mode: Mix::Normal.into(),
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_new() -> Option<NonNull<VelloPaint>> {
- NonNull::new(Box::into_raw(Box::default()))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_release(paint: Option<NonNull<VelloPaint>>) {
- paint.map(|ptr| Box::from_raw(ptr.as_ptr())).unwrap();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_style(
- mut paint: Option<NonNull<VelloPaint>>,
- style: rive::RenderPaint,
-) {
- paint.unwrap_and_deref().style = style.into();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_color(mut paint: Option<NonNull<VelloPaint>>, color: u32) {
- paint.unwrap_and_deref().brush = Brush::Solid(from_bgra8(color));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_gradient(
- mut paint: Option<NonNull<VelloPaint>>,
- mut gradient: Option<NonNull<Gradient>>,
-) {
- paint.unwrap_and_deref().brush = Brush::Gradient(gradient.unwrap_and_deref().clone());
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_thickness(
- mut paint: Option<NonNull<VelloPaint>>,
- thickness: f32,
-) {
- let style = &mut paint.unwrap_and_deref().style;
- loop {
- if let RenderStyle::Stroke(stroke) = style {
- stroke.width = thickness;
- break;
- } else {
- *style = RenderStyle::Stroke(Stroke::new(0.0));
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_join(
- mut paint: Option<NonNull<VelloPaint>>,
- join: rive::StrokeJoin,
-) {
- let style = &mut paint.unwrap_and_deref().style;
- loop {
- if let RenderStyle::Stroke(stroke) = style {
- stroke.join = match join {
- rive::StrokeJoin::Miter => Join::Miter,
- rive::StrokeJoin::Round => Join::Round,
- rive::StrokeJoin::Bevel => Join::Bevel,
- };
- break;
- } else {
- *style = RenderStyle::Stroke(Stroke::new(0.0));
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_cap(
- mut paint: Option<NonNull<VelloPaint>>,
- cap: rive::StrokeCap,
-) {
- let style = &mut paint.unwrap_and_deref().style;
- loop {
- if let RenderStyle::Stroke(stroke) = style {
- stroke.start_cap = match cap {
- rive::StrokeCap::Butt => Cap::Butt,
- rive::StrokeCap::Round => Cap::Round,
- rive::StrokeCap::Square => Cap::Square,
- };
- stroke.end_cap = stroke.start_cap;
- break;
- } else {
- *style = RenderStyle::Stroke(Stroke::new(0.0));
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_paint_set_blend_mode(
- mut paint: Option<NonNull<VelloPaint>>,
- blend_mode: rive::BlendMode,
-) {
- let mix: Mix = blend_mode.into();
- paint.unwrap_and_deref().blend_mode = mix.into();
-}
-
-#[derive(Debug)]
-pub struct VelloPath {
- path: BezPath,
- fill: Fill,
-}
-
-impl Default for VelloPath {
- fn default() -> Self {
- Self {
- path: Default::default(),
- fill: Fill::NonZero,
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_new() -> Option<NonNull<VelloPath>> {
- NonNull::new(Box::into_raw(Box::default()))
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_release(path: Option<NonNull<VelloPath>>) {
- path.map(|ptr| Box::from_raw(ptr.as_ptr())).unwrap();
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_set_fill_rule(
- mut path: Option<NonNull<VelloPath>>,
- fill_rule: rive::FillRule,
-) {
- path.unwrap_and_deref().fill = match fill_rule {
- rive::FillRule::NonZero => Fill::NonZero,
- rive::FillRule::EvenOdd => Fill::EvenOdd,
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_rewind(mut path: Option<NonNull<VelloPath>>) {
- path.unwrap_and_deref().path.truncate(0);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_extend(
- mut path: Option<NonNull<VelloPath>>,
- mut from: Option<NonNull<VelloPath>>,
- mut transform: Option<NonNull<[f32; 6]>>,
-) {
- let mut from = from.unwrap_and_deref().path.clone();
- from.apply_affine(Affine::new(transform.unwrap_and_deref().map(Into::into)));
-
- path.unwrap_and_deref()
- .path
- .extend(from.elements().iter().cloned());
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_move_to(mut path: Option<NonNull<VelloPath>>, x: f32, y: f32) {
- path.unwrap_and_deref()
- .path
- .move_to(Point::new(x as f64, y as f64));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_line_to(mut path: Option<NonNull<VelloPath>>, x: f32, y: f32) {
- path.unwrap_and_deref()
- .path
- .line_to(Point::new(x as f64, y as f64));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_cubic_to(
- mut path: Option<NonNull<VelloPath>>,
- ox: f32,
- oy: f32,
- ix: f32,
- iy: f32,
- x: f32,
- y: f32,
-) {
- path.unwrap_and_deref().path.curve_to(
- Point::new(ox as f64, oy as f64),
- Point::new(ix as f64, iy as f64),
- Point::new(x as f64, y as f64),
- );
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_path_close(mut path: Option<NonNull<VelloPath>>) {
- path.unwrap_and_deref().path.close_path();
-}
-
-pub struct VelloRenderer {
- pub scene: Box<SceneFragment>,
- builder: SceneBuilder<'static>,
- transforms: Vec<Affine>,
- clips: Vec<bool>,
-}
-
-impl VelloRenderer {
- fn last_transform(&mut self) -> &mut Affine {
- self.transforms.last_mut().unwrap()
- }
-
- fn last_clip(&mut self) -> &mut bool {
- self.clips.last_mut().unwrap()
- }
-}
-
-impl Default for VelloRenderer {
- fn default() -> Self {
- let mut scene = Box::<SceneFragment>::default();
- let builder = {
- let scene_mut: &mut SceneFragment = &mut scene;
- SceneBuilder::for_fragment(unsafe {
- // Quite a hack until we have a better way to do this in Vello.
- // Pretend that the scene fragment pointer lives for 'static.
- std::mem::transmute(scene_mut)
- })
- };
-
- Self {
- scene,
- builder,
- transforms: vec![Affine::IDENTITY],
- clips: vec![false],
- }
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_save(mut renderer: Option<NonNull<VelloRenderer>>) {
- let renderer = renderer.unwrap_and_deref();
-
- let last_transform = *renderer.last_transform();
-
- renderer.transforms.push(last_transform);
- renderer.clips.push(false);
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_restore(mut renderer: Option<NonNull<VelloRenderer>>) {
- let renderer = renderer.unwrap_and_deref();
-
- renderer.transforms.pop();
- if renderer.clips.pop().unwrap_or_default() {
- renderer.builder.pop_layer();
- }
-
- if renderer.transforms.is_empty() {
- renderer.transforms.push(Affine::IDENTITY);
- renderer.clips.push(false);
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_transform(
- mut renderer: Option<NonNull<VelloRenderer>>,
- transform: *const [f32; 6],
-) {
- let last_transform = renderer.unwrap_and_deref().last_transform();
- *last_transform *= Affine::new((*transform).map(Into::into));
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_draw_path(
- mut renderer: Option<NonNull<VelloRenderer>>,
- mut path: Option<NonNull<VelloPath>>,
- mut paint: Option<NonNull<VelloPaint>>,
-) {
- let renderer = renderer.unwrap_and_deref();
- let path = path.unwrap_and_deref();
- let paint = paint.unwrap_and_deref();
-
- let transform = *renderer.last_transform();
-
- let builder = &mut renderer.builder;
-
- let skip_blending = paint.blend_mode == Mix::Normal.into();
-
- if !skip_blending {
- builder.push_layer(paint.blend_mode, 1.0, transform, &path.path.bounding_box());
- }
-
- match &paint.style {
- RenderStyle::Fill => builder.fill(path.fill, transform, &paint.brush, None, &path.path),
- RenderStyle::Stroke(stroke) => {
- builder.stroke(stroke, transform, &paint.brush, None, &path.path)
- }
- }
-
- if !skip_blending {
- builder.pop_layer();
- }
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_clip_path(
- mut renderer: Option<NonNull<VelloRenderer>>,
- mut clip: Option<NonNull<VelloPath>>,
-) {
- let renderer = renderer.unwrap_and_deref();
-
- let transform = *renderer.last_transform();
-
- if *renderer.last_clip() {
- renderer.builder.pop_layer();
- }
-
- renderer
- .builder
- .push_layer(Mix::Clip, 1.0, transform, &clip.unwrap_and_deref().path);
-
- *renderer.last_clip() = true;
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_draw_image(
- mut renderer: Option<NonNull<VelloRenderer>>,
- mut image: Option<NonNull<Image>>,
- blend_mode: rive::BlendMode,
- opacity: f32,
-) {
- let renderer = renderer.unwrap_and_deref();
- let image = image.unwrap_and_deref();
- let mix: Mix = blend_mode.into();
-
- let transform = renderer.last_transform().pre_translate(Vec2::new(
- image.width as f64 * -0.5,
- image.height as f64 * -0.5,
- ));
- let rect = Rect::new(0.0, 0.0, image.width as f64, image.height as f64);
-
- let builder = &mut renderer.builder;
-
- let skip_blending = mix == Mix::Normal && opacity == 1.0;
-
- if skip_blending {
- builder.push_layer(mix, opacity, transform, &rect);
- }
-
- builder.draw_image(image, transform);
-
- if skip_blending {
- builder.pop_layer();
- }
-}
-
-fn triangle_path(points: [Point; 3]) -> BezPath {
- BezPath::from_path_segments(
- [
- PathSeg::Line(Line::new(points[0], points[1])),
- PathSeg::Line(Line::new(points[1], points[2])),
- PathSeg::Line(Line::new(points[2], points[0])),
- ]
- .into_iter(),
- )
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn vello_renderer_draw_image_mesh(
- mut renderer: Option<NonNull<VelloRenderer>>,
- mut image: Option<NonNull<Image>>,
- vertices_data: *const rive::Vec2D,
- vertices_len: usize,
- uvs_data: *const rive::Vec2D,
- uvs_len: usize,
- indices_data: *const u16,
- indices_len: usize,
- blend_mode: rive::BlendMode,
- opacity: f32,
-) {
- let renderer = renderer.unwrap_and_deref();
- let image = image.unwrap_and_deref();
-
- let vertices = slice::from_raw_parts(vertices_data, vertices_len);
- let uvs = slice::from_raw_parts(uvs_data, uvs_len);
- let indices = slice::from_raw_parts(indices_data, indices_len);
-
- let mix: Mix = blend_mode.into();
-
- for triangle_indices in indices.chunks_exact(3) {
- let points = [
- vertices[triangle_indices[0] as usize],
- vertices[triangle_indices[1] as usize],
- vertices[triangle_indices[2] as usize],
- ];
- let uvs = [
- uvs[triangle_indices[0] as usize],
- uvs[triangle_indices[1] as usize],
- uvs[triangle_indices[2] as usize],
- ];
-
- let center = Point::new(
- ((points[0].x + points[1].x + points[2].x) / 3.0) as f64,
- ((points[0].y + points[1].y + points[2].y) / 3.0) as f64,
- );
-
- let path = triangle_path(points.map(|v| Point::new(v.x as f64, v.y as f64)));
-
- let transform = renderer
- .last_transform()
- .pre_scale_from_origin(1.03, center);
- let brush_transform = util::map_uvs_to_triangle(&points, &uvs, image.width, image.height);
-
- let builder = &mut renderer.builder;
-
- let skip_blending = mix == Mix::Normal;
-
- if !skip_blending {
- builder.push_layer(mix, opacity, transform, &path.bounding_box());
- }
-
- builder.fill(
- Fill::NonZero,
- transform,
- BrushRef::Image(image),
- Some(brush_transform),
- &path,
- );
-
- if !skip_blending {
- builder.pop_layer();
- }
- }
-}
diff --git a/vello/src/main.rs b/vello/src/main.rs
index 06a4dc0..9bb6c32 100644
--- a/vello/src/main.rs
+++ b/vello/src/main.rs
@@ -1,6 +1,6 @@
-use std::time::Instant;
+use std::{fs, time::Instant};
-use rive_vello::{VelloRenderer, ViewerContent};
+use rive_rs::{Artboard, File, Instantiate, Viewport};
use vello::{
kurbo::{Affine, Rect, Vec2},
peniko::{Color, Fill},
@@ -24,7 +24,8 @@
const SCROLL_FACTOR_THRESHOLD: f64 = 100.0;
fn main() {
- let mut viewer_content: Option<ViewerContent> = None;
+ let mut viewport = Viewport::default();
+ let mut scene: Option<Box<dyn rive_rs::Scene>> = None;
let event_loop = EventLoop::new();
let mut cached_window: Option<Window> = None;
@@ -46,9 +47,7 @@
match event {
WindowEvent::CloseRequested => *control_flow = ControlFlow::Exit,
WindowEvent::Resized(size) => {
- if let Some(viewer_content) = &viewer_content {
- viewer_content.handle_resize(size.width, size.height);
- }
+ viewport.resize(size.width, size.height);
render_cx.resize_surface(&mut render_state.surface, size.width, size.height);
render_state.window.request_redraw();
@@ -58,19 +57,23 @@
button: MouseButton::Left,
..
} => {
- if let Some(viewer_content) = &viewer_content {
- let handler = match state {
- ElementState::Pressed => ViewerContent::handle_pointer_down,
- ElementState::Released => ViewerContent::handle_pointer_up,
- };
-
- handler(viewer_content, mouse_pos);
+ if let Some(scene) = &mut scene {
+ match state {
+ ElementState::Pressed => scene.pointer_down(
+ mouse_pos.x as f32,
+ mouse_pos.y as f32,
+ &viewport,
+ ),
+ ElementState::Released => {
+ scene.pointer_up(mouse_pos.x as f32, mouse_pos.y as f32, &viewport)
+ }
+ }
}
}
WindowEvent::CursorMoved { position, .. } => {
mouse_pos = Vec2::new(position.x, position.y);
- if let Some(viewer_content) = &viewer_content {
- viewer_content.handle_pointer_move(mouse_pos);
+ if let Some(scene) = &mut scene {
+ scene.pointer_move(mouse_pos.x as f32, mouse_pos.y as f32, &viewport);
}
}
WindowEvent::MouseWheel { delta, .. } => match delta {
@@ -84,12 +87,12 @@
}
},
WindowEvent::DroppedFile(path) => {
- viewer_content = ViewerContent::new(path);
+ scene = Some({
+ let file = File::new(&fs::read(path).unwrap()).unwrap();
+ let artboard = Artboard::instantiate(&file, None).unwrap();
- if let Some(viewer_content) = &viewer_content {
- let size = render_state.window.inner_size();
- viewer_content.handle_resize(size.width, size.height);
- }
+ Box::<dyn rive_rs::Scene>::instantiate(&artboard, None).unwrap()
+ });
}
_ => {}
}
@@ -100,7 +103,7 @@
}
}
Event::RedrawRequested(_) => {
- let mut vello_renderer = VelloRenderer::default();
+ let mut rive_renderer = rive_rs::Renderer::default();
let factor = (scroll_delta / SCROLL_FACTOR_THRESHOLD).max(1.0) as u32;
let elapsed = &frame_start_time.elapsed();
@@ -142,15 +145,15 @@
.get_current_texture()
.expect("failed to get surface texture");
- let mut scene = Scene::default();
- let mut builder = SceneBuilder::for_scene(&mut scene);
+ let mut vello_scene = Scene::default();
+ let mut builder = SceneBuilder::for_scene(&mut vello_scene);
- if let Some(viewer_content) = &mut viewer_content {
- viewer_content.handle_draw(&mut vello_renderer, elapsed.as_secs_f64());
+ if let Some(scene) = &mut scene {
+ scene.advance_and_maybe_draw(&mut rive_renderer, *elapsed, &mut viewport);
for i in 0..factor.pow(2) {
builder.append(
- &vello_renderer.scene,
+ rive_renderer.scene(),
Some(
Affine::default()
.then_scale(1.0 / factor as f64)
@@ -162,7 +165,7 @@
);
}
} else {
- // Vello currently crashes when rendering an empty scene.
+ // Vello doesn't draw base color when there is no geometry.
builder.fill(
Fill::NonZero,
Affine::IDENTITY,
@@ -172,17 +175,19 @@
);
}
- vello::block_on_wgpu(
- &device_handle.device,
- renderer.as_mut().unwrap().render_to_surface_async(
+ if !vello_scene.data().is_empty() {
+ vello::block_on_wgpu(
&device_handle.device,
- &device_handle.queue,
- &scene,
- &surface_texture,
- &render_params,
- ),
- )
- .expect("failed to render to surface");
+ renderer.as_mut().unwrap().render_to_surface_async(
+ &device_handle.device,
+ &device_handle.queue,
+ &vello_scene,
+ &surface_texture,
+ &render_params,
+ ),
+ )
+ .expect("failed to render to surface");
+ }
surface_texture.present();
device_handle.device.poll(wgpu::Maintain::Poll);
@@ -220,6 +225,7 @@
timestamp_period: render_cx.devices[render_state.surface.dev_id]
.queue
.get_timestamp_period(),
+ use_cpu: false,
},
)
.expect("Could create renderer"),
diff --git a/vello/src/rive.rs b/vello/src/rive.rs
deleted file mode 100644
index 7c6c222..0000000
--- a/vello/src/rive.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-use vello::peniko::{Mix, Stroke};
-
-use crate::RenderStyle;
-
-#[repr(C)]
-#[derive(Debug, Default)]
-pub enum RenderPaint {
- Stroke,
- #[default]
- Fill,
-}
-
-impl From<RenderPaint> for RenderStyle {
- fn from(value: RenderPaint) -> Self {
- match value {
- RenderPaint::Stroke => Self::Stroke(Stroke::new(0.0)),
- RenderPaint::Fill => Self::Fill,
- }
- }
-}
-
-#[repr(u32)]
-#[derive(Debug, Default)]
-pub enum StrokeJoin {
- #[default]
- Miter = 0,
- Round = 1,
- Bevel = 2,
-}
-
-#[repr(u32)]
-#[derive(Debug, Default)]
-pub enum StrokeCap {
- #[default]
- Butt = 0,
- Round = 1,
- Square = 2,
-}
-
-#[repr(u32)]
-#[derive(Debug, Default)]
-pub enum BlendMode {
- #[default]
- SrcOver = 3,
- Screen = 14,
- Overlay = 15,
- Darken = 16,
- Lighten = 17,
- ColorDodge = 18,
- ColorBurn = 19,
- HardLight = 20,
- SoftLight = 21,
- Difference = 22,
- Exclusion = 23,
- Multiply = 24,
- Hue = 25,
- Saturation = 26,
- Color = 27,
- Luminosity = 28,
-}
-
-impl From<BlendMode> for Mix {
- fn from(value: BlendMode) -> Self {
- match value {
- BlendMode::SrcOver => Self::Normal,
- BlendMode::Screen => Self::Screen,
- BlendMode::Overlay => Self::Overlay,
- BlendMode::Darken => Self::Darken,
- BlendMode::Lighten => Self::Lighten,
- BlendMode::ColorDodge => Self::ColorDodge,
- BlendMode::ColorBurn => Self::ColorBurn,
- BlendMode::HardLight => Self::HardLight,
- BlendMode::SoftLight => Self::SoftLight,
- BlendMode::Difference => Self::Difference,
- BlendMode::Exclusion => Self::Exclusion,
- BlendMode::Multiply => Self::Multiply,
- BlendMode::Hue => Self::Hue,
- BlendMode::Saturation => Self::Saturation,
- BlendMode::Color => Self::Color,
- BlendMode::Luminosity => Self::Luminosity,
- }
- }
-}
-
-#[repr(C)]
-#[derive(Debug, Default)]
-pub enum FillRule {
- #[default]
- NonZero,
- EvenOdd,
-}
-
-#[repr(C)]
-#[derive(Clone, Copy, Debug)]
-pub struct Vec2D {
- pub x: f32,
- pub y: f32,
-}
diff --git a/vello/src/util.rs b/vello/src/util.rs
deleted file mode 100644
index aba56d9..0000000
--- a/vello/src/util.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-use std::{
- ops::{Add, Mul, Neg, Sub},
- ptr::NonNull,
-};
-
-use vello::kurbo::{Affine, Point};
-
-use crate::rive;
-
-pub trait UnwrapAndDeref {
- type Deref;
-
- unsafe fn unwrap_and_deref(&mut self) -> &mut Self::Deref;
-}
-
-impl<T> UnwrapAndDeref for Option<NonNull<T>> {
- type Deref = T;
-
- unsafe fn unwrap_and_deref(&mut self) -> &mut Self::Deref {
- self.map(|mut ptr| ptr.as_mut()).unwrap()
- }
-}
-
-#[derive(Clone, Copy, Debug)]
-struct Vec2 {
- x: f32,
- y: f32,
-}
-
-impl Vec2 {
- pub fn new(x: f32, y: f32) -> Self {
- Self { x, y }
- }
-
- pub fn splat(val: f32) -> Self {
- Self::new(val, val)
- }
-}
-
-impl Add for Vec2 {
- type Output = Self;
-
- fn add(self, rhs: Self) -> Self::Output {
- Self::new(self.x + rhs.x, self.y + rhs.y)
- }
-}
-
-impl Sub for Vec2 {
- type Output = Self;
-
- fn sub(self, rhs: Self) -> Self::Output {
- Self::new(self.x - rhs.x, self.y - rhs.y)
- }
-}
-
-impl Mul for Vec2 {
- type Output = Self;
-
- fn mul(self, rhs: Self) -> Self::Output {
- Self::new(self.x * rhs.x, self.y * rhs.y)
- }
-}
-
-impl Mul<f32> for Vec2 {
- type Output = Self;
-
- fn mul(self, rhs: f32) -> Self::Output {
- self * Self::splat(rhs)
- }
-}
-
-impl Neg for Vec2 {
- type Output = Self;
-
- fn neg(self) -> Self::Output {
- Self::new(-self.x, -self.y)
- }
-}
-
-/// Finds the affine transform that maps triangle `from` to triangle `to`. The algorithm is based
-/// on the [Simplex Affine Mapping] method which has a [Swift implementation].
-///
-/// [Simplex Affine Mapping]: https://www.researchgate.net/publication/332410209_Beginner%27s_guide_to_mapping_simplexes_affinely
-/// [Swift implementation]: https://rethunk.medium.com/finding-an-affine-transform-using-three-2d-point-correspondences-using-simplex-affine-mapping-255aeb4e8055
-fn simplex_affine_mapping(from: [Vec2; 3], to: [Vec2; 3]) -> Affine {
- let [a, b, c] = from;
- let [d, e, f] = to;
-
- let det_recip = (a.x * b.y + b.x * c.y + c.x * a.y - a.x * c.y - b.x * a.y - c.x * b.y).recip();
-
- let p = (d * (b.y - c.y) - e * (a.y - c.y) + f * (a.y - b.y)) * det_recip;
-
- let q = (e * (a.x - c.x) - d * (b.x - c.x) - f * (a.x - b.x)) * det_recip;
-
- let t = (d * (b.x * c.y - b.y * c.x) - e * (a.x * c.y - a.y * c.x)
- + f * (a.x * b.y - a.y * b.x))
- * det_recip;
-
- Affine::new([
- p.x as f64, p.y as f64, q.x as f64, q.y as f64, t.x as f64, t.y as f64,
- ])
-}
-
-pub fn map_uvs_to_triangle(
- points: &[rive::Vec2D; 3],
- uvs: &[rive::Vec2D; 3],
- width: u32,
- height: u32,
-) -> Affine {
- simplex_affine_mapping(
- uvs.map(|v| Vec2::new(v.x * width as f32, v.y * height as f32)),
- points.map(|v| Vec2::new(v.x, v.y)),
- )
-}
-
-pub trait ScaleFromOrigin {
- fn pre_scale_from_origin(self, scale: f64, origin: Point) -> Self;
-}
-
-impl ScaleFromOrigin for Affine {
- fn pre_scale_from_origin(self, scale: f64, origin: Point) -> Self {
- let origin = origin.to_vec2();
- self.pre_translate(origin)
- .pre_scale(scale)
- .pre_translate(-origin)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- use vello::kurbo;
-
- #[test]
- fn straightforward_sam() {
- let from = [
- Vec2::new(1.0, 1.0),
- Vec2::new(3.0, 1.0),
- Vec2::new(1.0, 3.0),
- ];
- let to = [
- Vec2::new(4.0, 4.0),
- Vec2::new(4.0, -1.0),
- Vec2::new(-2.0, 4.0),
- ];
-
- let mapping = simplex_affine_mapping(from, to);
-
- for (from, to) in from.into_iter().zip(to.into_iter()) {
- let res = mapping * kurbo::Point::new(from.x as f64, from.y as f64);
-
- assert_eq!(res.x as f32, to.x);
- assert_eq!(res.y as f32, to.y);
- }
- }
-}
diff --git a/vello/src/vello_renderer.cpp b/vello/src/vello_renderer.cpp
deleted file mode 100644
index ffd59af..0000000
--- a/vello/src/vello_renderer.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-#include "vello_renderer.hpp"
-
-VelloPath::~VelloPath() { vello_path_release(m_path); }
-
-void VelloPath::rewind() { vello_path_rewind(m_path); }
-
-void VelloPath::addRenderPath(RenderPath* path, const Mat2D& transform)
-{
- vello_path_extend(m_path, static_cast<VelloPath*>(path)->m_path, transform.values());
-}
-
-void VelloPath::fillRule(FillRule value) { vello_path_set_fill_rule(m_path, value); }
-
-void VelloPath::moveTo(float x, float y) { vello_path_move_to(m_path, x, y); }
-
-void VelloPath::lineTo(float x, float y) { vello_path_line_to(m_path, x, y); }
-
-void VelloPath::cubicTo(float ox, float oy, float ix, float iy, float x, float y)
-{
- vello_path_cubic_to(m_path, ox, oy, ix, iy, x, y);
-}
-
-void VelloPath::close() { vello_path_close(m_path); }
-
-VelloGradient::~VelloGradient() { vello_gradient_release(m_gradient); }
-
-VelloImage::~VelloImage() { vello_image_release(m_image); }
-
-VelloPaint::~VelloPaint() { vello_paint_release(m_paint); }
-
-void VelloPaint::style(RenderPaintStyle style) { vello_paint_set_style(m_paint, style); }
-
-void VelloPaint::color(unsigned int value) { vello_paint_set_color(m_paint, value); }
-
-void VelloPaint::thickness(float value) { vello_paint_set_thickness(m_paint, value); }
-
-void VelloPaint::join(StrokeJoin value) { vello_paint_set_join(m_paint, value); }
-
-void VelloPaint::cap(StrokeCap value) { vello_paint_set_cap(m_paint, value); }
-
-void VelloPaint::blendMode(BlendMode value) { vello_paint_set_blend_mode(m_paint, value); }
-
-void VelloPaint::shader(rcp<RenderShader> shader)
-{
- VelloGradient* gradient = (VelloGradient*)shader.get();
-
- if (gradient != nullptr)
- {
- vello_paint_set_gradient(m_paint, gradient->gradient());
- }
-}
-
-void VelloRenderer::save() { vello_renderer_save(m_renderer); }
-
-void VelloRenderer::restore() { vello_renderer_restore(m_renderer); }
-
-void VelloRenderer::transform(const Mat2D& transform)
-{
- vello_renderer_transform(m_renderer, transform.values());
-}
-
-void VelloRenderer::clipPath(RenderPath* path)
-{
- vello_renderer_clip_path(m_renderer, static_cast<VelloPath*>(path)->path());
-}
-
-void VelloRenderer::drawPath(RenderPath* path, RenderPaint* paint)
-{
- vello_renderer_draw_path(m_renderer,
- static_cast<VelloPath*>(path)->path(),
- static_cast<VelloPaint*>(paint)->paint());
-}
-
-void VelloRenderer::drawImage(const RenderImage* image, BlendMode blend_mode, float opacity)
-{
- vello_renderer_draw_image(m_renderer,
- static_cast<const VelloImage*>(image)->image(),
- blend_mode,
- opacity);
-}
-
-void VelloRenderer::drawImageMesh(const RenderImage* image,
- rcp<RenderBuffer> vertices,
- rcp<RenderBuffer> uvCoords,
- rcp<RenderBuffer> indices,
- uint32_t vertexCount,
- uint32_t indexCount,
- BlendMode blendMode,
- float opacity)
-{
- vello_renderer_draw_image_mesh(m_renderer,
- static_cast<const VelloImage*>(image)->image(),
- DataRenderBuffer::Cast(vertices.get())->vecs(),
- vertexCount,
- DataRenderBuffer::Cast(uvCoords.get())->vecs(),
- vertexCount,
- DataRenderBuffer::Cast(indices.get())->u16s(),
- indexCount,
- blendMode,
- opacity);
-}
-
-rcp<RenderBuffer> VelloFactory::makeRenderBuffer(RenderBufferType type,
- RenderBufferFlags flags,
- size_t sizeInBytes)
-{
- return make_rcp<DataRenderBuffer>(type, flags, sizeInBytes);
-}
-
-rcp<RenderShader> VelloFactory::makeLinearGradient(float sx,
- float sy,
- float ex,
- float ey,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- size_t count)
-{
- RawVelloGradient gradient = vello_gradient_new_linear(sx, sy, ex, ey, colors, stops, count);
- return rcp<RenderShader>(new VelloGradient(std::move(gradient)));
-}
-
-rcp<RenderShader> VelloFactory::makeRadialGradient(float cx,
- float cy,
- float radius,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- size_t count)
-{
- RawVelloGradient gradient = vello_gradient_new_radial(cx, cy, radius, colors, stops, count);
- return rcp<RenderShader>(new VelloGradient(std::move(gradient)));
-}
-
-std::unique_ptr<RenderPath> VelloFactory::makeRenderPath(RawPath& rawPath, FillRule fillRule)
-{
- std::unique_ptr<VelloPath> path = std::make_unique<VelloPath>();
-
- for (auto [verb, points] : rawPath)
- {
- switch (verb)
- {
- case PathVerb::move:
- path->move(points[0]);
- break;
- case PathVerb::line:
- path->line(points[1]);
- break;
- case PathVerb::cubic:
- path->cubic(points[1], points[2], points[3]);
- break;
- case PathVerb::close:
- path->close();
- break;
- }
- }
-
- return path;
-}
-
-std::unique_ptr<RenderPath> VelloFactory::makeEmptyRenderPath()
-{
- return std::make_unique<VelloPath>();
-}
-
-std::unique_ptr<RenderPaint> VelloFactory::makeRenderPaint()
-{
- return std::make_unique<VelloPaint>();
-}
-
-std::unique_ptr<RenderImage> VelloFactory::decodeImage(Span<const uint8_t> encoded)
-{
- return std::make_unique<VelloImage>(vello_image_new(encoded.data(), encoded.size()));
-}
-
-static VelloFactory factory;
-rive::Factory* ViewerContent::RiveFactory() { return &factory; }
diff --git a/vello/src/vello_renderer.hpp b/vello/src/vello_renderer.hpp
deleted file mode 100644
index ab8a0c6..0000000
--- a/vello/src/vello_renderer.hpp
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef _RIVE_VELLO_RENDERER_HPP_
-#define _RIVE_VELLO_RENDERER_HPP_
-
-#include "rive/factory.hpp"
-#include "rive/math/mat2d.hpp"
-#include "rive/math/path_types.hpp"
-#include "rive/math/vec2d.hpp"
-#include "rive/renderer.hpp"
-#include "utils/factory_utils.hpp"
-#include "viewer/viewer_content.hpp"
-
-#include "vello_renderer.hpp"
-
-using namespace rive;
-
-typedef void* RawVelloPath;
-typedef void* RawVelloGradient;
-typedef void* RawVelloImage;
-typedef void* RawVelloPaint;
-typedef void* RawVelloRenderer;
-
-extern "C"
-{
- typedef void* RawVelloPath;
- typedef void* RawVelloGradient;
- typedef void* RawVelloImage;
- typedef void* RawVelloPaint;
- typedef void* RawVelloRenderer;
-
- const RawVelloPath vello_path_new();
- void vello_path_release(const RawVelloPath path);
- void vello_path_rewind(const RawVelloPath path);
- void vello_path_extend(const RawVelloPath path, void* other, const float* transform);
- void vello_path_set_fill_rule(const RawVelloPath path, FillRule fill_rule);
- void vello_path_move_to(const RawVelloPath path, float x, float y);
- void vello_path_line_to(const RawVelloPath path, float x, float y);
- void vello_path_cubic_to(const RawVelloPath path,
- float ox,
- float oy,
- float ix,
- float iy,
- float x,
- float y);
- void vello_path_close(const RawVelloPath path);
-
- const RawVelloGradient vello_gradient_new_linear(float sx,
- float sy,
- float ex,
- float ey,
- const uint32_t* colors_data,
- const float* stops_data,
- size_t len);
- const RawVelloGradient vello_gradient_new_radial(float cx,
- float cy,
- float radius,
- const uint32_t* colors_data,
- const float* stops_data,
- size_t len);
- void vello_gradient_release(const RawVelloGradient gradient);
-
- const RawVelloImage vello_image_new(const uint8_t* data, size_t len);
- void vello_image_release(const RawVelloImage image);
-
- const RawVelloPaint vello_paint_new();
- void vello_paint_release(const RawVelloPaint paint);
- void vello_paint_set_style(const RawVelloPaint paint, RenderPaintStyle style);
- void vello_paint_set_color(const RawVelloPaint paint, uint32_t color);
- void vello_paint_set_thickness(const RawVelloPaint paint, float thickness);
- void vello_paint_set_join(const RawVelloPaint paint, StrokeJoin join);
- void vello_paint_set_cap(const RawVelloPaint paint, StrokeCap cap);
- void vello_paint_set_blend_mode(const RawVelloPaint paint, BlendMode blend_mode);
- void vello_paint_set_gradient(const RawVelloPaint paint, const RawVelloGradient gradient);
-
- const RawVelloRenderer vello_renderer_new();
- void vello_renderer_release(const RawVelloRenderer renderer);
- void vello_renderer_save(const RawVelloRenderer renderer);
- void vello_renderer_restore(const RawVelloRenderer renderer);
- void vello_renderer_transform(const RawVelloRenderer renderer, const float* transform);
- void vello_renderer_clip_path(const RawVelloRenderer renderer, const RawVelloPath path);
- void vello_renderer_draw_path(const RawVelloRenderer renderer,
- const RawVelloPath path,
- const RawVelloPaint paint);
- void vello_renderer_draw_image(const RawVelloRenderer renderer,
- const RawVelloImage image,
- BlendMode blend_mode,
- float opacity);
- void vello_renderer_draw_image_mesh(const RawVelloRenderer renderer,
- const RawVelloImage image,
- const Vec2D* vertices_data,
- size_t vertices_len,
- const Vec2D* uvs_data,
- size_t uvs_len,
- const uint16_t* indices_data,
- size_t indices_len,
- BlendMode blend_mode,
- float opacity);
-}
-
-using namespace rive;
-
-class VelloPath : public RenderPath
-{
-private:
- RawVelloPath m_path;
-
-public:
- VelloPath() : m_path(vello_path_new()) {}
- VelloPath(RawVelloPath& path) : m_path(std::move(path)) {}
- ~VelloPath() override;
-
- const RawVelloPath& path() const { return m_path; }
-
- void rewind() override;
- void addRenderPath(RenderPath* path, const Mat2D& transform) override;
- void fillRule(FillRule value) override;
- void moveTo(float x, float y) override;
- void lineTo(float x, float y) override;
- void cubicTo(float ox, float oy, float ix, float iy, float x, float y) override;
- virtual void close() override;
-};
-
-class VelloGradient : public RenderShader
-{
-private:
- RawVelloGradient m_gradient;
-
-public:
- VelloGradient(RawVelloGradient gradient) : m_gradient(gradient) {}
- ~VelloGradient() override;
-
- const RawVelloGradient& gradient() const { return m_gradient; }
-};
-
-class VelloImage : public RenderImage
-{
-private:
- RawVelloImage m_image;
-
-public:
- VelloImage(RawVelloImage image) : m_image(image) {}
- ~VelloImage() override;
-
- const RawVelloImage& image() const { return m_image; }
-};
-
-class VelloPaint : public RenderPaint
-{
-private:
- RawVelloPaint m_paint;
-
-public:
- VelloPaint() : m_paint(vello_paint_new()) {}
- ~VelloPaint() override;
-
- const RawVelloPaint& paint() const { return m_paint; }
-
- void style(RenderPaintStyle style) override;
- void color(unsigned int value) override;
- void thickness(float value) override;
- void join(StrokeJoin value) override;
- void cap(StrokeCap value) override;
- void blendMode(BlendMode value) override;
- void shader(rcp<RenderShader>) override;
- void invalidateStroke() override {}
-};
-
-class VelloRenderer : public Renderer
-{
-protected:
- RawVelloRenderer m_renderer;
-
-public:
- VelloRenderer() : m_renderer(vello_renderer_new()) {}
- VelloRenderer(RawVelloRenderer renderer) : m_renderer(std::move(renderer)) {}
- ~VelloRenderer() override {}
-
- void save() override;
- void restore() override;
- void transform(const Mat2D& transform) override;
- void clipPath(RenderPath* path) override;
- void drawPath(RenderPath* path, RenderPaint* paint) override;
- void drawImage(const RenderImage*, BlendMode, float opacity) override;
- void drawImageMesh(const RenderImage*,
- rcp<RenderBuffer> vertices_f32,
- rcp<RenderBuffer> uvCoords_f32,
- rcp<RenderBuffer> indices_u16,
- uint32_t vertexCount,
- uint32_t indexCount,
- BlendMode,
- float opacity) override;
-};
-
-class VelloFactory : public Factory
-{
-public:
- rcp<RenderBuffer> makeRenderBuffer(RenderBufferType, RenderBufferFlags, size_t) override;
-
- rcp<RenderShader> makeLinearGradient(float sx,
- float sy,
- float ex,
- float ey,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- size_t count) override;
-
- rcp<RenderShader> makeRadialGradient(float cx,
- float cy,
- float radius,
- const ColorInt colors[], // [count]
- const float stops[], // [count]
- size_t count) override;
-
- std::unique_ptr<RenderPath> makeRenderPath(RawPath&, FillRule) override;
-
- std::unique_ptr<RenderPath> makeEmptyRenderPath() override;
-
- std::unique_ptr<RenderPaint> makeRenderPaint() override;
-
- std::unique_ptr<RenderImage> decodeImage(Span<const uint8_t>) override;
-};
-
-#endif
diff --git a/vello/src/viewer.rs b/vello/src/viewer.rs
deleted file mode 100644
index 2b51a58..0000000
--- a/vello/src/viewer.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-use std::{
- ffi::CString, fs::File, io::Read, os::unix::prelude::OsStrExt, path::Path, ptr::NonNull,
-};
-
-use vello::kurbo::Vec2;
-
-use crate::VelloRenderer;
-
-#[derive(Debug)]
-enum RawViewerContent {}
-
-extern "C" {
- fn viewer_content_new(raw_path: *const i8) -> Option<NonNull<RawViewerContent>>;
- fn viewer_content_release(raw_viewer_content: Option<NonNull<RawViewerContent>>);
- fn viewer_content_handle_resize(
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
- width: i32,
- height: i32,
- );
- // We're simply propagating the `VelloRender` pointer opaquely through the FFI.
- #[allow(improper_ctypes)]
- fn viewer_content_handle_draw(
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
- raw_vello_renderer: Option<NonNull<VelloRenderer>>,
- elapsed: f64,
- );
- fn viewer_content_handle_pointer_move(
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
- x: f32,
- y: f32,
- );
- fn viewer_content_handle_pointer_down(
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
- x: f32,
- y: f32,
- );
- fn viewer_content_handle_pointer_up(
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
- x: f32,
- y: f32,
- );
-}
-
-#[derive(Debug)]
-pub struct ViewerContent {
- raw_viewer_content: Option<NonNull<RawViewerContent>>,
-}
-
-impl ViewerContent {
- pub fn new<P: AsRef<Path>>(path: P) -> Option<Self> {
- let path = path.as_ref();
-
- let header = {
- let mut file = File::open(path).ok()?;
- let mut buffer = [0; 4];
-
- file.read_exact(&mut buffer).ok()?;
-
- buffer
- };
-
- if &header != b"RIVE" {
- return None;
- }
-
- let c_str = CString::new(path.as_os_str().as_bytes()).unwrap();
- let raw_viewer_content = Some(unsafe { viewer_content_new(c_str.as_ptr())? });
-
- Some(Self { raw_viewer_content })
- }
-
- pub fn handle_resize(&self, width: u32, height: u32) {
- unsafe {
- viewer_content_handle_resize(self.raw_viewer_content, width as i32, height as i32);
- }
- }
-
- pub fn handle_draw(&mut self, renderer: &mut VelloRenderer, elapsed: f64) {
- unsafe {
- viewer_content_handle_draw(
- self.raw_viewer_content,
- NonNull::new(renderer as *mut VelloRenderer),
- elapsed,
- )
- }
- }
-
- pub fn handle_pointer_move(&self, pos: Vec2) {
- unsafe {
- viewer_content_handle_pointer_move(self.raw_viewer_content, pos.x as f32, pos.y as f32);
- }
- }
-
- pub fn handle_pointer_down(&self, pos: Vec2) {
- unsafe {
- viewer_content_handle_pointer_down(self.raw_viewer_content, pos.x as f32, pos.y as f32);
- }
- }
-
- pub fn handle_pointer_up(&self, pos: Vec2) {
- unsafe {
- viewer_content_handle_pointer_up(self.raw_viewer_content, pos.x as f32, pos.y as f32);
- }
- }
-}
-
-impl Drop for ViewerContent {
- fn drop(&mut self) {
- unsafe {
- viewer_content_release(self.raw_viewer_content);
- }
- }
-}
diff --git a/vello/src/winit_viewer.cpp b/vello/src/winit_viewer.cpp
deleted file mode 100644
index 9406af1..0000000
--- a/vello/src/winit_viewer.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "viewer/viewer_content.hpp"
-
-#include "vello_renderer.hpp"
-
-extern "C"
-{
- typedef void* RawViewerContent;
-
- const RawViewerContent viewer_content_new(const char* filename)
- {
- return static_cast<void*>(ViewerContent::findHandler(filename).release());
- }
-
- void viewer_content_release(const RawViewerContent viewer_content)
- {
- std::unique_ptr<ViewerContent> val(std::move(static_cast<ViewerContent*>(viewer_content)));
- }
-
- void viewer_content_handle_resize(const RawViewerContent viewer_content,
- int32_t width,
- int32_t height)
- {
- static_cast<ViewerContent*>(viewer_content)->handleResize(width, height);
- }
-
- void viewer_content_handle_draw(const RawViewerContent viewer_content,
- RawVelloRenderer raw_renderer,
- double elapsed)
- {
- VelloRenderer renderer = VelloRenderer(raw_renderer);
- static_cast<ViewerContent*>(viewer_content)->handleDraw(&renderer, elapsed);
- }
-
- void viewer_content_handle_pointer_move(const RawViewerContent viewer_content, float x, float y)
- {
- static_cast<ViewerContent*>(viewer_content)->handlePointerMove(x, y);
- }
-
- void viewer_content_handle_pointer_down(const RawViewerContent viewer_content, float x, float y)
- {
- static_cast<ViewerContent*>(viewer_content)->handlePointerDown(x, y);
- }
-
- void viewer_content_handle_pointer_up(const RawViewerContent viewer_content, float x, float y)
- {
- static_cast<ViewerContent*>(viewer_content)->handlePointerUp(x, y);
- }
-}