summaryrefslogtreecommitdiffstats
path: root/graphics
diff options
context:
space:
mode:
authorLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-19 22:55:12 +0200
committerLibravatar Héctor Ramón Jiménez <hector0193@gmail.com>2020-05-19 23:19:39 +0200
commit720e7756f2afe30706b6b1a7fbde86b9f15e1d8c (patch)
tree3a55248a4b25654b1d63b8c547fd0f653471606d /graphics
parente6180912488db4d59fbffcb46c5930282306cb92 (diff)
downloadiced-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.rs266
-rw-r--r--graphics/src/lib.rs7
-rw-r--r--graphics/src/primitive.rs6
-rw-r--r--graphics/src/triangle.rs1
-rw-r--r--graphics/src/widget.rs4
-rw-r--r--graphics/src/widget/canvas/frame.rs2
-rw-r--r--graphics/src/widget/image.rs2
-rw-r--r--graphics/src/widget/svg.rs2
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