1use retroglyph_core::grid::Grid;
9
10#[must_use]
19pub fn join_h(grids: &[Grid]) -> Grid {
20 if grids.is_empty() {
21 return Grid::new(1, 0);
22 }
23 let width = grids
24 .iter()
25 .fold(0u16, |acc, g| acc.saturating_add(g.width()));
26 let height = grids.iter().map(Grid::height).max().unwrap_or(0);
27 let mut out = Grid::new(width, height);
28
29 let mut x_offset = 0u16;
30 for g in grids {
31 out.blit(0, g, g.size().to_rect(), x_offset, 0);
32 x_offset = x_offset.saturating_add(g.width());
33 }
34 out
35}
36
37#[must_use]
45pub fn join_v(grids: &[Grid]) -> Grid {
46 if grids.is_empty() {
47 return Grid::new(1, 0);
48 }
49 let width = grids.iter().map(Grid::width).max().unwrap_or(0);
50 let height = grids
51 .iter()
52 .fold(0u16, |acc, g| acc.saturating_add(g.height()));
53 let mut out = Grid::new(width, height);
54
55 let mut y_offset = 0u16;
56 for g in grids {
57 out.blit(0, g, g.size().to_rect(), 0, y_offset);
58 y_offset = y_offset.saturating_add(g.height());
59 }
60 out
61}
62
63#[cfg(test)]
64mod tests {
65 use retroglyph_core::color::Style;
66 use retroglyph_core::grid::Pos;
67 use retroglyph_core::tile::Tile;
68
69 use super::*;
70
71 #[test]
72 fn join_h_concatenates_and_pads_shorter_grids() {
73 let mut a = Grid::new(2, 3);
74 a.put_tile(0, (0, 0), Tile::new('a', Style::default()));
75 let mut b = Grid::new(2, 1);
76 b.put_tile(0, (0, 0), Tile::new('b', Style::default()));
77
78 let joined = join_h(&[a, b]);
79 assert_eq!((joined.width(), joined.height()), (4, 3));
80 assert_eq!(joined[Pos::new(0, 0)].glyph(), 'a');
81 assert_eq!(joined[Pos::new(2, 0)].glyph(), 'b');
82 assert_eq!(joined[Pos::new(2, 1)].glyph(), ' ');
84 }
85
86 #[test]
87 fn join_v_stacks_and_pads_narrower_grids() {
88 let mut a = Grid::new(3, 1);
89 a.put_tile(0, (0, 0), Tile::new('a', Style::default()));
90 let mut b = Grid::new(1, 1);
91 b.put_tile(0, (0, 0), Tile::new('b', Style::default()));
92
93 let joined = join_v(&[a, b]);
94 assert_eq!((joined.width(), joined.height()), (3, 2));
95 assert_eq!(joined[Pos::new(0, 0)].glyph(), 'a');
96 assert_eq!(joined[Pos::new(0, 1)].glyph(), 'b');
97 assert_eq!(joined[Pos::new(1, 1)].glyph(), ' ');
99 }
100
101 #[test]
102 fn join_empty_slice_is_essentially_empty() {
103 let joined = join_h(&[]);
106 assert_eq!((joined.width(), joined.height()), (1, 0));
107 let joined = join_v(&[]);
108 assert_eq!((joined.width(), joined.height()), (1, 0));
109 }
110
111 #[test]
112 fn join_only_copies_layer_zero() {
113 let mut a = Grid::new(1, 1);
114 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]);
118 assert_eq!(joined[Pos::new(0, 0)].glyph(), 'a');
119 assert_eq!(joined.tile(1, (0, 0)), None); }
121}