use super::super::drawable::*;
use super::super::transform::*;
use coord::{Coord, ToUnsigned};
#[derive(Debug, Clone, Copy)]
pub struct Rect {
pub top_left: Coord,
pub bottom_right: Coord,
pub color: Color,
}
impl Rect {
pub fn new(top_left: Coord, bottom_right: Coord, color: u8) -> Self {
Rect {
top_left,
bottom_right,
color,
}
}
}
impl<'a> IntoIterator for &'a Rect {
type Item = Pixel;
type IntoIter = RectIterator;
fn into_iter(self) -> Self::IntoIter {
RectIterator {
top_left: self.top_left,
bottom_right: self.bottom_right,
color: self.color,
x: self.top_left[0],
y: self.top_left[1],
screen_size: (self.bottom_right - self.top_left).abs(),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct RectIterator {
top_left: Coord,
bottom_right: Coord,
color: Color,
x: i32,
y: i32,
screen_size: Coord,
}
impl Iterator for RectIterator {
type Item = Pixel;
fn next(&mut self) -> Option<Self::Item> {
if (self.top_left[0] < 0 || self.top_left[1] < 0)
&& (self.bottom_right[0] < 0 || self.bottom_right[1] < 0)
{
return None;
}
let coord = loop {
if self.y > self.bottom_right[1] {
return None;
}
let coord = Coord::new(self.x, self.y);
if self.y == self.top_left[1] || self.y == self.bottom_right[1] {
self.x += 1;
}
else {
self.x += self.screen_size[0];
}
if self.x > self.bottom_right[0] {
self.x = self.top_left[0];
self.y += 1;
}
if coord[0] >= 0 && coord[1] >= 0 {
break coord;
}
};
Some((coord.to_unsigned(), self.color))
}
}
impl Drawable for Rect {}
impl Transform for Rect {
fn translate(&self, by: Coord) -> Self {
Self {
top_left: self.top_left + by,
bottom_right: self.bottom_right + by,
..*self
}
}
fn translate_mut(&mut self, by: Coord) -> &mut Self {
self.top_left += by;
self.bottom_right += by;
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use unsignedcoord::UnsignedCoord;
#[test]
fn it_can_be_translated() {
let rect = Rect::new(Coord::new(5, 10), Coord::new(15, 20), 1);
let moved = rect.translate(Coord::new(10, 10));
assert_eq!(moved.top_left, Coord::new(15, 20));
assert_eq!(moved.bottom_right, Coord::new(25, 30));
}
#[test]
fn it_draws_unfilled_rect() {
let mut rect = Rect::new(Coord::new(2, 2), Coord::new(4, 4), 1).into_iter();
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 2), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(3, 2), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(4, 2), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 3), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(4, 3), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 4), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(3, 4), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(4, 4), 1)));
}
#[test]
fn it_can_be_negative() {
let mut rect = Rect::new(Coord::new(-2, -2), Coord::new(2, 2), 1).into_iter();
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 0), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 1), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(0, 2), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(1, 2), 1)));
assert_eq!(rect.next(), Some((UnsignedCoord::new(2, 2), 1)));
}
}