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 16 glyphs in a 16×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 = 16;
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        (viewport_width / self.cell_size.0, viewport_height / self.cell_size.1)
62    }
63
64    pub fn cell_size(&self) -> (i32, i32) {
65        self.cell_size
66    }
67}
68
69impl Default for FontAtlasData {
70    fn default() -> Self {
71        Self::from_binary(include_bytes!("../atlas/bitmap_font.atlas")).unwrap()
72    }
73}
74
75#[derive(Copy, Clone, Debug, PartialEq)]
76pub struct LineDecoration {
77    /// 0.0 to 1.0, where 0.0 is the top of the text line and 1.0 is the bottom.
78    pub(super) position: f32,
79    /// Thickness of the line as a fraction of the cell height (0.0 to 1.0)
80    pub(super) thickness: f32,
81}
82
83impl LineDecoration {
84    pub fn new(position: f32, thickness: f32) -> Self {
85        Self {
86            position: position.clamp(0.0, 1.0),
87            thickness: thickness.clamp(0.0, 1.0),
88        }
89    }
90}