Commit Graph

265 Commits

Author SHA1 Message Date
Patrick Walton 1deb53fa9c Implement the remaining Porter-Duff compositing operators 2020-02-25 18:37:23 -08:00
Patrick Walton e7de50eb67 Fix sub-Z-buffer indexing error with render targets 2020-02-25 18:36:46 -08:00
Patrick Walton 0a3f64eb44 Implement the difference and exclusion blend modes 2020-02-25 14:55:58 -08:00
Patrick Walton a8e33d3d3d Add the soft light blend mode 2020-02-25 14:39:06 -08:00
Patrick Walton 9b4217300f Implement the source-in, destination-in, source-out, and destination-atop blend
modes to round out the assortment of Porter-Duff blend modes
2020-02-25 12:52:11 -08:00
Patrick Walton 02012431ca Implement color dodge and color burn blend modes 2020-02-25 11:37:42 -08:00
Patrick Walton 5b228ed825 Implement multiply, screen, hard light, and overlay blend modes. 2020-02-24 21:23:17 -08:00
Patrick Walton 149efeb672 Fix `is_fully_transparent()` for colors.
Oops!
2020-02-24 21:22:36 -08:00
Patrick Walton 99d980c0c7 Fix batch breaking logic for blend modes 2020-02-24 21:22:15 -08:00
Patrick Walton 5421525eaa Implement the HSL filters (called "non-separable blend modes" in the spec).
These cannot be implemented with the standard OpenGL blending functions, so we
have to do them manually in a shader, which requires a good deal of machinery
to create intermediate framebuffers and so forth.
2020-02-24 15:37:44 -08:00
Patrick Walton 67d12adb6c Replace layers with render targets, which can be used as patterns.
This allows us to efficiently handle a lot of workloads that require multiple
HTML canvases, without CPU readback. For example, you can render paths to a
render target, then turn that render target into a repeating pattern that you
fill other paths with. Or you can render paths to a render target and then
composite that render target as a whole with a blend mode.

This introduces a new `DrawRenderTarget` render command that blits a render
target without any paths involved. This is basically just a hack that works
around the fact that our tiled renderer doesn't yet support effects that widen
the ink region (i.e. blurs). It can be removed once we have that support.
2020-02-21 22:14:18 -08:00
Patrick Walton 3245796445 Add support for multiple paint texture pages.
This avoids arbitrary limits on the number of images, gradients, etc. you can
have.
2020-02-21 14:46:10 -08:00
Patrick Walton 36538d5748 Implement a few more blend modes and switch to premultiplied alpha for layer
compositing
2020-02-20 22:22:15 -08:00
Patrick Walton 4933efb513 Add Lighten and Darken composite ops 2020-02-20 20:38:43 -08:00
Patrick Walton ab55b9509b Fix handling of solid tiles with the Clear blend mode 2020-02-20 18:15:20 -08:00
Patrick Walton 6acd2d91f7 Implement `clear_rect()` in the canvas front-end by introducing the concept of
per-path blend modes.

These should be useful for some canvas composite operations as well.
2020-02-20 15:52:40 -08:00
Patrick Walton 0c3dad974f Expose individual blend factors in `pathfinder_gpu` 2020-02-20 15:28:37 -08:00
Patrick Walton 16a2de88df Rename "postprocessing" to "effects" and start initial work on composite ops 2020-02-20 14:22:07 -08:00
Patrick Walton d9e994e46d Transition the existing postprocessing system to a layers system.
This is preparatory work for composite ops and blurs.

Closes #261.
2020-02-20 11:21:45 -08:00
Patrick Walton cc9711e151 Transform some paints in the canvas API 2020-02-18 16:06:39 -08:00
Patrick Walton 3f79927eb1 Allow the paint texture to grow a bit 2020-02-18 15:06:09 -08:00
Patrick Walton 3ad1c25796 Implement the even-odd fill rule 2020-02-17 14:44:48 -08:00
Patrick Walton 677c607a8c Get clips working for canvas 2020-02-16 13:45:15 -08:00
Patrick Walton 0d3bbbd506 Clip entire tiles appropriately.
This doesn't composite masks together, so it's currently incomplete.
2020-02-15 18:01:23 -08:00
Patrick Walton 631e16ce9b Fix flipped Y axis in mask texture positioning 2020-02-15 14:08:22 -08:00
Patrick Walton f26eecae7a Build clip paths before draw paths 2020-02-15 14:04:01 -08:00
Patrick Walton 496b55ee4e Add front-end support for clip paths. They don't do anything yet. 2020-02-15 13:21:12 -08:00
Patrick Walton fefa3c3cd3 Rename `PathObject` to `DrawPath` to differentiate it from a clip path 2020-02-15 12:39:15 -08:00
Patrick Walton 0883f54e2d Add a separate mask blit step, in preparation for supporting clips.
We can elide this in the future if there are no clips, but it isn't a huge
performance regression right now, so let's just unconditionally do it.
2020-02-14 21:56:43 -08:00
Patrick Walton 6a73a63336 Factor out mask texture UV calculation, and rename a couple of render commands 2020-02-14 21:37:20 -08:00
Patrick Walton 31becb1570 Flatten objects' tiles ourselves instead of having Rayon do it.
A prerequisite for clips.
2020-02-14 21:20:19 -08:00
Patrick Walton 84ffc3151e Split shaders out into a separate module. 2020-02-14 11:56:38 -08:00
Patrick Walton 90445bac7e Implement basic support for non-repeating image patterns. 2020-02-11 17:20:21 -08:00
Patrick Walton aad467e716 Implement basic radial gradients.
This doesn't handle the case where the circles are not concentric yet.
2020-02-10 22:15:50 -08:00
Patrick Walton 5a21557a6d Implement basic linear gradients.
This is not a very efficient implementation yet, but it seems to work.
2020-02-10 16:01:05 -08:00
Patrick Walton 740597d886
Merge pull request #254 from arturoc/remove-log-restriction
Remove log restriction
2020-02-06 08:38:08 -08:00
Emmanuel Gil Peyrot 6ce416e77c Bump all outdated dependencies
I’m pleasantly surprised that none of these required any (visible) code
change, but tests pass so let’s go with that. :)
2020-02-06 09:39:50 +01:00
Patrick Walton 706b6dbd1d Add an API for gradients to the canvas frontend, not implemented yet 2020-02-05 20:01:11 -08:00
Patrick Walton a66ed4c073 Specify tile texture coordinates as an affine transform.
Part of the groundwork for gradients.
2020-02-05 13:59:32 -08:00
Patrick Walton b269723254 Switch to per-pixel texture lookup for paints.
This is a prerequisite for supporting gradients and images.
2020-02-04 21:50:13 -08:00
Patrick Walton 1e84ddf1ff Use the texture allocator to allocate solid colors 2020-02-03 22:24:34 -08:00
Patrick Walton b8f622203a Add a simple quadtree-based texture allocator 2020-01-31 14:38:01 +01:00
Patrick Walton 2db43797c3 Split colors out into their own crate.
A lot of downstream consumers of `pathfinder_gpu` want to use colors without
the path stuff.
2020-01-31 09:17:04 +01:00
Arturo Castro 3be6d70577 remove log restrictions from renderer, demo/common and gl crates 2020-01-28 15:24:21 +01:00
Patrick Walton ce3b40cd5c Make timer queries and framebuffer readback async 2020-01-07 13:03:15 -08:00
Patrick Walton 0bb6b88859 Stop using AVX2 when packing pixels.
Partially addresses #241.
2019-12-29 12:38:36 -08:00
Patrick Walton 986792349f Use the SSE2 `_mm_movemask_ps` on x86 instead of the SSE4.1 `_mm_test_all_ones`
and `_mm_test_all_zeros`.

Partially addresses #241.
2019-12-29 12:13:58 -08:00
Sebastian K 805066e65c use a binary search for pathfinder_renderer::SortedVector 2019-12-28 11:14:25 +03:00
Patrick Walton 0662f6433f Allow any texture format to be uploaded; fix Metal compilation on newer rustcs 2019-12-20 11:48:51 -08:00
Patrick Walton 7c655246ae Add some more features to blending, and expand texture upload features 2019-12-19 08:58:02 -08:00
Patrick Walton 521ab3b5ba Add a 3D vector type 2019-12-07 11:52:35 -08:00
est31 ad143712a8 Remove redundant fixedbitset dependency 2019-08-30 20:24:09 +02:00
Sebastian Köln 47e77f2513 don't run doc code 2019-07-16 13:53:03 +03:00
Patrick Walton 437eda96da Overload `*` between transforms and points 2019-07-12 11:55:01 -07:00
Patrick Walton 1eb28a5539 Fix incorrect definition of 2D transform multiplication 2019-07-12 11:26:09 -07:00
Patrick Walton 96758dfc17 Add `rotate` and `scale` methods to `Transform4F` 2019-07-11 15:57:45 -07:00
Patrick Walton 3f91206d57 Add a `translate` method to 3D transforms 2019-07-11 15:44:01 -07:00
Patrick Walton bcac119324 Rename `Transform2DF` to `Transform2F` and `Transform3DF` to `Transform4F` 2019-07-11 14:59:10 -07:00
Patrick Walton 55825cbc6a Switch scale and translation constructors for `Transform3DF` over to use vectors 2019-07-11 14:58:45 -07:00
Patrick Walton eb0a61679d Use operator overloading for 3D matrix multiplication 2019-07-11 13:59:39 -07:00
Patrick Walton b886c157c1 Use 2-lane instead of 4-lane SIMD types for 2D vectors.
Also, this commit rewrites the `add_fill()` method to stop using shuffle
instructions, which can be slow and make the code overly complicated. The
shuffle instructions have been removed from the various SIMD backends.
2019-06-26 16:38:37 -07:00
Patrick Walton 222fa89b23 Use a 3D transform in the tile vertex shaders.
This opens the door to caching tiles at different zoom levels (issue #191).
2019-06-25 11:32:39 -07:00
Patrick Walton 4cdded74b4 Fix SVG export in the demo; update `Cargo.lock` 2019-06-25 11:32:26 -07:00
Sebastian Köln 090c21a20a Move all scene exports into the export crate.
SVG, PDF and PS can now be created with Scene::export.
2019-06-25 11:26:37 +03:00
Sebastian Köln 1ca35d8426 add PS export as well. also rename svg2pdf into convert and add PS export to it 2019-06-24 22:41:34 +03:00
Sebastian Köln 0a5c4007f9 merge with master 2019-06-24 18:31:13 +03:00
Patrick Walton d86ff9011a Update the postprocessing shader and vertex array for the Metal changes.
Closes #201.
2019-06-21 18:04:18 -07:00
Patrick Walton 431dcf3d2e Rename `pathfinder_geometry::basic` to simply `pathfinder_geometry`, and move
the remaining code in that crate to a new crate, `pathfinder_content`

The old hierarchy was confusing.
2019-06-21 10:06:19 -07:00
Patrick Walton 487577a11b Add Metal support.
This commit substantially reworks the `pathfinder_gpu` API to better support
modern APIs like Metal. It should open the door to `gfx-rs`, `wgpu`, Vulkan,
and D3D12 backends relatively straightforwardly.

A new example, `canvas_metal_minimal`, has been added.

Note that the new Metal shaders require a patched version of `spirv-cross` to
build properly. An upstream patch is forthcoming.
2019-06-20 11:47:22 -07:00
Sebastian Köln 4039658155 add a simple PDF export 2019-06-15 17:50:25 +03:00
Patrick Walton dbf02fb742 Make `get_vertex_attr()` fallible 2019-06-12 10:50:24 -07:00
Patrick Walton 7973148603 Implement basic shadows (no blur yet) 2019-06-03 21:09:04 -07:00
Patrick Walton a1b0df0a42 Rename `Point2DF` to `Vector2F`, `Point3DF` to `Vector4F`, and `LineSegmentF`
to `LineSegment2F`.

Straw poll on Twitter suggested that these names were preferred.
2019-06-03 12:39:29 -07:00
Patrick Walton e1bcc11ace Change the `F32` and `I32` suffixes to `F` and `I` to match the C API.
They're shorter and less noisy.
2019-05-29 19:17:16 -07:00
Patrick Walton acf666b701 Stop using triangle fans for DX12/Vulkan compatibility.
Closes #165.
2019-05-29 16:04:33 -07:00
Bastien Orivel 349c1a9cd0 Update quickcheck to 0.8
This dedupes some dependencies
2019-05-24 19:22:23 +02:00
Patrick Walton 0deb12b3a2 Implement `fill-opacity` and `stroke-opacity` in SVG 2019-05-14 18:09:01 -07:00
Patrick Walton 25a6c33a1a Remove the object index attribute from the shaders, since it's now unused 2019-05-14 15:22:50 -07:00
Patrick Walton 86f5bdb44a Store paints in the paint texture indexed by paint ID, not object index 2019-05-14 15:21:15 -07:00
Patrick Walton 7a02b78b3d Explicitly specify color texture coordinates for alpha and solid tiles.
This is groundwork for gradients and images.

This commit also refactors the interface for vertex attributes to use named
parameters (via structs), for clarity.
2019-05-14 15:11:04 -07:00
Patrick Walton a54378f931 Make the paint texture dynamically-sized on the GPU side 2019-05-14 11:38:48 -07:00
Patrick Walton 376a1c7165 Rename "fill colors" to "paint" in preparation for gradients and images 2019-05-14 11:33:52 -07:00
Patrick Walton 89ca998fa8 Add a convenience method for creating a scene proxy with an empty scene.
This makes animation rendering loops a bit easier for users.
2019-05-13 18:29:57 -07:00
Patrick Walton d5a12e0e9f Revert "batch alpha and solid tiles"
This reverts commit 753a254726.
2019-05-13 18:20:21 -07:00
Patrick Walton f24d93819b Add arc building methods and switch the Moiré demo to use them.
Also, stop taking points by reference in many methods, for consistency.
2019-05-13 12:42:13 -07:00
Patrick Walton 55be787ffd
Merge pull request #150 from nical/glitch-fix
Fix vertex attribute configuration of alpha tiles
2019-05-13 10:58:06 -07:00
Nicolas Silva 820a0286aa Fix vertex attribute configuration of alpha tiles.
Fixes #134.

glVertexAttribPointer takes a size as parameter which refers to the number of components and not the size in bytes of the value.
The tile index was registered as a 2-components value which caused the second component to overlap with the first member of the next primitive, which was mostly fine except for the last element which would overlfow the buffer. Intel and nvidia GPUs/drivers on linux at least refuse to read the first component of this two-component value if the other component is outside of the valid range which caused the shader to get zero instead and always select the first mask tile.
2019-05-13 18:00:54 +02:00
Patrick Walton b4bdbec4aa
Merge pull request #148 from bzm3r/master
Constrain sizes of solid tile and alpha tile batches being sent to the GPU
2019-05-13 07:59:44 -07:00
Patrick Walton 639a8f39e8 Add Moiré demo 2019-05-11 11:53:50 -07:00
bhmerchant@gmail.com 753a254726 batch alpha and solid tiles 2019-05-10 22:57:34 -07:00
Patrick Walton a5d373cb91 Rename "object" to "path" in preparation for image objects 2019-05-10 12:03:38 -07:00
Patrick Walton 54672f2089 Add "save as SVG" support to the demo.
This is intended to help diagnose rendering problems, by allowing export to a
format that can be minimized and in which issues can be reproduced.
2019-05-07 14:37:46 -07:00
Patrick Walton b198c06968 Properly account for concurrency in the performance measurement 2019-05-07 13:43:37 -07:00
Patrick Walton 15f63df844 Rename `DebugUI` to `DebugUIPresenter` and `UI` to `UIPresenter` 2019-05-06 15:36:39 -07:00
Patrick Walton 3857a28e6a Move logic out of the `gpu_data` module 2019-05-03 18:51:36 -07:00
Patrick Walton 9de7d95d33 Start a simple HTML canvas-like API, and add a minimal example to show how to
use it.
2019-05-03 14:15:38 -07:00
Patrick Walton 5c5e4e9313 Factor the scene thread out of the demo and into the renderer proper.
This simplifies Pathfinder's API considerably. Now users get off-main-thread
scene building "for free".
2019-05-01 17:12:25 -07:00
Patrick Walton a96ee73da6 Introduce an Executor abstraction to enable alternatives to Rayon 2019-04-30 15:17:07 -07:00
Patrick Walton db8eb1c97c Run `rustfmt` on the renderer crate 2019-04-29 16:45:29 -07:00
Patrick Walton 8606cd013e Replace commented out printlns with proper debug statements 2019-04-29 16:43:24 -07:00
Patrick Walton 6c31e1bc01 In VR mode, render one eye and then reproject to both eyes instead of rendering
twice.

This reduces both CPU and GPU time a lot in exchange for a small loss in
quality.
2019-04-26 17:22:54 -07:00
Patrick Walton 58d55c5eaa Allow rendering to non-default framebuffers 2019-04-18 19:05:01 -07:00
Patrick Walton 62a3fefca4 Reenable the tile and fill counts in the debug display 2019-04-18 15:09:37 -07:00
Patrick Walton c688d04412 Remove the scene assembly thread, and pipeline only fills instead of alpha
tiles.

Removing a thread should make it easier to manually assign threads to CPUs, as
is necessary on devices with poor schedulers like Magic Leap 1.
2019-04-18 13:50:26 -07:00
Patrick Walton 06439f858f Store the tile rect in only one place in the scene assembly thread 2019-04-12 11:55:05 -07:00
Patrick Walton 21563d9d7f Move the Z-buffer over to the `DenseTileMap` abstraction 2019-04-11 19:38:31 -07:00
Patrick Walton eef6045ed7 Add missing `tile_map.rs` file 2019-04-11 19:36:55 -07:00
Patrick Walton 6a967c19f4 Introduce a `DenseTileMap<T>` type for better abstraction and SIMD use 2019-04-11 19:25:02 -07:00
Patrick Walton 9e38da25e1 Remove the `TileObjectPrimitive` structure in favor of a flat list of
backdrops.

This reduces memory usage a bit and adds the infrastructure needed to support a
tile map.
2019-04-11 18:54:03 -07:00
Patrick Walton 4e6bbf59ba Stop using `crossbeam-channel`, as it's slower than `std::sync::mpsc` on macOS
at least
2019-04-10 20:29:13 -07:00
Patrick Walton 3d4f8bd008 Pipeline between CPU and GPU at a more fine-grained level.
This makes us stop running one frame behind.
2019-04-09 17:06:43 -07:00
Patrick Walton d090dd459b Remove the layer of indirection between object indices and shaders 2019-04-03 11:58:45 -07:00
Patrick Walton db3851d754 Get subpixel AA and gamma correction working in 2D 2019-03-25 16:20:34 -07:00
Patrick Walton 224c8e85b9 Create separate shaders for monochrome and multicolor tiles.
This is preparation for fixing subpixel AA.
2019-03-22 14:28:31 -07:00
Patrick Walton 6ca5dc5f62 Add basic barrel distortion support for VR 2019-03-20 13:41:04 -07:00
Patrick Walton 0458d9a7f2 Factor out bits of the postprocessing shader into includes 2019-03-18 21:40:10 -07:00
Patrick Walton bb32777101 Initial work toward VR support 2019-03-14 14:42:22 -07:00
Patrick Walton 9c404dfdc1 Add an Android port 2019-03-12 13:55:26 -07:00
Patrick Walton b80ab2ad25 Only show the "Text Effects" button when a monochrome SVG is loaded 2019-03-06 19:35:57 -08:00
Patrick Walton 6062676d0e Add tooltips to the buttons in the demo 2019-03-06 11:33:59 -08:00
Patrick Walton 4dff13ef00 Use an advancing cursor when laying out UI elements 2019-03-06 10:47:52 -08:00
Patrick Walton 8dc3a84d09 Remove `tile-svg` and the serialization code.
They can be added later if needed, but for now they're just bitrotting.
2019-03-05 15:38:10 -08:00
Patrick Walton 33aa6f905d Move UI event code and widgets to the `pathfinder_ui` crate 2019-03-05 15:36:07 -08:00
Patrick Walton ad0691c146 Move the generic UI code in the renderer crate to a separate crate 2019-03-05 15:13:55 -08:00
Patrick Walton f7a8b573ce Move the GPU rendering code out of `pathfinder_gl`, since it's now no longer
OpenGL-specific
2019-03-05 14:46:18 -08:00
Patrick Walton 5c7423d59c Add more statistics to the performance debug window 2019-02-25 16:12:47 -08:00
Patrick Walton 1e3298fdb7 Switch to guard-band style clipping to eliminate artefacts 2019-02-22 13:15:00 -08:00
Patrick Walton fc62e9bc71 Subdivide offset curves to an error bound. 2019-02-20 18:27:27 -08:00
Patrick Walton c7a1d9e960 Use stencil to integrate the vector scene into the 3D environment 2019-02-19 12:03:02 -08:00
Patrick Walton 9af3bac11f Implement depth interpolation, not working yet 2019-02-18 13:42:30 -08:00
Patrick Walton e4803cfddf Add some ground to the 3D scene, no depth buffer yet 2019-02-14 18:53:02 -08:00
Patrick Walton 31f1fae951 Add a TODO about monotonic conversion 2019-02-12 08:57:49 -08:00
Patrick Walton f04c000cae Add a quick check to skip clipping when an outline is entirely inside or
outside the clip area
2019-02-09 19:24:30 -08:00
Patrick Walton 2a118c3af0 Get all postprocessing filters working 2019-02-08 14:37:30 -08:00
Patrick Walton ba5a0f987c Add basic postprocessing support 2019-02-08 13:55:31 -08:00
Patrick Walton a81850a899 Add window resizing support to the demo 2019-02-06 18:09:37 -08:00
Patrick Walton 8771dd6789 wip: dilation not working yet 2019-02-05 20:10:20 -08:00
Patrick Walton 3d0463999c Add a SIMD integer rect type 2019-02-05 10:55:01 -08:00
Patrick Walton fe410e066f Add a SIMD rect type 2019-02-05 10:03:20 -08:00
Patrick Walton 63b47f1abe Move basic geometry primitives to the `pathfinder_geometry::basic` module 2019-02-04 20:20:32 -08:00
Patrick Walton f25682f0f1 Add a defringing shader for subpixel antialiasing, untested as of yet 2019-02-04 16:04:13 -08:00
Patrick Walton a5234e6695 Stop clipping 3D quads over and over 2019-02-02 13:53:04 -08:00
Patrick Walton b0e91369e5 Do scene building just-in-time on a per-outline basis as part of tiling 2019-02-02 11:36:42 -08:00
Patrick Walton df59fd9792 Rename `Point4DF32` to `Point3DF32` 2019-02-01 17:07:03 -08:00
Patrick Walton 6a286ab153 Remove `Point3DF32` 2019-02-01 17:05:35 -08:00
Patrick Walton 0b0c913332 Split out SIMD into a separate crate 2019-02-01 11:48:10 -08:00
Patrick Walton 89244ba6cf Do clipping in 3D homogeneous space 2019-01-31 15:29:13 -08:00
Patrick Walton 4801503dd8 Fix curve/edge intersection logic in clipping 2019-01-31 10:12:37 -08:00
Patrick Walton e105bdb7c9 Display timing info in the demo 2019-01-30 14:42:06 -08:00
Patrick Walton 6b8848bb35 Fix boundary condition for active edges precisely on tile boundaries 2019-01-29 19:29:42 -08:00
Patrick Walton e3bf703105 Stop using 100% CPU; fix bug when splitting line segments at Y extrema 2019-01-29 15:35:07 -08:00
Patrick Walton e958363872 Allow scenes to be dumped as SVG (untested) and make 3D mode optional in the demo 2019-01-29 14:50:15 -08:00
Patrick Walton ab93ea1f22 Fix bogus thin culling that was causing artefacts 2019-01-29 11:27:25 -08:00
Patrick Walton d1ca5fe757 Use a much better technique for curve flattening 2019-01-28 20:36:06 -08:00
Patrick Walton a9c1760de5 Clipping mostly works now 2019-01-28 14:58:57 -08:00
Patrick Walton 7e3365c481 wip 2019-01-28 12:57:15 -08:00
Patrick Walton 80db7155b8 wip 2019-01-25 17:07:37 -08:00
Patrick Walton 938bd30a78 wip 2019-01-25 14:28:53 -08:00
Patrick Walton 3ce60afb44 Fix clipping 2019-01-22 11:46:01 -08:00
Patrick Walton 93ae7d3548 Basic perspective support 2019-01-16 16:53:10 -08:00
Patrick Walton 02928f295d Basic rect clipping 2019-01-15 13:49:26 -08:00
Patrick Walton 0097ffab19 wip 2019-01-15 11:42:25 -08:00
Patrick Walton 5bbb5a1b74 Get the native code demo rendering the tiger 2019-01-15 10:52:37 -08:00
Patrick Walton a4c2796883 Implement a third demo with native code, not working yet 2019-01-14 19:32:53 -08:00
Patrick Walton 821b54b8f4 Factor renderer and SVG code out into separate crates 2019-01-14 14:20:36 -08:00