beamterm_data/
atlas.rs

1use std::fmt::Debug;
2
3use compact_str::CompactString;
4
5use crate::{Deserializer, FontAtlasDeserializationError, Glyph, Serializable};
6
7/// Font atlas data for GPU-accelerated terminal rendering.
8///
9/// Contains a pre-rasterized font atlas stored as a 2D texture array, where each layer
10/// holds 32 glyphs in a 32×1 grid. The atlas includes multiple font styles (normal, bold,
11/// italic, bold+italic) and full Unicode support including emoji.
12#[derive(PartialEq)]
13pub struct FontAtlasData {
14    /// The name of the font
15    pub font_name: CompactString,
16    /// The font size in points
17    pub font_size: f32,
18    /// Width, height and depth of the texture in pixels
19    pub texture_dimensions: (i32, i32, i32),
20    /// Width and height of each character cell
21    pub cell_size: (i32, i32),
22    /// Underline configuration
23    pub underline: LineDecoration,
24    /// Strikethrough configuration
25    pub strikethrough: LineDecoration,
26    /// The glyphs in the font
27    pub glyphs: Vec<Glyph>,
28    /// The 3d texture data containing the font glyphs
29    pub texture_data: Vec<u8>,
30}
31
32impl Debug for FontAtlasData {
33    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34        f.debug_struct("FontAtlasData")
35            .field("font_name", &self.font_name)
36            .field("font_size", &self.font_size)
37            .field("texture_dimensions", &self.texture_dimensions)
38            .field("cell_size", &self.cell_size)
39            .field("glyphs_count", &self.glyphs.len())
40            .field("texture_data_kb", &(self.texture_data.len() * 4 / 1024))
41            .finish()
42    }
43}
44
45impl FontAtlasData {
46    pub const PADDING: i32 = 1;
47    pub const CELLS_PER_SLICE: i32 = 32;
48
49    pub fn from_binary(serialized: &[u8]) -> Result<Self, FontAtlasDeserializationError> {
50        let mut deserializer = Deserializer::new(serialized);
51        FontAtlasData::deserialize(&mut deserializer).map_err(|e| FontAtlasDeserializationError {
52            message: format!("Failed to deserialize font atlas: {}", e.message),
53        })
54    }
55
56    pub fn to_binary(&self) -> Vec<u8> {
57        self.serialize()
58    }
59
60    pub fn terminal_size(&self, viewport_width: i32, viewport_height: i32) -> (i32, i32) {
61        (
62            viewport_width / self.cell_size.0,
63            viewport_height / self.cell_size.1,
64        )
65    }
66
67    pub fn cell_size(&self) -> (i32, i32) {
68        self.cell_size
69    }
70}
71
72impl Default for FontAtlasData {
73    fn default() -> Self {
74        Self::from_binary(include_bytes!("../atlas/bitmap_font.atlas")).unwrap()
75    }
76}
77
78#[derive(Copy, Clone, Debug, PartialEq)]
79pub struct LineDecoration {
80    /// 0.0 to 1.0, where 0.0 is the top of the text line and 1.0 is the bottom.
81    pub position: f32,
82    /// Thickness of the line as a fraction of the cell height (0.0 to 1.0)
83    pub thickness: f32,
84}
85
86impl LineDecoration {
87    pub fn new(position: f32, thickness: f32) -> Self {
88        Self {
89            position: position.clamp(0.0, 1.0),
90            thickness: thickness.clamp(0.0, 1.0),
91        }
92    }
93}