r-lib / svglite

A lightweight svg graphics device for R
https://svglite.r-lib.org
181 stars 38 forks source link

Feature request: add a base64 argument to embed encoded web fonts #128

Open jplecavalier opened 3 years ago

jplecavalier commented 3 years ago

As you probably know, when integrating svg files using <img> tag inside an HTML document, the svg won't be able to load external resources such as web fonts due to security reason. I'm really new to this, but I think that the workaround would be to include a base64 encoded version of the font instead of the link pointing to the external resource. The user could then trigger this behaviour by passing TRUE to a new base64 argument to be added in the font_face() function.

The internal function validate_web_fonts() would have to be modified to include this new argument as well for users specifying an URL instead of using the font_face() function. We could then add a new web_fonts_base64 argument to the svglite() function to trigger the behaviour.

The preferred workflow to embed web fonts in an svg built with svglite in a knitr chunk would then become something like this for a user having Open Sans installed locally:

Setup chunk making it easy to use Open Sans in any other chunk

```{r, include=FALSE}
library(ggplot2)
library(extrafont) # To make the local fonts available to R

knitr::opts_chunk$set(
  dev = "svglite",
  web_fonts = "https://fonts.googleapis.com/css2?family=Open+Sans&display=swap",
  web_fonts_base64 = TRUE
)
``` #

...

Chunk outputting a ggplot using Open Sans in an svg

```{r}
ggplot(mpg, aes(displ, hwy, colour = class)) + 
  geom_point() +
  theme_minimal(base_family = "Open Sans")
``` #

Does that make any sense at all or am I totally missing something?

paessens commented 3 years ago

Hi, I appreciated embedding the preferred fonts in the image. Although it would be overkill regarding file size, to embedd in each and every image if there are many of them in a document. Wouldn't it be better to include svg inline and embedd fonts once in the html-doc?

jplecavalier commented 3 years ago

I think that the size is still manageable if the users only include the fonts they really need. Moreover, users could simply set the web_fonts_base64 argument to FALSE if they want the actual behaviour. This would indeed by the preferred workflow when including the svg inline.

However, having the fonts embed would facilitate sharing the svg as a single self contained file (as one often wants to do with images) and would make the svg recognizable as images by search engines (which is not the case with inline svg or svg wrapped in an <object> tag).

I think both options should be available for users easily, which would be the case with my feature suggestion.

paessens commented 3 years ago

agreed, did you try svg-buddy?

jplecavalier commented 3 years ago

I did not, but it looks to do exactly what I'd like. Do you think it would be possible (and a good idea, of course) to wrap it inside svglite or should I create another independent package only dedicated to make an R interface for svg-buddy?

paessens commented 3 years ago

Currently I do kind of postprocessing like this on debian-10:

imagepath = '/Users/hp/Downloads/logo-left-black.svg' sprintf("xxx/svg-buddy %s %s --optimize &",imagepath,imagepath) %>% system()

that'll do the job for me (the postprocessing works also on windows & macos but different executable)

if you write an awesome package that certainly is appreciated, but obviously you will have to contact both developers of svglite and svg-buddy and mange any dependency ...