use retroglyph_core::{Backend, Grid, Rect, Terminal};
#[must_use]
pub fn join_h(grids: &[Grid]) -> Grid {
if grids.is_empty() {
return Grid::new(1, 0);
}
let width = grids
.iter()
.fold(0u16, |acc, g| acc.saturating_add(g.width()));
let height = grids.iter().map(Grid::height).max().unwrap_or(0);
let mut out = Grid::new(width, height);
let mut x_offset = 0u16;
for g in grids {
out.blit(0, g, Rect::new(0, 0, g.width(), g.height()), x_offset, 0);
x_offset = x_offset.saturating_add(g.width());
}
out
}
#[must_use]
pub fn join_v(grids: &[Grid]) -> Grid {
if grids.is_empty() {
return Grid::new(1, 0);
}
let width = grids.iter().map(Grid::width).max().unwrap_or(0);
let height = grids
.iter()
.fold(0u16, |acc, g| acc.saturating_add(g.height()));
let mut out = Grid::new(width, height);
let mut y_offset = 0u16;
for g in grids {
out.blit(0, g, Rect::new(0, 0, g.width(), g.height()), 0, y_offset);
y_offset = y_offset.saturating_add(g.height());
}
out
}
pub fn blit_into<B: Backend>(term: &mut Terminal<B>, grid: &Grid, x: u16, y: u16) {
let rect = Rect::new(0, 0, grid.width(), grid.height());
term.grid_mut().blit(0, grid, rect, x, y);
}
#[cfg(test)]
mod tests {
use retroglyph_core::{Color, Headless, Style, Terminal, Tile};
use super::*;
#[test]
fn join_h_concatenates_and_pads_shorter_grids() {
let mut a = Grid::new(2, 3);
a.put(0, 0, Tile::new('a', Style::default()));
let mut b = Grid::new(2, 1);
b.put(0, 0, Tile::new('b', Style::default()));
let joined = join_h(&[a, b]);
assert_eq!((joined.width(), joined.height()), (4, 3));
assert_eq!(joined.get(0, 0).glyph(), 'a');
assert_eq!(joined.get(2, 0).glyph(), 'b');
assert_eq!(joined.get(2, 1).glyph(), ' ');
}
#[test]
fn join_v_stacks_and_pads_narrower_grids() {
let mut a = Grid::new(3, 1);
a.put(0, 0, Tile::new('a', Style::default()));
let mut b = Grid::new(1, 1);
b.put(0, 0, Tile::new('b', Style::default()));
let joined = join_v(&[a, b]);
assert_eq!((joined.width(), joined.height()), (3, 2));
assert_eq!(joined.get(0, 0).glyph(), 'a');
assert_eq!(joined.get(0, 1).glyph(), 'b');
assert_eq!(joined.get(1, 1).glyph(), ' ');
}
#[test]
fn join_empty_slice_is_essentially_empty() {
let joined = join_h(&[]);
assert_eq!((joined.width(), joined.height()), (1, 0));
let joined = join_v(&[]);
assert_eq!((joined.width(), joined.height()), (1, 0));
}
#[test]
fn join_only_copies_layer_zero() {
let mut a = Grid::new(1, 1);
a.put(0, 0, Tile::new('a', Style::default())); a.put_tile(1, 0, 0, Tile::new('z', Style::default()));
let joined = join_h(&[a]);
assert_eq!(joined.get(0, 0).glyph(), 'a');
assert_eq!(joined.get_tile(1, 0, 0), None); }
#[test]
fn blit_into_stamps_a_grid_onto_a_terminal_at_an_offset() {
let mut grid = Grid::new(2, 2);
grid.put(0, 0, Tile::new('x', Style::new().fg(Color::GREEN)));
grid.put(1, 1, Tile::new('y', Style::default()));
let mut term = Terminal::new(Headless::new(5, 5));
blit_into(&mut term, &grid, 2, 1);
assert_eq!(term.grid().get(2, 1).glyph(), 'x');
assert_eq!(term.grid().get(3, 2).glyph(), 'y');
assert_eq!(term.grid().get(0, 0).glyph(), ' ');
}
}