use crate::{
core::{GridError, Layout as _, Pos, Rect},
ops::{GridRead, GridWrite},
};
pub trait GridBlend: GridRead + GridWrite
where
for<'a> <Self as GridRead>::Element<'a>: Copy,
Self: Sized,
{
fn blend_set(
&mut self,
dst: Pos,
value: <Self as GridWrite>::Element,
blend: &impl Fn(
<Self as GridRead>::Element<'_>,
<Self as GridWrite>::Element,
) -> <Self as GridWrite>::Element,
) -> Result<(), GridError> {
let current = self.get(dst).ok_or(GridError)?;
self.set(dst, blend(current, value))
}
fn blend_rect<'src, S>(
&mut self,
dst: Pos,
src: &'src S,
rect: Rect,
blend: &impl Fn(
<Self as GridRead>::Element<'_>,
<Self as GridWrite>::Element,
) -> <Self as GridWrite>::Element,
) where
S: GridRead<Element<'src> = <Self as GridWrite>::Element>,
{
for pos in <Self as GridRead>::Layout::iter_pos(rect) {
if let Some(value) = src.get(pos) {
let _ = self.blend_set(dst + pos, value, blend);
}
}
}
}
impl<T> GridBlend for T
where
T: GridRead + GridWrite,
for<'a> <T as GridRead>::Element<'a>: Copy,
{
}
pub fn clear<S, D>(_src: S, _dst: D) -> D
where
D: Default,
{
D::default()
}
pub fn source<S, D>(src: S, _dst: D) -> S {
src
}
pub fn destination<S, D>(_src: S, dst: D) -> D {
dst
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn blend_clear_test() {
let src = 42;
let dst: i32 = 24;
let result = clear(src, dst);
assert_eq!(result, 0);
}
#[test]
fn blend_source_test() {
let src = 42;
let dst: i32 = 24;
let result = source(src, dst);
assert_eq!(result, 42);
}
#[test]
fn blend_destination_test() {
let src = 42;
let dst: i32 = 24;
let result = destination(src, dst);
assert_eq!(result, 24);
}
}