pub struct FrameBuffer { /* private fields */ }Expand description
Double-buffered frame management for flicker-free animation.
FrameBuffer maintains two BrailleGrid buffers:
- Front buffer: The currently displayed frame (rendered to terminal)
- Back buffer: The next frame being prepared (where you draw)
This separation ensures users never see partially drawn frames, eliminating visual tearing and flickering common in terminal graphics.
§Performance
Buffer swapping is an O(1) pointer swap operation (<1ms), not a data copy. This makes it suitable for high frame-rate animations (60+ fps).
§Examples
Basic double-buffering workflow:
use dotmax::animation::FrameBuffer;
// Create a double-buffered frame system (80x24 terminal cells)
let mut buffer = FrameBuffer::new(80, 24);
// Draw to the back buffer
{
let back = buffer.get_back_buffer();
back.clear();
back.set_dot(10, 10).unwrap();
back.set_dot(11, 10).unwrap();
}
// Swap buffers - the back buffer becomes the new front
buffer.swap_buffers();
// Now the front buffer contains what we drew
assert!(buffer.get_front_buffer().get_dot(10 / 2, 10 / 4, 0).is_ok());Animation loop pattern:
use dotmax::animation::FrameBuffer;
use dotmax::TerminalRenderer;
let mut buffer = FrameBuffer::new(80, 24);
let mut renderer = TerminalRenderer::new().unwrap();
loop {
// 1. Clear back buffer
buffer.get_back_buffer().clear();
// 2. Draw next frame
buffer.get_back_buffer().set_dot(10, 10).unwrap();
// 3. Swap buffers (instant)
buffer.swap_buffers();
// 4. Render to terminal
buffer.render(&mut renderer).unwrap();
// 5. Wait for next frame timing
std::thread::sleep(std::time::Duration::from_millis(16)); // ~60fps
}Implementations§
Source§impl FrameBuffer
impl FrameBuffer
Sourcepub fn new(width: usize, height: usize) -> Self
pub fn new(width: usize, height: usize) -> Self
Creates a new double-buffered frame system.
Allocates two BrailleGrid buffers of the specified dimensions.
Both buffers are initialized empty (all dots cleared).
§Arguments
width- Width in terminal cells (characters)height- Height in terminal cells (lines)
§Panics
Panics if BrailleGrid::new() fails (e.g., zero dimensions).
For fallible construction, use the underlying BrailleGrid::new() directly.
§Examples
use dotmax::animation::FrameBuffer;
// Standard terminal size
let buffer = FrameBuffer::new(80, 24);
assert_eq!(buffer.width(), 80);
assert_eq!(buffer.height(), 24);
// Larger buffer for detailed graphics
let large = FrameBuffer::new(200, 50);
assert_eq!(large.width(), 200);Sourcepub fn get_back_buffer(&mut self) -> &mut BrailleGrid
pub fn get_back_buffer(&mut self) -> &mut BrailleGrid
Returns a mutable reference to the back buffer for drawing.
Use this to prepare the next frame. Draw operations on the back buffer do not affect the currently displayed front buffer.
§Examples
use dotmax::animation::FrameBuffer;
let mut buffer = FrameBuffer::new(80, 24);
// Get the back buffer and draw to it
let back = buffer.get_back_buffer();
back.clear();
back.set_dot(0, 0).unwrap(); // Top-left dot
back.set_dot(1, 0).unwrap(); // Adjacent dot
// Front buffer is unchanged until swap_buffers() is calledSourcepub const fn get_front_buffer(&self) -> &BrailleGrid
pub const fn get_front_buffer(&self) -> &BrailleGrid
Returns an immutable reference to the front buffer.
The front buffer contains the currently displayed frame. This is
read-only access; to modify a buffer, use get_back_buffer().
§Examples
use dotmax::animation::FrameBuffer;
let buffer = FrameBuffer::new(80, 24);
// Inspect the front buffer (read-only)
let front = buffer.get_front_buffer();
let (width, height) = front.dimensions();
assert_eq!(width, 80);
assert_eq!(height, 24);Sourcepub fn swap_buffers(&mut self)
pub fn swap_buffers(&mut self)
Atomically swaps the front and back buffers.
After this call:
- The previous back buffer becomes the new front buffer
- The previous front buffer becomes the new back buffer
This is an O(1) pointer swap operation, not a data copy. Typical execution time is <1μs (well under the 1ms target).
§Examples
use dotmax::animation::FrameBuffer;
let mut buffer = FrameBuffer::new(80, 24);
// Draw a dot in the back buffer
buffer.get_back_buffer().set_dot(0, 0).unwrap();
// Swap - now the front buffer has the dot
buffer.swap_buffers();
// The old front (now back) is available for the next frame
buffer.get_back_buffer().clear(); // Prepare for next frameSourcepub fn render(&self, renderer: &mut TerminalRenderer) -> Result<(), DotmaxError>
pub fn render(&self, renderer: &mut TerminalRenderer) -> Result<(), DotmaxError>
Renders the front buffer to the terminal.
Delegates to TerminalRenderer::render() to display the current
front buffer contents. Supports both colored and non-colored grids.
§Arguments
renderer- The terminal renderer to output to
§Errors
Returns DotmaxError::Terminal if terminal I/O fails.
§Examples
use dotmax::animation::FrameBuffer;
use dotmax::TerminalRenderer;
let mut buffer = FrameBuffer::new(80, 24);
let mut renderer = TerminalRenderer::new().unwrap();
// Draw something
buffer.get_back_buffer().set_dot(10, 10).unwrap();
buffer.swap_buffers();
// Render to terminal
buffer.render(&mut renderer).expect("Failed to render");
// Clean up
renderer.cleanup().unwrap();Auto Trait Implementations§
impl Freeze for FrameBuffer
impl RefUnwindSafe for FrameBuffer
impl Send for FrameBuffer
impl Sync for FrameBuffer
impl Unpin for FrameBuffer
impl UnwindSafe for FrameBuffer
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> 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