There are many advantages to using Cairo to save R graphics (see here, for example). When saving PDFs, for instance, the cairo_pdf
device correctly embeds custom fonts.
Using the cairo_pdf
graphics device is easy with ggplot-based graphics with ggsave()
:
library(ggplot2)
ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = "Some data about cars") +
theme_gray(base_family = "Papyrus")
ugly_plot
ggsave(ugly_plot, filename = "ugly_plot.pdf",
width = 4, height = 2.5, device = cairo_pdf)
Using the cairo_pdf
device in R Markdown with knitr is also easy—add dev: cairo_pdf
to the YAML front matter:
---
title: "Cairo stuff"
output:
pdf_document:
dev: cairo_pdf
---
```{r make-ugly-plot, fig.width=4, fig.height=2.5}
library(ggplot2)
ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = "Some data about cars") +
theme_gray(base_family = "Papyrus")
ugly_plot
```
There are also advantages to using Cairo-based PNGs, since Cairo correctly deals with DPI. If you place a normally-saved PNG with a high DPI into a Word or PowerPoint file, the dimensions of the figure are exaggerated and not accurate. If you place a Cairo-based PNG with the same high DPI into Word, the dimensions are correct:
Saving ggplot output as high resolution Cairo PNGs is easy with ggsave()
, but the syntax is slightly different from saving as Cairo PDFs. Instead of specifying a device, we specify type:
ggsave(ugly_plot, filename = "ugly_plot.png",
width = 4, height = 2.5, dpi = 300, type = "cairo")
Placing that file in Word or PowerPoint works great and everything is sized correctly at high resolution.
This misinterpretation of dimensions carries over into R Markdown when knitting to HTML or Word. It'd be great to have knitr use type = "cairo"
when knitting, but replicating this dpi = 300, type = "cairo"
in R Markdown, however, is more difficult. The Cairo library includes devices like Cairo::CairoPNG()
, but ggsave(..., type = "cairo")
doesn't use this device. It uses R's standard PNG device, but with Cairo support turned on.
Making the figure high resolution is easy enough with adding dpi=300
to the chunk options, but I can't get knitr to use the built-in PNG device with type = cairo
enabled. I tried naively adding type: cairo
to the YAML metadata, but it unsurprisingly doesn't work. The PNG that knitr generates doesn't use Cairo and is much larger than expected (and is gigantic in HTML and Word documents).
---
title: "Cairo stuff"
output:
html_document:
self_contained: no # to see resulting figure as a file
dev: png
type: cairo # this doesn't do anything
---
```{r make-ugly-plot, fig.width=5, fig.height=3.5, dpi=300}
library(ggplot2)
ugly_plot <- ggplot(mtcars, aes(x = wt, y = mpg)) +
geom_point() +
labs(title = "Some data about cars") +
theme_gray(base_family = "Papyrus")
ugly_plot
```
In sum, I'm looking for a way to use the same output you'd get from ggsave(..., filename = "blah.png", dpi = 300, type = "cairo")
in knitr. Is there a way to do this?
---
title: "Something"
output:
pdf_document:
dev: cairo_pdf # yay Cairo output
html_document: # What needs to go here?
dev: png
type: cairo
---
dev.args
instead of justdev
, as in my answer below?? – Stannite