knitr::opts_chunk$set(
  collapse = FALSE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)


library(svgparser)
library(ggplot2)
library(gggrid)
library(dplyr)
library(knitr)
library(kableExtra)

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Ensure that images are rendered using a device which understands patterns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
knitr::opts_chunk$set(dev.args = list(png = list(type = "cairo")))
pkgdown::build_site(override = list(destination = "../coolbutuseless.github.io/package/svgparser"))
svg_features <- readr::read_csv(
"Feature, Support, Notes
<path> elements    ,  yes, Working well! 
<rect> <circle> etc,  yes, Working 
<ellipse>          ,  yes, No rotation yet
<text>             ,  meh, Works at a basic level. Don't expect anything using fancy text effects to work
style cascading    ,  yes, Using `{cssparser}`
<linearGradient> <radialGradient>,  yes, converted to R4.1 gradient objects. 'userSpaceOnUse' coordinate space only. Send examples!
transform presentation attribute, yes, .
<defs> <use>  , yes, .
<pattern>     , no, Impossible?
<filter>      , no, Impossible?
animation     , no, Impossible?
linetypes     , no, Planned feature - but R is much more limited compared to SVGs linetype features.
masks         , no, need example SVG
clipping paths, yes, works on the few examples tested
<a>           , yes, treated as a <g> grouping element. {grid} doesn't support clickable links though.
<switch>      , meh, supported; but instead of selecting the best child element it selects the first non-null child. Needs fixing.
<image>       , yes, image support via {magick}. Does not currently handle transforms for images. Aspect ratio is fixed to match that of image.
", show_col_types = FALSE, lazy = FALSE)

svgparser

Load SVG files as R vector objects (grobs) or data.frames

R-CMD-check

svgparser loads vector-based SVG images as R vector objects.

The vector objects which are created in R are the standard graphics object ('grob') in the base R {grid} graphics system.

SVG images can also be imported as data.frames. Each shape, line and point is represented in the data.frame with copious helpings of metadata to relate individual coordinates to the original SVG structure.

Example: Load SVG as vector image

This example loads an SVG image into a base R grid graphics object, and then draws the object using grid.draw.

Note that this is not a fixed size raster image! This is a vector image which can be resized without loss of precision.

tiger_filename <- system.file("tiger.svg", package = "svgparser")
tiger_grob <- svgparser::read_svg(tiger_filename)
grid::grid.draw(tiger_grob)

Example: Load SVG as a data.frame

This example loads an SVG as a data.frame and then plots the coordinates using ggplot. The element type from the original SVG is used as the aesthetic for colouring the lines in the plot.

tiger_df <- svgparser::read_svg(tiger_filename, obj_type = 'data.frame')

nrow(tiger_df)
knitr::kable(head(tiger_df, 3))

There's enough information in the data.frame to manually recreate most of the SVG using whatever drawing mechanism you'd like. Here, I've used ggplot2 to draw the outlines from the data.

ggplot(tiger_df) + 
  geom_path(aes(x, y, colour = name, group = interaction(elem_idx, path_idx))) +
  scale_y_reverse()
# Taking artistic license to keep the example small, and doing more
# presentation work here.
tiger_df <- svgparser::read_svg(tiger_filename, obj_type = 'data.frame')
ggplot(tiger_df) + 
  geom_path(aes(x, y, colour = name, group = interaction(elem_idx, path_idx)), 
            alpha = 1, size = 0.25) + 
  coord_equal() + 
  theme_bw() + 
  theme(
    legend.position = c(0.02, 0.02),
    legend.justification = c(0, 0),
    legend.background = element_blank()
  ) + 
  scale_y_reverse() + 
  labs(title = "Manually drawing an SVG from its data.frame representation")

What's in the box

Installation

This package is available on GitHub.

# install.package('remotes')
remotes::install_github('coolbutuseless/cssparser') # Handles CSS styling
remotes::install_github('coolbutuseless/svgparser')

With R > v4.1.0:

With R < v4.1.0:

Vignettes

| Description | | |-------------|----| | SVG in ggplot using gggrid | | | Creating tileable patterns for R graphics | | | Add SVG to ggplot2 plots | | | Debugging Issues by Using False Colouring | | | Customising SVG with CSS | |

SVG Feature Support

svg_features %>%
  mutate(
    Support = cell_spec(Support, background = case_when(
      Support == 'yes'  ~ 'lightgreen',
      Support == 'meh' ~ 'lemonchiffon',
      Support == 'no'  ~ 'lightcoral'
    )),
    Feature = htmltools::htmlEscape(Feature),
    Notes   = htmltools::htmlEscape(Notes)
  ) %>%
  kable(caption  = "SVG Feature Support", escape = FALSE)

SVG icon pack SuperTinyIcons is included with the package

SuperTinyIcons is a set of icons focussed on small representations of logos of some internet companies and other images.

These icons can be accessed from this package using:

See LICENSE-supertinycons.txt for MIT license information for this icon set.

supertinyicon_names[1:10]
load_supertinyicon('twitter', obj_type = 'svg')
supertinyicon_names[1:10]
# Artistic license to skip over the details of how to get pretty svg output
cat(as.character(xml2::read_xml(load_supertinyicon('twitter', obj_type = 'svg'))))
grid.draw(load_supertinyicon('twitter'))

Technical bits

svgparser is vanilla R code which walks the XML tree and converts elements (and nested sub-elements) into a nested set of grid::grobTree() objects.

Circles, lines and points are translated to their corresponding grid object i.e. grid::circleGrob(), grid::linesGrob(), grid::pointsGrob().

Radial and linear gradients are captured as the new objects available in R4.1: grid::radialGradient() and grid::linearGradient()

For <use> tags, {svgparser} extracts xpath information to retrieve relevant referenced section of the SVG, parse it into R objects and then insert it at the given location.

There are only a few dependencies:

Related Software

Comparison to related R packages

| | svgparser | rsvg | grImport2 | |------------------------|----------- |----------------------------------------|-------------------------------------| | Loads as Vector Object | Yes (grob) | No (bitmap) | Yes (grob) | | Loads as Standard Grob | Yes (grobTree) | No (bitmap) | No (custom PictureGrob) | | Exposes coordinates | Yes (as a data.frame) along with SVG meta-information | No | Yes (via grid::grobPoints), but lacks meta-information | | Note | | Backed by fast + well tested C library | Will only load SVG created by Cairo |

Acknowledgements



coolbutuseless/svgparser documentation built on Dec. 26, 2021, 12:03 a.m.