1use std::marker::PhantomData;
8
9
10use crate::core::buffer::Buff;
11use crate::types::rect::Rect;
12use crate::types::point::Point;
13
14pub trait Renderable<Pixel> {
17 fn render(&mut self, graphics: &mut Graphics<Pixel>, buffer: &mut Buff<Pixel>);
18}
19
20pub trait Sprite<Pixel> {
22 fn get(&mut self, x: usize, y: usize) -> &Pixel;
23 fn size(&self) -> (usize, usize);
24}
25
26
27pub struct Graphics<Pixel> {
30 x: usize,
31 y: usize,
32 w: usize,
33 h: usize,
34 _pixel: PhantomData<Pixel>,
35}
36
37impl <Pixel>Graphics<Pixel> {
38 pub fn new(x: usize, y: usize, w: usize, h: usize) -> Self {
40 return Self{x, y, w, h, _pixel: PhantomData};
41 }
42
43 pub fn set(&self, b: &mut Buff<Pixel>, x: usize, y: usize, p: &Pixel) {
45 let new_x = self.x + x;
46 let new_y = self.y + y;
47
48 if x < self.w && y < self.h {
49 b.set(new_x, new_y, p);
50 }
51 }
52
53 pub fn get_bounds(&mut self) -> Rect {
54 return Rect::new(self.x, self.y, self.w, self.h);
55 }
56
57 pub fn set_bounds(&mut self, bounds: &Rect) {
60 self.x = bounds.x;
61 self.y = bounds.y;
62 self.w = bounds.w;
63 self.h = bounds.h;
64 }
65
66 fn limit(min: usize, max: usize, actual: usize) -> usize {
67 if actual > max { return max }
68 if actual < min { return min }
69 return actual
70 }
71
72 pub fn draw_line(&self, buf: &mut Buff<Pixel>, p1: Point, p2: Point, p: &Pixel) {
74 let mut a = p1;
79 let mut b = p2;
80
81 let mut delta_x = b.x as isize - a.x as isize;
88 let mut delta_y = b.y as isize - a.y as isize;
89
90 let sign_x = delta_x.signum();
91 let sign_y = delta_y.signum();
92
93 delta_x = delta_x.abs();
94 delta_y = delta_y.abs();
95
96 b.x = (b.x as isize + sign_x) as usize;
97 b.y = (b.y as isize + sign_y) as usize;
98
99 self.set(buf, a.x, a.y, p);
100
101 if delta_x > delta_y {
102 let mut accum = delta_x / 2;
103 loop {
104 self.set(buf, a.x, a.y, p);
105 accum -= delta_y;
106 if accum < 0 {
107 accum += delta_x;
108 a.y = (a.y as isize + sign_y) as usize;
109 }
110 a.x = (a.x as isize + sign_x) as usize;
111
112 if a.x == b.x { break; }
113 }
114
115 } else {
116 let mut accum = delta_y / 2;
117 loop {
118 self.set(buf, a.x, a.y, p);
119
120 accum -= delta_x;
121 if accum < 0 {
122 accum += delta_y;
123 a.x = (a.x as isize + sign_x) as usize;
124 }
125 a.y = (a.y as isize + sign_y) as usize;
126
127 if a.y == b.y { break; }
128 }
129 }
130 }
131
132 pub fn draw_rect(&self, b: &mut Buff<Pixel>, r: Rect, p: &Pixel) {
134 for x in 0..r.w {
135 self.set(b, r.x + x, r.y, p);
136 self.set(b, r.x + x, r.y + r.h, p);
137 }
138 for y in 0..r.h {
139 self.set(b, r.x, r.y + y, p);
140 self.set(b, r.x + r.w, r.y + y, p);
141 }
142 }
143
144 pub fn fill_rect(&self, b: &mut Buff<Pixel>, r: Rect, p: &Pixel) {
146 for y in 0..r.h {
147 for x in 0..r.w {
148 self.set(b, r.x + x, r.y + y, p);
149 }
150 }
151 }
152
153 pub fn draw_polyline(&self, b: &mut Buff<Pixel>, points: &[Point], p: &Pixel) {
155 let len = points.len();
156 for i in 0..len-1 {
157 let p1 = points[i];
158 let p2 = points[i+1];
159 self.draw_line(b, p1, p2, p);
160 }
161 }
162
163 pub fn draw_ellipse(&self, buf: &mut Buff<Pixel>, r: Rect, p: &Pixel) {
165 let left = (r.x) as isize;
169 let right = (r.x + r.w) as isize;
170 let top = (r.y) as isize;
171 let bottom = (r.y + r.h) as isize;
172
173 let a = ((right - left + 1) / 2) as isize;
174 let b = ((bottom - top + 1) / 2) as isize;
175
176 if a != 0 && b != 0 {
177 let a2 = (a * a) as isize;
178 let b2 = (b * b) as isize;
179 let two_a2 = (a2 * 2) as isize;
180 let two_b2 = (b2 * 2) as isize;
181 let four_a2 = (a2 * 4) as isize;
182 let four_b2 = (b2 * 4) as isize;
183 let mut x = 0 as isize;
184 let mut y = b as isize;
185 let mut s = a2 * (1 - (b * 2)) + two_b2;
186 let mut t = b2 - two_a2 * ((b * 2) - 1);
187
188 self.set(buf, (right + x - a) as usize, (bottom + y - b) as usize, p);
189 self.set(buf, (left - x + a) as usize, (bottom + y - b) as usize, p);
190 self.set(buf, (left - x + a) as usize, (top - y + b) as usize, p);
191 self.set(buf, (right + x - a) as usize, (top - y + b) as usize, p);
192
193 loop {
194 if s < 0 {
195 s += two_b2 * ((x << 1) + 3);
196 t += four_b2 * (x + 1);
197 x += 1;
198 } else if t < 0 {
199 s += two_b2 * ((x << 1) + 3) - four_a2 * (y - 1);
200 t += four_b2 * (x + 1) - two_a2 * ((y << 1) - 3);
201 x += 1;
202 y -= 1;
203 } else {
204 s -= four_a2 * (y - 1);
205 t -= two_a2 * ((y << 1) - 3);
206 y -= 1;
207 }
208
209 self.set(buf, (right + x - a) as usize, (bottom + y - b) as usize, p);
210 self.set(buf, (left - x + a) as usize, (bottom + y - b) as usize, p);
211 self.set(buf, (left - x + a) as usize, (top - y + b) as usize, p);
212 self.set(buf, (right + x - a) as usize, (top - y + b) as usize, p);
213
214 if y <= 0 { break; }
215 }
216
217 }
218 }
219
220 }