Skip to main content

gpui_engine/
atlas.rs

1//! Sprite atlas contract and tile identifiers shared by the engine and its
2//! platform backends.
3
4use crate::{RenderGlyphParams, RenderImageParams, RenderSvgParams};
5use anyhow::Result;
6use gpui_types::{Bounds, DevicePixels, Size};
7use std::{borrow::Cow, ops};
8
9#[derive(PartialEq, Eq, Hash, Clone)]
10#[expect(missing_docs)]
11pub enum AtlasKey {
12    Glyph(RenderGlyphParams),
13    Svg(RenderSvgParams),
14    Image(RenderImageParams),
15}
16
17impl AtlasKey {
18    /// Returns the texture kind for this atlas key.
19    pub fn texture_kind(&self) -> AtlasTextureKind {
20        match self {
21            AtlasKey::Glyph(params) => {
22                if params.is_emoji {
23                    AtlasTextureKind::Polychrome
24                } else if params.subpixel_rendering {
25                    AtlasTextureKind::Subpixel
26                } else {
27                    AtlasTextureKind::Monochrome
28                }
29            }
30            AtlasKey::Svg(_) => AtlasTextureKind::Monochrome,
31            AtlasKey::Image(_) => AtlasTextureKind::Polychrome,
32        }
33    }
34}
35
36impl From<RenderGlyphParams> for AtlasKey {
37    fn from(params: RenderGlyphParams) -> Self {
38        Self::Glyph(params)
39    }
40}
41
42impl From<RenderSvgParams> for AtlasKey {
43    fn from(params: RenderSvgParams) -> Self {
44        Self::Svg(params)
45    }
46}
47
48impl From<RenderImageParams> for AtlasKey {
49    fn from(params: RenderImageParams) -> Self {
50        Self::Image(params)
51    }
52}
53
54#[expect(missing_docs)]
55pub trait PlatformAtlas {
56    fn get_or_insert_with<'a>(
57        &self,
58        key: &AtlasKey,
59        build: &mut dyn FnMut() -> Result<Option<(Size<DevicePixels>, Cow<'a, [u8]>)>>,
60    ) -> Result<Option<AtlasTile>>;
61    fn remove(&self, key: &AtlasKey);
62
63    #[cfg(any(test, feature = "test-support", feature = "bench-support"))]
64    fn contains(&self, _key: &AtlasKey) -> bool {
65        false
66    }
67}
68
69#[doc(hidden)]
70pub struct AtlasTextureList<T> {
71    pub textures: Vec<Option<T>>,
72    pub free_list: Vec<usize>,
73}
74
75impl<T> Default for AtlasTextureList<T> {
76    fn default() -> Self {
77        Self {
78            textures: Vec::default(),
79            free_list: Vec::default(),
80        }
81    }
82}
83
84impl<T> ops::Index<usize> for AtlasTextureList<T> {
85    type Output = Option<T>;
86
87    fn index(&self, index: usize) -> &Self::Output {
88        &self.textures[index]
89    }
90}
91
92impl<T> AtlasTextureList<T> {
93    #[allow(unused)]
94    pub fn drain(&mut self) -> std::vec::Drain<'_, Option<T>> {
95        self.free_list.clear();
96        self.textures.drain(..)
97    }
98
99    #[allow(dead_code)]
100    pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut T> {
101        self.textures.iter_mut().flatten()
102    }
103}
104
105/// A tile within a sprite atlas texture.
106#[derive(Copy, Clone, Debug, PartialEq, Eq)]
107#[repr(C)]
108pub struct AtlasTile {
109    /// The texture this tile belongs to.
110    pub texture_id: AtlasTextureId,
111    /// The unique ID of this tile within its texture.
112    pub tile_id: TileId,
113    /// Padding around the tile content in pixels.
114    pub padding: u32,
115    /// The bounds of this tile within the texture.
116    pub bounds: Bounds<DevicePixels>,
117}
118
119/// Identifies a texture within the sprite atlas.
120#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
121#[repr(C)]
122pub struct AtlasTextureId {
123    // We use u32 instead of usize for Metal Shader Language compatibility
124    /// The index of this texture in the atlas.
125    pub index: u32,
126    /// The kind of content stored in this texture.
127    pub kind: AtlasTextureKind,
128}
129
130/// The kind of content stored in an atlas texture.
131#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
132#[repr(C)]
133#[cfg_attr(
134    all(
135        any(target_os = "linux", target_os = "freebsd"),
136        not(any(feature = "x11", feature = "wayland"))
137    ),
138    allow(dead_code)
139)]
140pub enum AtlasTextureKind {
141    /// Single-channel coverage.
142    Monochrome = 0,
143    /// Full-color pixels.
144    Polychrome = 1,
145    /// Subpixel-antialiased coverage.
146    Subpixel = 2,
147}
148
149/// The unique ID of a tile within its texture.
150#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
151#[repr(C)]
152pub struct TileId(pub u32);
153
154impl From<etagere::AllocId> for TileId {
155    fn from(id: etagere::AllocId) -> Self {
156        Self(id.serialize())
157    }
158}
159
160impl From<TileId> for etagere::AllocId {
161    fn from(id: TileId) -> Self {
162        Self::deserialize(id.0)
163    }
164}