1 use crate::drawing::backend::{BackendCoord, BackendStyle, DrawingErrorKind};
2 use crate::drawing::DrawingBackend;
3 
4 use crate::style::Color;
5 
draw_circle<B: DrawingBackend, S: BackendStyle>( b: &mut B, center: BackendCoord, radius: u32, style: &S, fill: bool, ) -> Result<(), DrawingErrorKind<B::ErrorType>>6 pub fn draw_circle<B: DrawingBackend, S: BackendStyle>(
7     b: &mut B,
8     center: BackendCoord,
9     radius: u32,
10     style: &S,
11     fill: bool,
12 ) -> Result<(), DrawingErrorKind<B::ErrorType>> {
13     if style.as_color().alpha() == 0.0 {
14         return Ok(());
15     }
16 
17     if !fill && style.stroke_width() != 1 {
18         // FIXME: We are currently ignore the stroke width for circles
19     }
20 
21     let min = (f64::from(radius) * (1.0 - (2f64).sqrt() / 2.0)).ceil() as i32;
22     let max = (f64::from(radius) * (1.0 + (2f64).sqrt() / 2.0)).floor() as i32;
23 
24     let range = min..=max;
25 
26     let (up, down) = (
27         range.start() + center.1 - radius as i32,
28         range.end() + center.1 - radius as i32,
29     );
30 
31     for dy in range {
32         let dy = dy - radius as i32;
33         let y = center.1 + dy;
34 
35         let lx = (f64::from(radius) * f64::from(radius)
36             - (f64::from(dy) * f64::from(dy)).max(1e-5))
37         .sqrt();
38 
39         let left = center.0 - lx.floor() as i32;
40         let right = center.0 + lx.floor() as i32;
41 
42         let v = lx - lx.floor();
43 
44         let x = center.0 + dy;
45         let top = center.1 - lx.floor() as i32;
46         let bottom = center.1 + lx.floor() as i32;
47 
48         if fill {
49             check_result!(b.draw_line((left, y), (right, y), &style.as_color()));
50             check_result!(b.draw_line((x, top), (x, up), &style.as_color()));
51             check_result!(b.draw_line((x, down), (x, bottom), &style.as_color()));
52         } else {
53             check_result!(b.draw_pixel((left, y), &style.as_color().mix(1.0 - v)));
54             check_result!(b.draw_pixel((right, y), &style.as_color().mix(1.0 - v)));
55 
56             check_result!(b.draw_pixel((x, top), &style.as_color().mix(1.0 - v)));
57             check_result!(b.draw_pixel((x, bottom), &style.as_color().mix(1.0 - v)));
58         }
59 
60         check_result!(b.draw_pixel((left - 1, y), &style.as_color().mix(v)));
61         check_result!(b.draw_pixel((right + 1, y), &style.as_color().mix(v)));
62         check_result!(b.draw_pixel((x, top - 1), &style.as_color().mix(v)));
63         check_result!(b.draw_pixel((x, bottom + 1), &style.as_color().mix(v)));
64     }
65 
66     Ok(())
67 }
68