use super::values::{escape_xml, num};
use crate::resolve::AttrMap;
use std::fmt::Write;
pub(crate) fn emit(
out: &mut String,
indent: &str,
class: &str,
content: &str,
pos: (f64, f64),
attrs: &AttrMap,
style: &str,
) {
let (x, y) = pos;
let (xs, ys) = (num(x), num(y));
let ls = attrs.number("letter-spacing").unwrap_or(0.0);
let xform = match attrs.number("rotate") {
Some(r) if r != 0.0 => format!(r#" transform="rotate({} {} {})""#, num(r), xs, ys),
_ => String::new(),
};
let lines: Vec<&str> = content.split('\n').collect();
if lines.len() <= 1 {
writeln!(
out,
r#"{indent}<text class="{class}" x="{xs}" y="{ys}"{}{style}{xform}>{}</text>"#,
dx_attr(content, ls),
escape_xml(content),
)
.unwrap();
return;
}
let size = attrs.number("font-size").unwrap_or(0.0);
let spacing = size * 1.2 + attrs.number("line-spacing").unwrap_or(0.0);
let top = y - spacing * (lines.len() as f64 - 1.0) / 2.0;
write!(
out,
r#"{indent}<text class="{class}" x="{xs}" y="{ys}"{style}{xform}>"#
)
.unwrap();
for (i, line) in lines.iter().enumerate() {
if i == 0 {
write!(
out,
r#"<tspan x="{xs}" y="{}"{}>{}</tspan>"#,
num(top),
dx_attr(line, ls),
escape_xml(line)
)
.unwrap();
} else {
write!(
out,
r#"<tspan x="{xs}" dy="{}"{}>{}</tspan>"#,
num(spacing),
dx_attr(line, ls),
escape_xml(line)
)
.unwrap();
}
}
writeln!(out, "</text>").unwrap();
}
fn dx_attr(line: &str, letter_spacing: f64) -> String {
let count = line.chars().count();
if letter_spacing == 0.0 || count < 2 {
return String::new();
}
let mut s = String::from(r#" dx="0"#);
for _ in 1..count {
s.push(' ');
s.push_str(&num(letter_spacing));
}
s.push('"');
s
}