DifferentialRenderer

Struct DifferentialRenderer 

Source
pub struct DifferentialRenderer { /* private fields */ }
Expand description

Optimized renderer that only outputs changed cells.

DifferentialRenderer compares the current frame to the previous frame and renders only the cells that have changed. For typical animations with small moving objects on static backgrounds, this reduces terminal I/O by 60-80% or more.

§Performance

  • Full render at 80×24: 1920 cells, ~1920 escape codes
  • Differential with 5% changes: ~96 cells, ~96 escape codes
  • Typical I/O reduction: 60-95%

§Example

use dotmax::animation::DifferentialRenderer;
use dotmax::{BrailleGrid, TerminalRenderer};

let mut diff_renderer = DifferentialRenderer::new();
let mut terminal = TerminalRenderer::new()?;

// First frame renders fully (no previous frame)
let frame1 = BrailleGrid::new(80, 24)?;
diff_renderer.render_diff(&frame1, &mut terminal)?;

// Subsequent frames render only changes
let mut frame2 = BrailleGrid::new(80, 24)?;
frame2.set_dot(10, 10)?;  // One changed cell
diff_renderer.render_diff(&frame2, &mut terminal)?;  // Only outputs one cell!

Implementations§

Source§

impl DifferentialRenderer

Source

pub const fn new() -> Self

Creates a new differential renderer.

The first call to render_diff() will render the full frame since there’s no previous frame to compare against.

§Examples
use dotmax::animation::DifferentialRenderer;

let renderer = DifferentialRenderer::new();
// First render_diff() call will render the entire frame
Source

pub fn render_diff( &mut self, current: &BrailleGrid, renderer: &mut TerminalRenderer, ) -> Result<(), DotmaxError>

Renders only the cells that changed since the last frame.

Compares current to the stored previous frame and outputs only the changed cells using ANSI cursor positioning.

§Behavior
  • First call: Renders entire grid (no previous frame)
  • Dimension mismatch: Renders entire grid (auto-invalidates)
  • Normal operation: Renders only changed cells
§Arguments
  • current - The current frame to render
  • renderer - The terminal renderer for full-frame fallback
§Returns
  • Ok(()) - Render completed successfully
  • Err(DotmaxError) - Terminal I/O error
§Errors

Returns DotmaxError::Terminal if terminal I/O operations fail (cursor positioning or character output).

§Examples
use dotmax::animation::DifferentialRenderer;
use dotmax::{BrailleGrid, TerminalRenderer};

let mut diff = DifferentialRenderer::new();
let mut terminal = TerminalRenderer::new()?;

let frame = BrailleGrid::new(80, 24)?;
diff.render_diff(&frame, &mut terminal)?;
Source

pub fn invalidate(&mut self)

Forces a full render on the next render_diff() call.

Use this after terminal resize, mode changes, or when the entire screen needs to be refreshed.

§Examples
use dotmax::animation::DifferentialRenderer;

let mut renderer = DifferentialRenderer::new();
// ... after some renders ...
renderer.invalidate();  // Next render_diff() will render full frame
Source

pub fn count_changed_cells( &self, current: &BrailleGrid, previous: &BrailleGrid, ) -> usize

Returns the number of cells that would change between two frames.

This is useful for benchmarking and debugging to understand how much I/O reduction differential rendering provides.

§Arguments
  • current - The current frame
  • previous - The previous frame to compare against
§Returns

The number of cells that differ between the two frames.

§Examples
use dotmax::animation::DifferentialRenderer;
use dotmax::BrailleGrid;

let renderer = DifferentialRenderer::new();

let mut frame1 = BrailleGrid::new(80, 24).unwrap();
let mut frame2 = BrailleGrid::new(80, 24).unwrap();
frame2.set_dot(10, 10).unwrap();

let changed = renderer.count_changed_cells(&frame2, &frame1);
assert_eq!(changed, 1);  // Only one cell changed
Source

pub const fn has_previous_frame(&self) -> bool

Returns whether the renderer has a cached previous frame.

§Returns
  • true - A previous frame is cached (differential rendering enabled)
  • false - No previous frame (next render will be full)
§Examples
use dotmax::animation::DifferentialRenderer;

let renderer = DifferentialRenderer::new();
assert!(!renderer.has_previous_frame());

Trait Implementations§

Source§

impl Clone for DifferentialRenderer

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for DifferentialRenderer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for DifferentialRenderer

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more