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 pub(crate) 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 pub fn add_cells_offset(&mut self, src: &[CellAa], dx: i32, dy: i32) {
217 self.sorted = false;
218 self.cells.reserve(src.len());
219 for c in src {
220 let x = c.x + dx;
221 let y = c.y + dy;
222 if x < self.min_x {
223 self.min_x = x;
224 }
225 if x > self.max_x {
226 self.max_x = x;
227 }
228 if y < self.min_y {
229 self.min_y = y;
230 }
231 if y > self.max_y {
232 self.max_y = y;
233 }
234 self.cells.push(CellAa {
235 x,
236 y,
237 cover: c.cover,
238 area: c.area,
239 });
240 }
241 }
242
243 #[inline]
245 fn set_curr_cell(&mut self, x: i32, y: i32) {
246 if self.curr_cell.not_equal(x, y, &self.style_cell) {
247 self.add_curr_cell();
248 self.curr_cell.style(&self.style_cell);
249 self.curr_cell.x = x;
250 self.curr_cell.y = y;
251 self.curr_cell.cover = 0;
252 self.curr_cell.area = 0;
253 }
254 }
255
256 fn render_hline(&mut self, ey: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
264 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
265 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
266 let fx1 = x1 & POLY_SUBPIXEL_MASK as i32;
267 let fx2 = x2 & POLY_SUBPIXEL_MASK as i32;
268
269 if y1 == y2 {
271 self.set_curr_cell(ex2, ey);
272 return;
273 }
274
275 if ex1 == ex2 {
277 let delta = y2 - y1;
278 self.curr_cell.cover += delta;
279 self.curr_cell.area += (fx1 + fx2) * delta;
280 return;
281 }
282
283 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fx1 as i64) * (y2 - y1) as i64;
285 let mut first = POLY_SUBPIXEL_SCALE as i32;
286 let mut incr = 1_i32;
287
288 let mut dx = x2 as i64 - x1 as i64;
289
290 if dx < 0 {
291 p = fx1 as i64 * (y2 - y1) as i64;
292 first = 0;
293 incr = -1;
294 dx = -dx;
295 }
296
297 let mut delta = (p / dx) as i32;
298 let mut modulo = p % dx;
299
300 if modulo < 0 {
301 delta -= 1;
302 modulo += dx;
303 }
304
305 self.curr_cell.cover += delta;
306 self.curr_cell.area += (fx1 + first) * delta;
307
308 let mut ex1 = ex1 + incr;
309 self.set_curr_cell(ex1, ey);
310 let mut y1 = y1 + delta;
311
312 if ex1 != ex2 {
313 p = POLY_SUBPIXEL_SCALE as i64 * (y2 - y1 + delta) as i64;
314 let mut lift = (p / dx) as i32;
315 let mut rem = p % dx;
316
317 if rem < 0 {
318 lift -= 1;
319 rem += dx;
320 }
321
322 modulo -= dx;
323
324 while ex1 != ex2 {
325 delta = lift;
326 modulo += rem;
327 if modulo >= 0 {
328 modulo -= dx;
329 delta += 1;
330 }
331
332 self.curr_cell.cover += delta;
333 self.curr_cell.area += POLY_SUBPIXEL_SCALE as i32 * delta;
334 y1 += delta;
335 ex1 += incr;
336 self.set_curr_cell(ex1, ey);
337 }
338 }
339 delta = y2 - y1;
340 self.curr_cell.cover += delta;
341 self.curr_cell.area += (fx2 + POLY_SUBPIXEL_SCALE as i32 - first) * delta;
342 }
343
344 pub fn line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32) {
349 let dx = x2 as i64 - x1 as i64;
350
351 if dx >= DX_LIMIT || dx <= -DX_LIMIT {
352 let cx = ((x1 as i64 + x2 as i64) >> 1) as i32;
353 let cy = ((y1 as i64 + y2 as i64) >> 1) as i32;
354 self.line(x1, y1, cx, cy);
355 self.line(cx, cy, x2, y2);
356 return;
357 }
358
359 let dy = y2 as i64 - y1 as i64;
360 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
361 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
362 let ey1_orig = y1 >> POLY_SUBPIXEL_SHIFT;
363 let ey2 = y2 >> POLY_SUBPIXEL_SHIFT;
364 let fy1 = y1 & POLY_SUBPIXEL_MASK as i32;
365 let fy2 = y2 & POLY_SUBPIXEL_MASK as i32;
366
367 if ex1 < self.min_x {
369 self.min_x = ex1;
370 }
371 if ex1 > self.max_x {
372 self.max_x = ex1;
373 }
374 if ey1_orig < self.min_y {
375 self.min_y = ey1_orig;
376 }
377 if ey1_orig > self.max_y {
378 self.max_y = ey1_orig;
379 }
380 if ex2 < self.min_x {
381 self.min_x = ex2;
382 }
383 if ex2 > self.max_x {
384 self.max_x = ex2;
385 }
386 if ey2 < self.min_y {
387 self.min_y = ey2;
388 }
389 if ey2 > self.max_y {
390 self.max_y = ey2;
391 }
392
393 let mut ey1 = ey1_orig;
394
395 self.set_curr_cell(ex1, ey1);
396
397 if ey1 == ey2 {
399 self.render_hline(ey1, x1, fy1, x2, fy2);
400 return;
401 }
402
403 let mut incr = 1_i32;
405 if dx == 0 {
406 let ex = x1 >> POLY_SUBPIXEL_SHIFT;
407 let two_fx = (x1 - (ex << POLY_SUBPIXEL_SHIFT)) << 1;
408
409 let mut first = POLY_SUBPIXEL_SCALE as i32;
410 if dy < 0 {
411 first = 0;
412 incr = -1;
413 }
414
415 let x_from = x1;
416 let _ = x_from; let mut delta = first - fy1;
419 self.curr_cell.cover += delta;
420 self.curr_cell.area += two_fx * delta;
421
422 ey1 += incr;
423 self.set_curr_cell(ex, ey1);
424
425 delta = first + first - POLY_SUBPIXEL_SCALE as i32;
426 let area = two_fx * delta;
427 while ey1 != ey2 {
428 self.curr_cell.cover = delta;
429 self.curr_cell.area = area;
430 ey1 += incr;
431 self.set_curr_cell(ex, ey1);
432 }
433 delta = fy2 - POLY_SUBPIXEL_SCALE as i32 + first;
434 self.curr_cell.cover += delta;
435 self.curr_cell.area += two_fx * delta;
436 return;
437 }
438
439 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fy1 as i64) * dx;
441 let mut first = POLY_SUBPIXEL_SCALE as i32;
442
443 let mut dy_abs = dy;
444 if dy < 0 {
445 p = fy1 as i64 * dx;
446 first = 0;
447 incr = -1;
448 dy_abs = -dy;
449 }
450
451 let mut delta = (p / dy_abs) as i32;
452 let mut modulo = p % dy_abs;
453
454 if modulo < 0 {
455 delta -= 1;
456 modulo += dy_abs;
457 }
458
459 let mut x_from = x1 + delta;
460 self.render_hline(ey1, x1, fy1, x_from, first);
461
462 ey1 += incr;
463 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
464
465 if ey1 != ey2 {
466 p = POLY_SUBPIXEL_SCALE as i64 * dx;
467 let mut lift = (p / dy_abs) as i32;
468 let mut rem = p % dy_abs;
469
470 if rem < 0 {
471 lift -= 1;
472 rem += dy_abs;
473 }
474 modulo -= dy_abs;
475
476 while ey1 != ey2 {
477 delta = lift;
478 modulo += rem;
479 if modulo >= 0 {
480 modulo -= dy_abs;
481 delta += 1;
482 }
483
484 let x_to = x_from + delta;
485 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x_to, first);
486 x_from = x_to;
487
488 ey1 += incr;
489 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
490 }
491 }
492 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x2, fy2);
493 }
494
495 pub fn sort_cells(&mut self) {
500 if self.sorted {
501 return;
502 }
503
504 self.add_curr_cell();
505 self.curr_cell.x = i32::MAX;
506 self.curr_cell.y = i32::MAX;
507 self.curr_cell.cover = 0;
508 self.curr_cell.area = 0;
509
510 if self.cells.is_empty() {
511 return;
512 }
513
514 let num_cells = self.cells.len();
516 self.sorted_cells.clear();
517 self.sorted_cells.resize(num_cells, 0);
518
519 let y_range = (self.max_y - self.min_y + 1) as usize;
520 self.sorted_y.clear();
521 self.sorted_y.resize(y_range, SortedY::default());
522
523 for cell in &self.cells {
525 let yi = (cell.y - self.min_y) as usize;
526 self.sorted_y[yi].start += 1;
527 }
528
529 let mut start = 0u32;
531 for sy in &mut self.sorted_y {
532 let count = sy.start;
533 sy.start = start;
534 start += count;
535 }
536
537 for (i, cell) in self.cells.iter().enumerate() {
539 let yi = (cell.y - self.min_y) as usize;
540 let sy = &mut self.sorted_y[yi];
541 self.sorted_cells[(sy.start + sy.num) as usize] = i as u32;
542 sy.num += 1;
543 }
544
545 for sy in &self.sorted_y {
547 if sy.num > 0 {
548 let start = sy.start as usize;
549 let end = (sy.start + sy.num) as usize;
550 let slice = &mut self.sorted_cells[start..end];
551 let cells = &self.cells;
552 slice.sort_unstable_by_key(|&idx| cells[idx as usize].x);
553 }
554 }
555
556 self.sorted = true;
557 }
558}
559
560impl Default for RasterizerCellsAa {
561 fn default() -> Self {
562 Self::new()
563 }
564}
565
566pub struct ScanlineHitTest {
575 x: i32,
576 hit: bool,
577}
578
579impl ScanlineHitTest {
580 pub fn new(x: i32) -> Self {
581 Self { x, hit: false }
582 }
583
584 #[inline]
585 pub fn reset_spans(&mut self) {}
586
587 #[inline]
588 pub fn finalize(&mut self, _y: i32) {}
589
590 #[inline]
591 pub fn add_cell(&mut self, x: i32, _cover: u32) {
592 if self.x == x {
593 self.hit = true;
594 }
595 }
596
597 #[inline]
598 pub fn add_span(&mut self, x: i32, len: u32, _cover: u32) {
599 if self.x >= x && self.x < x + len as i32 {
600 self.hit = true;
601 }
602 }
603
604 #[inline]
605 pub fn num_spans(&self) -> u32 {
606 1
607 }
608
609 #[inline]
610 pub fn hit(&self) -> bool {
611 self.hit
612 }
613}
614
615#[cfg(test)]
620mod tests {
621 use super::*;
622
623 #[test]
628 fn test_cell_aa_default() {
629 let cell = CellAa::default();
630 assert_eq!(cell.x, i32::MAX);
631 assert_eq!(cell.y, i32::MAX);
632 assert_eq!(cell.cover, 0);
633 assert_eq!(cell.area, 0);
634 }
635
636 #[test]
637 fn test_cell_aa_initial() {
638 let mut cell = CellAa {
639 x: 10,
640 y: 20,
641 cover: 5,
642 area: 100,
643 };
644 cell.initial();
645 assert_eq!(cell.x, i32::MAX);
646 assert_eq!(cell.y, i32::MAX);
647 assert_eq!(cell.cover, 0);
648 assert_eq!(cell.area, 0);
649 }
650
651 #[test]
652 fn test_cell_aa_not_equal() {
653 let cell = CellAa {
654 x: 10,
655 y: 20,
656 cover: 0,
657 area: 0,
658 };
659 let style = CellAa::default();
660 assert!(!cell.not_equal(10, 20, &style));
661 assert!(cell.not_equal(11, 20, &style));
662 assert!(cell.not_equal(10, 21, &style));
663 assert!(cell.not_equal(11, 21, &style));
664 }
665
666 #[test]
671 fn test_new_rasterizer_is_empty() {
672 let ras = RasterizerCellsAa::new();
673 assert_eq!(ras.total_cells(), 0);
674 assert!(!ras.sorted());
675 assert_eq!(ras.min_x(), i32::MAX);
676 assert_eq!(ras.min_y(), i32::MAX);
677 assert_eq!(ras.max_x(), i32::MIN);
678 assert_eq!(ras.max_y(), i32::MIN);
679 }
680
681 #[test]
682 fn test_reset() {
683 let mut ras = RasterizerCellsAa::new();
684 ras.line(0, 0, 256, 256);
686 assert!(ras.total_cells() > 0 || true); ras.reset();
688 assert_eq!(ras.total_cells(), 0);
689 assert!(!ras.sorted());
690 }
691
692 #[test]
697 fn test_horizontal_line_no_cells() {
698 let mut ras = RasterizerCellsAa::new();
699 let y = 10 << POLY_SUBPIXEL_SHIFT;
701 ras.line(0, y, 512, y);
702 ras.sort_cells();
703 }
706
707 #[test]
712 fn test_vertical_line_generates_cells() {
713 let mut ras = RasterizerCellsAa::new();
714 let x = 10 << POLY_SUBPIXEL_SHIFT;
715 let y1 = 5 << POLY_SUBPIXEL_SHIFT;
716 let y2 = 15 << POLY_SUBPIXEL_SHIFT;
717 ras.line(x, y1, x, y2);
718 ras.sort_cells();
719 assert!(ras.total_cells() > 0);
720 assert_eq!(ras.min_y(), 5);
722 assert_eq!(ras.max_y(), 15);
723 }
724
725 #[test]
726 fn test_vertical_line_cover_sum() {
727 let mut ras = RasterizerCellsAa::new();
728 let x = (10 << POLY_SUBPIXEL_SHIFT) + 128; let y1 = 5 << POLY_SUBPIXEL_SHIFT;
731 let y2 = 8 << POLY_SUBPIXEL_SHIFT;
732 ras.line(x, y1, x, y2);
733 ras.sort_cells();
734
735 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
737 assert_eq!(total_cover, (y2 - y1) >> 0); assert_eq!(total_cover, 3 * POLY_SUBPIXEL_SCALE as i32);
741 }
742
743 #[test]
748 fn test_diagonal_line_generates_cells() {
749 let mut ras = RasterizerCellsAa::new();
750 let x1 = 0;
751 let y1 = 0;
752 let x2 = 10 << POLY_SUBPIXEL_SHIFT;
753 let y2 = 10 << POLY_SUBPIXEL_SHIFT;
754 ras.line(x1, y1, x2, y2);
755 ras.sort_cells();
756 assert!(ras.total_cells() > 0);
757 assert_eq!(ras.min_x(), 0);
758 assert_eq!(ras.min_y(), 0);
759 assert_eq!(ras.max_x(), 10);
760 assert_eq!(ras.max_y(), 10);
761 }
762
763 #[test]
764 fn test_diagonal_line_cover_sum() {
765 let mut ras = RasterizerCellsAa::new();
766 let x1 = 0;
767 let y1 = 0;
768 let x2 = 5 << POLY_SUBPIXEL_SHIFT;
769 let y2 = 5 << POLY_SUBPIXEL_SHIFT;
770 ras.line(x1, y1, x2, y2);
771 ras.sort_cells();
772
773 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
775 assert_eq!(total_cover, 5 * POLY_SUBPIXEL_SCALE as i32);
776 }
777
778 #[test]
783 fn test_sort_cells_idempotent() {
784 let mut ras = RasterizerCellsAa::new();
785 let x = 5 << POLY_SUBPIXEL_SHIFT;
786 ras.line(x, 0, x, 3 << POLY_SUBPIXEL_SHIFT);
787 ras.sort_cells();
788 let count1 = ras.total_cells();
789 ras.sort_cells(); assert_eq!(ras.total_cells(), count1);
791 }
792
793 #[test]
794 fn test_sort_empty_rasterizer() {
795 let mut ras = RasterizerCellsAa::new();
796 ras.sort_cells();
797 assert_eq!(ras.total_cells(), 0);
798 }
799
800 #[test]
801 fn test_scanline_query() {
802 let mut ras = RasterizerCellsAa::new();
803 let x = 5 << POLY_SUBPIXEL_SHIFT;
804 ras.line(x, 2 << POLY_SUBPIXEL_SHIFT, x, 5 << POLY_SUBPIXEL_SHIFT);
805 ras.sort_cells();
806
807 for y in ras.min_y()..=ras.max_y() {
809 let num = ras.scanline_num_cells(y as u32);
810 let indices = ras.scanline_cells(y as u32);
811 assert_eq!(indices.len(), num as usize);
812 for &idx in indices {
814 assert_eq!(ras.cell(idx).y, y);
815 }
816 }
817 }
818
819 #[test]
820 fn test_cells_sorted_by_x_within_scanline() {
821 let mut ras = RasterizerCellsAa::new();
822 ras.line(0, 0, 10 << POLY_SUBPIXEL_SHIFT, 1 << POLY_SUBPIXEL_SHIFT);
824 ras.sort_cells();
825
826 for y in ras.min_y()..=ras.max_y() {
827 let indices = ras.scanline_cells(y as u32);
828 for window in indices.windows(2) {
829 let x_a = ras.cell(window[0]).x;
830 let x_b = ras.cell(window[1]).x;
831 assert!(x_a <= x_b, "Cells not sorted by X: {} > {}", x_a, x_b);
832 }
833 }
834 }
835
836 #[test]
841 fn test_triangle_closed_polygon() {
842 let mut ras = RasterizerCellsAa::new();
843 let s = POLY_SUBPIXEL_SCALE as i32;
844 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();
849
850 assert!(ras.total_cells() > 0);
851 assert_eq!(ras.min_y(), 10);
852 assert_eq!(ras.max_y(), 20);
853 }
854
855 #[test]
860 fn test_large_dx_subdivision() {
861 let mut ras = RasterizerCellsAa::new();
862 let x1 = 0;
864 let y1 = 0;
865 let x2 = 20000 << POLY_SUBPIXEL_SHIFT;
866 let y2 = 1 << POLY_SUBPIXEL_SHIFT;
867 ras.line(x1, y1, x2, y2);
868 ras.sort_cells();
869 assert!(ras.total_cells() > 0);
871 }
872
873 #[test]
878 fn test_scanline_hit_test_add_cell() {
879 let mut ht = ScanlineHitTest::new(42);
880 assert!(!ht.hit());
881 ht.add_cell(41, 255);
882 assert!(!ht.hit());
883 ht.add_cell(42, 255);
884 assert!(ht.hit());
885 }
886
887 #[test]
888 fn test_scanline_hit_test_add_span() {
889 let mut ht = ScanlineHitTest::new(15);
890 assert!(!ht.hit());
891 ht.add_span(10, 4, 255); assert!(!ht.hit());
893 ht.add_span(10, 6, 255); assert!(ht.hit());
895 }
896
897 #[test]
898 fn test_scanline_hit_test_num_spans() {
899 let ht = ScanlineHitTest::new(0);
900 assert_eq!(ht.num_spans(), 1);
901 }
902}