diff options
| author | 2020-05-19 22:55:12 +0200 | |
|---|---|---|
| committer | 2020-05-19 23:19:39 +0200 | |
| commit | 720e7756f2afe30706b6b1a7fbde86b9f15e1d8c (patch) | |
| tree | 3a55248a4b25654b1d63b8c547fd0f653471606d /graphics/src | |
| parent | e6180912488db4d59fbffcb46c5930282306cb92 (diff) | |
| download | iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.gz iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.bz2 iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.zip | |
Move `Layer` to `iced_graphics`
Diffstat (limited to '')
| -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 | 
