iced_wgpu/image/atlas/
allocator.rs

1use crate::core;
2
3use guillotiere::{AtlasAllocator, Size};
4
5pub struct Allocator {
6    raw: AtlasAllocator,
7    allocations: usize,
8}
9
10impl Allocator {
11    const PADDING: u32 = 1;
12
13    pub fn new(size: u32) -> Allocator {
14        let raw = AtlasAllocator::new(Size::new(size as i32, size as i32));
15
16        Allocator {
17            raw,
18            allocations: 0,
19        }
20    }
21
22    pub fn allocate(&mut self, width: u32, height: u32) -> Option<Region> {
23        let size = self.raw.size();
24
25        let padded_width = width + Self::PADDING * 2;
26        let padded_height = height + Self::PADDING * 2;
27
28        let pad_width = padded_width as i32 <= size.width;
29        let pad_height = padded_height as i32 <= size.height;
30
31        let mut allocation = self.raw.allocate(Size::new(
32            if pad_width { padded_width } else { width } as i32,
33            if pad_height { padded_height } else { height } as i32,
34        ))?;
35
36        if pad_width {
37            allocation.rectangle.min.x += Self::PADDING as i32;
38            allocation.rectangle.max.x -= Self::PADDING as i32;
39        }
40
41        if pad_height {
42            allocation.rectangle.min.y += Self::PADDING as i32;
43            allocation.rectangle.max.y -= Self::PADDING as i32;
44        }
45
46        self.allocations += 1;
47
48        Some(Region {
49            allocation,
50            padding: core::Size::new(
51                if pad_width { Self::PADDING } else { 0 },
52                if pad_height { Self::PADDING } else { 0 },
53            ),
54        })
55    }
56
57    pub fn deallocate(&mut self, region: &Region) {
58        self.raw.deallocate(region.allocation.id);
59
60        self.allocations = self.allocations.saturating_sub(1);
61    }
62
63    pub fn is_empty(&self) -> bool {
64        self.allocations == 0
65    }
66
67    pub fn allocations(&self) -> usize {
68        self.allocations
69    }
70}
71
72pub struct Region {
73    allocation: guillotiere::Allocation,
74    padding: core::Size<u32>,
75}
76
77impl Region {
78    pub fn position(&self) -> (u32, u32) {
79        let rectangle = &self.allocation.rectangle;
80
81        (rectangle.min.x as u32, rectangle.min.y as u32)
82    }
83
84    pub fn size(&self) -> core::Size<u32> {
85        let size = self.allocation.rectangle.size();
86
87        core::Size::new(size.width as u32, size.height as u32)
88    }
89
90    pub fn padding(&self) -> crate::core::Size<u32> {
91        self.padding
92    }
93}
94
95impl std::fmt::Debug for Allocator {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        write!(f, "Allocator")
98    }
99}
100
101impl std::fmt::Debug for Region {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        f.debug_struct("Region")
104            .field("id", &self.allocation.id)
105            .field("rectangle", &self.allocation.rectangle)
106            .finish()
107    }
108}