6

Edit: This page provides the code: https://www.andrewheiss.com/blog/2017/09/27/working-with-r-cairo-graphics-custom-fonts-and-ggplot/

ggsave("test_cario.eps", device=cairo_ps)

ggsave("test_cario.pdf", device=cairo_pdf)

However, I am wondering where the commands come from. They are not included in the list of possible devices in the official documentation (https://ggplot2.tidyverse.org/reference/ggsave.html). And, cairo_png does not exist; instead, type="cairo-png" is necessary, e.g.:

ggsave("test_cairo.png", type = "cairo-png")

Does anyone know why the argument is one time device = "" and another time type = ""?


I have tried code like

ggsave("model.eps", type = "cairo")

or

ggsave("model.eps", type = "cairo-ps")

or

ggsave("model.eps", device = "cairo-ps")

but nothing seems to work. In general, is it possible to create .eps files with ggsave using the Cairo graphics device? If so, how?

00schneider
  • 698
  • 9
  • 21

3 Answers3

3

The code you need to look at to understand the differences is in a non-exported function named plot_dev in the ggplot namespace. You get this information by looking at the ggsave code. The line that dispatches to a device is:

dev <- plot_dev(device, filename, dpi = dpi)
# Look at that function
getAnywhere(plot_dev)  # not exported, so need getAnywhere

The logic of plot_dev is to first check to see whether the "device" value was given as a function name and if so to just call that function. That is what happens in the first two calls you offered. If it's not a function and no character value for "device" is given (which is the situation in your third call), then plot_dev dispatchs from a named list of functions based on the extension of the file name offered as "filename". The type argument gets passed to the png function to get the 'cairo' version of png used rather than the default.

This is the list of possible devices and their default arguments. Those defaults can be offered alternate values and the "dots" can be used to specify other device parameters. (See their respective help pages for specifics):

devices <- list(eps = eps, 
                ps = eps, 
     tex = function(filename, ...) 
                    grDevices::pictex(file = filename, ...),
     pdf = function(filename, ..., version = "1.4") 
               grDevices::pdf(file = filename, ..., version = version), 
      svg = function(filename, ...) vglite::svglite(file = filename,  ...), 
     emf = function(...) grDevices::win.metafile(...), 
     wmf = function(...) grDevices::win.metafile(...), 
     png = function(...) grDevices::png(..., res = dpi,
                                       units = "in"), 
     jpg = function(...) grDevices::jpeg(..., res = dpi,
                                         units = "in"), 
     jpeg = function(...) grDevices::jpeg(..., res = dpi,
                                          units = "in"), 
     bmp = function(...) grDevices::bmp(..., res = dpi,
                                      units = "in"), 
      tiff = function(...) grDevices::tiff(..., res = dpi,
                                           units = "in"))

Notice that the first two parameters are given values of eps. That is an internally defined function:

eps <- function(filename, ...) {
       grDevices::postscript(file = filename, ..., onefile = FALSE, 
            horizontal = FALSE, paper = "special")
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • Thank you very much for this elaborate answer. Do you know if it is possible call cairo directly with the 'device=""' argument? – 00schneider Sep 24 '18 at 06:56
  • 1
    Does not look possible in the context of `ggsave` because a) that would throw an error, and b) there is no corresponding entry in the `devices`-list, so it's not possible to have the selection driven off an extension. (There's no "cairo" extension recognized by system functions anyway.) – IRTFM Sep 24 '18 at 18:47
  • @00schneider You can create your own function wrapper to `png` with the cario version as the default. – James Sep 25 '18 at 08:56
  • Thanks! Do you know if it is possible to produce wmf or emf files with ggsave (and possibly with cairo)? Is that the windows device? – 00schneider Sep 26 '18 at 07:11
2

TL;DR

You need to call specific pdf and ps cairo devices while the standard png device can be set to produce cario output using its own type parameter.

Explanation

The device parameter of ggsave can take a device function, a character string matching one of a predefined list, or be left as NULL (in which case the device is guessed from the file extension). In any case, a device function will be called. Note that when using the function form, you may need to set some parameters that ggsave would do for you if you used the character or auto-detection forms.

The grDevices package which contains most of the devices used by default also has cario_pdf and cairo_ps devices that you can pass to ggsave.

There is no cairo_png device. However, the png device has a type parameter which takes options from the following vector(on Windows as least): c("windows", "cairo", "cairo-png"). ggsave passes on the type specification to the png device when it calls it.

James
  • 65,548
  • 14
  • 155
  • 193
  • Thanks! Do you know if it is possible to produce wmf or emf files with ggsave (and possibly with cairo)? Is that the windows device? – 00schneider Sep 26 '18 at 07:11
  • 1
    Yes, that is one of the built in options that can guessed by extension or you can use by using `"emf"` or `"wmf"` as the device string. There is no cairo option for the default `win.metafile` device though. – James Sep 26 '18 at 08:47
0

You can save to EPS with

ggsave("model.eps", device = "eps")
Marcelo Ventura
  • 581
  • 7
  • 19