pub struct BrailleGrid { /* private fields */ }Expand description
High-resolution grid using Braille characters
Extracted from crabmusic - Battle-tested rendering engine.
Each terminal cell contains a 2×4 dot pattern (8 dots total), giving us high-resolution graphics in any terminal that supports Unicode braille.
§Architecture (Preserved from crabmusic)
patterns: Vec<u8>- Flat array, each u8 is a bitfield (8 bits = 8 dots)- Dot coordinates: (
dot_x,dot_y) in pixel space (width2 × height4) - Cell coordinates: (
cell_x,cell_y) in terminal space (width × height)
§Dot Indexing (Unicode Braille Standard)
Braille cell (8 dots):
1 4 (Dot1=0x01, Dot4=0x08)
2 5 (Dot2=0x02, Dot5=0x10)
3 6 (Dot3=0x04, Dot6=0x20)
7 8 (Dot7=0x40, Dot8=0x80)§Example
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(40, 20).unwrap();
// Grid is 40×20 cells = 80×80 dot resolution
grid.set_dot(0, 0); // Top-left dot
grid.set_dot(1, 0); // Top-right dot of first cellImplementations§
Source§impl BrailleGrid
impl BrailleGrid
Sourcepub fn new(width: usize, height: usize) -> Result<Self, DotmaxError>
pub fn new(width: usize, height: usize) -> Result<Self, DotmaxError>
Create a new Braille grid
Extracted from crabmusic::BrailleGrid::new() with added validation.
§Arguments
width- Width in terminal cells (must be > 0 and <=MAX_GRID_WIDTH)height- Height in terminal cells (must be > 0 and <=MAX_GRID_HEIGHT)
§Returns
Ok(BrailleGrid)if dimensions are validErr(DotmaxError::InvalidDimensions)if width/height is 0 or exceeds max
§Errors
Returns InvalidDimensions if width or height is 0 or exceeds max allowed dimensions.
§Crabmusic Change
Original crabmusic code never validated dimensions. Dotmax adds validation for security (NFR-S2).
Sourcepub const fn width(&self) -> usize
pub const fn width(&self) -> usize
Get width in terminal cells
Extracted from crabmusic (lines 104-106)
Sourcepub const fn height(&self) -> usize
pub const fn height(&self) -> usize
Get height in terminal cells
Extracted from crabmusic (lines 108-111)
Sourcepub const fn dot_width(&self) -> usize
pub const fn dot_width(&self) -> usize
Get width in dots (2× terminal width)
Extracted from crabmusic (lines 113-116)
Sourcepub const fn dot_height(&self) -> usize
pub const fn dot_height(&self) -> usize
Get height in dots (4× terminal height)
Extracted from crabmusic (lines 118-121)
Sourcepub const fn dimensions(&self) -> (usize, usize)
pub const fn dimensions(&self) -> (usize, usize)
Get the dimensions of the grid (dotmax addition for AC #7)
NEW - Not in crabmusic. Added to satisfy AC #7 requirement.
§Returns
A tuple of (width, height) in terminal cells
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clear all dots
Extracted from crabmusic (lines 124-127) with minor adaptation
Sourcepub fn set_dot(&mut self, dot_x: usize, dot_y: usize) -> Result<(), DotmaxError>
pub fn set_dot(&mut self, dot_x: usize, dot_y: usize) -> Result<(), DotmaxError>
Set a single dot at the specified position
Extracted from crabmusic (lines 144-172) with added error handling.
CRITICAL: This uses PIXEL coordinates (dot_x, dot_y), not cell coordinates.
The grid is width2 × height4 dots.
§Arguments
dot_x- X position in dots (0 to width*2-1)dot_y- Y position in dots (0 to height*4-1)
§Crabmusic Change
Original crabmusic silently ignored out-of-bounds coordinates. Dotmax returns an error for explicit bounds checking (zero panics policy).
§Errors
Returns OutOfBounds if dot coordinates exceed grid dimensions.
Sourcepub fn get_dot(
&self,
x: usize,
y: usize,
dot_index: u8,
) -> Result<bool, DotmaxError>
pub fn get_dot( &self, x: usize, y: usize, dot_index: u8, ) -> Result<bool, DotmaxError>
Get an individual dot value
NEW - Not in crabmusic. Added to match AC #4 requirement.
§Arguments
dot_x- X position in dots (0 to width*2-1)dot_y- Y position in dots (0 to height*4-1)dot_index- Dot position 0-7 in the cell
§Returns
Ok(bool)- The dot value (true = enabled, false = disabled)Err(DotmaxError::OutOfBounds)if coordinates exceed grid dimensionsErr(DotmaxError::InvalidDotIndex)ifdot_index> 7
§Errors
Returns OutOfBounds if dot coordinates exceed grid dimensions, or InvalidDotIndex if dot index > 7.
Sourcepub fn clear_region(
&mut self,
x: usize,
y: usize,
width: usize,
height: usize,
) -> Result<(), DotmaxError>
pub fn clear_region( &mut self, x: usize, y: usize, width: usize, height: usize, ) -> Result<(), DotmaxError>
Clear a rectangular region of the grid
NEW - Not in crabmusic. Added to satisfy AC #6 requirement.
§Arguments
x- Starting column in cells (0-indexed)y- Starting row in cells (0-indexed)width- Width of region to clear in cellsheight- Height of region to clear in cells
§Returns
Ok(())if region was cleared successfullyErr(DotmaxError::OutOfBounds)if region extends beyond grid bounds
§Errors
Returns OutOfBounds if the specified region extends beyond grid dimensions.
Sourcepub fn get_char(&self, cell_x: usize, cell_y: usize) -> char
pub fn get_char(&self, cell_x: usize, cell_y: usize) -> char
Get the Braille character at a cell position
Extracted from crabmusic (lines 338-347)
§Arguments
cell_x- X position in cellscell_y- Y position in cells
§Returns
Character at the cell position:
- If a text character is set (Story 4.4 density rendering), returns that character
- Otherwise, returns braille character representing the dot pattern
Sourcepub fn get_color(&self, cell_x: usize, cell_y: usize) -> Option<Color>
pub fn get_color(&self, cell_x: usize, cell_y: usize) -> Option<Color>
Get the color at a cell position
Extracted from crabmusic (lines 350-357)
Sourcepub fn is_empty(&self, cell_x: usize, cell_y: usize) -> bool
pub fn is_empty(&self, cell_x: usize, cell_y: usize) -> bool
Check if a cell has any dots set
Extracted from crabmusic (lines 360-368)
Sourcepub fn get_raw_patterns(&self) -> &[u8] ⓘ
pub fn get_raw_patterns(&self) -> &[u8] ⓘ
Get raw access to the pattern buffer for serialization.
Story 6.4 - Enables efficient animation frame serialization.
Returns a slice of the internal pattern buffer, where each byte represents one braille cell’s dot pattern (8 bits = 8 dots).
§Returns
A byte slice of length width * height containing dot patterns.
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 5).unwrap();
grid.set_dot(0, 0).unwrap(); // Set top-left dot
let patterns = grid.get_raw_patterns();
assert_eq!(patterns.len(), 50); // 10 * 5 cells
assert_eq!(patterns[0], 0b0000_0001); // First cell has dot 1 setSourcepub fn set_raw_patterns(&mut self, data: &[u8])
pub fn set_raw_patterns(&mut self, data: &[u8])
Set raw pattern buffer from serialized data.
Story 6.4 - Enables efficient animation frame deserialization.
Copies data into the internal pattern buffer. The data slice length
must match width * height. If the length doesn’t match, excess data
is truncated or missing data is left unchanged.
§Arguments
data- Raw pattern bytes to copy into the grid
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 5).unwrap();
let mut patterns = vec![0u8; 50];
patterns[0] = 0b0000_0001; // Set dot 1 in first cell
grid.set_raw_patterns(&patterns);
assert!(grid.get_char(0, 0) == '⠁'); // First cell shows dot 1Sourcepub fn to_unicode_grid(&self) -> Vec<Vec<char>>
pub fn to_unicode_grid(&self) -> Vec<Vec<char>>
Convert entire grid to 2D array of Unicode braille characters
Story 2.2 - Batch conversion for rendering pipeline.
This method converts the entire grid from dot patterns to Unicode braille characters, producing a 2D array that matches the grid dimensions.
Uses the proven dots_to_char() function extracted from crabmusic
(lines 53-56) which applies the Unicode Braille standard formula:
U+2800 + bitfield
§Returns
A 2D vector of Unicode braille characters, where result[y][x] corresponds
to cell (x, y) in the grid.
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(5, 5).unwrap();
grid.set_dot(0, 0).unwrap(); // Top-left dot of cell (0,0)
let chars = grid.to_unicode_grid();
assert_eq!(chars.len(), 5); // 5 rows
assert_eq!(chars[0].len(), 5); // 5 columns
assert_eq!(chars[0][0], '⠁'); // Cell (0,0) has dot 1 set§Performance
Time complexity: O(width × height) - processes each cell once
Allocates: Vec<Vec<char>> with dimensions matching grid size
Sourcepub fn cell_to_braille_char(
&self,
x: usize,
y: usize,
) -> Result<char, DotmaxError>
pub fn cell_to_braille_char( &self, x: usize, y: usize, ) -> Result<char, DotmaxError>
Convert single cell at (x, y) to Unicode braille character
Story 2.2 - Single-cell conversion with bounds validation.
Returns the Unicode braille character for a specific cell, or an error if coordinates are out of bounds.
§Arguments
x- X position in cells (0 to width-1)y- Y position in cells (0 to height-1)
§Returns
Ok(char)- Unicode braille character (U+2800 to U+28FF)Err(DotmaxError::OutOfBounds)- If coordinates exceed grid dimensions
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 10).unwrap();
grid.set_dot(2, 4).unwrap(); // Set a dot in cell (1,1)
let ch = grid.cell_to_braille_char(1, 1).unwrap();
assert!(ch >= '\u{2800}' && ch <= '\u{28FF}'); // Valid braille range§Errors
Returns OutOfBounds if x >= width or y >= height.
Sourcepub fn resize(
&mut self,
new_width: usize,
new_height: usize,
) -> Result<(), DotmaxError>
pub fn resize( &mut self, new_width: usize, new_height: usize, ) -> Result<(), DotmaxError>
Resize the grid to new dimensions
NEW for Story 2.5 - Not in crabmusic. Enables terminal resize handling.
§Arguments
new_width- New width in braille cellsnew_height- New height in braille cells
§Behavior
- Grow: New cells initialized to empty (pattern=0, color=None)
- Shrink: Existing dots outside new bounds are truncated
- Preserve: Dots within overlap region are preserved
- Colors: Color buffer resizes in sync with patterns
§Errors
Returns DotmaxError::InvalidDimensions if:
new_widthornew_heightis 0new_widthornew_heightexceedsMAX_GRID_WIDTH/MAX_GRID_HEIGHT(10,000)
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 10)?;
grid.set_dot(0, 0)?; // Set top-left dot
// Resize to larger dimensions
grid.resize(20, 20)?;
assert_eq!(grid.dimensions(), (20, 20));
// Resize to smaller dimensions
grid.resize(5, 5)?;
assert_eq!(grid.dimensions(), (5, 5));Sourcepub fn enable_color_support(&mut self)
pub fn enable_color_support(&mut self)
Enable color support by allocating color buffer
Story 2.6 - Allocates per-cell color storage.
Note: In the current implementation, the color buffer is always allocated
during BrailleGrid::new(), so this method is a no-op for compatibility
with the AC specification. It ensures the color buffer exists.
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 10).unwrap();
grid.enable_color_support(); // Ensures color support is enabledSourcepub fn set_cell_color(
&mut self,
x: usize,
y: usize,
color: Color,
) -> Result<(), DotmaxError>
pub fn set_cell_color( &mut self, x: usize, y: usize, color: Color, ) -> Result<(), DotmaxError>
Assign RGB color to cell at (x, y)
Story 2.6 - Per-cell color assignment with bounds validation.
Sets the color for a specific cell. The color will be applied when
rendering via TerminalRenderer.
§Arguments
x- X position in cells (0 to width-1)y- Y position in cells (0 to height-1)color- RGB color to assign
§Returns
Ok(())if color was assigned successfullyErr(DotmaxError::OutOfBounds)if coordinates exceed grid dimensions
§Examples
use dotmax::{BrailleGrid, Color};
let mut grid = BrailleGrid::new(10, 10).unwrap();
grid.enable_color_support();
// Set cell (5, 5) to red
grid.set_cell_color(5, 5, Color::rgb(255, 0, 0)).unwrap();
// Verify color was set
assert_eq!(grid.get_color(5, 5), Some(Color::rgb(255, 0, 0)));§Errors
Returns OutOfBounds if x >= width or y >= height.
Sourcepub fn clear_colors(&mut self)
pub fn clear_colors(&mut self)
Reset all colors to None (monochrome)
Story 2.6 - Clear color buffer without deallocating.
Resets all cell colors to None while keeping the color buffer
allocated. This is useful for switching back to monochrome rendering
without disabling color support entirely.
§Examples
use dotmax::{BrailleGrid, Color};
let mut grid = BrailleGrid::new(10, 10).unwrap();
grid.enable_color_support();
// Set some colors
grid.set_cell_color(5, 5, Color::rgb(255, 0, 0)).unwrap();
grid.set_cell_color(7, 7, Color::rgb(0, 255, 0)).unwrap();
// Clear all colors
grid.clear_colors();
// All colors are now None
assert_eq!(grid.get_color(5, 5), None);
assert_eq!(grid.get_color(7, 7), None);Sourcepub fn set_char(
&mut self,
x: usize,
y: usize,
character: char,
) -> Result<(), DotmaxError>
pub fn set_char( &mut self, x: usize, y: usize, character: char, ) -> Result<(), DotmaxError>
Set a text character at a cell position (Story 4.4)
Story 4.4 - Character density-based rendering support.
Sets a text character at the specified cell position. When a character is set, it overrides the braille dot pattern for that cell during rendering. This enables ASCII-art style density rendering as an alternative to binary braille dots.
§Arguments
x- X position in cells (0-indexed)y- Y position in cells (0-indexed)character- The character to set at this position
§Returns
Ok(())if character was set successfullyErr(DotmaxError::OutOfBounds)if coordinates exceed grid dimensions
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 10).unwrap();
// Set character at cell (5, 5)
grid.set_char(5, 5, '@').unwrap();
// Verify character was set
assert_eq!(grid.get_char(5, 5), '@');§Errors
Returns OutOfBounds if x >= width or y >= height.
Sourcepub fn clear_characters(&mut self)
pub fn clear_characters(&mut self)
Clear all text characters (Story 4.4)
Story 4.4 - Reset character buffer for density rendering.
Resets all cell characters to None, restoring default braille dot rendering
mode. This is useful for switching back from density rendering to braille dots
without creating a new grid.
§Examples
use dotmax::BrailleGrid;
let mut grid = BrailleGrid::new(10, 10).unwrap();
// Set some characters
grid.set_char(5, 5, '@').unwrap();
grid.set_char(7, 7, '#').unwrap();
// Clear all characters
grid.clear_characters();
// All characters are now None (braille mode restored)
assert_eq!(grid.get_char(5, 5), '⠀'); // Empty braille patternSourcepub fn apply_color_scheme(
&mut self,
intensities: &[f32],
scheme: &ColorScheme,
) -> Result<(), DotmaxError>
pub fn apply_color_scheme( &mut self, intensities: &[f32], scheme: &ColorScheme, ) -> Result<(), DotmaxError>
Apply a color scheme to a flattened intensity buffer.
Story 5.5 - Convenience method for colorizing intensity data.
Maps a 1D intensity buffer to colors using the provided color scheme,
populating the grid’s color buffer. The intensity buffer must be in
row-major order and match the grid dimensions (width × height).
This method directly modifies the grid’s internal color buffer for maximum performance, avoiding intermediate allocations.
§Arguments
intensities- Flattened 1D intensity buffer (row-major order)scheme- Color scheme for intensity-to-color mapping
§Returns
Ok(())if colors were applied successfullyErr(DotmaxError::BufferSizeMismatch)if buffer length doesn’t match grid size
§Intensity Handling
- Values in range 0.0-1.0 are mapped normally
- Values outside range are clamped (consistent with
ColorScheme::sample) - NaN values are treated as 0.0
- Infinity values are clamped to 0.0 or 1.0
§Examples
use dotmax::{BrailleGrid, ColorScheme};
let mut grid = BrailleGrid::new(4, 3).unwrap();
// Create intensity buffer (4×3 = 12 cells)
let intensities: Vec<f32> = (0..12)
.map(|i| i as f32 / 11.0)
.collect();
// Apply heat map scheme
let scheme = ColorScheme::heat_map();
grid.apply_color_scheme(&intensities, &scheme).unwrap();
// First cell is black (intensity 0.0)
let c0 = grid.get_color(0, 0).unwrap();
assert_eq!(c0.r, 0);
// Last cell is white (intensity 1.0)
let c11 = grid.get_color(3, 2).unwrap();
assert_eq!(c11.r, 255);§Integration with Epic 3 Image Pipeline
use dotmax::{BrailleGrid, ColorScheme};§Performance
Target: <10ms for 80×24 grid (1,920 cells)
§Errors
Returns DotmaxError::BufferSizeMismatch if intensities.len() != width × height.
Source§impl BrailleGrid
impl BrailleGrid
Sourcepub fn render_density(
&mut self,
intensity_buffer: &[f32],
density_set: &DensitySet,
) -> Result<(), DotmaxError>
pub fn render_density( &mut self, intensity_buffer: &[f32], density_set: &DensitySet, ) -> Result<(), DotmaxError>
Render intensity buffer using character density mapping
Renders a buffer of intensity values [0.0, 1.0] onto the grid using character density mapping. Each intensity value is mapped to a character via the provided density set, then rendered at the corresponding grid cell position.
§Arguments
intensity_buffer: Row-major array of f32 intensity values [0.0, 1.0]- Length must equal
grid.width() * grid.height() - Row-major order:
[row0_col0, row0_col1, ..., row1_col0, ...] - 0.0 = darkest (sparse character), 1.0 = brightest (dense character)
- Length must equal
density_set: Character mapping for intensity → character conversion
§Errors
Returns DotmaxError::BufferSizeMismatch if intensity_buffer.len() != grid.width() * grid.height().
§Performance
- Complexity: O(n) where n = width × height cells
- Expected: ~1μs per cell = ~2ms for 80×24 terminal
- Target: <10ms for full terminal rendering
§Examples
use dotmax::{BrailleGrid, density::DensitySet};
// Create grid and generate horizontal gradient
let mut grid = BrailleGrid::new(10, 5).unwrap();
let intensities: Vec<f32> = (0..50)
.map(|i| (i % 10) as f32 / 9.0) // Gradient per row
.collect();
// Render using ASCII density set
let density = DensitySet::ascii();
grid.render_density(&intensities, &density).unwrap();§Error Handling
use dotmax::{BrailleGrid, density::DensitySet};
let mut grid = BrailleGrid::new(10, 5).unwrap();
let wrong_size = vec![0.5_f32; 30]; // Wrong size (expected 50)
let density = DensitySet::simple();
let result = grid.render_density(&wrong_size, &density);
assert!(result.is_err()); // BufferSizeMismatch errorTrait Implementations§
Source§impl Clone for BrailleGrid
impl Clone for BrailleGrid
Source§fn clone(&self) -> BrailleGrid
fn clone(&self) -> BrailleGrid
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for BrailleGrid
impl RefUnwindSafe for BrailleGrid
impl Send for BrailleGrid
impl Sync for BrailleGrid
impl Unpin for BrailleGrid
impl UnwindSafe for BrailleGrid
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more