makepad_draw/text/
image.rs

1use {
2    super::{
3        geom::{Point, Rect, Size},
4        num::Zero,
5    },
6    std::{mem, ops::{Index, IndexMut}},
7};
8
9#[derive(Clone, Debug, Eq, Hash, PartialEq)]
10pub struct Image<T> {
11    size: Size<usize>,
12    pixels: Vec<T>,
13}
14
15impl<T> Image<T> {
16    pub fn new(size: Size<usize>) -> Self
17    where
18        T: Clone + Default,
19    {
20        Self {
21            size,
22            pixels: vec![Default::default(); size.width * size.height],
23        }
24    }
25
26    pub fn from_size_and_pixels(size: Size<usize>, pixels: Vec<T>) -> Self {
27        assert_eq!(size.width * size.height, pixels.len());
28        Self { size, pixels }
29    }
30
31    pub fn into_pixels(self) -> Vec<T> {
32        self.pixels
33    }
34
35    pub fn is_empty(&self) -> bool {
36        self.size() == Size::ZERO
37    }
38
39    pub fn size(&self) -> Size<usize> {
40        self.size
41    }
42
43    pub fn as_pixels(&self) -> &[T] {
44        &self.pixels
45    }
46
47    pub fn as_mut_pixels(&mut self) -> &mut [T] {
48        &mut self.pixels
49    }
50
51    pub unsafe fn replace_pixels(&mut self, pixels: Vec<T>) -> Vec<T> {
52        mem::replace(&mut self.pixels, pixels)
53    }
54
55    pub fn subimage(&self, rect: Rect<usize>) -> Subimage<'_, T> {
56        assert!(
57            Rect::from(self.size).contains_rect(rect),
58            "rect is out of bounds"
59        );
60        Subimage {
61            image: self,
62            bounds: rect,
63        }
64    }
65
66    pub fn subimage_mut(&mut self, rect: Rect<usize>) -> SubimageMut<'_, T> {
67        assert!(
68            Rect::from(self.size()).contains_rect(rect),
69            "rect {:?} is out of bounds (should fit in rect {:?})",
70            rect,
71            Rect::from(self.size())
72        );
73        SubimageMut {
74            image: self,
75            bounds: rect,
76        }
77    }
78}
79
80impl<T> Index<Point<usize>> for Image<T> {
81    type Output = T;
82
83    fn index(&self, point: Point<usize>) -> &Self::Output {
84        assert!(
85            Rect::from(self.size()).contains_point(point),
86            "point is out of bounds"
87        );
88        &self.pixels[point.y * self.size.width + point.x]
89    }
90}
91
92impl<T> IndexMut<Point<usize>> for Image<T> {
93    fn index_mut(&mut self, point: Point<usize>) -> &mut Self::Output {
94        assert!(
95            Rect::from(self.size()).contains_point(point),
96            "point is out of bounds"
97        );
98        &mut self.pixels[point.y * self.size.width + point.x]
99    }
100}
101
102#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
103pub struct Subimage<'a, T> {
104    image: &'a Image<T>,
105    bounds: Rect<usize>,
106}
107
108impl<'a, T> Subimage<'a, T> {
109    pub fn is_empty(&self) -> bool {
110        self.bounds().is_empty()
111    }
112
113    pub fn size(&self) -> Size<usize> {
114        self.bounds().size
115    }
116
117    pub fn bounds(&self) -> Rect<usize> {
118        self.bounds
119    }
120
121    pub fn to_image(&self) -> Image<T>
122    where
123        T: Copy,
124    {
125        let mut pixels = Vec::with_capacity(self.size().width * self.size().height);
126        for y in 0..self.size().height {
127            for x in 0..self.size().width {
128                pixels.push(self[Point::new(x, y)]);
129            }
130        }
131        Image::from_size_and_pixels(self.size(), pixels)
132    }
133}
134
135impl<'a, T> Index<Point<usize>> for Subimage<'a, T> {
136    type Output = T;
137
138    fn index(&self, point: Point<usize>) -> &Self::Output {
139        assert!(
140            Rect::from(self.bounds().size).contains_point(point),
141            "point is out of bounds"
142        );
143        &self.image[self.bounds.origin + Size::from(point)]
144    }
145}
146
147#[derive(Debug, Eq, Hash, PartialEq)]
148pub struct SubimageMut<'a, T> {
149    image: &'a mut Image<T>,
150    bounds: Rect<usize>,
151}
152
153impl<'a, T> SubimageMut<'a, T> {
154    pub fn is_empty(&self) -> bool {
155        self.bounds().is_empty()
156    }
157
158    pub fn size(&self) -> Size<usize> {
159        self.bounds().size
160    }
161
162    pub fn bounds(&self) -> Rect<usize> {
163        self.bounds
164    }
165
166    pub fn subimage_mut(self, rect: Rect<usize>) -> SubimageMut<'a, T> {
167        assert!(
168            Rect::from(self.size()).contains_rect(rect),
169            "rect {:?} is out of bounds (should fit in rect {:?})",
170            rect,
171            Rect::from(self.size())
172        );
173        SubimageMut {
174            image: self.image,
175            bounds: Rect::new(self.bounds.origin + Size::from(rect.origin), rect.size),
176        }
177    }
178}
179
180impl<'a, T> Index<Point<usize>> for SubimageMut<'a, T> {
181    type Output = T;
182
183    fn index(&self, point: Point<usize>) -> &Self::Output {
184        assert!(
185            Rect::from(self.bounds().size).contains_point(point),
186            "point is out of bounds"
187        );
188        &self.image[self.bounds.origin + Size::from(point)]
189    }
190}
191
192impl<'a, T> IndexMut<Point<usize>> for SubimageMut<'a, T> {
193    fn index_mut(&mut self, point: Point<usize>) -> &mut Self::Output {
194        assert!(
195            Rect::from(self.bounds().size).contains_point(point),
196            "point is out of bounds"
197        );
198        &mut self.image[self.bounds.origin + Size::from(point)]
199    }
200}
201
202#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
203#[repr(transparent)]
204pub struct R {
205    pub bits: u8,
206}
207
208impl R {
209    pub const fn new(r: u8) -> Self {
210        Self { bits: r }
211    }
212
213    pub fn r(self) -> u8 {
214        self.bits
215    }
216}
217
218#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
219#[repr(transparent)]
220pub struct Bgra {
221    pub bits: u32,
222}
223
224impl Bgra {
225    pub fn new(b: u8, g: u8, r: u8, a: u8) -> Self {
226        let b = u32::from(b);
227        let g = u32::from(g);
228        let r = u32::from(r);
229        let a = u32::from(a);
230        Self { bits: (a << 24) | (r << 16) | (g << 8) | b }
231    }
232
233    pub fn b(self) -> u8 {
234        (self.bits & 0xFF) as u8
235    }
236
237    pub fn g(self) -> u8 {
238        ((self.bits >> 8) & 0xFF) as u8
239    }
240
241    pub fn r(self) -> u8 {
242        ((self.bits >> 16) & 0xFF) as u8
243    }
244
245    pub fn a(self) -> u8 {
246        ((self.bits >> 24) & 0xFF) as u8
247    }
248}