Skip to main content

cranpose_render_pixels/
lib.rs

1mod draw;
2mod pipeline;
3pub mod scene;
4pub mod style;
5
6use cranpose_render_common::{
7    RenderScene, Renderer,
8    text_measure::{CachedFontTextMeasurer, SoftwareTextResources},
9};
10use cranpose_ui::LayoutTree;
11use cranpose_ui_graphics::Size;
12pub use draw::draw_scene;
13pub use scene::{HitRegion, Scene};
14
15#[derive(Debug)]
16pub enum PixelsRendererError {
17    Layout(String),
18}
19
20pub struct PixelsRenderer {
21    scene: Scene,
22    text_resources: SoftwareTextResources,
23}
24
25impl Default for PixelsRenderer {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl PixelsRenderer {
32    pub fn new() -> Self {
33        Self {
34            scene: Scene::new(),
35            text_resources: SoftwareTextResources::default(),
36        }
37    }
38
39    pub fn draw(&self, frame: &mut [u8], width: u32, height: u32) {
40        draw::draw_scene_with_text_resources(
41            frame,
42            width,
43            height,
44            &self.scene,
45            &self.text_resources,
46        );
47    }
48
49    /// Rasterizes logical scene coordinates at `scale` device pixels per point.
50    /// Hit regions stay in logical coordinates. Invalid scales use 1.0.
51    pub fn draw_scaled(&self, frame: &mut [u8], width: u32, height: u32, scale: f32) {
52        let scale = if scale.is_finite() && scale > 0.0 {
53            scale
54        } else {
55            1.0
56        };
57        draw::draw_scene_scaled(
58            frame,
59            width,
60            height,
61            &self.scene,
62            &self.text_resources,
63            scale,
64        );
65    }
66}
67
68impl Renderer for PixelsRenderer {
69    type Scene = Scene;
70    type Error = PixelsRendererError;
71
72    fn attach_app_context_services(&mut self, app_context: &cranpose_ui::AppContext) {
73        app_context.set_text_measurer(CachedFontTextMeasurer::with_text_resources(
74            self.text_resources.clone(),
75            64,
76        ));
77    }
78
79    fn scene(&self) -> &Self::Scene {
80        &self.scene
81    }
82
83    fn scene_mut(&mut self) -> &mut Self::Scene {
84        &mut self.scene
85    }
86
87    fn rebuild_scene(
88        &mut self,
89        layout_tree: &LayoutTree,
90        _viewport: Size,
91    ) -> Result<(), Self::Error> {
92        self.scene.clear();
93        pipeline::render_layout_tree(layout_tree.root(), &mut self.scene);
94        Ok(())
95    }
96
97    fn rebuild_scene_from_applier(
98        &mut self,
99        applier: &mut cranpose_core::MemoryApplier,
100        root: cranpose_core::NodeId,
101        _viewport: Size,
102    ) -> Result<(), Self::Error> {
103        pipeline::render_from_applier(applier, root, &mut self.scene);
104        Ok(())
105    }
106}