1 | //! Module containing renderer implementations. |
2 | |
3 | use imgref::ImgVec; |
4 | use rgb::RGBA8; |
5 | |
6 | use crate::{ |
7 | geometry::Position, paint::GlyphTexture, Color, CompositeOperationState, ErrorKind, FillRule, ImageFilter, ImageId, |
8 | ImageInfo, ImageSource, ImageStore, |
9 | }; |
10 | |
11 | mod opengl; |
12 | pub use opengl::OpenGl; |
13 | |
14 | #[cfg (feature = "wgpu" )] |
15 | mod wgpu; |
16 | #[cfg (feature = "wgpu" )] |
17 | pub use wgpu::WGPURenderer; |
18 | |
19 | mod void; |
20 | pub use void::Void; |
21 | |
22 | mod params; |
23 | pub(crate) use params::Params; |
24 | |
25 | /// Represents a drawable object. |
26 | #[derive (Copy, Clone, Default, Debug)] |
27 | pub struct Drawable { |
28 | pub(crate) fill_verts: Option<(usize, usize)>, |
29 | pub(crate) stroke_verts: Option<(usize, usize)>, |
30 | } |
31 | |
32 | /// Defines different types of commands that can be executed by the renderer. |
33 | #[derive (Debug)] |
34 | pub enum CommandType { |
35 | /// Set the render target (screen or image). |
36 | SetRenderTarget(RenderTarget), |
37 | /// Clear a rectangle with the specified color. |
38 | ClearRect { |
39 | /// Color to fill the rectangle with. |
40 | color: Color, |
41 | }, |
42 | /// Fill a convex shape. |
43 | ConvexFill { |
44 | /// Rendering parameters for the fill operation. |
45 | params: Params, |
46 | }, |
47 | /// Fill a concave shape. |
48 | ConcaveFill { |
49 | /// Rendering parameters for the stencil operation. |
50 | stencil_params: Params, |
51 | /// Rendering parameters for the fill operation. |
52 | fill_params: Params, |
53 | }, |
54 | /// Stroke a shape. |
55 | Stroke { |
56 | /// Rendering parameters for the stroke operation. |
57 | params: Params, |
58 | }, |
59 | /// Stroke a shape using stencil. |
60 | StencilStroke { |
61 | /// Rendering parameters for the first stroke operation. |
62 | params1: Params, |
63 | /// Rendering parameters for the second stroke operation. |
64 | params2: Params, |
65 | }, |
66 | /// Render triangles. |
67 | Triangles { |
68 | /// Rendering parameters for the triangle operation. |
69 | params: Params, |
70 | }, |
71 | /// Render a filtered image. |
72 | RenderFilteredImage { |
73 | /// ID of the target image. |
74 | target_image: ImageId, |
75 | /// Image filter to apply. |
76 | filter: ImageFilter, |
77 | }, |
78 | } |
79 | |
80 | /// Represents a command that can be executed by the renderer. |
81 | #[derive (Debug)] |
82 | pub struct Command { |
83 | pub(crate) cmd_type: CommandType, |
84 | pub(crate) drawables: Vec<Drawable>, |
85 | pub(crate) triangles_verts: Option<(usize, usize)>, |
86 | pub(crate) image: Option<ImageId>, |
87 | pub(crate) glyph_texture: GlyphTexture, |
88 | pub(crate) fill_rule: FillRule, |
89 | pub(crate) composite_operation: CompositeOperationState, |
90 | } |
91 | |
92 | impl Command { |
93 | /// Creates a new command with the specified command type. |
94 | pub fn new(flavor: CommandType) -> Self { |
95 | Self { |
96 | cmd_type: flavor, |
97 | drawables: Vec::new(), |
98 | triangles_verts: None, |
99 | image: None, |
100 | glyph_texture: Default::default(), |
101 | fill_rule: Default::default(), |
102 | composite_operation: Default::default(), |
103 | } |
104 | } |
105 | } |
106 | |
107 | /// Represents different render targets (screen or image). |
108 | #[derive (Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] |
109 | pub enum RenderTarget { |
110 | /// Render to the screen. |
111 | Screen, |
112 | /// Render to a specific image. |
113 | Image(ImageId), |
114 | } |
115 | |
116 | /// The main renderer trait that the [Canvas](../struct.Canvas.html) draws to. |
117 | pub trait Renderer { |
118 | /// Associated image type. |
119 | type Image; |
120 | |
121 | /// Associated native texture type. |
122 | type NativeTexture; |
123 | |
124 | /// Associated surface type. |
125 | type Surface; |
126 | |
127 | /// Associated type to hold commands created via flush_to_surface. |
128 | type CommandBuffer; |
129 | |
130 | /// Set the size of the renderer. |
131 | fn set_size(&mut self, width: u32, height: u32, dpi: f32); |
132 | |
133 | /// Render the specified commands. |
134 | fn render( |
135 | &mut self, |
136 | surface: &Self::Surface, |
137 | images: &mut ImageStore<Self::Image>, |
138 | verts: &[Vertex], |
139 | commands: Vec<Command>, |
140 | ) -> Self::CommandBuffer; |
141 | |
142 | /// Allocate a new image with the specified image info. |
143 | fn alloc_image(&mut self, info: ImageInfo) -> Result<Self::Image, ErrorKind>; |
144 | |
145 | /// Create a new image from a native texture. |
146 | fn create_image_from_native_texture( |
147 | &mut self, |
148 | native_texture: Self::NativeTexture, |
149 | info: ImageInfo, |
150 | ) -> Result<Self::Image, ErrorKind>; |
151 | |
152 | /// Update an image with new data. |
153 | fn update_image(&mut self, image: &mut Self::Image, data: ImageSource, x: usize, y: usize) |
154 | -> Result<(), ErrorKind>; |
155 | |
156 | /// Get the native texture associated with an image (default implementation returns an error). |
157 | #[allow (unused_variables)] |
158 | fn get_native_texture(&self, image: &Self::Image) -> Result<Self::NativeTexture, ErrorKind> { |
159 | Err(ErrorKind::UnsupportedImageFormat) |
160 | } |
161 | |
162 | /// Delete an image. |
163 | fn delete_image(&mut self, image: Self::Image, image_id: ImageId); |
164 | |
165 | /// Take a screenshot of the current render target. |
166 | fn screenshot(&mut self) -> Result<ImgVec<RGBA8>, ErrorKind>; |
167 | } |
168 | |
169 | /// Marker trait for renderers that don't have a surface. |
170 | pub trait SurfacelessRenderer: Renderer { |
171 | /// Render the specified commands. |
172 | fn render_surfaceless(&mut self, images: &mut ImageStore<Self::Image>, verts: &[Vertex], commands: Vec<Command>); |
173 | } |
174 | |
175 | use bytemuck::{Pod, Zeroable}; |
176 | |
177 | /// Vertex struct for specifying triangle geometry. |
178 | #[derive (Copy, Clone, Debug, PartialEq, PartialOrd, Default, Pod, Zeroable)] |
179 | #[repr (C)] |
180 | pub struct Vertex { |
181 | /// X-coordinate of the vertex. |
182 | pub x: f32, |
183 | /// Y-coordinate of the vertex. |
184 | pub y: f32, |
185 | /// U-coordinate of the vertex (for texture mapping). |
186 | pub u: f32, |
187 | /// V-coordinate of the vertex (for texture mapping). |
188 | pub v: f32, |
189 | } |
190 | |
191 | impl Vertex { |
192 | pub(crate) fn pos(position: Position, u: f32, v: f32) -> Self { |
193 | let Position { x: f32, y: f32 } = position; |
194 | Self { x, y, u, v } |
195 | } |
196 | |
197 | /// Create a new vertex with the specified coordinates. |
198 | pub fn new(x: f32, y: f32, u: f32, v: f32) -> Self { |
199 | Self { x, y, u, v } |
200 | } |
201 | |
202 | /// Set the coordinates of the vertex. |
203 | pub fn set(&mut self, x: f32, y: f32, u: f32, v: f32) { |
204 | *self = Self { x, y, u, v }; |
205 | } |
206 | } |
207 | |
208 | /// Represents different types of shaders used by the renderer. |
209 | /// |
210 | /// The default value is `FillGradient`. |
211 | #[derive (Copy, Clone, Debug, Eq, PartialEq, Hash, Default)] |
212 | pub enum ShaderType { |
213 | /// Fill gradient shader. |
214 | #[default] |
215 | FillGradient, |
216 | /// Fill image shader. |
217 | FillImage, |
218 | /// Stencil shader. |
219 | Stencil, |
220 | /// Fill image gradient shader. |
221 | FillImageGradient, |
222 | /// Filter image shader. |
223 | FilterImage, |
224 | /// Fill color shader. |
225 | FillColor, |
226 | /// Texture copy unclipped shader. |
227 | TextureCopyUnclipped, |
228 | /// Fill color shader without clipping, used for clear_rect() |
229 | FillColorUnclipped, |
230 | } |
231 | |
232 | impl ShaderType { |
233 | /// Convert the shader type to a u8 value. |
234 | pub fn to_u8(self) -> u8 { |
235 | match self { |
236 | Self::FillGradient => 0, |
237 | Self::FillImage => 1, |
238 | Self::Stencil => 2, |
239 | Self::FillImageGradient => 3, |
240 | Self::FilterImage => 4, |
241 | Self::FillColor => 5, |
242 | Self::TextureCopyUnclipped => 6, |
243 | Self::FillColorUnclipped => 7, |
244 | } |
245 | } |
246 | |
247 | /// Convert the shader type to a f32 value. |
248 | pub fn to_f32(self) -> f32 { |
249 | self.to_u8() as f32 |
250 | } |
251 | } |
252 | |