lapix/
layer.rs

1use crate::color::TRANSPARENT;
2use crate::{Bitmap, Canvas, Color, Point, Rect, Size};
3use serde::{Deserialize, Serialize};
4
5/// An ordered collection of [`Layer`]s. There is always one active layer.
6#[derive(Debug, Serialize, Deserialize)]
7pub struct Layers<IMG> {
8    inner: Vec<Layer<IMG>>,
9    active: usize,
10}
11
12impl<IMG: Bitmap> Layers<IMG> {
13    /// Creates a new set of layers
14    pub fn new(size: Size<i32>) -> Self {
15        Self {
16            inner: vec![Layer::new(size)],
17            active: 0,
18        }
19    }
20
21    /// Get the active [`Layer`]
22    pub fn active(&self) -> &Layer<IMG> {
23        &self.inner[self.active]
24    }
25
26    /// Get the index of the active [`Layer`]
27    pub fn active_index(&self) -> usize {
28        self.active
29    }
30
31    /// Get the number of [`Layer`]s
32    pub fn count(&self) -> usize {
33        self.inner.len()
34    }
35
36    /// Get the [`Canvas`] of the [`Layer`] at the specified index
37    pub fn canvas_at(&self, index: usize) -> &Canvas<IMG> {
38        self.inner[index].canvas()
39    }
40
41    /// Get the [`Canvas`] of the active [`Layer`]
42    pub fn active_canvas(&self) -> &Canvas<IMG> {
43        self.canvas_at(self.active)
44    }
45
46    /// Get a [`Layer`] by its index
47    pub fn get(&self, index: usize) -> &Layer<IMG> {
48        &self.inner[index]
49    }
50
51    /// Get an image of all the [`Layer`]s blended together
52    pub fn blended(&self) -> IMG {
53        let w = self.canvas_at(0).width();
54        let h = self.canvas_at(0).height();
55
56        self.blended_area((0, 0, w, h).into())
57    }
58
59    /// Get an image of an area (determined by a rectangle) of all [`Layer`]s
60    /// blended together
61    pub fn blended_area(&self, r: Rect<i32>) -> IMG {
62        let mut result = IMG::new((r.w, r.h).into(), TRANSPARENT);
63
64        for i in 0..r.w {
65            for j in 0..r.h {
66                let ij = Point::new(i, j);
67                result.set_pixel(ij, self.visible_pixel(ij + r.pos()));
68            }
69        }
70
71        result
72    }
73
74    /// Get a mutable reference to a [`Layer`] by its index
75    pub fn get_mut(&mut self, index: usize) -> &mut Layer<IMG> {
76        &mut self.inner[index]
77    }
78
79    /// Get a mutable reference to the [`Canvas`] of the [`Layer`] at a certain
80    /// index
81    pub fn canvas_at_mut(&mut self, index: usize) -> &mut Canvas<IMG> {
82        self.inner[index].canvas_mut()
83    }
84
85    /// Get a mutable reference to the [`Canvas`] of the active [`Layer`]
86    pub fn active_canvas_mut(&mut self) -> &mut Canvas<IMG> {
87        self.inner[self.active].canvas_mut()
88    }
89
90    /// Resize all [`Layer`]s, returning the images that were there before the
91    /// resizing (used for undoing)
92    pub fn resize_all(&mut self, size: Size<i32>) -> Vec<IMG> {
93        let mut imgs = Vec::new();
94        for layer in self.inner.iter_mut() {
95            let img = layer.resize(size);
96            imgs.push(img);
97        }
98
99        imgs
100    }
101
102    /// Set the active [`Layer`] to the specified index
103    pub fn switch_to(&mut self, index: usize) {
104        self.active = index;
105    }
106
107    /// Add a new [`Layer`] above all layers
108    pub fn add_new_above(&mut self) {
109        let layer = Layer::new(self.active_canvas().size());
110        self.inner.push(layer);
111    }
112
113    /// Add a new [`Layer`] at the specified index
114    pub fn add_at(&mut self, index: usize, layer: Layer<IMG>) {
115        self.inner.insert(index, layer);
116    }
117
118    /// Delete the [`Layer`] at the specified index
119    pub fn delete(&mut self, index: usize) -> Layer<IMG> {
120        let layer = self.inner.remove(index);
121        self.active = self.active.clamp(0, self.count() - 1);
122
123        layer
124    }
125
126    /// Set whether the [`Layer`] at the specified index is visible or not
127    pub fn set_visibility(&mut self, index: usize, visible: bool) {
128        self.inner[index].set_visibility(visible);
129    }
130
131    /// Set the opacity (alpha) of the [`Layer`] at the specified index
132    pub fn set_opacity(&mut self, index: usize, opacity: u8) {
133        self.inner[index].set_opacity(opacity);
134    }
135
136    /// Swap the positions of two [`Layer`]s
137    pub fn swap(&mut self, first: usize, second: usize) {
138        self.inner.swap(first, second);
139    }
140
141    // TODO: maybe Canvas is a better name for Layers than for that type, since
142    // the canvas is a combination of all layers, not a single layer's image
143    /// Get the color of the visible pixel at a certain [`Point`] in the canvas,
144    /// considering the blended result of all layers with their visibility and
145    /// opacity settings
146    pub fn visible_pixel(&self, p: Point<i32>) -> Color {
147        let mut result = if self.inner[0].visible() {
148            self.canvas_at(0)
149                .pixel(p)
150                .with_multiplied_alpha(self.get(0).opacity())
151        } else {
152            TRANSPARENT
153        };
154
155        for i in 1..self.count() {
156            if !self.get(i).visible() {
157                continue;
158            }
159
160            let color = self
161                .canvas_at(i)
162                .pixel(p)
163                .with_multiplied_alpha(self.get(i).opacity());
164            result = color.blend_over(result);
165        }
166
167        result
168    }
169}
170
171/// Represents a layer of the canvas. Layers are stacked on top of each other to
172/// make a final image, blending colors with transparency. Layers can be moved
173/// up or down relative to each other, can be made invisible or have a level of
174/// transparency (opacity).
175#[derive(Debug, Serialize, Deserialize)]
176pub struct Layer<IMG> {
177    canvas: Canvas<IMG>,
178    visible: bool,
179    opacity: u8,
180}
181
182impl<IMG: Bitmap> Layer<IMG> {
183    /// Create a new layer with a specified size
184    pub fn new(size: Size<i32>) -> Self {
185        Self {
186            canvas: Canvas::new(size),
187            visible: true,
188            opacity: 255,
189        }
190    }
191
192    /// Get the [`Canvas`] of this layer
193    pub fn canvas(&self) -> &Canvas<IMG> {
194        &self.canvas
195    }
196
197    /// Get a mutable reference to the [`Canvas`] of this layer
198    pub fn canvas_mut(&mut self) -> &mut Canvas<IMG> {
199        &mut self.canvas
200    }
201
202    /// Whether this layer is visible
203    pub fn visible(&self) -> bool {
204        self.visible
205    }
206
207    /// Get the opacity level (alpha) of this layer, a value from 0-255
208    pub fn opacity(&self) -> u8 {
209        self.opacity
210    }
211
212    /// Take the image of this layer's [`Canvas`], leaving a dummy empty one in
213    /// its place
214    pub fn take_img(&mut self) -> IMG {
215        self.canvas.take_inner()
216    }
217
218    /// Resize this layer, returning the previous image (the image before the
219    /// resizing)
220    pub fn resize(&mut self, size: Size<i32>) -> IMG {
221        self.canvas.resize(size)
222    }
223
224    /// Set whether this layer is visible
225    pub fn set_visibility(&mut self, visible: bool) {
226        self.visible = visible;
227    }
228
229    /// Set the opacity of this layer
230    pub fn set_opacity(&mut self, opacity: u8) {
231        self.opacity = opacity;
232    }
233}
234
235#[cfg(test)]
236mod tests {
237    use super::*;
238    use crate::bitmap::TestImage;
239    use crate::color;
240    use test_case::test_case;
241
242    fn get_three_layer_canvas() -> Layers<TestImage> {
243        let mut layers = Layers::<TestImage>::new(Size::new(2, 2));
244        layers.add_new_above();
245        layers.add_new_above();
246
247        layers
248    }
249
250    #[test_case((0, 0, 0, 255), (255, 255, 255, 255), (0, 0, 0, 255))]
251    #[test_case((10, 200, 99, 255), (0, 255, 0, 99), (10, 200, 99, 255))]
252    #[test_case((0, 0, 0, 127), (255, 255, 255, 255), (127, 127, 127, 255))]
253    #[test_case((0, 0, 0, 127), (255, 255, 255, 127), (85, 85, 85, 190))]
254    #[test_case((255, 0, 0, 11), (0, 255, 0, 11), (130, 124, 0, 21))]
255    fn visible_pixel<C: Into<Color>>(a: C, b: C, res: C) {
256        let mut layers = get_three_layer_canvas();
257        layers
258            .canvas_at_mut(1)
259            .set_pixel(Point::new(1, 1), a.into());
260        layers
261            .canvas_at_mut(0)
262            .set_pixel(Point::new(1, 1), b.into());
263        let pixel = layers.visible_pixel(Point::new(1, 1));
264
265        assert_eq!(pixel, res.into());
266    }
267}