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