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}