@@ -20,15 +20,6 @@ pub struct Layer<'a> {
2020 pub masks : Vec < Mask < ' a > > ,
2121}
2222
23- /// Defines a property that can be either owned or borrowed.
24- #[ derive( Debug , Clone ) ]
25- pub enum Either < ' a , T > {
26- /// The owned value.
27- Owned ( T ) ,
28- /// The borrowed value.
29- Borrowed ( & ' a T ) ,
30- }
31-
3223// MARK: Creation
3324
3425impl < ' a > Layer < ' a > {
@@ -63,13 +54,209 @@ impl<'a> Layer<'a> {
6354
6455impl < ' a > Layer < ' a > {
6556 /// Returns the alpha for the mask at a given location.
57+ ///
58+ /// If the layer should be fully opaque at this location,
59+ /// u8::MAX is returned.
60+ /// If it should be fully transparent, 0 is returned,
6661 /// If there is no mask, u8::MAX is returned.
6762 pub fn mask_alpha ( & self , location : Point < u32 > ) -> u8 {
6863 let mut result = u8:: MAX ;
6964
65+ let mut location = location. into ( ) ;
7066 for mask in self . masks . iter ( ) {
71- // result = ()
67+ let color = match mask {
68+ Mask :: Positioned ( positioned_mask) => {
69+ location -= positioned_mask. origin ;
70+ positioned_mask. image . pixel_color ( location)
71+ }
72+ Mask :: Tiled ( tiled_mask) => {
73+ location -= tiled_mask. offset ;
74+ let width = tiled_mask. image . size . width as i32 ;
75+ let height = tiled_mask. image . size . height as i32 ;
76+ if location. x < 0 {
77+ location. x = width + ( location. x % width) ;
78+ }
79+ if location. x >= width {
80+ location. x = location. x % width;
81+ }
82+ if location. y < 0 {
83+ location. y = height + ( location. y % height) ;
84+ }
85+ if location. y >= height {
86+ location. y = location. y % height;
87+ }
88+ tiled_mask. image . pixel_color ( location)
89+ }
90+ } ;
91+ // Out of bounds.
92+ let Some ( color) = color else {
93+ return 0 ;
94+ } ;
95+ let alpha = ( result as u16 * color. alpha as u16 ) / u8:: MAX as u16 ;
96+ result = alpha as u8 ;
7297 }
7398 result
7499 }
75100}
101+
102+ #[ cfg( test) ]
103+ mod test {
104+ use std:: borrow:: Cow ;
105+
106+ use crate :: { Color , Image , Mask , Point , PositionedMask , Size , TiledMask } ;
107+
108+ use super :: Layer ;
109+
110+ #[ test]
111+ fn mask_alpha_no_masks ( ) {
112+ let image = Image :: color (
113+ & Color :: MAGENTA ,
114+ Size {
115+ width : 13 ,
116+ height : 21 ,
117+ } ,
118+ ) ;
119+ let position = Point { x : 3.0 , y : 5.0 } ;
120+ let layer = Layer :: new ( & image, position) ;
121+
122+ let location = Point { x : 4 , y : 9 } ;
123+ let alpha = layer. mask_alpha ( location) ;
124+
125+ assert_eq ! ( alpha, u8 :: MAX ) ;
126+ }
127+
128+ #[ test]
129+ fn mask_alpha_positioned_mask ( ) {
130+ let image = Image :: color (
131+ & Color :: MAGENTA ,
132+ Size {
133+ width : 13 ,
134+ height : 21 ,
135+ } ,
136+ ) ;
137+ let position = Point { x : 3.0 , y : 5.0 } ;
138+ let mut layer = Layer :: new ( & image, position) ;
139+
140+ let image = Image :: color (
141+ & Color :: BLACK ,
142+ Size {
143+ width : 4 ,
144+ height : 3 ,
145+ } ,
146+ ) ;
147+ let mask = PositionedMask {
148+ image : Cow :: Borrowed ( & image) ,
149+ origin : Point { x : 2 , y : 1 } ,
150+ } ;
151+ let mask = Mask :: Positioned ( mask) ;
152+ layer. masks = vec ! [ mask] ;
153+
154+ let location = Point { x : 4 , y : 3 } ;
155+ let alpha = layer. mask_alpha ( location) ;
156+ assert_eq ! ( alpha, u8 :: MAX ) ;
157+
158+ let location = Point { x : 0 , y : 0 } ;
159+ let alpha = layer. mask_alpha ( location) ;
160+ assert_eq ! ( alpha, 0 ) ;
161+ }
162+
163+ #[ test]
164+ fn mask_alpha_tiled_mask ( ) {
165+ let image = Image :: color (
166+ & Color :: MAGENTA ,
167+ Size {
168+ width : 13 ,
169+ height : 21 ,
170+ } ,
171+ ) ;
172+ let position = Point { x : 3.0 , y : 5.0 } ;
173+ let mut layer = Layer :: new ( & image, position) ;
174+
175+ // Setting up a checkerboard image.
176+ let mut image = Image :: empty ( Size {
177+ width : 2 ,
178+ height : 2 ,
179+ } ) ;
180+ image. set_pixel_color ( Color :: BLACK , Point :: zero ( ) ) ;
181+ image. set_pixel_color ( Color :: BLACK , Point { x : 1 , y : 1 } ) ;
182+
183+ let mask = TiledMask {
184+ image : Cow :: Borrowed ( & image) ,
185+ offset : Point { x : 1 , y : 0 } ,
186+ } ;
187+ let mask = Mask :: Tiled ( mask) ;
188+ layer. masks = vec ! [ mask] ;
189+
190+ let location = Point { x : 0 , y : 0 } ;
191+ let alpha = layer. mask_alpha ( location) ;
192+ assert_eq ! ( alpha, 0 ) ;
193+
194+ let location = Point { x : 1 , y : 0 } ;
195+ let alpha = layer. mask_alpha ( location) ;
196+ assert_eq ! ( alpha, u8 :: MAX ) ;
197+
198+ let location = Point { x : 2 , y : 0 } ;
199+ let alpha = layer. mask_alpha ( location) ;
200+ assert_eq ! ( alpha, 0 ) ;
201+
202+ let location = Point { x : 3 , y : 0 } ;
203+ let alpha = layer. mask_alpha ( location) ;
204+ assert_eq ! ( alpha, u8 :: MAX ) ;
205+
206+ let location = Point { x : 4 , y : 0 } ;
207+ let alpha = layer. mask_alpha ( location) ;
208+ assert_eq ! ( alpha, 0 ) ;
209+
210+ let location = Point { x : 5 , y : 0 } ;
211+ let alpha = layer. mask_alpha ( location) ;
212+ assert_eq ! ( alpha, u8 :: MAX ) ;
213+
214+ let location = Point { x : 0 , y : 2 } ;
215+ let alpha = layer. mask_alpha ( location) ;
216+ assert_eq ! ( alpha, 0 ) ;
217+
218+ let location = Point { x : 1 , y : 2 } ;
219+ let alpha = layer. mask_alpha ( location) ;
220+ assert_eq ! ( alpha, u8 :: MAX ) ;
221+
222+ let location = Point { x : 2 , y : 2 } ;
223+ let alpha = layer. mask_alpha ( location) ;
224+ assert_eq ! ( alpha, 0 ) ;
225+
226+ let location = Point { x : 3 , y : 2 } ;
227+ let alpha = layer. mask_alpha ( location) ;
228+ assert_eq ! ( alpha, u8 :: MAX ) ;
229+
230+ let location = Point { x : 4 , y : 2 } ;
231+ let alpha = layer. mask_alpha ( location) ;
232+ assert_eq ! ( alpha, 0 ) ;
233+
234+ let location = Point { x : 5 , y : 2 } ;
235+ let alpha = layer. mask_alpha ( location) ;
236+ assert_eq ! ( alpha, u8 :: MAX ) ;
237+
238+ let location = Point { x : 0 , y : 3 } ;
239+ let alpha = layer. mask_alpha ( location) ;
240+ assert_eq ! ( alpha, u8 :: MAX ) ;
241+
242+ let location = Point { x : 1 , y : 3 } ;
243+ let alpha = layer. mask_alpha ( location) ;
244+ assert_eq ! ( alpha, 0 ) ;
245+
246+ let location = Point { x : 2 , y : 3 } ;
247+ let alpha = layer. mask_alpha ( location) ;
248+ assert_eq ! ( alpha, u8 :: MAX ) ;
249+
250+ let location = Point { x : 3 , y : 3 } ;
251+ let alpha = layer. mask_alpha ( location) ;
252+ assert_eq ! ( alpha, 0 ) ;
253+
254+ let location = Point { x : 4 , y : 3 } ;
255+ let alpha = layer. mask_alpha ( location) ;
256+ assert_eq ! ( alpha, u8 :: MAX ) ;
257+
258+ let location = Point { x : 5 , y : 3 } ;
259+ let alpha = layer. mask_alpha ( location) ;
260+ assert_eq ! ( alpha, 0 ) ;
261+ }
262+ }
0 commit comments