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); - } -}