Skip to main content

rocketsplash_rt/render/
cls_render_buffer.rs

1// <FILE>crates/rocketsplash-rt/src/render/cls_render_buffer.rs</FILE>
2// <DESC>Flat render buffer with per-cell styling</DESC>
3// <VERS>VERSION: 1.0.0</VERS>
4// <WCTX>Runtime library implementation</WCTX>
5// <CLOG>Add RenderBuffer and RenderCell primitives</CLOG>
6
7use rocketsplash_formats::Rgb;
8
9use crate::TextStyle;
10
11#[derive(Clone, Debug)]
12pub struct RenderBuffer {
13    pub width: usize,
14    pub height: usize,
15    pub cells: Vec<RenderCell>,
16}
17
18#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub struct RenderCell {
20    pub ch: char,
21    pub fg: Option<Rgb>,
22    pub bg: Option<Rgb>,
23    pub style: TextStyle,
24    pub opacity: u8,
25}
26
27impl RenderCell {
28    pub fn empty() -> Self {
29        Self {
30            ch: ' ',
31            fg: None,
32            bg: None,
33            style: TextStyle::empty(),
34            opacity: 0,
35        }
36    }
37
38    pub fn is_empty(&self) -> bool {
39        self.ch == ' ' && self.opacity == 0 && self.fg.is_none() && self.bg.is_none()
40    }
41}
42
43impl RenderBuffer {
44    pub fn new(width: usize, height: usize) -> Self {
45        let size = width.saturating_mul(height);
46        Self {
47            width,
48            height,
49            cells: vec![RenderCell::empty(); size],
50        }
51    }
52
53    pub fn cell(&self, x: usize, y: usize) -> Option<&RenderCell> {
54        self.index(x, y).and_then(|idx| self.cells.get(idx))
55    }
56
57    pub fn cell_mut(&mut self, x: usize, y: usize) -> Option<&mut RenderCell> {
58        self.index(x, y).and_then(|idx| self.cells.get_mut(idx))
59    }
60
61    fn index(&self, x: usize, y: usize) -> Option<usize> {
62        if x >= self.width || y >= self.height {
63            return None;
64        }
65        Some(y * self.width + x)
66    }
67}
68
69// <FILE>crates/rocketsplash-rt/src/render/cls_render_buffer.rs</FILE>
70// <VERS>END OF VERSION: 1.0.0</VERS>