StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | use crate::rendering::atlas::allocator::Allocator; |
| 2 | use crate::rendering::atlas::{AllocatedRegion, AllocationError}; |
| 3 | use anyhow::Result; |
| 4 | use pathfinder_geometry::vector::Vector2I; |
| 5 | |
| 6 | /// Manager that is responsible for allocating areas into a series of textures atlases. |
| 7 | pub(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)] |
| 14 | pub struct TextureId(usize); |
| 15 | |
| 16 | impl 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)] |
| 35 | pub(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 | |
| 42 | impl 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 |