Skip to main content

widgetkit_render/
surface.rs

1use crate::{Canvas, RenderFrame, frame::Frame, raster::Rasterizer};
2use widgetkit_core::{Color, Error, Result};
3
4pub trait RenderSurface {
5    fn size(&self) -> (u32, u32);
6    fn present(&mut self, pixels: &[Color]) -> Result<()>;
7}
8
9pub trait Renderer: Send {
10    fn render_frame(&mut self, frame: RenderFrame, surface: &mut dyn RenderSurface) -> Result<()>;
11
12    fn render_canvas(&mut self, canvas: Canvas, surface: &mut dyn RenderSurface) -> Result<()> {
13        self.render_frame(canvas.into_frame(), surface)
14    }
15}
16
17pub struct SoftwareRenderer {
18    pixels: Vec<Color>,
19}
20
21impl SoftwareRenderer {
22    pub fn new() -> Self {
23        Self { pixels: Vec::new() }
24    }
25
26    fn ensure_buffer(&mut self, width: u32, height: u32) -> Result<()> {
27        let len = usize::try_from(width)
28            .ok()
29            .and_then(|w| usize::try_from(height).ok().map(|h| w.saturating_mul(h)))
30            .ok_or_else(|| Error::render("surface dimensions exceed addressable memory"))?;
31        if self.pixels.len() != len {
32            self.pixels.resize(len, Color::TRANSPARENT);
33        }
34        Ok(())
35    }
36}
37
38impl Default for SoftwareRenderer {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl Renderer for SoftwareRenderer {
45    fn render_frame(
46        &mut self,
47        render_frame: RenderFrame,
48        surface: &mut dyn RenderSurface,
49    ) -> Result<()> {
50        let (width, height) = surface.size();
51        self.ensure_buffer(width, height)?;
52        let surface_frame = Frame::new(width, height, &mut self.pixels);
53        let mut raster = Rasterizer::new(surface_frame);
54        raster.execute(render_frame);
55        drop(raster);
56        surface.present(&self.pixels)
57    }
58}
59
60// TODO(v0.3): allow alternate renderer implementations
61// TODO(v0.7): evaluate compatibility path for web/tauri-backed rendering