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, PartialEq, Eq, PartialOrd, Ord, Hash)]
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    /// Computes the bounds of the given path.
39    ///
40    /// The returned bounds may be larger than necessary, because this
41    /// function aims to be fast, not accurate. The bounds are guaranteed
42    /// to contain the path.
43    ///
44    /// It is possible that the returned rectangle has 0 width and/or height.
45    /// This can happen when the path only describes a point or an
46    /// axis-aligned line.
47    ///
48    /// If the path is empty, false is returned and @bounds are set to
49    /// graphene_rect_zero(). This is different from the case where the path
50    /// is a single point at the origin, where the @bounds will also be set to
51    /// the zero rectangle but true will be returned.
52    ///
53    /// # Returns
54    ///
55    /// true if the path has bounds, false if the path is known
56    ///   to be empty and have no bounds
57    ///
58    /// ## `bounds`
59    /// return location for the bounds
60    #[doc(alias = "gsk_path_get_bounds")]
61    #[doc(alias = "get_bounds")]
62    pub fn bounds(&self) -> Option<graphene::Rect> {
63        unsafe {
64            let mut bounds = graphene::Rect::uninitialized();
65            let ret = from_glib(ffi::gsk_path_get_bounds(
66                self.to_glib_none().0,
67                bounds.to_glib_none_mut().0,
68            ));
69            if ret {
70                Some(bounds)
71            } else {
72                None
73            }
74        }
75    }
76
77    /// Computes the closest point on the path to the given point.
78    ///
79    /// If there is no point closer than the given threshold,
80    /// false is returned.
81    /// ## `point`
82    /// the point
83    /// ## `threshold`
84    /// maximum allowed distance
85    ///
86    /// # Returns
87    ///
88    /// true if @point was set to the closest point
89    ///   on @self, false if no point is closer than @threshold
90    ///
91    /// ## `result`
92    /// return location for the closest point
93    ///
94    /// ## `distance`
95    /// return location for the distance
96    #[doc(alias = "gsk_path_get_closest_point")]
97    #[doc(alias = "get_closest_point")]
98    pub fn closest_point(
99        &self,
100        point: &graphene::Point,
101        threshold: f32,
102    ) -> Option<(PathPoint, f32)> {
103        unsafe {
104            let mut result = PathPoint::uninitialized();
105            let mut distance = std::mem::MaybeUninit::uninit();
106            let ret = from_glib(ffi::gsk_path_get_closest_point(
107                self.to_glib_none().0,
108                point.to_glib_none().0,
109                threshold,
110                result.to_glib_none_mut().0,
111                distance.as_mut_ptr(),
112            ));
113            if ret {
114                Some((result, distance.assume_init()))
115            } else {
116                None
117            }
118        }
119    }
120
121    /// Gets the end point of the path.
122    ///
123    /// An empty path has no points, so false
124    /// is returned in this case.
125    ///
126    /// # Returns
127    ///
128    /// true if @result was filled
129    ///
130    /// ## `result`
131    /// return location for point
132    #[doc(alias = "gsk_path_get_end_point")]
133    #[doc(alias = "get_end_point")]
134    pub fn end_point(&self) -> Option<PathPoint> {
135        unsafe {
136            let mut result = PathPoint::uninitialized();
137            let ret = from_glib(ffi::gsk_path_get_end_point(
138                self.to_glib_none().0,
139                result.to_glib_none_mut().0,
140            ));
141            if ret {
142                Some(result)
143            } else {
144                None
145            }
146        }
147    }
148
149    /// Gets the start point of the path.
150    ///
151    /// An empty path has no points, so false
152    /// is returned in this case.
153    ///
154    /// # Returns
155    ///
156    /// true if @result was filled
157    ///
158    /// ## `result`
159    /// return location for point
160    #[doc(alias = "gsk_path_get_start_point")]
161    #[doc(alias = "get_start_point")]
162    pub fn start_point(&self) -> Option<PathPoint> {
163        unsafe {
164            let mut result = PathPoint::uninitialized();
165            let ret = from_glib(ffi::gsk_path_get_start_point(
166                self.to_glib_none().0,
167                result.to_glib_none_mut().0,
168            ));
169            if ret {
170                Some(result)
171            } else {
172                None
173            }
174        }
175    }
176
177    /// Computes the bounds for stroking the given path with the
178    /// given parameters.
179    ///
180    /// The returned bounds may be larger than necessary, because this
181    /// function aims to be fast, not accurate. The bounds are guaranteed
182    /// to contain the area affected by the stroke, including protrusions
183    /// like miters.
184    /// ## `stroke`
185    /// stroke parameters
186    ///
187    /// # Returns
188    ///
189    /// true if the path has bounds, false if the path is known
190    ///   to be empty and have no bounds.
191    ///
192    /// ## `bounds`
193    /// the bounds to fill in
194    #[doc(alias = "gsk_path_get_stroke_bounds")]
195    #[doc(alias = "get_stroke_bounds")]
196    pub fn stroke_bounds(&self, stroke: &Stroke) -> Option<graphene::Rect> {
197        unsafe {
198            let mut bounds = graphene::Rect::uninitialized();
199            let ret = from_glib(ffi::gsk_path_get_stroke_bounds(
200                self.to_glib_none().0,
201                stroke.to_glib_none().0,
202                bounds.to_glib_none_mut().0,
203            ));
204            if ret {
205                Some(bounds)
206            } else {
207                None
208            }
209        }
210    }
211
212    /// Returns whether a point is inside the fill area of a path.
213    ///
214    /// Note that this function assumes that filling a contour
215    /// implicitly closes it.
216    /// ## `point`
217    /// the point to test
218    /// ## `fill_rule`
219    /// the fill rule to follow
220    ///
221    /// # Returns
222    ///
223    /// true if @point is inside
224    #[doc(alias = "gsk_path_in_fill")]
225    pub fn in_fill(&self, point: &graphene::Point, fill_rule: FillRule) -> bool {
226        unsafe {
227            from_glib(ffi::gsk_path_in_fill(
228                self.to_glib_none().0,
229                point.to_glib_none().0,
230                fill_rule.into_glib(),
231            ))
232        }
233    }
234
235    /// Returns if the path represents a single closed contour.
236    ///
237    /// # Returns
238    ///
239    /// true if the path is closed
240    #[doc(alias = "gsk_path_is_closed")]
241    pub fn is_closed(&self) -> bool {
242        unsafe { from_glib(ffi::gsk_path_is_closed(self.to_glib_none().0)) }
243    }
244
245    /// Checks if the path is empty, i.e. contains no lines or curves.
246    ///
247    /// # Returns
248    ///
249    /// true if the path is empty
250    #[doc(alias = "gsk_path_is_empty")]
251    pub fn is_empty(&self) -> bool {
252        unsafe { from_glib(ffi::gsk_path_is_empty(self.to_glib_none().0)) }
253    }
254
255    /// Appends the path to a cairo context for drawing with Cairo.
256    ///
257    /// This may cause some suboptimal conversions to be performed as
258    /// Cairo does not support all features of [`Path`][crate::Path].
259    ///
260    /// This function does not clear the existing Cairo path. Call
261    /// cairo_new_path() if you want this.
262    /// ## `cr`
263    /// a cairo context
264    #[doc(alias = "gsk_path_to_cairo")]
265    pub fn to_cairo(&self, cr: &cairo::Context) {
266        unsafe {
267            ffi::gsk_path_to_cairo(self.to_glib_none().0, mut_override(cr.to_glib_none().0));
268        }
269    }
270
271    /// Converts the path into a human-readable string.
272    ///
273    /// You can use this function in a debugger to get a quick overview
274    /// of the path.
275    ///
276    /// This is a wrapper around `Gsk::Path::print()`, see that function
277    /// for details.
278    ///
279    /// # Returns
280    ///
281    /// a new string for @self
282    #[doc(alias = "gsk_path_to_string")]
283    #[doc(alias = "to_string")]
284    pub fn to_str(&self) -> glib::GString {
285        unsafe { from_glib_full(ffi::gsk_path_to_string(self.to_glib_none().0)) }
286    }
287
288    /// Constructs a path from a serialized form.
289    ///
290    /// The string is expected to be in (a superset of)
291    /// [SVG path syntax](https://www.w3.org/TR/SVG11/paths.html#PathData),
292    /// as e.g. produced by [`to_str()`][Self::to_str()].
293    ///
294    /// A high-level summary of the syntax:
295    ///
296    /// - `M x y` Move to `(x, y)`
297    /// - `L x y` Add a line from the current point to `(x, y)`
298    /// - `Q x1 y1 x2 y2` Add a quadratic Bézier from the current point to `(x2, y2)`, with control point `(x1, y1)`
299    /// - `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)`
300    /// - `Z` Close the contour by drawing a line back to the start point
301    /// - `H x` Add a horizontal line from the current point to the given x value
302    /// - `V y` Add a vertical line from the current point to the given y value
303    /// - `T x2 y2` Add a quadratic Bézier, using the reflection of the previous segments' control point as control point
304    /// - `S x2 y2 x3 y3` Add a cubic Bézier, using the reflection of the previous segments' second control point as first control point
305    /// - `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.
306    /// - `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`.
307    ///
308    /// All the commands have lowercase variants that interpret coordinates
309    /// relative to the current point.
310    ///
311    /// The `O` command is an extension that is not supported in SVG.
312    /// ## `string`
313    /// a string
314    ///
315    /// # Returns
316    ///
317    /// a new [`Path`][crate::Path], or `NULL` if @string could not be parsed
318    #[doc(alias = "gsk_path_parse")]
319    pub fn parse(string: &str) -> Result<Path, glib::BoolError> {
320        assert_initialized_main_thread!();
321        unsafe {
322            Option::<_>::from_glib_full(ffi::gsk_path_parse(string.to_glib_none().0))
323                .ok_or_else(|| glib::bool_error!("Can't parse Path"))
324        }
325    }
326}
327
328impl std::fmt::Display for Path {
329    #[inline]
330    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
331        f.write_str(&self.to_str())
332    }
333}