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