{"id":16571795,"url":"https://github.com/coolbutuseless/svgparser","last_synced_at":"2025-03-21T12:31:05.979Z","repository":{"id":95359892,"uuid":"433776925","full_name":"coolbutuseless/svgparser","owner":"coolbutuseless","description":"Render SVG images in R. Load SVG data as data.frames","archived":false,"fork":false,"pushed_at":"2021-12-25T00:05:00.000Z","size":4315,"stargazers_count":48,"open_issues_count":6,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-01T06:11:11.639Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://coolbutuseless.github.io/package/svgparser","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coolbutuseless.png","metadata":{"files":{"readme":"README.Rmd","changelog":"NEWS.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-01T10:13:51.000Z","updated_at":"2024-09-19T21:43:46.000Z","dependencies_parsed_at":"2023-07-04T20:16:26.695Z","dependency_job_id":null,"html_url":"https://github.com/coolbutuseless/svgparser","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolbutuseless%2Fsvgparser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolbutuseless%2Fsvgparser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolbutuseless%2Fsvgparser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coolbutuseless%2Fsvgparser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coolbutuseless","download_url":"https://codeload.github.com/coolbutuseless/svgparser/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244135909,"owners_count":20403798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T21:25:18.657Z","updated_at":"2025-03-21T12:31:05.969Z","avatar_url":"https://github.com/coolbutuseless.png","language":"R","readme":"---\noutput: github_document\n---\n\n\u003c!-- README.md is generated from README.Rmd. Please edit that file --\u003e\n\n```{r, include = FALSE}\nknitr::opts_chunk$set(\n  collapse = FALSE,\n  comment = \"#\u003e\",\n  fig.path = \"man/figures/README-\",\n  out.width = \"100%\"\n)\n\n\nlibrary(svgparser)\nlibrary(ggplot2)\nlibrary(gggrid)\nlibrary(dplyr)\nlibrary(knitr)\nlibrary(kableExtra)\n\n#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n# Ensure that images are rendered using a device which understands patterns\n#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\nknitr::opts_chunk$set(dev.args = list(png = list(type = \"cairo\")))\n```\n\n\n```{r pkgdown, eval=FALSE, include=FALSE}\npkgdown::build_site(override = list(destination = \"../coolbutuseless.github.io/package/svgparser\"))\n```\n\n\n\n\n```{r feature_tables, echo = FALSE, message = FALSE}\nsvg_features \u003c- readr::read_csv(\n\"Feature, Support, Notes\n\u003cpath\u003e elements    ,  yes, Working well! \n\u003crect\u003e \u003ccircle\u003e etc,  yes, Working \n\u003cellipse\u003e          ,  yes, No rotation yet\n\u003ctext\u003e             ,  meh, Works at a basic level. Don't expect anything using fancy text effects to work\nstyle cascading    ,  yes, Using `{cssparser}`\n\u003clinearGradient\u003e \u003cradialGradient\u003e,  yes, converted to R4.1 gradient objects. 'userSpaceOnUse' coordinate space only. Send examples!\ntransform presentation attribute, yes, .\n\u003cdefs\u003e \u003cuse\u003e  , yes, .\n\u003cpattern\u003e     , no, Impossible?\n\u003cfilter\u003e      , no, Impossible?\nanimation     , no, Impossible?\nlinetypes     , no, Planned feature - but R is much more limited compared to SVGs linetype features.\nmasks         , no, need example SVG\nclipping paths, yes, works on the few examples tested\n\u003ca\u003e           , yes, treated as a \u003cg\u003e grouping element. {grid} doesn't support clickable links though.\n\u003cswitch\u003e      , meh, supported; but instead of selecting the best child element it selects the first non-null child. Needs fixing.\n\u003cimage\u003e       , yes, image support via {magick}. Does not currently handle transforms for images. Aspect ratio is fixed to match that of image.\n\", show_col_types = FALSE, lazy = FALSE)\n```\n\n\n\n\n\n# svgparser \n\n#### Load SVG files as R vector objects (grobs) or data.frames\n\n\u003c!-- badges: start --\u003e\n![](https://img.shields.io/badge/cool-useless-green.svg)\n[![R-CMD-check](https://github.com/coolbutuseless/svgparser/workflows/R-CMD-check/badge.svg)](https://github.com/coolbutuseless/svgparser/actions)\n\u003c!-- badges: end --\u003e\n\n`svgparser` loads vector-based **SVG** images as R vector objects.\n\nThe vector objects which are created in R are the standard graphics object ('grob')\nin the base R `{grid}` graphics system.\n\nSVG images can also be imported as data.frames.  Each shape, line and point is\nrepresented in the data.frame with copious helpings of metadata to relate \nindividual coordinates to the original SVG structure.\n\n\n## Example: Load SVG as vector image\n\nThis example loads an SVG image into a base R `grid` graphics object, and \nthen draws the object using `grid.draw`.\n\nNote that this is not a fixed size raster image!  This is a vector image \nwhich can be resized without loss of precision.\n\n```{r opener1, fig.height = 6, out.width=\"50%\"}\ntiger_filename \u003c- system.file(\"tiger.svg\", package = \"svgparser\")\ntiger_grob \u003c- svgparser::read_svg(tiger_filename)\ngrid::grid.draw(tiger_grob)\n```\n\n## Example: Load SVG as a data.frame\n\nThis example loads an SVG as a data.frame and then plots the coordinates\nusing ggplot. The element type from the original SVG is used as the \naesthetic for colouring the lines in the plot.\n\n```{r opener2, fig.height = 6, out.width=\"60%\", eval = TRUE, echo = TRUE}\ntiger_df \u003c- svgparser::read_svg(tiger_filename, obj_type = 'data.frame')\n\nnrow(tiger_df)\nknitr::kable(head(tiger_df, 3))\n```\n\nThere's enough information in the data.frame to manually recreate most of the\nSVG using whatever drawing mechanism you'd like.   Here, I've used `ggplot2` to\ndraw the outlines from the data.\n\n```{r opener2b, fig.height = 6, out.width=\"60%\", eval = FALSE, echo = TRUE}\nggplot(tiger_df) + \n  geom_path(aes(x, y, colour = name, group = interaction(elem_idx, path_idx))) +\n  scale_y_reverse()\n```\n\n```{r opener3, fig.height = 6, out.width=\"60%\", eval = TRUE, echo = FALSE}\n# Taking artistic license to keep the example small, and doing more\n# presentation work here.\ntiger_df \u003c- svgparser::read_svg(tiger_filename, obj_type = 'data.frame')\nggplot(tiger_df) + \n  geom_path(aes(x, y, colour = name, group = interaction(elem_idx, path_idx)), \n            alpha = 1, size = 0.25) + \n  coord_equal() + \n  theme_bw() + \n  theme(\n    legend.position = c(0.02, 0.02),\n    legend.justification = c(0, 0),\n    legend.background = element_blank()\n  ) + \n  scale_y_reverse() + \n  labs(title = \"Manually drawing an SVG from its data.frame representation\")\n```\n\n\n  \n## What's in the box\n\n* `read_svg()` read SVG into R as a `{grid}` graphics object (grob) or data.frame\n* `load_supertinyicon()` to load an SVG icon from the \n  [Super Tiny Icons](https://github.com/edent/SuperTinyIcons) icon pack\n  included with this package. See `LICENSE-supertinycons.txt` (MIT License)\n\n        \n## Installation\n\nThis package is available on [GitHub](https://github.com/coolbutuseless/svgparser).\n\n``` r\n# install.package('remotes')\nremotes::install_github('coolbutuseless/cssparser') # Handles CSS styling\nremotes::install_github('coolbutuseless/svgparser')\n```\n\nWith **R \u003e v4.1.0**:\n\n* gradients and clipping paths are rendered as correctly as possible.\n\nWith  **R \u003c v4.1.0**:\n\n* solid colours will be used in place of gradients, and \n* any elements which use a clipping path in the SVG will not be properly clipped in R.\n\n\n## Vignettes\n\n| Description |    |\n|-------------|----|\n| [SVG in ggplot using gggrid](https://coolbutuseless.github.io/package/svgparser/articles/gggrid.html) | [\u003cimg width=\"40%\" src=\"man/figures/vignettes/gggrid.png\"\u003e](https://coolbutuseless.github.io/package/svgparser/articles/gggrid.html) |\n| [Creating tileable patterns for R graphics](https://coolbutuseless.github.io/package/svgparser/articles/tileable.html) |  [\u003cimg width=\"40%\" src=\"man/figures/vignettes/seamless3-1.png\"\u003e](https://coolbutuseless.github.io/package/svgparser/articles/tileable.html) |\n| [Add SVG to ggplot2 plots](https://coolbutuseless.github.io/package/svgparser/articles/ggplot2.html) |  [\u003cimg width=\"40%\" src=\"man/figures/vignettes/ggplot.png\"\u003e](https://coolbutuseless.github.io/package/svgparser/articles/ggplot2.html) |\n| [Debugging Issues by Using False Colouring](https://coolbutuseless.github.io/package/svgparser/articles/false-colours.html) |  [\u003cimg width=\"40%\" src=\"man/figures/vignettes/tiger-mont.png\"\u003e](https://coolbutuseless.github.io/package/svgparser/articles/false-colours.html) |\n| [Customising SVG with CSS](https://coolbutuseless.github.io/package/svgparser/articles/css.html) |  [\u003cimg width=\"40%\" src=\"man/figures/vignettes/css-mont.png\"\u003e](https://coolbutuseless.github.io/package/svgparser/articles/css.html) |\n\n\n## SVG Feature Support\n\n```{r features_svg, echo = FALSE}\nsvg_features %\u003e%\n  mutate(\n    Support = cell_spec(Support, background = case_when(\n      Support == 'yes'  ~ 'lightgreen',\n      Support == 'meh' ~ 'lemonchiffon',\n      Support == 'no'  ~ 'lightcoral'\n    )),\n    Feature = htmltools::htmlEscape(Feature),\n    Notes   = htmltools::htmlEscape(Notes)\n  ) %\u003e%\n  kable(caption  = \"SVG Feature Support\", escape = FALSE)\n```\n\n\n\n## SVG icon pack `SuperTinyIcons` is included with the package\n\n[SuperTinyIcons](https://github.com/edent/SuperTinyIcons) \nis a set of icons focussed on small representations of logos of some internet companies \nand other images.\n\nThese icons can be accessed from this package using:\n\n* `supertinyicons` (for the names of all the icons), and \n* `load_supertinyicon()` to load an icon as an R object. \n\nSee `LICENSE-supertinycons.txt` for MIT license information for this icon set.\n\n```{r icon1, echo = TRUE, eval = FALSE}\nsupertinyicon_names[1:10]\nload_supertinyicon('twitter', obj_type = 'svg')\n```\n\n\n```{r icon2, echo = FALSE, evel = TRUE, comment = \"\"}\nsupertinyicon_names[1:10]\n# Artistic license to skip over the details of how to get pretty svg output\ncat(as.character(xml2::read_xml(load_supertinyicon('twitter', obj_type = 'svg'))))\n```\n\n\n```{r icon3, out.width = \"30%\", fig.height = 4, comment = \" \"}\ngrid.draw(load_supertinyicon('twitter'))\n```\n \n \n## Technical bits\n\n`svgparser` is vanilla R code which walks the XML tree and converts elements (and nested sub-elements) into\na nested set of `grid::grobTree()` objects.\n\nCircles, lines and points are translated to their corresponding `grid` object i.e.\n`grid::circleGrob()`, `grid::linesGrob()`, `grid::pointsGrob()`.\n\nRadial and linear gradients are captured as the new objects available in R4.1: `grid::radialGradient()` and \n`grid::linearGradient()`\n\nFor `\u003cuse\u003e` tags, `{svgparser}` extracts *xpath* information to retrieve relevant referenced section of the\nSVG, parse it into R objects and then insert it at the given location.\n\nThere are only a few dependencies:\n\n* [`{xml2}`](https://cran.r-project.org/package=xml2) is used as to parse the SVG into R\n* [`{cssparser}`](https://github.com/coolbutuseless/cssparser) is used to cascade stylesheets within the XML representation.  This\n  was initially built-in to svgparser, but was moved to a separate package as \n  things got complicated.  (Who could have known that parsing and cascading style sheets\n  could be so complicated!)\n* [`{stringi}`](https://cran.r-project.org/package=stringi) is used as part of the lexer which breaks some of the SVG structures \n  into smaller objects for parsing e.g. transform strings like `translate(10, 10) rotate(50)`\n\n    \n\n## Related Software\n\n* [{rsvg}](https://cran.r-project.org/package=rsvg) renders SVG files into bitmaps, and \n   some other file representations.\n    * This package is wraps the C library [librsvg](https://github.com/GNOME/librsvg)\n* [{grImport2}](https://cran.r-project.org/package=grImport2) reads SVG files into R\n    * `grImport2` only seems to load SVG created by the Cairo graphics library\n\n#### Comparison to related R packages\n\n|                        | svgparser            | rsvg                                   | grImport2                           |\n|------------------------|-----------           |----------------------------------------|-------------------------------------|\n| Loads as Vector Object | Yes (grob)           | No (bitmap)                            | Yes (grob)                          |\n| Loads as Standard Grob | Yes (grobTree)       | No (bitmap)                            | No (custom PictureGrob)             |\n| Exposes coordinates    | Yes (as a data.frame) along with SVG meta-information | No                                     | Yes (via grid::grobPoints), but lacks meta-information |\n| Note                   |                      | Backed by fast + well tested C library | Will only load SVG created by Cairo |\n \n## Acknowledgements\n\n* Thanks to early alpha testers:\n    * [Trevor Davis](https://github.com/trevorld)\n    * [timelyportfolio](https://github.com/timelyportfolio)\n    * [Simon Coulombe](https://github.com/SimonCoulombe)\n    * [Mitchell O'hara-Wild](https://github.com/mitchelloharawild)\n    * [Maya Gans](https://github.com/MayaGans)\n    * [Thomas Mock](https://github.com/jthomasmock)\n    * [Jeroen Ooms](https://github.com/jeroen)\n    * [Ijeamakaanyene](https://github.com/Ijeamakaanyene)\n    * [Halian Vilela](https://github.com/halian-vilela)\n    * [Dmytro Perepolkin](https://github.com/dmi3kno)\n    * [arthurwelle](https://github.com/arthurwelle)\n* R Core for developing and maintaining the language.\n* CRAN maintainers, for patiently shepherding packages onto CRAN and maintaining\n  the repository\n","funding_links":[],"categories":["R"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoolbutuseless%2Fsvgparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoolbutuseless%2Fsvgparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoolbutuseless%2Fsvgparser/lists"}