cranpose_render_pixels/
lib.rs1#![doc = include_str!("../README.md")]
2
3mod draw;
4mod pipeline;
5pub mod scene;
6pub mod sprites;
7pub mod style;
8
9use cranpose_render_common::{
10 RenderScene, Renderer, SceneUpdates,
11 text_measure::{CachedFontTextMeasurer, SoftwareTextResources},
12};
13use cranpose_ui::LayoutTree;
14use cranpose_ui_graphics::Size;
15pub use draw::draw_scene;
16pub use scene::{HitRegion, Scene};
17
18#[derive(Debug)]
19pub enum PixelsRendererError {
20 Layout(String),
21}
22
23pub struct PixelsRenderer {
24 scene: Scene,
25 text_resources: SoftwareTextResources,
26 app_context: Option<std::rc::Weak<cranpose_ui::AppContext>>,
28}
29
30impl Default for PixelsRenderer {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl PixelsRenderer {
37 pub fn new() -> Self {
38 Self {
39 scene: Scene::new(),
40 text_resources: SoftwareTextResources::default(),
41 app_context: None,
42 }
43 }
44
45 pub fn draw(&self, frame: &mut [u8], width: u32, height: u32) {
46 draw::draw_scene_with_text_resources(
47 frame,
48 width,
49 height,
50 &self.scene,
51 &self.text_resources,
52 );
53 }
54
55 pub fn draw_scaled(&self, frame: &mut [u8], width: u32, height: u32, scale: f32) {
58 let scale = if scale.is_finite() && scale > 0.0 {
59 scale
60 } else {
61 1.0
62 };
63 draw::draw_scene_scaled(
64 frame,
65 width,
66 height,
67 &self.scene,
68 &self.text_resources,
69 scale,
70 );
71 }
72}
73
74impl PixelsRenderer {
75 pub fn compose_sprites(
79 &self,
80 frame: &mut sprites::SpriteFrame,
81 width: u32,
82 height: u32,
83 scale: f32,
84 ) {
85 let scale = if scale.is_finite() && scale > 0.0 {
86 scale
87 } else {
88 1.0
89 };
90 let scene = match self.scene.graph.as_ref() {
91 Some(graph) => pipeline::build_raster_scene(graph, self.scene.diagnostics(), scale),
92 None => scene::RasterScene::new(),
93 };
94 frame.compose(
95 &scene,
96 width,
97 height,
98 self.scene.diagnostics(),
99 &self.text_resources,
100 );
101 }
102}
103
104impl Renderer for PixelsRenderer {
105 type Scene = Scene;
106 type Error = PixelsRendererError;
107
108 fn attach_app_context_services(&mut self, app_context: &cranpose_ui::AppContext) {
109 app_context.set_text_measurer(CachedFontTextMeasurer::with_text_resources(
110 self.text_resources.clone(),
111 64,
112 ));
113 self.app_context = Some(app_context.downgrade());
114 }
115
116 #[cfg(feature = "installed-fonts")]
117 fn apply_installed_fonts(&mut self, app_context: &cranpose_ui::AppContext) {
118 let Some(resources) = self.text_resources.with_installed_faces() else {
119 return;
120 };
121 self.text_resources = resources;
122 let attached = self
123 .app_context
124 .as_ref()
125 .and_then(std::rc::Weak::upgrade)
126 .is_some_and(|attached| std::ptr::eq(&*attached, app_context));
127 if attached {
128 self.attach_app_context_services(app_context);
129 }
130 }
131
132 fn scene(&self) -> &Self::Scene {
133 &self.scene
134 }
135
136 fn scene_mut(&mut self) -> &mut Self::Scene {
137 &mut self.scene
138 }
139
140 fn rebuild_scene(
141 &mut self,
142 layout_tree: &LayoutTree,
143 _viewport: Size,
144 ) -> Result<(), Self::Error> {
145 self.scene.clear();
146 pipeline::render_layout_tree(layout_tree.root(), &mut self.scene);
147 Ok(())
148 }
149
150 fn rebuild_scene_from_applier(
151 &mut self,
152 applier: &mut cranpose_core::MemoryApplier,
153 root: cranpose_core::NodeId,
154 _viewport: Size,
155 ) -> Result<(), Self::Error> {
156 self.scene.rebuild_from_applier(applier, root);
157 Ok(())
158 }
159
160 fn update_scene_from_applier(
161 &mut self,
162 applier: &mut cranpose_core::MemoryApplier,
163 root: cranpose_core::NodeId,
164 _viewport: Size,
165 updates: SceneUpdates<'_>,
166 ) -> Result<(), Self::Error> {
167 self.scene.update_from_applier(applier, root, updates, true);
168 Ok(())
169 }
170
171 fn update_visual_scene_from_applier(
172 &mut self,
173 applier: &mut cranpose_core::MemoryApplier,
174 root: cranpose_core::NodeId,
175 _viewport: Size,
176 updates: SceneUpdates<'_>,
177 ) -> Result<(), Self::Error> {
178 self.scene
179 .update_from_applier(applier, root, updates, false);
180 Ok(())
181 }
182}