mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-29 20:27:05 -06:00
Merge pull request #4604 from Ridzzz0Alam/fix/3209-svg-css-units
Fix #3209: SVG export writes type sizes and spacing in CSS with px
This commit is contained in:
@@ -292,14 +292,18 @@ impl Writer<'_> {
|
||||
format!("matrix({} {} {} {} {} {})", self.num(c[0]), self.num(c[1]), self.num(c[2]), self.num(c[3]), self.num(c[4]), self.num(c[5]))
|
||||
}
|
||||
|
||||
/// How style properties are written: the styling option, but SVG Tiny has presentation
|
||||
/// attributes alone.
|
||||
pub(super) fn styling(&self) -> Styling {
|
||||
if self.tiny() { Styling::PresentationAttributes } else { self.opts.styling }
|
||||
}
|
||||
|
||||
/// Style properties as attributes, an inline style, or a CSS class, per the styling option.
|
||||
pub(super) fn attrs(&mut self, props: &Props) -> String {
|
||||
if props.is_empty() {
|
||||
return String::new();
|
||||
}
|
||||
// SVG Tiny has presentation attributes alone.
|
||||
let styling = if self.tiny() { Styling::PresentationAttributes } else { self.opts.styling };
|
||||
match styling {
|
||||
match self.styling() {
|
||||
Styling::PresentationAttributes => {
|
||||
// CSS-only properties go in a style attribute (SVG Tiny has none: left out).
|
||||
let (style, attrs): (Vec<_>, Vec<_>) = props.iter().partition(|(k, _)| {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use super::output::xml_text;
|
||||
use super::{
|
||||
Affine, AppearanceItem, Arc, BTreeSet, BezPath, BlendMode, CharStyle, FillRule, FontDb, FontFace, GradientKind, HashMap, Justify, Node, NodeId,
|
||||
NodeKind, Paint, PathData, Props, Rect, StrokeAlign, TextKind, TextObject, Writer, base64_encode, css, css_string, fmt_num, font_descriptor,
|
||||
xml_escape,
|
||||
NodeKind, Paint, PathData, Props, Rect, StrokeAlign, Styling, TextKind, TextObject, Writer, base64_encode, css, css_string, fmt_num,
|
||||
font_descriptor, xml_escape,
|
||||
};
|
||||
|
||||
/// `chars` (sorted) as a CSS `unicode-range` (`U+41-5A,U+61`).
|
||||
@@ -36,7 +36,10 @@ impl Writer<'_> {
|
||||
/// (as on the canvas).
|
||||
fn char_props(&mut self, st: &CharStyle, space: (Rect, Affine)) -> Props {
|
||||
let decimals = self.opts.decimals;
|
||||
let len = |v: f64| fmt_num(v, decimals);
|
||||
// Only presentation attributes take a bare number (in user units). Written as CSS, a
|
||||
// length needs its unit, a user unit being a `px`: a browser drops `font-size:8.6` (#3209).
|
||||
let unit = if self.styling() == Styling::PresentationAttributes { "" } else { "px" };
|
||||
let len = |v: f64| format!("{}{unit}", fmt_num(v, decimals));
|
||||
let mut p = css::font_props(st, &len);
|
||||
// Character paints resolve in the text's space (`to_user` maps it into user space).
|
||||
let (bounds, to_user) = space;
|
||||
|
||||
@@ -228,8 +228,16 @@ fn shared_properties_read_as_svg_export_writes_them() {
|
||||
let decl = format!("{k}:{v}").replace('"', """).replace('\'', "'");
|
||||
assert!(style.contains(&decl), "{decl} as in SVG export: {style}");
|
||||
}
|
||||
// Lengths are the same numbers, with units on the web.
|
||||
assert!(style.contains("font-size:18") && prop(&r, "font-size") == Some("18px"), "{style}");
|
||||
// Lengths are the same, with units: CSS takes a bare number only for 0, and a browser drops
|
||||
// `font-size:18`, leaving the type at its default size (#3209). Presentation attributes take
|
||||
// bare numbers (`text_layout`).
|
||||
let spacing = prop(&r, "letter-spacing").unwrap_or_default();
|
||||
assert!(prop(&r, "font-size") == Some("18px") && spacing.ends_with("px"), "{r:?}");
|
||||
for decl in ["font-size:18px".to_string(), format!("letter-spacing:{spacing}")] {
|
||||
assert!(style.contains(&decl), "{decl} as in SVG export: {style}");
|
||||
}
|
||||
let inline = export(&d, &ExportOptions { styling: Styling::InlineStyle, ..ExportOptions::default() });
|
||||
assert!(inline.contains("font-size:18px") && inline.contains(&format!("letter-spacing:{spacing}")), "{inline}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user