1#[derive(Debug, Copy, Clone, PartialEq, Eq)]
6pub struct Rect {
7 pub x: u16,
8 pub y: u16,
9 pub w: u16,
10 pub h: u16,
11}
12
13impl Rect {
14 pub fn new(x: u16, y: u16, w: u16, h: u16) -> Self {
15 Self { x, y, w, h }
16 }
17
18 pub fn is_empty(&self) -> bool {
19 self.w == 0 || self.h == 0
20 }
21
22 pub fn right(&self) -> u16 {
23 self.x.saturating_add(self.w)
24 }
25
26 pub fn bottom(&self) -> u16 {
27 self.y.saturating_add(self.h)
28 }
29
30 pub fn intersects_or_touches(&self, other: &Rect) -> bool {
31 let ax1 = self.x;
33 let ay1 = self.y;
34 let ax2 = self.right();
35 let ay2 = self.bottom();
36
37 let bx1 = other.x;
38 let by1 = other.y;
39 let bx2 = other.right();
40 let by2 = other.bottom();
41
42 !(ax2 < bx1 || bx2 < ax1 || ay2 < by1 || by2 < ay1)
43 }
44
45 pub fn union(&self, other: &Rect) -> Rect {
46 let x1 = self.x.min(other.x);
47 let y1 = self.y.min(other.y);
48 let x2 = self.right().max(other.right());
49 let y2 = self.bottom().max(other.bottom());
50 Rect::new(x1, y1, x2.saturating_sub(x1), y2.saturating_sub(y1))
51 }
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct Damage {
56 pub full_redraw: bool,
57 pub rects: Vec<Rect>,
58}
59
60impl Damage {
61 pub fn empty() -> Self {
62 Self {
63 full_redraw: false,
64 rects: Vec::new(),
65 }
66 }
67
68 pub fn full() -> Self {
69 Self {
70 full_redraw: true,
71 rects: Vec::new(),
72 }
73 }
74
75 pub fn push_rect(&mut self, rect: Rect, max_rects: usize) {
76 if self.full_redraw {
77 return;
78 }
79 if rect.is_empty() {
80 return;
81 }
82
83 self.rects.push(rect);
84 self.merge_in_place();
85
86 if self.rects.len() > max_rects {
87 self.full_redraw = true;
88 self.rects.clear();
89 }
90 }
91
92 fn merge_in_place(&mut self) {
93 let mut out: Vec<Rect> = Vec::with_capacity(self.rects.len());
95 for r in self.rects.drain(..) {
96 let mut merged = r;
97 let mut i = 0;
98 while i < out.len() {
99 if merged.intersects_or_touches(&out[i]) {
100 merged = merged.union(&out[i]);
101 out.remove(i);
102 i = 0;
103 } else {
104 i += 1;
105 }
106 }
107 out.push(merged);
108 }
109 self.rects = out;
110 }
111}