Skip to content

Commit

Permalink
Accept more single-function transforms in pico_svg.
Browse files Browse the repository at this point in the history
  • Loading branch information
xorgy committed Mar 10, 2024
1 parent c341e40 commit 71d4138
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 24 deletions.
56 changes: 40 additions & 16 deletions examples/scenes/src/pico_svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ use std::{num::ParseFloatError, str::FromStr};

use roxmltree::{Document, Node};
use vello::{
kurbo::{Affine, BezPath, Point, Size},
kurbo::{Affine, BezPath, Point, Size, Vec2},
peniko::Color,
};

pub struct PicoSvg {
pub items: Vec<Item>,
pub origin: Point,
pub size: Size,
}

Expand Down Expand Up @@ -41,15 +40,6 @@ impl PicoSvg {
let root = doc.root_element();
let mut items = Vec::new();
let mut parser = Parser::new(&mut items, scale);
let transform = if scale >= 0.0 {
Affine::scale(scale)
} else {
Affine::new([-scale, 0.0, 0.0, scale, 0.0, 0.0])
};
let props = RecursiveProperties {
transform,
fill: Some(Color::BLACK),
};
let (origin, size) = if let Some(vb_attr) = root.attribute("viewBox") {
let vs: Vec<f64> = vb_attr
.split(' ')
Expand Down Expand Up @@ -86,15 +76,21 @@ impl PicoSvg {
)
}
};
let transform = Affine::translate(origin.to_vec2() * -1.0)
* if scale >= 0.0 {
Affine::scale(scale)
} else {
Affine::new([-scale, 0.0, 0.0, scale, 0.0, 0.0])
};
let props = RecursiveProperties {
transform,
fill: Some(Color::BLACK),
};
// The root element is the svg document element, which we don't care about
for node in root.children() {
parser.rec_parse(node, &props)?;
}
Ok(PicoSvg {
items,
origin,
size,
})
Ok(PicoSvg { items, size })
}
}

Expand Down Expand Up @@ -182,6 +178,34 @@ fn parse_transform(transform: &str) -> Affine {
vals.try_into()
.expect("Should be six arguments to `matrix`"),
)
} else if transform.starts_with("translate(") {
if let Ok(vals) = transform["translate(".len()..transform.len() - 1]
.split(' ')
.map(str::trim)
.map(str::parse)
.collect::<Result<Vec<f64>, ParseFloatError>>()
{
match vals.as_slice() {
&[x, y] => Affine::translate(Vec2 { x, y }),
_ => Affine::IDENTITY,
}
} else {
Affine::IDENTITY
}
} else if transform.starts_with("scale(") {
if let Ok(vals) = transform["scale(".len()..transform.len() - 1]
.split(' ')
.map(str::trim)
.map(str::parse)
.collect::<Result<Vec<f64>, ParseFloatError>>()
{
match vals.as_slice() {
&[x, y] => Affine::scale_non_uniform(x, y),
_ => Affine::IDENTITY,
}
} else {
Affine::IDENTITY
}
} else {
eprintln!("Did not understand transform attribute {transform:?}");
Affine::IDENTITY
Expand Down
17 changes: 9 additions & 8 deletions examples/scenes/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,24 +101,25 @@ pub fn svg_function_of<R: AsRef<str>>(
let mut new_scene = Scene::new();
let mut resolution = Vec2::new(420 as f64, 420 as f64);
match PicoSvg::load(contents, 1.0) {
std::result::Result::Ok(PicoSvg {
items,
origin,
size,
}) => {
std::result::Result::Ok(PicoSvg { items, size }) => {
eprintln!("Parsed svg {name} in {:?}", start.elapsed());
start = Instant::now();
resolution = size.to_vec2();
let transform = Affine::translate(origin.to_vec2() * -1.0);
for item in items {
match item {
Item::Fill(fill) => {
new_scene.fill(Fill::NonZero, transform, fill.color, None, &fill.path);
new_scene.fill(
Fill::NonZero,
Affine::IDENTITY,
fill.color,
None,
&fill.path,
);
}
Item::Stroke(stroke) => {
new_scene.stroke(
&Stroke::new(stroke.width),
transform,
Affine::IDENTITY,
stroke.color,
None,
&stroke.path,
Expand Down

0 comments on commit 71d4138

Please sign in to comment.