Skip to main content

path_kit/
stroke_rec.rs

1//! 描边参数。Stroke parameters for path outlining.
2
3use crate::path::Path;
4use crate::pathkit;
5
6/// 线端样式。Line cap style - how stroke ends are drawn.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
8pub enum StrokeCap {
9    /// 平头 / Butt (no cap)
10    #[default]
11    Butt = 0,
12    /// 圆头 / Round cap
13    Round = 1,
14    /// 方头 / Square cap
15    Square = 2,
16}
17
18/// 转角连接样式。Line join style - how stroke corners are drawn.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
20pub enum StrokeJoin {
21    /// 尖角 / Miter join (sharp)
22    #[default]
23    Miter = 0,
24    /// 圆角 / Round join
25    Round = 1,
26    /// 斜切 / Bevel join
27    Bevel = 2,
28}
29
30impl From<StrokeCap> for pathkit::SkPaint_Cap::Type {
31    fn from(c: StrokeCap) -> Self {
32        match c {
33            StrokeCap::Butt => pathkit::SkPaint_Cap::kButt_Cap,
34            StrokeCap::Round => pathkit::SkPaint_Cap::kRound_Cap,
35            StrokeCap::Square => pathkit::SkPaint_Cap::kSquare_Cap,
36        }
37    }
38}
39
40impl From<u32> for StrokeCap {
41    fn from(v: u32) -> Self {
42        match v {
43            1 => StrokeCap::Round,
44            2 => StrokeCap::Square,
45            _ => StrokeCap::Butt,
46        }
47    }
48}
49
50impl From<StrokeJoin> for pathkit::SkPaint_Join::Type {
51    fn from(j: StrokeJoin) -> Self {
52        match j {
53            StrokeJoin::Miter => pathkit::SkPaint_Join::kMiter_Join,
54            StrokeJoin::Round => pathkit::SkPaint_Join::kRound_Join,
55            StrokeJoin::Bevel => pathkit::SkPaint_Join::kBevel_Join,
56        }
57    }
58}
59
60impl From<u32> for StrokeJoin {
61    fn from(v: u32) -> Self {
62        match v {
63            1 => StrokeJoin::Round,
64            2 => StrokeJoin::Bevel,
65            _ => StrokeJoin::Miter,
66        }
67    }
68}
69
70/// 描边样式。Stroke style.
71#[derive(Debug, Clone, Copy, PartialEq)]
72pub enum StrokeStyle {
73    /// 极细线 / Hairline (1 pixel)
74    Hairline,
75    /// 填充 / Fill (no stroke)
76    Fill,
77    /// 描边 / Stroke with width
78    Stroke { width: f32, stroke_and_fill: bool },
79    /// 描边+填充 / Stroke and fill
80    StrokeAndFill { width: f32 },
81}
82
83/// 描边参数,描述如何将路径转为描边轮廓。
84/// Stroke parameters - describes how to expand a path to a stroke outline.
85///
86/// 用于 `apply_to_path` 将路径转换为描边后的填充路径。
87/// Used with `apply_to_path` to convert a path to its stroked fill equivalent.
88pub struct StrokeRec {
89    inner: pathkit::SkStrokeRec,
90}
91
92impl StrokeRec {
93    /// 创建填充样式(无描边)。Creates fill style (no stroke).
94    pub fn new_fill() -> Self {
95        Self {
96            inner: unsafe {
97                pathkit::SkStrokeRec::new(pathkit::SkStrokeRec_InitStyle::kFill_InitStyle)
98            },
99        }
100    }
101
102    /// 创建极细线样式。Creates hairline style (1-pixel stroke).
103    pub fn new_hairline() -> Self {
104        Self {
105            inner: unsafe {
106                pathkit::SkStrokeRec::new(pathkit::SkStrokeRec_InitStyle::kHairline_InitStyle)
107            },
108        }
109    }
110
111    /// 创建描边样式。Creates stroke style with given width.
112    pub fn new_stroke(width: f32, stroke_and_fill: bool) -> Self {
113        let mut rec = Self::new_hairline();
114        unsafe {
115            rec.inner.setStrokeStyle(width, stroke_and_fill);
116        }
117        rec
118    }
119
120    /// 设置为填充样式。Sets to fill style.
121    pub fn set_fill(&mut self) {
122        unsafe {
123            self.inner.setFillStyle();
124        }
125    }
126
127    /// 设置为极细线。Sets to hairline style.
128    pub fn set_hairline(&mut self) {
129        unsafe {
130            self.inner.setHairlineStyle();
131        }
132    }
133
134    /// 设置描边宽度。Sets stroke width (width=0 may switch to fill/hairline).
135    pub fn set_stroke_style(&mut self, width: f32, stroke_and_fill: bool) {
136        unsafe {
137            self.inner.setStrokeStyle(width, stroke_and_fill);
138        }
139    }
140
141    /// 设置线端样式。Sets line cap (Butt, Round, Square).
142    pub fn set_cap(&mut self, cap: StrokeCap) {
143        self.inner.set_fCap(cap as u32);
144    }
145
146    /// 设置转角连接样式。Sets line join (Miter, Round, Bevel).
147    pub fn set_join(&mut self, join: StrokeJoin) {
148        self.inner.set_fJoin(join as u32);
149    }
150
151    /// 设置描边端点与转角参数。Sets cap, join, and miter limit.
152    pub fn set_stroke_params(&mut self, cap: StrokeCap, join: StrokeJoin, miter_limit: f32) {
153        self.inner.set_fCap(cap as u32);
154        self.inner.set_fJoin(join as u32);
155        self.inner.fMiterLimit = miter_limit;
156    }
157
158    /// 线端样式。Returns line cap.
159    pub fn cap(&self) -> StrokeCap {
160        StrokeCap::from(self.inner.fCap())
161    }
162
163    /// 转角连接样式。Returns line join.
164    pub fn join(&self) -> StrokeJoin {
165        StrokeJoin::from(self.inner.fJoin())
166    }
167
168    /// Miter 限制(尖角最长延伸比)。Returns miter limit.
169    pub fn miter_limit(&self) -> f32 {
170        self.inner.fMiterLimit
171    }
172
173    /// 当前样式。Returns current style (hairline/fill/stroke).
174    pub fn style(&self) -> StrokeStyle {
175        let raw = unsafe { self.inner.getStyle() };
176        match raw {
177            pathkit::SkStrokeRec_Style::kHairline_Style => StrokeStyle::Hairline,
178            pathkit::SkStrokeRec_Style::kFill_Style => StrokeStyle::Fill,
179            pathkit::SkStrokeRec_Style::kStroke_Style => StrokeStyle::Stroke {
180                width: self.inner.fWidth,
181                stroke_and_fill: false,
182            },
183            pathkit::SkStrokeRec_Style::kStrokeAndFill_Style => StrokeStyle::StrokeAndFill {
184                width: self.inner.fWidth,
185            },
186            _ => StrokeStyle::Fill,
187        }
188    }
189
190    /// 描边宽度。Returns stroke width.
191    pub fn width(&self) -> f32 {
192        self.inner.fWidth
193    }
194
195    /// 膨胀半径(用于边界计算)。Inflation radius for bounds.
196    pub fn inflation_radius(&self) -> f32 {
197        unsafe { self.inner.getInflationRadius() }
198    }
199
200    /// 将描边参数应用到路径,返回描边后的填充路径。
201    /// Applies stroke to path, returning the stroked outline as a fill path.
202    ///
203    /// 若样式为 fill/hairline 则返回 None。
204    /// Returns None if style is fill or hairline (no expansion).
205    pub fn apply_to_path(&self, path: &Path) -> Option<Path> {
206        let mut dst = Path::new();
207        let ok = unsafe {
208            pathkit::SkStrokeRec_applyToPath(
209                &self.inner as *const _,
210                dst.as_raw_mut() as *mut _,
211                path.as_raw() as *const _,
212            )
213        };
214        if ok {
215            Some(dst)
216        } else {
217            None
218        }
219    }
220
221    /// 内部 SkStrokeRec 引用(仅 crate 内使用,如 PathEffect filterPath)。Internal use only.
222    #[allow(dead_code)]
223    pub(crate) fn as_raw(&self) -> &pathkit::SkStrokeRec {
224        &self.inner
225    }
226
227    /// 内部 SkStrokeRec 可变引用(仅 crate 内使用,如 PathEffect filterPath)。Internal use only.
228    #[allow(dead_code)]
229    pub(crate) fn as_raw_mut(&mut self) -> &mut pathkit::SkStrokeRec {
230        &mut self.inner
231    }
232}
233
234impl Default for StrokeRec {
235    fn default() -> Self {
236        Self::new_fill()
237    }
238}