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
use crate::pixel::Rgba;
use crate::render::{Render, RenderOpt};
use crate::path::Path;

#[derive(Debug)]
pub enum CompositeMode {
    None,
    Normal(Path)
}

pub struct Composite {
    pub layers: Vec<(Box<Render<Rgba>>, CompositeMode)>
}

impl Render<Rgba> for Composite {
    fn sample(&self, u: f64, v: f64, time: f64) -> Rgba {
        let mut value = Rgba::default();
        for (render, cm) in &self.layers {
            composite(&mut [value], &[render.sample(u, v, time)], time, cm);
        }
        value
    }

    fn render(&self, ro: &RenderOpt, buffer: &mut [Rgba]) {
        let RenderOpt {u_res, v_res, frame_range, framerate, ..} = ro;
        let mut sub_buffer = vec![Rgba::default(); buffer.len()];
        let frame_size = u_res * v_res;

        for (render, cm) in &self.layers {
            render.render(ro, sub_buffer.as_mut_slice());
            for f in frame_range.start..frame_range.end {
                let start = frame_size * (f - frame_range.start) as usize;
                composite(
                    &mut buffer[start..start+frame_size],
                    &sub_buffer[start..start+frame_size],
                    f as f64 / *framerate as f64, cm);
            }
        }
    }
}

#[inline(always)]
fn composite(base: &mut [Rgba], value: &[Rgba], time: f64, cm: &CompositeMode) {
    match cm {
        CompositeMode::None => {
            for i in 0..base.len() {
                base[i] = value[i];
            }
        },
        CompositeMode::Normal(alpha_path) => {
            let alpha = alpha_path.get_value(time);
            for i in 0..base.len() {
                base[i] = base[i].normal_blend(&value[i], alpha);
            }
        }
    };
}