1use crate::color::Color;
5
6#[derive(Clone, Debug, PartialEq)]
8pub struct DashPattern {
9 pub dashes: Vec<f64>,
11 pub offset: f64,
13}
14
15impl DashPattern {
16 pub fn new(dashes: &[f64]) -> Self {
18 Self {
19 dashes: dashes.to_vec(),
20 offset: 0.0,
21 }
22 }
23
24 pub fn to_svg_string(&self) -> String {
26 self.dashes
27 .iter()
28 .map(|d| format!("{d}"))
29 .collect::<Vec<_>>()
30 .join(",")
31 }
32}
33
34#[derive(Clone, Debug)]
36pub struct Stroke {
37 pub color: Color,
39 pub width: f64,
41 pub dash: Option<DashPattern>,
43 pub line_cap: LineCap,
45 pub line_join: LineJoin,
47}
48
49impl Stroke {
50 pub fn solid(color: Color, width: f64) -> Self {
52 Self {
53 color,
54 width,
55 dash: None,
56 line_cap: LineCap::Butt,
57 line_join: LineJoin::Miter,
58 }
59 }
60
61 pub fn dashed(color: Color, width: f64, dashes: &[f64]) -> Self {
63 Self {
64 color,
65 width,
66 dash: Some(DashPattern::new(dashes)),
67 line_cap: LineCap::Butt,
68 line_join: LineJoin::Miter,
69 }
70 }
71}
72
73impl Default for Stroke {
74 fn default() -> Self {
75 Self::solid(Color::BLACK, 1.0)
76 }
77}
78
79#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
81pub enum LineCap {
82 #[default]
84 Butt,
85 Round,
87 Square,
89}
90
91impl LineCap {
92 pub fn as_svg_str(self) -> &'static str {
94 match self {
95 Self::Butt => "butt",
96 Self::Round => "round",
97 Self::Square => "square",
98 }
99 }
100}
101
102#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
104pub enum LineJoin {
105 #[default]
107 Miter,
108 Round,
110 Bevel,
112}
113
114impl LineJoin {
115 pub fn as_svg_str(self) -> &'static str {
117 match self {
118 Self::Miter => "miter",
119 Self::Round => "round",
120 Self::Bevel => "bevel",
121 }
122 }
123}
124
125#[derive(Clone, Debug, Default)]
127pub enum Fill {
128 #[default]
130 None,
131 Solid(Color),
133 Gradient(String),
135}
136
137impl Fill {
138 pub fn to_svg_string(&self) -> String {
140 match self {
141 Self::None => "none".to_string(),
142 Self::Solid(c) => c.to_svg_string(),
143 Self::Gradient(id) => format!("url(#{id})"),
144 }
145 }
146}
147
148#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
150pub enum TextAnchor {
151 #[default]
153 Start,
154 Middle,
156 End,
158}
159
160impl TextAnchor {
161 pub fn as_svg_str(self) -> &'static str {
163 match self {
164 Self::Start => "start",
165 Self::Middle => "middle",
166 Self::End => "end",
167 }
168 }
169}
170
171#[derive(Clone, Debug)]
173pub struct FontStyle {
174 pub family: String,
176 pub size: f64,
178 pub weight: u16,
180 pub color: Color,
182 pub anchor: TextAnchor,
184}
185
186impl FontStyle {
187 pub fn new(size: f64) -> Self {
189 Self {
190 family: "sans-serif".to_string(),
191 size,
192 weight: 400,
193 color: Color::BLACK,
194 anchor: TextAnchor::Start,
195 }
196 }
197}
198
199impl Default for FontStyle {
200 fn default() -> Self {
201 Self::new(12.0)
202 }
203}