Skip to content

vellum 0.6.0

Choose a tag to compare

@schochastics schochastics released this 31 Jul 11:31
· 22 commits to main since this release

Six phases of engine work since 0.5.1. The theme running through them: vellum resolves layout, text metrics and geometry before it draws, and this release spends that in six directions at once.

38 new exports. vellumplot (2741 tests) and vellumwidget (181) both pass unchanged against it.

Typography

  • text_grob(width=, height=, align=, fit=) — wrap a label to an absolute measure, align left/centre/right/justify, and auto-fit the font until the block fits. Break decisions use the shaped width of each candidate line, so kerning and OpenType features are accounted for and a line can never render wider than it measured.
  • text_path_grob() — text set along a curve, with halos, features and all three backends intact.
  • plotmath: declined, with reasoning recorded. No math-run node type; a $...$ span in md() if ever needed.

Placement

  • vl_place() / vl_repel() — label collision solving over resolved geometry. Solves in device pixels and applies the answer as an absolute offset, so faceted, polar and warped panels are all solved together, with no second compile.
  • vl_empty_region() — the largest empty rectangle, for putting a legend where the marks are not.
  • vl_hull() / vl_buffer() — convex and concave hulls, and outward offsetting.

Geometry

  • vl_path_op() — boolean union / intersect / difference / xor. The result is geometry, so it can be gradient-filled, stroked along its new boundary, and used as the operand of another boolean.
  • vl_contour() / contour_grob() — marching squares over any matrix, chained into polylines.
  • svg_grob() / vl_svg_path() — the full SVG path d grammar, so icon sets become crisp vector markers.

Accessible and reproducible output

  • Tagged PDF from the existing per-mark id/role/name channel — no new annotation API. role = "presentation" marks furniture as a PDF artifact so screen readers skip it.
  • scene_fonts() / font_pin() / font_check() — make the one part of the determinism claim vellum does not control visible and checkable.

Output reach

  • Animated SVG (vl_render_animation(format = "svg")) — resolution-independent, honours prefers-reduced-motion. Choose it by mark count: it beats GIF on line art and loses on dense scatter, and warns above 5 MB.
  • pdf_pages() — several scenes as one document, pages of differing size, tagging preserved.
  • render_all() — render independent scenes across cores, byte-identical to sequential.

Addressable marks

  • Every mark family can now carry a key. Previously only 6 of 18 constructors could, so a line, an area, a choropleth region or a data label could never be hovered, tooltipped, brushed or cross-filtered. Now a whole series can be one addressable thing.
  • vl_nearest() / element_geometry() — hit-testing against the real shape rather than the bounding box, so a diagonal is not matched from the far corner of its bbox.

Fixes that change output

Four bugs whose fixes deliberately alter rendering:

  • Multi-line text hung below its anchor by (n-1)·lineheight/2.
  • Multi-line text collapsed onto one line in SVG.
  • A halo ate neighbouring glyphs on text set along a path.
  • vl_repel() was defeated by a panel background (29 of 32 labels unresolvable) and could push labels off the page.

Plus a portability fix: render_all() now respects _R_CHECK_LIMIT_CORES_, without which any package depending on vellum would have failed its own R CMD check.

See NEWS.md for the full list.