From f3cb904f866a9469dae606dde112e1872a553386 Mon Sep 17 00:00:00 2001 From: Raph Levien Date: Sun, 31 May 2020 09:55:20 -0700 Subject: [PATCH] Add command line args for loading svg --- Cargo.lock | 72 ++++++++++++++++++++++++++++++++++++++++ piet-gpu/Cargo.toml | 1 + piet-gpu/bin/cli.rs | 27 +++++++++++++-- piet-gpu/src/lib.rs | 40 +++++++++++----------- piet-gpu/src/pico_svg.rs | 29 +++++++++++----- 5 files changed, 139 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4a0a133..2755d5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,6 +26,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407" +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +dependencies = [ + "winapi 0.3.8", +] + [[package]] name = "approx" version = "0.3.2" @@ -59,6 +68,17 @@ dependencies = [ "raw-window-handle", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi 0.3.8", +] + [[package]] name = "autocfg" version = "1.0.0" @@ -106,6 +126,21 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" +[[package]] +name = "clap" +version = "2.33.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" +dependencies = [ + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -259,6 +294,15 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36b5f248235f45773d4944f555f83ea61fe07b18b561ccf99d7483d7381e54d" +[[package]] +name = "hermit-abi" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" +dependencies = [ + "libc", +] + [[package]] name = "inflate" version = "0.4.5" @@ -525,6 +569,7 @@ dependencies = [ name = "piet-gpu" version = "0.1.0" dependencies = [ + "clap", "piet", "piet-gpu-hal", "piet-gpu-types", @@ -758,6 +803,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "syn" version = "1.0.17" @@ -769,6 +820,21 @@ dependencies = [ "unicode-xid 0.2.0", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "unicode-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" + [[package]] name = "unicode-xid" version = "0.1.0" @@ -781,6 +847,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "void" version = "1.0.2" diff --git a/piet-gpu/Cargo.toml b/piet-gpu/Cargo.toml index 6bdf178..a338d76 100644 --- a/piet-gpu/Cargo.toml +++ b/piet-gpu/Cargo.toml @@ -26,3 +26,4 @@ png = "0.16.2" rand = "0.7.3" roxmltree = "0.11" winit = "0.22" +clap = "2.33" diff --git a/piet-gpu/bin/cli.rs b/piet-gpu/bin/cli.rs index 5d7c09e..31024aa 100644 --- a/piet-gpu/bin/cli.rs +++ b/piet-gpu/bin/cli.rs @@ -2,10 +2,12 @@ use std::fs::File; use std::io::BufWriter; use std::path::Path; +use clap::{Arg, App}; + use piet_gpu_hal::vulkan::VkInstance; use piet_gpu_hal::{CmdBuf, Device, Error, MemFlags}; -use piet_gpu::{render_scene, PietGpuRenderContext, Renderer, HEIGHT, WIDTH}; +use piet_gpu::{render_scene, render_svg, PietGpuRenderContext, Renderer, HEIGHT, WIDTH}; #[allow(unused)] fn dump_scene(buf: &[u8]) { @@ -152,6 +154,17 @@ fn trace_ptcl(buf: &[u32]) { fn main() -> Result<(), Error> { + let matches = App::new("piet-gpu test") + .arg(Arg::with_name("INPUT") + .index(1)) + .arg(Arg::with_name("flip") + .short("f") + .long("flip")) + .arg(Arg::with_name("scale") + .short("s") + .long("scale") + .takes_value(true)) + .get_matches(); let (instance, _) = VkInstance::new(None)?; unsafe { let device = instance.device(None)?; @@ -161,7 +174,17 @@ fn main() -> Result<(), Error> { let query_pool = device.create_query_pool(5)?; let mut ctx = PietGpuRenderContext::new(); - render_scene(&mut ctx); + if let Some(input) = matches.value_of("INPUT") { + let mut scale = matches.value_of("scale") + .map(|scale| scale.parse().unwrap()) + .unwrap_or(8.0); + if matches.is_present("flip") { + scale = -scale; + } + render_svg(&mut ctx, input, scale); + } else { + render_scene(&mut ctx); + } let scene = ctx.get_scene_buf(); //dump_scene(&scene); diff --git a/piet-gpu/src/lib.rs b/piet-gpu/src/lib.rs index 4652c5a..3ec7e1d 100644 --- a/piet-gpu/src/lib.rs +++ b/piet-gpu/src/lib.rs @@ -34,6 +34,17 @@ const N_CIRCLES: usize = 0; const N_WG: u32 = 16; +pub fn render_svg(rc: &mut impl RenderContext, filename: &str, scale: f64) { + let xml_str = std::fs::read_to_string(filename).unwrap(); + let start = std::time::Instant::now(); + let svg = PicoSvg::load(&xml_str, scale).unwrap(); + println!("parsing time: {:?}", start.elapsed()); + + let start = std::time::Instant::now(); + svg.render(rc); + println!("flattening and encoding time: {:?}", start.elapsed()); +} + pub fn render_scene(rc: &mut impl RenderContext) { let mut rng = rand::thread_rng(); for _ in 0..N_CIRCLES { @@ -138,7 +149,7 @@ pub struct Renderer { k4_pipeline: D::Pipeline, k4_ds: D::DescriptorSet, - + n_elements: usize, } @@ -177,13 +188,10 @@ impl Renderer { // TODO: constants let bin_alloc_start = ((n_elements + 255) & !255) * 8; - device - .write_buffer(&bin_alloc_buf_host, &[ - n_elements as u32, - 0, - bin_alloc_start as u32, - ]) - ?; + device.write_buffer( + &bin_alloc_buf_host, + &[n_elements as u32, 0, bin_alloc_start as u32], + )?; let bin_code = include_bytes!("../shader/binning.spv"); let bin_pipeline = device.create_simple_compute_pipeline(bin_code, 4, 0)?; let bin_ds = device.create_descriptor_set( @@ -196,12 +204,10 @@ impl Renderer { let coarse_alloc_buf_dev = device.create_buffer(8, dev)?; let coarse_alloc_start = WIDTH_IN_TILES * HEIGHT_IN_TILES * PTCL_INITIAL_ALLOC; - device - .write_buffer(&coarse_alloc_buf_host, &[ - n_elements as u32, - coarse_alloc_start as u32, - ]) - ?; + device.write_buffer( + &coarse_alloc_buf_host, + &[n_elements as u32, coarse_alloc_start as u32], + )?; let coarse_code = include_bytes!("../shader/coarse.spv"); let coarse_pipeline = device.create_simple_compute_pipeline(coarse_code, 4, 0)?; let coarse_ds = device.create_descriptor_set( @@ -212,11 +218,7 @@ impl Renderer { let k4_code = include_bytes!("../shader/kernel4.spv"); let k4_pipeline = device.create_simple_compute_pipeline(k4_code, 1, 1)?; - let k4_ds = device.create_descriptor_set( - &k4_pipeline, - &[&ptcl_buf], - &[&image_dev], - )?; + let k4_ds = device.create_descriptor_set(&k4_pipeline, &[&ptcl_buf], &[&image_dev])?; Ok(Renderer { scene_buf, diff --git a/piet-gpu/src/pico_svg.rs b/piet-gpu/src/pico_svg.rs index 5317f5e..140c42d 100644 --- a/piet-gpu/src/pico_svg.rs +++ b/piet-gpu/src/pico_svg.rs @@ -29,6 +29,7 @@ pub struct FillItem { } struct Parser<'a> { + scale: f64, items: &'a mut Vec, } @@ -37,7 +38,7 @@ impl PicoSvg { let doc = Document::parse(xml_string)?; let root = doc.root_element(); let mut items = Vec::new(); - let mut parser = Parser::new(&mut items); + let mut parser = Parser::new(&mut items, scale); for node in root.children() { parser.rec_parse(node)?; } @@ -60,13 +61,16 @@ impl PicoSvg { } impl<'a> Parser<'a> { - fn new(items: &'a mut Vec) -> Parser<'a> { - Parser { - items - } + fn new(items: &'a mut Vec, scale: f64) -> Parser<'a> { + Parser { scale, items } } fn rec_parse(&mut self, node: Node) -> Result<(), Box> { + let transform = if self.scale >= 0.0 { + Affine::scale(self.scale) + } else { + Affine::new([-self.scale, 0.0, 0.0, self.scale, 0.0, 1536.0]) + }; if node.is_element() { match node.tag_name().name() { "g" => { @@ -77,21 +81,28 @@ impl<'a> Parser<'a> { "path" => { let d = node.attribute("d").ok_or("missing 'd' attribute")?; let bp = BezPath::from_svg(d)?; - let path = Affine::new([1.5, 0.0, 0.0, -1.5, 0.0, 1500.0]) * bp; + let path = transform * bp; // TODO: default fill color is black, but this is overridden in tiger to this logic. if let Some(fill_color) = node.attribute("fill") { if fill_color != "none" { let color = parse_color(fill_color); let color = modify_opacity(color, "fill-opacity", node); - self.items.push(Item::Fill(FillItem { color, path: path.clone() })); + self.items.push(Item::Fill(FillItem { + color, + path: path.clone(), + })); } } if let Some(stroke_color) = node.attribute("stroke") { if stroke_color != "none" { - let width = 1.5 * f64::from_str(node.attribute("stroke-width").ok_or("missing width")?)?; + let width = self.scale.abs() + * f64::from_str( + node.attribute("stroke-width").ok_or("missing width")?, + )?; let color = parse_color(stroke_color); let color = modify_opacity(color, "stroke-opacity", node); - self.items.push(Item::Stroke(StrokeItem { width, color, path })); + self.items + .push(Item::Stroke(StrokeItem { width, color, path })); } } }