R/standalone-guess_has_R4.1_features.R

Defines functions deny_feature deny_via_dev_capabilities confirm_feature confirm_via_dev_capabilities guess_has_R4.1_features

Documented in guess_has_R4.1_features

# ---
# repo: trevorld/gridpattern
# file: standalone-guess_has_R4.1_features.R
# last-updated: 2023-08-02
# license: https://spdx.org/licenses/MIT-0.html
# imports: [grDevices, utils]
# ---
#
# nocov start
#
# You may copy this source into your own R package
# by either using `usethis::use_standalone("trevorld/gridpattern", "standalone-guess_has_R4.1_features.R")`
# or simply copying this file into your `R` directory and adding `grDevices` and `utils` to the `Imports` of
# your `DESCRIPTION` file.

#' Guess whether "active" graphics device supports
#' the grid graphics features introduced in R v4.1.
#'
#' `guess_has_R4.1_features()` guesses whether "active" graphics device supports
#' the grid graphics features introduced in R v4.1.  If it guesses it does
#' it returns `TRUE` else `FALSE`.
#'
#' @param features Character vector of features to guess support for.
#'                 Will return `TRUE` only if guesses support for all requested features.\describe{
#'                 \item{"clippingPaths"}{Supports clipping path feature}
#'                 \item{"gradients"}{Supports (both linear and radial) gradient feature}
#'                 \item{"masks"}{Supports (alpha) mask feature}
#'                 \item{"patterns"}{Supports (tiling) pattern feature}
#'                 }
#' @seealso \url{https://www.stat.auckland.ac.nz/~paul/Reports/GraphicsEngine/definitions/definitions.html}
#'   for more info about the new grid graphics features introduced in R v4.1.
#' @return `TRUE` if we guess all `features` are supported else `FALSE`
#' @examples
#'   # If R version (weakly) greater than 4.1 should be TRUE
#'   pdf(tempfile(fileext = ".pdf"))
#'   print(guess_has_R4.1_features())
#'   invisible(dev.off())
#'
#'   # Should be FALSE
#'   postscript(tempfile(fileext = ".ps"))
#'   print(guess_has_R4.1_features())
#'   invisible(dev.off())
#'
#' @keywords internal
#' @noRd
guess_has_R4.1_features <- function(features = c("clippingPaths", "gradients", "masks", "patterns")) {
    if (getRversion() < "4.1.0")
        return(FALSE)

    # In R 4.2 `dev.capabilities()` can confirm/deny R 4.1 graphic feature support
    # if active graphics device has implemented this feature
    if (getRversion() >= "4.2.0") {
        dev_capabilities <- grDevices::dev.capabilities()
        if (confirm_via_dev_capabilities(features, dev_capabilities))
            return(TRUE)
        if (deny_via_dev_capabilities(features, dev_capabilities))
            return(FALSE)
    }

    device <- names(grDevices::dev.cur())
    if (device %in% c("cairo_pdf", "cairo_ps", "pdf", "svg", "X11cairo")) {
        TRUE
    } else if (device %in% c("bmp", "jpeg", "png", "tiff")) {
        # on unix non-"cairo" type have different device names from "cairo" type
        # but on Windows can't distinguish between `type = "windows"` or `type = "cairo"`
        .Platform$OS.type == "unix"
    } else if (device %in% c("agg_jpeg", "agg_ppm", "agg_png", "agg_tiff")) {
        utils::packageVersion("ragg") >= "1.2.0"
    } else if (device == "devSVG") {
        # `vdiffr:::svglite()` has name "devSVG_vdiffr" since v1.0.6
        utils::packageVersion("svglite") >= "2.1.0"
    } else {
        FALSE
    }
}

# Will always return FALSE if called within R 4.1
# or if graphics device hasn't been updated to provide this information
# even if the device had been updated to provide R 4.1 graphic feature support
confirm_via_dev_capabilities <- function(features = c("clippingPaths", "gradients", "masks", "patterns"),
                                         dev_capabilities = grDevices::dev.capabilities()) {
    for (feature in features) {
        if (!confirm_feature(feature, dev_capabilities))
            return(FALSE)
    }
    TRUE
}

confirm_feature <- function(feature, dev_capabilities) {
    switch(feature,
           clippingPaths = isTRUE(dev_capabilities$clippingPaths),
           gradients = all(c("LinearGradient", "RadialGradient") %in% dev_capabilities$patterns),
           masks = "alpha" %in% dev_capabilities$masks,
           patterns = "TilingPattern" %in% dev_capabilities$patterns
           )
}

# Will return `TRUE` if `dev.capabilities()` explicitly indicates
# the given features are not supported (versus merely missing a positive indication)
deny_via_dev_capabilities <- function(features = c("clippingPaths", "gradients", "masks", "patterns"),
                                      dev_capabilities = grDevices::dev.capabilities()) {
    for (feature in features) {
        if (deny_feature(feature, dev_capabilities))
            return(TRUE)
    }
    FALSE
}

deny_feature <- function(feature, dev_capabilities) {
    switch(feature,
           clippingPaths = isFALSE(dev_capabilities$clippingPaths),
           gradients = !is.na(dev_capabilities$patterns) &&
               !all(c("LinearGradient", "RadialGradient") %in% dev_capabilities$patterns),
           masks = !is.na(dev_capabilities$masks) && !("alpha" %in% dev_capabilities$masks),
           patterns = !is.na(dev_capabilities$patterns) && !("TilingPattern" %in% dev_capabilities$patterns)
           )
}

# nocov end

Try the gridpattern package in your browser

Any scripts or data that you put into this service are public.

gridpattern documentation built on Oct. 26, 2023, 1:07 a.m.