Seregon/StratoSDK

StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.

Rust/27.3 KB/No license
crates/strato-ui-renderer/src/rendering/atlas/manager.rs
1use crate::rendering::atlas::allocator::Allocator;
2use crate::rendering::atlas::{AllocatedRegion, AllocationError};
3use anyhow::Result;
4use pathfinder_geometry::vector::Vector2I;
5 
6/// Manager that is responsible for allocating areas into a series of textures atlases.
7pub(crate) struct Manager {
8 current_allocator: Allocator,
9 current_texture_id: TextureId,
10 atlas_size: usize,
11}
12 
13#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
14pub struct TextureId(usize);
15 
16impl TextureId {
17 /// Returns the initial [`TextureId`] value to use in a fresh texture atlas
18 /// cache.
19 pub fn initial_value() -> Self {
20 Self(0)
21 }
22 
23 /// Returns the next [`TextureId`] value to use after this one.
24 pub fn next(&self) -> Self {
25 Self(self.0 + 1)
26 }
27 
28 pub fn as_usize(&self) -> usize {
29 self.0
30 }
31}
32 
33/// An offset into a region of a given texture that has been allocated for an item.
34#[derive(Copy, Debug, Clone)]
35pub(crate) struct TextureOffset {
36 /// The unique identifier for the texture.
37 pub texture_id: TextureId,
38 /// The region of the texture that was allocated.
39 pub allocated_region: AllocatedRegion,
40}
41 
42impl Manager {
43 pub fn new(atlas_size: usize) -> Self {
44 Self {
45 current_allocator: Allocator::new(atlas_size),
46 current_texture_id: TextureId::initial_value(),
47 atlas_size,
48 }
49 }
50 
51 /// Allocates a region of `size` into a texture. Returns a [`TextureOffset`] denoting the region
52 /// that was allocated.
53 pub fn insert(&mut self, size: Vector2I) -> Result<TextureOffset> {
54 match self.current_allocator.insert(size) {
55 Ok(allocated_region) => Ok(TextureOffset {
56 texture_id: self.current_texture_id,
57 allocated_region,
58 }),
59 Err(AllocationError::Full) => {
60 self.current_texture_id = self.current_texture_id.next();
61 self.current_allocator = Allocator::new(self.atlas_size);
62 self.insert(size)
63 }
64 Err(insert_error) => Err(insert_error.into()),
65 }
66 }
67}
68