Skip to content

Commit

Permalink
Add full support for ragg (#4388)
Browse files Browse the repository at this point in the history
  • Loading branch information
thomasp85 committed Apr 9, 2021
1 parent 0990114 commit a9b3b17
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 24 deletions.
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Imports:
withr (>= 2.0.0)
Suggests:
covr,
ragg,
dplyr,
ggplot2movies,
hexbin,
Expand Down
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# ggplot2 (development version)

* `ggsave()` now uses ragg to render raster output if ragg is available
(@thomasp85, #4388)

* `coord_sf()` now has an argument `default_crs` that specifies the coordinate
reference system (CRS) for non-sf layers and scale/coord limits. This argument
defaults to the World Geodetic System 1984 (WGS84), which means x and y positions
Expand Down
48 changes: 32 additions & 16 deletions R/save.r
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
#' are combined to create the fully qualified file name. Defaults to the
#' working directory.
#' @param scale Multiplicative scaling factor.
#' @param width,height,units Plot size in `units` ("in", "cm", or "mm").
#' @param width,height,units Plot size in `units` ("in", "cm", "mm", or "px").
#' If not supplied, uses the size of current graphics device.
#' @param dpi Plot resolution. Also accepts a string input: "retina" (320),
#' "print" (300), or "screen" (72). Applies only to raster output types.
Expand Down Expand Up @@ -75,13 +75,13 @@
#' }
ggsave <- function(filename, plot = last_plot(),
device = NULL, path = NULL, scale = 1,
width = NA, height = NA, units = c("in", "cm", "mm"),
width = NA, height = NA, units = c("in", "cm", "mm", "px"),
dpi = 300, limitsize = TRUE, bg = NULL, ...) {

dpi <- parse_dpi(dpi)
dev <- plot_dev(device, filename, dpi = dpi)
dim <- plot_dim(c(width, height), scale = scale, units = units,
limitsize = limitsize)
limitsize = limitsize, dpi = dpi)

if (!is.null(path)) {
filename <- file.path(path, filename)
Expand Down Expand Up @@ -122,12 +122,12 @@ parse_dpi <- function(dpi) {
}
}

plot_dim <- function(dim = c(NA, NA), scale = 1, units = c("in", "cm", "mm"),
limitsize = TRUE) {
plot_dim <- function(dim = c(NA, NA), scale = 1, units = c("in", "cm", "mm", "px"),
limitsize = TRUE, dpi = 300) {

units <- match.arg(units)
to_inches <- function(x) x / c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
from_inches <- function(x) x * c(`in` = 1, cm = 2.54, mm = 2.54 * 10)[units]
to_inches <- function(x) x / c(`in` = 1, cm = 2.54, mm = 2.54 * 10, px = dpi)[units]
from_inches <- function(x) x * c(`in` = 1, cm = 2.54, mm = 2.54 * 10, px = dpi)[units]

dim <- to_inches(dim) * scale

Expand Down Expand Up @@ -158,18 +158,34 @@ plot_dev <- function(device, filename = NULL, dpi = 300) {
force(dpi)

if (is.function(device)) {
if ("file" %in% names(formals(device))) {
dev <- function(filename, ...) device(file = filename, ...)
return(dev)
} else {
return(device)
args <- formals(device)
call_args <- list()
if ("file" %in% names(args)) {
call_args$file <- filename
}
if ("res" %in% names(args)) {
call_args$res <- dpi
}
if ("units" %in% names(args)) {
call_args$units <- 'in'
}
dev <- function(...) do.call(device, modify_list(list(...), call_args))
return(dev)
}

eps <- function(filename, ...) {
grDevices::postscript(file = filename, ..., onefile = FALSE, horizontal = FALSE,
paper = "special")
}
if (requireNamespace('ragg', quietly = TRUE)) {
png_dev <- ragg::agg_png
jpeg_dev <- ragg::agg_jpeg
tiff_dev <- ragg::agg_tiff
} else {
png_dev <- grDevices::png
jpeg_dev <- grDevices::jpeg
tiff_dev <- grDevices::tiff
}
devices <- list(
eps = eps,
ps = eps,
Expand All @@ -178,11 +194,11 @@ plot_dev <- function(device, filename = NULL, dpi = 300) {
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"),
jpg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
jpeg = function(...) grDevices::jpeg(..., res = dpi, units = "in"),
png = function(...) png_dev(..., res = dpi, units = "in"),
jpg = function(...) jpeg_dev(..., res = dpi, units = "in"),
jpeg = function(...) jpeg_dev(..., res = dpi, units = "in"),
bmp = function(...) grDevices::bmp(..., res = dpi, units = "in"),
tiff = function(...) grDevices::tiff(..., res = dpi, units = "in")
tiff = function(...) tiff_dev(..., res = dpi, units = "in")
)

if (is.null(device)) {
Expand Down
4 changes: 2 additions & 2 deletions man/ggsave.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 2 additions & 6 deletions tests/testthat/test-ggsave.R
Original file line number Diff line number Diff line change
Expand Up @@ -85,23 +85,19 @@ test_that("scale multiplies height & width", {

# plot_dev ---------------------------------------------------------------------

test_that("function is passed back unchanged", {
expect_equal(plot_dev(png), png)
})

test_that("unknown device triggers error", {
expect_error(plot_dev("xyz"), "Unknown graphics device")
expect_error(plot_dev(NULL, "test.xyz"), "Unknown graphics device")
})


test_that("text converted to function", {
expect_identical(body(plot_dev("png"))[[1]], quote(grDevices::png))
expect_identical(body(plot_dev("png"))[[1]], quote(png_dev))
expect_identical(body(plot_dev("pdf"))[[1]], quote(grDevices::pdf))
})

test_that("if device is NULL, guess from extension", {
expect_identical(body(plot_dev(NULL, "test.png"))[[1]], quote(grDevices::png))
expect_identical(body(plot_dev(NULL, "test.png"))[[1]], quote(png_dev))
})

# parse_dpi ---------------------------------------------------------------
Expand Down

0 comments on commit a9b3b17

Please sign in to comment.