use crate::iter::Coordinates;
#[derive(Eq, PartialEq, Copy, Clone, Debug)]
pub struct Region {
pub x: u32,
pub y: u32,
pub width: u32,
pub height: u32,
}
impl Region {
pub fn new() -> Builder {
Default::default()
}
#[inline]
pub fn from(x: u32, y: u32, width: u32, height: u32) -> Self {
Region { x, y, width, height }
}
#[inline]
pub fn relative(&self) -> Coordinates {
Coordinates::new(*self)
}
#[inline]
pub fn absolute(&self) -> Coordinates {
Coordinates::new(Region {
x: 0,
y: 0,
width: self.width,
height: self.height,
})
}
}
#[derive(Eq, PartialEq, Copy, Clone, Default, Debug)]
pub struct Builder {
pub x: Option<u32>,
pub y: Option<u32>,
pub width: Option<u32>,
pub height: Option<u32>,
}
impl Builder {
#[inline]
pub fn complete(&self, region: Region) -> Region {
let (x, width) = if let Some(x) = self.x {
if let Some(width) = self.width {
(x, width)
}
else {
(x, region.width - x)
}
}
else {
(region.x, self.width.unwrap_or(region.width))
};
let (y, height) = if let Some(y) = self.y {
if let Some(height) = self.height {
(y, height)
}
else {
(y, region.height - y)
}
}
else {
(region.y, self.height.unwrap_or(region.height))
};
Region { x, y, width, height }
}
#[inline]
pub fn with<F: FnMut(&Builder) -> Region>(&self, mut func: F) -> Region {
func(self)
}
#[inline]
pub fn unwrap(self) -> Region {
Region {
x: self.x.unwrap(),
y: self.y.unwrap(),
width: self.width.unwrap(),
height: self.height.unwrap(),
}
}
#[inline]
pub fn x(mut self, value: u32) -> Self {
self.x = Some(value);
self
}
#[inline]
pub fn y(mut self, value: u32) -> Self {
self.y = Some(value);
self
}
#[inline]
pub fn width(mut self, value: u32) -> Self {
self.width = Some(value);
self
}
#[inline]
pub fn height(mut self, value: u32) -> Self {
self.height = Some(value);
self
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn complete() {
assert_eq!(
Region::from(5, 0, 5, 10),
Region::new().x(5).complete(Region::from(0, 0, 10, 10))
);
assert_eq!(
Region::from(0, 0, 5, 10),
Region::new().width(5).complete(Region::from(0, 0, 10, 10))
);
}
#[test]
fn relative() {
assert_eq!(
vec![(2, 4), (3, 4), (2, 5), (3, 5), (2, 6), (3, 6), (2, 7), (3, 7)],
Region::new()
.x(2)
.y(4)
.width(2)
.height(4)
.unwrap()
.relative()
.collect::<Vec<(u32, u32)>>()
);
}
#[test]
fn absolute() {
assert_eq!(
vec![(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2), (0, 3), (1, 3)],
Region::new()
.x(2)
.y(4)
.width(2)
.height(4)
.unwrap()
.absolute()
.collect::<Vec<(u32, u32)>>()
);
}
}