1use 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 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#[derive(Copy, Clone, Debug, PartialEq, Eq)]
107#[repr(C)]
108pub struct AtlasTile {
109 pub texture_id: AtlasTextureId,
111 pub tile_id: TileId,
113 pub padding: u32,
115 pub bounds: Bounds<DevicePixels>,
117}
118
119#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
121#[repr(C)]
122pub struct AtlasTextureId {
123 pub index: u32,
126 pub kind: AtlasTextureKind,
128}
129
130#[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 Monochrome = 0,
143 Polychrome = 1,
145 Subpixel = 2,
147}
148
149#[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}