1use crate::bridge::ffi;
4use crate::path::Path;
5use cxx::UniquePtr;
6
7pub use crate::bridge::ffi::{StrokeCap, StrokeJoin};
8
9impl Default for StrokeCap {
10 fn default() -> Self {
11 StrokeCap::Butt
12 }
13}
14
15impl Default for StrokeJoin {
16 fn default() -> Self {
17 StrokeJoin::Miter
18 }
19}
20
21#[derive(Debug, Clone, Copy, PartialEq)]
24pub enum StrokeStyle {
25 Hairline,
27 Fill,
29 Stroke {
32 width: f32,
34 stroke_and_fill: bool,
37 },
38 StrokeAndFill {
40 width: f32,
42 },
43}
44
45pub struct StrokeRec {
51 inner: UniquePtr<ffi::StrokeRecHolder>,
52}
53
54impl StrokeRec {
55 pub fn new_fill() -> Self {
57 Self {
58 inner: ffi::stroke_rec_new(ffi::StrokeRecInit::Fill),
59 }
60 }
61
62 pub fn new_hairline() -> Self {
64 Self {
65 inner: ffi::stroke_rec_new(ffi::StrokeRecInit::Hairline),
66 }
67 }
68
69 pub fn new_stroke(width: f32, stroke_and_fill: bool) -> Self {
71 let mut rec = Self::new_hairline();
72 ffi::stroke_rec_set_stroke_style(rec.inner.pin_mut(), width, stroke_and_fill);
73 rec
74 }
75
76 pub fn set_fill(&mut self) {
78 ffi::stroke_rec_set_fill(self.inner.pin_mut());
79 }
80
81 pub fn set_hairline(&mut self) {
83 ffi::stroke_rec_set_hairline(self.inner.pin_mut());
84 }
85
86 pub fn set_stroke_style(&mut self, width: f32, stroke_and_fill: bool) {
88 ffi::stroke_rec_set_stroke_style(self.inner.pin_mut(), width, stroke_and_fill);
89 }
90
91 pub fn set_cap(&mut self, cap: StrokeCap) {
93 ffi::stroke_rec_set_cap(self.inner.pin_mut(), cap);
94 }
95
96 pub fn set_join(&mut self, join: StrokeJoin) {
98 ffi::stroke_rec_set_join(self.inner.pin_mut(), join);
99 }
100
101 pub fn set_stroke_params(&mut self, cap: StrokeCap, join: StrokeJoin, miter_limit: f32) {
103 ffi::stroke_rec_set_stroke_params(self.inner.pin_mut(), cap, join, miter_limit);
104 }
105
106 pub fn cap(&self) -> StrokeCap {
108 ffi::stroke_rec_cap(self.as_holder_ref())
109 }
110
111 pub fn join(&self) -> StrokeJoin {
113 ffi::stroke_rec_join(self.as_holder_ref())
114 }
115
116 pub fn miter_limit(&self) -> f32 {
118 ffi::stroke_rec_miter_limit(self.as_holder_ref())
119 }
120
121 pub fn style(&self) -> StrokeStyle {
123 match ffi::stroke_rec_get_style(self.as_holder_ref()) {
124 ffi::StrokeRecStyleTag::Hairline => StrokeStyle::Hairline,
125 ffi::StrokeRecStyleTag::Fill => StrokeStyle::Fill,
126 ffi::StrokeRecStyleTag::Stroke => StrokeStyle::Stroke {
127 width: ffi::stroke_rec_width(self.as_holder_ref()),
128 stroke_and_fill: false,
129 },
130 ffi::StrokeRecStyleTag::StrokeAndFill => StrokeStyle::StrokeAndFill {
131 width: ffi::stroke_rec_width(self.as_holder_ref()),
132 },
133 _ => StrokeStyle::Fill,
134 }
135 }
136
137 pub fn width(&self) -> f32 {
139 ffi::stroke_rec_width(self.as_holder_ref())
140 }
141
142 pub fn inflation_radius(&self) -> f32 {
144 ffi::stroke_rec_inflation_radius(self.as_holder_ref())
145 }
146
147 pub fn apply_to_path(&self, path: &Path) -> Option<Path> {
153 let mut dst = Path::new();
154 let ok = ffi::stroke_rec_apply_to_path(
155 self.as_holder_ref(),
156 dst.as_raw_pin_mut(),
157 path.as_raw(),
158 );
159 if ok {
160 Some(dst)
161 } else {
162 None
163 }
164 }
165
166 pub(crate) fn as_holder_ref(&self) -> &ffi::StrokeRecHolder {
167 self.inner.as_ref().expect("StrokeRec")
168 }
169
170 pub(crate) fn pin_holder_mut(&mut self) -> std::pin::Pin<&mut ffi::StrokeRecHolder> {
171 self.inner.pin_mut()
172 }
173}
174
175impl Default for StrokeRec {
176 fn default() -> Self {
177 Self::new_fill()
178 }
179}