| use crate::drawing::backend::{BackendCoord, BackendStyle, DrawingErrorKind}; |
| use crate::drawing::DrawingBackend; |
| |
| use crate::style::Color; |
| |
| pub fn draw_circle<B: DrawingBackend, S: BackendStyle>( |
| b: &mut B, |
| center: BackendCoord, |
| radius: u32, |
| style: &S, |
| fill: bool, |
| ) -> Result<(), DrawingErrorKind<B::ErrorType>> { |
| if style.as_color().alpha() == 0.0 { |
| return Ok(()); |
| } |
| |
| if !fill && style.stroke_width() != 1 { |
| // FIXME: We are currently ignore the stroke width for circles |
| } |
| |
| let min = (f64::from(radius) * (1.0 - (2f64).sqrt() / 2.0)).ceil() as i32; |
| let max = (f64::from(radius) * (1.0 + (2f64).sqrt() / 2.0)).floor() as i32; |
| |
| let range = min..=max; |
| |
| let (up, down) = ( |
| range.start() + center.1 - radius as i32, |
| range.end() + center.1 - radius as i32, |
| ); |
| |
| for dy in range { |
| let dy = dy - radius as i32; |
| let y = center.1 + dy; |
| |
| let lx = (f64::from(radius) * f64::from(radius) |
| - (f64::from(dy) * f64::from(dy)).max(1e-5)) |
| .sqrt(); |
| |
| let left = center.0 - lx.floor() as i32; |
| let right = center.0 + lx.floor() as i32; |
| |
| let v = lx - lx.floor(); |
| |
| let x = center.0 + dy; |
| let top = center.1 - lx.floor() as i32; |
| let bottom = center.1 + lx.floor() as i32; |
| |
| if fill { |
| check_result!(b.draw_line((left, y), (right, y), &style.as_color())); |
| check_result!(b.draw_line((x, top), (x, up), &style.as_color())); |
| check_result!(b.draw_line((x, down), (x, bottom), &style.as_color())); |
| } else { |
| check_result!(b.draw_pixel((left, y), &style.as_color().mix(1.0 - v))); |
| check_result!(b.draw_pixel((right, y), &style.as_color().mix(1.0 - v))); |
| |
| check_result!(b.draw_pixel((x, top), &style.as_color().mix(1.0 - v))); |
| check_result!(b.draw_pixel((x, bottom), &style.as_color().mix(1.0 - v))); |
| } |
| |
| check_result!(b.draw_pixel((left - 1, y), &style.as_color().mix(v))); |
| check_result!(b.draw_pixel((right + 1, y), &style.as_color().mix(v))); |
| check_result!(b.draw_pixel((x, top - 1), &style.as_color().mix(v))); |
| check_result!(b.draw_pixel((x, bottom + 1), &style.as_color().mix(v))); |
| } |
| |
| Ok(()) |
| } |