1use crate::console::graphics::{ClampedInto, RasterOps};
19use crate::console::{PixelsXY, SizeInPixels};
20use std::convert::TryFrom;
21use std::io;
22
23fn draw_line_low<R>(rasops: &mut R, x1: i32, y1: i32, x2: i32, y2: i32) -> io::Result<()>
25where
26 R: RasterOps,
27{
28 let dx = x2 - x1;
29 let mut dy = y2 - y1;
30
31 let mut yi = 1;
32 if dy < 0 {
33 yi = -1;
34 dy = -dy;
35 }
36 let mut d = (2 * dy) - dx;
37 let mut y = y1;
38
39 for x in x1..(x2 + 1) {
40 if cfg!(debug_assertions) {
41 rasops.draw_pixel(PixelsXY {
42 x: i16::try_from(x).expect("Coordinate must fit after computations"),
43 y: i16::try_from(y).expect("Coordinate must fit after computations"),
44 })?;
45 } else {
46 rasops.draw_pixel(PixelsXY { x: x as i16, y: y as i16 })?;
47 }
48 if d > 0 {
49 y += yi;
50 d += 2 * (dy - dx);
51 } else {
52 d += 2 * dy;
53 }
54 }
55
56 Ok(())
57}
58
59fn draw_line_high<R>(rasops: &mut R, x1: i32, y1: i32, x2: i32, y2: i32) -> io::Result<()>
61where
62 R: RasterOps,
63{
64 let mut dx = x2 - x1;
65 let dy = y2 - y1;
66
67 let mut xi = 1;
68 if dx < 0 {
69 xi = -1;
70 dx = -dx;
71 }
72 let mut d = (2 * dx) - dy;
73 let mut x = x1;
74
75 for y in y1..(y2 + 1) {
76 if cfg!(debug_assertions) {
77 rasops.draw_pixel(PixelsXY {
78 x: i16::try_from(x).expect("Coordinate must fit after computations"),
79 y: i16::try_from(y).expect("Coordinate must fit after computations"),
80 })?;
81 } else {
82 rasops.draw_pixel(PixelsXY { x: x as i16, y: y as i16 })?;
83 }
84 if d > 0 {
85 x += xi;
86 d += 2 * (dx - dy);
87 } else {
88 d += 2 * dx;
89 }
90 }
91
92 Ok(())
93}
94
95pub fn draw_line<R>(rasops: &mut R, x1y1: PixelsXY, x2y2: PixelsXY) -> io::Result<()>
100where
101 R: RasterOps,
102{
103 let x1 = i32::from(x1y1.x);
105 let y1 = i32::from(x1y1.y);
106 let x2 = i32::from(x2y2.x);
107 let y2 = i32::from(x2y2.y);
108
109 if (y2 - y1).abs() < (x2 - x1).abs() {
110 if x1y1.x > x2y2.x {
111 draw_line_low(rasops, x2, y2, x1, y1)
112 } else {
113 draw_line_low(rasops, x1, y1, x2, y2)
114 }
115 } else {
116 if x1y1.y > x2y2.y {
117 draw_line_high(rasops, x2, y2, x1, y1)
118 } else {
119 draw_line_high(rasops, x1, y1, x2, y2)
120 }
121 }
122}
123
124pub fn draw_circle<R>(rasops: &mut R, center: PixelsXY, radius: u16) -> io::Result<()>
129where
130 R: RasterOps,
131{
132 fn point<R: RasterOps>(rasops: &mut R, x: i16, y: i16) -> io::Result<()> {
133 rasops.draw_pixel(PixelsXY { x, y })
134 }
135
136 if radius == 0 {
137 return Ok(());
138 } else if radius == 1 {
139 return rasops.draw_pixel(center);
140 }
141
142 let (diameter, radius): (i16, i16) = match radius.checked_mul(2) {
143 Some(d) => match i16::try_from(d) {
144 Ok(d) => (d, radius as i16),
145 Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "Radius is too big")),
146 },
147 None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "Radius is too big")),
148 };
149
150 let mut x: i16 = radius - 1;
151 let mut y: i16 = 0;
152 let mut tx: i16 = 1;
153 let mut ty: i16 = 1;
154 let mut e: i16 = tx - diameter;
155
156 while x >= y {
157 point(rasops, center.x + x, center.y - y)?;
158 point(rasops, center.x + x, center.y + y)?;
159 point(rasops, center.x - x, center.y - y)?;
160 point(rasops, center.x - x, center.y + y)?;
161 point(rasops, center.x + y, center.y - x)?;
162 point(rasops, center.x + y, center.y + x)?;
163 point(rasops, center.x - y, center.y - x)?;
164 point(rasops, center.x - y, center.y + x)?;
165
166 if e <= 0 {
167 y += 1;
168 e += ty;
169 ty += 2;
170 }
171
172 if e > 0 {
173 x -= 1;
174 tx += 2;
175 e += tx - diameter;
176 }
177 }
178
179 Ok(())
180}
181
182pub fn draw_circle_filled<R>(rasops: &mut R, center: PixelsXY, radius: u16) -> io::Result<()>
187where
188 R: RasterOps,
189{
190 fn line<R: RasterOps>(rasops: &mut R, x1: i16, y1: i16, x2: i16, y2: i16) -> io::Result<()> {
191 rasops.draw_line(PixelsXY { x: x1, y: y1 }, PixelsXY { x: x2, y: y2 })
192 }
193
194 if radius == 0 {
195 return Ok(());
196 } else if radius == 1 {
197 return rasops.draw_pixel(center);
198 }
199
200 let (diameter, radius): (i16, i16) = match radius.checked_mul(2) {
201 Some(d) => match i16::try_from(d) {
202 Ok(d) => (d, radius as i16),
203
204 Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "Radius is too big")),
205 },
206 None => return Err(io::Error::new(io::ErrorKind::InvalidInput, "Radius is too big")),
207 };
208
209 let mut x: i16 = radius - 1;
210 let mut y: i16 = 0;
211 let mut tx: i16 = 1;
212 let mut ty: i16 = 1;
213 let mut e: i16 = tx - diameter;
214
215 while x >= y {
216 line(rasops, center.x + x, center.y - y, center.x + x, center.y + y)?;
217 line(rasops, center.x - x, center.y - y, center.x - x, center.y + y)?;
218 line(rasops, center.x + y, center.y - x, center.x + y, center.y + x)?;
219 line(rasops, center.x - y, center.y - x, center.x - y, center.y + x)?;
220
221 if e <= 0 {
222 y += 1;
223 e += ty;
224 ty += 2;
225 }
226
227 if e > 0 {
228 x -= 1;
229 tx += 2;
230 e += tx - diameter;
231 }
232 }
233
234 Ok(())
235}
236
237pub fn draw_rect<R>(rasops: &mut R, x1y1: PixelsXY, size: SizeInPixels) -> io::Result<()>
239where
240 R: RasterOps,
241{
242 let x2y2 = PixelsXY {
243 x: (i32::from(x1y1.x) + i32::from(size.width - 1)).clamped_into(),
244 y: (i32::from(x1y1.y) + i32::from(size.height - 1)).clamped_into(),
245 };
246 rasops.draw_line(PixelsXY { x: x1y1.x, y: x1y1.y }, PixelsXY { x: x2y2.x, y: x1y1.y })?;
247 rasops.draw_line(PixelsXY { x: x2y2.x, y: x1y1.y }, PixelsXY { x: x2y2.x, y: x2y2.y })?;
248 rasops.draw_line(PixelsXY { x: x2y2.x, y: x2y2.y }, PixelsXY { x: x1y1.x, y: x2y2.y })?;
249 rasops.draw_line(PixelsXY { x: x1y1.x, y: x2y2.y }, PixelsXY { x: x1y1.x, y: x1y1.y })?;
250 Ok(())
251}
252
253#[cfg(test)]
254mod testutils {
255 use super::*;
256 use crate::console::graphics::RasterInfo;
257 use crate::console::{SizeInPixels, RGB};
258
259 #[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
261 pub(crate) enum CapturedRasop {
262 DrawLine(i16, i16, i16, i16),
263 DrawPixel(i16, i16),
264 }
265
266 #[derive(Default)]
268 pub(crate) struct RecordingRasops {
269 pub(crate) ops: Vec<CapturedRasop>,
270 }
271
272 impl RasterOps for RecordingRasops {
273 type ID = u8;
274
275 fn get_info(&self) -> RasterInfo {
276 unimplemented!();
277 }
278
279 fn set_draw_color(&mut self, _color: RGB) {
280 unimplemented!();
281 }
282
283 fn clear(&mut self) -> io::Result<()> {
284 unimplemented!();
285 }
286
287 fn set_sync(&mut self, _enabled: bool) {
288 unimplemented!();
289 }
290
291 fn present_canvas(&mut self) -> io::Result<()> {
292 unimplemented!();
293 }
294
295 fn read_pixels(&mut self, _xy: PixelsXY, _size: SizeInPixels) -> io::Result<Self::ID> {
296 unimplemented!();
297 }
298
299 fn put_pixels(&mut self, _xy: PixelsXY, _data: &Self::ID) -> io::Result<()> {
300 unimplemented!();
301 }
302
303 fn move_pixels(
304 &mut self,
305 _x1y1: PixelsXY,
306 _x2y2: PixelsXY,
307 _size: SizeInPixels,
308 ) -> io::Result<()> {
309 unimplemented!();
310 }
311
312 fn write_text(&mut self, _xy: PixelsXY, _text: &str) -> io::Result<()> {
313 unimplemented!();
314 }
315
316 fn draw_circle(&mut self, _center: PixelsXY, _radius: u16) -> io::Result<()> {
317 unimplemented!();
318 }
319
320 fn draw_circle_filled(&mut self, _center: PixelsXY, _radius: u16) -> io::Result<()> {
321 unimplemented!();
322 }
323
324 fn draw_line(&mut self, x1y1: PixelsXY, x2y2: PixelsXY) -> io::Result<()> {
325 self.ops.push(CapturedRasop::DrawLine(x1y1.x, x1y1.y, x2y2.x, x2y2.y));
326 Ok(())
327 }
328
329 fn draw_pixel(&mut self, xy: PixelsXY) -> io::Result<()> {
330 self.ops.push(CapturedRasop::DrawPixel(xy.x, xy.y));
331 Ok(())
332 }
333
334 fn draw_rect(&mut self, _xy: PixelsXY, _size: SizeInPixels) -> io::Result<()> {
335 unimplemented!();
336 }
337
338 fn draw_rect_filled(&mut self, _xy: PixelsXY, _size: SizeInPixels) -> io::Result<()> {
339 unimplemented!();
340 }
341 }
342}
343
344#[cfg(test)]
345mod tests {
346 use super::testutils::*;
347 use super::*;
348
349 #[test]
350 fn test_draw_circle_zero() {
351 let mut rasops = RecordingRasops::default();
352 draw_circle(&mut rasops, PixelsXY::new(10, 20), 0).unwrap();
353 assert!(rasops.ops.is_empty());
354 }
355
356 #[test]
357 fn test_draw_circle_dot() {
358 let mut rasops = RecordingRasops::default();
359 draw_circle(&mut rasops, PixelsXY::new(10, 20), 1).unwrap();
360 assert_eq!([CapturedRasop::DrawPixel(10, 20)], rasops.ops.as_slice());
361 }
362
363 #[test]
364 fn test_draw_circle_larger() {
365 let mut rasops = RecordingRasops::default();
366 draw_circle(&mut rasops, PixelsXY::new(10, 20), 4).unwrap();
367 rasops.ops.sort();
368 assert_eq!(
369 [
370 CapturedRasop::DrawPixel(7, 18),
371 CapturedRasop::DrawPixel(7, 19),
372 CapturedRasop::DrawPixel(7, 20),
373 CapturedRasop::DrawPixel(7, 20),
374 CapturedRasop::DrawPixel(7, 21),
375 CapturedRasop::DrawPixel(7, 22),
376 CapturedRasop::DrawPixel(8, 17),
377 CapturedRasop::DrawPixel(8, 23),
378 CapturedRasop::DrawPixel(9, 17),
379 CapturedRasop::DrawPixel(9, 23),
380 CapturedRasop::DrawPixel(10, 17),
381 CapturedRasop::DrawPixel(10, 17),
382 CapturedRasop::DrawPixel(10, 23),
383 CapturedRasop::DrawPixel(10, 23),
384 CapturedRasop::DrawPixel(11, 17),
385 CapturedRasop::DrawPixel(11, 23),
386 CapturedRasop::DrawPixel(12, 17),
387 CapturedRasop::DrawPixel(12, 23),
388 CapturedRasop::DrawPixel(13, 18),
389 CapturedRasop::DrawPixel(13, 19),
390 CapturedRasop::DrawPixel(13, 20),
391 CapturedRasop::DrawPixel(13, 20),
392 CapturedRasop::DrawPixel(13, 21),
393 CapturedRasop::DrawPixel(13, 22),
394 ],
395 rasops.ops.as_slice()
396 );
397 }
398
399 #[test]
400 fn test_draw_circle_corners() {
401 for corner in
402 [PixelsXY::TOP_LEFT, PixelsXY::TOP_RIGHT, PixelsXY::BOTTOM_LEFT, PixelsXY::BOTTOM_RIGHT]
403 {
404 let mut rasops = RecordingRasops::default();
405 draw_circle(&mut rasops, corner, 1).unwrap();
406 assert_eq!([CapturedRasop::DrawPixel(corner.x, corner.y)], rasops.ops.as_slice());
407 }
408 }
409
410 #[test]
411 fn test_draw_circle_filled_zero() {
412 let mut rasops = RecordingRasops::default();
413 draw_circle_filled(&mut rasops, PixelsXY::new(10, 20), 0).unwrap();
414 assert!(rasops.ops.is_empty());
415 }
416
417 #[test]
418 fn test_draw_circle_filled_dot() {
419 let mut rasops = RecordingRasops::default();
420 draw_circle_filled(&mut rasops, PixelsXY::new(10, 20), 1).unwrap();
421 assert_eq!([CapturedRasop::DrawPixel(10, 20)], rasops.ops.as_slice());
422 }
423
424 #[test]
425 fn test_draw_circle_filled_larger() {
426 let mut rasops = RecordingRasops::default();
427 draw_circle_filled(&mut rasops, PixelsXY::new(10, 20), 4).unwrap();
428 rasops.ops.sort();
429 assert_eq!(
430 [
431 CapturedRasop::DrawLine(7, 18, 7, 22),
432 CapturedRasop::DrawLine(7, 19, 7, 21),
433 CapturedRasop::DrawLine(7, 20, 7, 20),
434 CapturedRasop::DrawLine(8, 17, 8, 23),
435 CapturedRasop::DrawLine(9, 17, 9, 23),
436 CapturedRasop::DrawLine(10, 17, 10, 23),
437 CapturedRasop::DrawLine(10, 17, 10, 23),
438 CapturedRasop::DrawLine(11, 17, 11, 23),
439 CapturedRasop::DrawLine(12, 17, 12, 23),
440 CapturedRasop::DrawLine(13, 18, 13, 22),
441 CapturedRasop::DrawLine(13, 19, 13, 21),
442 CapturedRasop::DrawLine(13, 20, 13, 20),
443 ],
444 rasops.ops.as_slice()
445 );
446 }
447
448 #[test]
449 fn test_draw_circle_filled_corners() {
450 for corner in
451 [PixelsXY::TOP_LEFT, PixelsXY::TOP_RIGHT, PixelsXY::BOTTOM_LEFT, PixelsXY::BOTTOM_RIGHT]
452 {
453 let mut rasops = RecordingRasops::default();
454 draw_circle_filled(&mut rasops, corner, 1).unwrap();
455 assert_eq!([CapturedRasop::DrawPixel(corner.x, corner.y)], rasops.ops.as_slice());
456 }
457 }
458
459 #[test]
460 fn test_draw_line_dot() {
461 let mut rasops = RecordingRasops::default();
462 draw_line(&mut rasops, PixelsXY::new(10, 20), PixelsXY::new(10, 20)).unwrap();
463 assert_eq!([CapturedRasop::DrawPixel(10, 20)], rasops.ops.as_slice());
464 }
465
466 #[test]
467 fn test_draw_line_horizontal_right() {
468 let mut rasops = RecordingRasops::default();
469 draw_line(&mut rasops, PixelsXY::new(100, 0), PixelsXY::new(105, 0)).unwrap();
470 assert_eq!(
471 [
472 CapturedRasop::DrawPixel(100, 0),
473 CapturedRasop::DrawPixel(101, 0),
474 CapturedRasop::DrawPixel(102, 0),
475 CapturedRasop::DrawPixel(103, 0),
476 CapturedRasop::DrawPixel(104, 0),
477 CapturedRasop::DrawPixel(105, 0),
478 ],
479 rasops.ops.as_slice()
480 );
481 }
482
483 #[test]
484 fn test_draw_line_horizontal_left() {
485 let mut rasops = RecordingRasops::default();
486 draw_line(&mut rasops, PixelsXY::new(105, 0), PixelsXY::new(100, 0)).unwrap();
487 assert_eq!(
488 [
489 CapturedRasop::DrawPixel(100, 0),
490 CapturedRasop::DrawPixel(101, 0),
491 CapturedRasop::DrawPixel(102, 0),
492 CapturedRasop::DrawPixel(103, 0),
493 CapturedRasop::DrawPixel(104, 0),
494 CapturedRasop::DrawPixel(105, 0),
495 ],
496 rasops.ops.as_slice()
497 );
498 }
499
500 #[test]
501 fn test_draw_line_vertical_down() {
502 let mut rasops = RecordingRasops::default();
503 draw_line(&mut rasops, PixelsXY::new(0, 100), PixelsXY::new(0, 105)).unwrap();
504 assert_eq!(
505 [
506 CapturedRasop::DrawPixel(0, 100),
507 CapturedRasop::DrawPixel(0, 101),
508 CapturedRasop::DrawPixel(0, 102),
509 CapturedRasop::DrawPixel(0, 103),
510 CapturedRasop::DrawPixel(0, 104),
511 CapturedRasop::DrawPixel(0, 105),
512 ],
513 rasops.ops.as_slice()
514 );
515 }
516
517 #[test]
518 fn test_draw_line_vertical_up() {
519 let mut rasops = RecordingRasops::default();
520 draw_line(&mut rasops, PixelsXY::new(0, 105), PixelsXY::new(0, 100)).unwrap();
521 assert_eq!(
522 [
523 CapturedRasop::DrawPixel(0, 100),
524 CapturedRasop::DrawPixel(0, 101),
525 CapturedRasop::DrawPixel(0, 102),
526 CapturedRasop::DrawPixel(0, 103),
527 CapturedRasop::DrawPixel(0, 104),
528 CapturedRasop::DrawPixel(0, 105),
529 ],
530 rasops.ops.as_slice()
531 );
532 }
533
534 #[test]
535 fn test_draw_line_horizontal_slope_right() {
536 let mut rasops = RecordingRasops::default();
537 draw_line(&mut rasops, PixelsXY::new(100, 0), PixelsXY::new(105, 3)).unwrap();
538 assert_eq!(
539 [
540 CapturedRasop::DrawPixel(100, 0),
541 CapturedRasop::DrawPixel(101, 1),
542 CapturedRasop::DrawPixel(102, 1),
543 CapturedRasop::DrawPixel(103, 2),
544 CapturedRasop::DrawPixel(104, 2),
545 CapturedRasop::DrawPixel(105, 3),
546 ],
547 rasops.ops.as_slice()
548 );
549 }
550
551 #[test]
552 fn test_draw_line_horizontal_slope_left() {
553 let mut rasops = RecordingRasops::default();
554 draw_line(&mut rasops, PixelsXY::new(105, 0), PixelsXY::new(100, 3)).unwrap();
555 assert_eq!(
556 [
557 CapturedRasop::DrawPixel(100, 3),
558 CapturedRasop::DrawPixel(101, 2),
559 CapturedRasop::DrawPixel(102, 2),
560 CapturedRasop::DrawPixel(103, 1),
561 CapturedRasop::DrawPixel(104, 1),
562 CapturedRasop::DrawPixel(105, 0),
563 ],
564 rasops.ops.as_slice()
565 );
566 }
567
568 #[test]
569 fn test_draw_line_vertical_slope_up() {
570 let mut rasops = RecordingRasops::default();
571 draw_line(&mut rasops, PixelsXY::new(0, 100), PixelsXY::new(3, 105)).unwrap();
572 assert_eq!(
573 [
574 CapturedRasop::DrawPixel(0, 100),
575 CapturedRasop::DrawPixel(1, 101),
576 CapturedRasop::DrawPixel(1, 102),
577 CapturedRasop::DrawPixel(2, 103),
578 CapturedRasop::DrawPixel(2, 104),
579 CapturedRasop::DrawPixel(3, 105),
580 ],
581 rasops.ops.as_slice()
582 );
583 }
584
585 #[test]
586 fn test_draw_line_vertical_slope_down() {
587 let mut rasops = RecordingRasops::default();
588 draw_line(&mut rasops, PixelsXY::new(0, 105), PixelsXY::new(3, 100)).unwrap();
589 assert_eq!(
590 [
591 CapturedRasop::DrawPixel(3, 100),
592 CapturedRasop::DrawPixel(2, 101),
593 CapturedRasop::DrawPixel(2, 102),
594 CapturedRasop::DrawPixel(1, 103),
595 CapturedRasop::DrawPixel(1, 104),
596 CapturedRasop::DrawPixel(0, 105),
597 ],
598 rasops.ops.as_slice()
599 );
600 }
601
602 #[test]
603 fn test_draw_line_corners() {
604 for corner in
605 [PixelsXY::TOP_LEFT, PixelsXY::TOP_RIGHT, PixelsXY::BOTTOM_LEFT, PixelsXY::BOTTOM_RIGHT]
606 {
607 let mut rasops = RecordingRasops::default();
608 draw_line(&mut rasops, corner, corner).unwrap();
609 assert_eq!([CapturedRasop::DrawPixel(corner.x, corner.y)], rasops.ops.as_slice());
610 }
611 }
612
613 #[test]
614 fn test_draw_line_perimeter() {
615 for corners in [
616 (PixelsXY::TOP_LEFT, PixelsXY::TOP_RIGHT),
617 (PixelsXY::TOP_RIGHT, PixelsXY::BOTTOM_RIGHT),
618 (PixelsXY::BOTTOM_RIGHT, PixelsXY::BOTTOM_LEFT),
619 (PixelsXY::BOTTOM_LEFT, PixelsXY::TOP_LEFT),
620 ] {
621 let mut rasops = RecordingRasops::default();
622 draw_line(&mut rasops, corners.0, corners.1).unwrap();
623 assert_eq!(usize::from(u16::MAX) + 1, rasops.ops.len());
624 }
625 }
626
627 #[test]
628 fn test_draw_line_diagonals() {
629 for corners in [
630 (PixelsXY::TOP_LEFT, PixelsXY::BOTTOM_RIGHT),
631 (PixelsXY::BOTTOM_RIGHT, PixelsXY::TOP_LEFT),
632 (PixelsXY::TOP_RIGHT, PixelsXY::BOTTOM_LEFT),
633 (PixelsXY::BOTTOM_LEFT, PixelsXY::TOP_RIGHT),
634 ] {
635 let mut rasops = RecordingRasops::default();
636 draw_line(&mut rasops, corners.0, corners.1).unwrap();
637 assert_eq!(usize::from(u16::MAX) + 1, rasops.ops.len());
638 }
639 }
640
641 #[test]
642 fn test_draw_rect_dot() {
643 let mut rasops = RecordingRasops::default();
644 draw_rect(&mut rasops, PixelsXY::new(10, 20), SizeInPixels::new(1, 1)).unwrap();
645 assert_eq!(
646 [
647 CapturedRasop::DrawLine(10, 20, 10, 20),
648 CapturedRasop::DrawLine(10, 20, 10, 20),
649 CapturedRasop::DrawLine(10, 20, 10, 20),
650 CapturedRasop::DrawLine(10, 20, 10, 20),
651 ],
652 rasops.ops.as_slice()
653 );
654 }
655
656 #[test]
657 fn test_draw_rect_horizontal_line() {
658 let mut rasops = RecordingRasops::default();
659 draw_rect(&mut rasops, PixelsXY::new(10, 20), SizeInPixels::new(6, 1)).unwrap();
660 assert_eq!(
661 [
662 CapturedRasop::DrawLine(10, 20, 15, 20),
663 CapturedRasop::DrawLine(15, 20, 15, 20),
664 CapturedRasop::DrawLine(15, 20, 10, 20),
665 CapturedRasop::DrawLine(10, 20, 10, 20),
666 ],
667 rasops.ops.as_slice()
668 );
669 }
670
671 #[test]
672 fn test_draw_rect_vertical_line() {
673 let mut rasops = RecordingRasops::default();
674 draw_rect(&mut rasops, PixelsXY::new(10, 20), SizeInPixels::new(1, 6)).unwrap();
675 assert_eq!(
676 [
677 CapturedRasop::DrawLine(10, 20, 10, 20),
678 CapturedRasop::DrawLine(10, 20, 10, 25),
679 CapturedRasop::DrawLine(10, 25, 10, 25),
680 CapturedRasop::DrawLine(10, 25, 10, 20),
681 ],
682 rasops.ops.as_slice()
683 );
684 }
685
686 #[test]
687 fn test_draw_rect_2d() {
688 let mut rasops = RecordingRasops::default();
689 draw_rect(&mut rasops, PixelsXY::new(10, 20), SizeInPixels::new(6, 7)).unwrap();
690 assert_eq!(
691 [
692 CapturedRasop::DrawLine(10, 20, 15, 20),
693 CapturedRasop::DrawLine(15, 20, 15, 26),
694 CapturedRasop::DrawLine(15, 26, 10, 26),
695 CapturedRasop::DrawLine(10, 26, 10, 20),
696 ],
697 rasops.ops.as_slice()
698 );
699 }
700
701 #[test]
702 fn test_draw_rect_corners() {
703 let mut rasops = RecordingRasops::default();
704 draw_rect(&mut rasops, PixelsXY::TOP_LEFT, SizeInPixels::MAX).unwrap();
705 assert_eq!(
706 [
707 CapturedRasop::DrawLine(i16::MIN, i16::MIN, i16::MAX - 1, i16::MIN),
708 CapturedRasop::DrawLine(i16::MAX - 1, i16::MIN, i16::MAX - 1, i16::MAX - 1),
709 CapturedRasop::DrawLine(i16::MAX - 1, i16::MAX - 1, i16::MIN, i16::MAX - 1),
710 CapturedRasop::DrawLine(i16::MIN, i16::MAX - 1, i16::MIN, i16::MIN),
711 ],
712 rasops.ops.as_slice()
713 );
714 }
715}