1use crate::buffer::GenericBuffer;
4use crate::fill_rule::FillRule;
5use crate::point::Point;
6
7pub type RasterizeBuffer = GenericBuffer<f64>;
8
9impl RasterizeBuffer {
10    pub fn new(width: u32, height: u32) -> Self {
11        GenericBuffer {
12            width,
13            height,
14            buffer: vec![0.0; (width * height) as usize],
15        }
16    }
17
18    pub fn rasterize(
20        &mut self,
21        segments: impl Iterator<Item = (Point, Point)>,
22        fill_rule: impl FillRule,
23        writer: &mut impl FnMut(u32, u32, f64),
24        write_transparent_src: bool,
25    ) {
26        let mut bound = [self.width as f64, 0.0f64, self.height as f64, 0.0f64];
27        for (a, b) in segments {
28            if a.1 == b.1 {
29                continue;
30            }
31            let (a, b, signum) = if a.1 < b.1 { (a, b, -1.0) } else { (b, a, 1.0) };
32            let upper = a.1;
33            let lower = b.1;
34            if lower < 0.0 || self.height as f64 <= upper {
35                continue;
36            }
37            bound[0] = bound[0].min(a.0.min(b.0));
38            bound[1] = bound[1].max(a.0.max(b.0));
39            bound[2] = bound[2].min(upper);
40            bound[3] = bound[3].max(lower);
41            if a.0 == b.0 {
42                if 0.0 <= upper {
43                    if lower <= upper.ceil() {
44                        f2(&mut self.buffer, self.width, signum, upper, lower, a.0);
45                        continue;
46                    }
47                    f2(
48                        &mut self.buffer,
49                        self.width,
50                        signum,
51                        upper,
52                        upper.ceil(),
53                        a.0,
54                    );
55                }
56                if lower < self.height as f64 {
57                    f2(
58                        &mut self.buffer,
59                        self.width,
60                        signum,
61                        lower.floor(),
62                        lower,
63                        a.0,
64                    );
65                }
66                for y in
67                    (upper.ceil() as i32).max(0)..(lower.floor() as i32).min(self.height as i32)
68                {
69                    f2(
70                        &mut self.buffer,
71                        self.width,
72                        signum,
73                        y as f64,
74                        (y + 1) as f64,
75                        a.0,
76                    );
77                }
78            } else {
79                let int = Intersection::new(a, b);
80                if 0.0 <= upper {
81                    if lower <= upper.ceil() {
82                        f1(&mut self.buffer, self.width, &int, signum, upper, lower);
83                        continue;
84                    }
85                    f1(
86                        &mut self.buffer,
87                        self.width,
88                        &int,
89                        signum,
90                        upper,
91                        upper.ceil(),
92                    );
93                }
94                if lower < self.height as f64 {
95                    f1(
96                        &mut self.buffer,
97                        self.width,
98                        &int,
99                        signum,
100                        lower.floor(),
101                        lower,
102                    );
103                }
104                for y in
105                    (upper.ceil() as i32).max(0)..(lower.floor() as i32).min(self.height as i32)
106                {
107                    f1(
108                        &mut self.buffer,
109                        self.width,
110                        &int,
111                        signum,
112                        y as f64,
113                        (y + 1) as f64,
114                    );
115                }
116            }
117        }
118        self.transfer(fill_rule, writer, write_transparent_src, bound);
119    }
120
121    pub fn rasterize_no_aa(
123        &mut self,
124        segments: impl Iterator<Item = (Point, Point)>,
125        fill_rule: impl FillRule,
126        writer: &mut impl FnMut(u32, u32, f64),
127        write_transparent_src: bool,
128    ) {
129        let mut bound = [self.width as f64, 0.0f64, self.height as f64, 0.0f64];
130        for (a, b) in segments {
131            if a.1 == b.1 {
132                continue;
133            }
134            let (a, b, signum) = if a.1 < b.1 { (a, b, -1.0) } else { (b, a, 1.0) };
135            let upper = a.1;
136            let lower = b.1;
137            if lower < 0.0 || self.height as f64 <= upper {
138                continue;
139            }
140            bound[0] = bound[0].min(a.0.min(b.0));
141            bound[1] = bound[1].max(a.0.max(b.0));
142            bound[2] = bound[2].min(upper);
143            bound[3] = bound[3].max(lower);
144            let int = Intersection::new(a, b);
145            let width = self.width as usize;
146            for y in (upper.round() as i32).max(0) as usize
147                ..(lower.round() as i32).min(self.height as i32) as usize
148            {
149                let x = int.intersect_h(y as f64 + 0.5).round() as usize;
150                if width <= x {
151                    continue;
152                }
153                self.buffer[y * width as usize + x.max(0) as usize] += signum;
154            }
155        }
156        self.transfer(fill_rule, writer, write_transparent_src, bound);
157    }
158
159    #[inline]
160    pub fn transfer(
161        &mut self,
162        fill_rule: impl FillRule,
163        writer: &mut impl FnMut(u32, u32, f64),
164        write_transparent_src: bool,
165        bound: [f64; 4],
166    ) {
167        if write_transparent_src {
168            for y in 0..self.height {
169                let mut acc = 0.0;
170                for x in 0..self.width {
171                    let i = (y * self.width + x) as usize;
172                    acc += self.buffer[i];
173                    self.buffer[i] = 0.0;
174                    writer(x, y, fill_rule.apply(acc));
175                }
176            }
177        } else {
178            for y in
179                bound[2].max(0.0).floor() as u32..bound[3].min(self.height as f64).ceil() as u32
180            {
181                let mut acc = 0.0;
182                for x in bound[0].max(0.0).floor() as u32
183                    ..(bound[1] + 1.0).min(self.width as f64).ceil() as u32
184                {
185                    let i = (y * self.width + x) as usize;
186                    acc += self.buffer[i];
187                    self.buffer[i] = 0.0;
188                    let v = fill_rule.apply(acc);
189                    if v != 0.0 {
190                        writer(x, y, v);
191                    }
192                }
193            }
194        }
195    }
196}
197
198#[inline]
199fn f1(buf: &mut Vec<f64>, width: u32, int: &Intersection, signum: f64, upper: f64, lower: f64) {
200    let offset = upper.floor() as usize * width as usize;
201    let mut acc = 0.0;
202    let mut v = 0.0;
203    let mut write = |x: i32, a: f64| {
204        buf[offset + x as usize] += (a - acc - v) * signum;
205        v = a - acc;
206        acc = a;
207    };
208    let upper_x = int.intersect_h(upper);
209    let lower_x = int.intersect_h(lower);
210    let xi = if upper_x < lower_x {
211        for xi in (upper_x.floor() as i32).max(0)..(lower_x.floor() as i32).min(width as i32) {
212            let x = (xi + 1) as f64;
213            let y = int.intersect_v(x);
214            write(xi, (x - upper_x) * (y - upper) * 0.5);
215        }
216        lower_x.floor() as i32
217    } else {
218        for xi in (lower_x.floor() as i32).max(0)..(upper_x.floor() as i32).min(width as i32) {
219            let x = (xi + 1) as f64;
220            let y = int.intersect_v(x);
221            write(xi, (x - lower_x) * (lower - y) * 0.5);
222        }
223        upper_x.floor() as i32
224    };
225    if xi < 0 {
226        write(0, lower - upper);
227    } else if xi < width as i32 {
228        let a = ((xi + 1) as f64 - (upper_x + lower_x) * 0.5) * (lower - upper);
229        write(xi, a);
230        if xi + 1 < width as i32 {
231            write(xi + 1, a + (lower - upper));
232        }
233    }
234}
235
236#[inline]
237fn f2(buf: &mut Vec<f64>, width: u32, signum: f64, upper: f64, lower: f64, x: f64) {
238    let offset = upper.floor() as usize * width as usize;
239    if x < 0.0 {
240        buf[offset] += (lower - upper) * signum;
241    } else if x < width as f64 {
242        let a = (1.0 - x.fract()) * (lower - upper);
243        let x = x.floor() as usize;
244        buf[offset + x] += a * signum;
245        if x + 1 < width as usize {
246            buf[offset + x + 1] += (lower - upper - a) * signum;
247        }
248    }
249}
250
251struct Intersection(f64, f64, f64, f64);
252
253impl Intersection {
254    #[inline]
255    fn new(a: Point, b: Point) -> Intersection {
256        Intersection(
257            a.1,
258            (b.0 - a.0) / (b.1 - a.1),
259            a.0,
260            (b.1 - a.1) / (b.0 - a.0),
261        )
262    }
263
264    #[inline]
265    fn intersect_h(&self, y: f64) -> f64 {
266        (y - self.0).mul_add(self.1, self.2)
267    }
268
269    #[inline]
270    fn intersect_v(&self, x: f64) -> f64 {
271        (x - self.2).mul_add(self.3, self.0)
272    }
273}