You do not have to rewrite existing graphics to draw them with
vellum’s backend. as_vellum() converts a grid grob tree, or
a ggplot2 plot, into a vl_scene(), and
render_grid() does that and writes the result to a file.
This is the interop path: grid-based graphics rendered by vellum’s
deterministic PNG / SVG / PDF backend.
How it works
grid graphics are lazy: a grob’s real geometry is only known once a
device and viewport resolve its units. as_vellum() leans on
that machinery rather than reimplementing it. It spins up an offscreen
grid device, lets grid resolve every coordinate to an absolute position,
and then emits the corresponding vellum grobs. The output is a normal
vellum_scene, so everything else in vellum (multi-backend
render(), scene_raster(),
display()) applies.
A grid grob tree
Any grob or gTree works. Here is a small hand-built one.
library(grid)
g <- gTree(children = gList(
rectGrob(gp = grid::gpar(fill = "grey97", col = "grey70")),
circleGrob(r = 0.3, gp = grid::gpar(fill = "#3a7bd5", col = NA)),
textGrob("grid -> vellum", y = 0.12, gp = grid::gpar(fontface = "bold"))
))
as_vellum(g, width = 5, height = 3)
as_vellum() returns a scene, which auto-prints
(displays) here. Assign it and you can render it to any backend:
render_grid(g, "grid.png", width = 5, height = 3)
render_grid(g, "grid.pdf", width = 5, height = 3)A ggplot2 plot
Passing a ggplot object works the same way: ggplot builds a gtable of
grobs, and as_vellum() renders that.
library(ggplot2)
p <- ggplot(mtcars, aes(wt, mpg, colour = factor(cyl))) +
geom_point(size = 2) +
labs(title = "mtcars", colour = "cyl") +
theme_minimal()
as_vellum(p, width = 6, height = 4)
To write it out, use render_grid() with the format in
the file extension:
render_grid(p, "mtcars.png", width = 6, height = 4)
render_grid(p, "mtcars.svg", width = 6, height = 4)lattice output works through the same door: draw the lattice object
to capture its grob tree, or pass a captured grob to
as_vellum().
When to use interop versus the native API
Reach for as_vellum() / render_grid() when
you already have grid, ggplot2, or lattice output and want vellum’s
deterministic, multi-backend rendering (for example byte-stable PNGs for
snapshot tests, or one plot emitted to PNG, SVG, and PDF from the same
source).
Build with the native vl_scene() API instead when you
want what the retained scene graph offers: named and editable nodes,
hit-testing, and a per-element scene_model() (see
vignette("retained-mode")). Interop reproduces the
pixels of a grid scene, but a grammar built directly on vellum
is what carries the per-element identity that interactivity needs.
A native vellum graphics device (so plot() and friends
target vellum directly) is future work; until then,
as_vellum() is the bridge. ```
