From e1ad189d29aba3a9dc6bb9d06ea1cac0d01dabf9 Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Fri, 8 Dec 2017 10:53:52 -0600 Subject: [PATCH 1/2] ggsave(): restore previous device. Fixes #2363 --- NEWS.md | 3 +++ R/save.r | 6 +++++- tests/testthat/test-ggsave.R | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 54c56be6ea..358690cfe2 100644 --- a/NEWS.md +++ b/NEWS.md @@ -253,6 +253,9 @@ up correct aspect ratio, and draws a graticule. * `ggsave()`'s DPI argument now supports 3 string options: "retina" (320 DPI), "print" (300 DPI), and "screen" (72 DPI) (@foo-bar-baz-qux, #2156). +* `ggsave()` now correctly restores the previous graphics device when several + graphics devices are open. (#2363) + * `print.ggplot()` now returns the original ggplot object, instead of the output from `ggplot_build()`. Also, the object returned from `ggplot_build()` now has the class `"ggplot_built"`. (#2034) diff --git a/R/save.r b/R/save.r index ea2875ffdb..418f36e41a 100644 --- a/R/save.r +++ b/R/save.r @@ -53,8 +53,12 @@ ggsave <- function(filename, plot = last_plot(), if (!is.null(path)) { filename <- file.path(path, filename) } + old_dev <- dev.cur() dev(file = filename, width = dim[1], height = dim[2], ...) - on.exit(utils::capture.output(grDevices::dev.off())) + on.exit(utils::capture.output({ + grDevices::dev.off() + dev.set(old_dev) + })) grid.draw(plot) invisible() diff --git a/tests/testthat/test-ggsave.R b/tests/testthat/test-ggsave.R index abd8715920..7cd6fdb248 100644 --- a/tests/testthat/test-ggsave.R +++ b/tests/testthat/test-ggsave.R @@ -11,6 +11,26 @@ test_that("ggsave creates file", { expect_true(file.exists(path)) }) +test_that("ggsave restores previous graphics device", { + # When multiple devices are open, dev.off() restores the next one in the list, + # not the previously-active one. (#2363) + path <- tempfile() + on.exit(unlink(path)) + + png() + png() + on.exit({ + dev.off() + dev.off() + }, add = TRUE) + + old_dev <- dev.cur() + p <- ggplot(mpg, aes(displ, hwy)) + geom_point() + ggsave(path, p, device = "png", width = 5, height = 5) + + expect_identical(old_dev, dev.cur()) +}) + # plot_dim --------------------------------------------------------------- From 93882e6bf30c36933f4bf9d463063c7f1daa2d41 Mon Sep 17 00:00:00 2001 From: Winston Chang Date: Fri, 8 Dec 2017 11:05:32 -0600 Subject: [PATCH 2/2] ggsave(): fix partial argument match --- NEWS.md | 2 ++ R/save.r | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/NEWS.md b/NEWS.md index 358690cfe2..4d796290b1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -253,6 +253,8 @@ up correct aspect ratio, and draws a graticule. * `ggsave()`'s DPI argument now supports 3 string options: "retina" (320 DPI), "print" (300 DPI), and "screen" (72 DPI) (@foo-bar-baz-qux, #2156). +* Fixed partial argument matches in `ggsave()`. (#2355) + * `ggsave()` now correctly restores the previous graphics device when several graphics devices are open. (#2363) diff --git a/R/save.r b/R/save.r index 418f36e41a..7848f7e77e 100644 --- a/R/save.r +++ b/R/save.r @@ -54,7 +54,7 @@ ggsave <- function(filename, plot = last_plot(), filename <- file.path(path, filename) } old_dev <- dev.cur() - dev(file = filename, width = dim[1], height = dim[2], ...) + dev(filename = filename, width = dim[1], height = dim[2], ...) on.exit(utils::capture.output({ grDevices::dev.off() dev.set(old_dev) @@ -120,16 +120,16 @@ plot_dev <- function(device, filename, dpi = 300) { if (is.function(device)) return(device) - eps <- function(...) { - grDevices::postscript(..., onefile = FALSE, horizontal = FALSE, + eps <- function(filename, ...) { + grDevices::postscript(file = filename, ..., onefile = FALSE, horizontal = FALSE, paper = "special") } devices <- list( eps = eps, ps = eps, - tex = function(...) grDevices::pictex(...), - pdf = function(..., version = "1.4") grDevices::pdf(..., version = version), - svg = function(...) svglite::svglite(...), + tex = function(filename, ...) grDevices::pictex(file = filename, ...), + pdf = function(filename, ..., version = "1.4") grDevices::pdf(file = filename, ..., version = version), + svg = function(filename, ...) svglite::svglite(file = filename, ...), emf = function(...) grDevices::win.metafile(...), wmf = function(...) grDevices::win.metafile(...), png = function(...) grDevices::png(..., res = dpi, units = "in"),