pixel-canvas 0.2.3

A crate to make it easy to build interactive computer art with just a pixel buffer.
Documentation
use packed_simd::*;
use pixel_canvas::{input::MouseState, prelude::*};
use rayon::prelude::*;
use std::ops::{Add, Mul};

const CHUNK: usize = 8;
type F32s = f32x8;
type I32s = i32x8;
type M32s = m32x8;

#[derive(Clone, Copy)]
struct C32 {
    r: F32s,
    i: F32s,
}

impl Add for C32 {
    type Output = C32;
    fn add(self, rhs: C32) -> C32 {
        C32 {
            r: self.r + rhs.r,
            i: self.i + rhs.i,
        }
    }
}

impl Mul for C32 {
    type Output = C32;
    fn mul(self, rhs: C32) -> C32 {
        C32 {
            r: self.r * rhs.r - self.i * rhs.i,
            i: self.r * rhs.i + self.i * rhs.r,
        }
    }
}

impl C32 {
    fn len2(&self) -> F32s {
        self.r * self.r + self.i * self.i
    }

    fn diverges(&self) -> M32s {
        self.len2().gt(F32s::splat(4.0))
    }
}

fn main() {
    let canvas = Canvas::new(1280, 720)
        .title("Julia Set")
        .hidpi(true)
        .show_ms(true)
        .state(MouseState::new())
        .input(MouseState::handle_input);
    canvas.render(|mouse, image| {
        let half_width = image.width() as i32 / 2;
        let half_height = image.height() as i32 / 2;
        let scale = half_height as f32 / 1.2;
        let splay = F32s::new(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0);
        let coord = |x, y| C32 {
            r: (x - F32s::splat(half_width as f32)) / scale,
            i: (y - F32s::splat(half_height as f32)) / scale,
        };
        let c = coord(F32s::splat(mouse.x as f32), F32s::splat(mouse.y as f32));
        let width = image.width() as usize;
        image
            .par_chunks_mut(width)
            .enumerate()
            .for_each(|(y, row)| {
                let y = F32s::splat(y as f32);
                for (x, pix) in row.chunks_mut(CHUNK).enumerate() {
                    let x = F32s::splat((x * CHUNK) as f32) + splay;
                    let mut z = coord(x, y);
                    let mut i = I32s::splat(0);
                    let mut div = M32s::splat(false);
                    for _ in 0..127 {
                        z = z * z + c;
                        i += div.select(I32s::splat(0), I32s::splat(1));
                        div |= z.diverges();
                        if div.all() {
                            break;
                        }
                    }

                    for j in 0..CHUNK {
                        pix[j] = if div.extract(j) {
                            Color {
                                r: 255,
                                g: i.extract(j) as u8 * 2,
                                b: 0,
                            }
                        } else {
                            Color::BLACK
                        };
                    }
                }
            });
    });
}