From febd0c40392ab03d9b1f004c17818cf493fe0f62 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Tue, 30 Jul 2024 11:34:44 +0200 Subject: [PATCH 1/2] Remove usage of metaprogramming in device helpers --- DESCRIPTION | 4 +- R/devices.R | 266 +++++++++++++++++++++++++++---------------- man/devices.Rd | 301 +++++-------------------------------------------- 3 files changed, 199 insertions(+), 372 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 00bb5d8..1a32d46 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -48,10 +48,9 @@ Collate: 'defer-exit.R' 'standalone-defer.R' 'defer.R' - 'wrap.R' + 'devices.R' 'local_.R' 'with_.R' - 'devices.R' 'dir.R' 'env.R' 'file.R' @@ -65,6 +64,7 @@ Collate: 'path.R' 'rng.R' 'seed.R' + 'wrap.R' 'sink.R' 'tempfile.R' 'timezone.R' diff --git a/R/devices.R b/R/devices.R index 8cf3b36..13643a7 100644 --- a/R/devices.R +++ b/R/devices.R @@ -1,59 +1,3 @@ -#' @include with_.R -#' @include wrap.R -NULL - -# Internal *_dev functions ------------------------------------------------ - -pdf_dev <- wrap(grDevices::pdf, NULL, grDevices::dev.cur()) - -postscript_dev <- wrap(grDevices::postscript, NULL, grDevices::dev.cur()) - -svg_wrapper <- function(filename, width = 7, height = 7, pointsize = 12, - onefile = FALSE, family = "sans", bg = "white", - antialias = c("default", "none", "gray", "subpixel"), ...) { - grDevices::svg(filename, width, height, pointsize, onefile, family, bg, antialias, ...) -} -svg_dev <- wrap(svg_wrapper, NULL, grDevices::dev.cur()) - -xfig_dev <- wrap(grDevices::xfig, NULL, grDevices::dev.cur()) - - -# These functions arguments differ between R versions, so just use ... - -cairo_pdf_dev <- function(filename, ...) { - grDevices::cairo_pdf(filename = filename, ...) - grDevices::dev.cur() -} - -cairo_ps_dev <- function(filename, ...) { - grDevices::cairo_ps(filename = filename, ...) - grDevices::dev.cur() -} - -# These functions arguments differ between unix and windows, so just use ... - -bmp_dev <- function(filename, ...) { - grDevices::bmp(filename = filename, ...) - grDevices::dev.cur() -} - -tiff_dev <- function(filename, ...) { - grDevices::tiff(filename = filename, ...) - grDevices::dev.cur() -} - -png_dev <- function(filename, ...) { - grDevices::png(filename = filename, ...) - grDevices::dev.cur() -} - -jpeg_dev <- function(filename, ...) { - grDevices::jpeg(filename = filename, ...) - grDevices::dev.cur() -} - -# User-level with_* fns --------------------------------------------------- - #' Graphics devices #' #' Temporarily use a graphics device. @@ -64,6 +8,18 @@ jpeg_dev <- function(filename, ...) { #' @param new \code{[named character]}\cr New graphics device #' @param ... Additional arguments passed to the graphics device. #' @param .local_envir `[environment]`\cr The environment to use for scoping. +#' @details +#' * `with_bmp()` and `local_bmp()` wrap around [grDevices::bmp()]. +#' * `with_cairo_pdf()` and `local_cairo_pdf()` wrap around [grDevices::cairo_pdf()]. +#' * `with_cairo_ps()` and `local_cairo_ps()` wrap around [grDevices::cairo_ps()]. +#' * `with_pdf()` and `local_pdf()` wrap around [grDevices::pdf()]. +#' * `with_postscript()` and `local_postscript()` wrap around [grDevices::postscript()]. +#' * `with_svg()` and `local_svg()` wrap around [grDevices::svg()]. +#' * `with_tiff()` and `local_tiff()` wrap around [grDevices::tiff()]. +#' * `with_xfig()` and `local_xfig()` wrap around [grDevices::xfig()]. +#' * `with_png()` and `local_png()` wrap around [grDevices::png()]. +#' * `with_jpeg()` and `local_jpeg()` wrap around [grDevices::jpeg()]. +#' #' @seealso \code{\link[grDevices]{Devices}} #' @examples #' # dimensions are in inches @@ -77,105 +33,217 @@ jpeg_dev <- function(filename, ...) { #' ) NULL -dev_close <- function(which) { - prev <- grDevices::dev.prev(which) - grDevices::dev.off(which) - - # No devices active - if (prev != which) { - grDevices::dev.set(prev) - } - - prev -} - #' @describeIn devices BMP device #' @export -with_bmp <- with_(bmp_dev, dev_close) +with_bmp <- function(new, code, ...) { + local_bmp(new, ...) + code +} #' @rdname devices #' @export -local_bmp <- local_(bmp_dev, dev_close) +local_bmp <- function(new, ..., .local_envir = parent.frame()) { + old <- bmp_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices CAIRO_PDF device -#' @inheritParams grDevices::cairo_pdf #' @export -with_cairo_pdf <- with_(cairo_pdf_dev, dev_close) +with_cairo_pdf <- function(new, code, ...) { + local_cairo_pdf(new, ...) + code +} #' @rdname devices #' @export -local_cairo_pdf <- local_(cairo_pdf_dev, dev_close) +local_cairo_pdf <- function(new, ..., .local_envir = parent.frame()) { + old <- cairo_pdf_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices CAIRO_PS device -#' @inheritParams grDevices::cairo_ps #' @export -with_cairo_ps <- with_(cairo_ps_dev, dev_close) +with_cairo_ps <- function(new, code, ...) { + local_cairo_ps(new, ...) + code +} #' @rdname devices #' @export -local_cairo_ps <- local_(cairo_ps_dev, dev_close) +local_cairo_ps <- function(new, ..., .local_envir = parent.frame()) { + old <- cairo_ps_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices PDF device -#' @inheritParams grDevices::pdf #' @export -with_pdf <- with_(pdf_dev, dev_close) +with_pdf <- function(new, code, ...) { + local_pdf(new, ...) + code +} #' @rdname devices #' @export -local_pdf <- local_(pdf_dev, dev_close) +local_pdf <- function(new, ..., .local_envir = parent.frame()) { + old <- pdf_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices POSTSCRIPT device -#' @inheritParams grDevices::postscript -#' @param command the command to be used for \sQuote{printing}. Defaults -#' to \code{"default"}, the value of option \code{"printcmd"}. The -#' length limit is \code{2*PATH_MAX}, typically 8096 bytes on unix systems and -#' 520 bytes on windows. #' @export -with_postscript <- with_(postscript_dev, dev_close) +with_postscript <- function(new, code, ...) { + local_postscript(new, ...) + code +} #' @rdname devices #' @export -local_postscript <- local_(postscript_dev, dev_close) +local_postscript <- function(new, ..., .local_envir = parent.frame()) { + old <- postscript_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices SVG device -#' @inheritParams grDevices::svg #' @export -with_svg <- with_(svg_dev, dev_close) +with_svg <- function(new, code, ...) { + local_svg(new, ...) + code +} #' @rdname devices #' @export -local_svg <- local_(svg_dev, dev_close) +local_svg <- function(new, ..., .local_envir = parent.frame()) { + old <- svg_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices TIFF device #' @export -with_tiff <- with_(tiff_dev, dev_close) - +with_tiff <- function(new, code, ...) { + local_tiff(new, ...) + code +} #' @rdname devices #' @export -local_tiff <- local_(tiff_dev, dev_close) +local_tiff <- function(new, ..., .local_envir = parent.frame()) { + old <- tiff_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices XFIG device -#' @inheritParams grDevices::xfig #' @export -with_xfig <- with_(xfig_dev, dev_close) +with_xfig <- function(new, code, ...) { + local_xfig(new, ...) + code +} #' @rdname devices #' @export -local_xfig <- local_(xfig_dev, dev_close) +local_xfig <- function(new, ..., .local_envir = parent.frame()) { + old <- xfig_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices PNG device #' @export -with_png <- with_(png_dev, dev_close) +with_png <- function(new, code, ...) { + local_png(new, ...) + code +} #' @rdname devices #' @export -local_png <- local_(png_dev, dev_close) +local_png <- function(new, ..., .local_envir = parent.frame()) { + old <- png_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} #' @describeIn devices JPEG device #' @export -with_jpeg <- with_(jpeg_dev, dev_close) +with_jpeg <- function(new, code, ...) { + local_jpeg(new, ...) + code +} #' @rdname devices #' @export -local_jpeg <- local_(jpeg_dev, dev_close) +local_jpeg <- function(new, ..., .local_envir = parent.frame()) { + old <- jpeg_dev(new, ...) + defer(dev_close(old), envir = .local_envir) + invisible(old) +} + + +# Internal *_dev functions ------------------------------------------------ + +pdf_dev <- function(filename, ...) { + grDevices::pdf(file = filename, ...) + grDevices::dev.cur() +} + +postscript_dev <- function(filename, ...) { + grDevices::postscript(file = filename, ...) + grDevices::dev.cur() +} + +svg_dev <- function(filename, ...) { + grDevices::svg(filename = filename, ...) + grDevices::dev.cur() +} + +xfig_dev <- function(filename, ...) { + grDevices::xfig(file = filename, ...) + grDevices::dev.cur() +} + +cairo_pdf_dev <- function(filename, ...) { + grDevices::cairo_pdf(filename = filename, ...) + grDevices::dev.cur() +} + +cairo_ps_dev <- function(filename, ...) { + grDevices::cairo_ps(filename = filename, ...) + grDevices::dev.cur() +} + +bmp_dev <- function(filename, ...) { + grDevices::bmp(filename = filename, ...) + grDevices::dev.cur() +} + +tiff_dev <- function(filename, ...) { + grDevices::tiff(filename = filename, ...) + grDevices::dev.cur() +} + +png_dev <- function(filename, ...) { + grDevices::png(filename = filename, ...) + grDevices::dev.cur() +} + +jpeg_dev <- function(filename, ...) { + grDevices::jpeg(filename = filename, ...) + grDevices::dev.cur() +} + +dev_close <- function(which) { + prev <- grDevices::dev.prev(which) + grDevices::dev.off(which) + + # No devices active + if (prev != which) { + grDevices::dev.set(prev) + } + + prev +} diff --git a/man/devices.Rd b/man/devices.Rd index 11ed45b..a2fd84b 100644 --- a/man/devices.Rd +++ b/man/devices.Rd @@ -28,181 +28,43 @@ \usage{ with_bmp(new, code, ...) -local_bmp(new = list(), ..., .local_envir = parent.frame()) +local_bmp(new, ..., .local_envir = parent.frame()) with_cairo_pdf(new, code, ...) -local_cairo_pdf(new = list(), ..., .local_envir = parent.frame()) +local_cairo_pdf(new, ..., .local_envir = parent.frame()) with_cairo_ps(new, code, ...) -local_cairo_ps(new = list(), ..., .local_envir = parent.frame()) - -with_pdf( - new, - code, - width, - height, - onefile, - family, - title, - fonts, - version, - paper, - encoding, - bg, - fg, - pointsize, - pagecentre, - colormodel, - useDingbats, - useKerning, - fillOddEven, - compress -) +local_cairo_ps(new, ..., .local_envir = parent.frame()) -local_pdf( - new = list(), - width, - height, - onefile, - family, - title, - fonts, - version, - paper, - encoding, - bg, - fg, - pointsize, - pagecentre, - colormodel, - useDingbats, - useKerning, - fillOddEven, - compress, - .local_envir = parent.frame() -) +with_pdf(new, code, ...) -with_postscript( - new, - code, - onefile, - family, - title, - fonts, - encoding, - bg, - fg, - width, - height, - horizontal, - pointsize, - paper, - pagecentre, - print.it, - command, - colormodel, - useKerning, - fillOddEven -) +local_pdf(new, ..., .local_envir = parent.frame()) -local_postscript( - new = list(), - onefile, - family, - title, - fonts, - encoding, - bg, - fg, - width, - height, - horizontal, - pointsize, - paper, - pagecentre, - print.it, - command, - colormodel, - useKerning, - fillOddEven, - .local_envir = parent.frame() -) +with_postscript(new, code, ...) -with_svg( - new, - code, - width = 7, - height = 7, - pointsize = 12, - onefile = FALSE, - family = "sans", - bg = "white", - antialias = c("default", "none", "gray", "subpixel"), - ... -) +local_postscript(new, ..., .local_envir = parent.frame()) -local_svg( - new = list(), - width = 7, - height = 7, - pointsize = 12, - onefile = FALSE, - family = "sans", - bg = "white", - antialias = c("default", "none", "gray", "subpixel"), - ..., - .local_envir = parent.frame() -) +with_svg(new, code, ...) + +local_svg(new, ..., .local_envir = parent.frame()) with_tiff(new, code, ...) -local_tiff(new = list(), ..., .local_envir = parent.frame()) - -with_xfig( - new, - code, - onefile = FALSE, - encoding = "none", - paper = "default", - horizontal = TRUE, - width = 0, - height = 0, - family = "Helvetica", - pointsize = 12, - bg = "transparent", - fg = "black", - pagecentre = TRUE, - defaultfont = FALSE, - textspecial = FALSE -) +local_tiff(new, ..., .local_envir = parent.frame()) -local_xfig( - new = list(), - onefile = FALSE, - encoding = "none", - paper = "default", - horizontal = TRUE, - width = 0, - height = 0, - family = "Helvetica", - pointsize = 12, - bg = "transparent", - fg = "black", - pagecentre = TRUE, - defaultfont = FALSE, - textspecial = FALSE, - .local_envir = parent.frame() -) +with_xfig(new, code, ...) + +local_xfig(new, ..., .local_envir = parent.frame()) with_png(new, code, ...) -local_png(new = list(), ..., .local_envir = parent.frame()) +local_png(new, ..., .local_envir = parent.frame()) with_jpeg(new, code, ...) -local_jpeg(new = list(), ..., .local_envir = parent.frame()) +local_jpeg(new, ..., .local_envir = parent.frame()) } \arguments{ \item{new}{\code{[named character]}\cr New graphics device} @@ -212,123 +74,6 @@ local_jpeg(new = list(), ..., .local_envir = parent.frame()) \item{...}{Additional arguments passed to the graphics device.} \item{.local_envir}{\verb{[environment]}\cr The environment to use for scoping.} - -\item{width}{the width of the device in inches.} - -\item{height}{the height of the device in inches.} - -\item{onefile}{should all plots appear in one file or in separate files?} - -\item{family}{one of the device-independent font families, - \code{"sans"}, \code{"serif"} and \code{"mono"}, or a character - string specify a font family to be searched for in a - system-dependent way. - - On unix-alikes (incl.\\ macOS), see - the \sQuote{Cairo fonts} section in the help for \code{\link[grDevices]{X11}}. - } - -\item{title}{title string to embed as the \samp{/Title} field in the - file. Defaults to \code{"R Graphics Output"}.} - -\item{fonts}{a character vector specifying \R graphics font family - names for additional fonts which will be included in the PDF file. - Defaults to \code{NULL}.} - -\item{version}{a string describing the PDF version that will be - required to view the output. This is a minimum, and will be - increased (with a warning) if necessary. Defaults to \code{"1.4"}, - but see \sQuote{Details}.} - -\item{paper}{the target paper size. The choices are - \code{"a4"}, \code{"letter"}, \code{"legal"} (or \code{"us"}) and - \code{"executive"} (and these can be capitalized), or \code{"a4r"} - and \code{"USr"} for rotated (\sQuote{landscape}). - The default is \code{"special"}, which means that the \code{width} - and \code{height} specify the paper size. A further choice is - \code{"default"}; if this is selected, the - paper size is taken from the option \code{"papersize"} - if that is set and as \code{"a4"} if it is unset or empty. - Defaults to \code{"special"}. - } - -\item{encoding}{the name of an encoding file. Defaults to - \code{"default"}. The latter is interpreted - \describe{ - \item{on Unix-alikes}{ - as \file{"ISOLatin1.enc"} unless the locale is recognized as - corresponding to a language using ISO 8859-\{2,5,7,13,15\} or KOI8-\{R,U\}. - } - \item{on Windows}{ - as \file{"CP1250.enc"} (Central European), \code{"CP1251.enc"} (Cyrillic), - \code{"CP1253.enc"} (Greek) or \code{"CP1257.enc"} (Baltic) if one - of those codepages is in use, otherwise \file{"WinAnsi.enc"} - (codepage 1252). - } - } - The file is looked for in the \file{enc} directory of package - \pkg{grDevices} if the path does not contain a path separator. An - extension \code{".enc"} can be omitted. - } - -\item{bg}{the initial background colour: can be overridden by setting - \code{par("bg")}.} - -\item{fg}{the initial foreground color to be used. Defaults to - \code{"black"}.} - -\item{pointsize}{the default pointsize of plotted text (in big points).} - -\item{pagecentre}{logical: should the device region be centred on the - page? -- is only relevant for \code{paper != "special"}. - Defaults to \code{TRUE}.} - -\item{colormodel}{a character string describing the color model: - currently allowed values are \code{"srgb"}, \code{"gray"} (or - \code{"grey"}) and \code{"cmyk"}. Defaults to \code{"srgb"}. See section - \sQuote{Color models}.} - -\item{useDingbats}{logical. Should small circles be rendered - \emph{via} the Dingbats font? Defaults to \code{FALSE}. - If \code{TRUE}, this can produce smaller and better output, but - can cause font display problems in broken PDF viewers: although this - font is one of the 14 guaranteed to be available in all PDF viewers, - that guarantee is not always honoured. - - For Unix-alikes (including macOS) see the \sQuote{Note} for a - possible fix for some viewers.} - -\item{useKerning}{logical. Should kerning corrections be included in - setting text and calculating string widths? Defaults to \code{TRUE}.} - -\item{fillOddEven}{logical controlling the polygon fill mode: see - \code{\link{polygon}} for details. Defaults to \code{FALSE}.} - -\item{compress}{logical. Should PDF streams be generated with Flate - compression? Defaults to \code{TRUE}.} - -\item{horizontal}{the orientation of the printed image, a logical. - Defaults to true, that is landscape orientation on paper sizes - with width less than height.} - -\item{print.it}{logical: should the file be printed when the device is - closed? (This only applies if \code{file} is a real file name.) - Defaults to false.} - -\item{command}{the command to be used for \sQuote{printing}. Defaults -to \code{"default"}, the value of option \code{"printcmd"}. The -length limit is \code{2*PATH_MAX}, typically 8096 bytes on unix systems and -520 bytes on windows.} - -\item{antialias}{string, the type of anti-aliasing (if any) to be used; - defaults to \code{"default"}.} - -\item{defaultfont}{logical: should the device use XFig's default - font?} - -\item{textspecial}{logical: should the device set the textspecial flag - for all text elements? This is useful when generating pstex from XFig - figures.} } \value{ \code{[any]}\cr The results of the evaluation of the \code{code} @@ -337,6 +82,20 @@ argument. \description{ Temporarily use a graphics device. } +\details{ +\itemize{ +\item \code{with_bmp()} and \code{local_bmp()} wrap around \code{\link[grDevices:png]{grDevices::bmp()}}. +\item \code{with_cairo_pdf()} and \code{local_cairo_pdf()} wrap around \code{\link[grDevices:cairo]{grDevices::cairo_pdf()}}. +\item \code{with_cairo_ps()} and \code{local_cairo_ps()} wrap around \code{\link[grDevices:cairo]{grDevices::cairo_ps()}}. +\item \code{with_pdf()} and \code{local_pdf()} wrap around \code{\link[grDevices:pdf]{grDevices::pdf()}}. +\item \code{with_postscript()} and \code{local_postscript()} wrap around \code{\link[grDevices:postscript]{grDevices::postscript()}}. +\item \code{with_svg()} and \code{local_svg()} wrap around \code{\link[grDevices:cairo]{grDevices::svg()}}. +\item \code{with_tiff()} and \code{local_tiff()} wrap around \code{\link[grDevices:png]{grDevices::tiff()}}. +\item \code{with_xfig()} and \code{local_xfig()} wrap around \code{\link[grDevices:xfig]{grDevices::xfig()}}. +\item \code{with_png()} and \code{local_png()} wrap around \code{\link[grDevices:png]{grDevices::png()}}. +\item \code{with_jpeg()} and \code{local_jpeg()} wrap around \code{\link[grDevices:png]{grDevices::jpeg()}}. +} +} \section{Functions}{ \itemize{ \item \code{with_bmp()}: BMP device From 2b8a5db4eb639c8ae790aad540559564be51dcf5 Mon Sep 17 00:00:00 2001 From: Lionel Henry Date: Tue, 30 Jul 2024 15:53:33 +0200 Subject: [PATCH 2/2] Inline device opening and abstract device closing --- R/devices.R | 106 +++++++++++++--------------------------------------- 1 file changed, 26 insertions(+), 80 deletions(-) diff --git a/R/devices.R b/R/devices.R index 13643a7..3540be0 100644 --- a/R/devices.R +++ b/R/devices.R @@ -43,9 +43,8 @@ with_bmp <- function(new, code, ...) { #' @rdname devices #' @export local_bmp <- function(new, ..., .local_envir = parent.frame()) { - old <- bmp_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::bmp(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices CAIRO_PDF device @@ -58,9 +57,8 @@ with_cairo_pdf <- function(new, code, ...) { #' @rdname devices #' @export local_cairo_pdf <- function(new, ..., .local_envir = parent.frame()) { - old <- cairo_pdf_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::cairo_pdf(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices CAIRO_PS device @@ -73,9 +71,8 @@ with_cairo_ps <- function(new, code, ...) { #' @rdname devices #' @export local_cairo_ps <- function(new, ..., .local_envir = parent.frame()) { - old <- cairo_ps_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::cairo_ps(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices PDF device @@ -88,9 +85,8 @@ with_pdf <- function(new, code, ...) { #' @rdname devices #' @export local_pdf <- function(new, ..., .local_envir = parent.frame()) { - old <- pdf_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::pdf(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices POSTSCRIPT device @@ -103,9 +99,8 @@ with_postscript <- function(new, code, ...) { #' @rdname devices #' @export local_postscript <- function(new, ..., .local_envir = parent.frame()) { - old <- postscript_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::postscript(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices SVG device @@ -118,9 +113,8 @@ with_svg <- function(new, code, ...) { #' @rdname devices #' @export local_svg <- function(new, ..., .local_envir = parent.frame()) { - old <- svg_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::svg(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices TIFF device @@ -133,9 +127,8 @@ with_tiff <- function(new, code, ...) { #' @rdname devices #' @export local_tiff <- function(new, ..., .local_envir = parent.frame()) { - old <- tiff_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::tiff(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices XFIG device @@ -148,9 +141,8 @@ with_xfig <- function(new, code, ...) { #' @rdname devices #' @export local_xfig <- function(new, ..., .local_envir = parent.frame()) { - old <- xfig_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::xfig(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices PNG device @@ -163,9 +155,8 @@ with_png <- function(new, code, ...) { #' @rdname devices #' @export local_png <- function(new, ..., .local_envir = parent.frame()) { - old <- png_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::png(new, ...) + defer_dev_close(.local_envir) } #' @describeIn devices JPEG device @@ -178,62 +169,17 @@ with_jpeg <- function(new, code, ...) { #' @rdname devices #' @export local_jpeg <- function(new, ..., .local_envir = parent.frame()) { - old <- jpeg_dev(new, ...) - defer(dev_close(old), envir = .local_envir) - invisible(old) + grDevices::jpeg(new, ...) + defer_dev_close(.local_envir) } +defer_dev_close <- function(frame) { + cur <- grDevices::dev.cur() + defer(dev_close(cur), envir = frame) -# Internal *_dev functions ------------------------------------------------ - -pdf_dev <- function(filename, ...) { - grDevices::pdf(file = filename, ...) - grDevices::dev.cur() -} - -postscript_dev <- function(filename, ...) { - grDevices::postscript(file = filename, ...) - grDevices::dev.cur() -} - -svg_dev <- function(filename, ...) { - grDevices::svg(filename = filename, ...) - grDevices::dev.cur() -} - -xfig_dev <- function(filename, ...) { - grDevices::xfig(file = filename, ...) - grDevices::dev.cur() -} - -cairo_pdf_dev <- function(filename, ...) { - grDevices::cairo_pdf(filename = filename, ...) - grDevices::dev.cur() -} - -cairo_ps_dev <- function(filename, ...) { - grDevices::cairo_ps(filename = filename, ...) - grDevices::dev.cur() -} - -bmp_dev <- function(filename, ...) { - grDevices::bmp(filename = filename, ...) - grDevices::dev.cur() -} - -tiff_dev <- function(filename, ...) { - grDevices::tiff(filename = filename, ...) - grDevices::dev.cur() -} - -png_dev <- function(filename, ...) { - grDevices::png(filename = filename, ...) - grDevices::dev.cur() -} - -jpeg_dev <- function(filename, ...) { - grDevices::jpeg(filename = filename, ...) - grDevices::dev.cur() + # Note that unlike typical `local_` functions we return the current device + # rather than the old one + invisible(cur) } dev_close <- function(which) {