| 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 | |