use image::DynamicImage;
use winio_primitive::{DrawingFont, Point, Rect, Size, Transform};
use crate::{sys, sys::Result};
pub trait Brush: sys::Brush {}
impl<B: sys::Brush> Brush for B {}
pub trait Pen: sys::Pen {}
impl<P: sys::Pen> Pen for P {}
pub struct DrawingImage(sys::DrawingImage);
impl DrawingImage {
pub fn size(&self) -> Result<Size> {
self.0.size()
}
}
pub struct DrawingContext<'a>(sys::DrawingContext<'a>);
#[inline]
fn fix_rect(mut rect: Rect) -> Rect {
rect.size = fix_size(rect.size);
rect
}
#[inline]
fn fix_size(mut size: Size) -> Size {
size.width = size.width.max(0.1);
size.height = size.height.max(0.1);
size
}
#[inline]
fn fix_font(mut font: DrawingFont) -> DrawingFont {
font.size = font.size.max(0.1);
if font.family.is_empty() {
font.family = "Arial".to_string();
}
font
}
impl<'a> DrawingContext<'a> {
pub(crate) fn new(ctx: sys::DrawingContext<'a>) -> Self {
Self(ctx)
}
pub fn close(self) -> Result<()> {
self.0.close()
}
pub fn set_transform(&mut self, transform: Transform) -> Result<()> {
self.0.set_transform(transform)
}
pub fn transform(&self) -> Result<Transform> {
self.0.transform()
}
pub fn draw_path(&mut self, pen: impl Pen, path: &DrawingPath) -> Result<()> {
self.0.draw_path(pen, &path.0)
}
pub fn fill_path(&mut self, brush: impl Brush, path: &DrawingPath) -> Result<()> {
self.0.fill_path(brush, &path.0)
}
pub fn draw_arc(&mut self, pen: impl Pen, rect: Rect, start: f64, end: f64) -> Result<()> {
self.0.draw_arc(pen, fix_rect(rect), start, end)
}
pub fn draw_pie(&mut self, pen: impl Pen, rect: Rect, start: f64, end: f64) -> Result<()> {
self.0.draw_pie(pen, fix_rect(rect), start, end)
}
pub fn fill_pie(&mut self, brush: impl Brush, rect: Rect, start: f64, end: f64) -> Result<()> {
self.0.fill_pie(brush, fix_rect(rect), start, end)
}
pub fn draw_ellipse(&mut self, pen: impl Pen, rect: Rect) -> Result<()> {
self.0.draw_ellipse(pen, fix_rect(rect))
}
pub fn fill_ellipse(&mut self, brush: impl Brush, rect: Rect) -> Result<()> {
self.0.fill_ellipse(brush, fix_rect(rect))
}
pub fn draw_line(&mut self, pen: impl Pen, start: Point, end: Point) -> Result<()> {
self.0.draw_line(pen, start, end)
}
pub fn draw_rect(&mut self, pen: impl Pen, rect: Rect) -> Result<()> {
self.0.draw_rect(pen, fix_rect(rect))
}
pub fn fill_rect(&mut self, brush: impl Brush, rect: Rect) -> Result<()> {
self.0.fill_rect(brush, fix_rect(rect))
}
pub fn draw_round_rect(&mut self, pen: impl Pen, rect: Rect, round: Size) -> Result<()> {
self.0.draw_round_rect(pen, fix_rect(rect), round)
}
pub fn fill_round_rect(&mut self, brush: impl Brush, rect: Rect, round: Size) -> Result<()> {
self.0.fill_round_rect(brush, fix_rect(rect), round)
}
pub fn draw_str(
&mut self,
brush: impl Brush,
font: DrawingFont,
pos: Point,
text: impl AsRef<str>,
) -> Result<()> {
self.0.draw_str(brush, fix_font(font), pos, text.as_ref())
}
pub fn measure_str(&self, font: DrawingFont, text: &str) -> Result<Size> {
self.0.measure_str(fix_font(font), text)
}
pub fn create_image(&self, image: DynamicImage) -> Result<DrawingImage> {
Ok(DrawingImage(self.0.create_image(image)?))
}
pub fn draw_image(
&mut self,
image: &DrawingImage,
rect: Rect,
clip: Option<Rect>,
) -> Result<()> {
self.0.draw_image(&image.0, fix_rect(rect), clip)
}
pub fn create_path_builder(&self, start: Point) -> Result<DrawingPathBuilder> {
Ok(DrawingPathBuilder(self.0.create_path_builder(start)?))
}
}
pub struct DrawingPath(sys::DrawingPath);
pub struct DrawingPathBuilder(sys::DrawingPathBuilder);
impl DrawingPathBuilder {
pub fn add_line(&mut self, p: Point) -> Result<()> {
self.0.add_line(p)?;
Ok(())
}
pub fn add_arc(
&mut self,
center: Point,
radius: Size,
start: f64,
end: f64,
clockwise: bool,
) -> Result<()> {
self.0
.add_arc(center, fix_size(radius), start, end, clockwise)?;
Ok(())
}
pub fn add_bezier(&mut self, p1: Point, p2: Point, p3: Point) -> Result<()> {
self.0.add_bezier(p1, p2, p3)?;
Ok(())
}
pub fn build(self, close: bool) -> Result<DrawingPath> {
Ok(DrawingPath(self.0.build(close)?))
}
}