add WindowMut
This commit is contained in:
parent
04f8884a14
commit
c9ad4e3357
4 changed files with 160 additions and 5 deletions
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{
|
||||
DataRef, DisplayBitVec, Grid, Payload, ValueGrid, PIXEL_HEIGHT, PIXEL_WIDTH,
|
||||
DataRef, DisplayBitVec, Grid, Payload, ValueGrid, WindowMut, PIXEL_HEIGHT,
|
||||
PIXEL_WIDTH,
|
||||
};
|
||||
use ::bitvec::{order::Msb0, prelude::BitSlice, slice::IterMut};
|
||||
use inherent::inherent;
|
||||
|
|
@ -262,6 +263,20 @@ impl TryFrom<&ValueGrid<bool>> for Bitmap {
|
|||
}
|
||||
}
|
||||
|
||||
impl<G: Grid<bool>> TryFrom<&WindowMut<'_, bool, G>> for Bitmap {
|
||||
type Error = ();
|
||||
|
||||
fn try_from(value: &WindowMut<'_, bool, G>) -> Result<Self, Self::Error> {
|
||||
let mut result = Self::new(value.width(), value.height()).ok_or(())?;
|
||||
for y in 0..value.height() {
|
||||
for x in 0..value.width() {
|
||||
result.set(x, y, value.get(x, y));
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Bitmap> for ValueGrid<bool> {
|
||||
/// Converts a [Bitmap] into a grid of [bool]s.
|
||||
fn from(value: &Bitmap) -> Self {
|
||||
|
|
@ -315,9 +330,7 @@ pub enum LoadBitmapError {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{
|
||||
Bitmap, DataRef, DisplayBitVec, LoadBitmapError, ValueGrid,
|
||||
};
|
||||
use crate::{Bitmap, DataRef, DisplayBitVec, LoadBitmapError, ValueGrid};
|
||||
|
||||
#[test]
|
||||
fn fill() {
|
||||
|
|
|
|||
128
src/containers/grid_view.rs
Normal file
128
src/containers/grid_view.rs
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
use crate::Grid;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WindowMut<'t, TElement: Copy, TGrid: Grid<TElement>> {
|
||||
grid: &'t mut TGrid,
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
phantom: PhantomData<TElement>,
|
||||
}
|
||||
|
||||
impl<'t, TElement: Copy, TGrid: Grid<TElement>> WindowMut<'t, TElement, TGrid> {
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
grid: &'t mut TGrid,
|
||||
x: usize,
|
||||
y: usize,
|
||||
width: usize,
|
||||
height: usize,
|
||||
) -> Option<Self> {
|
||||
if width == 0 || height == 0 {
|
||||
return None;
|
||||
}
|
||||
if !grid.is_in_bounds(x + width - 1, y + height - 1) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(Self {
|
||||
grid,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
phantom: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<TElement: Copy, TGrid: Grid<TElement>> Grid<TElement>
|
||||
for WindowMut<'_, TElement, TGrid>
|
||||
{
|
||||
fn set(&mut self, x: usize, y: usize, value: TElement) {
|
||||
self.grid.set(x + self.x, y + self.y, value)
|
||||
}
|
||||
fn get(&self, x: usize, y: usize) -> TElement {
|
||||
self.grid.get(x + self.x, y + self.y)
|
||||
}
|
||||
|
||||
fn fill(&mut self, value: TElement) {
|
||||
for y in self.y..(self.y + self.height) {
|
||||
for x in self.x..(self.x + self.width) {
|
||||
self.grid.set(x, y, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn width(&self) -> usize {
|
||||
self.width
|
||||
}
|
||||
|
||||
fn height(&self) -> usize {
|
||||
self.height
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::containers::grid_view::WindowMut;
|
||||
use crate::{Bitmap, CharGrid, DataRef, Grid};
|
||||
|
||||
#[test]
|
||||
fn test_grid_view_bitmap() {
|
||||
let mut bitmap = Bitmap::new(8, 4).unwrap();
|
||||
|
||||
// non-byte-aligned views work
|
||||
let mut view = WindowMut::new(&mut bitmap, 3, 1, 4, 2).unwrap();
|
||||
view.fill(true);
|
||||
|
||||
assert_eq!(bitmap.data_ref(), &[0, 30, 30, 0]);
|
||||
|
||||
// full size view works
|
||||
_ = WindowMut::new(&mut bitmap, 0, 0, 8, 4).unwrap();
|
||||
|
||||
// zero size view does not work
|
||||
assert!(WindowMut::new(&mut bitmap, 1, 2, 3, 0).is_none());
|
||||
assert!(WindowMut::new(&mut bitmap, 1, 2, 0, 1).is_none());
|
||||
|
||||
// oob does not work
|
||||
assert!(WindowMut::new(&mut bitmap, 30, 43, 3, 1).is_none());
|
||||
assert!(WindowMut::new(&mut bitmap, 0, 0, 9, 1).is_none());
|
||||
assert!(WindowMut::new(&mut bitmap, 0, 0, 1, 5).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_grid_view_char_grid() {
|
||||
let mut grid = CharGrid::new(3, 4);
|
||||
grid.fill(' ');
|
||||
|
||||
let mut view = WindowMut::new(&mut grid, 1, 1, 1, 2).unwrap();
|
||||
view.fill('#');
|
||||
|
||||
assert_eq!(
|
||||
grid.data_ref(),
|
||||
&[' ', ' ', ' ', ' ', '#', ' ', ' ', '#', ' ', ' ', ' ', ' ']
|
||||
);
|
||||
|
||||
// full size view works
|
||||
_ = WindowMut::new(&mut grid, 0, 0, 3, 4).unwrap();
|
||||
|
||||
// zero size view does not work
|
||||
assert!(WindowMut::new(&mut grid, 1, 2, 2, 0).is_none());
|
||||
assert!(WindowMut::new(&mut grid, 1, 2, 0, 1).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trip_bitmap() {
|
||||
let mut bitmap = Bitmap::new(8, 4).unwrap();
|
||||
|
||||
let non_aligned = WindowMut::new(&mut bitmap, 3, 1, 4, 2).unwrap();
|
||||
assert_eq!(Bitmap::try_from(&non_aligned), Err(()));
|
||||
|
||||
let aligned = WindowMut::new(&mut bitmap, 0, 1, 8, 2).unwrap();
|
||||
|
||||
assert!(matches!(Bitmap::try_from(&aligned), Ok(_)));
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ mod char_grid;
|
|||
mod cp437_grid;
|
||||
mod data_ref;
|
||||
mod grid;
|
||||
mod grid_view;
|
||||
mod value_grid;
|
||||
|
||||
pub use bit_vec::{bitvec, DisplayBitVec};
|
||||
|
|
@ -16,6 +17,7 @@ pub use char_grid::CharGrid;
|
|||
pub use cp437_grid::Cp437Grid;
|
||||
pub use data_ref::DataRef;
|
||||
pub use grid::Grid;
|
||||
pub use grid_view::WindowMut;
|
||||
pub use value_grid::{
|
||||
IterGridRows, SetValueSeriesError, TryLoadValueGridError, Value, ValueGrid,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{DataRef, Grid};
|
||||
use crate::{DataRef, Grid, WindowMut};
|
||||
use inherent::inherent;
|
||||
use std::fmt::Debug;
|
||||
use std::slice::{Iter, IterMut};
|
||||
|
|
@ -441,6 +441,18 @@ impl<T: Value> Iterator for EnumerateGrid<'_, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<E: Value> From<&WindowMut<'_, E, Self>> for ValueGrid<E> {
|
||||
fn from(value: &WindowMut<'_, E, Self>) -> Self {
|
||||
let mut result = Self::new(value.width(), value.height());
|
||||
for y in 0..value.height() {
|
||||
for x in 0..value.width() {
|
||||
result.set(x, y, value.get(x, y));
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{SetValueSeriesError, ValueGrid, *};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue