devotee 0.2.0-beta.32

Visualization engine
Documentation
use std::ops::RangeInclusive;

use crate::util::vector::Vector;

/// General image trait.
pub trait Image<P> {
    /// Get specific pixel.
    fn pixel(&self, position: Vector<i32>) -> Option<P>;

    /// Get specific pixel without bounds check.
    ///
    /// # Safety
    /// - position must be in range [(0, 0), (width - 1, height - 1)]
    unsafe fn pixel_unchecked(&self, position: Vector<i32>) -> P;

    /// Get width of this image.
    fn width(&self) -> i32;

    /// Get height of this image.
    fn height(&self) -> i32;
}

/// Mutable part of an Image.
pub trait ImageMut<P>: Image<P> {
    /// Set specific pixel as `position`.
    fn set_pixel(&mut self, position: Vector<i32>, value: &P);

    /// Modify specific pixel using provided function.
    fn modify_pixel(&mut self, position: Vector<i32>, function: &mut dyn FnMut((i32, i32), P) -> P);

    // TODO: Speed up in specific cases.
    /// Set horizontal line values.
    fn set_horizontal_line(&mut self, x_range: RangeInclusive<i32>, y: i32, value: &P) {
        let start = (*x_range.start()).max(0);
        let end = (*x_range.end()).min(self.width() - 1);

        for x in start..=end {
            self.set_pixel(Vector::new(x, y), value);
        }
    }

    // TODO: Speed up in specific cases.
    /// Modify all pixels in the horizontal line.
    fn modify_horizontal_line(
        &mut self,
        x_range: RangeInclusive<i32>,
        y: i32,
        function: &mut dyn FnMut((i32, i32), P) -> P,
    ) {
        let start = (*x_range.start()).max(0);
        let end = (*x_range.end()).min(self.width() - 1);

        for x in start..=end {
            self.modify_pixel(Vector::new(x, y), function);
        }
    }

    /// Set specific pixel value without bounds check.
    ///
    /// # Safety
    /// - position must be in range [(0, 0), (width - 1, height - 1)]
    unsafe fn set_pixel_unchecked(&mut self, position: Vector<i32>, value: &P);

    /// Clear this image with color provided.
    fn clear(&mut self, color: P);
}