1use crate::basics::{POLY_SUBPIXEL_MASK, POLY_SUBPIXEL_SCALE, POLY_SUBPIXEL_SHIFT};
10
11#[derive(Debug, Clone, Copy)]
22pub struct CellAa {
23 pub x: i32,
24 pub y: i32,
25 pub cover: i32,
26 pub area: i32,
27}
28
29impl CellAa {
30 #[inline]
32 pub fn initial(&mut self) {
33 self.x = i32::MAX;
34 self.y = i32::MAX;
35 self.cover = 0;
36 self.area = 0;
37 }
38
39 #[inline]
42 pub fn style(&mut self, _other: &CellAa) {}
43
44 #[inline]
47 pub fn not_equal(&self, ex: i32, ey: i32, _style: &CellAa) -> bool {
48 (ex as u32).wrapping_sub(self.x as u32) | (ey as u32).wrapping_sub(self.y as u32) != 0
49 }
50}
51
52impl Default for CellAa {
53 fn default() -> Self {
54 Self {
55 x: i32::MAX,
56 y: i32::MAX,
57 cover: 0,
58 area: 0,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, Default)]
68struct SortedY {
69 start: u32,
70 num: u32,
71}
72
73pub struct RasterizerCellsAa {
85 cells: Vec<CellAa>,
86 sorted_cells: Vec<u32>,
87 sorted_y: Vec<SortedY>,
88 curr_cell: CellAa,
89 style_cell: CellAa,
90 min_x: i32,
91 min_y: i32,
92 max_x: i32,
93 max_y: i32,
94 sorted: bool,
95}
96
97const DX_LIMIT: i64 = 16384 << POLY_SUBPIXEL_SHIFT;
99
100impl RasterizerCellsAa {
101 pub fn new() -> Self {
103 Self {
104 cells: Vec::new(),
105 sorted_cells: Vec::new(),
106 sorted_y: Vec::new(),
107 curr_cell: CellAa::default(),
108 style_cell: CellAa::default(),
109 min_x: i32::MAX,
110 min_y: i32::MAX,
111 max_x: i32::MIN,
112 max_y: i32::MIN,
113 sorted: false,
114 }
115 }
116
117 pub fn reset(&mut self) {
119 self.cells.clear();
120 self.sorted_cells.clear();
121 self.sorted_y.clear();
122 self.curr_cell.initial();
123 self.style_cell.initial();
124 self.min_x = i32::MAX;
125 self.min_y = i32::MAX;
126 self.max_x = i32::MIN;
127 self.max_y = i32::MIN;
128 self.sorted = false;
129 }
130
131 #[inline]
133 pub fn style(&mut self, style_cell: &CellAa) {
134 self.style_cell.style(style_cell);
135 }
136
137 #[inline]
138 pub fn min_x(&self) -> i32 {
139 self.min_x
140 }
141 #[inline]
142 pub fn min_y(&self) -> i32 {
143 self.min_y
144 }
145 #[inline]
146 pub fn max_x(&self) -> i32 {
147 self.max_x
148 }
149 #[inline]
150 pub fn max_y(&self) -> i32 {
151 self.max_y
152 }
153
154 #[inline]
156 pub fn total_cells(&self) -> u32 {
157 self.cells.len() as u32
158 }
159
160 #[inline]
162 pub fn sorted(&self) -> bool {
163 self.sorted
164 }
165
166 #[inline]
168 pub fn scanline_num_cells(&self, y: u32) -> u32 {
169 self.sorted_y[(y as i32 - self.min_y) as usize].num
170 }
171
172 #[inline]
175 pub fn scanline_cells(&self, y: u32) -> &[u32] {
176 let sy = &self.sorted_y[(y as i32 - self.min_y) as usize];
177 &self.sorted_cells[sy.start as usize..(sy.start + sy.num) as usize]
178 }
179
180 #[inline]
182 pub fn cell(&self, idx: u32) -> &CellAa {
183 &self.cells[idx as usize]
184 }
185
186 #[inline]
188 pub fn cells(&self) -> &[CellAa] {
189 &self.cells
190 }
191
192 #[inline]
198 fn add_curr_cell(&mut self) {
199 if self.curr_cell.area | self.curr_cell.cover != 0 {
200 self.cells.push(self.curr_cell);
201 }
202 }
203
204 #[inline]
206 fn set_curr_cell(&mut self, x: i32, y: i32) {
207 if self.curr_cell.not_equal(x, y, &self.style_cell) {
208 self.add_curr_cell();
209 self.curr_cell.style(&self.style_cell);
210 self.curr_cell.x = x;
211 self.curr_cell.y = y;
212 self.curr_cell.cover = 0;
213 self.curr_cell.area = 0;
214 }
215 }
216
217 fn render_hline(&mut self, ey: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
225 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
226 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
227 let fx1 = x1 & POLY_SUBPIXEL_MASK as i32;
228 let fx2 = x2 & POLY_SUBPIXEL_MASK as i32;
229
230 if y1 == y2 {
232 self.set_curr_cell(ex2, ey);
233 return;
234 }
235
236 if ex1 == ex2 {
238 let delta = y2 - y1;
239 self.curr_cell.cover += delta;
240 self.curr_cell.area += (fx1 + fx2) * delta;
241 return;
242 }
243
244 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fx1 as i64) * (y2 - y1) as i64;
246 let mut first = POLY_SUBPIXEL_SCALE as i32;
247 let mut incr = 1_i32;
248
249 let mut dx = x2 as i64 - x1 as i64;
250
251 if dx < 0 {
252 p = fx1 as i64 * (y2 - y1) as i64;
253 first = 0;
254 incr = -1;
255 dx = -dx;
256 }
257
258 let mut delta = (p / dx) as i32;
259 let mut modulo = p % dx;
260
261 if modulo < 0 {
262 delta -= 1;
263 modulo += dx;
264 }
265
266 self.curr_cell.cover += delta;
267 self.curr_cell.area += (fx1 + first) * delta;
268
269 let mut ex1 = ex1 + incr;
270 self.set_curr_cell(ex1, ey);
271 let mut y1 = y1 + delta;
272
273 if ex1 != ex2 {
274 p = POLY_SUBPIXEL_SCALE as i64 * (y2 - y1 + delta) as i64;
275 let mut lift = (p / dx) as i32;
276 let mut rem = p % dx;
277
278 if rem < 0 {
279 lift -= 1;
280 rem += dx;
281 }
282
283 modulo -= dx;
284
285 while ex1 != ex2 {
286 delta = lift;
287 modulo += rem;
288 if modulo >= 0 {
289 modulo -= dx;
290 delta += 1;
291 }
292
293 self.curr_cell.cover += delta;
294 self.curr_cell.area += POLY_SUBPIXEL_SCALE as i32 * delta;
295 y1 += delta;
296 ex1 += incr;
297 self.set_curr_cell(ex1, ey);
298 }
299 }
300 delta = y2 - y1;
301 self.curr_cell.cover += delta;
302 self.curr_cell.area += (fx2 + POLY_SUBPIXEL_SCALE as i32 - first) * delta;
303 }
304
305 pub fn line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32) {
310 let dx = x2 as i64 - x1 as i64;
311
312 if dx >= DX_LIMIT || dx <= -DX_LIMIT {
313 let cx = ((x1 as i64 + x2 as i64) >> 1) as i32;
314 let cy = ((y1 as i64 + y2 as i64) >> 1) as i32;
315 self.line(x1, y1, cx, cy);
316 self.line(cx, cy, x2, y2);
317 return;
318 }
319
320 let dy = y2 as i64 - y1 as i64;
321 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
322 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
323 let ey1_orig = y1 >> POLY_SUBPIXEL_SHIFT;
324 let ey2 = y2 >> POLY_SUBPIXEL_SHIFT;
325 let fy1 = y1 & POLY_SUBPIXEL_MASK as i32;
326 let fy2 = y2 & POLY_SUBPIXEL_MASK as i32;
327
328 if ex1 < self.min_x {
330 self.min_x = ex1;
331 }
332 if ex1 > self.max_x {
333 self.max_x = ex1;
334 }
335 if ey1_orig < self.min_y {
336 self.min_y = ey1_orig;
337 }
338 if ey1_orig > self.max_y {
339 self.max_y = ey1_orig;
340 }
341 if ex2 < self.min_x {
342 self.min_x = ex2;
343 }
344 if ex2 > self.max_x {
345 self.max_x = ex2;
346 }
347 if ey2 < self.min_y {
348 self.min_y = ey2;
349 }
350 if ey2 > self.max_y {
351 self.max_y = ey2;
352 }
353
354 let mut ey1 = ey1_orig;
355
356 self.set_curr_cell(ex1, ey1);
357
358 if ey1 == ey2 {
360 self.render_hline(ey1, x1, fy1, x2, fy2);
361 return;
362 }
363
364 let mut incr = 1_i32;
366 if dx == 0 {
367 let ex = x1 >> POLY_SUBPIXEL_SHIFT;
368 let two_fx = (x1 - (ex << POLY_SUBPIXEL_SHIFT)) << 1;
369
370 let mut first = POLY_SUBPIXEL_SCALE as i32;
371 if dy < 0 {
372 first = 0;
373 incr = -1;
374 }
375
376 let x_from = x1;
377 let _ = x_from; let mut delta = first - fy1;
380 self.curr_cell.cover += delta;
381 self.curr_cell.area += two_fx * delta;
382
383 ey1 += incr;
384 self.set_curr_cell(ex, ey1);
385
386 delta = first + first - POLY_SUBPIXEL_SCALE as i32;
387 let area = two_fx * delta;
388 while ey1 != ey2 {
389 self.curr_cell.cover = delta;
390 self.curr_cell.area = area;
391 ey1 += incr;
392 self.set_curr_cell(ex, ey1);
393 }
394 delta = fy2 - POLY_SUBPIXEL_SCALE as i32 + first;
395 self.curr_cell.cover += delta;
396 self.curr_cell.area += two_fx * delta;
397 return;
398 }
399
400 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fy1 as i64) * dx;
402 let mut first = POLY_SUBPIXEL_SCALE as i32;
403
404 let mut dy_abs = dy;
405 if dy < 0 {
406 p = fy1 as i64 * dx;
407 first = 0;
408 incr = -1;
409 dy_abs = -dy;
410 }
411
412 let mut delta = (p / dy_abs) as i32;
413 let mut modulo = p % dy_abs;
414
415 if modulo < 0 {
416 delta -= 1;
417 modulo += dy_abs;
418 }
419
420 let mut x_from = x1 + delta;
421 self.render_hline(ey1, x1, fy1, x_from, first);
422
423 ey1 += incr;
424 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
425
426 if ey1 != ey2 {
427 p = POLY_SUBPIXEL_SCALE as i64 * dx;
428 let mut lift = (p / dy_abs) as i32;
429 let mut rem = p % dy_abs;
430
431 if rem < 0 {
432 lift -= 1;
433 rem += dy_abs;
434 }
435 modulo -= dy_abs;
436
437 while ey1 != ey2 {
438 delta = lift;
439 modulo += rem;
440 if modulo >= 0 {
441 modulo -= dy_abs;
442 delta += 1;
443 }
444
445 let x_to = x_from + delta;
446 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x_to, first);
447 x_from = x_to;
448
449 ey1 += incr;
450 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
451 }
452 }
453 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x2, fy2);
454 }
455
456 pub fn sort_cells(&mut self) {
461 if self.sorted {
462 return;
463 }
464
465 self.add_curr_cell();
466 self.curr_cell.x = i32::MAX;
467 self.curr_cell.y = i32::MAX;
468 self.curr_cell.cover = 0;
469 self.curr_cell.area = 0;
470
471 if self.cells.is_empty() {
472 return;
473 }
474
475 let num_cells = self.cells.len();
477 self.sorted_cells.clear();
478 self.sorted_cells.resize(num_cells, 0);
479
480 let y_range = (self.max_y - self.min_y + 1) as usize;
481 self.sorted_y.clear();
482 self.sorted_y.resize(y_range, SortedY::default());
483
484 for cell in &self.cells {
486 let yi = (cell.y - self.min_y) as usize;
487 self.sorted_y[yi].start += 1;
488 }
489
490 let mut start = 0u32;
492 for sy in &mut self.sorted_y {
493 let count = sy.start;
494 sy.start = start;
495 start += count;
496 }
497
498 for (i, cell) in self.cells.iter().enumerate() {
500 let yi = (cell.y - self.min_y) as usize;
501 let sy = &mut self.sorted_y[yi];
502 self.sorted_cells[(sy.start + sy.num) as usize] = i as u32;
503 sy.num += 1;
504 }
505
506 for sy in &self.sorted_y {
508 if sy.num > 0 {
509 let start = sy.start as usize;
510 let end = (sy.start + sy.num) as usize;
511 let slice = &mut self.sorted_cells[start..end];
512 let cells = &self.cells;
513 slice.sort_unstable_by_key(|&idx| cells[idx as usize].x);
514 }
515 }
516
517 self.sorted = true;
518 }
519}
520
521impl Default for RasterizerCellsAa {
522 fn default() -> Self {
523 Self::new()
524 }
525}
526
527pub struct ScanlineHitTest {
536 x: i32,
537 hit: bool,
538}
539
540impl ScanlineHitTest {
541 pub fn new(x: i32) -> Self {
542 Self { x, hit: false }
543 }
544
545 #[inline]
546 pub fn reset_spans(&mut self) {}
547
548 #[inline]
549 pub fn finalize(&mut self, _y: i32) {}
550
551 #[inline]
552 pub fn add_cell(&mut self, x: i32, _cover: u32) {
553 if self.x == x {
554 self.hit = true;
555 }
556 }
557
558 #[inline]
559 pub fn add_span(&mut self, x: i32, len: u32, _cover: u32) {
560 if self.x >= x && self.x < x + len as i32 {
561 self.hit = true;
562 }
563 }
564
565 #[inline]
566 pub fn num_spans(&self) -> u32 {
567 1
568 }
569
570 #[inline]
571 pub fn hit(&self) -> bool {
572 self.hit
573 }
574}
575
576#[cfg(test)]
581mod tests {
582 use super::*;
583
584 #[test]
589 fn test_cell_aa_default() {
590 let cell = CellAa::default();
591 assert_eq!(cell.x, i32::MAX);
592 assert_eq!(cell.y, i32::MAX);
593 assert_eq!(cell.cover, 0);
594 assert_eq!(cell.area, 0);
595 }
596
597 #[test]
598 fn test_cell_aa_initial() {
599 let mut cell = CellAa {
600 x: 10,
601 y: 20,
602 cover: 5,
603 area: 100,
604 };
605 cell.initial();
606 assert_eq!(cell.x, i32::MAX);
607 assert_eq!(cell.y, i32::MAX);
608 assert_eq!(cell.cover, 0);
609 assert_eq!(cell.area, 0);
610 }
611
612 #[test]
613 fn test_cell_aa_not_equal() {
614 let cell = CellAa {
615 x: 10,
616 y: 20,
617 cover: 0,
618 area: 0,
619 };
620 let style = CellAa::default();
621 assert!(!cell.not_equal(10, 20, &style));
622 assert!(cell.not_equal(11, 20, &style));
623 assert!(cell.not_equal(10, 21, &style));
624 assert!(cell.not_equal(11, 21, &style));
625 }
626
627 #[test]
632 fn test_new_rasterizer_is_empty() {
633 let ras = RasterizerCellsAa::new();
634 assert_eq!(ras.total_cells(), 0);
635 assert!(!ras.sorted());
636 assert_eq!(ras.min_x(), i32::MAX);
637 assert_eq!(ras.min_y(), i32::MAX);
638 assert_eq!(ras.max_x(), i32::MIN);
639 assert_eq!(ras.max_y(), i32::MIN);
640 }
641
642 #[test]
643 fn test_reset() {
644 let mut ras = RasterizerCellsAa::new();
645 ras.line(0, 0, 256, 256);
647 assert!(ras.total_cells() > 0 || true); ras.reset();
649 assert_eq!(ras.total_cells(), 0);
650 assert!(!ras.sorted());
651 }
652
653 #[test]
658 fn test_horizontal_line_no_cells() {
659 let mut ras = RasterizerCellsAa::new();
660 let y = 10 << POLY_SUBPIXEL_SHIFT;
662 ras.line(0, y, 512, y);
663 ras.sort_cells();
664 }
667
668 #[test]
673 fn test_vertical_line_generates_cells() {
674 let mut ras = RasterizerCellsAa::new();
675 let x = 10 << POLY_SUBPIXEL_SHIFT;
676 let y1 = 5 << POLY_SUBPIXEL_SHIFT;
677 let y2 = 15 << POLY_SUBPIXEL_SHIFT;
678 ras.line(x, y1, x, y2);
679 ras.sort_cells();
680 assert!(ras.total_cells() > 0);
681 assert_eq!(ras.min_y(), 5);
683 assert_eq!(ras.max_y(), 15);
684 }
685
686 #[test]
687 fn test_vertical_line_cover_sum() {
688 let mut ras = RasterizerCellsAa::new();
689 let x = (10 << POLY_SUBPIXEL_SHIFT) + 128; let y1 = 5 << POLY_SUBPIXEL_SHIFT;
692 let y2 = 8 << POLY_SUBPIXEL_SHIFT;
693 ras.line(x, y1, x, y2);
694 ras.sort_cells();
695
696 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
698 assert_eq!(total_cover, (y2 - y1) >> 0); assert_eq!(total_cover, 3 * POLY_SUBPIXEL_SCALE as i32);
702 }
703
704 #[test]
709 fn test_diagonal_line_generates_cells() {
710 let mut ras = RasterizerCellsAa::new();
711 let x1 = 0;
712 let y1 = 0;
713 let x2 = 10 << POLY_SUBPIXEL_SHIFT;
714 let y2 = 10 << POLY_SUBPIXEL_SHIFT;
715 ras.line(x1, y1, x2, y2);
716 ras.sort_cells();
717 assert!(ras.total_cells() > 0);
718 assert_eq!(ras.min_x(), 0);
719 assert_eq!(ras.min_y(), 0);
720 assert_eq!(ras.max_x(), 10);
721 assert_eq!(ras.max_y(), 10);
722 }
723
724 #[test]
725 fn test_diagonal_line_cover_sum() {
726 let mut ras = RasterizerCellsAa::new();
727 let x1 = 0;
728 let y1 = 0;
729 let x2 = 5 << POLY_SUBPIXEL_SHIFT;
730 let y2 = 5 << POLY_SUBPIXEL_SHIFT;
731 ras.line(x1, y1, x2, y2);
732 ras.sort_cells();
733
734 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
736 assert_eq!(total_cover, 5 * POLY_SUBPIXEL_SCALE as i32);
737 }
738
739 #[test]
744 fn test_sort_cells_idempotent() {
745 let mut ras = RasterizerCellsAa::new();
746 let x = 5 << POLY_SUBPIXEL_SHIFT;
747 ras.line(x, 0, x, 3 << POLY_SUBPIXEL_SHIFT);
748 ras.sort_cells();
749 let count1 = ras.total_cells();
750 ras.sort_cells(); assert_eq!(ras.total_cells(), count1);
752 }
753
754 #[test]
755 fn test_sort_empty_rasterizer() {
756 let mut ras = RasterizerCellsAa::new();
757 ras.sort_cells();
758 assert_eq!(ras.total_cells(), 0);
759 }
760
761 #[test]
762 fn test_scanline_query() {
763 let mut ras = RasterizerCellsAa::new();
764 let x = 5 << POLY_SUBPIXEL_SHIFT;
765 ras.line(x, 2 << POLY_SUBPIXEL_SHIFT, x, 5 << POLY_SUBPIXEL_SHIFT);
766 ras.sort_cells();
767
768 for y in ras.min_y()..=ras.max_y() {
770 let num = ras.scanline_num_cells(y as u32);
771 let indices = ras.scanline_cells(y as u32);
772 assert_eq!(indices.len(), num as usize);
773 for &idx in indices {
775 assert_eq!(ras.cell(idx).y, y);
776 }
777 }
778 }
779
780 #[test]
781 fn test_cells_sorted_by_x_within_scanline() {
782 let mut ras = RasterizerCellsAa::new();
783 ras.line(0, 0, 10 << POLY_SUBPIXEL_SHIFT, 1 << POLY_SUBPIXEL_SHIFT);
785 ras.sort_cells();
786
787 for y in ras.min_y()..=ras.max_y() {
788 let indices = ras.scanline_cells(y as u32);
789 for window in indices.windows(2) {
790 let x_a = ras.cell(window[0]).x;
791 let x_b = ras.cell(window[1]).x;
792 assert!(x_a <= x_b, "Cells not sorted by X: {} > {}", x_a, x_b);
793 }
794 }
795 }
796
797 #[test]
802 fn test_triangle_closed_polygon() {
803 let mut ras = RasterizerCellsAa::new();
804 let s = POLY_SUBPIXEL_SCALE as i32;
805 ras.line(10 * s, 10 * s, 20 * s, 10 * s); ras.line(20 * s, 10 * s, 15 * s, 20 * s); ras.line(15 * s, 20 * s, 10 * s, 10 * s); ras.sort_cells();
810
811 assert!(ras.total_cells() > 0);
812 assert_eq!(ras.min_y(), 10);
813 assert_eq!(ras.max_y(), 20);
814 }
815
816 #[test]
821 fn test_large_dx_subdivision() {
822 let mut ras = RasterizerCellsAa::new();
823 let x1 = 0;
825 let y1 = 0;
826 let x2 = 20000 << POLY_SUBPIXEL_SHIFT;
827 let y2 = 1 << POLY_SUBPIXEL_SHIFT;
828 ras.line(x1, y1, x2, y2);
829 ras.sort_cells();
830 assert!(ras.total_cells() > 0);
832 }
833
834 #[test]
839 fn test_scanline_hit_test_add_cell() {
840 let mut ht = ScanlineHitTest::new(42);
841 assert!(!ht.hit());
842 ht.add_cell(41, 255);
843 assert!(!ht.hit());
844 ht.add_cell(42, 255);
845 assert!(ht.hit());
846 }
847
848 #[test]
849 fn test_scanline_hit_test_add_span() {
850 let mut ht = ScanlineHitTest::new(15);
851 assert!(!ht.hit());
852 ht.add_span(10, 4, 255); assert!(!ht.hit());
854 ht.add_span(10, 6, 255); assert!(ht.hit());
856 }
857
858 #[test]
859 fn test_scanline_hit_test_num_spans() {
860 let ht = ScanlineHitTest::new(0);
861 assert_eq!(ht.num_spans(), 1);
862 }
863}