Skip to content

Commit

Permalink
Add viewbox and width/height support to pico_svg.
Browse files Browse the repository at this point in the history
  • Loading branch information
xorgy committed Mar 10, 2024
1 parent ce76835 commit c341e40
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 26 deletions.
46 changes: 44 additions & 2 deletions examples/scenes/src/pico_svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ use std::{num::ParseFloatError, str::FromStr};

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

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

pub enum Item {
Expand Down Expand Up @@ -48,11 +50,51 @@ impl PicoSvg {
transform,
fill: Some(Color::BLACK),
};
let (origin, size) = if let Some(vb_attr) = root.attribute("viewBox") {
let vs: Vec<f64> = vb_attr
.split(' ')
.map(|s| f64::from_str(s).unwrap())
.collect();
match vs.as_slice() {
&[x, y, width, height] => (Point { x, y }, Size { width, height }),
_ => (
Point::ZERO,
Size {
width: 300.0,
height: 150.0,
},
),
}
} else {
let maybe_width = root.attribute("width");
let maybe_height = root.attribute("height");
if maybe_width.is_some() && maybe_height.is_some() {
(
Point::ZERO,
Size {
width: f64::from_str(maybe_width.unwrap()).unwrap(),
height: f64::from_str(maybe_height.unwrap()).unwrap(),
},
)
} else {
(
Point::ZERO,
Size {
width: 300.0,
height: 150.0,
},
)
}
};
// 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 })
Ok(PicoSvg {
items,
origin,
size,
})
}
}

Expand Down
55 changes: 31 additions & 24 deletions examples/scenes/src/svg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,34 +97,41 @@ pub fn svg_function_of<R: AsRef<str>>(
) -> impl FnMut(&mut Scene, &mut SceneParams) {
fn render_svg_contents(name: &str, contents: &str) -> (Scene, Vec2) {
use crate::pico_svg::*;
let start = Instant::now();
eprintln!("Parsed svg {name} in {:?}", start.elapsed());
let svg = PicoSvg::load(contents, 1.0).unwrap();
let start = Instant::now();
let mut start = Instant::now();
let mut new_scene = Scene::new();
for item in &svg.items {
match item {
Item::Fill(fill) => {
new_scene.fill(
Fill::NonZero,
Affine::IDENTITY,
fill.color,
None,
&fill.path,
);
}
Item::Stroke(stroke) => {
new_scene.stroke(
&Stroke::new(stroke.width),
Affine::IDENTITY,
stroke.color,
None,
&stroke.path,
);
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,
}) => {
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);
}
Item::Stroke(stroke) => {
new_scene.stroke(
&Stroke::new(stroke.width),
transform,
stroke.color,
None,
&stroke.path,
);
}
}
}
}
std::result::Result::Err(e) => {
eprintln!("{:?}", e);
}
}
let resolution = Vec2::new(420 as f64, 420 as f64);

eprintln!("Encoded svg {name} in {:?}", start.elapsed());
(new_scene, resolution)
}
Expand Down

0 comments on commit c341e40

Please sign in to comment.