making svg a little smarter

This commit is contained in:
Chris Cochrun 2025-04-01 09:55:13 -05:00
parent ed80ccaa55
commit b65ac72a01

View file

@ -4,7 +4,7 @@ use colors_transform::Rgb;
use cosmic::{ use cosmic::{
iced::font::{Style, Weight}, iced::font::{Style, Weight},
prelude::*, prelude::*,
widget::{svg::Handle, Svg}, widget::{responsive, svg::Handle, Svg},
}; };
use tracing::error; use tracing::error;
@ -166,15 +166,25 @@ impl TextSvg {
"".into() "".into()
}; };
// text y coords are based on bottom left corner so we need to take height into consideration // text y coords are based on bottom left corner so we need to take height into consideration
let base = format!("<svg viewBox=\"0 0 240 100\" xmlns=\"http://www.w3.org/2000/svg\"><defs>{}</defs> responsive(move |s| {
let text_pieces: Vec<String> = self.text.lines().map(|t| format!("<tspan>{}</tspan>", t)).collect();
let base = format!("<svg viewBox=\"0 0 {} {}\" xmlns=\"http://www.w3.org/2000/svg\"><defs>{}</defs>
<text x=\"0\" y=\"50\" font-weight=\"bold\" font-family=\"{}\" font-size=\"{}\" fill=\"{}\" {} style=\"filter:url(#shadow);\"> <text x=\"0\" y=\"50\" font-weight=\"bold\" font-family=\"{}\" font-size=\"{}\" fill=\"{}\" {} style=\"filter:url(#shadow);\">
{} {}
</text></svg>", shadow, self.font.name, self.font.size, self.fill, stroke, self.text); </text></svg>", s.width, s.height, shadow, self.font.name, self.font.size, self.fill, stroke, self.text);
Svg::new(Handle::from_memory( Svg::new(Handle::from_memory(
Box::leak(base.into_boxed_str()).as_bytes(), Box::leak(base.into_boxed_str()).as_bytes(),
)) )).into()
})
.into() .into()
} }
fn text_spans(&self) -> Vec<String> {
self.text
.lines()
.map(|t| format!("<tspan>{}</tspan>", t))
.collect()
}
} }
pub fn shadow( pub fn shadow(
@ -201,3 +211,27 @@ pub fn stroke(size: u16, color: impl Into<Color>) -> Stroke {
pub fn color(color: impl AsRef<str>) -> Color { pub fn color(color: impl AsRef<str>) -> Color {
Color::from_hex_str(color) Color::from_hex_str(color)
} }
#[cfg(test)]
mod test {
use pretty_assertions::assert_eq;
use super::TextSvg;
#[test]
fn test_text_spans() {
let mut text = TextSvg::new();
text.text = "This is
multiline
text."
.into();
assert_eq!(
vec![
String::from("<tspan>This is</tspan>"),
String::from("<tspan>multiline</tspan>"),
String::from("<tspan>text.</tspan>"),
],
text.text_spans()
)
}
}