From 5cca6019d0f9eb0e7f041a3b10c10b8c1085237d Mon Sep 17 00:00:00 2001 From: Philipp A Date: Thu, 3 Dec 2020 01:43:08 +0100 Subject: [PATCH 1/2] Try using ragg --- DESCRIPTION | 1 + R/repr_recordedplot.r | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 33432c4..3309387 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -30,6 +30,7 @@ Suggests: methods, highr, Cairo, + ragg, stringr, testthat (>= 3.0.0), leaflet diff --git a/R/repr_recordedplot.r b/R/repr_recordedplot.r index ea6689e..5b292d5 100644 --- a/R/repr_recordedplot.r +++ b/R/repr_recordedplot.r @@ -1,4 +1,5 @@ is_cairo_installed <- function() requireNamespace('Cairo', quietly = TRUE) +is_ragg_installed <- function() requireNamespace('ragg', quietly = TRUE) # checking capability of X11 is slow, the short circult logic avoids # this if any other devices are found. @@ -89,7 +90,9 @@ repr_png.recordedplot <- function(obj, if (!is_cairo_installed() && !check_capability('png')) return(NULL) dev.cb <- function(tf) - if (is_cairo_installed()) + if (is_ragg_installed()) + ragg::agg_png(tf, width, height, 'in', pointsize, bg, res) # scaling, bitsize + else if (is_cairo_installed()) Cairo::Cairo(width, height, tf, 'png', pointsize, bg, 'transparent', 'in', res) else png(tf, width, height, 'in', pointsize, bg, res, antialias = antialias) @@ -113,7 +116,9 @@ repr_jpg.recordedplot <- function(obj, if (!is_cairo_installed() && !check_capability('jpeg')) return(NULL) dev.cb <- function(tf) - if (is_cairo_installed()) + if (is_ragg_installed()) + ragg::agg_jpeg(tf, width, height, 'in', pointsize, bg, res, quality = quality) + else if (is_cairo_installed()) Cairo::Cairo(width, height, tf, 'jpeg', pointsize, bg, 'transparent', 'in', res, quality = quality) else jpeg(tf, width, height, 'in', pointsize, quality, bg, res, antialias = antialias) From f887b28595dafc6aefe6c55b0a89489ccbf34f99 Mon Sep 17 00:00:00 2001 From: Philipp A Date: Wed, 20 Jan 2021 20:37:18 +0100 Subject: [PATCH 2/2] WIP --- R/options.r | 29 ++++++++++++++++------- R/repr_recordedplot.r | 55 +++++++++++++++++++++++-------------------- man/repr-options.Rd | 29 ++++++++++++++++------- 3 files changed, 72 insertions(+), 41 deletions(-) diff --git a/R/options.r b/R/options.r index 75b4721..07d8826 100644 --- a/R/options.r +++ b/R/options.r @@ -13,14 +13,27 @@ #' \item{\code{repr.plot.*}}{ #' Those are for representations of \code{recordedplot} instances: #' \describe{ -#' \item{\code{repr.plot.width}}{Plotting area width in inches (default: 7)} -#' \item{\code{repr.plot.height}}{Plotting area height in inches (default: 7)} -#' \item{\code{repr.plot.pointsize}}{Text height in pt (default: 12)} -#' \item{\code{repr.plot.bg}}{Background color (default: white)} -#' \item{\code{repr.plot.antialias}}{Which kind of antialiasing to use for for lines and text? 'gray', 'subpixel' or 'none'? (default: gray)} -#' \item{\code{repr.plot.res}}{PPI for rasterization (default: 120)} -#' \item{\code{repr.plot.quality}}{Quality of JPEG format in \% (default: 90)} -#' \item{\code{repr.plot.family}}{Vector font family. 'sans', 'serif', 'mono' or a specific one (default: sans)} +#' \item{\code{repr.plot.width}}{Plotting area width in inches (default: \code{7})} +#' \item{\code{repr.plot.height}}{Plotting area height in inches (default: \code{7})} +#' \item{\code{repr.plot.pointsize}}{Text height in pt (default: \code{12})} +#' \item{\code{repr.plot.bg}}{Background color (default: \code{'white'})} +#' \item{\code{repr.plot.antialias}}{ +#' Which kind of antialiasing to use for for lines and text? +#' 'gray', 'subpixel' or 'none'? +#' (default: \code{'gray'}) +#' } +#' \item{\code{repr.plot.res}}{PPI for rasterization (default: \code{120})} +#' \item{\code{repr.plot.quality}}{Quality of JPEG format in \% (default: \code{90})} +#' \item{\code{repr.plot.family}}{Font family. 'sans', 'serif', 'mono' or a specific one (default: \code{'sans'})} +#' \item{\code{repr.plot.backends}}{ +#' The order in which backends are tried. +#' \describe{ +#' \item{\link[ragg:ragg]{ragg}}{Can emit only raster formats (png, jpeg), good quality} +#' \item{\link[Cairo:Cairo]{Cairo}}{Cannot handle per-element fonts, excellent quality} +#' \item{\link[grDevices:Devices]{grDevices}}{OK quality} +#' } +#' (default: \code{c('ragg', 'Cairo', 'grDevices')}) +#' } #' } #' } #' \item{\code{repr.vector.quote}}{ diff --git a/R/repr_recordedplot.r b/R/repr_recordedplot.r index 5b292d5..bc5b9f6 100644 --- a/R/repr_recordedplot.r +++ b/R/repr_recordedplot.r @@ -1,6 +1,22 @@ is_cairo_installed <- function() requireNamespace('Cairo', quietly = TRUE) is_ragg_installed <- function() requireNamespace('ragg', quietly = TRUE) +get_device <- function(ragg, Cairo, grDevices) { + backends <- getOption('repr.plot.backends') + for (o in backends) switch( + o, + ragg = if (is_ragg_installed()) return(ragg), + Cairo = if (is_cairo_installed()) return(Cairo), + grDevices = return(grDevices), + stop("Unknown entry in getOption('repr.plot.backends'): ", o) + ) + stop( + "No plotting devide found in getOption('repr.plot.backends'): ", + toString(backends), + "\nDid you forget to add 'grDevices' to the vector?" + ) +} + # checking capability of X11 is slow, the short circult logic avoids # this if any other devices are found. check_capability <- function(dev) { @@ -88,15 +104,11 @@ repr_png.recordedplot <- function(obj, res = getOption('repr.plot.res'), ...) { if (!is_cairo_installed() && !check_capability('png')) return(NULL) - - dev.cb <- function(tf) - if (is_ragg_installed()) - ragg::agg_png(tf, width, height, 'in', pointsize, bg, res) # scaling, bitsize - else if (is_cairo_installed()) - Cairo::Cairo(width, height, tf, 'png', pointsize, bg, 'transparent', 'in', res) - else - png(tf, width, height, 'in', pointsize, bg, res, antialias = antialias) - + dev.cb <- function(tf) get_device( + ragg = ragg::agg_png(tf, width, height, 'in', pointsize, bg, res), # scaling, bitsize + Cairo = Cairo::Cairo(width, height, tf, 'png', pointsize, bg, 'transparent', 'in', res), + grDevices = png(tf, width, height, 'in', pointsize, bg, res, antialias = antialias) + ) repr_recordedplot_generic(obj, '.png', TRUE, dev.cb) } @@ -114,15 +126,11 @@ repr_jpg.recordedplot <- function(obj, quality = getOption('repr.plot.quality'), ...) { if (!is_cairo_installed() && !check_capability('jpeg')) return(NULL) - - dev.cb <- function(tf) - if (is_ragg_installed()) - ragg::agg_jpeg(tf, width, height, 'in', pointsize, bg, res, quality = quality) - else if (is_cairo_installed()) - Cairo::Cairo(width, height, tf, 'jpeg', pointsize, bg, 'transparent', 'in', res, quality = quality) - else - jpeg(tf, width, height, 'in', pointsize, quality, bg, res, antialias = antialias) - + dev.cb <- function(tf) get_device( + ragg = ragg::agg_jpeg(tf, width, height, 'in', pointsize, bg, res, quality = quality), + Cairo = Cairo::Cairo(width, height, tf, 'jpeg', pointsize, bg, 'transparent', 'in', res, quality = quality), + grDevices = jpeg(tf, width, height, 'in', pointsize, quality, bg, res, antialias = antialias) + ) repr_recordedplot_generic(obj, '.jpg', TRUE, dev.cb) } @@ -143,13 +151,10 @@ repr_svg.recordedplot <- function(obj, family = getOption('repr.plot.family'), ...) { if (!is_cairo_installed() && !capabilities('cairo')) return(NULL) #only cairo can do SVG - - dev.cb <- function(tf) - if (is_cairo_installed()) - Cairo::Cairo(width, height, tf, 'svg', pointsize, bg, 'transparent', 'in') - else - svg(tf, width, height, pointsize, FALSE, family, bg, antialias) - + dev.cb <- get_device( + Cairo = Cairo::Cairo(width, height, tf, 'svg', pointsize, bg, 'transparent', 'in'), + grDevices = svg(tf, width, height, pointsize, FALSE, family, bg, antialias) + ) repr_recordedplot_generic(obj, '.svg', FALSE, dev.cb) } diff --git a/man/repr-options.Rd b/man/repr-options.Rd index 37cfaa2..28fceeb 100644 --- a/man/repr-options.Rd +++ b/man/repr-options.Rd @@ -27,14 +27,27 @@ Setting all options set to \code{NULL} are reset to defaults when reloading the \item{\code{repr.plot.*}}{ Those are for representations of \code{recordedplot} instances: \describe{ - \item{\code{repr.plot.width}}{Plotting area width in inches (default: 7)} - \item{\code{repr.plot.height}}{Plotting area height in inches (default: 7)} - \item{\code{repr.plot.pointsize}}{Text height in pt (default: 12)} - \item{\code{repr.plot.bg}}{Background color (default: white)} - \item{\code{repr.plot.antialias}}{Which kind of antialiasing to use for for lines and text? 'gray', 'subpixel' or 'none'? (default: gray)} - \item{\code{repr.plot.res}}{PPI for rasterization (default: 120)} - \item{\code{repr.plot.quality}}{Quality of JPEG format in \% (default: 90)} - \item{\code{repr.plot.family}}{Vector font family. 'sans', 'serif', 'mono' or a specific one (default: sans)} + \item{\code{repr.plot.width}}{Plotting area width in inches (default: \code{7})} + \item{\code{repr.plot.height}}{Plotting area height in inches (default: \code{7})} + \item{\code{repr.plot.pointsize}}{Text height in pt (default: \code{12})} + \item{\code{repr.plot.bg}}{Background color (default: \code{'white'})} + \item{\code{repr.plot.antialias}}{ + Which kind of antialiasing to use for for lines and text? + 'gray', 'subpixel' or 'none'? + (default: \code{'gray'}) + } + \item{\code{repr.plot.res}}{PPI for rasterization (default: \code{120})} + \item{\code{repr.plot.quality}}{Quality of JPEG format in \% (default: \code{90})} + \item{\code{repr.plot.family}}{Font family. 'sans', 'serif', 'mono' or a specific one (default: \code{'sans'})} + \item{\code{repr.plot.backends}}{ + The order in which backends are tried. + \describe{ + \item{\link[ragg:ragg]{ragg}}{Can emit only raster formats (png, jpeg), good quality} + \item{\link[Cairo:Cairo]{Cairo}}{Cannot handle per-element fonts, excellent quality} + \item{\link[grDevices:Devices]{grDevices}}{OK quality} + } + (default: \code{c('ragg', 'Cairo', 'grDevices')}) + } } } \item{\code{repr.vector.quote}}{