1#[cfg(feature = "egc")]
4use crate::style::Style;
5use crate::tile::Tile;
6#[cfg(feature = "egc")]
7use crate::tile::TileFlags;
8#[cfg(feature = "egc")]
9use crate::tile::cap_grapheme;
10use alloc::vec::Vec;
11use core::fmt;
12use core::ops::{Index, IndexMut};
13use grixy::buf::GridBuf;
14use grixy::ops::layout::RowMajor;
15use grixy::ops::{ExactSizeGrid, GridDiff, GridRead, GridWrite};
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, PartialOrd, Ord)]
19pub struct Size {
20 pub width: u16,
22 pub height: u16,
24}
25
26pub type Pos = ixy::Pos<u16>;
32
33pub type Rect = ixy::Rect<u16>;
35
36impl From<(u16, u16)> for Size {
37 fn from((width, height): (u16, u16)) -> Self {
38 Self { width, height }
39 }
40}
41
42impl From<Size> for (u16, u16) {
43 fn from(s: Size) -> Self {
44 (s.width, s.height)
45 }
46}
47
48fn to_grixy_pos(pos: Pos) -> grixy::core::Pos {
53 grixy::core::Pos::new(usize::from(pos.x), usize::from(pos.y))
54}
55
56#[allow(clippy::missing_const_for_fn)]
57fn from_grixy_pos(pos: grixy::core::Pos) -> Pos {
58 #[allow(clippy::cast_possible_truncation)]
59 Pos::new(pos.x as u16, pos.y as u16)
60}
61
62pub struct Cells<'a> {
68 iter: core::iter::Enumerate<core::slice::Iter<'a, Tile>>,
69 width: usize,
70}
71
72impl<'a> Iterator for Cells<'a> {
73 type Item = (u16, u16, &'a Tile);
74
75 fn next(&mut self) -> Option<Self::Item> {
76 self.iter.next().map(|(i, tile)| {
77 #[allow(clippy::cast_possible_truncation)]
78 let x = (i % self.width) as u16;
79 #[allow(clippy::cast_possible_truncation)]
80 let y = (i / self.width) as u16;
81 (x, y, tile)
82 })
83 }
84}
85
86pub struct CellsMut<'a> {
88 iter: core::iter::Enumerate<core::slice::IterMut<'a, Tile>>,
89 width: usize,
90}
91
92impl<'a> Iterator for CellsMut<'a> {
93 type Item = (u16, u16, &'a mut Tile);
94
95 fn next(&mut self) -> Option<Self::Item> {
96 self.iter.next().map(|(i, tile)| {
97 #[allow(clippy::cast_possible_truncation)]
98 let x = (i % self.width) as u16;
99 #[allow(clippy::cast_possible_truncation)]
100 let y = (i / self.width) as u16;
101 (x, y, tile)
102 })
103 }
104}
105
106pub(crate) struct LayerBuf {
115 pub(crate) buf: GridBuf<Tile, Vec<Tile>, RowMajor>,
116}
117
118impl LayerBuf {
119 fn new(width: u16, height: u16) -> Self {
120 let n = usize::from(width) * usize::from(height);
121 Self {
122 buf: GridBuf::from_buffer(alloc::vec![Tile::default(); n], usize::from(width)),
123 }
124 }
125}
126
127pub struct Grid {
140 width: u16,
141 height: u16,
142 layers: Vec<Option<LayerBuf>>,
145}
146
147impl Grid {
152 fn layer(&self, id: u8) -> Option<&LayerBuf> {
154 self.layers[usize::from(id)].as_ref()
155 }
156
157 fn layer_or_alloc(&mut self, id: u8) -> &mut LayerBuf {
159 let idx = usize::from(id);
160 if self.layers[idx].is_none() {
161 self.layers[idx] = Some(LayerBuf::new(self.width, self.height));
162 }
163 self.layers[idx].as_mut().unwrap()
164 }
165
166 fn layer0(&self) -> &LayerBuf {
168 self.layers[0].as_ref().unwrap()
170 }
171
172 fn layer0_mut(&mut self) -> &mut LayerBuf {
174 self.layers[0].as_mut().unwrap()
175 }
176}
177
178impl Grid {
183 #[must_use]
188 pub fn new(width: u16, height: u16) -> Self {
189 let mut layers = alloc::vec![];
190 layers.resize_with(256, || None);
191 layers[0] = Some(LayerBuf::new(width, height));
192 Self {
193 width,
194 height,
195 layers,
196 }
197 }
198
199 #[must_use]
201 pub const fn width(&self) -> u16 {
202 self.width
203 }
204
205 #[must_use]
207 pub const fn height(&self) -> u16 {
208 self.height
209 }
210
211 pub fn put(&mut self, x: u16, y: u16, tile: Tile) {
217 let pos = to_grixy_pos(Pos::new(x, y));
218 let lb = self.layer0_mut();
219 assert!(
220 lb.buf.contains(pos),
221 "coordinates out of bounds: ({x}, {y})"
222 );
223 lb.buf[pos] = tile;
224 }
225
226 #[must_use]
232 pub fn get(&self, x: u16, y: u16) -> &Tile {
233 &self.layer0().buf[to_grixy_pos(Pos::new(x, y))]
234 }
235
236 pub fn checked_put(&mut self, x: u16, y: u16, tile: Tile) -> Option<()> {
240 let pos = to_grixy_pos(Pos::new(x, y));
241 let lb = self.layer0_mut();
242 if lb.buf.contains(pos) {
243 lb.buf[pos] = tile;
244 Some(())
245 } else {
246 None
247 }
248 }
249
250 #[must_use]
254 pub fn checked_get(&self, x: u16, y: u16) -> Option<&Tile> {
255 let pos = to_grixy_pos(Pos::new(x, y));
256 self.layer0().buf.get(pos)
257 }
258
259 pub fn checked_get_mut(&mut self, x: u16, y: u16) -> Option<&mut Tile> {
264 let pos = to_grixy_pos(Pos::new(x, y));
265 self.layer0_mut().buf.get_mut(pos)
266 }
267
268 #[must_use]
272 pub fn cells(&self, layer: u8) -> Option<Cells<'_>> {
273 let lb = self.layer(layer)?;
274 Some(Cells {
275 iter: lb.buf.as_ref().iter().enumerate(),
276 width: usize::from(self.width),
277 })
278 }
279
280 pub fn cells_mut(&mut self, layer: u8) -> CellsMut<'_> {
284 let width = usize::from(self.width);
285 let lb = self.layer_or_alloc(layer);
286 CellsMut {
287 iter: lb.buf.as_mut().iter_mut().enumerate(),
288 width,
289 }
290 }
291
292 pub fn clear(&mut self, layer: u8) {
296 if let Some(lb) = self.layers[usize::from(layer)].as_mut() {
297 lb.buf.clear();
298 }
299 }
300
301 pub fn resize(&mut self, width: u16, height: u16) {
307 self.width = width;
308 self.height = height;
309 for layer in self.layers.iter_mut().flatten() {
310 layer.buf.resize(usize::from(width), usize::from(height));
311 }
312 }
313
314 #[cfg(feature = "egc")]
343 pub fn write_grapheme(&mut self, x: u16, y: u16, grapheme: &str, style: Style) {
344 use unicode_width::UnicodeWidthStr;
345
346 let width = u16::try_from(grapheme.width()).expect("grapheme width exceeds u16");
347 if width == 0 {
348 return;
349 }
350
351 let w = usize::from(self.width);
353 let cap = w * usize::from(self.height);
354 let idx = usize::from(y) * w + usize::from(x);
355 if idx >= cap {
356 return;
357 }
358
359 if width == 2 && x.saturating_add(1) as usize >= w {
362 return;
363 }
364
365 self.clear_overlap(x, y, width);
368
369 let grid_w = usize::from(self.width);
371 let idx = usize::from(y) * grid_w + usize::from(x);
372
373 let lb = self.layer0_mut();
374 let mut chars = grapheme.chars();
376 let first = chars.next().unwrap_or(' ');
377 let has_extra = chars.next().is_some();
378 let extra = if has_extra {
379 Some(alloc::sync::Arc::new(cap_grapheme(grapheme)))
380 } else {
381 None
382 };
383 let flags = if width == 2 {
384 TileFlags::WIDE_CHAR
385 } else {
386 TileFlags::empty()
387 };
388
389 lb.buf.as_mut()[idx].glyph = first;
390 lb.buf.as_mut()[idx].style = style;
391 lb.buf.as_mut()[idx].extra = extra;
392 lb.buf.as_mut()[idx].flags = flags;
393
394 if width == 2 {
396 let spacer_idx = usize::from(y) * grid_w + usize::from(x + 1);
397 if spacer_idx < cap {
398 let spacer = &mut lb.buf.as_mut()[spacer_idx];
399 spacer.glyph = ' ';
400 spacer.style = style;
401 spacer.extra = None;
402 spacer.flags = TileFlags::WIDE_CHAR_SPACER;
403 }
404 }
405 }
406
407 #[cfg(feature = "egc")]
412 fn clear_overlap(&mut self, x: u16, y: u16, width: u16) {
413 let w = usize::from(self.width);
414 let cap = w * usize::from(self.height);
415 let lb = self.layer0_mut();
416 for cx in x..x.saturating_add(width) {
417 let idx = usize::from(y) * w + usize::from(cx);
418 if idx >= cap {
419 continue;
420 }
421 let flags = lb.buf.as_ref()[idx].flags;
423
424 if flags.contains(TileFlags::WIDE_CHAR_SPACER) && cx > 0 {
425 let pidx = usize::from(y) * w + usize::from(cx - 1);
426 if pidx < cap {
427 lb.buf.as_mut()[pidx].reset();
428 }
429 }
430
431 if flags.contains(TileFlags::WIDE_CHAR) {
432 let sidx = usize::from(y) * w + usize::from(cx + 1);
433 if sidx < cap {
434 lb.buf.as_mut()[sidx].reset();
435 }
436 }
437 }
438 }
439}
440
441impl Grid {
446 pub fn put_tile(&mut self, layer: u8, x: u16, y: u16, tile: Tile) -> Option<()> {
453 let pos = to_grixy_pos(Pos::new(x, y));
454 let lb = self.layer_or_alloc(layer);
455 if !lb.buf.contains(pos) {
456 return None;
457 }
458 lb.buf[pos] = tile;
459 Some(())
460 }
461
462 #[must_use]
465 pub fn get_tile(&self, layer: u8, x: u16, y: u16) -> Option<&Tile> {
466 let pos = to_grixy_pos(Pos::new(x, y));
467 self.layer(layer)?.buf.get(pos)
468 }
469
470 pub fn layers(&self) -> impl Iterator<Item = (u8, Pos, &Tile)> + '_ {
476 let mut results = Vec::new();
477 for id in 0u8..=255 {
478 if let Some(lb) = self.layer(id) {
479 #[allow(clippy::cast_possible_truncation)]
480 for (i, tile) in lb.buf.as_ref().iter().enumerate() {
481 let x = (i % usize::from(self.width)) as u16;
482 let y = (i / usize::from(self.width)) as u16;
483 results.push((id, Pos::new(x, y), tile));
484 }
485 }
486 }
487 results.into_iter()
488 }
489
490 pub fn clear_all(&mut self) {
492 for layer in self.layers.iter_mut().flatten() {
493 layer.buf.clear();
494 }
495 }
496
497 pub fn diff<'a>(&'a self, other: &'a Self) -> impl Iterator<Item = (u8, Pos, &'a Tile)> + 'a {
506 let mut results = Vec::new();
507 for id in 0u8..=255 {
508 match (self.layer(id), other.layer(id)) {
509 (None, _) => {}
510 (Some(cur), None) => {
511 #[allow(clippy::cast_possible_truncation)]
514 for (i, tile) in cur.buf.as_ref().iter().enumerate() {
515 let x = (i % usize::from(self.width)) as u16;
516 let y = (i / usize::from(self.width)) as u16;
517 results.push((id, Pos::new(x, y), tile));
518 }
519 }
520 (Some(cur), Some(prev)) => {
521 for (pos, tile) in cur.buf.diff(&prev.buf) {
522 results.push((id, from_grixy_pos(pos), tile));
523 }
524 }
525 }
526 }
527 results.into_iter()
528 }
529}
530
531impl Index<Pos> for Grid {
536 type Output = Tile;
537
538 fn index(&self, pos: Pos) -> &Tile {
539 &self.layer0().buf[to_grixy_pos(pos)]
540 }
541}
542
543impl IndexMut<Pos> for Grid {
544 fn index_mut(&mut self, pos: Pos) -> &mut Tile {
545 let pos = to_grixy_pos(pos);
546 &mut self.layer0_mut().buf[pos]
547 }
548}
549
550impl fmt::Display for Grid {
555 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
556 for y in 0..self.height() {
557 for x in 0..self.width() {
558 let tile = self.get(x, y);
559 #[cfg(feature = "egc")]
560 let is_spacer = tile.flags.contains(TileFlags::WIDE_CHAR_SPACER);
561 #[cfg(not(feature = "egc"))]
562 let is_spacer = tile.glyph == '\0';
563 let c = if is_spacer {
564 ' ' } else if tile.glyph == ' ' {
566 '·' } else {
568 tile.glyph
569 };
570 write!(f, "{c}")?;
571 }
572 writeln!(f)?;
573 }
574 Ok(())
575 }
576}
577
578impl fmt::Debug for Grid {
579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580 f.debug_struct("Grid")
581 .field("width", &self.width)
582 .field("height", &self.height)
583 .finish_non_exhaustive()
584 }
585}
586
587#[cfg(test)]
592mod tests {
593 use super::*;
594
595 #[test]
598 fn test_grid_new() {
599 let grid = Grid::new(80, 25);
600 assert_eq!(grid.width(), 80);
601 assert_eq!(grid.height(), 25);
602 }
603
604 #[test]
605 fn test_grid_put_get() {
606 let mut grid = Grid::new(10, 10);
607 let tile = Tile::default().with_glyph('X');
608
609 grid.put(5, 5, tile);
610 assert_eq!(grid.get(5, 5).glyph(), 'X');
611 }
612
613 #[test]
614 fn test_grid_checked_put_get() {
615 let mut grid = Grid::new(10, 10);
616 let tile = Tile::default().with_glyph('Y');
617
618 assert!(grid.checked_put(5, 5, tile).is_some());
619 assert_eq!(grid.checked_get(5, 5).unwrap().glyph(), 'Y');
620
621 assert!(grid.checked_get(10, 0).is_none());
622 assert!(grid.checked_put(0, 10, Tile::default()).is_none());
623 }
624
625 #[test]
626 #[should_panic(expected = "coordinates out of bounds")]
627 fn test_grid_panic_put() {
628 let mut grid = Grid::new(10, 10);
629 grid.put(10, 0, Tile::default());
630 }
631
632 #[test]
633 fn test_grid_diff() {
634 let mut g1 = Grid::new(2, 2);
635 let g2 = Grid::new(2, 2);
636
637 g1.put(0, 0, Tile::default().with_glyph('A'));
638
639 let diffs: Vec<_> = g1.diff(&g2).collect();
640 assert_eq!(diffs.len(), 1);
641 assert_eq!(diffs[0], (0, Pos::new(0, 0), g1.get(0, 0)));
642 }
643
644 #[test]
645 fn test_grid_resize_expand() {
646 let mut grid = Grid::new(3, 3);
647 grid.put(1, 1, Tile::default().with_glyph('X'));
648 grid.resize(6, 6);
649 assert_eq!(grid.width(), 6);
650 assert_eq!(grid.height(), 6);
651 assert_eq!(grid.get(1, 1).glyph(), 'X'); assert_eq!(grid.get(5, 5).glyph(), ' '); }
654
655 #[test]
656 fn test_grid_resize_shrink() {
657 let mut grid = Grid::new(10, 10);
658 grid.put(1, 1, Tile::default().with_glyph('A'));
659 grid.resize(5, 5);
660 assert_eq!(grid.width(), 5);
661 assert_eq!(grid.height(), 5);
662 assert_eq!(grid.get(1, 1).glyph(), 'A'); }
664
665 #[test]
666 fn test_grid_resize_preserves_overlap() {
667 let mut grid = Grid::new(4, 4);
668 grid.put(0, 0, Tile::default().with_glyph('@'));
669 grid.put(3, 3, Tile::default().with_glyph('X'));
670 grid.resize(3, 3); assert_eq!(grid.get(0, 0).glyph(), '@');
672 assert_eq!(grid.get(2, 2).glyph(), ' '); }
674
675 #[test]
676 fn test_grid_display() {
677 let mut grid = Grid::new(3, 2);
678 grid.put(0, 0, Tile::default().with_glyph('A'));
679
680 let s = alloc::format!("{grid}");
681 assert_eq!(s, "A··\n···\n");
682 }
683
684 #[test]
685 fn test_grid_cells_count() {
686 let grid = Grid::new(4, 3);
687 assert_eq!(grid.cells(0).unwrap().count(), 12);
688 }
689
690 #[test]
691 fn test_grid_cells_coordinates() {
692 let grid = Grid::new(3, 2);
693 let coords: Vec<(u16, u16)> = grid.cells(0).unwrap().map(|(x, y, _)| (x, y)).collect();
694 assert_eq!(
695 coords,
696 vec![(0, 0), (1, 0), (2, 0), (0, 1), (1, 1), (2, 1),]
697 );
698 }
699
700 #[test]
701 fn test_grid_cells_mut() {
702 use crate::style::Style;
703 let mut grid = Grid::new(2, 2);
704 for (x, y, tile) in grid.cells_mut(0) {
705 #[allow(clippy::cast_possible_truncation)]
706 let idx = (y * 2 + x) as u8;
707 *tile = Tile::new(char::from(b'A' + idx), Style::default());
708 }
709 assert_eq!(grid.get(0, 0).glyph(), 'A');
710 assert_eq!(grid.get(1, 0).glyph(), 'B');
711 assert_eq!(grid.get(0, 1).glyph(), 'C');
712 assert_eq!(grid.get(1, 1).glyph(), 'D');
713 }
714
715 #[test]
716 fn test_rect_contains() {
717 let r = Rect::new(2, 3, 4, 5);
718 assert!(r.contains_pos(Pos::new(2, 3)));
719 assert!(r.contains_pos(Pos::new(5, 7)));
720 assert!(!r.contains_pos(Pos::new(6, 3))); assert!(!r.contains_pos(Pos::new(2, 8))); assert!(!r.contains_pos(Pos::new(1, 3)));
723 }
724
725 #[test]
726 fn test_rect_area() {
727 assert_eq!(Rect::new(0, 0, 5, 3).area(), 15);
728 assert_eq!(Rect::default().area(), 0);
729 }
730
731 #[test]
732 fn test_rect_top_left_bottom_right() {
733 let r = Rect::new(1, 2, 3, 4);
734 assert_eq!(r.top_left(), Pos::new(1, 2));
735 assert_eq!(r.bottom_right(), Pos::new(4, 6));
736 }
737
738 #[test]
739 fn test_rect_intersects() {
740 let a = Rect::new(0, 0, 4, 4);
741 let b = Rect::new(2, 2, 4, 4);
742 let c = Rect::new(4, 0, 4, 4); assert!(!a.intersect(b).is_empty());
744 assert!(a.intersect(c).is_empty());
745 }
746
747 #[test]
748 fn test_rect_positions() {
749 let r = Rect::new(1, 2, 2, 2);
750 let pts: Vec<Pos> = r.pos_iter().collect();
751 assert_eq!(
752 pts,
753 vec![
754 Pos::new(1, 2),
755 Pos::new(2, 2),
756 Pos::new(1, 3),
757 Pos::new(2, 3),
758 ]
759 );
760 }
761
762 #[test]
763 fn test_index_position() {
764 let mut grid = Grid::new(5, 5);
765 let pos = Pos::new(2, 3);
766 grid[pos] = Tile::default().with_glyph('Z');
767 assert_eq!(grid[pos].glyph(), 'Z');
768 }
769
770 #[test]
771 fn test_position_from_tuple() {
772 let p: Pos = (3u16, 7u16).into();
773 assert_eq!(p, Pos::new(3, 7));
774 let t: (u16, u16) = p.into();
775 assert_eq!(t, (3, 7));
776 }
777
778 #[test]
779 fn test_size_from_tuple() {
780 let s: Size = (80u16, 25u16).into();
781 assert_eq!(
782 s,
783 Size {
784 width: 80,
785 height: 25
786 }
787 );
788 let t: (u16, u16) = s.into();
789 assert_eq!(t, (80, 25));
790 }
791
792 #[test]
793 fn test_position_ord_row_major() {
794 let mut positions = vec![Pos::new(5, 0), Pos::new(0, 1), Pos::new(3, 0)];
795 positions.sort();
796 assert_eq!(
797 positions,
798 vec![Pos::new(3, 0), Pos::new(5, 0), Pos::new(0, 1),]
799 );
800 }
801
802 #[test]
803 fn test_size_ord() {
804 assert!(
805 Size {
806 width: 1,
807 height: 2
808 } < Size {
809 width: 2,
810 height: 1
811 }
812 );
813 }
814
815 #[test]
818 fn test_grid_layer_zero_always_allocated() {
819 let g = Grid::new(5, 5);
820 assert!(g.layer(0).is_some());
821 for id in 1u8..=5 {
822 assert!(g.layer(id).is_none(), "layer {id} should be None");
823 }
824 }
825
826 #[test]
827 fn test_grid_put_tile_allocates_layer() {
828 let mut g = Grid::new(5, 5);
829 g.put_tile(3, 0, 0, Tile::new('@', Style::default()));
830 assert!(g.layer(3).is_some());
831 assert!(g.layer(4).is_none());
832 }
833
834 #[test]
835 fn test_grid_diff_empty_when_identical() {
836 let g = Grid::new(5, 5);
837 let prev = Grid::new(5, 5);
838 assert_eq!(g.diff(&prev).count(), 0);
839 }
840
841 #[test]
842 fn test_grid_diff_reports_changed_cell() {
843 let mut cur = Grid::new(5, 5);
844 let prev = Grid::new(5, 5);
845 cur.put_tile(0, 2, 3, Tile::new('X', Style::default()));
846 let diffs: Vec<_> = cur.diff(&prev).collect();
847 assert_eq!(diffs.len(), 1);
848 assert_eq!(diffs[0].0, 0);
849 assert_eq!(diffs[0].1, Pos::new(2, 3));
850 assert_eq!(diffs[0].2.glyph, 'X');
851 }
852
853 #[test]
854 fn test_grid_diff_new_layer_yields_all_cells() {
855 let mut cur = Grid::new(3, 4);
856 let prev = Grid::new(3, 4);
857 cur.put_tile(1, 0, 0, Tile::new('A', Style::default()));
858 let diffs: Vec<_> = cur.diff(&prev).collect();
859 assert_eq!(diffs.len(), 12);
861 assert!(diffs.iter().all(|(l, _, _)| *l == 1));
862 }
863
864 #[test]
865 fn test_grid_diff_layer_major_order() {
866 let mut cur = Grid::new(3, 3);
867 let prev = Grid::new(3, 3);
868 cur.put_tile(2, 0, 0, Tile::new('B', Style::default()));
869 cur.put_tile(0, 1, 0, Tile::new('A', Style::default()));
870 let layers: Vec<u8> = cur.diff(&prev).map(|(l, _, _)| l).collect();
871 assert_eq!(layers[0], 0);
873 assert!(layers[1..].iter().all(|&l| l == 2));
874 }
875
876 #[test]
877 fn test_grid_put_and_get_on_layer_2() {
878 use crate::style::Style;
879 let mut g = Grid::new(5, 5);
880 g.put_tile(2, 1, 1, Tile::new('Z', Style::default()));
881 assert_eq!(g.get_tile(2, 1, 1).unwrap().glyph, 'Z');
882 assert_eq!(g.get(1, 1).glyph, ' ');
884 assert!(g.get_tile(3, 0, 0).is_none());
886 }
887
888 #[test]
889 fn test_grid_clear_layer() {
890 let mut g = Grid::new(5, 5);
891 g.put_tile(1, 0, 0, Tile::new('Z', Style::default()));
892 g.put_tile(0, 0, 0, Tile::new('A', Style::default()));
893 g.clear(1);
894 assert_eq!(g.get_tile(0, 0, 0).unwrap().glyph, 'A');
895 assert!(g.get_tile(1, 0, 0).is_some());
896 assert_eq!(g.get_tile(1, 0, 0).unwrap().glyph, ' '); }
898
899 #[test]
900 fn test_grid_clear_all() {
901 let mut g = Grid::new(5, 5);
902 g.put_tile(1, 0, 0, Tile::new('Z', Style::default()));
903 g.put_tile(0, 0, 0, Tile::new('A', Style::default()));
904 g.clear_all();
905 assert_eq!(g.get(0, 0).glyph, ' ');
907 assert_eq!(g.get_tile(1, 0, 0).unwrap().glyph, ' ');
908 }
909}