gsk4/auto/path.rs
1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{ffi, FillRule, PathPoint, Stroke};
6use glib::translate::*;
7
8glib::wrapper! {
9 /// Describes lines and curves that are more complex than simple rectangles.
10 ///
11 /// Paths can used for rendering (filling or stroking) and for animations
12 /// (e.g. as trajectories).
13 ///
14 /// [`Path`][crate::Path] is an immutable, opaque, reference-counted struct.
15 /// After creation, you cannot change the types it represents. Instead,
16 /// new [`Path`][crate::Path] objects have to be created. The [`PathBuilder`][crate::PathBuilder]
17 /// structure is meant to help in this endeavor.
18 ///
19 /// Conceptually, a path consists of zero or more contours (continuous, connected
20 /// curves), each of which may or may not be closed. Contours are typically
21 /// constructed from Bézier segments.
22 ///
23 /// <picture>
24 /// <source srcset="path-dark.png" media="(prefers-color-scheme: dark)">
25 /// <img alt="A Path" src="path-light.png">
26 /// </picture>
27 #[derive(Debug)]
28 pub struct Path(Shared<ffi::GskPath>);
29
30 match fn {
31 ref => |ptr| ffi::gsk_path_ref(ptr),
32 unref => |ptr| ffi::gsk_path_unref(ptr),
33 type_ => || ffi::gsk_path_get_type(),
34 }
35}
36
37impl Path {
38 #[cfg(feature = "v4_22")]
39 #[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))]
40 #[doc(alias = "gsk_path_equal")]
41 fn equal(&self, path2: &Path) -> bool {
42 unsafe {
43 from_glib(ffi::gsk_path_equal(
44 self.to_glib_none().0,
45 path2.to_glib_none().0,
46 ))
47 }
48 }
49
50 /// Computes the bounds of the given path.
51 ///
52 /// The returned bounds may be larger than necessary, because this
53 /// function aims to be fast, not accurate. The bounds are guaranteed
54 /// to contain the path.
55 ///
56 /// It is possible that the returned rectangle has 0 width and/or height.
57 /// This can happen when the path only describes a point or an
58 /// axis-aligned line.
59 ///
60 /// If the path is empty, false is returned and @bounds are set to
61 /// graphene_rect_zero(). This is different from the case where the path
62 /// is a single point at the origin, where the @bounds will also be set to
63 /// the zero rectangle but true will be returned.
64 ///
65 /// # Returns
66 ///
67 /// true if the path has bounds, false if the path is known
68 /// to be empty and have no bounds
69 ///
70 /// ## `bounds`
71 /// return location for the bounds
72 #[doc(alias = "gsk_path_get_bounds")]
73 #[doc(alias = "get_bounds")]
74 pub fn bounds(&self) -> Option<graphene::Rect> {
75 unsafe {
76 let mut bounds = graphene::Rect::uninitialized();
77 let ret = from_glib(ffi::gsk_path_get_bounds(
78 self.to_glib_none().0,
79 bounds.to_glib_none_mut().0,
80 ));
81 if ret {
82 Some(bounds)
83 } else {
84 None
85 }
86 }
87 }
88
89 /// Computes the closest point on the path to the given point.
90 ///
91 /// If there is no point closer than the given threshold,
92 /// false is returned.
93 /// ## `point`
94 /// the point
95 /// ## `threshold`
96 /// maximum allowed distance
97 ///
98 /// # Returns
99 ///
100 /// true if @point was set to the closest point
101 /// on @self, false if no point is closer than @threshold
102 ///
103 /// ## `result`
104 /// return location for the closest point
105 ///
106 /// ## `distance`
107 /// return location for the distance
108 #[doc(alias = "gsk_path_get_closest_point")]
109 #[doc(alias = "get_closest_point")]
110 pub fn closest_point(
111 &self,
112 point: &graphene::Point,
113 threshold: f32,
114 ) -> Option<(PathPoint, f32)> {
115 unsafe {
116 let mut result = PathPoint::uninitialized();
117 let mut distance = std::mem::MaybeUninit::uninit();
118 let ret = from_glib(ffi::gsk_path_get_closest_point(
119 self.to_glib_none().0,
120 point.to_glib_none().0,
121 threshold,
122 result.to_glib_none_mut().0,
123 distance.as_mut_ptr(),
124 ));
125 if ret {
126 Some((result, distance.assume_init()))
127 } else {
128 None
129 }
130 }
131 }
132
133 /// Gets the end point of the path.
134 ///
135 /// An empty path has no points, so false
136 /// is returned in this case.
137 ///
138 /// # Returns
139 ///
140 /// true if @result was filled
141 ///
142 /// ## `result`
143 /// return location for point
144 #[doc(alias = "gsk_path_get_end_point")]
145 #[doc(alias = "get_end_point")]
146 pub fn end_point(&self) -> Option<PathPoint> {
147 unsafe {
148 let mut result = PathPoint::uninitialized();
149 let ret = from_glib(ffi::gsk_path_get_end_point(
150 self.to_glib_none().0,
151 result.to_glib_none_mut().0,
152 ));
153 if ret {
154 Some(result)
155 } else {
156 None
157 }
158 }
159 }
160
161 /// Gets the start point of the path.
162 ///
163 /// An empty path has no points, so false
164 /// is returned in this case.
165 ///
166 /// # Returns
167 ///
168 /// true if @result was filled
169 ///
170 /// ## `result`
171 /// return location for point
172 #[doc(alias = "gsk_path_get_start_point")]
173 #[doc(alias = "get_start_point")]
174 pub fn start_point(&self) -> Option<PathPoint> {
175 unsafe {
176 let mut result = PathPoint::uninitialized();
177 let ret = from_glib(ffi::gsk_path_get_start_point(
178 self.to_glib_none().0,
179 result.to_glib_none_mut().0,
180 ));
181 if ret {
182 Some(result)
183 } else {
184 None
185 }
186 }
187 }
188
189 /// Computes the bounds for stroking the given path with the
190 /// given parameters.
191 ///
192 /// The returned bounds may be larger than necessary, because this
193 /// function aims to be fast, not accurate. The bounds are guaranteed
194 /// to contain the area affected by the stroke, including protrusions
195 /// like miters.
196 /// ## `stroke`
197 /// stroke parameters
198 ///
199 /// # Returns
200 ///
201 /// true if the path has bounds, false if the path is known
202 /// to be empty and have no bounds.
203 ///
204 /// ## `bounds`
205 /// the bounds to fill in
206 #[doc(alias = "gsk_path_get_stroke_bounds")]
207 #[doc(alias = "get_stroke_bounds")]
208 pub fn stroke_bounds(&self, stroke: &Stroke) -> Option<graphene::Rect> {
209 unsafe {
210 let mut bounds = graphene::Rect::uninitialized();
211 let ret = from_glib(ffi::gsk_path_get_stroke_bounds(
212 self.to_glib_none().0,
213 stroke.to_glib_none().0,
214 bounds.to_glib_none_mut().0,
215 ));
216 if ret {
217 Some(bounds)
218 } else {
219 None
220 }
221 }
222 }
223
224 /// Returns whether a point is inside the fill area of a path.
225 ///
226 /// Note that this function assumes that filling a contour
227 /// implicitly closes it.
228 /// ## `point`
229 /// the point to test
230 /// ## `fill_rule`
231 /// the fill rule to follow
232 ///
233 /// # Returns
234 ///
235 /// true if @point is inside
236 #[doc(alias = "gsk_path_in_fill")]
237 pub fn in_fill(&self, point: &graphene::Point, fill_rule: FillRule) -> bool {
238 unsafe {
239 from_glib(ffi::gsk_path_in_fill(
240 self.to_glib_none().0,
241 point.to_glib_none().0,
242 fill_rule.into_glib(),
243 ))
244 }
245 }
246
247 /// Returns if the path represents a single closed contour.
248 ///
249 /// # Returns
250 ///
251 /// true if the path is closed
252 #[doc(alias = "gsk_path_is_closed")]
253 pub fn is_closed(&self) -> bool {
254 unsafe { from_glib(ffi::gsk_path_is_closed(self.to_glib_none().0)) }
255 }
256
257 /// Checks if the path is empty, i.e. contains no lines or curves.
258 ///
259 /// # Returns
260 ///
261 /// true if the path is empty
262 #[doc(alias = "gsk_path_is_empty")]
263 pub fn is_empty(&self) -> bool {
264 unsafe { from_glib(ffi::gsk_path_is_empty(self.to_glib_none().0)) }
265 }
266
267 /// Appends the path to a cairo context for drawing with Cairo.
268 ///
269 /// This may cause some suboptimal conversions to be performed as
270 /// Cairo does not support all features of [`Path`][crate::Path].
271 ///
272 /// This function does not clear the existing Cairo path. Call
273 /// cairo_new_path() if you want this.
274 /// ## `cr`
275 /// a cairo context
276 #[doc(alias = "gsk_path_to_cairo")]
277 pub fn to_cairo(&self, cr: &cairo::Context) {
278 unsafe {
279 ffi::gsk_path_to_cairo(self.to_glib_none().0, mut_override(cr.to_glib_none().0));
280 }
281 }
282
283 /// Converts the path into a human-readable string.
284 ///
285 /// You can use this function in a debugger to get a quick overview
286 /// of the path.
287 ///
288 /// This is a wrapper around `Gsk::Path::print()`, see that function
289 /// for details.
290 ///
291 /// # Returns
292 ///
293 /// a new string for @self
294 #[doc(alias = "gsk_path_to_string")]
295 #[doc(alias = "to_string")]
296 pub fn to_str(&self) -> glib::GString {
297 unsafe { from_glib_full(ffi::gsk_path_to_string(self.to_glib_none().0)) }
298 }
299
300 /// Constructs a path from a serialized form.
301 ///
302 /// The string is expected to be in (a superset of)
303 /// [SVG path syntax](https://www.w3.org/TR/SVG11/paths.html#PathData),
304 /// as e.g. produced by [`to_str()`][Self::to_str()].
305 ///
306 /// A high-level summary of the syntax:
307 ///
308 /// - `M x y` Move to `(x, y)`
309 /// - `L x y` Add a line from the current point to `(x, y)`
310 /// - `Q x1 y1 x2 y2` Add a quadratic Bézier from the current point to `(x2, y2)`, with control point `(x1, y1)`
311 /// - `C x1 y1 x2 y2 x3 y3` Add a cubic Bézier from the current point to `(x3, y3)`, with control points `(x1, y1)` and `(x2, y2)`
312 /// - `Z` Close the contour by drawing a line back to the start point
313 /// - `H x` Add a horizontal line from the current point to the given x value
314 /// - `V y` Add a vertical line from the current point to the given y value
315 /// - `T x2 y2` Add a quadratic Bézier, using the reflection of the previous segments' control point as control point
316 /// - `S x2 y2 x3 y3` Add a cubic Bézier, using the reflection of the previous segments' second control point as first control point
317 /// - `A rx ry r l s x y` Add an elliptical arc from the current point to `(x, y)` with radii rx and ry. See the SVG documentation for how the other parameters influence the arc.
318 /// - `O x1 y1 x2 y2 w` Add a rational quadratic Bézier from the current point to `(x2, y2)` with control point `(x1, y1)` and weight `w`.
319 ///
320 /// All the commands have lowercase variants that interpret coordinates
321 /// relative to the current point.
322 ///
323 /// The `O` command is an extension that is not supported in SVG.
324 /// ## `string`
325 /// a string
326 ///
327 /// # Returns
328 ///
329 /// a new [`Path`][crate::Path], or `NULL` if @string could not be parsed
330 #[doc(alias = "gsk_path_parse")]
331 pub fn parse(string: &str) -> Result<Path, glib::BoolError> {
332 assert_initialized_main_thread!();
333 unsafe {
334 Option::<_>::from_glib_full(ffi::gsk_path_parse(string.to_glib_none().0))
335 .ok_or_else(|| glib::bool_error!("Can't parse Path"))
336 }
337 }
338}
339
340#[cfg(feature = "v4_22")]
341#[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))]
342impl PartialEq for Path {
343 #[inline]
344 fn eq(&self, other: &Self) -> bool {
345 self.equal(other)
346 }
347}
348
349#[cfg(feature = "v4_22")]
350#[cfg_attr(docsrs, doc(cfg(feature = "v4_22")))]
351impl Eq for Path {}
352
353impl std::fmt::Display for Path {
354 #[inline]
355 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
356 f.write_str(&self.to_str())
357 }
358}