1use image::DynamicImage;
2use winio_primitive::{DrawingFont, Point, Rect, Size, Transform};
3
4use crate::{sys, sys::Result};
5
6pub trait Brush: sys::Brush {}
8
9impl<B: sys::Brush> Brush for B {}
10
11pub trait Pen: sys::Pen {}
13
14impl<P: sys::Pen> Pen for P {}
15
16pub struct DrawingImage(sys::DrawingImage);
18
19impl DrawingImage {
20 pub fn size(&self) -> Result<Size> {
22 self.0.size()
23 }
24}
25
26pub struct DrawingContext<'a>(sys::DrawingContext<'a>);
28
29#[inline]
30fn fix_rect(mut rect: Rect) -> Rect {
31 rect.size = fix_size(rect.size);
32 rect
33}
34
35#[inline]
36fn fix_size(mut size: Size) -> Size {
37 size.width = size.width.max(0.1);
38 size.height = size.height.max(0.1);
39 size
40}
41
42#[inline]
43fn fix_font(mut font: DrawingFont) -> DrawingFont {
44 font.size = font.size.max(0.1);
45 if font.family.is_empty() {
46 font.family = "Arial".to_string();
47 }
48 font
49}
50
51impl<'a> DrawingContext<'a> {
52 pub(crate) fn new(ctx: sys::DrawingContext<'a>) -> Self {
53 Self(ctx)
54 }
55
56 pub fn close(self) -> Result<()> {
58 self.0.close()
59 }
60
61 pub fn set_transform(&mut self, transform: Transform) -> Result<()> {
63 self.0.set_transform(transform)
64 }
65
66 pub fn transform(&self) -> Result<Transform> {
68 self.0.transform()
69 }
70
71 pub fn draw_path(&mut self, pen: impl Pen, path: &DrawingPath) -> Result<()> {
73 self.0.draw_path(pen, &path.0)
74 }
75
76 pub fn fill_path(&mut self, brush: impl Brush, path: &DrawingPath) -> Result<()> {
78 self.0.fill_path(brush, &path.0)
79 }
80
81 pub fn draw_arc(&mut self, pen: impl Pen, rect: Rect, start: f64, end: f64) -> Result<()> {
83 self.0.draw_arc(pen, fix_rect(rect), start, end)
84 }
85
86 pub fn draw_pie(&mut self, pen: impl Pen, rect: Rect, start: f64, end: f64) -> Result<()> {
88 self.0.draw_pie(pen, fix_rect(rect), start, end)
89 }
90
91 pub fn fill_pie(&mut self, brush: impl Brush, rect: Rect, start: f64, end: f64) -> Result<()> {
93 self.0.fill_pie(brush, fix_rect(rect), start, end)
94 }
95
96 pub fn draw_ellipse(&mut self, pen: impl Pen, rect: Rect) -> Result<()> {
98 self.0.draw_ellipse(pen, fix_rect(rect))
99 }
100
101 pub fn fill_ellipse(&mut self, brush: impl Brush, rect: Rect) -> Result<()> {
103 self.0.fill_ellipse(brush, fix_rect(rect))
104 }
105
106 pub fn draw_line(&mut self, pen: impl Pen, start: Point, end: Point) -> Result<()> {
108 self.0.draw_line(pen, start, end)
109 }
110
111 pub fn draw_rect(&mut self, pen: impl Pen, rect: Rect) -> Result<()> {
113 self.0.draw_rect(pen, fix_rect(rect))
114 }
115
116 pub fn fill_rect(&mut self, brush: impl Brush, rect: Rect) -> Result<()> {
118 self.0.fill_rect(brush, fix_rect(rect))
119 }
120
121 pub fn draw_round_rect(&mut self, pen: impl Pen, rect: Rect, round: Size) -> Result<()> {
123 self.0.draw_round_rect(pen, fix_rect(rect), round)
124 }
125
126 pub fn fill_round_rect(&mut self, brush: impl Brush, rect: Rect, round: Size) -> Result<()> {
128 self.0.fill_round_rect(brush, fix_rect(rect), round)
129 }
130
131 pub fn draw_str(
133 &mut self,
134 brush: impl Brush,
135 font: DrawingFont,
136 pos: Point,
137 text: impl AsRef<str>,
138 ) -> Result<()> {
139 self.0.draw_str(brush, fix_font(font), pos, text.as_ref())
140 }
141
142 pub fn measure_str(&self, font: DrawingFont, text: &str) -> Result<Size> {
144 self.0.measure_str(fix_font(font), text)
145 }
146
147 pub fn create_image(&self, image: DynamicImage) -> Result<DrawingImage> {
149 Ok(DrawingImage(self.0.create_image(image)?))
150 }
151
152 pub fn draw_image(
154 &mut self,
155 image: &DrawingImage,
156 rect: Rect,
157 clip: Option<Rect>,
158 ) -> Result<()> {
159 self.0.draw_image(&image.0, fix_rect(rect), clip)
160 }
161
162 pub fn create_path_builder(&self, start: Point) -> Result<DrawingPathBuilder> {
164 Ok(DrawingPathBuilder(self.0.create_path_builder(start)?))
165 }
166}
167
168pub struct DrawingPath(sys::DrawingPath);
170
171pub struct DrawingPathBuilder(sys::DrawingPathBuilder);
173
174impl DrawingPathBuilder {
175 pub fn add_line(&mut self, p: Point) -> Result<()> {
177 self.0.add_line(p)?;
178 Ok(())
179 }
180
181 pub fn add_arc(
184 &mut self,
185 center: Point,
186 radius: Size,
187 start: f64,
188 end: f64,
189 clockwise: bool,
190 ) -> Result<()> {
191 self.0
192 .add_arc(center, fix_size(radius), start, end, clockwise)?;
193 Ok(())
194 }
195
196 pub fn add_bezier(&mut self, p1: Point, p2: Point, p3: Point) -> Result<()> {
198 self.0.add_bezier(p1, p2, p3)?;
199 Ok(())
200 }
201
202 pub fn build(self, close: bool) -> Result<DrawingPath> {
204 Ok(DrawingPath(self.0.build(close)?))
205 }
206}