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 pub fn add_cells_offset(&mut self, src: &[CellAa], dx: i32, dy: i32) {
201 self.sorted = false;
202 self.cells.reserve(src.len());
203 for c in src {
204 let x = c.x + dx;
205 let y = c.y + dy;
206 if x < self.min_x { self.min_x = x; }
207 if x > self.max_x { self.max_x = x; }
208 if y < self.min_y { self.min_y = y; }
209 if y > self.max_y { self.max_y = y; }
210 self.cells.push(CellAa { x, y, cover: c.cover, area: c.area });
211 }
212 }
213
214 #[inline]
220 fn add_curr_cell(&mut self) {
221 if self.curr_cell.area | self.curr_cell.cover != 0 {
222 self.cells.push(self.curr_cell);
223 }
224 }
225
226 #[inline]
228 pub fn add_curr_cell_public(&mut self) {
229 self.add_curr_cell();
230 }
231
232 #[inline]
234 fn set_curr_cell(&mut self, x: i32, y: i32) {
235 if self.curr_cell.not_equal(x, y, &self.style_cell) {
236 self.add_curr_cell();
237 self.curr_cell.style(&self.style_cell);
238 self.curr_cell.x = x;
239 self.curr_cell.y = y;
240 self.curr_cell.cover = 0;
241 self.curr_cell.area = 0;
242 }
243 }
244
245 fn render_hline(&mut self, ey: i32, x1: i32, y1: i32, x2: i32, y2: i32) {
253 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
254 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
255 let fx1 = x1 & POLY_SUBPIXEL_MASK as i32;
256 let fx2 = x2 & POLY_SUBPIXEL_MASK as i32;
257
258 if y1 == y2 {
260 self.set_curr_cell(ex2, ey);
261 return;
262 }
263
264 if ex1 == ex2 {
266 let delta = y2 - y1;
267 self.curr_cell.cover += delta;
268 self.curr_cell.area += (fx1 + fx2) * delta;
269 return;
270 }
271
272 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fx1 as i64) * (y2 - y1) as i64;
274 let mut first = POLY_SUBPIXEL_SCALE as i32;
275 let mut incr = 1_i32;
276
277 let mut dx = x2 as i64 - x1 as i64;
278
279 if dx < 0 {
280 p = fx1 as i64 * (y2 - y1) as i64;
281 first = 0;
282 incr = -1;
283 dx = -dx;
284 }
285
286 let mut delta = (p / dx) as i32;
287 let mut modulo = p % dx;
288
289 if modulo < 0 {
290 delta -= 1;
291 modulo += dx;
292 }
293
294 self.curr_cell.cover += delta;
295 self.curr_cell.area += (fx1 + first) * delta;
296
297 let mut ex1 = ex1 + incr;
298 self.set_curr_cell(ex1, ey);
299 let mut y1 = y1 + delta;
300
301 if ex1 != ex2 {
302 p = POLY_SUBPIXEL_SCALE as i64 * (y2 - y1 + delta) as i64;
303 let mut lift = (p / dx) as i32;
304 let mut rem = p % dx;
305
306 if rem < 0 {
307 lift -= 1;
308 rem += dx;
309 }
310
311 modulo -= dx;
312
313 while ex1 != ex2 {
314 delta = lift;
315 modulo += rem;
316 if modulo >= 0 {
317 modulo -= dx;
318 delta += 1;
319 }
320
321 self.curr_cell.cover += delta;
322 self.curr_cell.area += POLY_SUBPIXEL_SCALE as i32 * delta;
323 y1 += delta;
324 ex1 += incr;
325 self.set_curr_cell(ex1, ey);
326 }
327 }
328 delta = y2 - y1;
329 self.curr_cell.cover += delta;
330 self.curr_cell.area += (fx2 + POLY_SUBPIXEL_SCALE as i32 - first) * delta;
331 }
332
333 pub fn line(&mut self, x1: i32, y1: i32, x2: i32, y2: i32) {
338 let dx = x2 as i64 - x1 as i64;
339
340 if dx >= DX_LIMIT || dx <= -DX_LIMIT {
341 let cx = ((x1 as i64 + x2 as i64) >> 1) as i32;
342 let cy = ((y1 as i64 + y2 as i64) >> 1) as i32;
343 self.line(x1, y1, cx, cy);
344 self.line(cx, cy, x2, y2);
345 return;
346 }
347
348 let dy = y2 as i64 - y1 as i64;
349 let ex1 = x1 >> POLY_SUBPIXEL_SHIFT;
350 let ex2 = x2 >> POLY_SUBPIXEL_SHIFT;
351 let ey1_orig = y1 >> POLY_SUBPIXEL_SHIFT;
352 let ey2 = y2 >> POLY_SUBPIXEL_SHIFT;
353 let fy1 = y1 & POLY_SUBPIXEL_MASK as i32;
354 let fy2 = y2 & POLY_SUBPIXEL_MASK as i32;
355
356 if ex1 < self.min_x {
358 self.min_x = ex1;
359 }
360 if ex1 > self.max_x {
361 self.max_x = ex1;
362 }
363 if ey1_orig < self.min_y {
364 self.min_y = ey1_orig;
365 }
366 if ey1_orig > self.max_y {
367 self.max_y = ey1_orig;
368 }
369 if ex2 < self.min_x {
370 self.min_x = ex2;
371 }
372 if ex2 > self.max_x {
373 self.max_x = ex2;
374 }
375 if ey2 < self.min_y {
376 self.min_y = ey2;
377 }
378 if ey2 > self.max_y {
379 self.max_y = ey2;
380 }
381
382 let mut ey1 = ey1_orig;
383
384 self.set_curr_cell(ex1, ey1);
385
386 if ey1 == ey2 {
388 self.render_hline(ey1, x1, fy1, x2, fy2);
389 return;
390 }
391
392 let mut incr = 1_i32;
394 if dx == 0 {
395 let ex = x1 >> POLY_SUBPIXEL_SHIFT;
396 let two_fx = (x1 - (ex << POLY_SUBPIXEL_SHIFT)) << 1;
397
398 let mut first = POLY_SUBPIXEL_SCALE as i32;
399 if dy < 0 {
400 first = 0;
401 incr = -1;
402 }
403
404 let x_from = x1;
405 let _ = x_from; let mut delta = first - fy1;
408 self.curr_cell.cover += delta;
409 self.curr_cell.area += two_fx * delta;
410
411 ey1 += incr;
412 self.set_curr_cell(ex, ey1);
413
414 delta = first + first - POLY_SUBPIXEL_SCALE as i32;
415 let area = two_fx * delta;
416 while ey1 != ey2 {
417 self.curr_cell.cover = delta;
418 self.curr_cell.area = area;
419 ey1 += incr;
420 self.set_curr_cell(ex, ey1);
421 }
422 delta = fy2 - POLY_SUBPIXEL_SCALE as i32 + first;
423 self.curr_cell.cover += delta;
424 self.curr_cell.area += two_fx * delta;
425 return;
426 }
427
428 let mut p = (POLY_SUBPIXEL_SCALE as i64 - fy1 as i64) * dx;
430 let mut first = POLY_SUBPIXEL_SCALE as i32;
431
432 let mut dy_abs = dy;
433 if dy < 0 {
434 p = fy1 as i64 * dx;
435 first = 0;
436 incr = -1;
437 dy_abs = -dy;
438 }
439
440 let mut delta = (p / dy_abs) as i32;
441 let mut modulo = p % dy_abs;
442
443 if modulo < 0 {
444 delta -= 1;
445 modulo += dy_abs;
446 }
447
448 let mut x_from = x1 + delta;
449 self.render_hline(ey1, x1, fy1, x_from, first);
450
451 ey1 += incr;
452 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
453
454 if ey1 != ey2 {
455 p = POLY_SUBPIXEL_SCALE as i64 * dx;
456 let mut lift = (p / dy_abs) as i32;
457 let mut rem = p % dy_abs;
458
459 if rem < 0 {
460 lift -= 1;
461 rem += dy_abs;
462 }
463 modulo -= dy_abs;
464
465 while ey1 != ey2 {
466 delta = lift;
467 modulo += rem;
468 if modulo >= 0 {
469 modulo -= dy_abs;
470 delta += 1;
471 }
472
473 let x_to = x_from + delta;
474 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x_to, first);
475 x_from = x_to;
476
477 ey1 += incr;
478 self.set_curr_cell(x_from >> POLY_SUBPIXEL_SHIFT, ey1);
479 }
480 }
481 self.render_hline(ey1, x_from, POLY_SUBPIXEL_SCALE as i32 - first, x2, fy2);
482 }
483
484 pub fn sort_cells(&mut self) {
489 if self.sorted {
490 return;
491 }
492
493 self.add_curr_cell();
494 self.curr_cell.x = i32::MAX;
495 self.curr_cell.y = i32::MAX;
496 self.curr_cell.cover = 0;
497 self.curr_cell.area = 0;
498
499 if self.cells.is_empty() {
500 return;
501 }
502
503 let num_cells = self.cells.len();
505 self.sorted_cells.clear();
506 self.sorted_cells.resize(num_cells, 0);
507
508 let y_range = (self.max_y - self.min_y + 1) as usize;
509 self.sorted_y.clear();
510 self.sorted_y.resize(y_range, SortedY::default());
511
512 for cell in &self.cells {
514 let yi = (cell.y - self.min_y) as usize;
515 self.sorted_y[yi].start += 1;
516 }
517
518 let mut start = 0u32;
520 for sy in &mut self.sorted_y {
521 let count = sy.start;
522 sy.start = start;
523 start += count;
524 }
525
526 for (i, cell) in self.cells.iter().enumerate() {
528 let yi = (cell.y - self.min_y) as usize;
529 let sy = &mut self.sorted_y[yi];
530 self.sorted_cells[(sy.start + sy.num) as usize] = i as u32;
531 sy.num += 1;
532 }
533
534 for sy in &self.sorted_y {
536 if sy.num > 0 {
537 let start = sy.start as usize;
538 let end = (sy.start + sy.num) as usize;
539 let slice = &mut self.sorted_cells[start..end];
540 let cells = &self.cells;
541 slice.sort_unstable_by_key(|&idx| cells[idx as usize].x);
542 }
543 }
544
545 self.sorted = true;
546 }
547}
548
549impl Default for RasterizerCellsAa {
550 fn default() -> Self {
551 Self::new()
552 }
553}
554
555pub struct ScanlineHitTest {
564 x: i32,
565 hit: bool,
566}
567
568impl ScanlineHitTest {
569 pub fn new(x: i32) -> Self {
570 Self { x, hit: false }
571 }
572
573 #[inline]
574 pub fn reset_spans(&mut self) {}
575
576 #[inline]
577 pub fn finalize(&mut self, _y: i32) {}
578
579 #[inline]
580 pub fn add_cell(&mut self, x: i32, _cover: u32) {
581 if self.x == x {
582 self.hit = true;
583 }
584 }
585
586 #[inline]
587 pub fn add_span(&mut self, x: i32, len: u32, _cover: u32) {
588 if self.x >= x && self.x < x + len as i32 {
589 self.hit = true;
590 }
591 }
592
593 #[inline]
594 pub fn num_spans(&self) -> u32 {
595 1
596 }
597
598 #[inline]
599 pub fn hit(&self) -> bool {
600 self.hit
601 }
602}
603
604#[cfg(test)]
609mod tests {
610 use super::*;
611
612 #[test]
617 fn test_cell_aa_default() {
618 let cell = CellAa::default();
619 assert_eq!(cell.x, i32::MAX);
620 assert_eq!(cell.y, i32::MAX);
621 assert_eq!(cell.cover, 0);
622 assert_eq!(cell.area, 0);
623 }
624
625 #[test]
626 fn test_cell_aa_initial() {
627 let mut cell = CellAa {
628 x: 10,
629 y: 20,
630 cover: 5,
631 area: 100,
632 };
633 cell.initial();
634 assert_eq!(cell.x, i32::MAX);
635 assert_eq!(cell.y, i32::MAX);
636 assert_eq!(cell.cover, 0);
637 assert_eq!(cell.area, 0);
638 }
639
640 #[test]
641 fn test_cell_aa_not_equal() {
642 let cell = CellAa {
643 x: 10,
644 y: 20,
645 cover: 0,
646 area: 0,
647 };
648 let style = CellAa::default();
649 assert!(!cell.not_equal(10, 20, &style));
650 assert!(cell.not_equal(11, 20, &style));
651 assert!(cell.not_equal(10, 21, &style));
652 assert!(cell.not_equal(11, 21, &style));
653 }
654
655 #[test]
660 fn test_new_rasterizer_is_empty() {
661 let ras = RasterizerCellsAa::new();
662 assert_eq!(ras.total_cells(), 0);
663 assert!(!ras.sorted());
664 assert_eq!(ras.min_x(), i32::MAX);
665 assert_eq!(ras.min_y(), i32::MAX);
666 assert_eq!(ras.max_x(), i32::MIN);
667 assert_eq!(ras.max_y(), i32::MIN);
668 }
669
670 #[test]
671 fn test_reset() {
672 let mut ras = RasterizerCellsAa::new();
673 ras.line(0, 0, 256, 256);
675 assert!(ras.total_cells() > 0 || true); ras.reset();
677 assert_eq!(ras.total_cells(), 0);
678 assert!(!ras.sorted());
679 }
680
681 #[test]
686 fn test_horizontal_line_no_cells() {
687 let mut ras = RasterizerCellsAa::new();
688 let y = 10 << POLY_SUBPIXEL_SHIFT;
690 ras.line(0, y, 512, y);
691 ras.sort_cells();
692 }
695
696 #[test]
701 fn test_vertical_line_generates_cells() {
702 let mut ras = RasterizerCellsAa::new();
703 let x = 10 << POLY_SUBPIXEL_SHIFT;
704 let y1 = 5 << POLY_SUBPIXEL_SHIFT;
705 let y2 = 15 << POLY_SUBPIXEL_SHIFT;
706 ras.line(x, y1, x, y2);
707 ras.sort_cells();
708 assert!(ras.total_cells() > 0);
709 assert_eq!(ras.min_y(), 5);
711 assert_eq!(ras.max_y(), 15);
712 }
713
714 #[test]
715 fn test_vertical_line_cover_sum() {
716 let mut ras = RasterizerCellsAa::new();
717 let x = (10 << POLY_SUBPIXEL_SHIFT) + 128; let y1 = 5 << POLY_SUBPIXEL_SHIFT;
720 let y2 = 8 << POLY_SUBPIXEL_SHIFT;
721 ras.line(x, y1, x, y2);
722 ras.sort_cells();
723
724 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
726 assert_eq!(total_cover, (y2 - y1) >> 0); assert_eq!(total_cover, 3 * POLY_SUBPIXEL_SCALE as i32);
730 }
731
732 #[test]
737 fn test_diagonal_line_generates_cells() {
738 let mut ras = RasterizerCellsAa::new();
739 let x1 = 0;
740 let y1 = 0;
741 let x2 = 10 << POLY_SUBPIXEL_SHIFT;
742 let y2 = 10 << POLY_SUBPIXEL_SHIFT;
743 ras.line(x1, y1, x2, y2);
744 ras.sort_cells();
745 assert!(ras.total_cells() > 0);
746 assert_eq!(ras.min_x(), 0);
747 assert_eq!(ras.min_y(), 0);
748 assert_eq!(ras.max_x(), 10);
749 assert_eq!(ras.max_y(), 10);
750 }
751
752 #[test]
753 fn test_diagonal_line_cover_sum() {
754 let mut ras = RasterizerCellsAa::new();
755 let x1 = 0;
756 let y1 = 0;
757 let x2 = 5 << POLY_SUBPIXEL_SHIFT;
758 let y2 = 5 << POLY_SUBPIXEL_SHIFT;
759 ras.line(x1, y1, x2, y2);
760 ras.sort_cells();
761
762 let total_cover: i32 = ras.cells.iter().map(|c| c.cover).sum();
764 assert_eq!(total_cover, 5 * POLY_SUBPIXEL_SCALE as i32);
765 }
766
767 #[test]
772 fn test_sort_cells_idempotent() {
773 let mut ras = RasterizerCellsAa::new();
774 let x = 5 << POLY_SUBPIXEL_SHIFT;
775 ras.line(x, 0, x, 3 << POLY_SUBPIXEL_SHIFT);
776 ras.sort_cells();
777 let count1 = ras.total_cells();
778 ras.sort_cells(); assert_eq!(ras.total_cells(), count1);
780 }
781
782 #[test]
783 fn test_sort_empty_rasterizer() {
784 let mut ras = RasterizerCellsAa::new();
785 ras.sort_cells();
786 assert_eq!(ras.total_cells(), 0);
787 }
788
789 #[test]
790 fn test_scanline_query() {
791 let mut ras = RasterizerCellsAa::new();
792 let x = 5 << POLY_SUBPIXEL_SHIFT;
793 ras.line(x, 2 << POLY_SUBPIXEL_SHIFT, x, 5 << POLY_SUBPIXEL_SHIFT);
794 ras.sort_cells();
795
796 for y in ras.min_y()..=ras.max_y() {
798 let num = ras.scanline_num_cells(y as u32);
799 let indices = ras.scanline_cells(y as u32);
800 assert_eq!(indices.len(), num as usize);
801 for &idx in indices {
803 assert_eq!(ras.cell(idx).y, y);
804 }
805 }
806 }
807
808 #[test]
809 fn test_cells_sorted_by_x_within_scanline() {
810 let mut ras = RasterizerCellsAa::new();
811 ras.line(0, 0, 10 << POLY_SUBPIXEL_SHIFT, 1 << POLY_SUBPIXEL_SHIFT);
813 ras.sort_cells();
814
815 for y in ras.min_y()..=ras.max_y() {
816 let indices = ras.scanline_cells(y as u32);
817 for window in indices.windows(2) {
818 let x_a = ras.cell(window[0]).x;
819 let x_b = ras.cell(window[1]).x;
820 assert!(x_a <= x_b, "Cells not sorted by X: {} > {}", x_a, x_b);
821 }
822 }
823 }
824
825 #[test]
830 fn test_triangle_closed_polygon() {
831 let mut ras = RasterizerCellsAa::new();
832 let s = POLY_SUBPIXEL_SCALE as i32;
833 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();
838
839 assert!(ras.total_cells() > 0);
840 assert_eq!(ras.min_y(), 10);
841 assert_eq!(ras.max_y(), 20);
842 }
843
844 #[test]
849 fn test_large_dx_subdivision() {
850 let mut ras = RasterizerCellsAa::new();
851 let x1 = 0;
853 let y1 = 0;
854 let x2 = 20000 << POLY_SUBPIXEL_SHIFT;
855 let y2 = 1 << POLY_SUBPIXEL_SHIFT;
856 ras.line(x1, y1, x2, y2);
857 ras.sort_cells();
858 assert!(ras.total_cells() > 0);
860 }
861
862 #[test]
867 fn test_scanline_hit_test_add_cell() {
868 let mut ht = ScanlineHitTest::new(42);
869 assert!(!ht.hit());
870 ht.add_cell(41, 255);
871 assert!(!ht.hit());
872 ht.add_cell(42, 255);
873 assert!(ht.hit());
874 }
875
876 #[test]
877 fn test_scanline_hit_test_add_span() {
878 let mut ht = ScanlineHitTest::new(15);
879 assert!(!ht.hit());
880 ht.add_span(10, 4, 255); assert!(!ht.hit());
882 ht.add_span(10, 6, 255); assert!(ht.hit());
884 }
885
886 #[test]
887 fn test_scanline_hit_test_num_spans() {
888 let ht = ScanlineHitTest::new(0);
889 assert_eq!(ht.num_spans(), 1);
890 }
891}