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
use crate::*;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u32)]
pub enum CapStyle {
Flat = D2D1_CAP_STYLE_FLAT.0,
Square = D2D1_CAP_STYLE_SQUARE.0,
Round = D2D1_CAP_STYLE_ROUND.0,
Triangle = D2D1_CAP_STYLE_TRIANGLE.0,
}
#[derive(Clone, Copy, Debug)]
pub enum LineJoin {
Miter,
Bevel,
Round,
MiterOrBevel(f32),
}
#[derive(Clone, Copy, Debug)]
pub enum DashStyle<'a> {
Solid,
Dash,
Dot,
DashDot,
DashDotDot,
Custom(&'a [f32]),
}
#[derive(Debug)]
pub struct Dash<'a> {
pub cap: CapStyle,
pub style: DashStyle<'a>,
pub offset: f32,
}
impl<'a> Default for Dash<'a> {
#[inline]
fn default() -> Self {
Self {
cap: CapStyle::Flat,
style: DashStyle::Solid,
offset: 0.0,
}
}
}
#[derive(Debug)]
pub struct StrokeStyleProperties<'a> {
pub start_cap: CapStyle,
pub end_cap: CapStyle,
pub line_join: LineJoin,
pub dash: Option<Dash<'a>>,
}
impl<'a> Default for StrokeStyleProperties<'a> {
#[inline]
fn default() -> Self {
Self {
start_cap: CapStyle::Flat,
end_cap: CapStyle::Flat,
line_join: LineJoin::Miter,
dash: None,
}
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct StrokeStyle(pub(crate) ID2D1StrokeStyle);
impl StrokeStyle {
pub(crate) fn new(
factory: &ID2D1Factory1,
props: &StrokeStyleProperties,
) -> windows::core::Result<Self> {
let (dash_cap, dash_style, dash_offset, dashes, dashes_len) = match props.dash.as_ref() {
Some(dash) => {
let cap = D2D1_CAP_STYLE(dash.cap as _);
let (style, dashes, dashes_len) = match dash.style {
DashStyle::Solid => (D2D1_DASH_STYLE_SOLID, std::ptr::null(), 0),
DashStyle::Dash => (D2D1_DASH_STYLE_DASH, std::ptr::null(), 0),
DashStyle::Dot => (D2D1_DASH_STYLE_DOT, std::ptr::null(), 0),
DashStyle::DashDot => (D2D1_DASH_STYLE_DASH_DOT, std::ptr::null(), 0),
DashStyle::DashDotDot => (D2D1_DASH_STYLE_DASH_DOT_DOT, std::ptr::null(), 0),
DashStyle::Custom(dashes) => {
(D2D1_DASH_STYLE_CUSTOM, dashes.as_ptr(), dashes.len())
}
};
(cap, style, dash.offset, dashes, dashes_len)
}
None => (
D2D1_CAP_STYLE_FLAT,
D2D1_DASH_STYLE_SOLID,
0.0,
std::ptr::null(),
0,
),
};
let (line_join, miter_limit) = match props.line_join {
LineJoin::Miter => (D2D1_LINE_JOIN_MITER, 1.0),
LineJoin::Bevel => (D2D1_LINE_JOIN_BEVEL, 1.0),
LineJoin::Round => (D2D1_LINE_JOIN_ROUND, 1.0),
LineJoin::MiterOrBevel(miter_limit) => (D2D1_LINE_JOIN_MITER_OR_BEVEL, miter_limit),
};
let props = D2D1_STROKE_STYLE_PROPERTIES {
startCap: D2D1_CAP_STYLE(props.start_cap as _),
endCap: D2D1_CAP_STYLE(props.end_cap as _),
dashCap: dash_cap,
lineJoin: line_join,
miterLimit: miter_limit,
dashStyle: dash_style,
dashOffset: dash_offset,
};
let stroke_style = unsafe { factory.CreateStrokeStyle(&props, dashes, dashes_len as _)? };
Ok(StrokeStyle(stroke_style))
}
}
unsafe impl Send for StrokeStyle {}
unsafe impl Sync for StrokeStyle {}