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