1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
//! A pixel mixer module.
use core::borrow::{Borrow, BorrowMut};
use crate::color::PixelRgb;
use crate::phase_amp::*;
/// Implementations of this trait should compute the vertical and horizontal intermediate data for a
/// [Mixer].
pub trait IntermediateCalculator<T> {
    /// Computes an intermediate data for a given angle.
    ///
    /// The input value is given in radians in the range: `[0, 2PI)`.
    /// The output will be stored in the array of given types as defined by [Mixer::IntermediateH]
    /// or [Mixer::IntermediateV]. The type should be a `f32` or a packed simd `f32x8` if a
    /// "use-simd" crate feature is enabled.
    fn calculate(&self, v: T) -> T;
}
/// Implementations of this trait should compute the color of each pixel based on an intermediate
/// data created by a [IntermediateCalculator].
///
/// The type `T` should be a `f32` or a packed simd `f32x8` if a "use-simd" crate feature is
/// enabled.
pub trait Mixer<T: Sized + Default + Copy> {
    /// This type should be an array of the type T for an intermediate horizontal data.
    type IntermediateH: Sized + Default + Copy + BorrowMut<[T]> + Borrow<[T]>;
    /// This type should be an array of the type T for an intermediate vertical data.
    type IntermediateV: Sized + Default + Copy + BorrowMut<[T]> + Borrow<[T]>;
    /// Returns the number of intermediate horizontal values.
    #[inline]
    fn intermediate_h_len() -> usize { core::mem::size_of::<Self::IntermediateH>() / core::mem::size_of::<T>() }
    /// Returns the number of intermediate vertical values.
    #[inline]
    fn intermediate_v_len() -> usize { core::mem::size_of::<Self::IntermediateV>() / core::mem::size_of::<T>() }
    /// The implementors should compute a pixel and send it as an instance of [PixelRgb] to the
    /// provided `next_pixel` function.
    ///
    /// The computation should be based on the provided combination of intermediate data.
    fn mix_pixels(vxp: &Self::IntermediateH, vyp: &Self::IntermediateV, next_pixel: &mut dyn FnMut(PixelRgb));
}
/// Implementations of this trait should produce an iterator of an [IntermediateCalculator] tool.
///
/// The type `T` should be a `f32` or a packed simd `f32x8` if a "use-simd" crate feature is
/// enabled.
pub trait IntermediateCalculatorProducer<'a, P, T>
    where P: PhaseAmpsSelect<'a> + ?Sized,
          T: Sized + Default + Copy
{
    /// Provide an iterator implementation which produce [IntermediateCalculator] tools.
    /// The iterator must be a [ExactSizeIterator] with exactly the same length as
    /// the associated [Mixer::IntermediateH] array's number of elements.
    type CalcIterH: ExactSizeIterator + Iterator<Item = Self::LineCalcH> + Sized;
    /// Provide an iterator implementation which produce [IntermediateCalculator] tools.
    /// The iterator must be a [ExactSizeIterator] with exactly the same length as
    /// the associated [Mixer::IntermediateV] array's number of elements.
    type CalcIterV: ExactSizeIterator + Iterator<Item = Self::LineCalcV> + Sized;
    /// Provide an implementation of a [IntermediateCalculator] for horizontal intermediate data.
    type LineCalcH: IntermediateCalculator<T> + Sized;
    /// Provide an implementation of a [IntermediateCalculator] for vertical intermediate data.
    type LineCalcV: IntermediateCalculator<T> + Sized;
    /// Should return an instance of a [IntermediateCalculatorProducer::LineCalcH].
    /// The input data references an implementation of [PhaseAmpsSelect] tool.
    fn compose_h_iter(pa: &'a P) -> Self::CalcIterH;
    /// Should return an instance of a [IntermediateCalculatorProducer::LineCalcV].
    /// The input data references an implementation of [PhaseAmpsSelect] tool.
    fn compose_v_iter(pa: &'a P) -> Self::CalcIterV;
}