diff options
author | 2020-05-19 22:55:12 +0200 | |
---|---|---|
committer | 2020-05-19 23:19:39 +0200 | |
commit | 720e7756f2afe30706b6b1a7fbde86b9f15e1d8c (patch) | |
tree | 3a55248a4b25654b1d63b8c547fd0f653471606d /graphics | |
parent | e6180912488db4d59fbffcb46c5930282306cb92 (diff) | |
download | iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.gz iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.bz2 iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.zip |
Move `Layer` to `iced_graphics`
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/src/layer.rs | 266 | ||||
-rw-r--r-- | graphics/src/lib.rs | 7 | ||||
-rw-r--r-- | graphics/src/primitive.rs | 6 | ||||
-rw-r--r-- | graphics/src/triangle.rs | 1 | ||||
-rw-r--r-- | graphics/src/widget.rs | 4 | ||||
-rw-r--r-- | graphics/src/widget/canvas/frame.rs | 2 | ||||
-rw-r--r-- | graphics/src/widget/image.rs | 2 | ||||
-rw-r--r-- | graphics/src/widget/svg.rs | 2 |
8 files changed, 282 insertions, 8 deletions
diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs new file mode 100644 index 00000000..ae9c6ce0 --- /dev/null +++ b/graphics/src/layer.rs @@ -0,0 +1,266 @@ +use crate::image; +use crate::svg; +use crate::triangle; +use crate::{ + Background, Font, HorizontalAlignment, Point, Primitive, Rectangle, Size, + Vector, VerticalAlignment, Viewport, +}; + +pub struct Layer<'a> { + pub bounds: Rectangle<u32>, + pub quads: Vec<Quad>, + pub meshes: Vec<Mesh<'a>>, + pub text: Vec<Text<'a>>, + pub images: Vec<Image>, +} + +impl<'a> Layer<'a> { + pub fn new(bounds: Rectangle<u32>) -> Self { + Self { + bounds, + quads: Vec::new(), + meshes: Vec::new(), + text: Vec::new(), + images: Vec::new(), + } + } + + pub fn overlay(lines: &'a [impl AsRef<str>], viewport: &Viewport) -> Self { + let (width, height) = viewport.dimensions(); + + let mut overlay = Layer::new(Rectangle { + x: 0, + y: 0, + width, + height, + }); + + 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: [0.9, 0.9, 0.9, 1.0], + size: 20.0, + font: Font::Default, + horizontal_alignment: HorizontalAlignment::Left, + vertical_alignment: VerticalAlignment::Top, + }; + + overlay.text.push(text); + + overlay.text.push(Text { + bounds: text.bounds + Vector::new(-1.0, -1.0), + color: [0.0, 0.0, 0.0, 1.0], + ..text + }); + } + + overlay + } + + pub(crate) fn intersection( + &self, + rectangle: Rectangle, + ) -> Option<Rectangle<u32>> { + let layer_bounds: Rectangle<f32> = self.bounds.into(); + + layer_bounds.intersection(&rectangle).map(Into::into) + } + + pub fn generate( + primitive: &'a Primitive, + viewport: &Viewport, + ) -> Vec<Self> { + let mut layers = Vec::new(); + let (width, height) = viewport.dimensions(); + + layers.push(Layer::new(Rectangle { + x: 0, + y: 0, + width, + height, + })); + + Self::process_primitive(&mut layers, Vector::new(0.0, 0.0), primitive); + + layers + } + + fn process_primitive( + layers: &mut Vec<Self>, + translation: Vector, + primitive: &'a Primitive, + ) { + match primitive { + Primitive::None => {} + Primitive::Group { primitives } => { + // TODO: Inspect a bit and regroup (?) + for primitive in primitives { + Self::process_primitive(layers, translation, primitive) + } + } + Primitive::Text { + content, + bounds, + size, + color, + font, + horizontal_alignment, + vertical_alignment, + } => { + let layer = layers.last_mut().unwrap(); + + layer.text.push(Text { + content, + bounds: *bounds + translation, + size: *size, + color: color.into_linear(), + font: *font, + horizontal_alignment: *horizontal_alignment, + vertical_alignment: *vertical_alignment, + }); + } + Primitive::Quad { + bounds, + background, + border_radius, + border_width, + border_color, + } => { + let layer = layers.last_mut().unwrap(); + + // TODO: Move some of these computations to the GPU (?) + layer.quads.push(Quad { + position: [ + bounds.x + translation.x, + bounds.y + translation.y, + ], + scale: [bounds.width, bounds.height], + color: match background { + Background::Color(color) => color.into_linear(), + }, + border_radius: *border_radius as f32, + border_width: *border_width as f32, + border_color: border_color.into_linear(), + }); + } + Primitive::Mesh2D { buffers, size } => { + let layer = layers.last_mut().unwrap(); + + let bounds = Rectangle::new( + Point::new(translation.x, translation.y), + *size, + ); + + // Only draw visible content + if let Some(clip_bounds) = layer.intersection(bounds) { + layer.meshes.push(Mesh { + origin: Point::new(translation.x, translation.y), + buffers, + clip_bounds: clip_bounds.into(), + }); + } + } + Primitive::Clip { + bounds, + offset, + content, + } => { + let layer = layers.last_mut().unwrap(); + + // Only draw visible content + if let Some(clip_bounds) = + layer.intersection(*bounds + translation) + { + let clip_layer = Layer::new(clip_bounds.into()); + let new_layer = Layer::new(layer.bounds); + + layers.push(clip_layer); + Self::process_primitive( + layers, + translation + - Vector::new(offset.x as f32, offset.y as f32), + content, + ); + layers.push(new_layer); + } + } + Primitive::Translate { + translation: new_translation, + content, + } => { + Self::process_primitive( + layers, + translation + *new_translation, + &content, + ); + } + Primitive::Cached { cache } => { + Self::process_primitive(layers, translation, &cache); + } + Primitive::Image { handle, bounds } => { + let layer = layers.last_mut().unwrap(); + + layer.images.push(Image::Raster { + handle: handle.clone(), + bounds: *bounds + translation, + }); + } + Primitive::Svg { handle, bounds } => { + let layer = layers.last_mut().unwrap(); + + layer.images.push(Image::Vector { + handle: handle.clone(), + bounds: *bounds + translation, + }); + } + } + } +} + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct Quad { + pub position: [f32; 2], + pub scale: [f32; 2], + pub color: [f32; 4], + pub border_color: [f32; 4], + pub border_radius: f32, + pub border_width: f32, +} + +#[derive(Debug, Clone, Copy)] +pub struct Mesh<'a> { + pub origin: Point, + pub buffers: &'a triangle::Mesh2D, + pub clip_bounds: Rectangle<u32>, +} + +#[derive(Debug, Clone, Copy)] +pub struct Text<'a> { + pub content: &'a str, + pub bounds: Rectangle, + pub color: [f32; 4], + pub size: f32, + pub font: Font, + pub horizontal_alignment: HorizontalAlignment, + pub vertical_alignment: VerticalAlignment, +} + +#[derive(Debug, Clone)] +pub enum Image { + Raster { + handle: image::Handle, + bounds: Rectangle, + }, + Vector { + handle: svg::Handle, + bounds: Rectangle, + }, +} + +unsafe impl bytemuck::Zeroable for Quad {} +unsafe impl bytemuck::Pod for Quad {} diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index 5dc4040f..5ab333c7 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -8,6 +8,7 @@ mod widget; pub mod backend; pub mod font; +pub mod layer; pub mod triangle; #[doc(no_inline)] @@ -16,7 +17,13 @@ pub use widget::*; pub use antialiasing::Antialiasing; pub use backend::Backend; pub use defaults::Defaults; +pub use layer::Layer; pub use primitive::Primitive; pub use renderer::Renderer; pub use transformation::Transformation; pub use viewport::Viewport; + +pub use iced_native::{ + Background, Font, HorizontalAlignment, Point, Rectangle, Size, Vector, + VerticalAlignment, +}; diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index e73227ef..95dbf7dd 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -82,13 +82,13 @@ pub enum Primitive { /// /// It can be used to render many kinds of geometry freely. Mesh2D { + /// The vertex and index buffers of the mesh + buffers: triangle::Mesh2D, + /// The size of the drawable region of the mesh. /// /// Any geometry that falls out of this region will be clipped. size: Size, - - /// The vertex and index buffers of the mesh - buffers: triangle::Mesh2D, }, /// A cached primitive. /// diff --git a/graphics/src/triangle.rs b/graphics/src/triangle.rs index 2b157e3a..474f69b8 100644 --- a/graphics/src/triangle.rs +++ b/graphics/src/triangle.rs @@ -5,6 +5,7 @@ pub struct Mesh2D { /// The vertices of the mesh pub vertices: Vec<Vertex2D>, + /// The list of vertex indices that defines the triangles of the mesh. /// /// Therefore, this list should always have a length that is a multiple of diff --git a/graphics/src/widget.rs b/graphics/src/widget.rs index d9c91d77..1f6d6559 100644 --- a/graphics/src/widget.rs +++ b/graphics/src/widget.rs @@ -10,18 +10,18 @@ pub mod button; pub mod checkbox; pub mod container; +pub mod image; pub mod pane_grid; pub mod progress_bar; pub mod radio; pub mod scrollable; pub mod slider; +pub mod svg; pub mod text_input; mod column; -mod image; mod row; mod space; -mod svg; mod text; #[doc(no_inline)] diff --git a/graphics/src/widget/canvas/frame.rs b/graphics/src/widget/canvas/frame.rs index 5262ab4e..48d28d95 100644 --- a/graphics/src/widget/canvas/frame.rs +++ b/graphics/src/widget/canvas/frame.rs @@ -304,11 +304,11 @@ impl Frame { pub fn into_geometry(mut self) -> Geometry { if !self.buffers.indices.is_empty() { self.primitives.push(Primitive::Mesh2D { - size: self.size, buffers: triangle::Mesh2D { vertices: self.buffers.vertices, indices: self.buffers.indices, }, + size: self.size, }); } diff --git a/graphics/src/widget/image.rs b/graphics/src/widget/image.rs index 79d82cb1..ea49febe 100644 --- a/graphics/src/widget/image.rs +++ b/graphics/src/widget/image.rs @@ -4,7 +4,7 @@ use iced_native::image; use iced_native::mouse; use iced_native::Layout; -pub use iced_native::Image; +pub use iced_native::image::{Handle, Image}; impl<B> image::Renderer for Renderer<B> where diff --git a/graphics/src/widget/svg.rs b/graphics/src/widget/svg.rs index b1aa7cea..8c681478 100644 --- a/graphics/src/widget/svg.rs +++ b/graphics/src/widget/svg.rs @@ -2,7 +2,7 @@ use crate::backend::{self, Backend}; use crate::{Primitive, Renderer}; use iced_native::{mouse, svg, Layout}; -pub use iced_native::Svg; +pub use iced_native::svg::{Handle, Svg}; impl<B> svg::Renderer for Renderer<B> where |