simple_blit/
types.rs

1use core::{
2    marker::PhantomData,
3    ops::{Deref, DerefMut, Index, IndexMut},
4};
5
6/// Point type.
7pub type Point = mint::Point2<u32>;
8/// Size type.
9pub type Size = mint::Vector2<u32>;
10
11/// Quickly construct a `Point`.
12#[inline]
13pub const fn point(x: u32, y: u32) -> Point {
14    Point { x, y }
15}
16
17/// Quickly construct a `Size`.
18#[inline]
19pub const fn size(x: u32, y: u32) -> Size {
20    Size { x, y }
21}
22
23/// 2D immutable surface trait.
24pub trait Surface<T> {
25    /// Surface size.
26    fn surface_size(&self) -> Size;
27
28    /// Get a value at (pt.x, pt.y).
29    fn surface_get(&self, pt: Point) -> Option<&T>;
30
31    /// Create a [`SubSurface`] that only uses a rectangular part of this surface.
32    #[inline]
33    fn sub_surface(&self, offset: Point, size: Size) -> SubSurface<&Self, T>
34    where
35        Self: Sized,
36    {
37        SubSurface::new(self, offset, size)
38    }
39
40    /// Create a [`SubSurface`] that only uses a rectangular part of this surface starting from (offset.x, offset.y).
41    #[inline]
42    fn offset_surface(&self, offset: Point) -> SubSurface<&Self, T>
43    where
44        Self: Sized,
45    {
46        let sur_size = self.surface_size();
47        SubSurface::new(
48            self,
49            offset,
50            size(sur_size.x - offset.x, sur_size.y - offset.y),
51        )
52    }
53
54    /// Create a [`SubSurface`] that only uses a rectangular part of this surface.
55    #[inline]
56    fn sub_surface_mut(&mut self, offset: Point, size: Size) -> SubSurface<&mut Self, T>
57    where
58        Self: Sized,
59    {
60        SubSurface::new(self, offset, size)
61    }
62
63    /// Create a [`SubSurface`] that only uses a rectangular part of this surface starting from (offset.x, offset.y).
64    #[inline]
65    fn offset_surface_mut(&mut self, offset: Point) -> SubSurface<&mut Self, T>
66    where
67        Self: Sized,
68    {
69        let sur_size = self.surface_size();
70        SubSurface::new(
71            self,
72            offset,
73            size(sur_size.x - offset.x, sur_size.y - offset.y),
74        )
75    }
76
77    /// Create a [`SubSurface`] that only uses a rectangular part of this surface.
78    #[inline]
79    fn into_sub_surface(self, offset: Point, size: Size) -> SubSurface<Self, T>
80    where
81        Self: Sized,
82    {
83        SubSurface::new(self, offset, size)
84    }
85
86    /// Create a [`SubSurface`] that only uses a rectangular part of this surface starting from (offset.x, offset.y).
87    #[inline]
88    fn into_offset_surface(self, offset: Point) -> SubSurface<Self, T>
89    where
90        Self: Sized,
91    {
92        let sur_size = self.surface_size();
93        SubSurface::new(
94            self,
95            offset,
96            size(sur_size.x - offset.x, sur_size.y - offset.y),
97        )
98    }
99}
100
101impl<S, T> Surface<T> for &S
102where
103    S: Surface<T>,
104{
105    #[inline]
106    fn surface_size(&self) -> Size {
107        (**self).surface_size()
108    }
109
110    #[inline]
111    fn surface_get(&self, pt: Point) -> Option<&T> {
112        (**self).surface_get(pt)
113    }
114}
115
116impl<S, T> Surface<T> for &mut S
117where
118    S: Surface<T>,
119{
120    #[inline]
121    fn surface_size(&self) -> Size {
122        (**self).surface_size()
123    }
124
125    #[inline]
126    fn surface_get(&self, pt: Point) -> Option<&T> {
127        (**self).surface_get(pt)
128    }
129}
130
131/// 2D mutable surface trait.
132pub trait SurfaceMut<T>: Surface<T> {
133    /// Get a mutable value at (pt.x, pt.y).
134    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut T>;
135}
136
137impl<S, T> SurfaceMut<T> for &mut S
138where
139    S: SurfaceMut<T>,
140{
141    #[inline]
142    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut T> {
143        (*self).surface_get_mut(pt)
144    }
145}
146
147/// Generic surface with width and height.
148#[derive(Clone, Copy, Debug, PartialEq, Eq)]
149#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
150pub struct GenericSurface<Slice, Item> {
151    slice: Slice,
152    size: Size,
153    ghost: PhantomData<Item>,
154}
155
156impl<Slice, Item> GenericSurface<Slice, Item>
157where
158    Slice: AsRef<[Item]>,
159{
160    /// Construct a new surface.
161    ///
162    /// Returns `None` if `slice.len() != size.x * size.y`.
163    #[inline]
164    pub fn new(slice: Slice, size: Size) -> Option<Self> {
165        if slice.as_ref().len() == (size.x * size.y) as _ {
166            Some(Self {
167                slice,
168                size,
169                ghost: PhantomData,
170            })
171        } else {
172            None
173        }
174    }
175
176    /// Constructs a new surface.
177    ///
178    /// Infers the height from slice length and width.
179    #[inline]
180    pub fn new_infer(slice: Slice, width: u32) -> Self {
181        Self {
182            size: size(width, slice.as_ref().len() as u32 / width),
183            slice,
184            ghost: PhantomData,
185        }
186    }
187
188    /// Returns the slice used to create the surface.
189    #[inline]
190    pub fn into_inner(self) -> Slice {
191        self.slice
192    }
193}
194
195impl<Slice, Item> Deref for GenericSurface<Slice, Item>
196where
197    Slice: AsRef<[Item]>,
198{
199    type Target = [Item];
200
201    #[inline]
202    fn deref(&self) -> &Self::Target {
203        self.slice.as_ref()
204    }
205}
206
207impl<Slice, Item> DerefMut for GenericSurface<Slice, Item>
208where
209    Slice: AsRef<[Item]> + AsMut<[Item]>,
210{
211    #[inline]
212    fn deref_mut(&mut self) -> &mut Self::Target {
213        self.slice.as_mut()
214    }
215}
216
217impl<Slice, Item> Surface<Item> for GenericSurface<Slice, Item>
218where
219    Slice: AsRef<[Item]>,
220{
221    #[inline]
222    fn surface_size(&self) -> Size {
223        self.size
224    }
225
226    #[inline]
227    fn surface_get(&self, pt: Point) -> Option<&Item> {
228        if pt.x < self.size.x && pt.y < self.size.y {
229            Some(
230                self.slice
231                    .as_ref()
232                    .index((pt.y * self.size.x + pt.x) as usize),
233            )
234        } else {
235            None
236        }
237    }
238}
239
240impl<Slice, Item> SurfaceMut<Item> for GenericSurface<Slice, Item>
241where
242    Slice: AsRef<[Item]> + AsMut<[Item]>,
243{
244    #[inline]
245    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut Item> {
246        if pt.x < self.size.x && pt.y < self.size.y {
247            Some(
248                self.slice
249                    .as_mut()
250                    .index_mut((pt.y * self.size.x + pt.x) as usize),
251            )
252        } else {
253            None
254        }
255    }
256}
257
258/// A 'surface' that holds a single value, like a plain-colored rectangle.
259#[derive(Clone, Copy, Debug, PartialEq, Eq)]
260#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
261pub struct SingleValueSurface<T> {
262    /// Surface size.
263    pub size: Size,
264    /// Stored value, likely a color.
265    pub value: T,
266}
267
268impl<T> SingleValueSurface<T> {
269    /// Construct a new surface.
270    #[inline]
271    pub const fn new(value: T, size: Size) -> Self {
272        Self { size, value }
273    }
274
275    /// Returns a reference to the underlying value.
276    #[inline]
277    pub fn value(&self) -> &T {
278        &self.value
279    }
280
281    /// Returns a reference to the underlying value.
282    #[inline]
283    pub fn value_mut(&mut self) -> &mut T {
284        &mut self.value
285    }
286
287    /// Returns the underlying value.
288    #[inline]
289    pub fn into_inner(self) -> T {
290        self.value
291    }
292}
293
294impl<T> Surface<T> for SingleValueSurface<T> {
295    #[inline]
296    fn surface_size(&self) -> Size {
297        self.size
298    }
299
300    #[inline]
301    fn surface_get(&self, _pt: Point) -> Option<&T> {
302        Some(&self.value)
303    }
304}
305
306impl<T> SurfaceMut<T> for SingleValueSurface<T> {
307    #[inline]
308    fn surface_get_mut(&mut self, _pt: Point) -> Option<&mut T> {
309        Some(&mut self.value)
310    }
311}
312
313/// A surface that only uses a rectangular part of another surface.
314#[derive(Clone, Copy, Debug, PartialEq, Eq)]
315#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
316pub struct SubSurface<S, Item> {
317    surface: S,
318    offset: Point,
319    size: Size,
320    ghost: PhantomData<Item>,
321}
322
323impl<S, Item> SubSurface<S, Item> {
324    /// Position of the rectangular part on the original surface.
325    #[inline]
326    pub fn offset(&self) -> Point {
327        self.offset
328    }
329
330    /// Size of the rectangular part (size of the `SubSurface` itself).
331    #[inline]
332    pub fn size(&self) -> Size {
333        self.size
334    }
335
336    /// Returns a reference to the underlying surface.
337    #[inline]
338    pub fn inner(&self) -> &S {
339        &self.surface
340    }
341
342    /// Returns a reference to the underlying surface.
343    #[inline]
344    pub fn inner_mut(&mut self) -> &mut S {
345        &mut self.surface
346    }
347
348    /// Returns the underlying surface.
349    #[inline]
350    pub fn into_inner(self) -> S {
351        self.surface
352    }
353}
354
355impl<S, Item> SubSurface<S, Item>
356where
357    S: Surface<Item>,
358{
359    /// Create a new `SubSurface`.
360    #[inline]
361    pub fn new(surface: S, offset: Point, size: Size) -> Self {
362        Self {
363            surface,
364            offset,
365            size,
366            ghost: PhantomData,
367        }
368    }
369}
370
371impl<S, Item> Surface<Item> for SubSurface<S, Item>
372where
373    S: Surface<Item>,
374{
375    #[inline]
376    fn surface_size(&self) -> Size {
377        self.size
378    }
379
380    #[inline]
381    fn surface_get(&self, pt: Point) -> Option<&Item> {
382        if pt.x < self.size.x && pt.y < self.size.y {
383            self.surface
384                .surface_get(point(pt.x + self.offset.x, pt.y + self.offset.y))
385        } else {
386            None
387        }
388    }
389}
390
391impl<S, Item> SurfaceMut<Item> for SubSurface<S, Item>
392where
393    S: SurfaceMut<Item>,
394{
395    #[inline]
396    fn surface_get_mut(&mut self, pt: Point) -> Option<&mut Item> {
397        if pt.x < self.size.x && pt.y < self.size.y {
398            self.surface
399                .surface_get_mut(point(pt.x + self.offset.x, pt.y + self.offset.y))
400        } else {
401            None
402        }
403    }
404}