1 | use crate::{prelude::*, scalar, Matrix, Path, Point, Vector}; |
2 | use skia_bindings::{self as sb, SkContourMeasure, SkContourMeasureIter, SkRefCntBase}; |
3 | use std::fmt; |
4 | |
5 | pub type ContourMeasure = RCHandle<SkContourMeasure>; |
6 | unsafe_send_sync!(ContourMeasure); |
7 | |
8 | impl NativeRefCountedBase for SkContourMeasure { |
9 | type Base = SkRefCntBase; |
10 | } |
11 | |
12 | bitflags! { |
13 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
14 | pub struct MatrixFlags : u32 { |
15 | const GET_POSITION = sb::SkContourMeasure_MatrixFlags_kGetPosition_MatrixFlag as _; |
16 | const GET_TANGENT = sb::SkContourMeasure_MatrixFlags_kGetTangent_MatrixFlag as _; |
17 | const GET_POS_AND_TAN = Self::GET_POSITION.bits() | Self::GET_TANGENT.bits(); |
18 | } |
19 | } |
20 | |
21 | impl Default for MatrixFlags { |
22 | fn default() -> Self { |
23 | Self::GET_POS_AND_TAN |
24 | } |
25 | } |
26 | |
27 | impl fmt::Debug for ContourMeasure { |
28 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
29 | f&mut DebugStruct<'_, '_>.debug_struct("ContourMeasure" ) |
30 | .field("length" , &self.length()) |
31 | .field(name:"is_closed" , &self.is_closed()) |
32 | .finish() |
33 | } |
34 | } |
35 | |
36 | impl ContourMeasure { |
37 | pub fn length(&self) -> scalar { |
38 | unsafe { sb::C_SkContourMeasure_length(self.native()) } |
39 | } |
40 | |
41 | #[must_use ] |
42 | pub fn pos_tan(&self, distance: scalar) -> Option<(Point, Vector)> { |
43 | let mut p = Point::default(); |
44 | let mut v = Vector::default(); |
45 | unsafe { |
46 | self.native() |
47 | .getPosTan(distance, p.native_mut(), v.native_mut()) |
48 | } |
49 | .if_true_some((p, v)) |
50 | } |
51 | |
52 | #[must_use ] |
53 | pub fn get_matrix( |
54 | &self, |
55 | distance: scalar, |
56 | flags: impl Into<Option<MatrixFlags>>, |
57 | ) -> Option<Matrix> { |
58 | let mut m = Matrix::default(); |
59 | unsafe { |
60 | self.native().getMatrix( |
61 | distance, |
62 | m.native_mut(), |
63 | // note: depending on the OS, different representation types are generated for |
64 | // MatrixFlags, so the try_into() is required, even though clippy complains about |
65 | // it. |
66 | #[allow (clippy::useless_conversion)] |
67 | flags.into().unwrap_or_default().bits().try_into().unwrap(), |
68 | ) |
69 | } |
70 | .if_true_some(m) |
71 | } |
72 | |
73 | #[must_use ] |
74 | pub fn segment( |
75 | &self, |
76 | start_d: scalar, |
77 | stop_d: scalar, |
78 | start_with_move_to: bool, |
79 | ) -> Option<Path> { |
80 | let mut p = Path::default(); |
81 | unsafe { |
82 | self.native() |
83 | .getSegment(start_d, stop_d, p.native_mut(), start_with_move_to) |
84 | } |
85 | .if_true_some(p) |
86 | } |
87 | |
88 | pub fn is_closed(&self) -> bool { |
89 | unsafe { sb::C_SkContourMeasure_isClosed(self.native()) } |
90 | } |
91 | } |
92 | |
93 | pub type ContourMeasureIter = Handle<SkContourMeasureIter>; |
94 | unsafe_send_sync!(ContourMeasureIter); |
95 | |
96 | impl NativeDrop for SkContourMeasureIter { |
97 | fn drop(&mut self) { |
98 | unsafe { |
99 | sb::C_SkContourMeasureIter_destruct(self); |
100 | } |
101 | } |
102 | } |
103 | |
104 | impl Iterator for ContourMeasureIter { |
105 | type Item = ContourMeasure; |
106 | |
107 | fn next(&mut self) -> Option<Self::Item> { |
108 | ContourMeasure::from_ptr(unsafe { sb::C_SkContourMeasureIter_next(self.native_mut()) }) |
109 | } |
110 | } |
111 | |
112 | impl fmt::Debug for ContourMeasureIter { |
113 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
114 | f.debug_struct(name:"ContourMeasureIter" ).finish() |
115 | } |
116 | } |
117 | |
118 | impl ContourMeasureIter { |
119 | // Canonical new: |
120 | pub fn new(path: &Path, force_closed: bool, res_scale: impl Into<Option<scalar>>) -> Self { |
121 | Self::from_path(path, force_closed, res_scale) |
122 | } |
123 | |
124 | // TODO: rename to of_path? for_path? |
125 | // TODO: may deprecate in favor of Self::new(). |
126 | pub fn from_path( |
127 | path: &Path, |
128 | force_closed: bool, |
129 | res_scale: impl Into<Option<scalar>>, |
130 | ) -> Self { |
131 | Self::from_native_c(unsafe { |
132 | SkContourMeasureIter::new1(path.native(), force_closed, res_scale.into().unwrap_or(1.0)) |
133 | }) |
134 | } |
135 | |
136 | pub fn reset( |
137 | &mut self, |
138 | path: &Path, |
139 | force_closed: bool, |
140 | res_scale: impl Into<Option<scalar>>, |
141 | ) -> &mut Self { |
142 | unsafe { |
143 | self.native_mut() |
144 | .reset(path.native(), force_closed, res_scale.into().unwrap_or(1.0)) |
145 | } |
146 | self |
147 | } |
148 | } |
149 | |