From 5fd5d1cdf8e5354788dc40729c4565ef377d3bba Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 1 Mar 2023 21:34:26 +0100 Subject: Implement `Canvas` support for `iced_tiny_skia` --- wgpu/src/layer.rs | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 wgpu/src/layer.rs (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs new file mode 100644 index 00000000..0840555a --- /dev/null +++ b/wgpu/src/layer.rs @@ -0,0 +1,274 @@ +//! Organize rendering primitives into a flattened list of layers. +mod image; +mod quad; +mod text; + +pub mod mesh; + +pub use image::Image; +pub use mesh::Mesh; +pub use quad::Quad; +pub use text::Text; + +use crate::Primitive; + +use iced_graphics::alignment; +use iced_graphics::{ + Background, Color, Font, Point, Rectangle, Size, Vector, Viewport, +}; + +/// A group of primitives that should be clipped together. +#[derive(Debug)] +pub struct Layer<'a> { + /// The clipping bounds of the [`Layer`]. + pub bounds: Rectangle, + + /// The quads of the [`Layer`]. + pub quads: Vec, + + /// The triangle meshes of the [`Layer`]. + pub meshes: Vec>, + + /// The text of the [`Layer`]. + pub text: Vec>, + + /// The images of the [`Layer`]. + pub images: Vec, +} + +impl<'a> Layer<'a> { + /// Creates a new [`Layer`] with the given clipping bounds. + pub fn new(bounds: Rectangle) -> Self { + Self { + bounds, + quads: Vec::new(), + meshes: Vec::new(), + text: Vec::new(), + images: Vec::new(), + } + } + + /// Creates a new [`Layer`] for the provided overlay text. + /// + /// This can be useful for displaying debug information. + pub fn overlay(lines: &'a [impl AsRef], viewport: &Viewport) -> Self { + let mut overlay = + Layer::new(Rectangle::with_size(viewport.logical_size())); + + for (i, line) in lines.iter().enumerate() { + let text = Text { + content: line.as_ref(), + bounds: Rectangle::new( + Point::new(11.0, 11.0 + 25.0 * i as f32), + Size::INFINITY, + ), + color: Color::new(0.9, 0.9, 0.9, 1.0), + size: 20.0, + font: Font::Monospace, + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + }; + + overlay.text.push(text); + + overlay.text.push(Text { + bounds: text.bounds + Vector::new(-1.0, -1.0), + color: Color::BLACK, + ..text + }); + } + + overlay + } + + /// Distributes the given [`Primitive`] and generates a list of layers based + /// on its contents. + pub fn generate( + primitives: &'a [Primitive], + viewport: &Viewport, + ) -> Vec { + let first_layer = + Layer::new(Rectangle::with_size(viewport.logical_size())); + + let mut layers = vec![first_layer]; + + for primitive in primitives { + Self::process_primitive( + &mut layers, + Vector::new(0.0, 0.0), + primitive, + 0, + ); + } + + layers + } + + fn process_primitive( + layers: &mut Vec, + translation: Vector, + primitive: &'a Primitive, + current_layer: usize, + ) { + match primitive { + Primitive::Text { + content, + bounds, + size, + color, + font, + horizontal_alignment, + vertical_alignment, + } => { + let layer = &mut layers[current_layer]; + + layer.text.push(Text { + content, + bounds: *bounds + translation, + size: *size, + color: *color, + font: *font, + horizontal_alignment: *horizontal_alignment, + vertical_alignment: *vertical_alignment, + }); + } + Primitive::Quad { + bounds, + background, + border_radius, + border_width, + border_color, + } => { + let layer = &mut layers[current_layer]; + + // TODO: Move some of these computations to the GPU (?) + layer.quads.push(Quad { + position: [ + bounds.x + translation.x, + bounds.y + translation.y, + ], + size: [bounds.width, bounds.height], + color: match background { + Background::Color(color) => color.into_linear(), + }, + border_radius: *border_radius, + border_width: *border_width, + border_color: border_color.into_linear(), + }); + } + Primitive::Image { handle, bounds } => { + let layer = &mut layers[current_layer]; + + layer.images.push(Image::Raster { + handle: handle.clone(), + bounds: *bounds + translation, + }); + } + Primitive::Svg { + handle, + color, + bounds, + } => { + let layer = &mut layers[current_layer]; + + layer.images.push(Image::Vector { + handle: handle.clone(), + color: *color, + bounds: *bounds + translation, + }); + } + Primitive::SolidMesh { buffers, size } => { + let layer = &mut layers[current_layer]; + + let bounds = Rectangle::new( + Point::new(translation.x, translation.y), + *size, + ); + + // Only draw visible content + if let Some(clip_bounds) = layer.bounds.intersection(&bounds) { + layer.meshes.push(Mesh::Solid { + origin: Point::new(translation.x, translation.y), + buffers, + clip_bounds, + }); + } + } + Primitive::GradientMesh { + buffers, + size, + gradient, + } => { + let layer = &mut layers[current_layer]; + + let bounds = Rectangle::new( + Point::new(translation.x, translation.y), + *size, + ); + + // Only draw visible content + if let Some(clip_bounds) = layer.bounds.intersection(&bounds) { + layer.meshes.push(Mesh::Gradient { + origin: Point::new(translation.x, translation.y), + buffers, + clip_bounds, + gradient, + }); + } + } + Primitive::Group { primitives } => { + // TODO: Inspect a bit and regroup (?) + for primitive in primitives { + Self::process_primitive( + layers, + translation, + primitive, + current_layer, + ) + } + } + Primitive::Clip { bounds, content } => { + let layer = &mut layers[current_layer]; + let translated_bounds = *bounds + translation; + + // Only draw visible content + if let Some(clip_bounds) = + layer.bounds.intersection(&translated_bounds) + { + let clip_layer = Layer::new(clip_bounds); + layers.push(clip_layer); + + Self::process_primitive( + layers, + translation, + content, + layers.len() - 1, + ); + } + } + Primitive::Translate { + translation: new_translation, + content, + } => { + Self::process_primitive( + layers, + translation + *new_translation, + content, + current_layer, + ); + } + Primitive::Cache { content } => { + Self::process_primitive( + layers, + translation, + content, + current_layer, + ); + } + Primitive::Fill { .. } | Primitive::Stroke { .. } => { + // Unsupported! + // TODO: Draw a placeholder (?) + } + } + } +} -- cgit From bbeaf10c04a922af5c1c3b898f0c4301d23feab0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 3 Mar 2023 03:55:07 +0100 Subject: Mark `Primitive` as `non-exhaustive` in `iced_graphics` --- wgpu/src/layer.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 0840555a..69fcf899 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -265,9 +265,8 @@ impl<'a> Layer<'a> { current_layer, ); } - Primitive::Fill { .. } | Primitive::Stroke { .. } => { + _ => { // Unsupported! - // TODO: Draw a placeholder (?) } } } -- cgit From 3a0d34c0240f4421737a6a08761f99d6f8140d02 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 4 Mar 2023 05:37:11 +0100 Subject: Create `iced_widget` subcrate and re-organize the whole codebase --- wgpu/src/layer.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 69fcf899..cb9d5e2f 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -10,12 +10,9 @@ pub use mesh::Mesh; pub use quad::Quad; pub use text::Text; -use crate::Primitive; - -use iced_graphics::alignment; -use iced_graphics::{ - Background, Color, Font, Point, Rectangle, Size, Vector, Viewport, -}; +use crate::core::alignment; +use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector}; +use crate::graphics::{Primitive, Viewport}; /// A group of primitives that should be clipped together. #[derive(Debug)] -- cgit From 707de9d788dc3c49d4ac57a19afac1bb938b78d9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 30 Mar 2023 00:56:00 +0200 Subject: Introduce support for `Font` attributes --- wgpu/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index cb9d5e2f..c4723397 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -61,7 +61,7 @@ impl<'a> Layer<'a> { ), color: Color::new(0.9, 0.9, 0.9, 1.0), size: 20.0, - font: Font::Monospace, + font: Font::MONOSPACE, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, }; -- cgit From 33b5a900197e2798a393d6d9a0834039666eddbb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 19 Apr 2023 01:19:56 +0200 Subject: Make basic text shaping the default shaping strategy --- wgpu/src/layer.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index c4723397..7c5b43a3 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -64,6 +64,7 @@ impl<'a> Layer<'a> { font: Font::MONOSPACE, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, + advanced_shape: false, }; overlay.text.push(text); @@ -116,6 +117,7 @@ impl<'a> Layer<'a> { font, horizontal_alignment, vertical_alignment, + advanced_shape, } => { let layer = &mut layers[current_layer]; @@ -127,6 +129,7 @@ impl<'a> Layer<'a> { font: *font, horizontal_alignment: *horizontal_alignment, vertical_alignment: *vertical_alignment, + advanced_shape: *advanced_shape, }); } Primitive::Quad { -- cgit From 4bd290afe7d81d9aaf7467b3ce91491f6600261a Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 19 Apr 2023 02:00:45 +0200 Subject: Introduce `text::Shaping` enum and replace magic boolean --- wgpu/src/layer.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 7c5b43a3..b9fd044e 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -10,6 +10,7 @@ pub use mesh::Mesh; pub use quad::Quad; pub use text::Text; +use crate::core; use crate::core::alignment; use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector}; use crate::graphics::{Primitive, Viewport}; @@ -64,7 +65,7 @@ impl<'a> Layer<'a> { font: Font::MONOSPACE, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, - advanced_shape: false, + shaping: core::text::Shaping::Basic, }; overlay.text.push(text); @@ -117,7 +118,7 @@ impl<'a> Layer<'a> { font, horizontal_alignment, vertical_alignment, - advanced_shape, + shaping, } => { let layer = &mut layers[current_layer]; @@ -129,7 +130,7 @@ impl<'a> Layer<'a> { font: *font, horizontal_alignment: *horizontal_alignment, vertical_alignment: *vertical_alignment, - advanced_shape: *advanced_shape, + shaping: *shaping, }); } Primitive::Quad { -- cgit From 9499a8f9e6f9971dedfae563cb133232aa3cebc2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 4 May 2023 13:00:16 +0200 Subject: Support configurable `LineHeight` in text widgets --- wgpu/src/layer.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index b9fd044e..dcae0648 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -62,6 +62,7 @@ impl<'a> Layer<'a> { ), color: Color::new(0.9, 0.9, 0.9, 1.0), size: 20.0, + line_height: core::text::LineHeight::Relative(1.2), font: Font::MONOSPACE, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, @@ -114,6 +115,7 @@ impl<'a> Layer<'a> { content, bounds, size, + line_height, color, font, horizontal_alignment, @@ -126,6 +128,7 @@ impl<'a> Layer<'a> { content, bounds: *bounds + translation, size: *size, + line_height: *line_height, color: *color, font: *font, horizontal_alignment: *horizontal_alignment, -- cgit From c189ef62a6a5dd183b8098496ac31d30f7814ff3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 8 May 2023 14:46:56 +0200 Subject: Use `LineHeight::default` in `iced_wgpu::layer` --- wgpu/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index dcae0648..ab66264c 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -62,7 +62,7 @@ impl<'a> Layer<'a> { ), color: Color::new(0.9, 0.9, 0.9, 1.0), size: 20.0, - line_height: core::text::LineHeight::Relative(1.2), + line_height: core::text::LineHeight::default(), font: Font::MONOSPACE, horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, -- cgit From 91ef07e6ebe56e46ea235f6657b17a3a078ddf5b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 8 May 2023 14:51:53 +0200 Subject: Warn about unsupported primitives in `iced_wgpu` --- wgpu/src/layer.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index ab66264c..8af72b9d 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -270,7 +270,11 @@ impl<'a> Layer<'a> { ); } _ => { - // Unsupported! + // Not supported! + log::warn!( + "Unsupported primitive in `iced_wgpu`: {:?}", + primitive + ); } } } -- cgit From 6551a0b2ab6c831dd1d3646ecf55180339275e22 Mon Sep 17 00:00:00 2001 From: Bingus Date: Thu, 11 May 2023 09:12:06 -0700 Subject: Added support for gradients as background variants + other optimizations. --- wgpu/src/layer.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 17 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 8af72b9d..b3ee4739 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -1,13 +1,13 @@ //! Organize rendering primitives into a flattened list of layers. mod image; -mod quad; mod text; pub mod mesh; +pub mod quad; pub use image::Image; pub use mesh::Mesh; -pub use quad::Quad; +use quad::Quad; pub use text::Text; use crate::core; @@ -22,7 +22,7 @@ pub struct Layer<'a> { pub bounds: Rectangle, /// The quads of the [`Layer`]. - pub quads: Vec, + pub quads: Quads, /// The triangle meshes of the [`Layer`]. pub meshes: Vec>, @@ -34,12 +34,29 @@ pub struct Layer<'a> { pub images: Vec, } +/// The quads of the [`Layer`]. +#[derive(Default, Debug)] +pub struct Quads { + /// The solid quads of the [`Layer`]. + pub solids: Vec, + + /// The gradient quads of the [`Layer`]. + pub gradients: Vec, +} + +impl Quads { + /// Returns true if there are no quads of any type in [`Quads`]. + pub fn is_empty(&self) -> bool { + self.solids.is_empty() && self.gradients.is_empty() + } +} + impl<'a> Layer<'a> { /// Creates a new [`Layer`] with the given clipping bounds. pub fn new(bounds: Rectangle) -> Self { Self { bounds, - quads: Vec::new(), + quads: Quads::default(), meshes: Vec::new(), text: Vec::new(), images: Vec::new(), @@ -145,20 +162,39 @@ impl<'a> Layer<'a> { } => { let layer = &mut layers[current_layer]; - // TODO: Move some of these computations to the GPU (?) - layer.quads.push(Quad { + let quad = Quad { position: [ bounds.x + translation.x, bounds.y + translation.y, ], size: [bounds.width, bounds.height], - color: match background { - Background::Color(color) => color.into_linear(), - }, + border_color: border_color.into_linear(), border_radius: *border_radius, border_width: *border_width, - border_color: border_color.into_linear(), - }); + }; + + match background { + Background::Color(color) => { + layer.quads.solids.push(quad::Solid { + color: color.into_linear(), + quad, + }); + } + Background::Gradient(gradient) => { + let quad = quad::Gradient { + gradient: pack_gradient( + gradient, + Rectangle::new( + quad.position.into(), + quad.size.into(), + ), + ), + quad, + }; + + layer.quads.gradients.push(quad); + } + }; } Primitive::Image { handle, bounds } => { let layer = &mut layers[current_layer]; @@ -198,11 +234,7 @@ impl<'a> Layer<'a> { }); } } - Primitive::GradientMesh { - buffers, - size, - gradient, - } => { + Primitive::GradientMesh { buffers, size } => { let layer = &mut layers[current_layer]; let bounds = Rectangle::new( @@ -216,7 +248,6 @@ impl<'a> Layer<'a> { origin: Point::new(translation.x, translation.y), buffers, clip_bounds, - gradient, }); } } @@ -279,3 +310,32 @@ impl<'a> Layer<'a> { } } } + +/// Packs the [`Gradient`] for use in shader code. +fn pack_gradient(gradient: &core::Gradient, bounds: Rectangle) -> [f32; 44] { + match gradient { + core::Gradient::Linear(linear) => { + let mut pack: [f32; 44] = [0.0; 44]; + + for (index, stop) in linear.color_stops.iter().enumerate() { + let [r, g, b, a] = + stop.map_or(Color::default(), |s| s.color).into_linear(); + + pack[index * 4] = r; + pack[(index * 4) + 1] = g; + pack[(index * 4) + 2] = b; + pack[(index * 4) + 3] = a; + pack[32 + index] = stop.map_or(2.0, |s| s.offset); + } + + let (start, end) = linear.angle.to_distance(&bounds); + + pack[40] = start.x; + pack[41] = start.y; + pack[42] = end.x; + pack[43] = end.y; + + pack + } + } +} -- cgit From 4c1a082f0468a59099bbf8aa8991420a41234948 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 19 May 2023 03:32:21 +0200 Subject: Remove `Builder` abstractions for gradients --- wgpu/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index b3ee4739..08c0004a 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -317,7 +317,7 @@ fn pack_gradient(gradient: &core::Gradient, bounds: Rectangle) -> [f32; 44] { core::Gradient::Linear(linear) => { let mut pack: [f32; 44] = [0.0; 44]; - for (index, stop) in linear.color_stops.iter().enumerate() { + for (index, stop) in linear.stops.iter().enumerate() { let [r, g, b, a] = stop.map_or(Color::default(), |s| s.color).into_linear(); -- cgit From c888d0679bcaca13cd0dd5963e65449fef69ec01 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 19 May 2023 04:04:16 +0200 Subject: Fix inconsistent `pub use` in `wgpu::layer` --- wgpu/src/layer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 08c0004a..980d807b 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -7,7 +7,7 @@ pub mod quad; pub use image::Image; pub use mesh::Mesh; -use quad::Quad; +pub use quad::Quad; pub use text::Text; use crate::core; -- cgit From 902e333148a1ceed85aba36262a849aaed8d3ac9 Mon Sep 17 00:00:00 2001 From: Bingus Date: Fri, 26 May 2023 10:07:52 -0700 Subject: Changed gradient::Packed to be `repr(C)` for direct gpu upload. --- wgpu/src/layer.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 980d807b..9d7f9f2a 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -13,6 +13,7 @@ pub use text::Text; use crate::core; use crate::core::alignment; use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector}; +use crate::graphics::gradient; use crate::graphics::{Primitive, Viewport}; /// A group of primitives that should be clipped together. @@ -312,30 +313,33 @@ impl<'a> Layer<'a> { } /// Packs the [`Gradient`] for use in shader code. -fn pack_gradient(gradient: &core::Gradient, bounds: Rectangle) -> [f32; 44] { +fn pack_gradient( + gradient: &core::Gradient, + bounds: Rectangle, +) -> gradient::Packed { match gradient { core::Gradient::Linear(linear) => { - let mut pack: [f32; 44] = [0.0; 44]; + let mut data: [f32; 44] = [0.0; 44]; for (index, stop) in linear.stops.iter().enumerate() { let [r, g, b, a] = stop.map_or(Color::default(), |s| s.color).into_linear(); - pack[index * 4] = r; - pack[(index * 4) + 1] = g; - pack[(index * 4) + 2] = b; - pack[(index * 4) + 3] = a; - pack[32 + index] = stop.map_or(2.0, |s| s.offset); + data[index * 4] = r; + data[(index * 4) + 1] = g; + data[(index * 4) + 2] = b; + data[(index * 4) + 3] = a; + data[32 + index] = stop.map_or(2.0, |s| s.offset); } let (start, end) = linear.angle.to_distance(&bounds); - pack[40] = start.x; - pack[41] = start.y; - pack[42] = end.x; - pack[43] = end.y; + data[40] = start.x; + data[41] = start.y; + data[42] = end.x; + data[43] = end.y; - pack + data.into() } } } -- cgit From 8ca7b884c0695e4e7a031ea1359ee733bdcaa8a4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 29 May 2023 20:56:51 +0200 Subject: Make `Packed` fully opaque ... by only allowing direct conversion from our `Gradient` types --- wgpu/src/layer.rs | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 9d7f9f2a..bf5c4c0a 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -183,7 +183,7 @@ impl<'a> Layer<'a> { } Background::Gradient(gradient) => { let quad = quad::Gradient { - gradient: pack_gradient( + gradient: gradient::pack( gradient, Rectangle::new( quad.position.into(), @@ -311,35 +311,3 @@ impl<'a> Layer<'a> { } } } - -/// Packs the [`Gradient`] for use in shader code. -fn pack_gradient( - gradient: &core::Gradient, - bounds: Rectangle, -) -> gradient::Packed { - match gradient { - core::Gradient::Linear(linear) => { - let mut data: [f32; 44] = [0.0; 44]; - - for (index, stop) in linear.stops.iter().enumerate() { - let [r, g, b, a] = - stop.map_or(Color::default(), |s| s.color).into_linear(); - - data[index * 4] = r; - data[(index * 4) + 1] = g; - data[(index * 4) + 2] = b; - data[(index * 4) + 3] = a; - data[32 + index] = stop.map_or(2.0, |s| s.offset); - } - - let (start, end) = linear.angle.to_distance(&bounds); - - data[40] = start.x; - data[41] = start.y; - data[42] = end.x; - data[43] = end.y; - - data.into() - } - } -} -- cgit From 3f141459a66fe66e6dc25d579d0cda80662f0895 Mon Sep 17 00:00:00 2001 From: Bingus Date: Thu, 25 May 2023 10:27:27 -0700 Subject: Fixed issue where quads of different types were not ordered. --- wgpu/src/layer.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index bf5c4c0a..f5c4b576 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -43,6 +43,12 @@ pub struct Quads { /// The gradient quads of the [`Layer`]. pub gradients: Vec, + + /// The quad order of the [`Layer`]; stored as a tuple of the quad type & its count. + pub order: Vec<(quad::Order, usize)>, + + // The last index of quad ordering. + index: usize, } impl Quads { @@ -174,12 +180,13 @@ impl<'a> Layer<'a> { border_width: *border_width, }; - match background { + let quad_order = match background { Background::Color(color) => { layer.quads.solids.push(quad::Solid { color: color.into_linear(), quad, }); + quad::Order::Solid } Background::Gradient(gradient) => { let quad = quad::Gradient { @@ -194,8 +201,41 @@ impl<'a> Layer<'a> { }; layer.quads.gradients.push(quad); + quad::Order::Gradient } }; + + match (layer.quads.order.get_mut(layer.quads.index), quad_order) + { + (Some((quad_order, count)), quad::Order::Solid) => { + match quad_order { + quad::Order::Solid => { + *count += 1; + } + quad::Order::Gradient => { + layer.quads.order.push((quad::Order::Solid, 1)); + layer.quads.index += 1; + } + } + } + (Some((quad_order, count)), quad::Order::Gradient) => { + match quad_order { + quad::Order::Solid => { + layer + .quads + .order + .push((quad::Order::Gradient, 1)); + layer.quads.index += 1; + } + quad::Order::Gradient => { + *count += 1; + } + } + } + (None, _) => { + layer.quads.order.push((quad_order, 1)); + } + } } Primitive::Image { handle, bounds } => { let layer = &mut layers[current_layer]; -- cgit From eb6c663420a28e087c91c39e376db3c294b5aea1 Mon Sep 17 00:00:00 2001 From: Bingus Date: Fri, 26 May 2023 09:55:49 -0700 Subject: Adjusted `Quads` struct to be opaque `quad::Layer`. --- wgpu/src/layer.rs | 87 +++---------------------------------------------------- 1 file changed, 4 insertions(+), 83 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index f5c4b576..4e028eac 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -12,8 +12,7 @@ pub use text::Text; use crate::core; use crate::core::alignment; -use crate::core::{Background, Color, Font, Point, Rectangle, Size, Vector}; -use crate::graphics::gradient; +use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; use crate::graphics::{Primitive, Viewport}; /// A group of primitives that should be clipped together. @@ -23,7 +22,7 @@ pub struct Layer<'a> { pub bounds: Rectangle, /// The quads of the [`Layer`]. - pub quads: Quads, + pub quads: quad::Layer, /// The triangle meshes of the [`Layer`]. pub meshes: Vec>, @@ -35,35 +34,12 @@ pub struct Layer<'a> { pub images: Vec, } -/// The quads of the [`Layer`]. -#[derive(Default, Debug)] -pub struct Quads { - /// The solid quads of the [`Layer`]. - pub solids: Vec, - - /// The gradient quads of the [`Layer`]. - pub gradients: Vec, - - /// The quad order of the [`Layer`]; stored as a tuple of the quad type & its count. - pub order: Vec<(quad::Order, usize)>, - - // The last index of quad ordering. - index: usize, -} - -impl Quads { - /// Returns true if there are no quads of any type in [`Quads`]. - pub fn is_empty(&self) -> bool { - self.solids.is_empty() && self.gradients.is_empty() - } -} - impl<'a> Layer<'a> { /// Creates a new [`Layer`] with the given clipping bounds. pub fn new(bounds: Rectangle) -> Self { Self { bounds, - quads: Quads::default(), + quads: quad::Layer::default(), meshes: Vec::new(), text: Vec::new(), images: Vec::new(), @@ -180,62 +156,7 @@ impl<'a> Layer<'a> { border_width: *border_width, }; - let quad_order = match background { - Background::Color(color) => { - layer.quads.solids.push(quad::Solid { - color: color.into_linear(), - quad, - }); - quad::Order::Solid - } - Background::Gradient(gradient) => { - let quad = quad::Gradient { - gradient: gradient::pack( - gradient, - Rectangle::new( - quad.position.into(), - quad.size.into(), - ), - ), - quad, - }; - - layer.quads.gradients.push(quad); - quad::Order::Gradient - } - }; - - match (layer.quads.order.get_mut(layer.quads.index), quad_order) - { - (Some((quad_order, count)), quad::Order::Solid) => { - match quad_order { - quad::Order::Solid => { - *count += 1; - } - quad::Order::Gradient => { - layer.quads.order.push((quad::Order::Solid, 1)); - layer.quads.index += 1; - } - } - } - (Some((quad_order, count)), quad::Order::Gradient) => { - match quad_order { - quad::Order::Solid => { - layer - .quads - .order - .push((quad::Order::Gradient, 1)); - layer.quads.index += 1; - } - quad::Order::Gradient => { - *count += 1; - } - } - } - (None, _) => { - layer.quads.order.push((quad_order, 1)); - } - } + layer.quads.add(quad, background); } Primitive::Image { handle, bounds } => { let layer = &mut layers[current_layer]; -- cgit From fe9da174cafffbd77eb351c51ba017cf039a4cf4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 30 May 2023 00:56:52 +0200 Subject: Move `layer::quad` types to `quad` module Not sure why I split these to begin with! --- wgpu/src/layer.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 4e028eac..1a870c15 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -3,17 +3,16 @@ mod image; mod text; pub mod mesh; -pub mod quad; pub use image::Image; pub use mesh::Mesh; -pub use quad::Quad; pub use text::Text; use crate::core; use crate::core::alignment; use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; use crate::graphics::{Primitive, Viewport}; +use crate::quad::{self, Quad}; /// A group of primitives that should be clipped together. #[derive(Debug)] @@ -22,7 +21,7 @@ pub struct Layer<'a> { pub bounds: Rectangle, /// The quads of the [`Layer`]. - pub quads: quad::Layer, + pub quads: quad::Batch, /// The triangle meshes of the [`Layer`]. pub meshes: Vec>, @@ -39,7 +38,7 @@ impl<'a> Layer<'a> { pub fn new(bounds: Rectangle) -> Self { Self { bounds, - quads: quad::Layer::default(), + quads: quad::Batch::default(), meshes: Vec::new(), text: Vec::new(), images: Vec::new(), -- cgit From faa7627ea41b1ce372bae7f0d2ae36e9b15a97a3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 31 May 2023 21:31:58 +0200 Subject: Introduce `web-colors` feature flag to enable sRGB linear blending This is how browsers perform color management. They treat gamma-corrected sRGB colors as if they were linear RGB. Correctness aside, this mode is introduced for legacy reasons. Most UI/UX tooling uses this color management as well, and many have created an intuition about how color should behave from interacting with a browser. This feature flag should facilitate application development with `iced` in those cases. More details: https://webcolorisstillbroken.com/ --- wgpu/src/layer.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 1a870c15..71570e3d 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -11,6 +11,7 @@ pub use text::Text; use crate::core; use crate::core::alignment; use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; +use crate::graphics::color; use crate::graphics::{Primitive, Viewport}; use crate::quad::{self, Quad}; @@ -150,7 +151,7 @@ impl<'a> Layer<'a> { bounds.y + translation.y, ], size: [bounds.width, bounds.height], - border_color: border_color.into_linear(), + border_color: color::pack(*border_color), border_radius: *border_radius, border_width: *border_width, }; -- cgit From 0ae1baa37bd7b6607f79b33b8a6d8c5daafde0b2 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 22 Jun 2023 00:38:36 +0200 Subject: Introduce custom backend-specific primitives --- wgpu/src/layer.rs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 71570e3d..ef850cd9 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -12,8 +12,9 @@ use crate::core; use crate::core::alignment; use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; use crate::graphics::color; -use crate::graphics::{Primitive, Viewport}; +use crate::graphics::Viewport; use crate::quad::{self, Quad}; +use crate::Primitive; /// A group of primitives that should be clipped together. #[derive(Debug)] @@ -262,13 +263,7 @@ impl<'a> Layer<'a> { current_layer, ); } - _ => { - // Not supported! - log::warn!( - "Unsupported primitive in `iced_wgpu`: {:?}", - primitive - ); - } + Primitive::Custom(()) => {} } } } -- cgit From fa5650cfd1115e6ccec2ad795cf58fd970d5b43c Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 29 Jun 2023 07:48:03 +0200 Subject: Decouple `Mesh` primitives from main `Primitive` type --- wgpu/src/layer.rs | 86 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 36 deletions(-) (limited to 'wgpu/src/layer.rs') diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index ef850cd9..b8f32db1 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -11,10 +11,11 @@ pub use text::Text; use crate::core; use crate::core::alignment; use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; +use crate::graphics; use crate::graphics::color; use crate::graphics::Viewport; +use crate::primitive::{self, Primitive}; use crate::quad::{self, Quad}; -use crate::Primitive; /// A group of primitives that should be clipped together. #[derive(Debug)] @@ -180,40 +181,6 @@ impl<'a> Layer<'a> { bounds: *bounds + translation, }); } - Primitive::SolidMesh { buffers, size } => { - let layer = &mut layers[current_layer]; - - let bounds = Rectangle::new( - Point::new(translation.x, translation.y), - *size, - ); - - // Only draw visible content - if let Some(clip_bounds) = layer.bounds.intersection(&bounds) { - layer.meshes.push(Mesh::Solid { - origin: Point::new(translation.x, translation.y), - buffers, - clip_bounds, - }); - } - } - Primitive::GradientMesh { buffers, size } => { - let layer = &mut layers[current_layer]; - - let bounds = Rectangle::new( - Point::new(translation.x, translation.y), - *size, - ); - - // Only draw visible content - if let Some(clip_bounds) = layer.bounds.intersection(&bounds) { - layer.meshes.push(Mesh::Gradient { - origin: Point::new(translation.x, translation.y), - buffers, - clip_bounds, - }); - } - } Primitive::Group { primitives } => { // TODO: Inspect a bit and regroup (?) for primitive in primitives { @@ -263,7 +230,54 @@ impl<'a> Layer<'a> { current_layer, ); } - Primitive::Custom(()) => {} + Primitive::Custom(custom) => match custom { + primitive::Custom::Mesh(mesh) => match mesh { + graphics::Mesh::Solid { buffers, size } => { + let layer = &mut layers[current_layer]; + + let bounds = Rectangle::new( + Point::new(translation.x, translation.y), + *size, + ); + + // Only draw visible content + if let Some(clip_bounds) = + layer.bounds.intersection(&bounds) + { + layer.meshes.push(Mesh::Solid { + origin: Point::new( + translation.x, + translation.y, + ), + buffers, + clip_bounds, + }); + } + } + graphics::Mesh::Gradient { buffers, size } => { + let layer = &mut layers[current_layer]; + + let bounds = Rectangle::new( + Point::new(translation.x, translation.y), + *size, + ); + + // Only draw visible content + if let Some(clip_bounds) = + layer.bounds.intersection(&bounds) + { + layer.meshes.push(Mesh::Gradient { + origin: Point::new( + translation.x, + translation.y, + ), + buffers, + clip_bounds, + }); + } + } + }, + }, } } } -- cgit