Skip to main content

path_kit/
stroke_rec.rs

1//! 描边参数。Stroke parameters for path outlining.
2
3use crate::bridge::ffi;
4use crate::path::Path;
5use cxx::UniquePtr;
6
7pub use crate::bridge::ffi::{StrokeCap, StrokeJoin};
8
9impl Default for StrokeCap {
10    fn default() -> Self {
11        StrokeCap::Butt
12    }
13}
14
15impl Default for StrokeJoin {
16    fn default() -> Self {
17        StrokeJoin::Miter
18    }
19}
20
21/// 描边样式快照,由 `SkStrokeRec::getStyle` 与宽度组合而成。
22/// Stroke style snapshot from `SkStrokeRec::getStyle` plus width.
23#[derive(Debug, Clone, Copy, PartialEq)]
24pub enum StrokeStyle {
25    /// 极细线。Hairline stroke.
26    Hairline,
27    /// 填充(无描边扩展)。Fill only (no stroke expansion).
28    Fill,
29    /// 描边宽度;`stroke_and_fill` 与原生 `kStroke_Style` 一致时为 false。
30    /// Stroke width; `stroke_and_fill` is false for native `kStroke_Style`.
31    Stroke {
32        /// 描边宽度 / Stroke width
33        width: f32,
34        /// 是否与 fill 组合(原生 `StrokeAndFill` 为单独枚举变体)。
35        /// Combined stroke+fill flag (native uses a separate style for stroke-and-fill).
36        stroke_and_fill: bool,
37    },
38    /// 描边并填充。Stroke and fill.
39    StrokeAndFill {
40        /// 描边宽度 / Stroke width
41        width: f32,
42    },
43}
44
45/// 描边参数,描述如何将路径转为描边轮廓。
46/// Stroke parameters - describes how to expand a path to a stroke outline.
47///
48/// 用于 `apply_to_path` 将路径转换为描边后的填充路径。
49/// Used with `apply_to_path` to convert a path to a stroked fill equivalent.
50pub struct StrokeRec {
51    inner: UniquePtr<ffi::StrokeRecHolder>,
52}
53
54impl StrokeRec {
55    /// 创建填充样式(无描边)。Creates fill style (no stroke).
56    pub fn new_fill() -> Self {
57        Self {
58            inner: ffi::stroke_rec_new(ffi::StrokeRecInit::Fill),
59        }
60    }
61
62    /// 创建极细线样式。Creates hairline style (1-pixel stroke).
63    pub fn new_hairline() -> Self {
64        Self {
65            inner: ffi::stroke_rec_new(ffi::StrokeRecInit::Hairline),
66        }
67    }
68
69    /// 创建描边样式。Creates stroke style with given width.
70    pub fn new_stroke(width: f32, stroke_and_fill: bool) -> Self {
71        let mut rec = Self::new_hairline();
72        ffi::stroke_rec_set_stroke_style(rec.inner.pin_mut(), width, stroke_and_fill);
73        rec
74    }
75
76    /// 设置为填充样式。Sets to fill style.
77    pub fn set_fill(&mut self) {
78        ffi::stroke_rec_set_fill(self.inner.pin_mut());
79    }
80
81    /// 设置为极细线。Sets to hairline style.
82    pub fn set_hairline(&mut self) {
83        ffi::stroke_rec_set_hairline(self.inner.pin_mut());
84    }
85
86    /// 设置描边宽度。Sets stroke width (width=0 may switch to fill/hairline).
87    pub fn set_stroke_style(&mut self, width: f32, stroke_and_fill: bool) {
88        ffi::stroke_rec_set_stroke_style(self.inner.pin_mut(), width, stroke_and_fill);
89    }
90
91    /// 设置线端样式。Sets line cap (Butt, Round, Square).
92    pub fn set_cap(&mut self, cap: StrokeCap) {
93        ffi::stroke_rec_set_cap(self.inner.pin_mut(), cap);
94    }
95
96    /// 设置转角连接样式。Sets line join (Miter, Round, Bevel).
97    pub fn set_join(&mut self, join: StrokeJoin) {
98        ffi::stroke_rec_set_join(self.inner.pin_mut(), join);
99    }
100
101    /// 设置描边端点与转角参数。Sets cap, join, and miter limit.
102    pub fn set_stroke_params(&mut self, cap: StrokeCap, join: StrokeJoin, miter_limit: f32) {
103        ffi::stroke_rec_set_stroke_params(self.inner.pin_mut(), cap, join, miter_limit);
104    }
105
106    /// 线端样式。Returns line cap.
107    pub fn cap(&self) -> StrokeCap {
108        ffi::stroke_rec_cap(self.as_holder_ref())
109    }
110
111    /// 转角连接样式。Returns line join.
112    pub fn join(&self) -> StrokeJoin {
113        ffi::stroke_rec_join(self.as_holder_ref())
114    }
115
116    /// Miter 限制(尖角最长延伸比)。Returns miter limit.
117    pub fn miter_limit(&self) -> f32 {
118        ffi::stroke_rec_miter_limit(self.as_holder_ref())
119    }
120
121    /// 当前样式。Returns current style (hairline/fill/stroke).
122    pub fn style(&self) -> StrokeStyle {
123        match ffi::stroke_rec_get_style(self.as_holder_ref()) {
124            ffi::StrokeRecStyleTag::Hairline => StrokeStyle::Hairline,
125            ffi::StrokeRecStyleTag::Fill => StrokeStyle::Fill,
126            ffi::StrokeRecStyleTag::Stroke => StrokeStyle::Stroke {
127                width: ffi::stroke_rec_width(self.as_holder_ref()),
128                stroke_and_fill: false,
129            },
130            ffi::StrokeRecStyleTag::StrokeAndFill => StrokeStyle::StrokeAndFill {
131                width: ffi::stroke_rec_width(self.as_holder_ref()),
132            },
133            _ => StrokeStyle::Fill,
134        }
135    }
136
137    /// 描边宽度。Returns stroke width.
138    pub fn width(&self) -> f32 {
139        ffi::stroke_rec_width(self.as_holder_ref())
140    }
141
142    /// 膨胀半径(用于边界计算)。Inflation radius for bounds.
143    pub fn inflation_radius(&self) -> f32 {
144        ffi::stroke_rec_inflation_radius(self.as_holder_ref())
145    }
146
147    /// 将描边参数应用到路径,返回描边后的填充路径。
148    /// Applies stroke to path, returning the stroked outline as a fill path.
149    ///
150    /// 若样式为 fill/hairline 则返回 None。
151    /// Returns None if style is fill or hairline (no expansion).
152    pub fn apply_to_path(&self, path: &Path) -> Option<Path> {
153        let mut dst = Path::new();
154        let ok = ffi::stroke_rec_apply_to_path(
155            self.as_holder_ref(),
156            dst.as_raw_pin_mut(),
157            path.as_raw(),
158        );
159        if ok {
160            Some(dst)
161        } else {
162            None
163        }
164    }
165
166    pub(crate) fn as_holder_ref(&self) -> &ffi::StrokeRecHolder {
167        self.inner.as_ref().expect("StrokeRec")
168    }
169
170    pub(crate) fn pin_holder_mut(&mut self) -> std::pin::Pin<&mut ffi::StrokeRecHolder> {
171        self.inner.pin_mut()
172    }
173}
174
175impl Default for StrokeRec {
176    fn default() -> Self {
177        Self::new_fill()
178    }
179}