summaryrefslogtreecommitdiffstats
path: root/graphics/src/layer.rs
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/src/layer.rs
parente6180912488db4d59fbffcb46c5930282306cb92 (diff)
downloadiced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.gz
iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.tar.bz2
iced-720e7756f2afe30706b6b1a7fbde86b9f15e1d8c.zip
Move `Layer` to `iced_graphics`
Diffstat (limited to 'graphics/src/layer.rs')
-rw-r--r--graphics/src/layer.rs266
1 files changed, 266 insertions, 0 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 {}