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}