use retroglyph_core::{Grid, Rect};
use crate::Surface;
#[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(surface: &mut Surface<'_>, grid: &Grid, x: u16, y: u16) {
let rect = Rect::new(0, 0, grid.width(), grid.height());
let layer = surface.layer();
surface.grid_mut().blit(layer, grid, rect, x, y);
}
#[cfg(test)]
mod tests {
use retroglyph_core::{Color, Pos, Style, Tile};
use super::*;
#[test]
fn join_h_concatenates_and_pads_shorter_grids() {
let mut a = Grid::new(2, 3);
a.put_tile(0, (0, 0), Tile::new('a', Style::default()));
let mut b = Grid::new(2, 1);
b.put_tile(0, (0, 0), Tile::new('b', Style::default()));
let joined = join_h(&[a, b]);
assert_eq!((joined.width(), joined.height()), (4, 3));
assert_eq!(joined[Pos::new(0, 0)].glyph(), 'a');
assert_eq!(joined[Pos::new(2, 0)].glyph(), 'b');
assert_eq!(joined[Pos::new(2, 1)].glyph(), ' ');
}
#[test]
fn join_v_stacks_and_pads_narrower_grids() {
let mut a = Grid::new(3, 1);
a.put_tile(0, (0, 0), Tile::new('a', Style::default()));
let mut b = Grid::new(1, 1);
b.put_tile(0, (0, 0), Tile::new('b', Style::default()));
let joined = join_v(&[a, b]);
assert_eq!((joined.width(), joined.height()), (3, 2));
assert_eq!(joined[Pos::new(0, 0)].glyph(), 'a');
assert_eq!(joined[Pos::new(0, 1)].glyph(), 'b');
assert_eq!(joined[Pos::new(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_tile(0, (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[Pos::new(0, 0)].glyph(), 'a');
assert_eq!(joined.tile(1, (0, 0)), None); }
#[test]
fn blit_into_stamps_a_grid_onto_a_surface_at_an_offset() {
let mut src = Grid::new(2, 2);
src.put_tile(0, (0, 0), Tile::new('x', Style::new().fg(Color::GREEN)));
src.put_tile(0, (1, 1), Tile::new('y', Style::default()));
let mut dst = Grid::new(5, 5);
let area = Rect::new(0, 0, 5, 5);
blit_into(&mut Surface::new(&mut dst, area, 0), &src, 2, 1);
assert_eq!(dst[Pos::new(2, 1)].glyph(), 'x');
assert_eq!(dst[Pos::new(3, 2)].glyph(), 'y');
assert_eq!(dst[Pos::new(0, 0)].glyph(), ' ');
}
}